From 21e7874d9a9729b3ac7520a0a7ef8f7f5bc7601b Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 7 Feb 2021 11:36:04 +0200 Subject: Rewrite makefile --- .gitignore | 7 +- boot.s | 93 ------------ grub.cfg | 6 - grub/grub.cfg | 6 + grub/multiboot2.h | 416 +++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.cc | 75 ---------- kernel/boot.s | 93 ++++++++++++ kernel/kernel.cc | 75 ++++++++++ kernel/makefile | 2 + kernel/vga.cc | 61 ++++++++ kernel/vga.h | 39 +++++ libk/makefile | 15 +- libk/stdlib.h | 2 +- linker.ld | 2 - makefile | 74 +++++----- multiboot2.h | 416 ----------------------------------------------------- toolchain.makefile | 18 +++ vga.cc | 61 -------- vga.h | 39 ----- 19 files changed, 751 insertions(+), 749 deletions(-) delete mode 100644 boot.s delete mode 100644 grub.cfg create mode 100644 grub/grub.cfg create mode 100644 grub/multiboot2.h delete mode 100644 kernel.cc create mode 100644 kernel/boot.s create mode 100644 kernel/kernel.cc create mode 100644 kernel/makefile create mode 100644 kernel/vga.cc create mode 100644 kernel/vga.h delete mode 100644 multiboot2.h create mode 100644 toolchain.makefile delete mode 100644 vga.cc delete mode 100644 vga.h diff --git a/.gitignore b/.gitignore index 8bfb596..ae3d99d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -*.o -*.a -*.bin +glitch.elf +glitch.iso +obj/ +isodir/ diff --git a/boot.s b/boot.s deleted file mode 100644 index bb446d8..0000000 --- a/boot.s +++ /dev/null @@ -1,93 +0,0 @@ -/* - Declare a multiboot header that marks the program as a kernel. - https://www.gnu.org/software/grub/manual/multiboot2/html_node/index.html - - The Multiboot2 header must be contained completely within the first - 32kB of the OS image, and must be 64-bit (8 byte) aligned. -*/ -.set MULTIBOOT_HEADER_MAGIC, 0xe85250d6 # multiboot2 magic number -.set MULTIBOOT_ARCHITECTURE, 0 # protected mode i386 -.set MULTIBOOT_HEADER_TAG_END, 0 - -.section .multiboot -.align 8 -header_start: - .int MULTIBOOT_HEADER_MAGIC - .int MULTIBOOT_ARCHITECTURE - .int header_end - header_start - .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE + (header_end - header_start)) - - # TODO tags go here - - .short MULTIBOOT_HEADER_TAG_END - .short 0 - .int 8 -header_end: - -/* - The stack on x86 must be 16-byte aligned according to the System V ABI - standard and de-facto extensions. The compiler will assume the stack is - properly aligned and failure to align the stack will result in undefined - behavior. -*/ -.section .stack, "aw", @nobits -.align 16 -stack_bottom: - .skip 16 * 1024 -stack_top: - -/* - The linker script specifies _start as the entry point to the kernel and the - bootloader will jump to this position once the kernel has been loaded. -*/ -.section .text -.global _start -.type _start, @function -_start: - mov $stack_top, %esp # point the stack pointer to the stack - - /* - This is a good place to initialize crucial processor state before the - high-level kernel is entered. It's best to minimize the early - environment where crucial features are offline. Note that the - processor is not fully initialized yet: Features such as floating - point instructions and instruction set extensions are not initialized - yet. The GDT should be loaded here. Paging should be enabled here. - C++ features such as global constructors and exceptions will require - runtime support to work as well. - */ - - pushl %ebx # push the pointer to the multiboot structure - pushl %eax # push the multiboot magic value - - /* - Enter the high-level kernel. The ABI requires the stack is 16-byte - aligned at the time of the call instruction (which afterwards pushes - the return pointer of size 4 bytes). The stack was originally 16-byte - aligned above and we've pushed a multiple of 16 bytes to the - stack since (pushed 0 bytes so far), so the alignment has thus been - preserved and the call is well defined. - */ - call kernel_main - - /* - If the system has nothing more to do, put the computer into an - infinite loop. To do that: - 1) Disable interrupts with cli (clear interrupt enable in eflags). - They are already disabled by the bootloader, so this is not needed. - Mind that you might later enable interrupts and return from - kernel_main (which is sort of nonsensical to do). - 2) Wait for the next interrupt to arrive with hlt (halt instruction). - Since they are disabled, this will lock up the computer. - 3) Jump to the hlt instruction if it ever wakes up due to a - non-maskable interrupt occurring or due to system management mode. - */ - cli -hang: hlt - jmp hang - -/* -Set the size of the _start symbol to the current location '.' minus its start. -This is useful when debugging or when you implement call tracing. -*/ -.size _start, . - _start diff --git a/grub.cfg b/grub.cfg deleted file mode 100644 index d41ece4..0000000 --- a/grub.cfg +++ /dev/null @@ -1,6 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "glitch" { - multiboot2 /boot/glitch.elf splash -} diff --git a/grub/grub.cfg b/grub/grub.cfg new file mode 100644 index 0000000..d41ece4 --- /dev/null +++ b/grub/grub.cfg @@ -0,0 +1,6 @@ +set timeout=0 +set default=0 + +menuentry "glitch" { + multiboot2 /boot/glitch.elf splash +} diff --git a/grub/multiboot2.h b/grub/multiboot2.h new file mode 100644 index 0000000..5a3db5a --- /dev/null +++ b/grub/multiboot2.h @@ -0,0 +1,416 @@ +/* multiboot2.h - Multiboot 2 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 32768 +#define MULTIBOOT_HEADER_ALIGN 8 + +/* The magic field should contain this. */ +#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 + +/* This should be in %eax. */ +#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000008 + +/* Flags set in the 'flags' member of the multiboot header. */ + +#define MULTIBOOT_TAG_ALIGN 8 +#define MULTIBOOT_TAG_TYPE_END 0 +#define MULTIBOOT_TAG_TYPE_CMDLINE 1 +#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 +#define MULTIBOOT_TAG_TYPE_MODULE 3 +#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 +#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 +#define MULTIBOOT_TAG_TYPE_MMAP 6 +#define MULTIBOOT_TAG_TYPE_VBE 7 +#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 +#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 +#define MULTIBOOT_TAG_TYPE_APM 10 +#define MULTIBOOT_TAG_TYPE_EFI32 11 +#define MULTIBOOT_TAG_TYPE_EFI64 12 +#define MULTIBOOT_TAG_TYPE_SMBIOS 13 +#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 +#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 +#define MULTIBOOT_TAG_TYPE_NETWORK 16 +#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 +#define MULTIBOOT_TAG_TYPE_EFI_BS 18 +#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 +#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 +#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 + +#define MULTIBOOT_HEADER_TAG_END 0 +#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 +#define MULTIBOOT_HEADER_TAG_ADDRESS 2 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3 +#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 +#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 +#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 +#define MULTIBOOT_HEADER_TAG_EFI_BS 7 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 +#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 + +#define MULTIBOOT_ARCHITECTURE_I386 0 +#define MULTIBOOT_ARCHITECTURE_MIPS32 4 +#define MULTIBOOT_HEADER_TAG_OPTIONAL 1 + +#define MULTIBOOT_LOAD_PREFERENCE_NONE 0 +#define MULTIBOOT_LOAD_PREFERENCE_LOW 1 +#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 + +#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 +#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 + +#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; + + /* ISA */ + multiboot_uint32_t architecture; + + /* Total header length. */ + multiboot_uint32_t header_length; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; +}; + +struct multiboot_header_tag +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_information_request +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t requests[0]; +}; + +struct multiboot_header_tag_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; +}; + +struct multiboot_header_tag_entry_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t entry_addr; +}; + +struct multiboot_header_tag_console_flags +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t console_flags; +}; + +struct multiboot_header_tag_framebuffer +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +struct multiboot_header_tag_module_align +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_relocatable +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t min_addr; + multiboot_uint32_t max_addr; + multiboot_uint32_t align; + multiboot_uint32_t preference; +}; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + 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; + multiboot_uint32_t zero; +}; +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_tag +{ + multiboot_uint32_t type; + multiboot_uint32_t size; +}; + +struct multiboot_tag_string +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + char string[0]; +}; + +struct multiboot_tag_module +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + char cmdline[0]; +}; + +struct multiboot_tag_basic_meminfo +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; +}; + +struct multiboot_tag_bootdev +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t biosdev; + multiboot_uint32_t slice; + multiboot_uint32_t part; +}; + +struct multiboot_tag_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t entry_size; + multiboot_uint32_t entry_version; + struct multiboot_mmap_entry entries[0]; +}; + +struct multiboot_vbe_info_block +{ + multiboot_uint8_t external_specification[512]; +}; + +struct multiboot_vbe_mode_info_block +{ + multiboot_uint8_t external_specification[256]; +}; + +struct multiboot_tag_vbe +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + struct multiboot_vbe_info_block vbe_control_info; + struct multiboot_vbe_mode_info_block vbe_mode_info; +}; + +struct multiboot_tag_framebuffer_common +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + 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; + multiboot_uint16_t reserved; +}; + +struct multiboot_tag_framebuffer +{ + struct multiboot_tag_framebuffer_common common; + + union + { + struct + { + multiboot_uint16_t framebuffer_palette_num_colors; + struct multiboot_color framebuffer_palette[0]; + }; + 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; + }; + }; +}; + +struct multiboot_tag_elf_sections +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t num; + multiboot_uint32_t entsize; + multiboot_uint32_t shndx; + char sections[0]; +}; + +struct multiboot_tag_apm +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + 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; +}; + +struct multiboot_tag_efi32 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_smbios +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t major; + multiboot_uint8_t minor; + multiboot_uint8_t reserved[6]; + multiboot_uint8_t tables[0]; +}; + +struct multiboot_tag_old_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_new_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_network +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t dhcpack[0]; +}; + +struct multiboot_tag_efi_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t descr_size; + multiboot_uint32_t descr_vers; + multiboot_uint8_t efi_mmap[0]; +}; + +struct multiboot_tag_efi32_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_load_base_addr +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t load_base_addr; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/kernel.cc b/kernel.cc deleted file mode 100644 index 3045374..0000000 --- a/kernel.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* Check if the compiler thinks you are targeting the wrong operating system. */ -#if defined(__linux__) -#error "You are not using a cross-compiler" -#endif - -/* This tutorial will only work for the 32-bit ix86 targets. */ -#if !defined(__i386__) -#error "This tutorial needs to be compiled with a ix86-elf compiler" -#endif - -#include -#include -#include "multiboot2.h" -#include "vga.h" - -extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { - VGA terminal; - Console::set(&terminal); - - printk("Hello, kernel World!\n"); - - printk("multiboot magic: ", uhex{mb_magic}, mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " valid" : " invalid", '\n'); - printk("multiboot addr: ", uhex{mb_addr}, !(mb_addr & 7) ? " is aligned" : " is not aligned", '\n'); - - struct multiboot_tag* tag; - const uint32_t size = *(unsigned*)mb_addr; - printk("Announced mbi size ", size, '\n'); - - for (tag = (struct multiboot_tag*)(mb_addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7))) { - switch (tag->type) { - case MULTIBOOT_TAG_TYPE_CMDLINE: { - auto* t = reinterpret_cast(tag); - printk("Command line = [", t->string, "]\n"); - } break; - - case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: { - auto* t = reinterpret_cast(tag); - printk("Boot loader name = [", t->string, "]\n"); - } break; - - case MULTIBOOT_TAG_TYPE_BOOTDEV: { - auto* t = reinterpret_cast(tag); - printk("Boot device ", uhex{t->biosdev}, " slice ", t->slice, " part ", t->part, '\n'); - } break; - - case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: { - auto* t = reinterpret_cast(tag); - printk("mem_lower = ", t->mem_lower, "KB\n", "mem_upper = ", t->mem_upper, "KB\n"); - } break; - - case MULTIBOOT_TAG_TYPE_MMAP: { - auto* t = reinterpret_cast(tag); - multiboot_memory_map_t* mmap; - - printk("memory map\n"); - for (mmap = t->entries; (multiboot_uint8_t*)mmap < (multiboot_uint8_t*)tag + tag->size; - mmap = (multiboot_memory_map_t*)((unsigned long)mmap + ((struct multiboot_tag_mmap*)tag)->entry_size)) { - printk(" base_addr = ", uhex{(unsigned)(mmap->addr >> 32)}, ' ', uhex{(unsigned)(mmap->addr & 0xffffffff)}); - printk(" length = ", (unsigned)(mmap->len >> 32), ' ', (unsigned)(mmap->len & 0xffffffff)); - printk(" type = ", (unsigned)mmap->type, '\n'); - } - } break; - - default: - printk("Tag ", tag->type, ", Size ", tag->size, '\n'); - break; - } // switch(tag->type) - } // for(each tag) - - tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7)); - printk("Total mbi size ", (unsigned)tag - mb_addr, '\n'); - - abort(); -} diff --git a/kernel/boot.s b/kernel/boot.s new file mode 100644 index 0000000..bb446d8 --- /dev/null +++ b/kernel/boot.s @@ -0,0 +1,93 @@ +/* + Declare a multiboot header that marks the program as a kernel. + https://www.gnu.org/software/grub/manual/multiboot2/html_node/index.html + + The Multiboot2 header must be contained completely within the first + 32kB of the OS image, and must be 64-bit (8 byte) aligned. +*/ +.set MULTIBOOT_HEADER_MAGIC, 0xe85250d6 # multiboot2 magic number +.set MULTIBOOT_ARCHITECTURE, 0 # protected mode i386 +.set MULTIBOOT_HEADER_TAG_END, 0 + +.section .multiboot +.align 8 +header_start: + .int MULTIBOOT_HEADER_MAGIC + .int MULTIBOOT_ARCHITECTURE + .int header_end - header_start + .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE + (header_end - header_start)) + + # TODO tags go here + + .short MULTIBOOT_HEADER_TAG_END + .short 0 + .int 8 +header_end: + +/* + The stack on x86 must be 16-byte aligned according to the System V ABI + standard and de-facto extensions. The compiler will assume the stack is + properly aligned and failure to align the stack will result in undefined + behavior. +*/ +.section .stack, "aw", @nobits +.align 16 +stack_bottom: + .skip 16 * 1024 +stack_top: + +/* + The linker script specifies _start as the entry point to the kernel and the + bootloader will jump to this position once the kernel has been loaded. +*/ +.section .text +.global _start +.type _start, @function +_start: + mov $stack_top, %esp # point the stack pointer to the stack + + /* + This is a good place to initialize crucial processor state before the + high-level kernel is entered. It's best to minimize the early + environment where crucial features are offline. Note that the + processor is not fully initialized yet: Features such as floating + point instructions and instruction set extensions are not initialized + yet. The GDT should be loaded here. Paging should be enabled here. + C++ features such as global constructors and exceptions will require + runtime support to work as well. + */ + + pushl %ebx # push the pointer to the multiboot structure + pushl %eax # push the multiboot magic value + + /* + Enter the high-level kernel. The ABI requires the stack is 16-byte + aligned at the time of the call instruction (which afterwards pushes + the return pointer of size 4 bytes). The stack was originally 16-byte + aligned above and we've pushed a multiple of 16 bytes to the + stack since (pushed 0 bytes so far), so the alignment has thus been + preserved and the call is well defined. + */ + call kernel_main + + /* + If the system has nothing more to do, put the computer into an + infinite loop. To do that: + 1) Disable interrupts with cli (clear interrupt enable in eflags). + They are already disabled by the bootloader, so this is not needed. + Mind that you might later enable interrupts and return from + kernel_main (which is sort of nonsensical to do). + 2) Wait for the next interrupt to arrive with hlt (halt instruction). + Since they are disabled, this will lock up the computer. + 3) Jump to the hlt instruction if it ever wakes up due to a + non-maskable interrupt occurring or due to system management mode. + */ + cli +hang: hlt + jmp hang + +/* +Set the size of the _start symbol to the current location '.' minus its start. +This is useful when debugging or when you implement call tracing. +*/ +.size _start, . - _start diff --git a/kernel/kernel.cc b/kernel/kernel.cc new file mode 100644 index 0000000..9ea5c95 --- /dev/null +++ b/kernel/kernel.cc @@ -0,0 +1,75 @@ +/* Check if the compiler thinks you are targeting the wrong operating system. */ +#if defined(__linux__) +#error "You are not using a cross-compiler" +#endif + +/* This tutorial will only work for the 32-bit ix86 targets. */ +#if !defined(__i386__) +#error "This tutorial needs to be compiled with a ix86-elf compiler" +#endif + +#include +#include +#include +#include "vga.h" + +extern "C" void kernel_main(uint32_t mb_magic, uint32_t mb_addr) { + VGA terminal; + Console::set(&terminal); + + printk("Hello, kernel World!\n"); + + printk("multiboot magic: ", uhex{mb_magic}, mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " valid" : " invalid", '\n'); + printk("multiboot addr: ", uhex{mb_addr}, !(mb_addr & 7) ? " is aligned" : " is not aligned", '\n'); + + struct multiboot_tag* tag; + const uint32_t size = *(unsigned*)mb_addr; + printk("Announced mbi size ", size, '\n'); + + for (tag = (struct multiboot_tag*)(mb_addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7))) { + switch (tag->type) { + case MULTIBOOT_TAG_TYPE_CMDLINE: { + auto* t = reinterpret_cast(tag); + printk("Command line = [", t->string, "]\n"); + } break; + + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: { + auto* t = reinterpret_cast(tag); + printk("Boot loader name = [", t->string, "]\n"); + } break; + + case MULTIBOOT_TAG_TYPE_BOOTDEV: { + auto* t = reinterpret_cast(tag); + printk("Boot device ", uhex{t->biosdev}, " slice ", t->slice, " part ", t->part, '\n'); + } break; + + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: { + auto* t = reinterpret_cast(tag); + printk("mem_lower = ", t->mem_lower, "KB\n", "mem_upper = ", t->mem_upper, "KB\n"); + } break; + + case MULTIBOOT_TAG_TYPE_MMAP: { + auto* t = reinterpret_cast(tag); + multiboot_memory_map_t* mmap; + + printk("memory map\n"); + for (mmap = t->entries; (multiboot_uint8_t*)mmap < (multiboot_uint8_t*)tag + tag->size; + mmap = (multiboot_memory_map_t*)((unsigned long)mmap + ((struct multiboot_tag_mmap*)tag)->entry_size)) { + printk(" base_addr = ", uhex{(unsigned)(mmap->addr >> 32)}, ' ', uhex{(unsigned)(mmap->addr & 0xffffffff)}); + printk(" length = ", (unsigned)(mmap->len >> 32), ' ', (unsigned)(mmap->len & 0xffffffff)); + printk(" type = ", (unsigned)mmap->type, '\n'); + } + } break; + + default: + printk("Tag ", tag->type, ", Size ", tag->size, '\n'); + break; + } // switch(tag->type) + } // for(each tag) + + tag = (struct multiboot_tag*)((multiboot_uint8_t*)tag + ((tag->size + 7) & ~7)); + printk("Total mbi size ", (unsigned)tag - mb_addr, '\n'); + + abort(); +} diff --git a/kernel/makefile b/kernel/makefile new file mode 100644 index 0000000..23e3683 --- /dev/null +++ b/kernel/makefile @@ -0,0 +1,2 @@ +AS_OBJ += kernel/boot.o +CXX_OBJ += kernel/kernel.o kernel/vga.o diff --git a/kernel/vga.cc b/kernel/vga.cc new file mode 100644 index 0000000..83d0060 --- /dev/null +++ b/kernel/vga.cc @@ -0,0 +1,61 @@ +#include "vga.h" +#include + +constexpr uint8_t vga_entry_color(VGA::vga_color fg, VGA::vga_color bg) { + return fg | bg << 4; +} + +constexpr uint16_t vga_entry(unsigned char uc, uint8_t color) { + return (uint16_t)uc | (uint16_t)color << 8; +} + +VGA::VGA(vga_color fg, vga_color bg, uint32_t address) { + color = vga_entry_color(fg, bg); + buffer = (uint16_t*)address; + + // clear buffer + for (size_t y = 0; y < max_rows; y++) { + for (size_t x = 0; x < max_columns; x++) { + const size_t index = y * max_columns + x; + buffer[index] = vga_entry(' ', color); + } + } +} + +void VGA::write(char c) { + switch (c) { + case '\n': + column = 0; + ++row; + break; + default: { + const size_t index = row * max_columns + column; + buffer[index] = vga_entry(c, (color == 0) ? this->color : color); + ++column; + } + } + + if (column == max_columns) { + column = 0; + ++row; + } + + if (row == max_rows) { + // scroll up - move rows 1~25 up by one + for (size_t y = 1; y < max_rows; y++) { + const auto prev_y = y - 1; + for (size_t x = 0; x < max_columns; ++x) { + const auto prev = prev_y * max_columns + x; + const auto idx = y * max_columns + x; + buffer[prev] = buffer[idx]; + } + } + --row; + } +} + +void VGA::write(ViewIterator& iter) { + while (iter) { + write(iter.next()); + } +} diff --git a/kernel/vga.h b/kernel/vga.h new file mode 100644 index 0000000..3052dbc --- /dev/null +++ b/kernel/vga.h @@ -0,0 +1,39 @@ +#pragma once +#include + +class VGA : public Console { +public: + /* Hardware text mode color constants. */ + enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, + }; + + VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY, uint32_t address = 0xB8000); + ~VGA() = default; + + void write(char c) override; + void write(ViewIterator& iter) override; + + void set_color(vga_color fg, vga_color bg) { color = (fg | bg << 4); } + +private: + const size_t max_columns = 80, max_rows = 25; + size_t column = 0, row = 0; + uint8_t color; + uint16_t* buffer; +}; diff --git a/libk/makefile b/libk/makefile index ea684ba..0f75e5a 100644 --- a/libk/makefile +++ b/libk/makefile @@ -1,14 +1,3 @@ +CXX_OBJ += libk/string/string.o libk/string/integerview.o libk/stdlib/console.o +CXX_TEST_OBJ += libk/types/test.o libk/string/test.o -CXX_OBJ := string/string.o string/integerview.o stdlib/console.o -CXX_TEST_OBJ := types/test.o string/test.o - -libk.a: $(CXX_OBJ) - $(AR) rcs $@ $(CXX_OBJ) - -test: $(CXX_TEST_OBJ) - -$(CXX_OBJ) $(CXX_TEST_OBJ): %.o : %.cc - $(CXX) -target $(TARGET) $(CXX_FLAGS) -I$(CURDIR) -c $^ -o $@ - -clean: - rm -f libk.a $(CXX_OBJ) $(CXX_TEST_OBJ) diff --git a/libk/stdlib.h b/libk/stdlib.h index e1d3dd2..1b76b67 100644 --- a/libk/stdlib.h +++ b/libk/stdlib.h @@ -35,4 +35,4 @@ void printk(const T& a, const Args&... x) { printk(x...); } -__attribute__((__noreturn__)) void abort(); +extern "C" __attribute__((__noreturn__)) void abort(); diff --git a/linker.ld b/linker.ld index a0bb74f..c6c706e 100644 --- a/linker.ld +++ b/linker.ld @@ -1,8 +1,6 @@ ENTRY(_start) OUTPUT_FORMAT(elf32-i386) -SEARCH_DIR(libk) - /* Tell where the various sections of the object files will be put in the final kernel image. */ SECTIONS diff --git a/makefile b/makefile index 1a50a18..6dd59d7 100644 --- a/makefile +++ b/makefile @@ -3,58 +3,52 @@ # ?= only set if it doesn't have a value # != execute a shell script on the right-hand side and assign its result to the left-hand side -export TARGET := i686-elf +include toolchain.makefile +OBJ_DIR := obj -export AR := llvm-ar - -AS := clang - -LD := ld.lld -LD_FLAGS := -T linker.ld -lk - -export CXX := clang -export CXX_FLAGS := -std=c++20 -ffreestanding -nostdlib -nostdinc -nostdinc++ \ - -fno-exceptions -fno-rtti -Wall -Wextra -O2 -CXX_INCLUDE := $(CURDIR)/libk -CXX_OBJ := kernel.o vga.o +include kernel/makefile +include libk/makefile +AS_OBJ := $(addprefix $(OBJ_DIR)/, $(AS_OBJ)) +CXX_OBJ := $(addprefix $(OBJ_DIR)/, $(CXX_OBJ)) +CXX_TEST_OBJ := $(addprefix $(OBJ_DIR)/, $(CXX_TEST_OBJ)) +CXX_INCLUDE := $(addprefix -I, $(CXX_INCLUDE)) # $@ is target # $< is first dependency # $^ is all dependencies +.PHONY: default clean test check-grub run default: glitch.elf -check-grub: glitch.elf - grub-file --is-x86-multiboot2 glitch.elf - -glitch.elf: boot.o $(CXX_OBJ) libk/libk.a - $(LD) $(LD_FLAGS) -o $@ boot.o $(CXX_OBJ) +glitch.elf: $(AS_OBJ) $(CXX_OBJ) + @echo " LD $@" + @$(LD) $(LD_FLAGS) -o $@ $(AS_OBJ) $(CXX_OBJ) -boot.o: boot.s - $(AS) -target $(TARGET) -nostdlib -Wall -Wextra -c $^ -o $@ +$(AS_OBJ): $(OBJ_DIR)/%.o: %.s + @mkdir -p $(@D) + @echo " AS $^" + @$(AS) -target $(TARGET) -nostdlib -Wall -Wextra -c $^ -o $@ -$(CXX_OBJ): %.o : %.cc - $(CXX) -target $(TARGET) $(CXX_FLAGS) -I$(CXX_INCLUDE) -c $^ -o $@ +$(CXX_OBJ) $(CXX_TEST_OBJ): $(OBJ_DIR)/%.o : %.cc + @mkdir -p $(@D) + @echo " CXX $^" + @$(CXX) -target $(TARGET) $(CXX_FLAGS) $(CXX_INCLUDE) -c $^ -o $@ -libk/libk.a: - $(MAKE) -C libk libk.a - -libk/test: - $(MAKE) -C libk test -test: libk/test +clean: + rm -rf $(AS_OBJ) $(CXX_OBJ) $(CXX_TEST_OBJ) glitch.elf isodir -iso: glitch.elf - mkdir -p isodir/boot/grub - cp glitch.elf isodir/boot/glitch.elf - cp grub.cfg isodir/boot/grub/grub.cfg - grub-mkrescue -o myos.iso isodir +# testing +test: $(CXX_TEST_OBJ) check-grub +check-grub: glitch.elf + grub-file --is-x86-multiboot2 glitch.elf -run: iso - qemu-system-i386 -cdrom myos.iso +# disk image +glitch.iso: glitch.elf grub/grub.cfg + @mkdir -p isodir/boot/grub + @cp glitch.elf isodir/boot/glitch.elf + @cp grub/grub.cfg isodir/boot/grub/grub.cfg + @$(BOOT) -o $@ isodir -clean: - rm -f boot.o $(CXX_OBJ) glitch.elf - $(MAKE) -C libk clean +run: glitch.iso + @$(EMU) $< -clean-iso: - rm -rf isodir diff --git a/multiboot2.h b/multiboot2.h deleted file mode 100644 index 5a3db5a..0000000 --- a/multiboot2.h +++ /dev/null @@ -1,416 +0,0 @@ -/* multiboot2.h - Multiboot 2 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 32768 -#define MULTIBOOT_HEADER_ALIGN 8 - -/* The magic field should contain this. */ -#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 - -/* This should be in %eax. */ -#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 - -/* Alignment of multiboot modules. */ -#define MULTIBOOT_MOD_ALIGN 0x00001000 - -/* Alignment of the multiboot info structure. */ -#define MULTIBOOT_INFO_ALIGN 0x00000008 - -/* Flags set in the 'flags' member of the multiboot header. */ - -#define MULTIBOOT_TAG_ALIGN 8 -#define MULTIBOOT_TAG_TYPE_END 0 -#define MULTIBOOT_TAG_TYPE_CMDLINE 1 -#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 -#define MULTIBOOT_TAG_TYPE_MODULE 3 -#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 -#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 -#define MULTIBOOT_TAG_TYPE_MMAP 6 -#define MULTIBOOT_TAG_TYPE_VBE 7 -#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 -#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 -#define MULTIBOOT_TAG_TYPE_APM 10 -#define MULTIBOOT_TAG_TYPE_EFI32 11 -#define MULTIBOOT_TAG_TYPE_EFI64 12 -#define MULTIBOOT_TAG_TYPE_SMBIOS 13 -#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 -#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 -#define MULTIBOOT_TAG_TYPE_NETWORK 16 -#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 -#define MULTIBOOT_TAG_TYPE_EFI_BS 18 -#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 -#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 -#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 - -#define MULTIBOOT_HEADER_TAG_END 0 -#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 -#define MULTIBOOT_HEADER_TAG_ADDRESS 2 -#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3 -#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 -#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 -#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 -#define MULTIBOOT_HEADER_TAG_EFI_BS 7 -#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 -#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 - -#define MULTIBOOT_ARCHITECTURE_I386 0 -#define MULTIBOOT_ARCHITECTURE_MIPS32 4 -#define MULTIBOOT_HEADER_TAG_OPTIONAL 1 - -#define MULTIBOOT_LOAD_PREFERENCE_NONE 0 -#define MULTIBOOT_LOAD_PREFERENCE_LOW 1 -#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 - -#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 -#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 - -#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; - - /* ISA */ - multiboot_uint32_t architecture; - - /* Total header length. */ - multiboot_uint32_t header_length; - - /* The above fields plus this one must equal 0 mod 2^32. */ - multiboot_uint32_t checksum; -}; - -struct multiboot_header_tag -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; -}; - -struct multiboot_header_tag_information_request -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t requests[0]; -}; - -struct multiboot_header_tag_address -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t header_addr; - multiboot_uint32_t load_addr; - multiboot_uint32_t load_end_addr; - multiboot_uint32_t bss_end_addr; -}; - -struct multiboot_header_tag_entry_address -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t entry_addr; -}; - -struct multiboot_header_tag_console_flags -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t console_flags; -}; - -struct multiboot_header_tag_framebuffer -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t width; - multiboot_uint32_t height; - multiboot_uint32_t depth; -}; - -struct multiboot_header_tag_module_align -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; -}; - -struct multiboot_header_tag_relocatable -{ - multiboot_uint16_t type; - multiboot_uint16_t flags; - multiboot_uint32_t size; - multiboot_uint32_t min_addr; - multiboot_uint32_t max_addr; - multiboot_uint32_t align; - multiboot_uint32_t preference; -}; - -struct multiboot_color -{ - multiboot_uint8_t red; - multiboot_uint8_t green; - multiboot_uint8_t blue; -}; - -struct multiboot_mmap_entry -{ - 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; - multiboot_uint32_t zero; -}; -typedef struct multiboot_mmap_entry multiboot_memory_map_t; - -struct multiboot_tag -{ - multiboot_uint32_t type; - multiboot_uint32_t size; -}; - -struct multiboot_tag_string -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - char string[0]; -}; - -struct multiboot_tag_module -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t mod_start; - multiboot_uint32_t mod_end; - char cmdline[0]; -}; - -struct multiboot_tag_basic_meminfo -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t mem_lower; - multiboot_uint32_t mem_upper; -}; - -struct multiboot_tag_bootdev -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t biosdev; - multiboot_uint32_t slice; - multiboot_uint32_t part; -}; - -struct multiboot_tag_mmap -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t entry_size; - multiboot_uint32_t entry_version; - struct multiboot_mmap_entry entries[0]; -}; - -struct multiboot_vbe_info_block -{ - multiboot_uint8_t external_specification[512]; -}; - -struct multiboot_vbe_mode_info_block -{ - multiboot_uint8_t external_specification[256]; -}; - -struct multiboot_tag_vbe -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - - multiboot_uint16_t vbe_mode; - multiboot_uint16_t vbe_interface_seg; - multiboot_uint16_t vbe_interface_off; - multiboot_uint16_t vbe_interface_len; - - struct multiboot_vbe_info_block vbe_control_info; - struct multiboot_vbe_mode_info_block vbe_mode_info; -}; - -struct multiboot_tag_framebuffer_common -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - - 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; - multiboot_uint16_t reserved; -}; - -struct multiboot_tag_framebuffer -{ - struct multiboot_tag_framebuffer_common common; - - union - { - struct - { - multiboot_uint16_t framebuffer_palette_num_colors; - struct multiboot_color framebuffer_palette[0]; - }; - 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; - }; - }; -}; - -struct multiboot_tag_elf_sections -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t num; - multiboot_uint32_t entsize; - multiboot_uint32_t shndx; - char sections[0]; -}; - -struct multiboot_tag_apm -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - 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; -}; - -struct multiboot_tag_efi32 -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t pointer; -}; - -struct multiboot_tag_efi64 -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint64_t pointer; -}; - -struct multiboot_tag_smbios -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint8_t major; - multiboot_uint8_t minor; - multiboot_uint8_t reserved[6]; - multiboot_uint8_t tables[0]; -}; - -struct multiboot_tag_old_acpi -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint8_t rsdp[0]; -}; - -struct multiboot_tag_new_acpi -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint8_t rsdp[0]; -}; - -struct multiboot_tag_network -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint8_t dhcpack[0]; -}; - -struct multiboot_tag_efi_mmap -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t descr_size; - multiboot_uint32_t descr_vers; - multiboot_uint8_t efi_mmap[0]; -}; - -struct multiboot_tag_efi32_ih -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t pointer; -}; - -struct multiboot_tag_efi64_ih -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint64_t pointer; -}; - -struct multiboot_tag_load_base_addr -{ - multiboot_uint32_t type; - multiboot_uint32_t size; - multiboot_uint32_t load_base_addr; -}; - -#endif /* ! ASM_FILE */ - -#endif /* ! MULTIBOOT_HEADER */ diff --git a/toolchain.makefile b/toolchain.makefile new file mode 100644 index 0000000..f5fb1b1 --- /dev/null +++ b/toolchain.makefile @@ -0,0 +1,18 @@ +# Toolchain +TARGET := i686-elf + +AS := clang +AS_FLAGS := + +LD := ld.lld +LD_FLAGS := -T linker.ld + +CXX := clang++ +CXX_FLAGS := -std=c++20 -ffreestanding -nostdlib -nostdinc -nostdinc++ \ + -fno-exceptions -fno-rtti -Wall -Wextra -O2 +CXX_INCLUDE := $(CURDIR)/libk $(CURDIR)/grub + +# +BOOT := grub-mkrescue +EMU := qemu-system-i386 -cdrom + diff --git a/vga.cc b/vga.cc deleted file mode 100644 index 83d0060..0000000 --- a/vga.cc +++ /dev/null @@ -1,61 +0,0 @@ -#include "vga.h" -#include - -constexpr uint8_t vga_entry_color(VGA::vga_color fg, VGA::vga_color bg) { - return fg | bg << 4; -} - -constexpr uint16_t vga_entry(unsigned char uc, uint8_t color) { - return (uint16_t)uc | (uint16_t)color << 8; -} - -VGA::VGA(vga_color fg, vga_color bg, uint32_t address) { - color = vga_entry_color(fg, bg); - buffer = (uint16_t*)address; - - // clear buffer - for (size_t y = 0; y < max_rows; y++) { - for (size_t x = 0; x < max_columns; x++) { - const size_t index = y * max_columns + x; - buffer[index] = vga_entry(' ', color); - } - } -} - -void VGA::write(char c) { - switch (c) { - case '\n': - column = 0; - ++row; - break; - default: { - const size_t index = row * max_columns + column; - buffer[index] = vga_entry(c, (color == 0) ? this->color : color); - ++column; - } - } - - if (column == max_columns) { - column = 0; - ++row; - } - - if (row == max_rows) { - // scroll up - move rows 1~25 up by one - for (size_t y = 1; y < max_rows; y++) { - const auto prev_y = y - 1; - for (size_t x = 0; x < max_columns; ++x) { - const auto prev = prev_y * max_columns + x; - const auto idx = y * max_columns + x; - buffer[prev] = buffer[idx]; - } - } - --row; - } -} - -void VGA::write(ViewIterator& iter) { - while (iter) { - write(iter.next()); - } -} diff --git a/vga.h b/vga.h deleted file mode 100644 index 3052dbc..0000000 --- a/vga.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include - -class VGA : public Console { -public: - /* Hardware text mode color constants. */ - enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, - }; - - VGA(vga_color fg = VGA_COLOR_BLACK, vga_color bg = VGA_COLOR_LIGHT_GREY, uint32_t address = 0xB8000); - ~VGA() = default; - - void write(char c) override; - void write(ViewIterator& iter) override; - - void set_color(vga_color fg, vga_color bg) { color = (fg | bg << 4); } - -private: - const size_t max_columns = 80, max_rows = 25; - size_t column = 0, row = 0; - uint8_t color; - uint16_t* buffer; -}; -- cgit v1.2.1