From b7b97d32cbb6fbc928078ebe3a00714cbbebea86 Mon Sep 17 00:00:00 2001 From: EmulatedSeasons <89668582+EmulatedSeasons@users.noreply.github.com> Date: Fri, 29 Dec 2023 01:38:34 -0500 Subject: got grub memory map and added to kernel printf --- .gitignore | 2 + bochsrc.bxrc | 2 +- kernel/arch/i386/boot.asm | 6 + kernel/arch/i386/multiboot.cpp | 29 +++++ kernel/arch/i386/multiboot.h | 274 +++++++++++++++++++++++++++++++++++++++++ kernel/arch/i386/tmtty.cpp | 34 ++--- kernel/kernel.cpp | 9 +- kernel/makefile | 13 +- kernel/std/printf.c | 124 ++++++++++++++++++- run-qemu.bat | 2 +- 10 files changed, 463 insertions(+), 32 deletions(-) create mode 100644 kernel/arch/i386/multiboot.cpp create mode 100644 kernel/arch/i386/multiboot.h diff --git a/.gitignore b/.gitignore index 2c19c1b..b20cc07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ # directories that have to exist but shouldn't be added to git isodir/ sysroot/ +build/ # compiled files files *.bin *.iso *.o +*.d # i have no idea what this is for bx_enh_dbg.ini diff --git a/bochsrc.bxrc b/bochsrc.bxrc index 5dae11f..6bc50da 100644 --- a/bochsrc.bxrc +++ b/bochsrc.bxrc @@ -3,7 +3,7 @@ boot: cdrom megs: 256 -#display_library: win32, options="gui_debug" +display_library: win32, options="gui_debug" vga: extension=vbe diff --git a/kernel/arch/i386/boot.asm b/kernel/arch/i386/boot.asm index a2dccce..b5dfe11 100644 --- a/kernel/arch/i386/boot.asm +++ b/kernel/arch/i386/boot.asm @@ -30,6 +30,12 @@ _start: ; setup stack mov esp, stack_top + ; get multiboot header data (for memory map) + extern multiboot_main + push eax + push ebx + call multiboot_main + extern _init call _init diff --git a/kernel/arch/i386/multiboot.cpp b/kernel/arch/i386/multiboot.cpp new file mode 100644 index 0000000..4ce94df --- /dev/null +++ b/kernel/arch/i386/multiboot.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include "multiboot.h" +#include + +// gets the memory map and stuff +extern "C" void multiboot_main(multiboot_info_t* mbd, uint32_t magic) { + terminal_initialize(); + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printf("Invalid multiboot magic number\n"); + abort(); + } + + // checks bit 6 to see if there's a valid memory map + if (!(mbd->flags >> 6 & 0x1)) { + printf("Invalid GRUB memory map\n"); + abort(); + } + + // loop through memory map and display the values + for (int i = 0; i < mbd->mmap_length; i += sizeof(multiboot_memory_map_t)) { + multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(mbd->mmap_addr + i); + + printf("Start Addr: 0x%lx | Length: 0x%lx | Size: 0x%x | Type: %d\n", + mmmt->addr, mmmt->len, mmmt->size, mmmt->type); + //printf("%lx,%x,%x,%d\n", mmmt->size, mmmt->size, mmmt->size, mmmt->size); + } +} \ No newline at end of file diff --git a/kernel/arch/i386/multiboot.h b/kernel/arch/i386/multiboot.h new file mode 100644 index 0000000..0951ebe --- /dev/null +++ b/kernel/arch/i386/multiboot.h @@ -0,0 +1,274 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the ’flags’ member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the ’flags’ member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +/* APM BIOS info. */ +struct multiboot_apm_info +{ + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ \ No newline at end of file diff --git a/kernel/arch/i386/tmtty.cpp b/kernel/arch/i386/tmtty.cpp index 06eb578..d4dc772 100644 --- a/kernel/arch/i386/tmtty.cpp +++ b/kernel/arch/i386/tmtty.cpp @@ -10,17 +10,16 @@ static const size_t VGA_WIDTH = 80; static const size_t VGA_HEIGHT = 25; +static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000; size_t terminal_row; size_t terminal_column; uint8_t terminal_color; uint16_t* terminal_buffer; -void terminal_initialize(void) { +void terminal_clear(void) { terminal_row = 0; terminal_column = 0; - terminal_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK); - terminal_buffer = (uint16_t*) 0xB8000; for (size_t y = 0; y < VGA_HEIGHT; y++) { for (size_t x = 0; x < VGA_WIDTH; x++) { const size_t i = y * VGA_WIDTH + x; @@ -29,15 +28,10 @@ void terminal_initialize(void) { } } -void terminal_clear(void) { - terminal_row = 0; - terminal_column = 0; - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - const size_t i = y * VGA_WIDTH + x; - terminal_buffer[i] = vga_entry(' ', terminal_color); - } - } +void terminal_initialize(void) { + terminal_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK); + terminal_buffer = VGA_MEMORY; + terminal_clear(); } void terminal_setcolor(uint8_t color) { @@ -49,18 +43,26 @@ void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) { terminal_buffer[i] = vga_entry(c, color); } +void terminal_scroll() { + memmove(VGA_MEMORY, (VGA_MEMORY + VGA_WIDTH), (VGA_HEIGHT * VGA_WIDTH) - VGA_WIDTH); + memset(VGA_MEMORY + (VGA_WIDTH * VGA_HEIGHT) - VGA_WIDTH, 0x0, VGA_WIDTH * 2); + --terminal_row; +} + void terminal_putchar(char c) { - if (c == '\n') { + unsigned char uc = c; + if (uc == '\n') { terminal_column = 0; - ++terminal_row; + if (terminal_row++ == VGA_HEIGHT) + terminal_scroll(); return; } - terminal_putentryat(c, terminal_color, terminal_column, terminal_row); + terminal_putentryat(uc, terminal_color, terminal_column, terminal_row); if (++terminal_column == VGA_WIDTH) { terminal_column = 0; if (++terminal_row == VGA_HEIGHT) { - terminal_row = 0; + terminal_scroll(); } } } diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index c22647b..579e642 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -18,12 +18,13 @@ extern "C" void kernel_main(void) { // Initialize terminal - terminal_initialize(); + //terminal_initialize(); - initialize_ps2_controller(); - keyboard_init(); + //initialize_ps2_controller(); + //keyboard_init(); printf("Hello world!\n"); - printf("among"); + printf("among\n"); printf("balls\n"); + printf("a%db", 1); } \ No newline at end of file diff --git a/kernel/makefile b/kernel/makefile index c1aa57f..6c563b8 100644 --- a/kernel/makefile +++ b/kernel/makefile @@ -44,6 +44,9 @@ OBJECTS := $(patsubst %.c,%.o,$(C_SOURCES)) OBJECTS += $(patsubst %.cpp,%.o,$(CPP_SOURCES)) OBJECTS += $(patsubst %.asm,%.o,$(ASMFILES)) +DEPFILES := $(patsubst %.c,%.d,$(SRCFILES)) +DEPFILES += $(patsubst %.cpp,%.d,$(SRCFILES)) + LINKLST := crti.o LINKLST += $(CRTBEGIN) LINKLST += $(OBJECTS) @@ -51,6 +54,8 @@ LINKLST += $(LIBS) LINKLST += $(CRTEND) LINKLST += crtn.o +-include $(DEPFILES) + .PHONY: all crt clean all: crti.o crtn.o kernel.bin @@ -61,11 +66,11 @@ kernel.bin: ${OBJECTS} %.o: %.cpp $(info [INFO] Compiling $<) - $(CXX) ${CXXFLAGS} -c $< -o $@ + $(CXX) ${CXXFLAGS} -MMD -MP -c $< -o $@ %.o: %.c $(info [INFO] Compiling $<) - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ %.o: %.asm $(info [INFO] Assembling $<) @@ -78,8 +83,8 @@ crtn.o: $(NASM) arch/$(ARCH)/crtn.asm -felf32 -o $@ install-headers: - cp -r --preserve=timestamps include $(SYSROOT)/usr/include + cp -r --preserve=timestamps include/. $(SYSROOT)/usr/include clean: $(info [INFO] Cleaning) - rm ${OBJECTS} crti.o crtn.o \ No newline at end of file + rm ${OBJECTS} ${DEPFILES} crti.o crtn.o \ No newline at end of file diff --git a/kernel/std/printf.c b/kernel/std/printf.c index c383cad..fe45892 100644 --- a/kernel/std/printf.c +++ b/kernel/std/printf.c @@ -3,7 +3,8 @@ #include #include #include - +#include + static bool print(const char* data, size_t length) { const unsigned char* bytes = (const unsigned char*) data; for (size_t i = 0; i < length; i++) @@ -11,13 +12,82 @@ static bool print(const char* data, size_t length) { return false; return true; } - + +// for %d and %x. +static const char* itoa(unsigned int num, char* str, unsigned int base) { + asm("xchgw %bx, %bx"); + int cou = 0; // nt + + if (num == 0) { // 0 + str[cou] = '0'; + str[++cou] = '\0'; + return str; + } + + while (num) + { + unsigned int rem = (num % base); + // brings the number up to ascii 0 + the digit + if (rem > 9) { + str[cou] = rem + '7'; // 7 = 55 + 10(A) = 65 + } else { + str[cou] = rem + '0'; + } + num /= base; + ++cou; + } + + // reverse the string + for (int i = 0; i < cou; i++) { + char temp = str[i]; + str[i] = str[cou - i - 1]; + str[cou - 1] = temp; + } + + str[cou] = '\0'; + return str; +} + +// have no idea if there's a better way to do this. for %lx +static const char* itoa_u64(unsigned long long num, char* str, int base) { + int cou = 0; // nt + + if (num == 0) { // 0 + str[cou] = '0'; + str[++cou] = '\0'; + return str; + } + + while (num) + { + unsigned long long rem = num % base; + // brings the number up to ascii 0 + the digit + if (rem > 9) { + str[cou] = rem + '7'; // 7 = 55 + 10(A) = 65 + } else { + str[cou] = rem + '0'; + } + num /= base; + ++cou; + } + + // reverse the string + for (int i = 0; i < cou; i++) { + char temp = str[i]; + str[i] = str[cou - i - 1]; + str[cou - 1] = temp; + } + + str[cou] = '\0'; + return str; +} + int printf(const char* restrict format, ...) { va_list parameters; va_start(parameters, format); int written = 0; - + while (*format != '\0') { size_t maxrem = INT_MAX - written; @@ -37,9 +107,9 @@ int printf(const char* restrict format, ...) { written += amount; continue; } - + const char* format_begun_at = format++; - + if (*format == 'c') { format++; char c = (char) va_arg(parameters, int /* char promotes to int */); @@ -50,6 +120,48 @@ int printf(const char* restrict format, ...) { if (!print(&c, sizeof(c))) return -1; written++; + } else if (*format == 'd') { + format++; + char str[20]; // probably a long enough buffer + unsigned int d = va_arg(parameters, unsigned int); + itoa(d, str, 10); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else if (*format == 'x') { + format++; + char str[20]; // probably a long enough buffer + unsigned int d = va_arg(parameters, unsigned int); + itoa(d, str, 16); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else if (*format == 'l') { // for %lx and others that start with l + format++; + if (*format == 'x') { + format++; + char str[20]; // probably a long enough buffer + unsigned long long d = va_arg(parameters, unsigned long long); + itoa_u64(d, str, 16); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } } else if (*format == 's') { format++; const char* str = va_arg(parameters, const char*); @@ -74,7 +186,7 @@ int printf(const char* restrict format, ...) { format += len; } } - + va_end(parameters); return written; } \ No newline at end of file diff --git a/run-qemu.bat b/run-qemu.bat index bd1701d..19a5ae8 100644 --- a/run-qemu.bat +++ b/run-qemu.bat @@ -1,2 +1,2 @@ @echo off -qemu-system-i386 emuos.iso \ No newline at end of file +qemu-system-i386 -m 128 -drive format=raw,media=cdrom,file=emuos.iso \ No newline at end of file -- cgit v1.2.3-70-g09d2