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 for (uint32_t i = 0; i < n / 2; i++) {
78 char tmp = counter_str[i];
79 counter_str[i] = counter_str[n - 1 - i];
80 counter_str[n - 1 - i] = tmp;
81 }
82 char *cat = strcat(dest: prefix, src: counter_str);
83 return cat;
84}
85
86static void device_mkname(struct block_device *disk, const char *prefix,
87 uint64_t counter) {
88 char diff_prefix[16] = {0};
89 memcpy(diff_prefix, prefix, strlen(prefix));
90 char *name = mkname(prefix: diff_prefix, counter);
91 char fmtname[16] = {0};
92 memcpy(fmtname, name, 16);
93 memcpy(disk->name, fmtname, 16);
94}
95
96void registry_mkname(struct block_device *disk, const char *prefix,
97 uint64_t counter) {
98 device_mkname(disk, prefix, counter);
99}
100
101LOG_HANDLE_EXTERN(pci);
102LOG_HANDLE_EXTERN(vfs);
103void registry_setup() {
104 struct pci_device *devices;
105 uint64_t count;
106
107 pci_scan_devices(devices_out: &devices, count_out: &count);
108 log_info_global(LOG_HANDLE(pci), "Found %u devices", count);
109
110 pci_init_devices(devices, count);
111 ata_init(devices, count);
112
113 log_info_global(LOG_HANDLE(vfs), "Attempting to find and mount root '%s'",
114 global.root_partition);
115
116 bool found_root = false;
117 for (uint64_t i = 0; i < disk_count; i++) {
118 struct block_device *disk = registry_get_by_index(index: i);
119 detect_fs(drive: disk);
120 for (uint32_t j = 0; j < disk->partition_count; j++) {
121 struct partition *p = &disk->partitions[j];
122
123 if (strcmp(str1: p->name, str2: global.root_partition) == 0) {
124 struct vfs_node *root = p->mount(p);
125 if (!root)
126 panic("VFS failed to mount root '%s' - mount failure",
127 global.root_partition);
128 global.root_node = root;
129 global.root_node_disk = disk;
130 found_root = true;
131 }
132 }
133 }
134
135 if (!found_root)
136 panic("VFS failed to mount root '%s' - could not find root",
137 global.root_partition);
138
139 log_info_global(
140 LOG_HANDLE(vfs), "Root '%s' mounted - is a(n) %s filesystem",
141 global.root_partition, detect_fstr(global.root_node->fs_type));
142}
143