diff --git a/.gitignore b/.gitignore index c2f7ee5..fc207a3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ limine-bootloader/ include_cp *.elf qemu.log +lai/ diff --git a/Makefile b/Makefile index e5d3c0f..1e9d950 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ USED_LOOPBACK := /dev/loop2 LIMINE_INSTALL := ./limine-bootloader/limine-install-linux-x86_64 -QEMU_PATH := qemu-system-x86_64 +QEMU_PATH := qemu-system-x86_64 -accel kvm QEMU_ARGS := -monitor stdio \ -bios /usr/share/ovmf/OVMF.fd \ @@ -19,7 +19,8 @@ QEMU_ARGS := -monitor stdio \ -vga virtio \ -no-reboot \ -D qemu.log \ - -drive format=raw,file= + -device nvme,drive=NVME1,serial=nvme-1 \ + -drive format=raw,if=none,id=NVME1,file= # -usb \ # -device usb-host \ diff --git a/kernel/Makefile b/kernel/Makefile index 0fc0f88..8fc99a5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,25 +7,30 @@ CFLAGS = -Wall -Wextra -O3 -pipe INTERNALLDFLAGS := -Tlinker.ld \ -nostdlib \ - -Wl,--export-dynamic \ + -Wl,--export-dynamic \ -zmax-page-size=0x1000 \ -static \ -pie \ -ztext # ,--dynamic-linker -INTERNALCFLAGS := -mgeneral-regs-only \ - -ffreestanding \ - -mno-red-zone \ - -mno-80387 \ - -fno-omit-frame-pointer \ - -std=gnu11 \ - -Wall -Wextra \ +INTERNALCFLAGS := -mgeneral-regs-only \ + -ffreestanding \ + -mno-red-zone \ + -mno-80387 \ + -fno-omit-frame-pointer\ + -std=gnu11 \ + -Wall -Wextra \ -fcompare-debug-second \ -I/opt/cross/include/ \ + -I../lai/include \ -fpie \ -# -D BIGGER_FONT - + -D BIGGER_FONT + + +LAI_FILE := ../lai/lai.elf + + CFILES := $(shell find ./ -type f -name '*.c') SFILES := $(shell find ./ -type f -name '*.s') OBJ := $(SFILES:.s=.s.o) $(CFILES:.c=.c.o) @@ -39,9 +44,10 @@ all: $(KERNEL) + $(KERNEL): $(OBJ) $(LDSCRIPT) - $(CC) $(INTERNALLDFLAGS) $(OBJ) -o $@ + $(CC) $(INTERNALLDFLAGS) $(OBJ) $(LAI_FILE) -o $@ %.c.o: %.c diff --git a/kernel/acpi/acpi.c b/kernel/acpi/acpi.c index 523498f..722651b 100644 --- a/kernel/acpi/acpi.c +++ b/kernel/acpi/acpi.c @@ -2,6 +2,7 @@ #include #include + #include "acpi.h" #include "../lib/common.h" #include "../lib/assert.h" @@ -20,6 +21,8 @@ static void* apic_config_base, *hpet_config_space; // defined in pcie.c extern struct PCIE_Descriptor pcie_descriptor; +static const struct XSDT* xsdt; + static bool __ATTR_PURE__ checksum(const void* table, size_t size) { uint8_t sum = 0; @@ -36,11 +39,14 @@ static void parse_hpet(const struct HPET* table); static void parse_fadt(const struct ACPISDTHeader* table); static void parse_pcie(const struct PCIETable* table); +const struct XSDT* get_xsdt_location(void) { + return xsdt; +} + void read_acpi_tables(const void* rsdp_location) { const struct RSDPDescriptor20* rsdpd = rsdp_location; - assert(rsdpd->firstPart.revision >= 2); // checksum for xsdt @@ -49,7 +55,7 @@ void read_acpi_tables(const void* rsdp_location) { // lets parse it!! - const struct XSDT* xsdt = (void *)rsdpd->xsdtAddress; + xsdt = (void *)rsdpd->xsdtAddress; size_t n_entries = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(void*); @@ -141,7 +147,6 @@ static void parse_madt(const struct MADT* table) { break; case APIC_TYPE_IO_INTERRUPT_SOURCE_OVERRIDE: { - log_debug("ISSOU"); // const struct MADT_ioapic_interrupt_source_override_entry* entry = ptr; } break; @@ -180,7 +185,7 @@ static void parse_madt(const struct MADT* table) { static void parse_pcie(const struct PCIETable* table) { // fill the pcie driver's descriptor - size_t size = (table->header.length-sizeof(table->header)); + size_t size = (table->header.length-sizeof(struct ACPISDTHeader)-8); pcie_descriptor.size = size / sizeof(struct PCIE_segment_group_descriptor); diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h index 03e053b..dbf6f3a 100644 --- a/kernel/acpi/acpi.h +++ b/kernel/acpi/acpi.h @@ -5,5 +5,6 @@ read RSDP, XSDP, MADT, FADT */ void read_acpi_tables(const void* rsdp_location); +const struct XSDT* get_xsdt_location(void); -void map_acpi_mmios(void); +void map_acpi_mmios(void); \ No newline at end of file diff --git a/kernel/acpi/lai.c b/kernel/acpi/lai.c new file mode 100644 index 0000000..85c5a8e --- /dev/null +++ b/kernel/acpi/lai.c @@ -0,0 +1,71 @@ +#include +// this file impelments the functions needed +// by the LAI library + +#include "../lib/panic.h" +#include "../lib/logging.h" +#include "../memory/heap.h" +#include "acpitables.h" + +// OS-specific functions. +void *laihost_malloc(size_t s) { + return malloc(s); +} +void *laihost_realloc(void* p, size_t s) { + return realloc(p, s); +} +void laihost_free(void* p) { + free(p); +} + +void laihost_log(int level, const char * msg) { + if(level == LAI_DEBUG_LOG) + log_debug("LAI: %s", msg); + else + log_warn ("LAI: %s", msg); +} +void laihost_panic(const char* msg) { + char buff[1024]; + sprintf(buff, "LAI: %s", msg); + panic(buff); +} + + +// only called early: +void *laihost_scan(char * name, size_t c) { + const struct XSDT* xsdt = get_xsdt_location(); + + size_t n_entries = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(void*); + + const uint32_t* raw = (uint32_t*)name; + + for(size_t i = 0; i < n_entries; i++) { + const struct ACPISDTHeader* table = xsdt->entries[i]; + + if(*raw == table->signature.raw) + return table; + } + +// no such table + return NULL; +} + +void *laihost_map(size_t, size_t); +void laihost_outb(uint16_t, uint8_t); +void laihost_outw(uint16_t, uint16_t); +void laihost_outd(uint16_t, uint32_t); +uint8_t laihost_inb(uint16_t); +uint16_t laihost_inw(uint16_t); +uint32_t laihost_ind(uint16_t); + +void laihost_pci_writeb(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint8_t); +uint8_t laihost_pci_readb(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t); +void laihost_pci_writew(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t); +uint16_t laihost_pci_readw(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t); +void laihost_pci_writed(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint32_t); +uint32_t laihost_pci_readd(uint16_t, uint8_t, uint8_t, uint8_t, uint16_t); + +void laihost_sleep(uint64_t); + +void laihost_handle_amldebug(lai_variable_t *); + diff --git a/kernel/drivers/nvme.h b/kernel/drivers/nvme.h new file mode 100644 index 0000000..3f59c93 --- /dev/null +++ b/kernel/drivers/nvme.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/kernel/drivers/pcie.c b/kernel/drivers/pcie.c index b4d974a..5766e19 100644 --- a/kernel/drivers/pcie.c +++ b/kernel/drivers/pcie.c @@ -12,7 +12,10 @@ struct PCIE_configuration_space { volatile uint16_t deviceID; uint16_t unused0; uint16_t unused1; - volatile uint32_t class_code_revID; + volatile uint8_t revID; + volatile uint8_t progIF; + volatile uint8_t subclasscode; + volatile uint8_t classcode; volatile uint32_t infos; volatile uint64_t bar[3]; volatile uint32_t cardbud_cis_ptr; @@ -71,10 +74,10 @@ static struct PCIE_configuration_space* __attribute__((pure)) get_config_space_b } -static int __attribute__((pure)) check_function(unsigned bus, unsigned device, unsigned func) { +static int __attribute__((pure)) get_vendorID(unsigned bus, unsigned device, unsigned func) { struct PCIE_configuration_space* config_space = get_config_space_base(bus,device,func); - return config_space->vendorID != 0xffff; + return config_space->vendorID; } @@ -84,12 +87,12 @@ struct pcie_device_descriptor { }; // array of all installed devices' functions -static struct pcie_device_descriptor* installed_devices = NULL; -static size_t n_installed_devices = 0; +static struct pcie_device_descriptor* found_devices = NULL; +static size_t n_found_devices = 0; /** - * constructs the installed_devices array + * constructs the found_devices array */ static void scan_devices(void) { @@ -106,17 +109,13 @@ static void scan_devices(void) { // count the number of devices void insert( - unsigned bus, - unsigned device, - unsigned func, - struct PCIE_configuration_space* config_space - ) { - - current->next = malloc( - sizeof(struct device_desc_node) - ); - - log_debug("device %u:%u - %u", bus, device, func); + unsigned bus, + unsigned device, + unsigned func, + struct PCIE_configuration_space* config_space + ) + { + current->next = malloc(sizeof(struct device_desc_node)); current = current->next; current->next = NULL; @@ -127,7 +126,7 @@ static void scan_devices(void) { current->e.function = func; current->e.config_space = config_space; - n_installed_devices++; + n_found_devices++; } @@ -136,27 +135,39 @@ static void scan_devices(void) { // if the first function doesn't exist, so does // the device - if(!check_function(bus,device, 0)) + uint16_t vendorID = get_vendorID(bus,device, 0); + if(vendorID == 0xFFFF) continue; - insert(bus, device, 0, get_config_space_base(bus,device,0)); + insert(bus, + device, + 0, + get_config_space_base(bus,device,0) + ); - for(unsigned func = 1; func < 8; func++) - if(check_function(bus,device, func)) - insert(bus, device, func, get_config_space_base(bus,device,func)); - + for(unsigned func = 1; func < 8; func++) { + + if(get_vendorID(bus,device, func) != vendorID) + continue; + + insert(bus, + device, + func, + get_config_space_base(bus,device,func) + ); + } } } // now create the final array - installed_devices = malloc( - n_installed_devices + found_devices = malloc( + n_found_devices * sizeof(struct pcie_device_descriptor)); // now fill it and free the devices structure - struct pcie_device_descriptor* ptr = installed_devices; + struct pcie_device_descriptor* ptr = found_devices; for(struct device_desc_node* device = ghost_node.next; device != NULL; @@ -189,7 +200,7 @@ static void identity_map_possible_config_spaces(void) { static void identity_unmap_possible_config_spaces(void) { for(unsigned i = 0; i < pcie_descriptor.size; i++) - ;// unmap_pages((uint64_t)pcie_descriptor.array[i].address, 256 * 32 * 8); + unmap_pages((uint64_t)pcie_descriptor.array[i].address, 256 * 32 * 8); } /** @@ -209,13 +220,33 @@ void pcie_init(void) { max_bus = pcie_descriptor.array[i].end_bus; } + log_debug("%u PCIE bus groups found", pcie_descriptor.size); + identity_map_possible_config_spaces(); - scan_devices(); - identity_unmap_possible_config_spaces(); + for(unsigned i = 0; i < n_found_devices; i++) { + + log_warn("%2x:%2x:%2x: %2x:%2x:%2x, rev %2x, " + "vendor 0x%4x", + + found_devices[i].bus, + found_devices[i].device, + found_devices[i].function, + + found_devices[i].config_space->classcode, + found_devices[i].config_space->subclasscode, + found_devices[i].config_space->progIF, + found_devices[i].config_space->revID, + + found_devices[i].config_space->vendorID + ); + } + identity_unmap_possible_config_spaces(); + log_info("found %u PCI Express devices", n_found_devices); +} - log_info("found %u PCI Express devices", n_installed_devices); +void pcie_init_devices(void) { } \ No newline at end of file diff --git a/kernel/drivers/pcie.h b/kernel/drivers/pcie.h index 2a8fcd5..bbf181f 100644 --- a/kernel/drivers/pcie.h +++ b/kernel/drivers/pcie.h @@ -2,6 +2,7 @@ #include #include +#include "../lib/assert.h" struct PCIE_segment_group_descriptor { void* address; // Base address @@ -12,7 +13,9 @@ struct PCIE_segment_group_descriptor { uint8_t end_bus; // End PCI bus number // decoded by this host bridge uint32_t reserved; -}; +} __attribute__((packed)); + +static_assert(sizeof(struct PCIE_segment_group_descriptor) == 16); #define PCIE_SUPPORTED_SEGMENT_GROUPS 2 @@ -29,6 +32,8 @@ extern struct PCIE_Descriptor pcie_descriptor; void pcie_init(void); void pcie_scan(void); +void pcie_init_devices(void); + typedef void (*driver_init_fun)(void* config_space); diff --git a/kernel/drivers/terminal/terminal.c b/kernel/drivers/terminal/terminal.c index a7d364e..b1517bb 100644 --- a/kernel/drivers/terminal/terminal.c +++ b/kernel/drivers/terminal/terminal.c @@ -73,19 +73,19 @@ static unsigned timerID = INVALID_TIMER_ID; -static char* stream_buffer = NULL; +//static char* stream_buffer = NULL; -static unsigned stream_buffer_size = 0; -static volatile unsigned stream_buffer_content_size = 0; +//static unsigned stream_buffer_size = 0; +//static volatile unsigned stream_buffer_content_size = 0; // should be called every UPDATE_PERIOD ms // should execute in an IRQ void terminal_update(void) { + return; static unsigned update_cur_line = 0; - stream_buffer_content_size = 0; if(need_refresh) { @@ -137,7 +137,7 @@ void terminal_install_early(void) { margin_top = (screenImage->h - term_nlines * TERMINAL_FONTHEIGHT) / 2; #endif - stream_buffer = malloc(ncols * term_nlines); +// stream_buffer = NULL;//malloc(ncols * term_nlines); set_terminal_handler(empty_terminal_handler); } @@ -145,7 +145,7 @@ void terminal_install_early(void) { // finish intallation when memory // is well initialized void terminal_install_late(void) { - timerID = apic_create_timer(terminal_update, UPDATE_PERIOD_MS); + //timerID = apic_create_timer(terminal_update, UPDATE_PERIOD_MS); charmap = loadBMP_24b_1b(&_binary_charmap_bmp); @@ -231,6 +231,7 @@ static void emplace_normal_char(char c) { char_buffer[ncols * cur_line + cur_col] = make_Char(c); struct Char* ch = &char_buffer[ncols * cur_line + cur_col]; + cur_col += 1; if(cur_col >= ncols) @@ -240,7 +241,6 @@ static void emplace_normal_char(char c) { print_char(ch, cur_line - first_line, cur_col); - cur_col += 1; } @@ -321,10 +321,6 @@ static void print_char(const struct Char* restrict c, int line, int col) { margin_top + line * TERMINAL_LINE_HEIGHT); #endif - //imageDraw(charmap, NULL, NULL); - - //imageFillRect(c->bg_color, &interlineRect); - } static void flush_screen(void) { @@ -339,7 +335,7 @@ static void flush_screen(void) { } - +/* // add the string to the buffer static void append_string(const char *string, size_t length) { // atomic operation @@ -353,11 +349,11 @@ static void append_string(const char *string, size_t length) { _sti(); } - +*/ static void write_string(const char *string, size_t length) { - //need_refresh = false; + need_refresh = false; for(;length>0;--length) { char c = *string++; @@ -367,8 +363,8 @@ static void write_string(const char *string, size_t length) { emplace_char(c); } - //if(need_refresh) - // flush_screen(); + if(need_refresh) + flush_screen(); } diff --git a/kernel/entry.c b/kernel/entry.c index 7793f18..4cdb27f 100644 --- a/kernel/entry.c +++ b/kernel/entry.c @@ -6,6 +6,7 @@ #include "drivers/terminal/video.h" #include "drivers/terminal/terminal.h" #include "acpi/acpi.h" +#include "acpi/power.h" #include "int/apic.h" #include "int/idt.h" #include "int/pic.h" @@ -193,22 +194,25 @@ void _start(struct stivale2_struct *stivale2_struct) { puts(&_binary_bootmessage_txt); + + asm volatile("hlt"); printf("boot logs:\n"); puts(log_get()); log_flush(); - dump(boot_volume_tag, sizeof(struct stivale2_struct_tag_boot_volume), 8, DUMP_HEX8); - //log_info("boot volume: %x:%x:%x:%lx", - // boot_volume_tag->guid.a, - // boot_volume_tag->guid.b, - // boot_volume_tag->guid.c, - // *(uint64_t*)boot_volume_tag->guid.d); -// - //pcie_init(); + pcie_init(); + pcie_init_devices(); pic_init(); ps2kb_init(); + void kbhandler(const struct kbevent* ev) { + if(ev->type == KEYRELEASED && ev->scancode == PS2KB_ESCAPE) { + shutdown(); + } + }; + ps2kb_set_event_callback(kbhandler); + hpet_init(); apic_setup_clock(); diff --git a/kernel/memory/heap.c b/kernel/memory/heap.c index 3611785..7a1d5e3 100644 --- a/kernel/memory/heap.c +++ b/kernel/memory/heap.c @@ -257,7 +257,7 @@ void heap_init(void) { } -void* malloc(size_t size) { +void* __attribute__((noinline)) malloc(size_t size) { // align the size to assure that // the whole structure is alligned size = ((size + 7 ) / 8) * 8; @@ -274,7 +274,9 @@ void* malloc(size_t size) { break; } - else if(!seg->free || seg->size < size) { + assert(is_kernel_memory(seg)); + + if(!seg->free || seg->size < size) { // this segment is not right, check the next one pred = seg; @@ -287,7 +289,6 @@ void* malloc(size_t size) { } // we found a satisfying segment! - if(seg->size >= size + sizeof(seg_header) + MIN_SEGMENT_SIZE) { // we don't take the whole space @@ -323,7 +324,6 @@ void* malloc(size_t size) { // let's expand expand_heap(MAX(size+sizeof(seg_header), MIN_EXPAND_SIZE)); - // retrty now that we are sure that the memory is avaiable return malloc(size); } @@ -391,7 +391,7 @@ void* realloc(void* ptr, size_t size) { // O(1) free -void free(void *ptr) { +void __attribute__((noinline)) free(void *ptr) { seg_header* header = ptr - sizeof(seg_header); assert(header->free == 0); @@ -407,17 +407,27 @@ void free(void *ptr) { #ifndef NDEBUG + +void print_heap(void) { + for(seg_header* seg = current_segment; + seg != NULL; + seg = seg->next) { + log_debug("%lx size=%x,free=%u", seg,seg->size, seg->free); + } +} + void malloc_test(void) { + void* arr[128]; uint64_t size = 5; - + for(int j = 0; j < 100; j++) { for(int i = 0; i < 128; i++) { arr[i] = malloc(size % 1024); - size = (16807 * size) % ((1lu << 31) - 1); } + for(int i = 0; i < 128; i++) free(arr[i]); } diff --git a/lai b/lai new file mode 160000 index 0000000..bef3f0c --- /dev/null +++ b/lai @@ -0,0 +1 @@ +Subproject commit bef3f0c6b2f72f82f573440bfdf73ebf7fc7b141