diff --git a/.gitignore b/.gitignore index 90abd90..e2eab30 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,5 @@ config.h gen*.h build/ __pycache__/ -kernel *.iso +iso/kernel diff --git a/kernel/arch/x86_64/flags.cmake b/kernel/arch/x86_64/flags.cmake new file mode 100644 index 0000000..263666d --- /dev/null +++ b/kernel/arch/x86_64/flags.cmake @@ -0,0 +1,3 @@ +SET(ISA_C_FLAGS "-m64 -I../../kernel/arch/x86_64/include/") +SET(ISA_CXX_FLAGS "${ISA_C_FLAGS}") +SET(ISA_ASM_FLAGS "${ISA_ASM_FLAGS}") diff --git a/kernel/arch/x86_64/pc/flags.cmake b/kernel/arch/x86_64/pc/flags.cmake new file mode 100644 index 0000000..f6c0ea1 --- /dev/null +++ b/kernel/arch/x86_64/pc/flags.cmake @@ -0,0 +1,3 @@ +SET(PLATFORM_C_FLAGS "-I../../kernel/arch/x86_64/pc/include") +SET(PLATFORM_CXX_FLAGS "${PLATFORM_C_FLAGS}") +SET(PLATFORM_ASM_FLAGS "${PLATFORM_C_FLAGS}") diff --git a/kernel/arch/x86_64/pc/include/multiboot.h b/kernel/arch/x86_64/pc/include/multiboot.h new file mode 100644 index 0000000..2e70d58 --- /dev/null +++ b/kernel/arch/x86_64/pc/include/multiboot.h @@ -0,0 +1,264 @@ +/* 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; +} GRUB_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 { + grub_uint16_t version; + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/kernel/arch/x86_64/pc/layout.ld b/kernel/arch/x86_64/pc/layout.ld new file mode 100644 index 0000000..35b97b7 --- /dev/null +++ b/kernel/arch/x86_64/pc/layout.ld @@ -0,0 +1,36 @@ +ENTRY(_start) +SECTIONS { + . = 0x200000; + kernel_start = .; + .text : { + KEEP(*(.text.boot)); + *(.text) + } + .data : { + start_ctors = .; + KEEP(*(.init_array)); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*))); + KEEP(*(.ctors)); + end_ctors = .; + start_dtors = .; + KEEP(*(.fini_array)); + KEEP(*(.fini_array.*)); + KEEP(*(.dtors)); + end_dtors = .; + start_eh_frame = .; + KEEP(*(.eh_frame)); + KEEP(*(.eh_frame.*)); + QUAD(0); + KEEP(*(.gcc_except_table)); + KEEP(*(.gcc_except_table.*)); + *(.data) + } + .rodata : { + *(.rodata) + } + .bss : { + *(.bss) + *(COMMON) + } + kernel_end = .; +} diff --git a/kernel/arch/x86_64/pc/start.cpp b/kernel/arch/x86_64/pc/start.cpp new file mode 100644 index 0000000..524c154 --- /dev/null +++ b/kernel/arch/x86_64/pc/start.cpp @@ -0,0 +1,9 @@ +#include "../../../hw/pc/cgaterm/cgaterm.hpp" +#include +CGATerm term; +void main(); +extern "C" void start() { main(); } +void drivers_init() { + setMainTTY(&term); + --term; +} diff --git a/kernel/arch/x86_64/pc/start.s b/kernel/arch/x86_64/pc/start.s new file mode 100644 index 0000000..2b45210 --- /dev/null +++ b/kernel/arch/x86_64/pc/start.s @@ -0,0 +1,173 @@ +#define ASM_FILE 1 +#include +#include +.code32 +.section .text.boot +.global _start +_start: + jmp _start2 +.align MULTIBOOT_HEADER_ALIGN +.int MULTIBOOT_HEADER_MAGIC +.int 0x0 +.int -(MULTIBOOT_HEADER_MAGIC) +.align MULTIBOOT_HEADER_ALIGN +.extern start +_start2: + mov $mb_ptr, %edi + stosl + mov %ebx, %eax + stosl // Store mb stuff + +#ifdef ENABLE_FPU + finit //Enable FPU +#endif +#ifdef ENABLE_SSE + //No check for SSE as SSE2+ is always present on x86_64 + mov %cr0, %eax + and $0xFFFB, %ax + or $0x2, %ax + mov %eax, %cr0 + mov %cr4, %eax + or $3<<9, %ax + mov %eax, %cr4 +#endif + mov $kernel_stack, %esp + mov $0x80000001, %eax + cpuid + and $0x20000000, %edx //Check if long mode is supported + jz x86_64_err + jmp x86_64_OK +x86_64_err: + cli + hlt + jmp x86_64_err +x86_64_OK: + //Assume PAE is supported + mov $pmfill, %esi + mov $pagemapL4, %edi + movsl + movsl + mov $pagedirPT, %edi + mov $0x87, %eax + xor %ebx, %ebx + mov $1023, %ecx +.ptloop: + stosl + xchg %eax, %ebx + stosl + xchg %eax, %ebx + add $0x40000000, %eax + jnc .ptloop_nc + inc %ebx +.ptloop_nc: + loop .ptloop + mov %cr4, %eax + or $0x20, %eax + mov %eax, %cr4 //Activate PAE + mov $0xC0000080, %ecx + rdmsr + or $0x00000100, %eax + wrmsr //Activate x86_64 + mov $pagemapL4, %eax + mov %eax, %cr3 //Load page table + mov %cr0, %eax + bswap %eax + or $0x80, %eax + bswap %eax + mov %eax, %cr0 //Activate paging + lgdt gdtr + mov $0x30, %ax + ljmp $0x28, $_start3 //Jump into long mode +.code64 +_start3: + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss //Load 64-bit data + mov $mb_ptr, %rsi + lodsl + mov %rax, %rdi + lodsl + mov %rax, %rsi + call start +_stop: + cli + hlt + jmp _stop + + +.section .data +gdtr: + .word 9 * 8 + .int gdt +gdt: + .quad 0 //NULL + //32-bit kernel code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0x9A + .byte 0xCF + .byte 0x00 + //32-bit kernel code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0x92 + .byte 0xCF + .byte 00 + //32-bit user code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0xFA + .byte 0xCF + .byte 0x00 + //32-bit user data + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0xF2 + .byte 0xCF + .byte 00 + //64-bit kernel code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0x9B + .byte 0xAF + .byte 0x00 + //64-bit kernel code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0x93 + .byte 0xCF + .byte 00 + //64-bit user code + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0xFB + .byte 0xAF + .byte 0x00 + //64-bit user data + .word 0xFFFF + .word 0x0000 + .byte 0x00 + .byte 0xF3 + .byte 0xCF + .byte 00 +pmfill: + .int pagedirPT + 0x7 + .int 0 +.section .bss +mb_ptr: +.space 16384 +kernel_stack: + .align 4096 +pagemapL4: + .space 4096 +pagedirPT: + .space 4096 diff --git a/kernel/hw/framebuffer/framebuffer.cpp b/kernel/hw/framebuffer/framebuffer.cpp new file mode 100644 index 0000000..84dfe1e --- /dev/null +++ b/kernel/hw/framebuffer/framebuffer.cpp @@ -0,0 +1,40 @@ +#include "framebuffer.hpp" +#include +auto Framebuffer::plotPixel(int x, int y, int col) -> void {} +auto Framebuffer::plotChar(int x, int y, int c) -> void { + if (c > 65535) return; + int width = font_widths[c]; + if (width == 16) this->x++; + if (!width) return; + int color; + for (int px = x * 8; px < (x * 8) + width; x++) + for (int py = y * 16; py < (y * 16) + 16; y++) { + color = rgbColor; + if (!useRGB) { + switch (curColor) { + case Color::BLACK: color = 0x000000; break; + case Color::BLUE: color = 0x0000AA; break; + case Color::GREEN: color = 0x00AA00; break; + case Color::CYAN: color = 0x00AAAA; break; + case Color::RED: color = 0xAA0000; break; + case Color::MAGENTA: color = 0xAA00AA; break; + case Color::BROWN: color = 0xAA5500; break; + case Color::LIGHT_GRAY: color = 0xAAAAAA; break; + case Color::GRAY: color = 0x555555; break; + case Color::LIGHT_BLUE: color = 0x5555FF; break; + case Color::LIGHT_GREEN: color = 0x55FF55; break; + case Color::LIGHT_CYAN: color = 0x55FFFF; break; + case Color::LIGHT_RED: color = 0xFF5555; break; + case Color::LIGHT_MAGENTA: color = 0xFF55FF; break; + case Color::YELLOW: color = 0xFFFF55; break; + case Color::WHITE: color = 0xFFFFFF; break; + } + rgbColor = color; + useRGB = true; + } + plotPixel(px, py, color); + } +} +Framebuffer::Framebuffer(int height, int width) : TTY(height, width) {} +Framebuffer::~Framebuffer() {} +auto Framebuffer::rgbSupport() -> bool { return true; } diff --git a/kernel/hw/framebuffer/framebuffer.hpp b/kernel/hw/framebuffer/framebuffer.hpp new file mode 100644 index 0000000..8a91ca2 --- /dev/null +++ b/kernel/hw/framebuffer/framebuffer.hpp @@ -0,0 +1,12 @@ +#pragma once +#include +class Framebuffer : public TTY { + protected: + virtual auto plotPixel(int x, int y, int col) -> void; + virtual auto plotChar(int x, int y, int c) -> void; + + public: + Framebuffer(int height, int width); + virtual ~Framebuffer(); + virtual auto rgbSupport() -> bool; +}; diff --git a/kernel/hw/pc/vesafb/vesafb.cpp b/kernel/hw/pc/vesafb/vesafb.cpp new file mode 100644 index 0000000..15ee25e --- /dev/null +++ b/kernel/hw/pc/vesafb/vesafb.cpp @@ -0,0 +1,9 @@ +#include "vesafb.hpp" +#include +auto VESAfb::plotPixel(int x, int y, int col) -> void { + int *lfb = (int *)((uintptr_t)(mb_info->framebuffer_addr)); + lfb[y * mb_info->framebuffer_pitch + x] = col; +} +VESAfb::VESAfb(multiboot_info_t *mb_info) + : mb_info(mb_info), Framebuffer(mb_info->framebuffer_width / 8, mb_info->framebuffer_height / 16) {} +VESAfb::~VESAfb() {} diff --git a/kernel/hw/pc/vesafb/vesafb.hpp b/kernel/hw/pc/vesafb/vesafb.hpp new file mode 100644 index 0000000..04293d8 --- /dev/null +++ b/kernel/hw/pc/vesafb/vesafb.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "../../framebuffer/framebuffer.hpp" +#include +class VESAfb : public Framebuffer { + protected: + multiboot_info_t *mb_info; + virtual auto plotPixel(int x, int y, int col) -> void; + + public: + VESAfb(multiboot_info_t *mb_info); + virtual ~VESAfb(); +};