From 58b5c8ba417fe99c01d9a48731b887ce434e797e Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Fri, 27 Dec 2019 17:19:51 -0500 Subject: lots of new stuff. new memory manager, some stuff on file plumbing --- makefile | 6 ++- src/kernel/diskio.c | 36 ++++++++++++++++ src/kernel/diskio.h | 52 ++++++++++++++++++++++++ src/kernel/files.c | 35 ++++++++++++++++ src/kernel/files.h | 24 +++++++++++ src/kernel/gpt.c | 40 ++++++++++++++++++ src/kernel/gpt.h | 69 +++++++++++++++++++++++++++++++ src/kernel/main.c | 94 ++++++++++++++++++++++-------------------- src/kernel/mem.c | 115 ++++++++++++++++++++++++---------------------------- src/kernel/mem.h | 5 ++- 10 files changed, 365 insertions(+), 111 deletions(-) create mode 100644 src/kernel/diskio.c create mode 100644 src/kernel/diskio.h create mode 100644 src/kernel/gpt.c create mode 100644 src/kernel/gpt.h diff --git a/makefile b/makefile index c126c46..5c0eedd 100644 --- a/makefile +++ b/makefile @@ -14,14 +14,16 @@ kernel: obj out nasm src/kernel/keyb.asm -o obj/kkeyba.o -f elf32 nasm src/kernel/serial.asm -o obj/kserial.o -f elf32 nasm src/kernel/stub.asm -o obj/kstub.o -f elf32 + gcc -c src/kernel/diskio.c -o obj/kdiskio.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/files.c -o obj/kfiles.o -ffreestanding -nostdlib -m32 + gcc -c src/kernel/gpt.c -o obj/kgpt.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/keyb.c -o obj/kkeybc.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/main.c -o obj/kmain.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/mem.c -o obj/kmem.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/proc.c -o obj/kproc.o -ffreestanding -nostdlib -m32 gcc -c src/kernel/vga.c -o obj/kvga.o -ffreestanding -nostdlib -m32 - ld obj/kkeyba.o obj/kstub.o obj/kfiles.o obj/kkeybc.o obj/kmain.o \ - obj/kmem.o obj/kproc.o obj/kserial.o obj/kvga.o \ + ld obj/kkeyba.o obj/kserial.o obj/kstub.o obj/kdiskio.o obj/kfiles.o \ + obj/kgpt.o obj/kkeybc.o obj/kmain.o obj/kmem.o obj/kproc.o obj/kvga.o \ -o out/kernel.elf -T src/kernel/link.ld -s --orphan-handling=discard -melf_i386 clean: diff --git a/src/kernel/diskio.c b/src/kernel/diskio.c new file mode 100644 index 0000000..bd08136 --- /dev/null +++ b/src/kernel/diskio.c @@ -0,0 +1,36 @@ +/* +Copyright 2019 Benji Dial + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. +*/ + +#include "diskio.h" + +uint32_t read_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer) { + if ((drive >= 26) || !(drives[drive].flags & DISK_IN)) + return 0; + return 0;//TODO +} + +uint32_t write_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer) { + if ((drive >= 26) || !(drives[drive].flags & DISK_IN)) + return 0; + return 0;//TODO +} + +void update_status(uint8_t drive) { + //TODO +} diff --git a/src/kernel/diskio.h b/src/kernel/diskio.h new file mode 100644 index 0000000..2f83864 --- /dev/null +++ b/src/kernel/diskio.h @@ -0,0 +1,52 @@ +/* +Copyright 2019 Benji Dial + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. +*/ + +#include +#include + +#ifndef DISKIO_H +#define DISKIO_H + +enum interface { + FLOPPY, + IDE, + ATA +}; + +enum drive_flags { + SPUN = 0x01, + DISK_IN = 0x02, + PRESENT = 0x04 +}; + +struct drive_info { + uint8_t interface; + uint8_t number; + uint8_t flags; + uint8_t ssize;//log_2 of B + uint32_t length;//in kiB/2 +}; + +struct drive_info drives[26]; + +uint32_t read_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer); +uint32_t write_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer); +void update_status(uint8_t drive); + +#endif \ No newline at end of file diff --git a/src/kernel/files.c b/src/kernel/files.c index 78fe664..b8a9061 100644 --- a/src/kernel/files.c +++ b/src/kernel/files.c @@ -18,6 +18,23 @@ OF THIS SOFTWARE. */ #include "files.h" +#include "diskio.h" +#include "gpt.h" + +uint8_t working_drive; +uint8_t working_part; +uint8_t buffer[1024]; + +void set_working_drive(uint8_t name, uint8_t part) { + if ((name >= (uint8_t)'a') && (name <= (uint8_t)'z') && + (drives[name - (uint8_t)'a'].flags & PRESENT)) + working_drive = name - (uint8_t)'a'; + if (part_info[working_drive].format & ~DIRECT) + working_part = + (part >= (uint8_t)'0') && (name <= (uint8_t)'9') && + (part_info[working_drive].n_partitions > part) ? + (part & 0x0f) : 0; +} uint16_t open_file(uint8_t *name) { return 0;//TODO @@ -52,4 +69,22 @@ uint32_t read_line_file(uint16_t handle, uint32_t max, void *buffer) { } ++i; } +} + +void detect_disk_parts(uint8_t drive) { + if ((drive >= (uint8_t)'a') && (drive <= (uint8_t)'z')) { + uint8_t dn = (drive & 0x1f) - 1; + update_status(dn); + if (drives[dn].flags & (PRESENT | DISK_IN)) { + read_sectors(dn, 0, 2, buffer); + if ((*(uint32_t *)&buffer[0x200] == 0x20494645) &&//EFI + (*(uint32_t *)&buffer[0x204] == 0x54524150)) //PART + part_info[dn].format = gpt_parse_pt(dn, buffer) ? GPT : UNKNOWN; + ; + } + else { + part_info[dn].format = NOT_PRESENT; + part_info[dn].n_partitions = 0; + } + } } \ No newline at end of file diff --git a/src/kernel/files.h b/src/kernel/files.h index d9102ab..f199306 100644 --- a/src/kernel/files.h +++ b/src/kernel/files.h @@ -29,7 +29,30 @@ struct file_info { uint32_t position; }; +enum fs_format { + ISO9660 +}; + +enum pt_format { + NOT_PRESENT = 0, + UNKNOWN = 1, + DIRECT = 2, + MBR = 3, + GPT = 4 +}; + +struct drive_parts { + uint8_t format; + uint8_t n_partitions; + uint8_t partition_types[10]; + uint32_t partition_offsets[10]; + uint32_t partition_sizes[10]; + void *partition_cache[10]; +}; + +struct drive_parts part_info[26]; struct file_info file_table[65536]; +void set_working_drive(uint8_t drive, uint8_t part); uint16_t open_file(uint8_t *name); void close_file(uint16_t handle); uint32_t read_file(uint16_t handle, uint32_t length, void *buffer); @@ -37,5 +60,6 @@ void write_file(uint16_t handle, uint32_t length, void *buffer); void seek_file(uint16_t handle, int32_t by); uint32_t get_size(uint16_t handle); uint32_t read_line_file(uint16_t handle, uint32_t max, void *buffer); +void detect_disk_parts(uint8_t drive); #endif \ No newline at end of file diff --git a/src/kernel/gpt.c b/src/kernel/gpt.c new file mode 100644 index 0000000..32185eb --- /dev/null +++ b/src/kernel/gpt.c @@ -0,0 +1,40 @@ +/* +Copyright 2019 Benji Dial + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. +*/ + +#include "gpt.h" +#include "files.h" +#include "diskio.h" + +bool gpt_parse_pt(uint8_t dn, uint8_t *buffer) { + struct gpt_header *head = (struct gpt_header *)&buffer[0x200]; + struct drive_parts *pi = part_info + dn; + pi->format = GPT; + pi->n_partitions = (head->n_parts & 0xffffff00 ? 0x000000ff : head->n_parts); + uint32_t part_entry_size = head->part_size; + struct gpt_entry *as_entries = (struct gpt_entry *)buffer; + for (uint8_t i = 0; i < pi->n_partitions; ++i) { + if (!(i % 8)) + read_sectors(dn, 2 + i / 4, 2, buffer); + pi->partition_sizes[i] = ((as_entries[i % 8].last_sector + 1) >> 1) - (pi->partition_offsets[i] = ((as_entries[i % 8].sector) >> 1)); + switch (as_entries[i % 8].id.le) { + //TODO + } + } + return true; +} \ No newline at end of file diff --git a/src/kernel/gpt.h b/src/kernel/gpt.h new file mode 100644 index 0000000..fb872df --- /dev/null +++ b/src/kernel/gpt.h @@ -0,0 +1,69 @@ +/* +Copyright 2019 Benji Dial + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. +*/ + +#include +#include + +#ifndef GPT_H +#define GPT_H + +struct uuid { + uint64_t le; + uint64_t be; +} __attribute__ ((__packed__)); + +struct gpt_header { + uint8_t signature[8]; + uint32_t version; + uint32_t header_length; + uint32_t check;//crc + uint32_t spacing; + uint64_t head_sector; + uint64_t head_backup_sector; + uint64_t data_start; + uint64_t data_last; + struct uuid id; + uint64_t pt_sector; + uint32_t n_parts; + uint32_t part_size; + uint32_t pt_check; +} __attribute__ ((__packed__)); + +struct gpt_entry { + struct uuid type; + struct uuid id; + uint64_t sector; + uint64_t last_sector; + uint64_t flags; + uint8_t name[72]; +} __attribute__ ((__packed__)); + +enum type_le { + GPT_ESP_LE = 0xc12a7328f81f11d2, + GPT_BOOT_LE = 0x2168614864496e6f +}; + +enum type_be { + GPT_ESP_BE = 0x3bc93ec9a0004bba, + GPT_BOOT_BE = 0x4946456465654e74 +}; + +bool gpt_parse_pt(uint8_t dn, uint8_t *buffer); + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index 36257e9..f49d9e6 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -155,7 +155,8 @@ enum error_codes { INSUFF_MEMORY = 0x00000002, MMAP_TOO_SMALL = 0x00000003, MISSING_RC = 0x00000004, - BAD_RC_LINE = 0x00000005 + BAD_RC_LINE = 0x00000005, + BAD_MMAP = 0x00000006 }; struct tag_start *tag_pointer; @@ -172,7 +173,7 @@ uint32_t main(void) { case BOOT_COMMAND: put_sz(": boot arguments\n "); put_sz(*(uint8_t *)(tag_pointer + 1) ? - (uint8_t *)(tag_pointer + 1) : "No arguments"); + (uint8_t *)(tag_pointer + 1) : (uint8_t *)"No arguments"); break; case LOADER_NAME: @@ -219,20 +220,22 @@ uint32_t main(void) { break; case MEMORY_MAP: { + mmap_start = (struct mmap_entry *)0; uint32_t size = *(uint32_t *)(tag_pointer + 1); struct mmap_tag_entry *tag = (struct mmap_tag_entry *)(tag_pointer + 2); struct mmap_tag_entry *end = (struct mmap_tag_entry *)((uint32_t)tag_pointer + tag_pointer->size); struct mmap_entry *entry = mmap_bss; uint32_t bitmask = 0x00000001; uint32_t byte = 0; - struct mmap_entry **last_next = &mmap_start; uint32_t usable = 0; put_sz(": memory map\n Regions:\n"); while (tag != end) { - if (!(tag->base & 0xffffffff00000000)) { + if (!(tag->base & 0xffffffff00000000) && tag->length) { entry->base = (uint32_t)tag->base; entry->length = (tag->base + tag->length - 1) & 0xffffffff00000000 ? 1 + ~(uint32_t)tag->base : (uint32_t)tag->length; + if (!entry->base) + mmap_start = entry; put_sz(" 0x"); put_32_hex(entry->base); put_sz(" - 0x"); @@ -263,8 +266,6 @@ uint32_t main(void) { entry->whose = HARDWARE; break; } - *last_next = entry; - last_next = &entry->next; mmap_bitmap[byte] |= bitmask; ++entry; if (!(bitmask <<= 1)) { @@ -279,28 +280,24 @@ uint32_t main(void) { put_sz(" Total usable memory: 0x"); put_32_hex(usable); - bool dirty; - do { - dirty = false; - for (struct mmap_entry *current = mmap_start; current; current = current->next) - for (struct mmap_entry *against = mmap_start; against; against = against->next) - if ((current->base + current->length == against->base) && - (current->whose == against->whose)) { - current->length += against->length; - unmark_entry(against); - if (against == mmap_start) - mmap_start = against->next; - else { - for (current = mmap_start; current->next != against; current = current->next) - ; - current->next = against->next; - } - dirty = true; - } - } while (dirty); - - have_mmap = true; - break; + for (struct mmap_entry *b = mmap_bss; b < entry; ++b) + for (struct mmap_entry *a = mmap_bss; a < entry; ++a) + if (b->base + b->length == a->base) + (b->after = a)->before = b; + + for (struct mmap_entry *p = mmap_start; p->after; p = p->after) + while (p->whose == p->after->whose) { + p->length += p->after->whose; + unmark_entry(p->after); + if (p->after = p->after->after) + p->after->before = p; + } + + if (mmap_start) { + have_mmap = true; + break; + } + return BAD_MMAP; } case VBE_INFO: { @@ -408,26 +405,33 @@ uint32_t main(void) { if (!have_mmap) return NO_MMAP; - put_sz("\n\nImportant locations:"); + put_sz("\n\nInfo:"); if (have_text_base) { - put_sz("\n Text section: 0x"); + put_sz("\n Text section: 0x"); put_32_hex(text_base); } - put_sz("\n Memory map: 0x"); - put_32_hex((uint32_t)mmap_bss); - put_sz(" - 0x"); - put_32_hex((uint32_t)mmap_bss - 1 + - sizeof(struct mmap_entry) * MMAP_SIZE); - put_sz("\n Process table: 0x"); - put_32_hex((uint32_t)proc_table); - put_sz(" - 0x"); - put_32_hex((uint32_t)proc_table - 1 + - sizeof(struct proc_info) * 65536); - put_sz("\n File table: 0x"); - put_32_hex((uint32_t)file_table); - put_sz(" - 0x"); - put_32_hex((uint32_t)file_table - 1 + - sizeof(struct file_info) * 65536); + put_sz("\n Memory map size: 0x"); + put_32_hex(sizeof(struct mmap_entry) * MMAP_SIZE); + put_sz("\n Process table size: 0x"); + put_32_hex(sizeof(struct proc_info) * 65536); + put_sz("\n File table size: 0x"); + put_32_hex(sizeof(struct file_info) * 65536); + put_sz("\n\nDisks:"); + + for (uint8_t i = 0; i < 26; ++i) { + detect_disk_parts((uint8_t)'a' + i); + if (part_info[i].format) { + put_sz("\n "); + put_char((uint8_t)'a' + i); + if (part_info[i].n_partitions) { + put_char('0'); + uint8_t str[] = "\n 1"; + for (uint8_t m = part_info[i].n_partitions + (uint8_t)'0'; str[4] < m; ++(str[4])) + put_sz(str); + } + } + } + put_sz("\n\n"); put_sz("No file support yet. Halting."); diff --git a/src/kernel/mem.c b/src/kernel/mem.c index 99586d9..d9322a9 100644 --- a/src/kernel/mem.c +++ b/src/kernel/mem.c @@ -23,75 +23,66 @@ uint32_t last_byte = 0; uint32_t last_mask = 0x00000001; void *allocate_block(uint32_t size, uint16_t proc_n) { - struct mmap_entry *i = mmap_start; - while (i->whose || (i->length < size)) - if (i->next) - i = i->next; - else - return (void *)0; - if (i->length == size) { - i->whose = proc_n; - return (void *)i->base; - } - uint32_t remaining = i->length - size; - i->whose = proc_n; - i->length = size; - - uint32_t byte = last_byte; - uint32_t mask = last_mask; - do { - if (!(mask <<= 1)) { - mask = 0x00000001; - if (++byte == MMAP_SIZE) - byte = 0; + for (struct mmap_entry *find = mmap_start; find; find = find->after) + if (!find->whose) { + if (find->length == size) { + find->whose = proc_n; + return (void *)find->base; + } + else if (find->length > size) { + uint32_t byte = last_byte; + uint32_t mask = last_mask; + while (mmap_bitmap[byte] & mask) { + if ((byte == last_byte) && (mask == last_mask)) { + while (find = find->after) + if (find->length == size) { + find->whose = proc_n; + return (void *)find->base; + } + return (void *)0; + } + if (!(mask <<= 1)) { + mask = 0x00000001; + if (++byte == MMAP_SIZE) + byte = 0; + } + } + mmap_bitmap[last_byte = byte] |= last_mask = mask; + struct mmap_entry *new = mmap_bss + (byte << 5); + while (mask >>= 1) + ++new; + ((((new->after = find->after)->before = new)->before = find)->after = new)->base = find->base + size; + new->length = find->length - size; + find->length = size; + find->whose = proc_n; + new->whose = FREE; + return (void *)find->base; + } } - if ((byte == last_byte) && (mask == last_mask)) - return 0; - } while (mmap_bitmap[byte] & mask); - last_byte = byte; - last_mask = mask; - mmap_bitmap[byte] |= mask; - uint8_t bit = 0; - while (!(mask & 0x00000001)) { - ++bit; - mask >>= 1; - } - - struct mmap_entry *new = mmap_bss + (byte << 5) + bit; - new->base = i->base + size; - new->length = remaining; - new->whose = FREE; - new->next = i->next; - i->next = new; - return (void *)i->base; + return (void *)0; } void deallocate_block(void *start) { struct mmap_entry *find = mmap_start; while (find->base != (uint32_t)start) - if (find->next) - find = find->next; + if (find->after) + find = find->after; else return; find->whose = FREE; - - for (struct mmap_entry *find_after = mmap_start; find_after; find_after = find_after->next) - if (find_after->base == find->base + find->length) { - if (!find_after->whose) { - find->length += find_after->length; - find->next = find_after->next; - unmark_entry(find_after); - } - break; - } - - for (struct mmap_entry *find_before = mmap_start; find_before; find_before = find_before->next) - if (find->base == find_before->base + find_before->length) { - if (!find_before->whose) { - find_before->length += find->length; - find_before->next = find->next; - unmark_entry(find); - } - break; - } + while (find->before && !find->before->whose) { + find->before->length += find->length; + if (find->before->after = find->after) + find->after->before = find->before; + unmark_entry(find); + find = find->before; + } + if (!find->before) + mmap_start = find; + while (find->after && !find->after->whose) { + find->length += find->after->length; + unmark_entry(find->after); + if (find->after = find->after->after) + find->after->before = find; + } } \ No newline at end of file diff --git a/src/kernel/mem.h b/src/kernel/mem.h index 5c0d387..4a35978 100644 --- a/src/kernel/mem.h +++ b/src/kernel/mem.h @@ -32,14 +32,15 @@ struct mmap_entry { uint32_t base; uint32_t length; uint16_t whose; - struct mmap_entry *next; + struct mmap_entry *after; + struct mmap_entry *before; }; #define MMAP_SIZE 65536 struct mmap_entry *mmap_start; struct mmap_entry mmap_bss[MMAP_SIZE]; uint32_t mmap_bitmap[MMAP_SIZE / 32]; -#define unmark_entry(entry) mmap_bitmap[((entry) - mmap_bss) >> 5] ^= 1 << (((entry) - mmap_bss) & 0x0000001f); +#define unmark_entry(entry) (mmap_bitmap[((entry) - mmap_bss) >> 5] ^= 1 << (((entry) - mmap_bss) & 0x0000001f)) void *allocate_block(uint32_t size, uint16_t proc_n); void deallocate_block(void *start); -- cgit v1.2.3