1#include <block/block.h>
2#include <console/printf.h>
3#include <drivers/ahci.h>
4#include <drivers/ata.h>
5#include <drivers/e1000.h>
6#include <drivers/nvme.h>
7#include <drivers/pci.h>
8#include <fs/detect.h>
9#include <fs/vfs.h>
10#include <global.h>
11#include <mem/alloc.h>
12#include <registry.h>
13#include <stdbool.h>
14#include <stdint.h>
15#include <string.h>
16
17struct disk_node {
18 struct block_device *disk;
19 struct disk_node *next;
20};
21
22static struct disk_node *disk_list = NULL;
23static uint64_t disk_count = 0;
24
25void registry_register(struct block_device *disk) {
26 struct disk_node *node = kmalloc(sizeof(struct disk_node));
27 if (!node)
28 return;
29
30 node->disk = disk;
31 node->next = disk_list;
32 disk_list = node;
33 disk_count++;
34}
35
36void registry_unregister(struct block_device *disk) {
37 struct disk_node **indirect = &disk_list;
38 while (*indirect) {
39 if ((*indirect)->disk == disk) {
40 struct disk_node *old = *indirect;
41 *indirect = old->next;
42 kfree(old->disk);
43 kfree(old);
44 disk_count--;
45 return;
46 }
47 indirect = &(*indirect)->next;
48 }
49}
50
51struct block_device *registry_get_by_name(const char *name) {
52 for (struct disk_node *node = disk_list; node; node = node->next) {
53 if (strcmp(str1: node->disk->name, str2: name) == 0)
54 return node->disk;
55 }
56 return NULL;
57}
58
59struct block_device *registry_get_by_index(uint64_t index) {
60 struct disk_node *node = disk_list;
61 for (uint64_t i = 0; node && i < index; i++)
62 node = node->next;
63 return node ? node->disk : NULL;
64}
65
66uint64_t registry_get_disk_cnt(void) {
67 return disk_count;
68}
69
70static char *mkname(char *prefix, uint64_t counter) {
71 uint32_t n = 0;
72 char counter_str[25] = {0};
73 do {
74 counter_str[n++] = '0' + (counter % 10);
75 counter /= 10;
76 } while (counter > 0);
77 char *cat = strcat(dest: prefix, src: counter_str);
78 return cat;
79}
80
81static void device_mkname(struct block_device *disk, const char *prefix,
82 uint64_t counter) {
83 char diff_prefix[16] = {0};
84 memcpy(diff_prefix, prefix, strlen(prefix));
85 char *name = mkname(prefix: diff_prefix, counter);
86 char fmtname[16] = {0};
87 memcpy(fmtname, name, 16);
88 memcpy(disk->name, fmtname, 16);
89}
90
91void registry_mkname(struct block_device *disk, const char *prefix,
92 uint64_t counter) {
93 device_mkname(disk, prefix, counter);
94}
95
96LOG_HANDLE_EXTERN(pci);
97LOG_HANDLE_EXTERN(vfs);
98void registry_setup() {
99 struct pci_device *devices;
100 uint64_t count;
101
102 pci_scan_devices(devices_out: &devices, count_out: &count);
103 log_info_global(LOG_HANDLE(pci), "Found %u devices", count);
104
105 pci_init_devices(devices, count);
106 ata_init(devices, count);
107
108 log_info_global(LOG_HANDLE(vfs), "Attempting to find and mount root '%s'",
109 global.root_partition);
110
111 bool found_root = false;
112 for (uint64_t i = 0; i < disk_count; i++) {
113 struct block_device *disk = registry_get_by_index(index: i);
114 detect_fs(drive: disk);
115 for (uint32_t j = 0; j < disk->partition_count; j++) {
116 struct partition *p = &disk->partitions[j];
117
118 if (strcmp(str1: p->name, str2: global.root_partition) == 0) {
119 struct vfs_node *root = p->mount(p);
120 if (!root)
121 panic("VFS failed to mount root '%s' - mount failure",
122 global.root_partition);
123 global.root_node = root;
124 global.root_node_disk = disk;
125 found_root = true;
126 }
127 }
128 }
129
130 if (!found_root)
131 panic("VFS failed to mount root '%s' - could not find root",
132 global.root_partition);
133
134 log_info_global(
135 LOG_HANDLE(vfs), "Root '%s' mounted - is a(n) %s filesystem",
136 global.root_partition, detect_fstr(global.root_node->fs_type));
137}
138