diff --git a/.gitignore b/.gitignore index 5ab2831..74c5a08 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .vscode disk.hdd img_moint -limine-bootloader +limine-bootloader/ *.o include_cp *.elf \ No newline at end of file diff --git a/Makefile b/Makefile index 5c8c99e..63ba963 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,17 @@ HDD_ROOT := disc_root HDD_FILE := disk.hdd - + USED_LOOPBACK := /dev/loop6 +LIMINE_INSTALL := ./limine-bootloader/limine-install-linux-x86_64 + QEMU_PATH := "/mnt/d/Program Files/qemu/qemu-system-x86_64.exe" -QEMU_ARGS := -monitor stdio -d cpu_reset -bios "d:/Program Files/qemu/bios/OVMF.fd" +QEMU_ARGS := -monitor stdio -bios "d:/Program Files/qemu/bios/OVMF.fd" -m 256 -vga std -no-reboot +# -bios "d:/Program Files/qemu/bios/OVMF.fd" run: all - $(QEMU_PATH) $(QEMU_ARGS) $(HDD_FILE) + $(QEMU_PATH) $(QEMU_ARGS) -drive format=raw,file=$(HDD_FILE) all: disk @@ -22,7 +25,7 @@ $(HDD_FILE): kernel/entry.c sudo /sbin/parted -s $(HDD_FILE) mklabel gpt sudo /sbin/parted -s $(HDD_FILE) mkpart ESP fat32 2048s 100% sudo /sbin/parted -s $(HDD_FILE) set 1 esp on - ./limine-bootloader/limine-install $(HDD_FILE) + $(LIMINE_INSTALL) $(HDD_FILE) disk: kernel $(HDD_FILE) diff --git a/disk_root/EFI/BOOT/BOOTX64.EFI b/disk_root/EFI/BOOT/BOOTX64.EFI index 0968782..e61f344 100644 Binary files a/disk_root/EFI/BOOT/BOOTX64.EFI and b/disk_root/EFI/BOOT/BOOTX64.EFI differ diff --git a/disk_root/boot/limine.cfg b/disk_root/boot/limine.cfg index 7eb55bd..1f3fd49 100644 --- a/disk_root/boot/limine.cfg +++ b/disk_root/boot/limine.cfg @@ -2,20 +2,29 @@ DEFAULT_ENTRY=1 #TIMEOUT=10 #GRAPHICS=yes #VERBOSE=yes -TIMEOUT=0 +TIMEOUT=10 GRAPHICS=no VERBOSE=no THEME_MARGIN=64 -#RESOLUTION=800x600 +RESOLUTION=800x600 #BACKGROUND_PATH=boot:///boot/bg.bmp #THEME_BACKGROUND=8f000000 BACKGROUND_STYLE=centered -:Stivale2 Test +:Bincows PROTOCOL=stivale2 -#RESOLUTION=800x600 +#RESOLUTION=960x540 #BACKGROUND_PATH=boot:///boot/bg.bmp KERNEL_PATH=boot:///boot/kernel.elf -BACKGROUND_STYLE=centered \ No newline at end of file +BACKGROUND_STYLE=centered + + + +:Lucarnel + +PROTOCOL=stivale +#RESOLUTION=800x600 +#BACKGROUND_PATH=boot:///boot/bg.bmp +KERNEL_PATH=boot:///boot/lucarnel.elf \ No newline at end of file diff --git a/disk_root/boot/limine.sys b/disk_root/boot/limine.sys index 50973d4..95e2b52 100644 Binary files a/disk_root/boot/limine.sys and b/disk_root/boot/limine.sys differ diff --git a/kernel/Makefile b/kernel/Makefile index 5c0b7be..a20be39 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -4,34 +4,31 @@ ASM := nasm ASM_FLAGS := -felf64 CFLAGS = -Wall -Wextra -O3 -pipe - -INTERNALLDFLAGS := \ - -fno-pic \ - -Wl,-static,--no-dynamic-linker,-ztext \ - -znocombreloc \ - -nostdlib \ - -Tlinker.ld \ - -z max-page-size=0x1000 - -INTERNALCFLAGS := \ - -znocombreloc \ - -I/opt/cross/include/ \ - -std=gnu11 \ - -ffreestanding \ - -fno-stack-protector \ - -fno-pic \ - -mno-80387 \ - -mno-mmx \ - -mno-3dnow \ - -mno-sse \ - -mno-sse2 \ - -mno-red-zone \ - -m64 +INTERNALLDFLAGS := -Tlinker.ld \ + -nostdlib \ + -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 \ + -fcompare-debug-second \ + -I/opt/cross/include/ \ + -fpie CFILES := $(shell find ./ -type f -name '*.c') SFILES := $(shell find ./ -type f -name '*.s') -OBJ := $(SFILES:.s=.s.o) $(CFILES:.c=.c.o) charmap.bmp.o +OBJ := $(SFILES:.s=.s.o) $(CFILES:.c=.c.o) +#charmap.bmp.o .PHONY: all clean all: $(KERNEL) @@ -41,10 +38,10 @@ all: $(KERNEL) $(KERNEL): $(OBJ) $(CC) $(INTERNALLDFLAGS) $(OBJ) -o $@ -%.bmp.o: ../resources/bmp/%.bmp - $(LD) -r -b binary -o $@ $< -%.txt.o: ../resources/ascii/%.txt - $(LD) -r -b binary -o $@ $< +#%.bmp.o: ../resources/bmp/%.bmp +# $(LD) -r -b binary -o $@ $< +#%.txt.o: ../resources/ascii/%.txt +# $(LD) -r -b binary -o $@ $< %.c.o: %.c $(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@ diff --git a/kernel/acpi/acpi.c b/kernel/acpi/acpi.c index 76f504d..168f0df 100644 --- a/kernel/acpi/acpi.c +++ b/kernel/acpi/acpi.c @@ -1,55 +1,153 @@ -#include -#include -#include - -#include "acpi.h" -#include "../common.h" -#include "../debug/assert.h" -#include "../debug/dump.h" -#include "../klib/sprintf.h" -#include "acpitables.h" - - - -bool checksum(void* table, size_t size) { - uint8_t sum = 0; - uint8_t* raw = table; - - for(size_t i;size > 0; --size) { - sum += raw[i++]; - } - return sum == 0; -} - - -typedef uint64_t rsdp_entry_t; - - - -void read_acpi_tables(void* rsdp_location) { - struct RSDPDescriptor20* rsdpd = rsdp_location; - - - dump(rsdpd, sizeof(struct RSDPDescriptor20), 8, DUMP_HEX8); - - assert(rsdpd->firstPart.revision >= 2); - - // checksum for xsdt - assert(rsdpd->length == sizeof(rsdpd)); - assert(checksum(rsdpd, rsdpd->length)); - - - // lets parse it!! - const struct ACPISDTHeader* xsdt = (void *)rsdpd->xsdtAddress; - - size_t n_entries = (xsdt->length - sizeof(xsdt)) / sizeof(rsdp_entry_t); - - rsdp_entry_t* table = (xsdt + 1); - - for(int i = 0; i < n_entries; i++) { - - - kprintf("%3u: %s\n", table[i]) - //table[i] - } -} +#include +#include +#include + +#include "acpi.h" +#include "../common.h" +#include "../debug/assert.h" +#include "../debug/dump.h" +#include "../klib/sprintf.h" +#include "../klib/string.h" +#include "acpitables.h" +#include "../int/apic.h" + + +extern struct APICConfig* apic_config; + +static bool __ATTR_PURE__ checksum(const void* table, size_t size) { + uint8_t sum = 0; + const uint8_t* raw = table; + + for(size_t i;size > 0; --size) { + sum += raw[i++]; + } + return sum == 0; +} + +static void parse_madt(const struct MADT* table); +static void parse_fadt(const struct ACPISDTHeader* table); + + +#define MADT_SIGNATURE 0x43495041 +#define FACP_SIGNATURE 0x50434146 + +void read_acpi_tables(const void* rsdp_location) { + const struct RSDPDescriptor20* rsdpd = rsdp_location; + + + assert(rsdpd->firstPart.revision >= 2); + + // checksum for xsdt + assert(rsdpd->length == sizeof(struct RSDPDescriptor20)); + assert(checksum(rsdpd, rsdpd->length)); + + + // lets parse it!! + const struct XSDT* xsdt = (void *)rsdpd->xsdtAddress; + + + size_t n_entries = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(void*); + + + bool madt_parsed = false, + fadt_parsed = false; + + for(size_t i = 0; i < n_entries; i++) { + const struct ACPISDTHeader* table = xsdt->entries[i]; + assert(checksum(&table, table->length)); + + switch(table->signature.raw) { + case MADT_SIGNATURE: + parse_madt((const struct MADT *)table); + madt_parsed = true; + break; + case FACP_SIGNATURE: + parse_fadt(table); + fadt_parsed = true; + break; + default: + break; + } + kprintf("%3u: %4s\n", i, table->signature.arg); + } + + asm volatile("hlt"); + assert(madt_parsed); + assert(fadt_parsed); +} + +static void parse_madt(const struct MADT* table) { + // checksum is already done + + apic_config = (void*)(uint64_t)table->lAPIC_address; + const void* ptr = table->entries; + const void* end = (const void*)table + table->header.length; + +/// dont override the override lapic or io apic entry + bool override_lapic_passed = false; + bool override_ioapic_passed = false; + (void)override_lapic_passed; + (void)override_ioapic_passed; + + + kprintf("table size: %u\n", end-ptr); + while(ptr < end) { + //for(int i = 10; i>0; i--) { + const struct MADTEntryHeader* entry_header = ptr; + + + + switch(entry_header->type) { + case APIC_TYPE_LAPIC: + { + // const struct MADT_lapic_entry* entry = ptr; + + } + break; + case APIC_TYPE_IO_APIC: + { + // const struct MADT_ioapic_entry* entry = ptr; + } + break; + case APIC_TYPE_IO_INTERRUPT_SOURCE_OVERRIDE: + { + // const struct MADT_ioapic_interrupt_source_override_entry* entry = ptr; + } + break; + case APIC_TYPE_IO_NMI: + { + // const struct MADT_IO_NMI_entry* entry = ptr; + } + break; + case APIC_TYPE_LOCAL_NMI: + { + // const struct MADT_LOCAL_NMI_entry* entry = ptr; + } + break; + case APIC_TYPE_LAPIC_ADDRESS_OVERRIDE: + { + // const struct MADT_LAPIC_address_override_entry* entry = ptr; + } + break; + case APIC_TYPE_LAPICX2: + { + // const struct MADT_lapicx2_entry* entry = ptr; + } + break; + default: + kprintf("WARNING: invalid APIC MADT entry %u\n", entry_header->type); + + + } + + kprintf("entry: type %u ; size %u\n", entry_header->type,entry_header->length); + + ptr += entry_header->length; + } +} + + +static void parse_fadt(const struct ACPISDTHeader* table) { + (void) table; +} + diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h index d38452d..b79b447 100644 --- a/kernel/acpi/acpi.h +++ b/kernel/acpi/acpi.h @@ -1,7 +1,7 @@ -#pragma once - -/* - - read RSDP, XSDP, MADT, FADT -*/ -void read_acpi_tables(void* rsdp_location); +#pragma once + +/* + + read RSDP, XSDP, MADT, FADT +*/ +void read_acpi_tables(const void* rsdp_location); diff --git a/kernel/acpi/acpitables.h b/kernel/acpi/acpitables.h index e51eccc..baf1208 100644 --- a/kernel/acpi/acpitables.h +++ b/kernel/acpi/acpitables.h @@ -1,41 +1,141 @@ -#pragma once - -#include -#include - -#include "../common.h" - -struct RSDPDescriptor { - uint8_t signature[8]; - uint8_t checksum; - uint8_t OEMID[6]; - uint8_t revision; - uint32_t rsdtAddress; -} __packed; - -struct RSDPDescriptor20 { - struct RSDPDescriptor firstPart; - - uint32_t length; - uint64_t xsdtAddress; - uint8_t extendedChecksum; - uint8_t reserved[3]; -} __packed; - - - -// plagia from -// https://github.com/DorianXGH/Lucarnel/blob/master/src/includes/acpi.h -// -struct ACPISDTHeader -{ - uint8_t signature[4]; // signature of the table - uint32_t length; // length of the table - uint8_t revision; - uint8_t checksum; - uint8_t OEMID[6]; - uint8_t OEMtableID[8]; - uint32_t OEMrevision; - uint32_t creatorID; - uint32_t creator_revision; -} __packed; +#pragma once + +#include +#include + +#include "../common.h" + +struct RSDPDescriptor { + uint8_t signature[8]; + uint8_t checksum; + uint8_t OEMID[6]; + uint8_t revision; + uint32_t rsdtAddress; +} __packed; + +struct RSDPDescriptor20 { + struct RSDPDescriptor firstPart; + + uint32_t length; + uint64_t xsdtAddress; + uint8_t extendedChecksum; + uint8_t reserved[3]; +} __packed; + + +union acpi_signature { + char arg[4]; + uint32_t raw; +} __packed; + + + +// plagia from +// https://github.com/DorianXGH/Lucarnel/blob/master/src/includes/acpi.h +// +struct ACPISDTHeader { + union acpi_signature signature; + + uint32_t length; // length of the table + uint8_t revision; + uint8_t checksum; + uint8_t OEMID[6]; + uint8_t OEMtableID[8]; + uint32_t OEMrevision; + uint32_t creatorID; + uint32_t creator_revision; +} __packed; + + +struct XSDT { + struct ACPISDTHeader header; + struct ACPISDTHeader* entries[]; +} __packed; + + +struct RSDT { + struct ACPISDTHeader header; + uint32_t entries[]; +} __packed; + + +struct MADTEntryHeader { + uint8_t type; + uint8_t length; +} __packed; + + +struct MADT_lapic_entry { + struct MADTEntryHeader header; + uint8_t proc_apic_ID; + uint8_t procID; + uint32_t flags; // bit0: enabled +} __packed; + + +struct MADT_ioapic_entry { + struct MADTEntryHeader header; + uint8_t id; + uint8_t reserved; + uint32_t address; + uint32_t global_system_interrupt_base; +} __packed; + + +struct MADT_ioapic_interrupt_source_override_entry { + struct MADTEntryHeader header; + uint8_t bus_source; + uint8_t irq_source; + uint32_t global_system_interrupt; + uint16_t flags; +} __packed; + + +struct MADT_IO_NMI_entry { + struct MADTEntryHeader header; + uint8_t source; + uint8_t reserved; + uint32_t global_system_interrupt; +} __packed; + + +struct MADT_LOCAL_NMI_entry { + struct MADTEntryHeader header; + uint8_t procID; + uint16_t flags; + uint8_t lint; // 0 or 1 +} __packed; + + +struct MADT_LAPIC_address_override_entry { + struct MADTEntryHeader header; + uint8_t procID; + uint8_t flags; + uint32_t lint; // 0 or 1 +} __packed; + + +struct MADT_lapicx2_entry { + struct MADTEntryHeader header; + uint8_t proc_lapic_ID; + uint64_t flags; // bit0: enabled + uint32_t acpi_id; +} __packed; + + +struct MADT { + struct ACPISDTHeader header; + uint32_t lAPIC_address; + uint32_t flags; + struct MADTEntryHeader* entries[]; +} __packed; + + +// MADT entry types +#define APIC_TYPE_LAPIC 0 +#define APIC_TYPE_IO_APIC 1 +#define APIC_TYPE_IO_INTERRUPT_SOURCE_OVERRIDE 2 +#define APIC_TYPE_IO_NMI 3 +#define APIC_TYPE_LOCAL_NMI 4 +#define APIC_TYPE_LAPIC_ADDRESS_OVERRIDE 5 +#define APIC_TYPE_LAPICX2 9 diff --git a/kernel/cpuid.h b/kernel/cpuid.h index a590838..baa811f 100644 --- a/kernel/cpuid.h +++ b/kernel/cpuid.h @@ -1,109 +1,109 @@ -#pragma once - -#include - -struct cpuid_regs { - uint32_t eax, ebx, ecx, edx; -}; - -void cpuid(uint32_t eax, struct cpuid_regs* out_regs); - - -// doc from - -/** - * -Basic CPUID Information -Initial EAX Value Register Information Provided about the Processor -0H EAX Maximum Input Value for Basic CPUID Information (see second table) -- EBX "Genu" -- ECX "ntel" -- EDX "ineI" -01H EAX Version Information: Type, Family, Model, and Stepping ID -- EBX Bits 7-0: Brand Index -- - Bits 15-8: CLFLUSH line size (Value . 8 = cache line size in bytes) -- - Bits 23-16: Number of logical processors per physical processor; two for the Pentium 4 - processor supporting Hyper-Threading Technology -- - Bits 31-24: Local APIC ID -- ECX Extended Feature Information (see fourth table) -- EDX Feature Information (see fifth table) -02H EAX Cache and TLB Information (see sixth table) -- EBX Cache and TLB Information -- ECX Cache and TLB Information -- EDX Cache and TLB Information -03H ECX Bits 00-31 of 96 bit processor serial number. (Available in Pentium III processor only; - otherwise, the value in this register is reserved.) -- EDX Bits 32-63 of 96 bit processor serial number. (Available in Pentium III processor only; - otherwise, the value in this register is reserved.) -- - NOTE: Processor serial number (PSN) is not supported in the Pentium 4 processor or later. - On all models, use the PSN flag (returned using CPUID) to check for PSN support before - accessing the feature. See AP-485, Intel Processor Identification and the CPUID Instruction - (Order Number 241618) for more information on PSN. -04H EAX Bits 4-0: Cache Type** -- - Bits 7-5: Cache Level (starts at 1) -- - Bits 8: Self Initializing cache level (does not need SW initialization) -- - Bits 9: Fully Associative cache -- - Bits 13-10: Reserved -- - Bits 25-14: Number of threads sharing this cache* -- - Bits 31-26: Number of processor cores on this die (Multicore)* -- EBX Bits 11-00: L = System Coherency Line Size* -- - Bits 21-12: P = Physical Line partitions* -- - Bits 31-22: W = Ways of associativity* -- ECX Bits 31-00: S = Number of Sets* -- EDX Reserved = 0 -- - 0 = Null - No more caches -- - 1 = Data Cache -- - 2 = Instruction Cache -- - 3 = Unified Cache -- - 4-31 = Reserved -- - NOTE: CPUID leaves > 3 < 80000000 are only visible when IA32_CR_MISC_ENABLES.BOOT_NT4 (bit - 22) is clear (Default) -5H EAX Bits 15-00: Smallest monitor-line size in bytes (default is processor's monitor granularity) -- EBX Bits 15-00: Largest monitor-line size in bytes (default is processor's monitor granularity) - -*Add one to the value in the register file to get the number. For example, the number of processor cores is EAX[31:26]+1. -** Cache Types fields - - - -Extended Function CPUID Information -Initial EAX Value Register Information Provided about the Processor -80000000H EAX Maximum Input Value for Extended Function CPUID Information (see second table). -- EBX Reserved -- ECX Reserved -- EDX Reserved -80000001H EAX Extended Processor Signature and Extended Feature Bits. (Currently reserved) -- EBX Reserved -- ECX Reserved -- EDX Reserved -80000002H EAX Processor Brand String -- EBX Processor Brand String Continued -- ECX Processor Brand String Continued -- EDX Processor Brand String Continued -80000003H EAX Processor Brand String Continued -- EBX Processor Brand String Continued -- ECX Processor Brand String Continued -- EDX Processor Brand String Continued -80000004H EAX Processor Brand String Continued -- EBX Processor Brand String Continued -- ECX Processor Brand String Continued -- EDX Processor Brand String Continued -80000005H EAX Reserved = 0 -- EBX Reserved = 0 -- ECX Reserved = 0 -- EDX Reserved = 0 -80000006H EAX Reserved = 0 -- EBX Reserved = 0 -- ECX Bits 0-7: Cache Line Size -- - Bits 15-12: L2 Associativity -- - Bits 31-16: Cache size in 1K units -- EDX Reserved = 0 -- 80000007H EAX Reserved = 0 -- EBX Reserved = 0 -- ECX Reserved = 0 -- EDX Reserved = 0 -80000008H EAX Reserved = 0 -- EBX Reserved = 0 -- ECX Reserved = 0 -- EDX Reserved = 0 -*/ +#pragma once + +#include + +struct cpuid_regs { + uint32_t eax, ebx, ecx, edx; +}; + +void cpuid(uint32_t eax, struct cpuid_regs* out_regs); + + +// doc from + +/** + * +Basic CPUID Information +Initial EAX Value Register Information Provided about the Processor +0H EAX Maximum Input Value for Basic CPUID Information (see second table) +- EBX "Genu" +- ECX "ntel" +- EDX "ineI" +01H EAX Version Information: Type, Family, Model, and Stepping ID +- EBX Bits 7-0: Brand Index +- - Bits 15-8: CLFLUSH line size (Value . 8 = cache line size in bytes) +- - Bits 23-16: Number of logical processors per physical processor; two for the Pentium 4 + processor supporting Hyper-Threading Technology +- - Bits 31-24: Local APIC ID +- ECX Extended Feature Information (see fourth table) +- EDX Feature Information (see fifth table) +02H EAX Cache and TLB Information (see sixth table) +- EBX Cache and TLB Information +- ECX Cache and TLB Information +- EDX Cache and TLB Information +03H ECX Bits 00-31 of 96 bit processor serial number. (Available in Pentium III processor only; + otherwise, the value in this register is reserved.) +- EDX Bits 32-63 of 96 bit processor serial number. (Available in Pentium III processor only; + otherwise, the value in this register is reserved.) +- - NOTE: Processor serial number (PSN) is not supported in the Pentium 4 processor or later. + On all models, use the PSN flag (returned using CPUID) to check for PSN support before + accessing the feature. See AP-485, Intel Processor Identification and the CPUID Instruction + (Order Number 241618) for more information on PSN. +04H EAX Bits 4-0: Cache Type** +- - Bits 7-5: Cache Level (starts at 1) +- - Bits 8: Self Initializing cache level (does not need SW initialization) +- - Bits 9: Fully Associative cache +- - Bits 13-10: Reserved +- - Bits 25-14: Number of threads sharing this cache* +- - Bits 31-26: Number of processor cores on this die (Multicore)* +- EBX Bits 11-00: L = System Coherency Line Size* +- - Bits 21-12: P = Physical Line partitions* +- - Bits 31-22: W = Ways of associativity* +- ECX Bits 31-00: S = Number of Sets* +- EDX Reserved = 0 +- - 0 = Null - No more caches +- - 1 = Data Cache +- - 2 = Instruction Cache +- - 3 = Unified Cache +- - 4-31 = Reserved +- - NOTE: CPUID leaves > 3 < 80000000 are only visible when IA32_CR_MISC_ENABLES.BOOT_NT4 (bit + 22) is clear (Default) +5H EAX Bits 15-00: Smallest monitor-line size in bytes (default is processor's monitor granularity) +- EBX Bits 15-00: Largest monitor-line size in bytes (default is processor's monitor granularity) + +*Add one to the value in the register file to get the number. For example, the number of processor cores is EAX[31:26]+1. +** Cache Types fields + + + +Extended Function CPUID Information +Initial EAX Value Register Information Provided about the Processor +80000000H EAX Maximum Input Value for Extended Function CPUID Information (see second table). +- EBX Reserved +- ECX Reserved +- EDX Reserved +80000001H EAX Extended Processor Signature and Extended Feature Bits. (Currently reserved) +- EBX Reserved +- ECX Reserved +- EDX Reserved +80000002H EAX Processor Brand String +- EBX Processor Brand String Continued +- ECX Processor Brand String Continued +- EDX Processor Brand String Continued +80000003H EAX Processor Brand String Continued +- EBX Processor Brand String Continued +- ECX Processor Brand String Continued +- EDX Processor Brand String Continued +80000004H EAX Processor Brand String Continued +- EBX Processor Brand String Continued +- ECX Processor Brand String Continued +- EDX Processor Brand String Continued +80000005H EAX Reserved = 0 +- EBX Reserved = 0 +- ECX Reserved = 0 +- EDX Reserved = 0 +80000006H EAX Reserved = 0 +- EBX Reserved = 0 +- ECX Bits 0-7: Cache Line Size +- - Bits 15-12: L2 Associativity +- - Bits 31-16: Cache size in 1K units +- EDX Reserved = 0 +- 80000007H EAX Reserved = 0 +- EBX Reserved = 0 +- ECX Reserved = 0 +- EDX Reserved = 0 +80000008H EAX Reserved = 0 +- EBX Reserved = 0 +- ECX Reserved = 0 +- EDX Reserved = 0 +*/ diff --git a/kernel/cpuid.s b/kernel/cpuid.s index b66a544..217866c 100644 --- a/kernel/cpuid.s +++ b/kernel/cpuid.s @@ -1,26 +1,26 @@ -[section .text] -[global cpuid] - -;struct cpuid_regs { -; uint32_t eax, ebx, ecx, edx; -;} - - -; void cpuid(uint32_t eax, struct cpuid_regs* out_regs); -cpuid: - push ebp - mov ebp, esp - push rbx - - mov eax, edi - cpuid - - mov [rdi + 0], eax - mov [rdi + 4], ebx - mov [rdi + 8], ecx - mov [rdi + 12], edx - - - pop rbx - leave +[section .text] +[global cpuid] + +;struct cpuid_regs { +; uint32_t eax, ebx, ecx, edx; +;} + + +; void cpuid(uint32_t eax, struct cpuid_regs* out_regs); +cpuid: + push ebp + mov ebp, esp + push rbx + + mov eax, edi + cpuid + + mov [rdi + 0], eax + mov [rdi + 4], ebx + mov [rdi + 8], ecx + mov [rdi + 12], edx + + + pop rbx + leave ret \ No newline at end of file diff --git a/kernel/debug/dump.c b/kernel/debug/dump.c index f38edda..84a53d5 100644 --- a/kernel/debug/dump.c +++ b/kernel/debug/dump.c @@ -1,116 +1,115 @@ -#include "dump.h" -#include "../klib/sprintf.h" - -/** - * dump a memory chunk in kprintf - * addr: address of the beginning of the chunk - * size: number of bytes to dump - * line_size: number of words per line - * - * mode: either - * DUMP_HEX8 : hexadecimal integers of size 8 bits - * DUMP_HEX32 : hexadecimal integers of size 32 bits - * DUMP_HEX64 : hexadecimal integers of size 64 bits - * DUMP_DEC8 : decimal integers of size 8 bits - * DUMP_DEC32 : decimal integers of size 32 bits - * DUMP_DEC64 : decimal integers of size 64 bits - * - **/ -void dump(const void* addr, size_t size, size_t line_size, uint8_t mode) { - - char row_fmt[8], last_row_fmt[8]; - - size_t pitch; // sizeof word - - int i = 0; - row_fmt [i] = '%'; - last_row_fmt[i] = '%'; - i++; - - - // create fmts for printf - -// word width - if((mode & DUMP_8) != 0) { - // byte mode - - row_fmt [i] = '2'; - last_row_fmt[i] = '2'; - i++; - - pitch = 1; - } - else if((mode & DUMP_64) == 0) { - // normal 32bit mode - - row_fmt [i] = '8'; - last_row_fmt[i] = '8'; - i++; - - pitch = 4; - } - else { - // long mode - row_fmt [i] = 'l'; - last_row_fmt[i] = 'l'; - i++; - row_fmt [i] = '1'; - last_row_fmt[i] = '1'; - i++; - row_fmt [i] = '6'; - last_row_fmt[i] = '6'; - i++; - - pitch = 8; - } - -// base - char base_id; - - - if((mode & DUMP_HEX) == 0) // hex - base_id = 'x'; - else // dec - base_id = 'u'; - - row_fmt [i] = base_id; - last_row_fmt[i] = base_id; - i++; - - row_fmt [i] = ' '; - last_row_fmt[i] = '\n'; - i++; - - row_fmt [i] = '\0'; - last_row_fmt[i] = '\0'; - i++; - - - - size /= pitch; - size_t lines = (size + line_size - 1) / line_size; - - // iterator ptr - const uint8_t* ptr = addr; - -// create mask : create the complementary with 0xff...ff << n -// then complement it - const uint64_t mask = ~(~0llu << 8*pitch); - - for(size_t i = 0; i < lines; i++) { - // the last line might not be full - // therefore we have to check each one - - for(size_t j = 0; j < line_size-1; j++) { - if(size-- <= 1) - break; - else { - kprintf(row_fmt, *(uint64_t *)ptr & mask); - ptr+=pitch; - } - - } - kprintf(last_row_fmt, *(uint64_t *)ptr & mask); - ptr+=pitch; - } -} +#include "dump.h" +#include "../klib/sprintf.h" + +/** + * dump a memory chunk in kprintf + * addr: address of the beginning of the chunk + * size: number of bytes to dump + * line_size: number of words per line + * + * mode: either + * DUMP_HEX8 : hexadecimal integers of size 8 bits + * DUMP_HEX32 : hexadecimal integers of size 32 bits + * DUMP_HEX64 : hexadecimal integers of size 64 bits + * DUMP_DEC8 : decimal integers of size 8 bits + * DUMP_DEC32 : decimal integers of size 32 bits + * DUMP_DEC64 : decimal integers of size 64 bits + * + **/ +void dump(const void* addr, size_t size, size_t line_size, uint8_t mode) { + + char row_fmt[16], last_row_fmt[16]; + + size_t pitch; // sizeof word + + int i = 0; + row_fmt [i] = '%'; + last_row_fmt[i] = '%'; + i++; + + + // create fmts for printf + +// word width + if((mode & DUMP_8) != 0) { + // byte mode + + row_fmt [i] = '2'; + last_row_fmt[i] = '2'; + i++; + + pitch = 1; + } + else if((mode & DUMP_64) == 0) { + // normal 32bit mode + + row_fmt [i] = '8'; + last_row_fmt[i] = '8'; + i++; + + pitch = 4; + } + else { + // long mode + row_fmt [i] = 'l'; + last_row_fmt[i] = 'l'; + i++; + row_fmt [i] = '1'; + last_row_fmt[i] = '1'; + i++; + row_fmt [i] = '6'; + last_row_fmt[i] = '6'; + i++; + + pitch = 8; + } + +// base + char base_id; + + + if((mode & DUMP_HEX) == 0) // hex + base_id = 'x'; + else // dec + base_id = 'u'; + + row_fmt [i] = base_id; + last_row_fmt[i] = base_id; + i++; + + row_fmt [i] = ' '; + last_row_fmt[i] = '\n'; + i++; + + row_fmt [i] = '\0'; + last_row_fmt[i] = '\0'; + i++; + + + + size /= pitch; + size_t lines = (size + line_size - 1) / line_size; + + // iterator ptr + const uint8_t* ptr = addr; + +// create mask : create the complementary with 0xff...ff << n +// then complement it + const uint64_t mask = ~(~0llu << 8*pitch); + + for(size_t i = 0; i < lines; i++) { + // the last line might not be full + // therefore we have to check each one + + for(size_t j = 0; j < line_size-1; j++) { + if(size-- <= 1) + break; + else { + kprintf(row_fmt, *(uint64_t *)ptr & mask); + ptr+=pitch; + } + } + kprintf(last_row_fmt, *(uint64_t *)ptr & mask); + ptr+=pitch; + } +} diff --git a/kernel/debug/dump.h b/kernel/debug/dump.h index 75f8792..a2cd230 100644 --- a/kernel/debug/dump.h +++ b/kernel/debug/dump.h @@ -1,23 +1,23 @@ -#pragma once - -#include -#include - - - -#define DUMP_HEX 0 -#define DUMP_DEC 16 - -#define DUMP_8 32 -#define DUMP_32 0 -#define DUMP_64 1 - -#define DUMP_HEX8 (DUMP_HEX | DUMP_8) -#define DUMP_HEX32 (DUMP_HEX | DUMP_32) -#define DUMP_HEX64 (DUMP_HEX | DUMP_64) -#define DUMP_DEC8 (DUMP_DEC | DUMP_8) -#define DUMP_DEC32 (DUMP_DEC | DUMP_32) -#define DUMP_DEC64 (DUMP_DEC | DUMP_64) - - -void dump(const void* addr, size_t size, size_t line_size, uint8_t mode); +#pragma once + +#include +#include + + + +#define DUMP_HEX 0 +#define DUMP_DEC 16 + +#define DUMP_8 32 +#define DUMP_32 0 +#define DUMP_64 1 + +#define DUMP_HEX8 (DUMP_HEX | DUMP_8) +#define DUMP_HEX32 (DUMP_HEX | DUMP_32) +#define DUMP_HEX64 (DUMP_HEX | DUMP_64) +#define DUMP_DEC8 (DUMP_DEC | DUMP_8) +#define DUMP_DEC32 (DUMP_DEC | DUMP_32) +#define DUMP_DEC64 (DUMP_DEC | DUMP_64) + + +void dump(const void* addr, size_t size, size_t line_size, uint8_t mode); diff --git a/kernel/entry.c b/kernel/entry.c index 4c65668..89251b4 100644 --- a/kernel/entry.c +++ b/kernel/entry.c @@ -10,6 +10,7 @@ #include "acpi/acpi.h" #include "common.h" #include "regs.h" +#include "int/apic.h" #include "int/idt.h" @@ -44,9 +45,9 @@ static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = { }, // We set all the framebuffer specifics to 0 as we want the bootloader // to pick the best it can. - .framebuffer_width = 0, - .framebuffer_height = 0, - .framebuffer_bpp = 0 + .framebuffer_width = 1152, + .framebuffer_height = 864, + .framebuffer_bpp = 32 }; // The stivale2 specification says we need to define a "header structure". @@ -94,8 +95,8 @@ void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) { } -#define PRINT_VAL(v) kprintf(#v "=%ld\n", v); -#define PRINT_HEX(v) kprintf(#v "=%lx\n", v); +#define PRINT_VAL(v) kprintf(#v "=%ld\n", (uint64_t)v); +#define PRINT_HEX(v) kprintf(#v "=%lx\n", (uint64_t)v); // const char but represents a big string extern const char _binary_bootmessage_txt; @@ -112,6 +113,14 @@ static void debug_terminal() { kputs(buff); } +static void print_fb_infos(struct stivale2_struct_tag_framebuffer* fbtag) { + PRINT_VAL(fbtag->framebuffer_width); + PRINT_VAL(fbtag->framebuffer_height); + PRINT_VAL(fbtag->framebuffer_pitch); + PRINT_VAL(fbtag->framebuffer_bpp); + PRINT_HEX(fbtag->framebuffer_addr); +} + #pragma GCC diagnostic pop @@ -148,7 +157,7 @@ void _start(struct stivale2_struct *stivale2_struct) { uint64_t rsdp_location = rsdp_tag_ptr->rsdp; - + Image sc = {.w = fbtag.framebuffer_width, @@ -165,13 +174,24 @@ void _start(struct stivale2_struct *stivale2_struct) { setup_terminal(); setup_isr(); + terminal_set_colors(0xf0f0f0, 0x007000); + terminal_clear(); + kputs(&_binary_bootmessage_txt); read_acpi_tables((void*)rsdp_location); - - asm volatile("sti"); + kputs("DONE\n"); - kputs(&_binary_bootmessage_txt); + apic_setup_clock(); + + + + + + for(;;) { + asm volatile("hlt"); + kprintf("%lu\t", clock()); + } for(;;) { diff --git a/kernel/int/apic.c b/kernel/int/apic.c new file mode 100644 index 0000000..9f65f77 --- /dev/null +++ b/kernel/int/apic.c @@ -0,0 +1,95 @@ +#include + +#include "../debug/assert.h" +#include "idt.h" +#include "apic.h" +#include "../klib/sprintf.h" + +#define LAPIC_TIMER_IRQ 0xff + +struct APICConfig* apic_config = NULL; + + +void outb(uint16_t dx, uint16_t al); +uint8_t inb(uint16_t dx); + + +static void pit_wait(size_t ms) { + outb(0x43, 0x30); + uint16_t val = 0x4a9 * ms; + outb(0x40, (uint8_t)val); + outb(0x40, (uint8_t)(val >> 8)); + for(;;) { + outb(0x43, 0xe2); + uint8_t status = inb(0x40); + if ((status & (1 << 7)) != 0) { + break; + } + } +} + +static unsigned read_pit_count(void) { + unsigned count = 0; + + // Disable interrupts + uint64_t rf = get_rflags(); + _cli(); + + // al = channel in bits 6 and 7, remaining bits clear + outb(0x43,0b0000000); + + count = inb(0x40); // Low byte + count |= inb(0x40)<<8; // High byte + + + set_rflags(rf); + + return count; +} + + +uint64_t apic_timer_clock_count = 0; + + +__attribute__((interrupt)) void lapic_timer_handler(struct IFrame* frame) { + (void) frame; + ++apic_timer_clock_count; + + kprintf("%x\n", apic_timer_clock_count); + + apic_config->end_of_interrupt.reg = 0; +} + + +uint64_t clock(void) { + return apic_timer_clock_count; +} + +void apic_setup_clock(void) { + assert(apic_config != NULL); + + set_irq_handler(LAPIC_TIMER_IRQ, lapic_timer_handler); + + // disable apic and set spurious int to 32 + apic_config->spurious_interrupt_vector.reg = 0 | LAPIC_TIMER_IRQ; + + apic_config->timer_divide_configuration.reg = 2; // divide by 8 + apic_config->timer_initial_count.reg = UINT32_MAX; + + pit_wait(1); /// wait for 1 ms + + //apic_config->timer_initial_count.reg = UINT32_MAX - apic_config->timer_current_count.reg; + + + for(int i = 0; i < 1000000000; i++) { + kprintf("%x\t%x\n", apic_config->timer_current_count.reg, read_pit_count()); + + // asm volatile("hlt"); + } + // count + + + // enable the clock irqs + apic_config->spurious_interrupt_vector.reg = 0x100 | LAPIC_TIMER_IRQ; +} + diff --git a/kernel/int/apic.h b/kernel/int/apic.h new file mode 100644 index 0000000..c21e899 --- /dev/null +++ b/kernel/int/apic.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include "../debug/assert.h" + + +struct APICRegister +{ + uint32_t reg; + uint32_t reserved[3]; +}; +static_assert(sizeof(struct APICRegister) == 16); + +struct APICConfig +{ + struct APICRegister reserved1[2]; // + struct APICRegister LAPIC_ID; // RW + struct APICRegister LAPIC_version; // R + struct APICRegister reserved2[4]; // + struct APICRegister task_priority; // RW + struct APICRegister arbitration_priority; // R + struct APICRegister processor_priority; // R + struct APICRegister end_of_interrupt; // W + struct APICRegister remote_read; // R + struct APICRegister logical_destination; // RW + struct APICRegister destination_format; // RW + struct APICRegister spurious_interrupt_vector; // RW + struct APICRegister in_service[8]; // R + struct APICRegister trigger_mode[8]; // R + struct APICRegister interrupt_request[8]; // R + struct APICRegister error_status; // R + struct APICRegister reserved3[6]; // + struct APICRegister LVT_corrected_machine_check_interrupt;// RW + struct APICRegister interrupt_command[2]; // RW + struct APICRegister LVT_timer; // RW + struct APICRegister LVT_thermal_sensor; // RW + struct APICRegister LVT_performance_monitoring_counters; // RW + struct APICRegister LVT_LINT0; // RW + struct APICRegister LVT_LINT1; // RW + struct APICRegister LVT_error; // RW + struct APICRegister timer_initial_count; // RW + struct APICRegister timer_current_count; // R + struct APICRegister reserved4[4]; // + struct APICRegister timer_divide_configuration; // RW + struct APICRegister reserved5; // + +}; +static_assert(sizeof(struct APICConfig) == 0x400); + + +void apic_setup_clock(void); +uint64_t clock(void); diff --git a/kernel/int/idt.c b/kernel/int/idt.c index 649e53f..b4ffaee 100644 --- a/kernel/int/idt.c +++ b/kernel/int/idt.c @@ -1,98 +1,124 @@ -#include -#include - -#include "../common.h" -#include "idt.h" - - - -typedef struct { - uint16_t size; - const void* offset; -} __packed IDTD; - - -typedef struct { - uint8_t gate_type: 4; - uint8_t z : 1; - uint8_t dpl : 2; - uint8_t p : 1; -} __packed type_attr_t; - - -static_assert(sizeof(type_attr_t) == 1); - - -typedef struct { - uint16_t offset_1; // offset bits 0..15 - uint16_t selector; // a code segment selector in GDT or LDT - uint8_t ist; // bits 0..2 holds Interrupt - // Stack Table offset, rest of bits zero. - - type_attr_t type_attr; // type and attributes - uint16_t offset_2; // offset bits 16..31 - uint32_t offset_3; // offset bits 32..63 - uint32_t zero; // reserved -} __packed IDTE; - - - -IDTE idt[256] = {0}; - -void _lidt(IDTD* idtd); - -void setup_idt(void) { - IDTD idt_descriptor = { - .size = 255 * sizeof(IDTE), - .offset = idt, - }; - - _lidt(&idt_descriptor); -} - - -static type_attr_t make_type_attr_t(uint8_t gate_type) { - - assert((gate_type & 0xf0) == 0); - - return (type_attr_t) { - .gate_type = gate_type, - .z = 0, - .dpl = 0, - .p = 1, - }; -} - - -static IDTE make_idte(void* handler, type_attr_t type_attr) { - uint64_t h = (uint64_t) handler; - - return (IDTE) { - .offset_1 = h & 0xffff, - .selector = 0x08, // kernel code segment - .ist = 0, - .type_attr = type_attr, - .offset_2 = (h >> 16) & 0xffff, - .offset_3 = (h >> 32) & 0xffffffff, - .zero = 0, - }; -} - -static IDTE make_isr(void* handler) { - return make_idte(handler, make_type_attr_t(ATTR_64_GATE)); -} - - -void set_interrupt_handler(uint16_t number, void* handler) { - idt[number] = make_isr(handler); -} - - -void _cli(void) { - asm volatile("cli"); -} - - -void _sti(void) { - asm volatile("sti"); -} +#include +#include + +#include "../common.h" +#include "idt.h" + + + +typedef struct { + uint16_t size; + const void* offset; +} __packed IDTD; + + +typedef struct { + uint8_t gate_type: 4; + uint8_t z : 1; + uint8_t dpl : 2; + uint8_t p : 1; +} __packed type_attr_t; + + +static_assert(sizeof(type_attr_t) == 1); + + +typedef struct { + uint16_t offset_1; // offset bits 0..15 + uint16_t selector; // a code segment selector in GDT or LDT + uint8_t ist; // bits 0..2 holds Interrupt + // Stack Table offset, rest of bits zero. + + type_attr_t type_attr; // type and attributes + uint16_t offset_2; // offset bits 16..31 + uint32_t offset_3; // offset bits 32..63 + uint32_t zero; // reserved +} __packed IDTE; + + + +IDTE idt[256] = {0}; + +void _lidt(IDTD* idtd); + +void setup_idt(void) { + IDTD idt_descriptor = { + .size = 255 * sizeof(IDTE), + .offset = idt, + }; + + _lidt(&idt_descriptor); +} + + +static type_attr_t make_type_attr_t(uint8_t gate_type) { + + assert((gate_type & 0xf0) == 0); + + return (type_attr_t) { + .gate_type = gate_type, + .z = 0, + .dpl = 0, + .p = 1, + }; +} + + +static IDTE make_idte(void* handler, type_attr_t type_attr) { + uint64_t h = (uint64_t) handler; + + return (IDTE) { + .offset_1 = h & 0xffff, + .selector = 0x08, // kernel code segment + .ist = 0, + .type_attr = type_attr, + .offset_2 = (h >> 16) & 0xffff, + .offset_3 = (h >> 32) & 0xffffffff, + .zero = 0, + }; +} + +static IDTE make_isr(void* handler) { + return make_idte(handler, make_type_attr_t(ATTR_64_GATE)); +} +static IDTE make_irq(void* handler) { + return make_idte(handler, make_type_attr_t(ATTR_64_TRAP)); +} + + +void set_rflags(uint64_t RFLAGS); +uint64_t get_rflags(void); + + +void set_irs_handler(uint16_t number, void* handler) { +// make sure to disable interrupts +// while updating the idt +// then save IF to its old state + uint64_t rflags = get_rflags(); + _cli(); + + idt[number] = make_isr(handler); + + set_rflags(rflags); +} + + +void set_irq_handler(uint16_t number, void* handler) { +// same as above + uint64_t rflags = get_rflags(); + _cli(); + + idt[number] = make_irq(handler); + + set_rflags(rflags); +} + + +void _cli(void) { + asm volatile("cli"); +} + + +void _sti(void) { + asm volatile("sti"); +} diff --git a/kernel/int/idt.h b/kernel/int/idt.h index dcdf36d..708a3e8 100644 --- a/kernel/int/idt.h +++ b/kernel/int/idt.h @@ -1,35 +1,37 @@ -#ifndef IDT_H -#define IDT_H - -#include -#include -#include "../debug/assert.h" - -#define ATTR_64_GATE 0b1110 -#define ATTR_64_TRAP 0b1110 - - - -struct IFrame { - uint64_t RIP; - uint64_t CS; - uint64_t RFLAGS; - uint64_t RSP; - uint64_t SS; -} __packed; - -static_assert(sizeof(struct IFrame) == 40); - - - -void setup_idt(void); - -void set_interrupt_handler(uint16_t number, void* handler); -void _cli(void); -void _sti(void); - - -void setup_isr(void); - - +#ifndef IDT_H +#define IDT_H + +#include +#include +#include "../debug/assert.h" +#include "../common.h" + +#define ATTR_64_GATE 0b1110 +#define ATTR_64_TRAP 0b1110 + + + +struct IFrame { + uint64_t RIP; + uint64_t CS; + uint64_t RFLAGS; + uint64_t RSP; + uint64_t SS; +} __packed; + +static_assert(sizeof(struct IFrame) == 40); + + + +void setup_idt(void); + +void set_irs_handler(uint16_t number, void* handler); +void set_irq_handler(uint16_t number, void* handler); +void _cli(void); +void _sti(void); + + +void setup_isr(void); + + #endif // IDT_H \ No newline at end of file diff --git a/kernel/int/idt.s b/kernel/int/idt.s index 2ce2b99..62530c2 100644 --- a/kernel/int/idt.s +++ b/kernel/int/idt.s @@ -1,7 +1,7 @@ - -[section .text] -[global _lidt] - -_lidt: - lidt [rdi] + +[section .text] +[global _lidt] + +_lidt: + lidt [rdi] ret \ No newline at end of file diff --git a/kernel/int/isr.c b/kernel/int/isr.c index 4a298db..ff3a2fb 100644 --- a/kernel/int/isr.c +++ b/kernel/int/isr.c @@ -1,141 +1,126 @@ -#include "../klib/sprintf.h" -#include "../debug/assert.h" -#include "../debug/panic.h" -#include "idt.h" - - - - - -static void print_frame(struct IFrame* interrupt_frame) { - kprintf( - "RIP: %16lx\n" - "RSP: %16lx\n" - "CS: %16lx SS: %16lx\n" - "\n" - "RFLAGS: %8lx\n", - interrupt_frame->RIP, - interrupt_frame->RSP, - interrupt_frame->CS, - interrupt_frame->SS, - interrupt_frame->RFLAGS); -} - - -__attribute__((interrupt)) void ISR_general_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_general_handler()\n"); -} -__attribute__((interrupt)) void ISR_error_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) interrupt_frame; - kprintf("ISR_error_handler()\n"); -} - - -__attribute__((interrupt)) void ISR_div_by_zero_handler(struct IFrame* interrupt_frame) { - print_frame(interrupt_frame); - panic("ISR_div_by_zero_handler():\n"); - asm volatile("cli"); - asm volatile("hlt"); -} - - - -__attribute__((interrupt)) void ISR_debug_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_debug_handler()\n"); -} -__attribute__((interrupt)) void ISR_NMI_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_NMI_handler()\n"); -} -__attribute__((interrupt)) void ISR_breakpoint_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_breakpoint_handler()\n"); -} -__attribute__((interrupt)) void ISR_overflow_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_overflow_handler()\n"); -} -__attribute__((interrupt)) void ISR_bound_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_bound_handler()\n"); -} -__attribute__((interrupt)) void ISR_invalid_opcode_handler(struct IFrame* interrupt_frame) { - kprintf("ISR_invalid_opcode_handler()\n"); - print_frame(interrupt_frame); - asm volatile("cli"); - asm volatile("hlt"); -} -__attribute__((interrupt)) void ISR_device_not_available_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_device_not_available_handler()\n"); -} -__attribute__((interrupt)) void ISR_double_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) interrupt_frame; - (void) error_code; - kprintf("ISR_double_fault_handler()\n"); -} -__attribute__((interrupt)) void ISR_coproc_segment_overrun_handler(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_coproc_segment_overrun_handler()\n"); -} -__attribute__((interrupt)) void ISR_invalid_TSS_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) interrupt_frame; - (void) error_code; - - kprintf("ISR_invalid_TSS_handler()\n"); -} -__attribute__((interrupt)) void ISR_segment_not_present_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) error_code; - (void) interrupt_frame; - kprintf("ISR_segment_not_present_handler()\n"); -} -__attribute__((interrupt)) void ISR_stack_segment_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) error_code; - (void) interrupt_frame; - kprintf("ISR_stack_segment_fault_handler()\n"); -} -__attribute__((interrupt)) void ISR_general_protection_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) error_code; - (void) interrupt_frame; - kprintf("ISR_general_protection_fault_handler()\n"); -} -__attribute__((interrupt)) void ISR_page_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { - (void) error_code; - (void) interrupt_frame; - kprintf("ISR_page_fault_handler()\n"); -} -__attribute__((interrupt)) void ISR_spurious(struct IFrame* interrupt_frame) { - (void) interrupt_frame; - kprintf("ISR_spurious()\n"); -} - -extern uint64_t idt[256]; - - -void setup_isr(void) { - _cli(); - - set_interrupt_handler(0, (void *) ISR_div_by_zero_handler); - set_interrupt_handler(1, (void *) ISR_debug_handler); - set_interrupt_handler(2, (void *) ISR_NMI_handler); - set_interrupt_handler(3, (void *) ISR_breakpoint_handler); - set_interrupt_handler(4, (void *) ISR_overflow_handler); - set_interrupt_handler(5, (void *) ISR_bound_handler); - set_interrupt_handler(6, (void *) ISR_invalid_opcode_handler); - set_interrupt_handler(7, (void *) ISR_device_not_available_handler); - set_interrupt_handler(8, (void *) ISR_double_fault_handler); - set_interrupt_handler(9, (void *) ISR_coproc_segment_overrun_handler); - set_interrupt_handler(10, (void *) ISR_invalid_TSS_handler); - set_interrupt_handler(11, (void *) ISR_segment_not_present_handler); - set_interrupt_handler(12, (void *) ISR_stack_segment_fault_handler); - set_interrupt_handler(13, (void *) ISR_general_protection_fault_handler); - set_interrupt_handler(14, (void *) ISR_page_fault_handler); - - for(int i = 15; i <= 255; i++) - set_interrupt_handler(i, ISR_spurious); - - setup_idt(); - _sti(); +#include "../klib/sprintf.h" +#include "../debug/assert.h" +#include "../debug/panic.h" +#include "idt.h" + + + + + +static void print_frame(char* buff, struct IFrame* interrupt_frame) { + sprintf(buff, + "RIP: %16lx\n" + "RSP: %16lx\n" + "CS: %16lx SS: %16lx\n" + "\n" + "RFLAGS: %8lx\n", + interrupt_frame->RIP, + interrupt_frame->RSP, + interrupt_frame->CS, + interrupt_frame->SS, + interrupt_frame->RFLAGS); +} + + +static void panic_handler(const char* name,struct IFrame* interrupt_frame) { + char buff1[256], buff2[512]; + print_frame(buff1, interrupt_frame); + sprintf(buff2, "%s: \n%s", name, buff1); + + panic(buff2); + __builtin_unreachable(); +} + +__attribute__((interrupt)) void ISR_general_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_general_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_error_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_error_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_div_by_zero_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_div_by_zero_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_debug_handler(struct IFrame* interrupt_frame) { + + panic_handler("ISR_debug_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_NMI_handler(struct IFrame* interrupt_frame) { + + panic_handler("ISR_NMI_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_breakpoint_handler(struct IFrame* interrupt_frame) { + + panic_handler("ISR_breakpoint_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_overflow_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_overflow_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_bound_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_bound_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_invalid_opcode_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_invalid_opcode_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_device_not_available_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_device_not_available_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_double_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_double_fault_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_coproc_segment_overrun_handler(struct IFrame* interrupt_frame) { + panic_handler("ISR_coproc_segment_overrun_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_invalid_TSS_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_invalid_TSS_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_segment_not_present_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_segment_not_present_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_stack_segment_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_stack_segment_fault_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_general_protection_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_general_protection_fault_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_page_fault_handler(struct IFrame* interrupt_frame, uint64_t error_code) { + (void) error_code; + panic_handler("ISR_page_fault_handler", interrupt_frame); +} +__attribute__((interrupt)) void ISR_spurious(struct IFrame* interrupt_frame) { + panic_handler("ISR_spurious", interrupt_frame); +} + +extern uint64_t idt[256]; + + +void setup_isr(void) { + _cli(); + + set_irs_handler(0, (void *) ISR_div_by_zero_handler); + set_irs_handler(1, (void *) ISR_debug_handler); + set_irs_handler(2, (void *) ISR_NMI_handler); + set_irs_handler(3, (void *) ISR_breakpoint_handler); + set_irs_handler(4, (void *) ISR_overflow_handler); + set_irs_handler(5, (void *) ISR_bound_handler); + set_irs_handler(6, (void *) ISR_invalid_opcode_handler); + set_irs_handler(7, (void *) ISR_device_not_available_handler); + set_irs_handler(8, (void *) ISR_double_fault_handler); + set_irs_handler(9, (void *) ISR_coproc_segment_overrun_handler); + set_irs_handler(10, (void *) ISR_invalid_TSS_handler); + set_irs_handler(11, (void *) ISR_segment_not_present_handler); + set_irs_handler(12, (void *) ISR_stack_segment_fault_handler); + set_irs_handler(13, (void *) ISR_general_protection_fault_handler); + set_irs_handler(14, (void *) ISR_page_fault_handler); + + for(int i = 15; i <= 255; i++) + set_irs_handler(i, ISR_spurious); + + setup_idt(); + _sti(); } \ No newline at end of file diff --git a/kernel/klib/math.h b/kernel/klib/math.h new file mode 100644 index 0000000..a2148c6 --- /dev/null +++ b/kernel/klib/math.h @@ -0,0 +1,6 @@ +#pragma once + +#define MIN(X,Y) (X > Y ? Y : X) +#define MAX(X,Y) (X < Y ? Y : X) + +#define CEIL_DIV(X, Y) ((X + Y - 1) / Y) diff --git a/kernel/klib/sprintf.c b/kernel/klib/sprintf.c index 859a461..11dad04 100644 --- a/kernel/klib/sprintf.c +++ b/kernel/klib/sprintf.c @@ -1,11 +1,12 @@ #include "sprintf.h" +#include "math.h" #include "string.h" #include "../video/terminal.h" #define SIGN(X) X > 0 ? 1 : -1 #define ARG(TYPE) (TYPE)va_arg(ap, TYPE) -char* utohex(char* str, uint64_t x, size_t min_digits) { +static char* utohex(char* str, uint64_t x, int min_digits) { size_t digits = 1; uint64_t _x = x; @@ -16,7 +17,7 @@ char* utohex(char* str, uint64_t x, size_t min_digits) { digits++; } - if(digits < min_digits) + if((int)digits < min_digits) digits = min_digits; char* end = str+digits; @@ -41,7 +42,7 @@ char* utohex(char* str, uint64_t x, size_t min_digits) { // unsigned to string // return a ptr to the end of the string -char* utos(char* str, uint64_t x, size_t min_digits) { +static char* utos(char* str, uint64_t x, int min_digits) { size_t digits = 1; uint64_t _x = x; @@ -50,7 +51,7 @@ char* utos(char* str, uint64_t x, size_t min_digits) { digits++; } - if(digits < min_digits) + if((int)digits < min_digits) digits = min_digits; char* end = str+digits; @@ -68,7 +69,7 @@ char* utos(char* str, uint64_t x, size_t min_digits) { } // signed to string -char* itos(char* str, int64_t x, size_t min_digits) { +static char* itos(char* str, int64_t x, int min_digits) { if(x < 0) { *(str++) = '-'; x *= -1; @@ -82,7 +83,7 @@ int vsprintf(char *str, const char *format, va_list ap) { char cf; int args_put = 0; int persent = 0; - int digits = 0; + int digits = -1; // bool value: '%l..' int _long = 0; @@ -101,8 +102,11 @@ int vsprintf(char *str, const char *format, va_list ap) { } int i = cf - '0'; - if(i >= 0 && i <= 9) + if(i >= 0 && i <= 9) { + if(digits < 0) + digits = 0; digits = 10 * digits + i; + } else { switch(cf) { default: @@ -131,15 +135,24 @@ int vsprintf(char *str, const char *format, va_list ap) { case 's': { const char* arg = ARG(const char*); - strcpy(str, arg); - str += strlen(arg); + if(digits >= 0) { + strncpy(str, arg, digits); + if((int) strlen(arg) > digits) + str += strlen(arg); + else + str += digits; + } + else { + strcpy(str, arg); + str += strlen(arg); + } } break; case 'c': *(str++) = (char)ARG(int); break; } - digits = 0; + digits = -1; persent = 0; _long = 0; args_put++; @@ -147,6 +160,11 @@ int vsprintf(char *str, const char *format, va_list ap) { } else if(cf == '%') { + if(persent) { + // allow %% in fmt to print '%' + persent = 0; + *(str++) = '%'; + } persent = 1; } else { diff --git a/kernel/linker.ld b/kernel/linker.ld index 59076ca..642e87a 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,31 +1,59 @@ -/* Tell the linker that we want the symbol _start to be our entry point */ +/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) + +/* We want the symbol _start to be our entry point */ ENTRY(_start) -SECTIONS +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS { - . = 0x00100000; + null PT_NULL FLAGS(0) ; /* Null segment */ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ + dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic segment needed for PIE */ +} - /* We place the .stivalehdr section containing the header in its own section, */ - /* and we use the KEEP directive on it to make sure it doesn't get discarded. */ - .stivalehdr : { - KEEP(*(.stivalehdr)) - } +SECTIONS +{ + /* We wanna be placed in the higher half, 2MiB above 0 in physical memory. */ + /* Since we are going to use PIE, this is just the base load address, but the */ + /* bootloader will be able to relocate us as it sees fit. */ + . = 0xffffffff80200000; - /* Then let's place all the other traditional executable sections afterwards. */ - .text : ALIGN(0x1000) { + .text : { *(.text*) - } + } :text - .rodata : ALIGN(0x1000) { + /* Move to the next memory page for .rodata */ + . += 0x1000; + + /* We place the .stivale2hdr section containing the header in its own section, */ + /* and we use the KEEP directive on it to make sure it doesn't get discarded. */ + .stivale2hdr : { + KEEP(*(.stivale2hdr)) + } :rodata + + .rodata : { *(.rodata*) - } + } :rodata - .data : ALIGN(0x1000) { + /* Move to the next memory page for .data */ + . += 0x1000; + + .data : { *(.data*) - } + } :data + + /* Dynamic section needed for PIE */ + .dynamic : { + *(.dynamic) + } :data :dynamic - .bss : ALIGN(0x1000) { + .bss : { *(COMMON) *(.bss*) - } + } :data } \ No newline at end of file diff --git a/kernel/memory/kalloc.c b/kernel/memory/kalloc.c index de790ce..f99d084 100644 --- a/kernel/memory/kalloc.c +++ b/kernel/memory/kalloc.c @@ -1,24 +1,31 @@ #include #include +#include "../klib/sprintf.h" #include "kalloc.h" #include "../debug/assert.h" #include "../common.h" -#define HEAP_SIZE_MB 16 -#define HEAP_SIZE HEAP_SIZE_MB * 1024 * 1024 +#define HEAP_SIZE_KB 16 * 1024 +#define HEAP_BEGIN 0x01000000 +#define HEAP_SIZE 1024 * HEAP_SIZE_KB -static uint8_t heap[HEAP_SIZE] __attribute__((section(".bss"))); +//(0x00EFFFFF - HEAP_BEGIN) -static void* brk = (void *) heap; +//static const uint8_t* heap = (uint8_t*)0x00100000; //[HEAP_SIZE] __attribute__((section(".bss"))); + +static void* brk = (void *) HEAP_BEGIN; void* kmalloc(size_t size) { void* ptr = brk; brk = mallign16(brk+size); - assert((size_t)brk - (size_t)heap < HEAP_SIZE); + kprintf("kmalloc(%lu); heap use: %u ko / %u ko\n", + size, ((size_t)brk - (size_t)HEAP_BEGIN) / 1024, HEAP_SIZE / 1024); + + assert((size_t)brk - (size_t)HEAP_BEGIN < HEAP_SIZE); return ptr; } diff --git a/kernel/regs.s b/kernel/regs.s index 23a8e23..f1e478c 100644 --- a/kernel/regs.s +++ b/kernel/regs.s @@ -4,6 +4,10 @@ [global _es] [global _fs] [global _gs] +[global inb] +[global outb] +[global get_rflags] +[global set_rflags] section .text @@ -36,4 +40,36 @@ _fs: xor rax,rax mov ax, fs ret - \ No newline at end of file + + +get_rflags: + pushfq + pop rax + ret + +; set_rflags(uint64_t rflags) +set_rflags: + push rdi + popfq + ret + + +; uint8_t inb(port) +inb: + push rdx + mov rdx, rdi + xor rax, rax + + in al, dx + + pop rdx + ret + +outb: + push rdx + mov al, dil + + out dx, al + + pop rdx + ret diff --git a/kernel/video/terminal.c b/kernel/video/terminal.c index fb1bafd..841310c 100644 --- a/kernel/video/terminal.c +++ b/kernel/video/terminal.c @@ -21,8 +21,6 @@ static struct Char make_Char(char c); static void print_char(const struct Char* restrict c, int line, int col); static terminal_handler_t terminal_handler = NULL; -static uint32_t terminal_foreground = 0xa0a0a0; -static uint32_t terminal_background = 0x00; // need to redraw the entire terminal static bool need_refresh = false; @@ -54,7 +52,7 @@ void setup_terminal(void) { assert(charmap != NULL); assert(charmap->bpp == 1); - assert(charmap->pitch == 2); + assert(charmap->pitch == 1); assert(charmap->w == CHARMAP_W); assert(charmap->h == CHARMAP_H); @@ -71,14 +69,14 @@ void setup_terminal(void) { buffer = kmalloc(nlines * ncols * sizeof(struct Char)); - clear_terminal(); + terminal_clear(); set_terminal_handler(write_string); } -void clear_terminal(void) { +void terminal_clear(void) { cur_col = 0; cur_line = 0; first_line = 0; @@ -164,7 +162,7 @@ static void emplace_char(char c) { break; case '\t': - cur_col = (cur_col / TAB_SPACE) * TAB_SPACE; + cur_col = ((cur_col + TAB_SPACE - 1) / TAB_SPACE) * TAB_SPACE; if(cur_col >= ncols) next_line(); @@ -209,9 +207,12 @@ static void print_char(const struct Char* restrict c, int line, int col) { }; */ - blitchar(charmap, c->c, c->fg_color, c->bg_color, + blitcharX2(charmap, c->c, c->fg_color, c->bg_color, col * FONTWIDTH, line * LINE_HEIGHT); + + + //imageDraw(charmap, NULL, NULL); //imageFillRect(c->bg_color, &interlineRect); @@ -256,6 +257,6 @@ void set_terminal_handler(terminal_handler_t h) { } void terminal_set_colors(uint32_t foreground, uint32_t background) { - terminal_foreground = foreground; - terminal_background = background; + current_fgcolor = foreground; + current_bgcolor = background; } diff --git a/kernel/video/terminal.h b/kernel/video/terminal.h index 2300723..94cf94a 100644 --- a/kernel/video/terminal.h +++ b/kernel/video/terminal.h @@ -2,13 +2,15 @@ #include #include +#include "../debug/assert.h" - -#define CHARMAP_W 12 -#define CHARMAP_H 4096 +#define CHARMAP_W 6 +#define CHARMAP_H 2048 // must be divisible by 4 !!! +static_assert(CHARMAP_H % 4 == 0); + #define FONTWIDTH CHARMAP_W #define FONTHEIGHT (CHARMAP_H / 256) #define INTERLINE 0 @@ -30,7 +32,7 @@ void set_terminal_fgcolor(uint32_t c); void setup_terminal(void); -void clear_terminal(void); +void terminal_clear(void); // no use another terminal handler void set_terminal_handler(terminal_handler_t h); diff --git a/kernel/video/video.c b/kernel/video/video.c index e3f1a08..7606379 100644 --- a/kernel/video/video.c +++ b/kernel/video/video.c @@ -6,6 +6,7 @@ #include "../common.h" #include "../memory/kalloc.h" #include "../debug/assert.h" +#include "../debug/dump.h" #define MAX(X,Y) X > Y ? X : Y @@ -244,9 +245,8 @@ Image* alloc_image(uint32_t width, uint32_t height, uint32_t bpp) { assert(bpp % 8 == 0 || bpp == 1); if(bpp == 1) { - int words = (width + 15) / 16; - // align on 2 byte - ret->pitch = words * 2; + // align on 1 byte + ret->pitch = (width + 7) / 8; } else ret->pitch = (uint32_t)allign16(width * (bpp/8)); @@ -277,8 +277,8 @@ struct BMPFileHeader { uint16_t reserved2; // uint32_t body_offset;// byte offset of the pixel body uint32_t header_size;// should be eq to sizeof(BMPFileHeader) - int32_t w; // BMP width in pixels - int32_t h; // BMP height in pixels + int32_t w; // BMP width in pixels + int32_t h; // BMP height in pixels uint16_t one; // should be eq to 1 uint16_t bpp; // bits per pixel } __packed; @@ -421,47 +421,97 @@ void blitchar(const struct Image* charset, ((uint64_t) fg_color << 32) | bg_color, ((uint64_t) fg_color << 32) | fg_color, }; - - uint16_t srcy = c * FONTHEIGHT; uint64_t* dst_ptr = (uint64_t *)(screen.pix + screen.pitch * dsty + 4 * dstx); - uint16_t dst_skip = screen.pitch - FONTWIDTH * 4; + uint16_t dst_skip = screen.pitch - FONTWIDTH * 4; - // 4 2-byte lines = 4*16 = 64 (1 access every 4 lines) + // 4 2-byte lines = 8*8 = 64 (1 access every 4 lines) // 1st line address for the selected char - uint64_t* lines_ptr = charset->pix + srcy * 2; + uint64_t* lines_ptr = (uint64_t*)charset->pix + c; + + // loop over 4-line chunks - for(size_t n_lines = FONTHEIGHT / 4; n_lines > 0; --n_lines) { +// for(size_t n_lines = FONTHEIGHT / 4; n_lines > 0; --n_lines) { - uint64_t lines = *(lines_ptr++); + uint64_t lines = *lines_ptr; - // 64 bit = 4 lines - for(size_t n_line = 4; n_line > 0; n_line--) { - uint16_t line = lines; - // lines are 16bit aligned - - lines >>= 16; - - for(size_t n_col2 = FONTWIDTH / 2 ; n_col2 > 0 ; n_col2--) { - uint16_t index = line & 0b11; + // 64 bit = 8 lines +#pragma GCC unroll 8 + for(size_t n_line = 8; n_line > 0; n_line--) { + // lines are 8bit aligned + +#pragma GCC unroll 3 + for(size_t n_col2 = FONTWIDTH / 2 ; n_col2 > 0 ; n_col2--) { + uint16_t index = lines & 0b11; - - *(dst_ptr++) = colormap[index]; - line >>= 2; - } - dst_ptr += dst_skip / sizeof(dst_ptr); + *(dst_ptr++) = colormap[index]; + lines >>= 2; } + dst_ptr += dst_skip / 8; + + lines >>= 8 - FONTWIDTH; + } + +} + + + + +void blitcharX2(const struct Image* charset, + char c, uint32_t fg_color, uint32_t bg_color, + uint16_t dstx, uint16_t dsty) { + + const uint64_t colormap[] = { + ((uint64_t) bg_color << 32) | bg_color, + ((uint64_t) bg_color << 32) | fg_color, + ((uint64_t) fg_color << 32) | bg_color, + ((uint64_t) fg_color << 32) | fg_color, + }; + + uint16_t srcy = c * FONTHEIGHT; + + uint64_t* dst_ptr = (uint64_t *)(screen.pix + screen.pitch * dsty + 4 * dstx); + uint16_t dst_skip = screen.pitch - FONTWIDTH * 4; +/// second line to modify + uint64_t* dst_ptr2 = dst_ptr + dst_skip / 8; + + uint64_t* lines_ptr = (uint64_t*)charset->pix + c; + uint64_t lines = *lines_ptr; +#pragma GCC unroll 8 + for(size_t n_line = 8; n_line > 0; n_line--) { +#pragma GCC unroll 3 + + uint64_t lines0 = lines; + + for(size_t n_col2 = FONTWIDTH / 2 ; n_col2 > 0 ; n_col2--) { + uint16_t index = lines0 & 0b11; + + register uint64_t pixs_val = colormap[index]; + + *(dst_ptr++) = pixs_val; + *(dst_ptr2++) = pixs_val; + // x2 + lines0 >>= 2; + } + dst_ptr += dst_skip / 8; + dst_ptr2 += dst_skip / 8; + + + lines >>= 8 - FONTWIDTH; } + } + // else this func wont work -static_assert(FONTWIDTH % 2 == 0); -static_assert(FONTHEIGHT % 4 == 0); +static_assert(FONTWIDTH == 6); +static_assert(FONTWIDTH % 2 == 0); +static_assert(FONTHEIGHT == 8); @@ -474,44 +524,51 @@ Image* loadBMP_24b_1b(const void* rawFile) { if(check_BMP_header(header)) return NULL; - assert(header->bpp == 24); + //assert(header->bpp == 24); 5 -> - uint32_t w = header->w; uint32_t h = header->h; const uint8_t* srcpix = (const uint8_t *)header + header->body_offset; + + kprintf("%x ; %u\n", header, header->body_offset); + + dump(srcpix, 4 * 6 * 20, 4 * 5, DUMP_HEX8); + //asm volatile("hlt"); Image* ret = alloc_image(w,h, 1); + + assert(ret->pitch == 1); + assert(w == 6); + assert(h == 2048); - size_t bpitch = ret->pitch / 2; - uint16_t* pix = ret->pix; + size_t bpitch = ret->pitch; + uint8_t* pix = ret->pix; for(size_t y = 0; y < h; y++) { - uint16_t word = 0; + uint8_t byte = 0; uint16_t _x = 0; for(size_t x = 0; x < w; x++) { - const uint8_t* src_ptr = (srcpix + 3 * (h-1 - y) * w + 3 * (w-1-x)); + const uint8_t* src_ptr = (srcpix + 20 * (h-1 - y) + 3 * (w-1-x)); - word <<= 1; + byte <<= 1; // put 1 iif r channel > 128 - word |= *(src_ptr) >> 7; + byte |= *(src_ptr) >> 7; - if((x % 16 == 0 && x != 0) || x == w-1) { - - pix[_x + y * bpitch] = word; - ++_x; - word = 0; + //if((x % 8 == 0 && x != 0) || x == w-1) { + if(x == w-1) { + //pix[_x + y * bpitch] = byte; } } + pix[y] = byte; } return ret; diff --git a/kernel/video/video.h b/kernel/video/video.h index 173a515..2571189 100644 --- a/kernel/video/video.h +++ b/kernel/video/video.h @@ -72,5 +72,8 @@ Image *loadBMP_24b_1b(const void *rawFile); void blitchar(const struct Image *charset, char c, uint32_t fg_color, uint32_t bg_color, uint16_t dstx, uint16_t dsty); +void blitcharX2(const struct Image *charset, + char c, uint32_t fg_color, uint32_t bg_color, + uint16_t dstx, uint16_t dsty); #endif \ No newline at end of file diff --git a/resources/bmp/charmap.bmp b/resources/bmp/charmap.bmp index 58fb578..612cd4e 100644 Binary files a/resources/bmp/charmap.bmp and b/resources/bmp/charmap.bmp differ diff --git a/resources/bmp/font_converter.py b/resources/bmp/font_converter.py index 2601d88..43af809 100644 --- a/resources/bmp/font_converter.py +++ b/resources/bmp/font_converter.py @@ -1,18 +1,18 @@ -from PIL import Image -import numpy as np - -img = np.array(Image.open('charmap.bmp')) - - -i: int # col -j: int # line -ascii: int = 0 -chars = [] # chars tab - -for i in range(0,256,16): - for j in range(0,192,12): - chars.append(img[i:i+16,j:j+12,:]) - -chars_arr = np.concatenate(chars, axis=0) - -Image.fromarray(chars_arr).save("new.bmp") +from PIL import Image +import numpy as np + +img = np.array(Image.open('charmap.bmp')) + + +i: int # col +j: int # line +ascii: int = 0 +chars = [] # chars tab + +for i in range(0,256,16): + for j in range(0,192,12): + chars.append(img[i:i+16,j:j+12,:]) + +chars_arr = np.concatenate(chars, axis=0) + +Image.fromarray(chars_arr).save("new.bmp")