diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/CMakeLists.txt | 2 | ||||
-rw-r--r-- | kernel/boot/init/boot.s | 4 | ||||
-rw-r--r-- | kernel/include/common.h | 24 | ||||
-rw-r--r-- | kernel/include/mm/memory_map.h | 26 | ||||
-rw-r--r-- | kernel/include/mm/multiboot.h | 266 | ||||
-rw-r--r-- | kernel/kernel/kernel.c | 19 | ||||
-rw-r--r-- | kernel/mm/memory_map.c | 78 |
7 files changed, 415 insertions, 4 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 0037115..a4e88a6 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -11,6 +11,8 @@ set(SRC kernel/stack_smashing_protector.c kernel/io/io.c + mm/memory_map.c + drivers/vga_text_buffer/vga_text_buffer.c drivers/serial/serial.c diff --git a/kernel/boot/init/boot.s b/kernel/boot/init/boot.s index 35a89a2..8e0d10b 100644 --- a/kernel/boot/init/boot.s +++ b/kernel/boot/init/boot.s @@ -85,6 +85,10 @@ _start: */ movl $stack_top, %esp + /* Push Multiboot values to stack for kernel_main */ + push %eax + push %ebx + /* This is a good place to initialize crucial processor state before the high-level kernel is entered. It's best to minimize the early diff --git a/kernel/include/common.h b/kernel/include/common.h new file mode 100644 index 0000000..269d3f3 --- /dev/null +++ b/kernel/include/common.h @@ -0,0 +1,24 @@ +/* + * CMOS + * Copyright (C) 2025 Raghuram Subramani <raghus2247@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __common_h +#define __common_h + +#define ALWAYS_INLINE __attribute__((always_inline)) inline + +#endif diff --git a/kernel/include/mm/memory_map.h b/kernel/include/mm/memory_map.h new file mode 100644 index 0000000..5a80aa3 --- /dev/null +++ b/kernel/include/mm/memory_map.h @@ -0,0 +1,26 @@ +/* + * CMOS + * Copyright (C) 2025 Raghuram Subramani <raghus2247@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __mm_memory_map_h +#define __mm_memory_map_h + +#include <mm/multiboot.h> + +void memory_map_load(multiboot_info_t *); + +#endif diff --git a/kernel/include/mm/multiboot.h b/kernel/include/mm/multiboot.h new file mode 100644 index 0000000..5463cfb --- /dev/null +++ b/kernel/include/mm/multiboot.h @@ -0,0 +1,266 @@ +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * Copyright (C) 2025 Raghuram Subramani <raghus2247@gmail.com> + * + * 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 _mm_multiboot_h +#define _mm_multiboot_h + +/* 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_uint32_t addr_low; + multiboot_uint32_t addr_high; + multiboot_uint32_t len_low; + multiboot_uint32_t len_high; +#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 */ diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c index 63c5315..427dfbf 100644 --- a/kernel/kernel/kernel.c +++ b/kernel/kernel/kernel.c @@ -17,6 +17,10 @@ */ #include <boot/gdt.h> + +#include <mm/memory_map.h> +#include <mm/multiboot.h> + #include <kernel/halt.h> #include <libk/stdio.h> @@ -25,14 +29,21 @@ #include <drivers/vga_text_buffer.h> void -kernel_main(void) +kernel_main(multiboot_info_t *multiboot_info, uint32_t magic) { - GDT_load(); + serial_initialize(); - printk("Kernel", "Started."); + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { + printk("Kernel", "Invalid Multiboot Magic: %x", magic); + halt(); + } + + GDT_load(); + memory_map_load(multiboot_info); vga_text_buffer_initialize(); - serial_initialize(); + + printk("Kernel", "Started."); // exit(); halt(); /* If exit() fails (on real hardware) */ diff --git a/kernel/mm/memory_map.c b/kernel/mm/memory_map.c new file mode 100644 index 0000000..c6aefee --- /dev/null +++ b/kernel/mm/memory_map.c @@ -0,0 +1,78 @@ +/* + * CMOS + * Copyright (C) 2025 Raghuram Subramani <raghus2247@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include <common.h> + +#include <kernel/halt.h> +#include <libk/stdio.h> + +#include <mm/multiboot.h> + +ALWAYS_INLINE static char * +memory_map_fetch_type(multiboot_memory_map_t *mmap) +{ + switch (mmap->type) { + case MULTIBOOT_MEMORY_AVAILABLE: + return "AVAILABLE"; + case MULTIBOOT_MEMORY_RESERVED: + return "RESERVED"; + case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: + return "ACPI_RECLAIMABLE"; + case MULTIBOOT_MEMORY_NVS: + return "NVS"; + case MULTIBOOT_MEMORY_BADRAM: + return "BADRAM"; + default: + return "UNKNOWN"; + } +} + +void +memory_map_load(multiboot_info_t *multiboot_info) +{ + printk("mm", "Loading Memory Map:"); + + /* https://www.gnu.org/software/grub/manual/multiboot/multiboot.html: + * + * If bit 6 in the ‘flags’ word is set, then the ‘mmap_*’ fields are + * valid, and indicate the address and length of a buffer containing a + * memory map of the machine provided by the BIOS. ‘mmap_addr’ is the + * address, and ‘mmap_length’ is the total size of the buffer. The buffer + * consists of one or more of the following size/structure pairs (‘size’ + * is really used for skipping to the next pair): */ + + if (!(multiboot_info->flags & MULTIBOOT_INFO_ELF_SHDR)) { + printk("mm", "Invalid memory map!"); + halt(); + } + + for (uint32_t i = 0; i < multiboot_info->mmap_length; + i += sizeof(multiboot_memory_map_t)) { + multiboot_memory_map_t *mmap + = (multiboot_memory_map_t *) (multiboot_info->mmap_addr + i); + + printk("mm", + "start: 0x%x | length: 0x%x | size: 0x%x | type: %s", + mmap->addr_low, + mmap->len_low, + mmap->size, + memory_map_fetch_type(mmap)); + } +} |