From 7ff724fe8f709440da9c730fdb8dcbaa4f989ed5 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 13 Aug 2020 23:59:14 -0400 Subject: FAT16 directory enumeration, making many functions static, new 'log' functions to wrap vga and serial --- fs-skel/test.txt | 1 + makefile | 3 +- src/boot.asm | 28 +------ src/kernel/drive.c | 23 ++++-- src/kernel/drive.h | 20 +++-- src/kernel/fat.c | 221 ++++++++++++++++++++++++++++++++++++++++++++-------- src/kernel/ide.c | 34 +++----- src/kernel/log.c | 25 ++++++ src/kernel/log.h | 9 +++ src/kernel/main.c | 75 +++++++++--------- src/kernel/main2.c | 59 ++++++++++++++ src/kernel/panic.c | 7 +- src/kernel/pci.c | 11 +-- src/kernel/serial.c | 67 +++++++--------- src/kernel/serial.h | 18 +++-- src/kernel/vesa.c | 21 ----- src/kernel/vesa.h | 17 ---- src/kernel/vga.c | 44 +++-------- src/kernel/vga.h | 2 - 19 files changed, 434 insertions(+), 251 deletions(-) create mode 100644 fs-skel/test.txt create mode 100644 src/kernel/log.c create mode 100644 src/kernel/log.h create mode 100644 src/kernel/main2.c delete mode 100644 src/kernel/vesa.c delete mode 100644 src/kernel/vesa.h diff --git a/fs-skel/test.txt b/fs-skel/test.txt new file mode 100644 index 0000000..d6d9d34 --- /dev/null +++ b/fs-skel/test.txt @@ -0,0 +1 @@ +blah \ No newline at end of file diff --git a/makefile b/makefile index 2152dde..502a3cc 100644 --- a/makefile +++ b/makefile @@ -39,7 +39,9 @@ kernel: gcc ${kgccargs} -c src/kernel/drive.c -o obj/kernel/drive.o gcc ${kgccargs} -c src/kernel/fat.c -o obj/kernel/fat.o gcc ${kgccargs} -c src/kernel/ide.c -o obj/kernel/ide.o + gcc ${kgccargs} -c src/kernel/log.c -o obj/kernel/log.o gcc ${kgccargs} -c src/kernel/main.c -o obj/kernel/main.o + gcc ${kgccargs} -c src/kernel/main2.c -o obj/kernel/main2.o gcc ${kgccargs} -c src/kernel/mem.c -o obj/kernel/mem.o gcc ${kgccargs} -c src/kernel/panic.c -o obj/kernel/panic.o gcc ${kgccargs} -c src/kernel/pci.c -o obj/kernel/pci.o @@ -47,7 +49,6 @@ kernel: gcc ${kgccargs} -c src/kernel/serial.c -o obj/kernel/serial.o gcc ${kgccargs} -c src/kernel/task.c -o obj/kernel/task.o gcc ${kgccargs} -c src/kernel/util.c -o obj/kernel/util.o - gcc ${kgccargs} -c src/kernel/vesa.c -o obj/kernel/vesa.o gcc ${kgccargs} -c src/kernel/vga.c -o obj/kernel/vga.o ld -T src/kernel/elf-link.ld obj/kernel/*.o -o obj/kernel.elf objcopy -O binary obj/kernel.elf out/kernel.bin diff --git a/src/boot.asm b/src/boot.asm index eb3b2c9..c74145c 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -5,13 +5,12 @@ kernel_sectors equ 64 kernel_segment equ 0x3000 support_flags equ 0x4000 -pci_hw_char equ 0x4001 -pci_ver equ 0x4002 +pci_hw_char equ 0x4001 +pci_ver equ 0x4002 +last_pci_bus equ 0x4004 pci_support equ 0x80 -vesa_segment equ 0x0420 - in al, 0x92 or al, 0x02 out 0x92, al @@ -44,19 +43,9 @@ vesa_segment equ 0x0420 mov byte [support_flags], pci_support mov byte [pci_hw_char], al mov word [pci_ver], bx + mov byte [last_pci_bus], cl no_pci: - mov dword [vesa_segment * 16], 'V' + 'B' * 256 + 'E' * 65535 + '2' * 16777216 - - mov ax, vesa_segment - mov es, ax - xor di, di - mov ax, 0x4f00 - int 0x10 - - cmp ax, 0x004f - jne no_vbe - cli lgdt [gdt] @@ -67,15 +56,6 @@ no_pci: jmp 0x08:pmode -no_vbe: - ;TODO - - cli - -real_halt: - hlt - jmp real_halt - bits 32 pmode: diff --git a/src/kernel/drive.c b/src/kernel/drive.c index b001aca..38fef38 100644 --- a/src/kernel/drive.c +++ b/src/kernel/drive.c @@ -5,23 +5,34 @@ uint8_t n_drives = 0; struct drive drives[256]; -__attribute__ ((const)) drive_file_id_t unknown_get_file(const struct drive *d, const char *path) { +__attribute__ ((const)) +static drive_file_id_t unknown_get_file(const struct drive *d, const char *path) { return 0; } -void unknown_free_file(const struct drive *d, drive_file_id_t fid) { +static void unknown_free_file(const struct drive *d, drive_file_id_t fid) { panic("Free file called on unknown file system"); } -void unknown_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { +static void unknown_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { panic("Load sector called on unknown file system"); } -__attribute__ ((const)) uint32_t unknown_get_free_sectors(const struct drive *d) { +static uint32_t unknown_get_file_length(const struct drive *d, drive_file_id_t fid) { + panic("Get file length called on unknown file system"); +} + +__attribute__ ((const)) +static uint32_t unknown_get_free_sectors(const struct drive *d) { return -1; } -void determine_fs(struct drive *d) { +__attribute__ ((const)) +static uint32_t unknown_enumerate_dir(const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max) { + return 0; +} + +static void determine_fs(struct drive *d) { if (try_fat_init_drive(d)) return; @@ -29,6 +40,8 @@ void determine_fs(struct drive *d) { d->get_file = &unknown_get_file; d->free_file = &unknown_free_file; d->load_sector = &unknown_load_sector; + d->get_file_length = &unknown_get_file_length; + d->enumerate_dir = &unknown_enumerate_dir; d->get_free_sectors = &unknown_get_free_sectors; } diff --git a/src/kernel/drive.h b/src/kernel/drive.h index ca6d1ee..8eb6955 100644 --- a/src/kernel/drive.h +++ b/src/kernel/drive.h @@ -1,6 +1,7 @@ #ifndef DRIVE_H #define DRIVE_H +#include #include typedef uint8_t drive_file_id_t; @@ -9,20 +10,29 @@ typedef uint8_t fs_id_t; typedef uint8_t drive_id_t; #define MAX_DRIVES 256 +#define DCI_NAME_LEN 100 + +struct directory_content_info { + bool is_dir; + char name[DCI_NAME_LEN]; + uint32_t size; +}; struct drive { char *drive_type; char *fs_type; - uint8_t (*read_sectors)(const struct drive *d, uint32_t start, uint32_t count, void *buffer); + uint8_t (*read_sectors) (const struct drive *d, uint32_t start, uint32_t count, void *buffer); uint8_t (*write_sectors)(const struct drive *d, uint32_t start, uint32_t count, const void *buffer); uint32_t n_sectors; drive_id_t drive_id; - drive_file_id_t (*get_file)(const struct drive *d, const char *path); - void (*free_file)(const struct drive *d, drive_file_id_t fid); - void (*load_sector)(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at); - uint32_t (*get_free_sectors)(const struct drive *d); + drive_file_id_t (*get_file) (const struct drive *d, const char *path); + void (*free_file) (const struct drive *d, drive_file_id_t fid); + void (*load_sector) (const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at); + uint32_t (*get_file_length) (const struct drive *d, drive_file_id_t fid); + uint32_t (*enumerate_dir) (const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max); + uint32_t (*get_free_sectors)(const struct drive *d); fs_id_t fs_id; }; diff --git a/src/kernel/fat.c b/src/kernel/fat.c index 807af00..ff01d7d 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -8,6 +8,9 @@ #define MAX_FAT_DRIVES 16 #define MAX_OPEN_FILES_PER_DRIVE 32 +#define PATH_SEP_CHAR '/' +#define EXT_SEP_CHAR '.' + enum { FA_READ_ONLY = 0x01, FA_HIDDEN = 0x02, @@ -59,33 +62,44 @@ struct fat_info { #define CTOS(c, fdi) ((fdi)->data_start + (c) - 2) +struct open_file_info { + //directory entry is the di_number'th entry in the di_sector'th sector + //di_sector of 0 indicates an unused handle + uint32_t di_sector; + uint8_t di_number; + + uint16_t start_cluster; + uint32_t length; +}; + struct fat_drive_info { const struct fat_info *fi; uint16_t *fat; uint16_t root_start; uint16_t data_start; - struct directory_entry open_files[MAX_OPEN_FILES_PER_DRIVE]; + struct open_file_info open_files[MAX_OPEN_FILES_PER_DRIVE]; }; -struct fat_drive_info infos[MAX_FAT_DRIVES]; -uint8_t next_id = 0; +static struct fat_drive_info infos[MAX_FAT_DRIVES]; +static uint8_t next_id = 0; -uint8_t fat_driver_buffer[512]; -struct fat_info *next_fi; +static uint8_t fat_driver_buffer[512]; +static struct fat_info *next_fi; -void alloc_next_fi() { +static void alloc_next_fi() { if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff)) if (!(next_fi = allocate_pages(1))) panic("Out of memory in FAT driver."); } -const struct drive *cur_drive; -fs_id_t cur_id; -const struct fat_drive_info *cur_fdi; -struct directory_entry *cur_dir; +static const struct drive *cur_drive; +static fs_id_t cur_id; +static const struct fat_drive_info *cur_fdi; +static struct directory_entry *cur_dir; +static uint32_t cur_sect; //loads cluster `c` -void load_cluster(uint16_t c, void *to) { +static void load_cluster(uint16_t c, void *to) { if (c == 0) { *(uint8_t *)to = 0; return; @@ -95,26 +109,29 @@ void load_cluster(uint16_t c, void *to) { cur_drive->read_sectors(cur_drive, s, 1, to); } -uint16_t next_cluster(uint16_t c) { +static uint16_t next_cluster(uint16_t c) { panic("TODO: compute next sector (or 0 for none)"); } +static const uint8_t this_dir[] = {'.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; +static const uint8_t parent_dir[] = {'.', '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; + static inline bool check_fat_names(const uint8_t *a, const uint8_t *b) { return (((uint32_t *)a)[0] == ((uint32_t *)b)[0]) && (((uint32_t *)a)[1] == ((uint32_t *)b)[1]) && - (((uint16_t *)a)[8] == ((uint16_t *)b)[8]) && + (((uint16_t *)a)[4] == ((uint16_t *)b)[4]) && (((uint8_t *)a)[10] == ((uint8_t *)b)[10]); } //after: cur_dir -> specified entry in root -bool try_locate_root_entry(const uint8_t *fat_name) { - uint32_t cur_dir_sect = cur_fdi->root_start - 1; +static bool try_locate_root_entry(const uint8_t *fat_name) { + cur_sect = cur_fdi->root_start - 1; cur_dir = (struct directory_entry *)(fat_driver_buffer + 512); while (true) { if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) { cur_dir = (struct directory_entry *)fat_driver_buffer; - ++cur_dir_sect; - cur_drive->read_sectors(cur_drive, cur_dir_sect, 1, cur_dir); + ++cur_sect; + cur_drive->read_sectors(cur_drive, cur_sect, 1, cur_dir); } if (!*(uint8_t *)cur_dir) return false; @@ -127,53 +144,109 @@ bool try_locate_root_entry(const uint8_t *fat_name) { //before: cur_dir -> entry of dir to search //after: cur_dir -> specified entry in dir -bool try_locate_entry(const uint8_t *fat_name) { +static bool try_locate_entry(const uint8_t *fat_name) { uint16_t cur_dir_cluster = cur_dir->first_cluster; load_cluster(cur_dir_cluster, fat_driver_buffer); cur_dir = (struct directory_entry *)fat_driver_buffer; while (true) { if (cur_dir == (struct directory_entry *)(fat_driver_buffer + 512)) { cur_dir = (struct directory_entry *)fat_driver_buffer; - ++cur_dir_cluster; load_cluster(cur_dir_cluster = next_cluster(cur_dir_cluster), fat_driver_buffer); } if (!*(uint8_t *)cur_dir) return false; - if (check_fat_names(cur_dir -> name, fat_name)) + if (check_fat_names(cur_dir->name, fat_name)) { + cur_sect = CTOS(cur_dir_cluster, cur_fdi); return true; + } else ++cur_dir; } } -drive_file_id_t fat_get_file(const struct drive *d, const char *path) { +//puts first path component's fat name into fat_name_buffer, +//returns rest of path +static const char *split_path(const char *path, uint8_t *fat_name_buffer) { + uint8_t pi = 0, fi = 0; + while (1) { + if ((path[pi] == PATH_SEP_CHAR) || !path[pi]) { + while (fi != 11) + fat_name_buffer[fi++] = (uint8_t)' '; + return path + (path[pi] ? pi + 1 : pi); + } + if (path[pi] == EXT_SEP_CHAR) + if (fi <= 8) { + while (fi != 8) + fat_name_buffer[fi++] = (uint8_t)' '; + ++pi; + } + else + panic("Bad path in FAT16 driver"); + else if ((fi == 8) || (fi == 11)) + panic("Bad path in FAT16 driver"); + else { + fat_name_buffer[fi++] = (uint8_t)path[pi++]; + } + } +} + +//cur_dir -> specified entry +static bool try_load_from_path(const struct drive *d, const char *path) { cur_drive = d; cur_id = d->drive_id; cur_fdi = &infos[cur_id]; - const struct directory_entry *open_files = cur_fdi->open_files - 1; + + uint8_t fat_name[11]; + path = split_path(path, fat_name); + if (!try_locate_root_entry(fat_name)) + return false; + while (*path) { + path = split_path(path, fat_name); + if (!try_locate_entry(fat_name)) + return false; + } + + return true; +} + +static drive_file_id_t fat_get_file(const struct drive *d, const char *path) { + struct open_file_info *open_files = infos[d->drive_id].open_files - 1; for (drive_file_id_t n = 1; n != MAX_OPEN_FILES_PER_DRIVE + 1; ++n) - if (!*(uint8_t *)(&open_files[n])) { - panic("TODO: open path into open_files[n]"); + if (!open_files[n].di_sector) { + if (!try_load_from_path(d, path)) + return 0; + + open_files[n].di_sector = cur_sect; + open_files[n].di_number = cur_dir - (struct directory_entry *)fat_driver_buffer; + open_files[n].start_cluster = cur_dir->first_cluster; + open_files[n].length = cur_dir->length; return n; } + panic("Maximum number of files open reached for FAT drive."); } -void fat_free_file(const struct drive *d, drive_file_id_t fid) { - *(uint8_t *)(&infos[d->drive_id].open_files[fid - 1]) = 0; +static void fat_free_file(const struct drive *d, drive_file_id_t fid) { + infos[d->drive_id].open_files[fid - 1].di_sector = 0; } -void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { +static void fat_load_sector(const struct drive *d, drive_file_id_t fid, uint32_t sector, void *at) { cur_drive = d; cur_id = d->drive_id; cur_fdi = &infos[cur_id]; - uint16_t c = cur_fdi->open_files[fid - 1].first_cluster; + uint16_t c = cur_fdi->open_files[fid - 1].start_cluster; for (uint32_t i = 0; i < sector; ++i) c = next_cluster(c); load_cluster(c, at); } -__attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) { +__attribute__ ((pure)) +static uint32_t fat_get_file_length(const struct drive *d, drive_file_id_t fid) { + return infos[d->drive_id].open_files[fid - 1].length; +} + +__attribute__ ((pure)) +static uint32_t fat_get_free_sectors(const struct drive *d) { uint16_t *start = infos[d->fs_id].fat + 2; uint16_t *end = start + d->n_sectors - infos[d->fs_id].data_start; uint32_t count = 0; @@ -183,6 +256,90 @@ __attribute__ ((pure)) uint32_t fat_get_free_sectors(const struct drive *d) { return count; } +static void fat_name_to_path(const uint8_t *fat_name, char *path) { + uint8_t last_visible = -1; + for (uint8_t i = 0; i < 8; ++i) { + if (fat_name[i] != (uint8_t)' ') + last_visible = i; + path[i] = (char)fat_name[i]; + } + + if (fat_name[8] || fat_name[9] || fat_name[10]) { + path[last_visible + 1] = EXT_SEP_CHAR; + for (uint8_t fi = 8, ti = last_visible + 2; fi < 11; ++fi, ++ti) { + if (fat_name[fi] != (uint8_t)' ') + last_visible = ti; + path[ti] = (char)fat_name[fi]; + } + } + + path[last_visible + 1] = '\0'; +} + +static uint32_t enumerate_root(const struct drive *d, struct directory_content_info *info, uint32_t max) { + uint32_t sect = infos[d->drive_id].root_start - 1; + struct directory_entry *entry = (struct directory_entry *)(fat_driver_buffer + 512); + struct directory_content_info *fill = info; + + while (true) { + if (entry == (struct directory_entry *)(fat_driver_buffer + 512)) { + entry = (struct directory_entry *)fat_driver_buffer; + ++sect; + d->read_sectors(d, sect, 1, entry); + } + + if (!*(uint8_t *)entry || (info == fill + max)) + return fill - info; + + if (entry-> attrib & FA_LABEL) { + ++entry; + continue; + } + + fill->is_dir = entry->attrib & FA_DIRECTORY; + fill->size = entry->length; + fat_name_to_path(entry->name, fill->name); + + ++entry; + ++fill; + } +} + +static uint32_t fat_enumerate_dir(const struct drive *d, const char *path, struct directory_content_info *info, uint32_t max) { + if (!*path) + return enumerate_root(d, info, max); + + if (!try_load_from_path(d, path)) + return 0; + + uint16_t cluster = cur_dir->first_cluster; + load_cluster(cluster, fat_driver_buffer); + struct directory_entry *entry = (struct directory_entry *)fat_driver_buffer; + struct directory_content_info *fill = info; + + while (true) { + if (entry == (struct directory_entry *)(fat_driver_buffer + 512)) { + entry = (struct directory_entry *)fat_driver_buffer; + load_cluster(cluster = next_cluster(cluster), fat_driver_buffer); + } + + if (!*(uint8_t *)entry || (fill == info + max)) + return fill - info; + + if (check_fat_names(entry->name, this_dir) || check_fat_names(entry->name, parent_dir)) { + ++entry; + continue; + } + + fill->is_dir = entry->attrib & FA_DIRECTORY; + fill->size = entry->length; + fat_name_to_path(entry->name, fill->name); + + ++entry; + ++fill; + } +} + void init_fat() { next_fi = allocate_pages(1); } @@ -203,6 +360,8 @@ bool try_fat_init_drive(struct drive *d) { d->get_file = &fat_get_file; d->free_file = &fat_free_file; d->load_sector = &fat_load_sector; + d->get_file_length = &fat_get_file_length; + d->enumerate_dir = &fat_enumerate_dir; d->get_free_sectors = &fat_get_free_sectors; d->fs_id = next_id; @@ -214,9 +373,9 @@ bool try_fat_init_drive(struct drive *d) { ((next_fi->root_entries - 1) >> 4) + 1; d->read_sectors(d, next_fi->reserved_sectors, next_fi->sectors_per_fat, infos[next_id].fat); - struct directory_entry *open_files = infos[next_id].open_files - 1; + struct open_file_info *open_files = infos[next_id].open_files - 1; for (drive_file_id_t i = 0; i < MAX_OPEN_FILES_PER_DRIVE; ++i) - *(uint8_t *)&open_files[i] = 0; + open_files[i].di_sector = 0; alloc_next_fi(); ++next_id; diff --git a/src/kernel/ide.c b/src/kernel/ide.c index a32f149..a4ba34c 100644 --- a/src/kernel/ide.c +++ b/src/kernel/ide.c @@ -14,25 +14,13 @@ struct ide_drive_info { bool slave; }; -struct ide_drive_info ide_drives[MAX_IDE_DRIVES]; -drive_id_t n_ide_drives = 0; +static struct ide_drive_info ide_drives[MAX_IDE_DRIVES]; +static drive_id_t n_ide_drives = 0; typedef uint16_t spinner_t; //returns the status after waiting -uint8_t wait_after_cmd(uint16_t base_port) { - for (spinner_t n = -1; n; --n) { - uint8_t s = inb(base_port | ATA_REG_STATUS); - if (s & ATA_STATUS_ERROR) - panic("Error status in IDE driver."); - if (!(s & ATA_STATUS_BUSY)) - return s; - } - panic("Spun out in IDE driver."); -} - -//returns the status after waiting -uint8_t wait_for_ready(uint16_t base_port) { +static uint8_t wait_for_ready(uint16_t base_port) { for (spinner_t n = -1; n; --n) { uint8_t s = inb(base_port | ATA_REG_STATUS); if (s & ATA_STATUS_ERROR) @@ -44,7 +32,7 @@ uint8_t wait_for_ready(uint16_t base_port) { } //returns the status after waiting -uint8_t wait_for_error_or_ready(uint16_t base_port) { +static uint8_t wait_for_error_or_ready(uint16_t base_port) { for (spinner_t n = -1; n; --n) { uint8_t s = inb(base_port | ATA_REG_STATUS); if (s & (ATA_STATUS_DRIVE_READY | ATA_STATUS_ERROR)) @@ -54,7 +42,7 @@ uint8_t wait_for_error_or_ready(uint16_t base_port) { } //returns the status after waiting -uint8_t wait_for_data_ready_not_busy(uint16_t base_port) { +static uint8_t wait_for_data_ready_not_busy(uint16_t base_port) { for (spinner_t n = -1; n; --n) { uint8_t s = inb(base_port | ATA_REG_STATUS); if (!(s & ATA_STATUS_BUSY) && (s & ATA_STATUS_DATA_READY)) @@ -65,7 +53,7 @@ uint8_t wait_for_data_ready_not_busy(uint16_t base_port) { panic("Spun out in IDE driver."); } -uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { +static uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { if (start >= d->n_sectors) return 0; if (start + count > d->n_sectors) @@ -103,17 +91,17 @@ uint8_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void * return count; } -uint8_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { +static uint8_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { panic("IDE ATA writing not implemented yet"); return 0; } -uint8_t ide_atapi_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { +static uint8_t ide_atapi_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { //panic("IDE ATAPI reading not implemented yet"); return 0; } -uint8_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { +static uint8_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { panic("IDE ATAPI writing not implemented yet"); return 0; } @@ -124,9 +112,7 @@ struct id_space { uint8_t skip2[512 - (120 + 4)]; } __attribute__ ((__packed__ )); -void vga_printsz(char *s); - -void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { +static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { if (n_ide_drives == MAX_IDE_DRIVES) panic("Maximum number of IDE drives reached."); diff --git a/src/kernel/log.c b/src/kernel/log.c new file mode 100644 index 0000000..e8695cc --- /dev/null +++ b/src/kernel/log.c @@ -0,0 +1,25 @@ +#include "vga.h" +#include "serial.h" + +#define INFO_COM COM1 + +void init_log() { + vga_set_color(0x2f); + vga_blank(); +} + +void logch(char ch) { + if (ch == '\n') { + sout(INFO_COM, (uint8_t)'\r'); + sout(INFO_COM, (uint8_t)'\n'); + } + else + sout(INFO_COM, (uint8_t)ch); + + vga_printch(ch); +} + +void logsz(const char *sz) { + while (*sz) + logch(*sz++); +} \ No newline at end of file diff --git a/src/kernel/log.h b/src/kernel/log.h new file mode 100644 index 0000000..ff2a7a2 --- /dev/null +++ b/src/kernel/log.h @@ -0,0 +1,9 @@ +#ifndef LOG_H +#define LOG_H + +void init_log(); + +void logch(char ch); +void logsz(const char *sz); + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index cbdebfa..0c57ef3 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,55 +3,56 @@ #include "panic.h" #include "boot.h" #include "util.h" -#include "vesa.h" #include "fat.h" #include "ide.h" #include "mem.h" #include "pci.h" -#include "vga.h" +#include "log.h" -__attribute__ ((noreturn)) void main() { +void tree(struct drive *d); + +__attribute__ ((noreturn)) +void main() { char nbuf[11]; init_mmap(); - init_vesa(); init_serial(); + init_log(); - vga_blank(); - vga_printsz("Portland v0.0.11\n\n"); + logsz("Portland v0.0.11\n\n"); //list vesa modes? pci_init(); u16_dec(n_pci_devices, nbuf); - vga_printsz(nbuf); - vga_printsz(" PCI device(s) found:\n"); + logsz(nbuf); + logsz(" PCI device(s) found:\n"); for (uint16_t n = 0; n < n_pci_devices; ++n) { struct pci_device *pd = nth_pci_device(n); u16_hex(pd->number, nbuf); - vga_printsz(" "); - vga_printsz(nbuf); - vga_printsz(": "); + logsz(" "); + logsz(nbuf); + logsz(": "); u16_hex(pd->id_vendor, nbuf); nbuf[4] = '.'; u16_hex(pd->id_device, nbuf + 5); - vga_printsz(nbuf); + logsz(nbuf); u8_hex(pd->class, nbuf); nbuf[2] = '.'; u8_hex(pd->subclass, nbuf + 3); nbuf[5] = '.'; u8_hex(pd->iface, nbuf + 6); - vga_printsz(" ("); - vga_printsz(nbuf); - vga_printsz(")\n"); + logsz(" ("); + logsz(nbuf); + logsz(")\n"); } - vga_printch('\n'); + logch('\n'); init_fat(); //other fs drivers @@ -60,49 +61,49 @@ __attribute__ ((noreturn)) void main() { //other drive drivers u8_dec(n_drives, nbuf); - vga_printsz(nbuf); - vga_printsz(" drive(s) found:\n"); + logsz(nbuf); + logsz(" drive(s) found:\n"); for (uint8_t n = 0; n < n_drives; ++n) { struct drive *d = drives + n; u8_dec(n, nbuf); - vga_printsz(" sd"); - vga_printsz(nbuf); - vga_printsz(" ("); - vga_printsz(d->drive_type); - vga_printsz(", "); + logsz(" sd"); + logsz(nbuf); + logsz(" ("); + logsz(d->drive_type); + logsz(", "); u32_dec(d->n_sectors / 2, nbuf); - vga_printsz(nbuf); + logsz(nbuf); if (d->n_sectors % 2) - vga_printsz(".5"); - vga_printsz("k): "); + logsz(".5"); + logsz("k): "); - vga_printsz(d->fs_type); + logsz(d->fs_type); uint32_t free_sectors = d->get_free_sectors(d); if (free_sectors != -1) { u32_dec(free_sectors / 2, nbuf); - vga_printsz(", "); - vga_printsz(nbuf); + logsz(", "); + logsz(nbuf); if (free_sectors % 2) - vga_printsz(".5"); - vga_printsz("k free"); + logsz(".5"); + logsz("k free"); } - vga_printsz(".\n"); + logsz(".\n"); } - vga_printch('\n'); + logch('\n'); u32_dec(pages_left * 4, nbuf); - vga_printsz(nbuf); - vga_printsz("k dynamic memory free.\n\n"); + logsz(nbuf); + logsz("k dynamic memory free.\n\n"); - vga_printsz("Loading init process."); + logsz("sd0 root:\n"); + tree(&drives[0]); - vga_printsz("\n\nTODO: load and switch to init process"); while (1) asm ("hlt"); } \ No newline at end of file diff --git a/src/kernel/main2.c b/src/kernel/main2.c new file mode 100644 index 0000000..2b85592 --- /dev/null +++ b/src/kernel/main2.c @@ -0,0 +1,59 @@ +#include +#include "drive.h" +#include "util.h" +#include "log.h" + +static char nbuf2[11]; + +static char path_builder[200] = ""; +static uint8_t path_builder_len = 0; + +static char indent_builder[20] = " "; +static uint8_t indent_builder_len = 2; + +void tree(struct drive *d) { + struct directory_content_info infos[100]; + uint8_t n_infos = d->enumerate_dir(d, path_builder, infos, 100); + + if (!n_infos) { + logsz(indent_builder); + logsz("(empty)\n"); + return; + } + + for (uint8_t i = 0; i < n_infos; ++i) { + logsz(indent_builder); + logsz(infos[i].name); + + if (infos[i].is_dir) { + logsz(":\n"); + + indent_builder[indent_builder_len] = ' '; + indent_builder[indent_builder_len + 1] = ' '; + indent_builder[indent_builder_len + 2] = '\0'; + indent_builder_len += 2; + + uint8_t name_length = 0; + while (infos[i].name[name_length]) + ++name_length; + + memcpy(path_builder + path_builder_len, infos[i].name, name_length + 1); + path_builder_len += name_length; + + tree(d); + + path_builder_len -= name_length; + path_builder[path_builder_len] = '\0'; + + indent_builder_len -= 2; + indent_builder[indent_builder_len] = '\0'; + } + + else { + u32_dec(infos[i].size, nbuf2); + logsz(" ("); + logsz(nbuf2); + logsz(" bytes)\n"); + } + } +} \ No newline at end of file diff --git a/src/kernel/panic.c b/src/kernel/panic.c index e04ae38..7793065 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -1,12 +1,13 @@ #include "panic.h" +#include "log.h" #include "vga.h" void panic(const char *message) { vga_set_color(0x4f); vga_blank(); - vga_printsz("Kernel panic: "); - vga_printsz(message); - vga_printsz("\nHalting."); + logsz("Kernel panic: "); + logsz(message); + logsz("\nHalting."); while (1) asm volatile ("hlt"); } \ No newline at end of file diff --git a/src/kernel/pci.c b/src/kernel/pci.c index 5d8170d..28ca6c6 100644 --- a/src/kernel/pci.c +++ b/src/kernel/pci.c @@ -10,7 +10,7 @@ enum { }; uint16_t n_pci_devices = 0; -struct pci_device *pci_device_pages[256]; +static struct pci_device *pci_device_pages[256]; #define PCI_DEVICES_PER_PAGE (4096 / sizeof(struct pci_device)) @@ -29,20 +29,21 @@ struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_ return 0; } -struct pci_device *next_pci_device() { +static struct pci_device *next_pci_device() { if (!(n_pci_devices % PCI_DEVICES_PER_PAGE)) - pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_pages(1); + if (!(pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_pages(1))) + panic("Out of memory in PCI enumeration"); return nth_pci_device(n_pci_devices++); } -static inline uint32_t pci_read_config(uint16_t number, uint8_t reg) { +static uint32_t pci_read_config(uint16_t number, uint8_t reg) { uint32_t cspace_addr = 0x80000000 | (number << 8) | (reg << 2); outd(PCP_SELECT, cspace_addr); return ind(PCP_READ); } -void pci_device_check(uint16_t number) { +static void pci_device_check(uint16_t number) { uint32_t id = pci_read_config(number, 0); if ((id & 0xffff) == 0xffff) return; diff --git a/src/kernel/serial.c b/src/kernel/serial.c index c92f173..9ca8315 100644 --- a/src/kernel/serial.c +++ b/src/kernel/serial.c @@ -48,54 +48,47 @@ enum { CLS_READ = 0x01 }; -bool error; -#define SERIAL_SPIN_LIMIT 65535 +static const uint16_t ports[] = { + CP_1, CP_2, CP_3, CP_4 +}; + +static bool error[] = { + false, false, false, false +}; -bool serr() { - return error; +void reset_error(enum serial_port n) { + error[n] = false; } void init_serial() { - error = false; - outb(CP_1 | CP_INT, 0); - outb(CP_1 | CP_LINE, CL_BAUD); - outb(CP_1 | CP_DIVLOW, 0x03);//38400 - outb(CP_1 | CP_DIVHIGH, 0x00);//baud - outb(CP_1 | CP_LINE, CL_8BIT); - outb(CP_1 | CP_FIFO, 0xc7);//? + for (enum serial_port i = COM1; i <= COM4; ++i) { + outb(ports[i] | CP_INT, 0); + outb(ports[i] | CP_LINE, CL_BAUD); + outb(ports[i] | CP_DIVLOW, 0x03);//38400 + outb(ports[i] | CP_DIVHIGH, 0x00);//baud + outb(ports[i] | CP_LINE, CL_8BIT); + outb(ports[i] | CP_FIFO, 0xc7);//? + } } -void sout(char b) { - if (error) +typedef uint16_t serial_spin_t; + +void sout(enum serial_port n, uint8_t b) { + if (error[n]) return; - uint16_t s = SERIAL_SPIN_LIMIT; - while (!(inb(CP_1 | CP_LINE_S) & CLS_WRITE)) - if (!--s) { - error = true; + serial_spin_t spinner = -1; + while (!(inb(ports[n] | CP_LINE_S) & CLS_WRITE)) + if (--spinner) { + error[n] = true; return; } - outb(CP_1 | CP_DATA, (uint8_t)b); -} - -void soutsz(const char *s) { - while (*s) - sout(*(s++)); -} - -void soutsn(const char *s, uint8_t n) { - while (n--) - sout(*(s++)); + outb(ports[n] | CP_DATA, b); } -char sin() { - if (error) +uint8_t sin(enum serial_port n) { + if (error[n]) return 0; - while (!(inb(CP_1 | CP_LINE_S) & CLS_READ)) + while (!(inb(ports[n] | CP_LINE_S) & CLS_READ)) ;//spin - return (char)inb(CP_1 | CP_DATA); -} - -void sinsn(char *s, uint8_t n) { - while (n--) - *(s++) = sin(); + return inb(ports[n] | CP_DATA); } \ No newline at end of file diff --git a/src/kernel/serial.h b/src/kernel/serial.h index 2fb21a6..2ac359d 100644 --- a/src/kernel/serial.h +++ b/src/kernel/serial.h @@ -1,15 +1,19 @@ #ifndef SERIAL_H #define SERIAL_H -#include #include -bool serr() __attribute__ ((pure)); +enum serial_port { + COM1, + COM2, + COM3, + COM4 +}; + +void reset_error(enum serial_port n); void init_serial(); -void sout(char b); -void soutsz(const char *s); -void soutsn(const char *s, uint8_t n); -char sin(); -void sinsn(char *s, uint8_t n); + +void sout(enum serial_port n, uint8_t b); +uint8_t sin(enum serial_port n); #endif \ No newline at end of file diff --git a/src/kernel/vesa.c b/src/kernel/vesa.c deleted file mode 100644 index 4cdabb2..0000000 --- a/src/kernel/vesa.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "vesa.h" - -uint16_t screen_width; -uint16_t screen_height; -uint8_t bpp; - -void *frame_buffer; - -void put_pixel(uint16_t x, uint16_t y, color c) { - -} - -void screen_fill(color c) { - -} - -void init_vesa() { -// for (void *v = 0; v < 0x65536; ++v) { -// if (*(uint32_t *)v == 'P' + 'M' * 256 + 'I' * 65536 + 'D' * 16777216) -// } -} \ No newline at end of file diff --git a/src/kernel/vesa.h b/src/kernel/vesa.h deleted file mode 100644 index b2f17c8..0000000 --- a/src/kernel/vesa.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef VESA_H -#define VESA_H - -#include - -extern uint16_t screen_width; -extern uint16_t screen_height; -extern uint8_t bpp; - -typedef uint32_t color; - -void put_pixel(uint16_t x, uint16_t y, color c); -void screen_fill(color c); - -void init_vesa(); - -#endif \ No newline at end of file diff --git a/src/kernel/vga.c b/src/kernel/vga.c index e103732..7506416 100644 --- a/src/kernel/vga.c +++ b/src/kernel/vga.c @@ -1,61 +1,41 @@ #include #include -#define VGA_COM_MIRROR - -#ifdef VGA_COM_MIRROR -#include "serial.h" -#endif - #define VGA_COLUMNS 80 #define VGA_LINES 25 #define VGA_START (uint16_t *)0x000b8000 #define VGA_END (VGA_START + VGA_COLUMNS * VGA_LINES) -uint16_t *cursor = VGA_START; -uint16_t color = 0x1f00; +static uint16_t *cursor = VGA_START; +static uint16_t mask; void vga_set_color(uint8_t new_color) { - color = new_color << 8; + mask = new_color << 8; } void vga_scroll() { - cursor = VGA_START; + for (uint32_t *i = (uint32_t *)VGA_START; i < (uint32_t *)(VGA_END - VGA_COLUMNS); ++i) + *i = *(i + VGA_COLUMNS / 2); + uint32_t f = (mask | (uint8_t)' ') * 0x00010001; + for (uint32_t *i = (uint32_t *)(VGA_END - VGA_COLUMNS); i < (uint32_t *)VGA_END; ++i) + *i++ = f; + cursor -= VGA_COLUMNS; } void vga_blank() { -#ifdef VGA_COM_MIRROR - soutsz("\r\n\r\n\r\n\r\n"); -#endif - uint32_t f = (color << 16) | color | 0x00200020; + uint32_t f = (mask | (uint8_t)' ') * 0x00010001; uint32_t *p = (uint32_t *)VGA_START; while (p < (uint32_t *)VGA_END) - *(p++) = f; + *p++ = f; cursor = VGA_START; } void vga_printch(char ch) { if (ch == '\n') { -#ifdef VGA_COM_MIRROR - soutsz("\r\n"); -#endif if ((cursor = cursor - (cursor - VGA_START) % VGA_COLUMNS + VGA_COLUMNS) == VGA_END) vga_scroll(); return; } -#ifdef VGA_COM_MIRROR - sout(ch); -#endif - *(cursor++) = color | (uint8_t)ch; + *cursor++ = mask | (uint8_t)ch; if (cursor == VGA_END) vga_scroll(); -} - -void vga_printsz(const char *sz) { - while (*sz) - vga_printch(*(sz++)); -} - -void vga_printsn(const char *sn, uint8_t n) { - while (n--) - vga_printch(*(sn++)); } \ No newline at end of file diff --git a/src/kernel/vga.h b/src/kernel/vga.h index e88ddfe..703080f 100644 --- a/src/kernel/vga.h +++ b/src/kernel/vga.h @@ -7,7 +7,5 @@ void vga_set_color(uint8_t color); void vga_blank(); void vga_scroll(); void vga_printch(char ch); -void vga_printsz(const char *sz); -void vga_printsn(const char *sn, uint8_t n); #endif \ No newline at end of file -- cgit v1.2.3