From c880843b6c6fb20560b07ca6fce0d91a642470a7 Mon Sep 17 00:00:00 2001 From: notsomeidiot123 Date: Wed, 17 Sep 2025 12:24:30 -0400 Subject: [PATCH] Detecting IDE drives, allocating memory for PRDT --- makefile | 2 +- src/kernel/arch_i386/memory.c | 56 ++++++++++++ src/kernel/drivers/pci.c | 14 ++- src/kernel/kmain.c | 5 +- src/kernel/shared/memory.h | 2 + src/kernel/system/modules.c | 17 +++- src/kernel/system/modules.h | 2 + src/kernel/system/vfs.c | 27 ++++-- src/kernel/system/vfs.h | 4 +- src/kmodules/disk_driver.c | 162 ++++++++++++++++++++++++---------- src/kmodules/modlib.h | 39 ++++++-- 11 files changed, 260 insertions(+), 70 deletions(-) diff --git a/makefile b/makefile index e3c2da3..a4f076f 100644 --- a/makefile +++ b/makefile @@ -47,7 +47,7 @@ kernel: nasm src/kernel/arch_i386/idt.s -o bin/kernel/idt.o -felf32 # ld -T linker.ld bin/kernel/entry.o bin/kernel/*.o -melf_i386 ld -T linker.ld bin/kernel/*.o -melf_i386 -o kernel.elf -static -# ld -T linker.ld -o kernel_interface.elf -r -R kernel.elf -melf_i386 + ld -T linker.ld -o kernel_interface.elf -r -R kernel.elf -melf_i386 ld -pie bin/modules/disk_driver.o -o idm.elf -melf_i386 -e init --no-dynamic-linker -static -nostdlib # ld bin/modules/fs_driver.o -o ifsm.elf -melf_i386 ld -pie bin/modules/fs_driver.o -o ifsm.elf -melf_i386 -e init --no-dynamic-linker -static -nostdlib diff --git a/src/kernel/arch_i386/memory.c b/src/kernel/arch_i386/memory.c index 1dd3294..6b56857 100644 --- a/src/kernel/arch_i386/memory.c +++ b/src/kernel/arch_i386/memory.c @@ -24,6 +24,34 @@ uint32_t pm_alloc(){ } } } +uint32_t pm_alloc_index(uint32_t index){ + for(uint32_t i = index; i < 2; i++){ + for(int j = 0; j < 8; j++){ + // if(!(pm_map[i] & (1 << j))){ + pm_map[i] |= (1 << j); + // } + } + } + return (index << 3) << 12; +} +uint32_t pm_alloc_64kaligned(){ + uint32_t cont = 0; + for(uint32_t i = 0; i < mmap_count; i++){ + for(int j = 0; j < 8; j++){ + if(!(pm_map[i] & (1 << j))){ + continue; + }else{ + j++; + cont = -1; + break; + } + } + if(cont == 1){ + return pm_alloc_index(i); + } + cont++; + } +} void pm_free(uint32_t address){ pm_map[address >> 15] &= ~(1 << ((address>>12) & 7)); } @@ -169,6 +197,34 @@ void *kmalloc(uint32_t size_pgs){ return (void*)(i << 12); } } +void *kmalloc_page_paddr(uint32_t paddr, uint32_t size_pgs){ + uint32_t i = 0xc0000000 >> 12; //4mb/4096 (start search at 1mb line) + while(i < (1 << 22)){ + uint8_t found = 1; + for(uint32_t j = 0; j < size_pgs; j++){ + // printf("found at %x, %x\n", (i + j) << 12, get_paddr((void*)((i + j) << 12))); + if(get_pflags((void *)((i + j) << 12))){ + found = 0; + break; + } + } + if(!found){ + i++; + continue; + } + for(uint32_t j = 0; j < size_pgs; j++){ + uint32_t flags = PT_PRESENT | PT_SYS | (PT_LINK_L * (j != 0)) | (PT_LINK_N * (j < (size_pgs - 1))); + uint32_t physaddr = paddr + j * 4096; + // if(j == 0) printf("%x", physaddr); + // printf("Mapping %x to %x\n", (i + j) << 12, physaddr); + // if(fake) return 0; + map((void *)((i + j) << 12), (void*)physaddr, flags); + } + // fake = !fake; + // for(;;); + return (void*)(i << 12); + } +} void *kfree(void *vaddr){ uint32_t addr = (uint32_t)vaddr; addr &= ~0xfff; diff --git a/src/kernel/drivers/pci.c b/src/kernel/drivers/pci.c index a4234d6..e5d0f58 100644 --- a/src/kernel/drivers/pci.c +++ b/src/kernel/drivers/pci.c @@ -25,13 +25,20 @@ uint16_t pci_read_config(uint32_t bus, uint32_t slot, uint32_t func, uint8_t off uint16_t tmp = (uint16_t)((inl(0xcfc) >> ((offset & 2) * 8)) & 0xffff); return tmp; } +uint16_t pci_write_config(uint32_t bus, uint32_t slot, uint32_t func, uint8_t offset, uint16_t word){ + uint32_t address = (uint32_t)((bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); + outl(0xcf8, address); + outl(0xcfc, word); + return 0; +} + void pci_read_file(vfile_t *file, uint32_t *buffer, uint32_t offset, uint32_t count){ uint8_t bus = file->id >> 16; uint8_t func = file->id>> 8 & 0xff; uint8_t slot = file->id & 0xff; - for(uint32_t i = 0; i < count/2; i++){ - buffer[i] = pci_read_config(bus, slot, func, offset + i*2) | (pci_read_config(bus, slot, func, offset + i * 2 + 2) << 16); + for(uint32_t i = 0; i < (count); i++){ + buffer[i] = pci_read_config(bus, slot, func, offset + i*4) | (pci_read_config(bus, slot, func, offset + i*4 + 2) << 16); } return; } @@ -45,6 +52,9 @@ void pci_make_file(uint32_t class, uint8_t bus, uint8_t slot, uint8_t func){ switch(class >> 8){ case 0x1://PCI class 0x1 is disks strcpy("disk/", str + strlen(str)); + uint32_t l = (uint32_t)pci_read_config(bus, slot, func, 0x4) | (uint32_t)pci_read_config(bus, slot, func, 0x6) << 16; + pci_write_config(bus, slot, func, 0x4, l | 2); + break; case 0x2://PCI class 0x2 is network controllers strcpy("net/", str + strlen(str)); diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 1e7b013..e651480 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -35,8 +35,9 @@ extern void kmain(kernel_info_t *kernel_info){ vfs_init(); fcreate("/dev", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1); - + fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1); + vfile_t *file = fopen("/dev"); + printf("%x", file); mlog("KERNEL", "Initializing Scheduler & starting PID 1\n", MLOG_PRINT); boot_info = kernel_info; scheduler_init(); diff --git a/src/kernel/shared/memory.h b/src/kernel/shared/memory.h index cd58c1d..c72653c 100644 --- a/src/kernel/shared/memory.h +++ b/src/kernel/shared/memory.h @@ -71,6 +71,8 @@ uint32_t get_paddr(void *addr); uint32_t pm_alloc(); void pm_reserve(uint32_t addr); void pm_free(uint32_t addr); +uint32_t pm_alloc_64kaligned(); +void *kmalloc_page_paddr(uint32_t paddr, uint32_t size); inline void set_cr3(void *cr3){ asm volatile("mov %0, %%eax; mov %%eax, %%cr3":: "r"(cr3)); diff --git a/src/kernel/system/modules.c b/src/kernel/system/modules.c index 979eeb6..7499240 100644 --- a/src/kernel/system/modules.c +++ b/src/kernel/system/modules.c @@ -71,11 +71,14 @@ uint32_t module_api(uint32_t func, ...){ break; case MODULE_API_OPEN: name = va_arg(vars, char *); - file = va_arg(vars, vfile_t *); - return_value = fopen(name, file); + return_value = (uint32_t)fopen(name); break; case MODULE_API_MAP: - return_value = -1; + return_value = 0; + void *vaddr = va_arg(vars, void *); + void *paddr = va_arg(vars, void *); + uint32_t flags = va_arg(vars, uint32_t); + map(vaddr, paddr, flags); break; case MODULE_API_UNMAP: return_value = -1; @@ -93,6 +96,14 @@ uint32_t module_api(uint32_t func, ...){ kfree(ptr); return_value = 0; break; + case MODULE_API_PMALLOC64K: + return_value = pm_alloc_64kaligned(); + break; + case MODULE_API_KMALLOC_PADDR: + paddr = va_arg(vars, uint32_t); + uint32_t size = va_arg(vars, uint32_t); + return_value = kmalloc_page_paddr((uint32_t)paddr, size); + break; } va_end(vars); diff --git a/src/kernel/system/modules.h b/src/kernel/system/modules.h index a4d8790..d26bbfa 100644 --- a/src/kernel/system/modules.h +++ b/src/kernel/system/modules.h @@ -25,6 +25,8 @@ #define MODULE_API_PADDR 13 //get physical address of memory #define MODULE_API_MALLOC 14 //allocate memory in 4kb blocks #define MODULE_API_FREE 15 //free memory allocated by malloc +#define MODULE_API_PMALLOC64K 16 +#define MODULE_API_KMALLOC_PADDR 17 typedef struct module{ void *init_entry; diff --git a/src/kernel/system/vfs.c b/src/kernel/system/vfs.c index 1ca95c2..992ca55 100644 --- a/src/kernel/system/vfs.c +++ b/src/kernel/system/vfs.c @@ -18,6 +18,7 @@ void add_file(vfile_t *vfile, vfile_t *current_dir){ i++; } dir_data[i] = vfile; + dir_data[i + 1] = 0; } /* Long comment cause this one's a complicated one. @@ -77,8 +78,8 @@ vfile_t *fcreate(char *name, VFILE_TYPE type, ...){ void *ptr = va_arg(args, void*); vfile->access.data.ptr = ptr; vfile->access.data.size_pgs = va_arg(args, uint32_t); + *(uint32_t *)ptr = 0; add_file(vfile, current_dir); - // printf("Created File: %s\n", vfile->name); break; case VFILE_FILE: case VFILE_DEVICE: @@ -166,8 +167,16 @@ vfile_t *search_dir(char *name, vfile_t dir){ return 0; } -int fopen(char *name, vfile_t **file){ +vfile_t *fopen(char *name){ + if(name[0] == '/'){ + name++; + } + if(name[strlen(name) - 1] == '/'){ + name[strlen(name) - 1] = 0; + } + printf("%s\n", name); char *dir = strtok(name, '/'); + printf("%s", name); char *tmp = dir; uint32_t filename_offset = 0; vfile_t *current_dir = &root_dir; @@ -176,21 +185,23 @@ int fopen(char *name, vfile_t **file){ dir = tmp; tmpfile = search_dir(tmp, *current_dir); if(!tmpfile){ - return -1; + printf("not found\n"); + return 0; } switch(tmpfile->type){ case VFILE_DIRECTORY: + printf("found directory in %s: %s\n", current_dir->name, tmpfile->name); current_dir = tmpfile; break; case VFILE_MOUNT: - return ((mount_t*)(tmpfile->access.data.ptr))->open(name + filename_offset, file); + vfile_t *file = kmalloc(1); + ((mount_t*)(tmpfile->access.data.ptr))->open(name + filename_offset, file); + return file; default: - *file = tmpfile; - return 0; + return tmpfile; } filename_offset += strlen(tmp) + 1; tmp = strtok(0, '/'); } - *file = tmpfile; - return 0; + return tmpfile; } \ No newline at end of file diff --git a/src/kernel/system/vfs.h b/src/kernel/system/vfs.h index 93595b4..c6ff644 100644 --- a/src/kernel/system/vfs.h +++ b/src/kernel/system/vfs.h @@ -43,7 +43,7 @@ typedef enum fs_flags{ typedef struct mount_funcs{ int (*write)(vfile_t *file, void *data, uint32_t offset, uint32_t count); int (*read)(vfile_t *file, void *data, uint32_t offset, uint32_t count); - int (*open)(char *filename, vfile_t **file); + int (*open)(char *filename, vfile_t *file); void (*delete)(vfile_t *file); void (*create)(char *filename, FS_FILE_FLAGS flags); }mount_t; @@ -54,4 +54,4 @@ void fdelete(); int fwrite(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count); int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count); vfile_t *search_dir(char *name, vfile_t dir); -int fopen(char *name, vfile_t **file); \ No newline at end of file +vfile_t *fopen(char *name); \ No newline at end of file diff --git a/src/kmodules/disk_driver.c b/src/kmodules/disk_driver.c index 9f07b1e..01defad 100644 --- a/src/kmodules/disk_driver.c +++ b/src/kmodules/disk_driver.c @@ -1,30 +1,12 @@ #include #include "modlib.h" #include "../kernel/drivers/cpuio.h" +#include "../kernel/shared/string.h" #define MODULE_NAME "KIDM" KOS_MAPI_FP api; -// inline void outb(uint16_t port, uint8_t data){ -// asm volatile ("outb %0, %1" :: "a"(data), "Nd"(port)); -// } - -// inline void outw(uint16_t port, uint16_t data){ -// asm volatile ("outw %0, %1" :: "a"(data), "Nd"(port)); -// } - -// inline uint8_t inb(uint16_t port){ -// uint8_t byte = 0; -// asm volatile ("inb %1, %0" : "=a"(byte) : "Nd"(port)); -// return byte; -// } - -// inline uint16_t inw(uint16_t port){ -// uint16_t word = 0; -// asm volatile ("inw %1, %0" : "=a"(word) : "Nd"(port)); -// return word; -// } /* TODO: Register module @@ -49,11 +31,9 @@ make fini function to destroy global object, and free any remaining resources. #define ATA_LBA_MID ATA_CYLINDER_LOW #define ATA_LBA_HIH ATA_CYLINDER_HIGH -#define ATA_ALT_STATUS + 0x206 -#define ATA_DEVICE_CONTROL + 0x206 -#define ATA_DRIVE_ADDRESS + 0x207 - -#define ATA_IDENTIFY 0xEC +#define ATA_ALT_STATUS + 0 +#define ATA_DEVICE_CONTROL + 0 +#define ATA_DRIVE_ADDRESS + 1 #define ATA_PRIMARY_BUS 0x1F0 #define ATA_SECONDARY_BUS 0x170 @@ -95,36 +75,103 @@ make fini function to destroy global object, and free any remaining resources. //data address mark not found #define ATA_AMNF(a) a & 0x1; -struct { - uint8_t pio_mode:1; - uint8_t lba48:1; - uint8_t drive:2; -}settings = {1, 0, 0}; +//commands +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B + +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 + +#define PCI_IDE_NATIVE(a) a & 1 +#define PCI_IDE_CAN_SET_NATIVE(a) a & 2 +#define PCI_IDE_SECONDARY_NATIVE(a) a & 4 +#define PCI_IDE_SECONDARY_CAN_SET_NATIVE(a) a & 8 +#define PCI_IDE_SUPPORT_DMA(a) (a & 0x80) +#define PCI_CLASS_IS_IDE(a) a == 0x0101; + +typedef struct PRD{ + uint32_t address; + uint16_t byte_count; + uint16_t reserved;//set msb when last; +}__attribute__((packed)) PRD_T; + void fini(); -void ata_identify(); -//return 1 if ready, 0 if not + +enum DRIVE_TYPE{ + TYPE_NULL, + TYPE_IDE, + TYPE_AHCI, + TYPE_NVME, + TYPE_USB, + TYPE_FLOPPY, //Here, Navya, just for you +}; + +typedef struct drive_desc{ + uint32_t BARs[8]; + enum DRIVE_TYPE type; + uint64_t size_sectors; + uint32_t sector_size_bytes; + struct{ + uint8_t irq_dispatched:1; + uint8_t huge:1;//more than 2^28 sectors + uint8_t locked:1;//semaphores!!!!! + uint8_t slave:1;//is this drive a slave drive to another drive? + }__attribute__((packed))flags; + PRD_T *PRDT; +}drive_t; + +drive_t drives[32] = {0}; uint16_t get_bus_from_drive(uint32_t drive){ return drive & 2 ? ATA_SECONDARY_BUS : ATA_PRIMARY_BUS; } -int ata_ready(uint32_t drive){ - uint16_t bus = get_bus_from_drive(drive); - if(settings.drive != drive){ - if(drive & 1){ - outb(bus ATA_DRIVE_HEAD, drive & 1 ? 0xB0 : 0xA0); - } - for(uint32_t i = 0; i < 15; i++){ - uint8_t _ = inb(bus ATA_ALT_STATUS); - } - settings.drive = drive; +//return 1 if ready, 0 if not +int ata_ready(uint32_t BAR, uint32_t BAR2, uint8_t drive){ + if(drive){ + outb(BAR ATA_DRIVE_HEAD, drive ? 0xB0 : 0xA0); } - uint8_t status = inb(bus ATA_ALT_STATUS); + for(uint32_t i = 0; i < 15; i++){ + uint8_t _ = inb(BAR2 ATA_ALT_STATUS); + } + uint8_t status = inb(BAR2 ATA_ALT_STATUS); if(!ATA_BSY(status) || ATA_DRQ(status)) return 1; return 0; } +//return index of first free drive descriptor +uint32_t find_free_drive(){ + for(uint32_t i = 0; i < 32; i++){ + if(drives[i].type == TYPE_NULL){ + return i; + } + } +} + +void ide_init(uint32_t BARS[5]){ + uint32_t index = find_free_drive(); + drives[index].type = TYPE_IDE; + for(int i = 0; i < 5; i++){ + drives[index].BARs[i] = BARS[i]; + } + uint32_t paddr = api(MODULE_API_PMALLOC64K); + drives[index].PRDT = api(MODULE_API_KMALLOC_PADDR, paddr, 16); + api(MODULE_API_PRINT, MODULE_NAME, "Vaddr: %x, Paddr: %x", drives[index].PRDT, paddr); +} void init(KOS_MAPI_FP module_api, uint32_t api_version){ api = module_api; @@ -140,14 +187,35 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){ api(MODULE_API_PRINT, MODULE_NAME, "Failed to register module, exiting\n"); return; } - ata_identify(); + + vfile_t *pci_drive_dir = fopen(api, "/dev/pci/disk/"); + vfile_t **dir_data = (pci_drive_dir->access.data.ptr); + for(uint32_t i = 0; dir_data[i]; i++){ + vfile_t *current_file = dir_data[i]; + uint32_t class = 0; + fread(api, current_file, &class, 0x8, 1); + uint32_t progif = class >> 8 & 0xff; + class >>= 16; + api(MODULE_API_PRINT, MODULE_NAME, "Class: %x, %x\n", class, progif); + if(class == 0x101 && PCI_IDE_SUPPORT_DMA(progif)){ //in this house, we only support DMA. + uint32_t BARs[5] = {0}; + fread(api, current_file, BARs, 0x10, 5); + if(PCI_IDE_NATIVE(progif)){ + BARs[0] = ATA_PRIMARY_BUS; + BARs[1] = ATA_PRIMARY_BUS + 0x206; + } + if(PCI_IDE_SECONDARY_NATIVE(progif)){ + BARs[2] = ATA_SECONDARY_BUS; + BARs[3] = ATA_SECONDARY_BUS + 0x206; + } + ide_init(BARs); + } + } return; } -void ata_identify(){ - -} void fini(){ - //destroy all objects, free memory, and + //destroy all objects, free memory, and exit + return; //nothing to do (yet) } \ No newline at end of file diff --git a/src/kmodules/modlib.h b/src/kmodules/modlib.h index 1656b44..aa55e81 100644 --- a/src/kmodules/modlib.h +++ b/src/kmodules/modlib.h @@ -17,6 +17,8 @@ #define MODULE_API_PADDR 13 //get physical address of memory #define MODULE_API_MALLOC 14 //allocate memory in 4kb blocks #define MODULE_API_FREE 15 //free memory allocated by malloc +#define MODULE_API_PMALLOC64K 16 //get 64k-aligned pages +#define MODULE_API_KMALLOC_PADDR 17 typedef uint32_t (*KOS_MAPI_FP)(unsigned int function, ...); typedef struct module{ @@ -40,15 +42,42 @@ typedef struct virtual_file{ VFILE_TYPE type; uint32_t id;//to be assigned by driver; uint32_t mount_id; + uint8_t lock; + uint32_t size; + struct virtual_file *parent;//should point to A: a virtual directory, or B: a mounted filesystem union{ struct{ - void (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - void (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); + int (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); + int (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); }funcs; struct{ void *ptr; - uint16_t size_pgs; - uint16_t free_bytes; + uint32_t size_pgs; }__attribute__((packed))data; }access; -}vfile_t; \ No newline at end of file +}vfile_t; + +inline void *malloc(KOS_MAPI_FP api, uint32_t size_pages){ + return (void *)api(MODULE_API_MALLOC, size_pages); +} +inline void *free(KOS_MAPI_FP api, void *ptr){ + api(MODULE_API_FREE, ptr); + return 0; +} +inline vfile_t *fopen(KOS_MAPI_FP api, char *filename){ + // vfile_t *file = malloc(api, 1); + return (void *)api(MODULE_API_OPEN, filename); +} +inline int fread(KOS_MAPI_FP api, vfile_t *file, char *buffer, uint32_t offset, uint32_t count){ + return api(MODULE_API_READ, file, buffer, offset, count); +} +inline int fwrite(KOS_MAPI_FP api, vfile_t *file, char *buffer, uint32_t offset, uint32_t count){ + return api(MODULE_API_WRITE, file, buffer, offset, count); +} +//read documenation for this one +inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, VFILE_TYPE type, char *pointer_write, char *size_read){ + return (void *)api(MODULE_API_CREAT, filename, type, pointer_write, size_read); +} +inline void puts(KOS_MAPI_FP api, char *mname, char *str){ + api(MODULE_API_PRINT, mname, str); +};