From 0bed26ff26bda3df79ffc6da5ba54429fa68e887 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Mon, 15 May 2023 18:13:58 +0200 Subject: [PATCH] feature (drive manager): implemented a manager for drives/storage media --- inc/drivers/ahci.h | 10 ++- inc/drivers/drive_manager.h | 71 ++++++++++++++++++ src/boot/kmain.c | 3 + src/drivers/ahci.c | 12 ++- src/drivers/drive_manager.c | 144 ++++++++++++++++++++++++++++++++++++ 5 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 inc/drivers/drive_manager.h create mode 100644 src/drivers/drive_manager.c diff --git a/inc/drivers/ahci.h b/inc/drivers/ahci.h index 5e5baa1..965963c 100644 --- a/inc/drivers/ahci.h +++ b/inc/drivers/ahci.h @@ -5,6 +5,7 @@ #include "utils/stdtypes.h" #include "drivers/pci.h" +#include "drivers/drive_manager.h" #define SATA_SIG_ATA 0x00000101 #define SATA_SIG_ATAPI 0xEB140101 @@ -209,23 +210,26 @@ typedef struct{ } ahci_hba_command_table_T; +typedef struct ahci_controller_T ahci_controller_T; + typedef struct { ahci_hba_port_T* hba_port; ahci_device_type_E type; - uint8_t* buffer; + ahci_controller_T* controller; uint8_t id; + drive_T* drive; void* cmd_list_base; void* fis_base; void* command_tables [32]; } ahci_port_T; -typedef struct { +struct ahci_controller_T { ahci_port_T ports [32]; int num_ports; pci_device_T* pci_device; ahci_hba_memory_T* abar; -} ahci_controller_T; +}; ahci_controller_T* ahci_controller_alloc (pci_device_T* pci_device); void ahci_controller_destruct (ahci_controller_T* controller); diff --git a/inc/drivers/drive_manager.h b/inc/drivers/drive_manager.h new file mode 100644 index 0000000..c3a9f65 --- /dev/null +++ b/inc/drivers/drive_manager.h @@ -0,0 +1,71 @@ +// This file is part of noxos and licensed under the MIT open source license + +#ifndef NOXOS_DRIVE_MANAGER_H +#define NOXOS_DRIVE_MANAGER_H + +#include "drivers/fs/vfs.h" +#include "utils/stdtypes.h" +#include "utils/bitmap.h" + +#define DRIVE_CHUNK_SIZE 16 +#define DRIVE_PARTITION_CHUNK_SIZE 16 + +typedef enum { + DRIVE_CONTROLLER_AHCI +} drive_controller_types_E; + +typedef struct drive_chunk_T drive_chunk_T; +typedef struct drive_partition_chunk_T drive_partition_chunk_T; +typedef struct drive_partition_T drive_partition_T; +typedef struct drive_T drive_T; + +struct drive_partition_T{ + drive_partition_chunk_T* chunk; + uint32_t id_in_chunk; + uint32_t id; + drive_T* drive; + fs_T filesystem; + uint32_t start_sector; + uint32_t end_sector; +}; + +struct drive_T { + drive_chunk_T* chunk; + uint32_t id_in_chunk; + uint32_t id; + drive_partition_chunk_T* partitions_chunks; + drive_controller_types_E controller_type; + void* controller; +}; + +struct drive_chunk_T { + drive_T drives [DRIVE_CHUNK_SIZE]; + bitmap_T drives_bitmap; + uint32_t num_drives; + drive_chunk_T* prev; + drive_chunk_T* next; +}; + +struct drive_partition_chunk_T { + drive_partition_T partitions [DRIVE_PARTITION_CHUNK_SIZE]; + bitmap_T partitions_bitmap; + uint32_t num_partitions; + drive_partition_chunk_T* prev; + drive_partition_chunk_T* next; +}; + +typedef struct { + drive_chunk_T* chunks; +} drive_manager_T; + +drive_chunk_T* drive_chunk_alloc (drive_chunk_T* prev); +drive_partition_chunk_T* drive_partition_chunk_alloc (drive_partition_chunk_T* prev); +void drive_partition_chunk_destruct (drive_partition_chunk_T* chunk); + +void drive_manager_init (); +drive_T* drive_manager_add_drive (drive_controller_types_E controller_type, void* controller, void* device); +void drive_manager_remove_drive (drive_T* drive); +drive_partition_T* drive_manager_add_partition (drive_T* drive, uint32_t start_sector, uint32_t end_sector); +void drive_manager_remove_partition (drive_partition_T* partition); + +#endif //NOXOS_DRIVE_MANAGER_H diff --git a/src/boot/kmain.c b/src/boot/kmain.c index 1ed065e..15866c2 100644 --- a/src/boot/kmain.c +++ b/src/boot/kmain.c @@ -15,6 +15,7 @@ #include "drivers/graphics/renderer.h" #include "drivers/fs/vfs.h" #include "drivers/acpi/acpi.h" +#include "drivers/drive_manager.h" #include "drivers/pci.h" #include "drivers/ps2/controller.h" #include "drivers/tty.h" @@ -49,6 +50,8 @@ void kernel_init(boot_info_T* boot_info) { acpi_init(boot_info); + drive_manager_init(); + pci_init(); tty_init(); diff --git a/src/drivers/ahci.c b/src/drivers/ahci.c index 1cd2695..a35fb45 100644 --- a/src/drivers/ahci.c +++ b/src/drivers/ahci.c @@ -40,6 +40,7 @@ ahci_controller_T* ahci_controller_alloc(pci_device_T* pci_device) { port->type = type; port->hba_port = &controller->abar->ports[i]; port->id = controller->num_ports; + port->controller = controller; controller->num_ports += 1; break; @@ -94,6 +95,8 @@ void ahci_port_init(ahci_port_T* port) { ahci_port_command_start(port); + port->drive = drive_manager_add_drive(DRIVE_CONTROLLER_AHCI, port->controller, port); + ahci_port_init_partitions_mbr(port); } @@ -109,12 +112,15 @@ void ahci_port_init_partitions_mbr(ahci_port_T* port) { mbr_partition_types_E type = mbr->partitions[i].partition_type; if (type == MBR_PARTITION_TYPE_UNUSED) continue; - log(LOG_INFO, " p%d: 0x%xb - %d - %s", i, type, mbr->partitions[i].start_lba, mbr_partition_type_to_string(type)); + mbr_partition_header_T* partition = &mbr->partitions[i]; + log(LOG_INFO, " p%d: 0x%xb - (LBA: %d) - %s", i, type, partition->start_lba, mbr_partition_type_to_string(type)); if (type == MBR_PARTITION_TYPE_GPT) { ahci_port_init_partitions_gpt(port); break; } + + drive_manager_add_partition(port->drive, partition->start_lba, partition->start_lba + partition->num_sectors); } } @@ -156,6 +162,8 @@ void ahci_port_init_partitions_gpt(ahci_port_T* port) { } else { log(LOG_INFO, " p%d: (%d)<--LBA-->(%d) %s", i, entry->starting_lba, entry->ending_lba, gpt_partition_type_to_string(type)); } + + drive_manager_add_partition(port->drive, entry->starting_lba, entry->ending_lba); } } @@ -167,6 +175,8 @@ void ahci_port_init_partitions_gpt(ahci_port_T* port) { void ahci_port_destruct(ahci_port_T* port) { + drive_manager_remove_drive(port->drive); + for (uint32_t i = 0; i < 32; i++) { pframe_free(port->command_tables[i]); } diff --git a/src/drivers/drive_manager.c b/src/drivers/drive_manager.c new file mode 100644 index 0000000..37a4193 --- /dev/null +++ b/src/drivers/drive_manager.c @@ -0,0 +1,144 @@ +// This file is part of noxos and licensed under the MIT open source license + +#include "drivers/drive_manager.h" +#include "utils/memory.h" +#include "utils/logger.h" + +drive_manager_T g_drive_manager; + +drive_chunk_T* drive_chunk_alloc(drive_chunk_T* prev) { + drive_chunk_T* chunk = memory_allocate(sizeof(drive_chunk_T)); + + chunk->drives_bitmap = bitmap_init(DRIVE_CHUNK_SIZE); + chunk->num_drives = 0; + chunk->next = NULL; + chunk->prev = prev; + if (prev != NULL) { + prev->next = chunk; + } + + return chunk; +} + + +drive_partition_chunk_T* drive_partition_chunk_alloc(drive_partition_chunk_T* prev) { + drive_partition_chunk_T* chunk = memory_allocate(sizeof(drive_partition_chunk_T)); + + chunk->partitions_bitmap = bitmap_init(DRIVE_PARTITION_CHUNK_SIZE); + chunk->num_partitions = 0; + chunk->next = NULL; + chunk->prev = prev; + if (prev != NULL) { + prev->next = chunk; + } + + return chunk; +} + +void drive_partition_chunk_destruct(drive_partition_chunk_T* chunk) { + bitmap_destruct(&chunk->partitions_bitmap); + memory_free(chunk); +} + +void drive_manager_init(void) { + g_drive_manager.chunks = drive_chunk_alloc(NULL); +} + +drive_T* drive_manager_add_drive(drive_controller_types_E controller_type, void* controller, void* device) { + uint32_t num_chunks = 0; + + drive_chunk_T* chunk = g_drive_manager.chunks; + while (chunk->num_drives == DRIVE_CHUNK_SIZE) { + if (chunk->next == NULL) { + drive_chunk_alloc(chunk); + } + chunk = chunk->next; + num_chunks++; + } + + for (int i = 0; i < DRIVE_CHUNK_SIZE; i++) { + if (bitmap_get(&chunk->drives_bitmap, i)) continue; + bitmap_set(&chunk->drives_bitmap, i, true); + + drive_T* drive = &chunk->drives[i]; + + drive->id_in_chunk = i; + drive->id = (num_chunks * DRIVE_CHUNK_SIZE) + i; + drive->partitions_chunks = drive_partition_chunk_alloc(NULL); + drive->controller_type = controller_type; + drive->controller = controller; + drive->chunk = chunk; + + chunk->num_drives += 1; + + log(LOG_INFO, "Registered drive %d", drive->id); + + return drive; + } + + // this should never happen + return NULL; +} + +void drive_manager_remove_drive(drive_T* drive) { + if (drive == NULL) return; + drive_chunk_T* chunk = drive->chunk; + if (!bitmap_get(&chunk->drives_bitmap, drive->id_in_chunk)) return; + + drive_partition_chunk_T* partition_chunk = drive->partitions_chunks; + while (partition_chunk != NULL) { + drive_partition_chunk_T* next = partition_chunk->next; + drive_partition_chunk_destruct(partition_chunk); + partition_chunk = next; + } + + chunk->num_drives -= 1; + bitmap_set(&chunk->drives_bitmap, drive->id_in_chunk, false); +} + +drive_partition_T* drive_manager_add_partition(drive_T* drive, uint32_t start_sector, uint32_t end_sector) { + uint32_t num_chunks = 0; + + drive_partition_chunk_T* chunk = drive->partitions_chunks; + while (chunk->num_partitions == DRIVE_PARTITION_CHUNK_SIZE) { + if (chunk->next == NULL) { + drive_partition_chunk_alloc(chunk); + } + chunk = chunk->next; + num_chunks++; + } + + for (int i = 0; i < DRIVE_PARTITION_CHUNK_SIZE; i++) { + if (bitmap_get(&chunk->partitions_bitmap, i)) continue; + bitmap_set(&chunk->partitions_bitmap, i, true); + + drive_partition_T* partition = &chunk->partitions[i]; + + partition->id_in_chunk = i; + partition->id = (num_chunks * DRIVE_CHUNK_SIZE) + i; + partition->drive = drive; + partition->chunk = chunk; + partition->start_sector = start_sector; + partition->end_sector = end_sector; + + // TODO: set partition filesystem + + chunk->num_partitions += 1; + + log(LOG_INFO, "Registered partition %d in drive %d", partition->id, drive->id); + + return partition; + } + + // this should never happen + return NULL; +} + +void drive_manager_remove_partition(drive_partition_T* partition) { + if (partition == NULL) return; + drive_partition_chunk_T* chunk = partition->chunk; + if (!bitmap_get(&chunk->partitions_bitmap, partition->id_in_chunk)) return; + + chunk->num_partitions -= 1; + bitmap_set(&chunk->partitions_bitmap, partition->id_in_chunk, false); +}