| 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 | |
| 17 | struct disk_node { |
| 18 | struct block_device *disk; |
| 19 | struct disk_node *next; |
| 20 | }; |
| 21 | |
| 22 | static struct disk_node *disk_list = NULL; |
| 23 | static uint64_t disk_count = 0; |
| 24 | |
| 25 | void 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 | |
| 36 | void 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 | |
| 51 | struct 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 | |
| 59 | struct 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 | |
| 66 | uint64_t registry_get_disk_cnt(void) { |
| 67 | return disk_count; |
| 68 | } |
| 69 | |
| 70 | static 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 | |
| 81 | static 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 | |
| 91 | void registry_mkname(struct block_device *disk, const char *prefix, |
| 92 | uint64_t counter) { |
| 93 | device_mkname(disk, prefix, counter); |
| 94 | } |
| 95 | |
| 96 | LOG_HANDLE_EXTERN(pci); |
| 97 | LOG_HANDLE_EXTERN(vfs); |
| 98 | void 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 | |