├── .gitignore ├── Makefile ├── README.mdown ├── SPECIFICATION.mdown ├── bochsrc.txt ├── image ├── Makefile └── grub │ ├── grub.cfg │ └── stage2_eltorito ├── loader ├── Makefile ├── dump.txt ├── inc │ ├── acpi.h │ ├── apic.h │ ├── cpu.h │ ├── elf64.h │ ├── gdt.h │ ├── heap.h │ ├── hydrogen.h │ ├── idt.h │ ├── info.h │ ├── ioapic.h │ ├── kernel.h │ ├── lapic.h │ ├── main.h │ ├── multiboot.h │ ├── page.h │ ├── pic.h │ ├── pit.h │ ├── ports.h │ ├── screen.h │ ├── smp.h │ ├── stdint.h │ ├── string.h │ └── syscall.h ├── link.ld └── src │ ├── acpi.c │ ├── boot16.s │ ├── boot32.s │ ├── cpu.c │ ├── elf64.c │ ├── gdt.c │ ├── heap.c │ ├── idt.c │ ├── idt.s │ ├── info.c │ ├── ioapic.c │ ├── kernel.c │ ├── kernel.s │ ├── lapic.c │ ├── lapic.s │ ├── main.c │ ├── multiboot.c │ ├── multiboot.s │ ├── page.c │ ├── pic.c │ ├── pit.c │ ├── ports.c │ ├── screen.c │ ├── smp.c │ ├── string.c │ └── syscall.c └── test ├── Makefile ├── inc ├── buffer.h ├── isr.h ├── keyboard.h ├── lapic.h ├── ports.h ├── screen.h ├── stdint.h └── ui.h ├── link.ld └── src ├── buffer.c ├── hydrogen.c ├── isr.s ├── kernel.c ├── keyboard.c ├── lapic.c ├── ports.c ├── screen.c └── ui.c /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | loader/build/* 3 | image/build/* 4 | test/build/* 5 | bochsout.txt 6 | .project 7 | .cproject 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run clean loader image test 2 | 3 | PREFIX := ./build 4 | EMU := bochs 5 | EMUFLAGS := -q 6 | 7 | all: loader test image 8 | 9 | run: image 10 | @ $(EMU) $(EMUFLAGS) 11 | 12 | qemu: image 13 | @ qemu-system-x86_64 -cdrom $(PREFIX)/boot.iso -smp 4 14 | 15 | loader: 16 | @ $(MAKE) -C loader/ install 17 | 18 | image: loader 19 | @ $(MAKE) -C image/ 20 | 21 | test: 22 | @ $(MAKE) -C test/ install 23 | 24 | clean: 25 | @ rm -R $(PREFIX)/* 26 | -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | Hydrogen 2 | ====================== 3 | Hydrogen is an intermediate bootloader for AMD64 kernels. While being loaded itself by a 4 | Multiboot 1 compliant boot loader that supports loading of ELF64 binaries, it sets up the 5 | system for an AMD64 kernel attached as a Multiboot module. 6 | 7 | When developing kernels and operating systems for modern AMD64 platforms one is faced 8 | with many legacy interfaces dating back to the roots of X86 and tedious initialization 9 | processes. Hydrogen is designed to handle initialization of most interfaces required 10 | for development of a 64 bit kernel to hand the developers a well defined and mostly 11 | legacy-free system state. 12 | 13 | Hydrogen also exports an information table that combines all useful information gathered 14 | about the host system from various sources, such as ACPI or the Multiboot info tables. 15 | 16 | While Hydrogen assumes reasonable defaults on system initialization, the kernel can take 17 | influence on that process by providing an optional header structure. 18 | 19 | See `SPECIFICATION.mdown` and `loader/inc/hydrogen.h` (also `build/hydrogen.h` after the 20 | loader has been compiled) for a detailed specification of the loader and its ABI. 21 | 22 | The test/ directory contains an example kernel that is loaded with Hydrogen and 23 | can be used to browse the info tables generated by Hydrogen in a text interface. An 24 | bootable image of the test kernel can be built with 25 | 26 | > make test && make image KERNEL=`pwd`/build/bin/test64.bin. 27 | 28 | The Hydrogen loader requires a Multiboot 1 compliant bootloader with ELF64 support, 29 | such as GRUB2. A binary copy of GRUB2 that contains all necessary modules for booting 30 | from CD is shipped with this distribution and can be easily built by oneself using 31 | the freely available source of the GRUB project. 32 | 33 | Build Requirements 34 | ---------------------- 35 | Hydrogen requires the following tools to build: 36 | 37 | - gcc (tested with 4.6.3 20120306) 38 | - ld (tested with 2.21.53.0.1-6.fc16 20110716) 39 | - mkisofs (tested with 1.1.11) 40 | - nasm (tested with 2.09.08) 41 | 42 | Hydrogen is tested on the following emulators: 43 | 44 | - bochs (2.5.1) 45 | - qemu (0.15.1) 46 | - VirtualBox (4.1.12) 47 | 48 | Each release is tested on following hardware platforms: 49 | 50 | - Core i7 920, 6GiB DDR3 RAM, AMD Radeon HD 4870 51 | - Thinkpad X220i, Core i3 2310M, 4GiB DDR3 RAM, Intel HD Graphics 3000 52 | 53 | How to Build 54 | ---------------------- 55 | The top-level Makefile provides the following targets: 56 | 57 | - *loader*: Builds the `$(PREFIX)/bin/hydrogen.bin` loader binary and provides 58 | the hydrogen header in `$(PREFIX)/inc/hydrogen.h`. 59 | - *image*: Must be supplied with an absolute path to a `KERNEL` binary 60 | and creates a bootable ISO image `$(PREFIX)/boot.iso`. 61 | - *test*: Produces a test kernel binary in `$(PREFIX)/bin/test64.bin`. 62 | 63 | Reasons for Rewrite 64 | ---------------------- 65 | This version of Hydrogen is a rewrite of a former implementation that was written 66 | entirely in assembly. As the complexity of the system grew the author felt the need 67 | for a rewrite in C code to increase maintainability, flexibility and stability of 68 | the software. 69 | 70 | Related Work 71 | ---------------------- 72 | In development of the Hydrogen Loader the project Pure64 [1] by Return Infinity 73 | has been a great inspiration. While serving a quite similar purpose and also 74 | sharing the basic design philosophy, Pure64 is a stage 2 loader and has to care 75 | about loading the kernel from the boot medium itself, which is why to the date 76 | when Hydrogen was started it only supported FAT16 as a file system and did not 77 | support loading from devices other than a hard drive. 78 | 79 | Hydrogen has been developed out of the wish to profit from GRUB2's wide support 80 | of hardware, file systems and devices while still not having to care about the 81 | annoying and lengthy setup required for modern AMD64 systems. 82 | 83 | The author thanks the Return Infinity team for their great work and the inspiration 84 | that came with it. 85 | 86 | [1] http://www.returninfinity.com/pure64.html 87 | -------------------------------------------------------------------------------- /bochsrc.txt: -------------------------------------------------------------------------------- 1 | megs: 32 2 | romimage: file=/usr/local/share/bochs/BIOS-bochs-latest 3 | vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest 4 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 5 | ata0-master: type=cdrom, path="build/boot.iso", status=inserted 6 | boot: cdrom 7 | log: bochsout.txt 8 | mouse: enabled=0 9 | cpu: count=4 10 | display_library: x, options="gui_debug" 11 | magic_break: enabled=1 12 | cpuid: apic=x2apic -------------------------------------------------------------------------------- /image/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: prepare iso clean 2 | 3 | BUILD_DIR := ./build 4 | GRUB_DIR := ./grub 5 | 6 | PREFIX := ./../build 7 | 8 | ISO := $(PREFIX)/boot.iso 9 | ISO_DIR := $(BUILD_DIR)/iso 10 | ISO_BOOT := boot 11 | ISO_ELTORITO := $(ISO_BOOT)/stage2_eltorito 12 | 13 | KERNEL := 14 | HYDROGEN := $(PREFIX)/bin/hydrogen.bin 15 | MODULES := 16 | 17 | iso: prepare 18 | @ echo " Creating ISO file..." 19 | @ mkisofs -R -b $(ISO_ELTORITO) -no-emul-boot -boot-load-size 4 \ 20 | -boot-info-table -o $(ISO) $(ISO_DIR) 2> /dev/null 21 | 22 | prepare: 23 | ifneq ($(strip $(KERNEL)),) 24 | @ echo " Creating directory structure..." 25 | @ mkdir -p $(ISO_DIR)/$(ISO_BOOT)/ 26 | @ echo " Copying GRUB files..." 27 | @ cp $(GRUB_DIR)/* $(ISO_DIR)/$(ISO_BOOT)/ 28 | @ echo " Copying binaries..." 29 | @ cp $(KERNEL) $(ISO_DIR)/$(ISO_BOOT)/kernel64.bin 30 | @ cp $(HYDROGEN) $(ISO_DIR)/$(ISO_BOOT)/ 31 | ifneq ($(strip $(MODULES)),) 32 | @ cp $(MODULES) $(ISO_DIR)/$(ISO_BOOT)/ 33 | endif 34 | else 35 | $(error Specify a kernel binary in KERNEL.) 36 | endif 37 | 38 | clean: 39 | @ rm -R $(BUILD_DIR)/* 40 | -------------------------------------------------------------------------------- /image/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=5 2 | set default=0 3 | 4 | multiboot /boot/hydrogen.bin 5 | module /boot/kernel64.bin kernel64 6 | boot 7 | -------------------------------------------------------------------------------- /image/grub/stage2_eltorito: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zrho/Hydrogen/b58c084e6aea5b7ef29d5586a07e3511f5348efa/image/grub/stage2_eltorito -------------------------------------------------------------------------------- /loader/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all build link install uninstall clean 2 | 3 | # Target 4 | TARGET := hydrogen 5 | TARGET_BIN := $(TARGET).bin 6 | 7 | # Directories 8 | PREFIX := ./../build 9 | SOURCE_DIR := ./src 10 | BUILD_DIR := ./build 11 | INC_DIR := ./inc 12 | 13 | # Object Files 14 | OBJECTS := $(patsubst $(SOURCE_DIR)/%.c,$(BUILD_DIR)/%.c.o,$(shell find $(SOURCE_DIR) -name "*.c")) 15 | OBJECTS += $(patsubst $(SOURCE_DIR)/%.s,$(BUILD_DIR)/%.s.o,$(shell find $(SOURCE_DIR) -name "*.s")) 16 | 17 | # Toolchain 18 | CC := gcc 19 | AS := nasm 20 | LD := ld 21 | 22 | # Toolchain Flags 23 | INCFLAGS := -I$(INC_DIR) -I$(PREFIX)/include 24 | CFLAGS := -m64 -ffreestanding -Wall -Werror -mcmodel=large $(INCFLAGS) 25 | ASFLAGS := -f elf64 26 | LDFLAGS := -z max-page-size=0x1000 27 | 28 | # Link File 29 | LDFILE := link.ld 30 | 31 | # Build everything and link the target binary. 32 | all: build link 33 | 34 | # Install to prefix directory. 35 | install: all 36 | @ mkdir -p $(PREFIX)/bin 37 | @ mkdir -p $(PREFIX)/include 38 | 39 | @ echo " CP" $(TARGET_BIN) 40 | @ cp $(BUILD_DIR)/$(TARGET_BIN) $(PREFIX)/bin 41 | 42 | @ echo " CP hydrogen.h" 43 | @ cp $(INC_DIR)/hydrogen.h $(PREFIX)/include 44 | 45 | # Uninstalls from prefix directory. 46 | uninstall: 47 | @ rm $(PREFIX)/bin/$(TARGET_BIN) 48 | @ rm $(PREFIX)/include/hydrogen.h 49 | 50 | # Build all C and assembly files. 51 | build: $(OBJECTS) 52 | 53 | # Build an assembly file. 54 | $(BUILD_DIR)/%.s.o: $(SOURCE_DIR)/%.s 55 | @ echo " AS " $< 56 | @ mkdir -p $(@D) 57 | @ $(AS) $(ASFLAGS) $< -o $@ 58 | 59 | # Build a C file. 60 | $(BUILD_DIR)/%.c.o: $(SOURCE_DIR)/%.c 61 | @ echo " CC " $< 62 | @ mkdir -p $(@D) 63 | @ $(CC) $(CFLAGS) -c $< -o $@ 64 | 65 | # Link the target binary. 66 | link: 67 | @ echo " LD " $(TARGET_BIN) 68 | @ $(LD) $(LDFLAGS) -T $(LDFILE) -o $(BUILD_DIR)/$(TARGET_BIN) $(OBJECTS) 69 | 70 | # Cleans the build directory 71 | clean: 72 | @ rm -R $(BUILD_DIR)/* 73 | -------------------------------------------------------------------------------- /loader/inc/acpi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * The RSDP is a pointer to the RSDT/XSDT. 31 | * 32 | * Can be discovered by searching for its signature, 'RSD PTR' in low memory 33 | * on BIOS systems, or using the information provided by EFI on EFI enabled 34 | * systems. 35 | * 36 | * Has two versions: 37 | * 1.0 Denoted by a value of zero (0) in the revision field; the RSDP is fixed 38 | * to a size of 20 bytes and points to an RSDT. 39 | * 2.0 Denoted by a value of one (1) in the revision field; the RSDP has is 40 | * variably-sized (see the length field) and points to an XSDT. 41 | * 42 | * If any version later than 2.0 is encounted, it will be treated as of being 43 | * of version 2.0. 44 | */ 45 | typedef struct acpi_rsdp { 46 | uint8_t signature[8]; 47 | uint8_t checksum; 48 | uint8_t oemid[6]; 49 | uint8_t revision; 50 | uint32_t rsdt_addr; 51 | 52 | uint32_t length; 53 | uint64_t xsdt_addr; 54 | uint8_t xchecksum; 55 | uint8_t reserved[3]; 56 | } __attribute__((packed)) acpi_rsdp_t; 57 | 58 | /** 59 | * Each ACPI table (including the RSDT and XSDT) begins with the SDT header. 60 | */ 61 | typedef struct acpi_sdt_header { 62 | uint32_t signature; 63 | uint32_t length; 64 | uint8_t revision; 65 | uint8_t checksum; 66 | uint8_t oemid[6]; 67 | uint8_t oem_tbl_id[8]; 68 | uint32_t oem_rev; 69 | uint32_t creator_id; 70 | uint32_t creator_rev; 71 | } __attribute__((packed)) acpi_sdt_header_t; 72 | 73 | /** 74 | * Flag in the MADT denoting the presence of a 8259 PIC in the system. 75 | */ 76 | #define ACPI_MADT_PCAT_COMPAT (1 << 0) 77 | 78 | /** 79 | * Flag in the LAPIC MADT entry indicating that the LAPIC is enabled. 80 | * 81 | * Disabled LAPICs should be ignored by the operating system. 82 | */ 83 | #define ACPI_MADT_LAPIC_ENABLED (1 << 0) 84 | 85 | // Polarity flags in ISOs 86 | #define ACPI_MADT_ISO_POLARITY_OFFSET 0 87 | #define ACPI_MADT_ISO_POLARITY_DEFAULT (0b00) 88 | #define ACPI_MADT_ISO_POLARITY_HIGH (0b01) 89 | #define ACPI_MADT_ISO_POLARITY_LOW (0b11) 90 | 91 | // Trigger mode flags in ISOs 92 | #define ACPI_MADT_ISO_TRIGGER_OFFSET 2 93 | #define ACPI_MADT_ISO_TRIGGER_DEFAULT (0b00) 94 | #define ACPI_MADT_ISO_TRIGGER_EDGE (0b01) 95 | #define ACPI_MADT_ISO_TRIGGER_LEVEL (0b11) 96 | 97 | /** 98 | * MADT entry type ID for LAPICs, IO APICs and Interrupt Source Overrides. 99 | */ 100 | #define ACPI_MADT_TYPE_LAPIC 0 101 | #define ACPI_MADT_TYPE_IOAPIC 1 102 | #define ACPI_MADT_TYPE_ISO 2 103 | #define ACPI_MADT_TYPE_X2LAPIC 9 104 | 105 | /** 106 | * The Multiple APIC Description Table contains information about the interrupt 107 | * controllers installed to the system (such as LAPICs and IO APICs). 108 | * 109 | * This structure is followed by a variable sized list of APIC devices. 110 | */ 111 | typedef struct acpi_madt { 112 | acpi_sdt_header_t header; 113 | 114 | uint32_t lapic_paddr; 115 | uint32_t flags; 116 | } __attribute__((packed)) acpi_madt_t; 117 | 118 | /** 119 | * Header of an entry in the MADT. 120 | */ 121 | typedef struct acpi_madt_entry { 122 | uint8_t type; 123 | uint8_t length; 124 | } __attribute__((packed)) acpi_madt_entry_t; 125 | 126 | /** 127 | * MADT entry describing a LAPIC and its associated processor. 128 | */ 129 | typedef struct acpi_madt_lapic { 130 | acpi_madt_entry_t header; 131 | 132 | uint8_t acpi_id; 133 | uint8_t apic_id; 134 | uint32_t flags; 135 | } __attribute__((packed)) acpi_madt_lapic_t; 136 | 137 | /** 138 | * MADT entry describing an X2APIC LAPIC and its associated processor. 139 | */ 140 | typedef struct apci_madt_x2lapic { 141 | acpi_madt_entry_t header; 142 | 143 | uint16_t reserved; 144 | uint32_t x2apic_id; 145 | uint32_t flags; 146 | uint32_t acpi_id; 147 | } __attribute__((packed)) acpi_madt_x2lapic_t; 148 | 149 | /** 150 | * MADT entry describing an I/O APIC. 151 | */ 152 | typedef struct acpi_madt_ioapic { 153 | acpi_madt_entry_t header; 154 | 155 | uint8_t apic_id; 156 | uint8_t reserved; 157 | uint32_t mmio_addr; 158 | uint32_t gsi_base; 159 | } __attribute__((packed)) acpi_madt_ioapic_t; 160 | 161 | /** 162 | * MADT entry for interrupt source overrides. 163 | * 164 | * Denotes non-standard mappings of ISA IRQs to Global System Interrupts. 165 | */ 166 | typedef struct acpi_madt_iso { 167 | acpi_madt_entry_t header; 168 | 169 | uint8_t bus; 170 | uint8_t irq; 171 | uint32_t gsi; 172 | uint16_t flags; 173 | } __attribute__((packed)) acpi_madt_iso_t; 174 | 175 | /** 176 | * Flag in the LAPIC and x2LAPIC SRAT entries that indicates that the entry is 177 | * enabled and should be parsed. If this flag is clear, the entry must be ignored. 178 | */ 179 | #define ACPI_SRAT_LAPIC_ENABLED (1 << 0) 180 | 181 | // SRAT entry types. 182 | #define ACPI_SRAT_TYPE_LAPIC 0 183 | #define ACPI_SRAT_TYPE_MEMORY 1 184 | #define ACPI_SRAT_TYPE_X2LAPIC 2 185 | 186 | /** 187 | * The System Resource Affinity Table maps the system's CPUs to the NUMA domains 188 | * and the domains to the memory regions that are associated with them. 189 | * 190 | * This structure is followed by a variable sized list of entries. 191 | */ 192 | typedef struct acpi_srat { 193 | acpi_sdt_header_t header; 194 | 195 | uint32_t reserved0; 196 | uint64_t reserved1; 197 | } __attribute__((packed)) acpi_srat_t; 198 | 199 | /** 200 | * Header of an entry in the SRAT. 201 | */ 202 | typedef struct acpi_srat_entry { 203 | uint8_t type; 204 | uint8_t length; 205 | } __attribute__((packed)) acpi_srat_entry_t; 206 | 207 | /** 208 | * SRAT table entry that associates a CPU's LAPIC to a NUMA domain. 209 | */ 210 | typedef struct acpi_srat_lapic { 211 | acpi_srat_entry_t header; 212 | 213 | uint8_t domain_low; 214 | uint8_t apic_id; 215 | uint32_t flags; 216 | uint8_t sapic_eid; 217 | uint8_t domain_high[3]; 218 | uint32_t clock_domain; 219 | } __attribute__((packed)) acpi_srat_lapic_t; 220 | 221 | /** 222 | * SRAT table entry that associates a CPU's x2LAPIC to a NUMA domain. 223 | */ 224 | typedef struct acpi_srat_x2lapic { 225 | acpi_srat_entry_t header; 226 | 227 | uint16_t reserved0; 228 | uint32_t domain; 229 | uint32_t x2apic_id; 230 | uint32_t flags; 231 | uint32_t clock_domain; 232 | uint32_t reserved1; 233 | } __attribute__((packed)) acpi_srat_x2lapic_t; 234 | 235 | /** 236 | * SRAT table entry that associates a memory range to a NUMA domain. 237 | */ 238 | typedef struct acpi_srat_memory { 239 | acpi_srat_entry_t header; 240 | 241 | uint32_t domain; 242 | uint16_t reserved0; 243 | uint32_t base_low; 244 | uint32_t base_high; 245 | uint32_t length_low; 246 | uint32_t length_high; 247 | uint32_t reserved1; 248 | uint32_t flags; 249 | uint64_t reserved2; 250 | } __attribute__((packed)) acpi_srat_memory_t; 251 | 252 | /** 253 | * Searches for the RSDP on a 16 byte boundary, given a memory region to 254 | * search in. 255 | * 256 | * @param begin The address on which the region to search begins. 257 | * @param length The length of the region. 258 | * @return Pointer to the RSDP or null-pointer if it could not be found. 259 | */ 260 | acpi_rsdp_t *acpi_find_rsdp(uintptr_t begin, size_t length); 261 | 262 | /** 263 | * Validates the checksum of a table, given its length. 264 | * 265 | * Adds up all bytes of the table and checks whether the sum modulo 256 266 | * equals zero (0). 267 | * 268 | * @param table The address of the table whose checksum to validate. 269 | * @param length The length of the table. 270 | * @return true when the table is valid, false otherwise. 271 | */ 272 | bool acpi_check(void *table, size_t length); 273 | 274 | /** 275 | * Discovers the system's ACPI info tables and extracts all vital information 276 | * that is required to fill the Hydrogen info tables. 277 | */ 278 | void acpi_parse(void); 279 | -------------------------------------------------------------------------------- /loader/inc/apic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // Pin polarity 30 | #define APIC_POLARITY_HIGH 0 31 | #define APIC_POLARITY_LOW 1 32 | 33 | // Delivery mode 34 | #define APIC_DELIVERY_FIXED 0b000 35 | #define APIC_DELIVERY_LOW_PRIO 0b001 36 | #define APIC_DELIVERY_SMI 0b010 37 | #define APIC_DELIVERY_NMI 0b100 38 | #define APIC_DELIVERY_INIT 0b101 39 | #define APIC_DELIVERY_STARTUP 0b110 40 | 41 | // Destination shorthand 42 | #define APIC_SHORT_NONE 0b00 43 | #define APIC_SHORT_SELF 0b01 44 | #define APIC_SHORT_ALL_INCL 0b10 45 | #define APIC_SHORT_ALL_EXCL 0b11 46 | 47 | // Interrupt level 48 | #define APIC_LEVEL_DEASSERT 0 49 | #define APIC_LEVEL_ASSERT 1 50 | 51 | // Trigger mode 52 | #define APIC_TRIGGER_EDGE 0 53 | #define APIC_TRIGGER_LEVEL 1 54 | 55 | // Destination mode 56 | #define APIC_MODE_PHYSICAL 0 57 | #define APIC_MODE_LOGICAL 1 58 | 59 | -------------------------------------------------------------------------------- /loader/inc/cpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Result of a call to the CPUID instruction. Stores the value of the four 31 | * general purpose registers eax, ebx, ecx and edx after invocation. 32 | */ 33 | typedef struct cpu_cpuid_result { 34 | uint32_t a; 35 | uint32_t b; 36 | uint32_t c; 37 | uint32_t d; 38 | } cpu_cpuid_result_t; 39 | 40 | /** 41 | * Reads the value of a MSR. 42 | * 43 | * @param msr the index of the MSR to read. 44 | */ 45 | uint64_t cpu_msr_read(uint32_t msr); 46 | 47 | /** 48 | * Writes a value to a MSR. 49 | * 50 | * @param msr the index of the MSR to write to. 51 | * @param value the value to write to the MSR. 52 | */ 53 | void cpu_msr_write(uint32_t msr, uint64_t value); 54 | 55 | /** 56 | * Invokes the CPUID instruction for the given code and returns 57 | * the result in the parameter. 58 | * 59 | * @param code the CPUID code (in EAX). 60 | * @param result output parameter for CPUID result 61 | */ 62 | void cpu_cpuid(uint32_t code, cpu_cpuid_result_t *result); 63 | -------------------------------------------------------------------------------- /loader/inc/elf64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // Value for elf64_ehdr.e_ident_mag 30 | #define ELFMAG 0x464C457F //< 0x7F + 'ELF' 31 | 32 | // Values for elf64_ehdr.e_indent_class 33 | #define ELFCLASSNONE 0 //< unknown 34 | #define ELFCLASS32 1 //< 32 bit arch 35 | #define ELFCLASS64 2 //< 64 bit arch 36 | 37 | // Values for elf64_ehdr.e_ident_data 38 | #define ELFDATANONE 0 //< unknown 39 | #define ELFDATA2LSB 1 //< little endian 40 | #define ELFDATA2MSB 2 //< big endian 41 | 42 | // Values for elf64_ehdr.e_type 43 | #define ELF_ET_NONE 0 //< unknown 44 | #define ELF_ET_REL 1 //< relocatable 45 | #define ELF_ET_EXEC 2 //< executable 46 | #define ELF_ET_DYN 3 //< shared object 47 | #define ELF_ET_CORE 4 //< core file 48 | 49 | // Values for elf64_phdr.p_type 50 | #define ELF_PT_NULL 0 //< unused entry 51 | #define ELF_PT_LOAD 1 //< loadable segment 52 | #define ELF_PT_DYNAMIC 2 //< dynamic linking information segment 53 | #define ELF_PT_INTERP 3 //< pathname of interpreter 54 | #define ELF_PT_NOTE 4 //< auxiliary information 55 | #define ELF_PT_SHLIB 5 //< reserved (not used) 56 | #define ELF_PT_PHDR 6 //< location of program header itself 57 | 58 | // Values for elf64_phdr.p_flags 59 | #define ELF_PF_X (1 << 0) //< executable 60 | #define ELF_PF_W (1 << 1) //< writable 61 | #define ELF_PF_R (1 << 2) //< readable 62 | 63 | // Values for elf64_shdr.sh_type 64 | #define ELF_SHT_NULL 0 //< inactive 65 | #define ELF_SHT_PROGBITS 1 //< program defined information 66 | #define ELF_SHT_SYMTAB 2 //< symbol table section 67 | #define ELF_SHT_STRTAB 3 //< string table section 68 | #define ELF_SHT_RELA 4 //< relocation section with addends 69 | #define ELF_SHT_HASH 5 //< symbol hash table section 70 | #define ELF_SHT_DYNAMIC 6 //< dynamic section 71 | #define ELF_SHT_NOTE 7 //< note section 72 | #define ELF_SHT_NOBITS 8 //< no space section 73 | #define ELF_SHT_REL 9 //< relation section without addends 74 | #define ELF_SHT_SHLIB 10 //< reserved - purpose unknown 75 | #define ELF_SHT_DYNSYM 11 //< dynamic symbol table section 76 | #define ELF_SHT_LOPROC 0x70000000 //< reserved range for processor 77 | #define ELF_SHT_HIPROC 0x7FFFFFFF //< specific section header types 78 | #define ELF_SHT_LOUSER 0x80000000 //< reserved range for application 79 | #define ELF_SHT_HIUSER 0xFFFFFFFF //< specific indexes 80 | 81 | // Values for elf64_dyn.d_type 82 | #define ELF_DT_NULL 0 83 | #define ELF_DT_HASH 4 //< address of the symbol hash table 84 | 85 | /** 86 | * ELF64 file header. 87 | */ 88 | typedef struct elf64_ehdr { 89 | uint32_t e_ident_mag; 90 | uint8_t e_ident_class; 91 | uint8_t e_ident_data; 92 | uint8_t e_ident_version; 93 | uint8_t e_ident_osabi; 94 | uint8_t e_ident_abiversion; 95 | uint8_t e_ident_pad[7]; 96 | 97 | uint16_t e_type; 98 | uint16_t e_machine; 99 | uint32_t e_version; 100 | uint64_t e_entry; 101 | uint64_t e_phoff; 102 | uint64_t e_shoff; 103 | uint32_t e_flags; 104 | 105 | uint16_t e_ehsize; 106 | uint16_t e_phsize; 107 | uint16_t e_phnum; 108 | uint16_t e_shentsize; 109 | uint16_t e_shnum; 110 | uint16_t e_shstrndx; 111 | } __attribute__((packed)) elf64_ehdr_t; 112 | 113 | /** 114 | * ELF64 program header. 115 | * 116 | * Contains information on where to load the binary's data and code from and where 117 | * to map it to. 118 | */ 119 | typedef struct elf64_phdr { 120 | uint32_t p_type; 121 | uint32_t p_flags; 122 | uint64_t p_offset; 123 | uint64_t p_vaddr; 124 | uint64_t p_paddr; 125 | uint64_t p_filesz; 126 | uint64_t p_memsz; 127 | uint64_t p_align; 128 | } __attribute__((packed)) elf64_phdr_t; 129 | 130 | /** 131 | * ELF64 section header. 132 | */ 133 | typedef struct elf64_shdr { 134 | uint32_t sh_name; 135 | uint32_t sh_type; 136 | uint64_t sh_flags; 137 | uint64_t sh_addr; 138 | uint64_t sh_offset; 139 | uint64_t sh_size; 140 | uint32_t sh_link; 141 | uint32_t sh_info; 142 | uint64_t sh_addralign; 143 | uint64_t sh_entsize; 144 | } __attribute__((packed)) elf64_shdr_t; 145 | 146 | /** 147 | * ELF64 symbol table entry. 148 | */ 149 | typedef struct elf64_sym { 150 | uint32_t st_name; 151 | uint8_t st_info; 152 | uint8_t st_other; 153 | uint16_t st_shndx; 154 | uint64_t st_value; 155 | uint64_t st_size; 156 | } __attribute__((packed)) elf64_sym_t; 157 | 158 | /** 159 | * ELF64 dynamic table entry. 160 | */ 161 | typedef struct elf64_dyn { 162 | uint64_t d_type; 163 | 164 | union { 165 | uint64_t d_val; 166 | uint64_t d_ptr; 167 | } d_un; 168 | } __attribute__((packed)) elf64_dyn_t; 169 | 170 | /** 171 | * Calculates a hash value for a symbol . 172 | * 173 | * @param name the name to generate a hash for. 174 | * @return the hash of the name 175 | */ 176 | uint64_t elf64_hash(const char *name); 177 | 178 | /** 179 | * Returns the header of the first section of the given in an ELF64 . 180 | * 181 | * @param type the type of the section 182 | * @param binary the ELF64 binary 183 | * @return header of the first matching section 184 | */ 185 | elf64_shdr_t *elf64_shdr_find(uint32_t type, void *binary); 186 | 187 | /** 188 | * Tries to find a symbol in an ELF64 , given its . 189 | * 190 | * @param name the name of the symbol to find 191 | * @param binary the ELF64 binary 192 | * @return pointer to the symbol entry or null pointer, if there is no such symbol 193 | */ 194 | elf64_sym_t *elf64_sym_find(const char *name, void *binary); 195 | 196 | /** 197 | * Loads an ELF64 into virtual memory. 198 | * 199 | * @param binary the binary to load 200 | */ 201 | void elf64_load(void *binary); 202 | -------------------------------------------------------------------------------- /loader/inc/gdt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // 64 bit long mode GDT segment descriptors 30 | #define GDT_KERNEL_CODE 0x209800 //< kernel code (0x08) 31 | #define GDT_KERNEL_DATA 0x209200 //< kernel data (0x10) 32 | #define GDT_USER_CODE 0x20F800 //< user code (0x18) 33 | #define GDT_USER_DATA 0x20F200 //< user data (0x20) 34 | 35 | /** 36 | * The length of the GDT in bytes. 37 | */ 38 | #define GDT_LENGTH 0x1000 39 | 40 | /** 41 | * Pointer to the GDT that can be loaded using the LGDT instruction. 42 | */ 43 | typedef struct gdt_pointer { 44 | uint16_t length; //< length in bytes - 1 45 | uint64_t address; //< virtual address 46 | } __attribute__((packed)) gdt_pointer_t; 47 | 48 | /** 49 | * The data of the 64 bit General Descriptor Table. 50 | */ 51 | extern uint64_t gdt_data[GDT_LENGTH / sizeof(uint64_t)]; 52 | 53 | /** 54 | * The pointer to the 64 bit General Descriptor Table. 55 | */ 56 | extern gdt_pointer_t gdt_pointer; 57 | -------------------------------------------------------------------------------- /loader/inc/heap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Address of the top of the dynamically growing heap. Is always page-aligned. 31 | */ 32 | extern uintptr_t heap_top; 33 | 34 | /** 35 | * Sets up the heap by finding a top address and moving required data 36 | * structures behind the top of the heap in order to prevent them from 37 | * being accidentally overridden. 38 | */ 39 | void heap_init(void); 40 | 41 | /** 42 | * Dynamically allocates a page-aligned chunk of memory. 43 | * 44 | * The given size is aligned to the upper page boundary. 45 | * 46 | * @param size the size of the chunk to allocate in bytes 47 | * @return pointer to the newly allocated chunk 48 | */ 49 | void *heap_alloc(size_t size); 50 | -------------------------------------------------------------------------------- /loader/inc/idt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Length of the IDT in bytes 31 | */ 32 | #define IDT_LENGTH 0x1000 33 | 34 | /** 35 | * Number of entries in the IDT. 36 | */ 37 | #define IDT_MAX 256 38 | 39 | /** 40 | * Pointer to the Interrupt Descriptor Table that can be loaded using 41 | * the LIDT instruction. 42 | */ 43 | typedef struct idt_pointer { 44 | 45 | uint16_t length; //< length of the IDT - 1 46 | uint64_t address; //< virtual address of the IDT 47 | 48 | } __attribute__((packed)) idt_pointer_t; 49 | 50 | /** 51 | * Entry in the Interrupt Descriptor Table. 52 | * 53 | * The handler is the virtual address of the ISR to invoke when the 54 | * interrupt associated with this entry is raised. 55 | */ 56 | typedef struct idt_entry { 57 | 58 | uint16_t handlerLow; //< lowest 2 bytes of the handler 59 | uint16_t cs; //< code segment selector 60 | uint8_t ist; //< offset into the IST 61 | uint8_t flags; //< flags 62 | uint16_t handlerMiddle; //< middle 2 bytes of the handler 63 | uint32_t handlerHigh; //< highest 4 bytes of the handler 64 | uint32_t zero; //< cleared 65 | 66 | } __attribute__((packed)) idt_entry_t; 67 | 68 | /** 69 | * Data of the Interrupt Descriptor Table. 70 | * 71 | * Should be aligned on a page-boundary. 72 | */ 73 | extern idt_entry_t idt_data[IDT_MAX]; 74 | 75 | /** 76 | * The address of the IDT to use. 77 | */ 78 | extern uintptr_t idt_address; 79 | 80 | /** 81 | * An ISR that just IRETQs. 82 | */ 83 | void idt_null_handler(void); 84 | 85 | /** 86 | * Loads an interrupt descriptor table, given its
and . 87 | * 88 | * @param address virtual address of the IDT 89 | * @param length length of the IDT in bytes 90 | */ 91 | void idt_load(uintptr_t address, size_t length); 92 | 93 | /** 94 | * Prepares an interrupt gate, given the IDT entry to modify. 95 | * 96 | * @param entry IDT entry to modify 97 | * @param handler virtual address of the ISR 98 | * @param cs code segment the ISR should run in 99 | * @param dpl least privileged DPL at which the interrupt can be software triggered 100 | */ 101 | void idt_intgate(idt_entry_t *entry, uintptr_t handler, uint16_t cs, uint8_t dpl); 102 | 103 | /** 104 | * Sets up the IDT for the loader. 105 | * 106 | * Sets all entries to interrupt gates with a minimum DPL of 0x0, a code segment 107 | * of 0x08 and the idt_null_handler as ISR, except for some fault handlers. 108 | * 109 | * Can be called multiply times to reset the IDT. 110 | */ 111 | void idt_setup_loader(void); 112 | 113 | /** 114 | * Sets up the IDT for the kernel. 115 | * 116 | * Sets all entries in the IDT to be interrupt gates with a minimum DPL of 0x0, a 117 | * code segment of 0x08 and ISRs as specified by the ISR entry table passed with 118 | * the kernel header. If the pointer to the ISR entry table is a null-pointer, all 119 | * ISR addresses will default to zero (0x0). 120 | */ 121 | void idt_setup_kernel(void); 122 | -------------------------------------------------------------------------------- /loader/inc/info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include "hydrogen.h" 29 | 30 | /** 31 | * Macro to link a data structure into the info section. 32 | */ 33 | #define INFO_SECTION __attribute__((section (".info"))) 34 | 35 | /** 36 | * Pointer to the root structure of the info section. 37 | */ 38 | extern hy_info_root_t *info_root; 39 | 40 | /** 41 | * Pointer to the CPU list of the info section. 42 | */ 43 | extern hy_info_cpu_t *info_cpu; 44 | 45 | /** 46 | * Pointer to the IO APIC list of the info section. 47 | */ 48 | extern hy_info_ioapic_t *info_ioapic; 49 | 50 | /** 51 | * Pointer to the memory map list of the info section. 52 | */ 53 | extern hy_info_mmap_t *info_mmap; 54 | 55 | /** 56 | * Pointer to the module list of the info section. 57 | */ 58 | extern hy_info_module_t *info_module; 59 | 60 | /** 61 | * Pointer to the string table of the info section. 62 | */ 63 | extern char *info_strings; 64 | 65 | /** 66 | * Pointer to the place to put the next string to. 67 | */ 68 | extern char *info_strings_next; 69 | 70 | /** 71 | * Space that is left in the string table (in bytes). 72 | */ 73 | extern uint32_t info_string_space; 74 | 75 | // Linker symbols that specify the beginning and 76 | // the end of the info tables in memory 77 | extern uint8_t info_begin; 78 | extern uint8_t info_end; 79 | 80 | /** 81 | * Prepares the info structure by filling it with reasonable defaults. 82 | */ 83 | void info_init(void); 84 | 85 | /** 86 | * Copies the tables to the target location and compacts them to the given size. 87 | * 88 | * Panics, if the size does not suffice for storing the tables. 89 | * 90 | * @param target 91 | */ 92 | void info_copy(void *target, size_t size); 93 | 94 | /** 95 | * Allocates space for a string, given its length. 96 | * 97 | * The given length does not include the terminating zero byte. 98 | * 99 | * Panics, when running out of space in the string table. 100 | * 101 | * @param length the length of the string to allocate. 102 | * @return pointer to the allocate string 103 | */ 104 | char *info_string_alloc(size_t length); 105 | -------------------------------------------------------------------------------- /loader/inc/ioapic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include 29 | #include 30 | 31 | // Byte offsets in IO APIC MMIO section 32 | #define IOAPIC_MMIO_REGSEL 0x0 //< offset of register selector 33 | #define IOAPIC_MMIO_IOWIN 0x10 //< offset of I/O window 34 | 35 | // Macros for accessing the MMIO section (p is of type hy_info_ioapic_t *) 36 | #define IOAPIC_MMIO_REGSEL_PTR(p) (uint32_t *) ((p)->mmio_paddr + IOAPIC_MMIO_REGSEL) 37 | #define IOAPIC_MMIO_IOWIN_PTR(p) (uint32_t *)((p)->mmio_paddr + IOAPIC_MMIO_IOWIN) 38 | 39 | // Bit offsets of components in IO APIC redirection registers 40 | #define IOAPIC_REDIR_VECTOR 0 41 | #define IOAPIC_REDIR_DVL_MODE 8 42 | #define IOAPIC_REDIR_DEST_MODE 11 43 | #define IOAPIC_REDIR_DLV_STATUS 12 44 | #define IOAPIC_REDIR_POL 13 45 | #define IOAPIC_REDIR_RIRR 14 46 | #define IOAPIC_REDIR_TRIGGER 15 47 | #define IOAPIC_REDIR_MASK 16 48 | #define IOAPIC_REDIR_DEST 56 49 | 50 | // IO APIC register indices 51 | #define IOAPIC_REG_ID 0x00 52 | #define IOAPIC_REG_VERSION 0x01 53 | #define IOAPIC_REG_ARBITRATION 0x02 54 | #define IOAPIC_REG_REDTBL 0x10 55 | 56 | // PCI GSIs 57 | #define IOAPIC_PCI_INTA 17 58 | #define IOAPIC_PCI_INTB 18 59 | #define IOAPIC_PCI_INTC 19 60 | #define IOAPIC_PCI_INTD 20 61 | 62 | /** 63 | * Default redirection entry for loader setup. 64 | * 65 | * Fixed delivery to a single CPU. Masked by default. Vector must be OR'ed. 66 | */ 67 | #define IOAPIC_REDIR_LOADER ( \ 68 | (APIC_DELIVERY_FIXED << IOAPIC_REDIR_DVL_MODE) | \ 69 | (1 << IOAPIC_REDIR_MASK) | \ 70 | (APIC_MODE_PHYSICAL << IOAPIC_REDIR_DEST_MODE) ) 71 | 72 | /** 73 | * Default redirection entry for kernel setup. 74 | * 75 | * Delivery to lowest priority CPU. Vector must be OR'ed. 76 | */ 77 | #define IOAPIC_REDIR_KERNEL ( \ 78 | (APIC_DELIVERY_LOW_PRIO << IOAPIC_REDIR_DVL_MODE) | \ 79 | (APIC_MODE_LOGICAL << IOAPIC_REDIR_DEST_MODE) | \ 80 | ((uint64_t) 0xFF << IOAPIC_REDIR_DEST) ) 81 | 82 | /** 83 | * Default redirection entry for kernel setup (with single IOAPIC BSP flag). 84 | * 85 | * Delivery to a single CPU. Vector must be OR'ed. 86 | */ 87 | #define IOAPIC_REDIR_KERNEL_BSP ( \ 88 | (APIC_DELIVERY_FIXED << IOAPIC_REDIR_DVL_MODE) | \ 89 | (APIC_MODE_PHYSICAL << IOAPIC_REDIR_DEST_MODE) ) 90 | 91 | /** 92 | * Reads an IO APIC register, given its index. 93 | * 94 | * @param index The index of the register to read- 95 | * @param ioapic The IO APIC whose register to read. 96 | * @return The value of the register. 97 | */ 98 | uint32_t ioapic_register_read(uint16_t index, hy_info_ioapic_t *ioapic); 99 | 100 | /** 101 | * Writes an IO APIC register, given its index and new value. 102 | * 103 | * @param index The index of the register to write. 104 | * @param value The new value for the register. 105 | * @param ioapic The IO APIC whose register to write. 106 | * @return The previous value of the register. 107 | */ 108 | uint32_t ioapic_register_write(uint16_t index, uint32_t value, hy_info_ioapic_t *ioapic); 109 | 110 | /** 111 | * Returns an redirection entry, given its index. 112 | * 113 | * Behavior is undefined, when the entry does not exist. 114 | * 115 | * @param index The index of the redirection entry to return. 116 | * @param ioapic The IO APIC whose redirection entry to return. 117 | * @return The redirection entry. 118 | */ 119 | uint64_t ioapic_redir_get(uint16_t index, hy_info_ioapic_t *ioapic); 120 | 121 | /** 122 | * Sets an redirection entry, given its index. 123 | * 124 | * @param index The index of the redirection entry to set. 125 | * @param redir The redirection entry to set. 126 | * @param ioapic The IO APIC whose redirection entry to set. 127 | */ 128 | void ioapic_redir_set(uint16_t index, uint64_t redir, hy_info_ioapic_t *ioapic); 129 | 130 | /** 131 | * Returns the IO APIC that handles a given number. 132 | * 133 | * @param gsi the GSI number to return the IO APIC for. 134 | */ 135 | hy_info_ioapic_t *ioapic_get_by_gsi(uint32_t gsi); 136 | 137 | /** 138 | * Analyzes the system's IO APICs and adds the findings to the info tables. 139 | */ 140 | void ioapic_analyze(void); 141 | 142 | /** 143 | * Creates a redirection entry. 144 | * 145 | * @param gsi the GSI number of the redirection 146 | * @param kernel whether to use the entry for the kernel or the loader 147 | * @return redirection entry 148 | */ 149 | uint64_t ioapic_redir_forge(uint32_t gsi, bool kernel); 150 | 151 | /** 152 | * Sets up the IO APIC and its redirections for the jump into the kernel by 153 | * transferring them into a well-defined state. 154 | */ 155 | void ioapic_setup_kernel(void); 156 | 157 | /** 158 | * Sets up the IO APIC and its redirections for the initializations that 159 | * are to be performed by this loader. 160 | */ 161 | void ioapic_setup_loader(void); 162 | -------------------------------------------------------------------------------- /loader/inc/kernel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include 29 | 30 | /** 31 | * String the module name of the kernel binary module must begin with. 32 | */ 33 | #define KERNEL_NAME "kernel64" 34 | 35 | /** 36 | * Pointer to the kernel binary, after it has been discovered by kernel_find(). 37 | */ 38 | extern void *kernel_binary; 39 | 40 | /** 41 | * Pointer to the kernel header, after it has been discovered by kernel_analyze(). 42 | */ 43 | extern hy_header_root_t *kernel_header; 44 | 45 | /** 46 | * Finds the kernel binary module or panics if there is none. 47 | */ 48 | void kernel_find(void); 49 | 50 | /** 51 | * Checks the kernel binary and panics if its invalid. 52 | */ 53 | void kernel_check(void); 54 | 55 | /** 56 | * Locates the kernel header in the kernel binary or panics if there is none. 57 | */ 58 | void kernel_analyze(void); 59 | 60 | /** 61 | * Maps the stack of the current CPU to the virtual address specified in the 62 | * kernel header, if any. Also moves the stack pointer to an equivalent 63 | * offset in the mapped stack. 64 | */ 65 | void kernel_map_stack(void); 66 | 67 | /** 68 | * Maps the info tables to the virtual address specified in the kernel header, 69 | * if any. 70 | */ 71 | void kernel_map_info(void); 72 | 73 | /** 74 | * Maps and reloads the IDT. 75 | */ 76 | void kernel_map_idt(void); 77 | 78 | /** 79 | * Maps and reloads the GDT. 80 | */ 81 | void kernel_map_gdt(void); 82 | 83 | /** 84 | * Jumps to the kernel's BSP entry point 85 | */ 86 | void kernel_enter_bsp(void); 87 | 88 | /** 89 | * Jumps to the kernel's AP entry point or halts, if there is none. 90 | */ 91 | void kernel_enter_ap(void); 92 | -------------------------------------------------------------------------------- /loader/inc/lapic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include 29 | 30 | // LAPIC register indices 31 | #define LAPIC_REG_ID 0x02 //< LAPIC ID 32 | #define LAPIC_REG_VERSION 0x03 //< LAPIC version 33 | #define LAPIC_REG_TPR 0x08 //< Task Priority Register 34 | #define LAPIC_REG_EOI 0x0B //< End of Interrupt 35 | #define LAPIC_REG_LDR 0x0D //< Logical Destination Register 36 | #define LAPIC_REG_SVR 0x0F //< Spurious Vector Register 37 | #define LAPIC_REG_ICR_X2APIC 0x30 //< Interrupt Command Register (QWORD, x2APIC) 38 | #define LAPIC_REG_ICR_LOW 0x30 //< Interrupt Command Register (lower DWORD) 39 | #define LAPIC_REG_ICR_HIGH 0x31 //< Interrupt Command Register (upper DWORD) 40 | #define LAPIC_REG_TIMER 0x32 //< Local: Timer 41 | #define LAPIC_REG_PCINT 0x34 //< Local: Performance Counter 42 | #define LAPIC_REG_LINT0 0x35 //< Local: LINT0 Pin (Normal) 43 | #define LAPIC_REG_LINT1 0x36 //< Local: LINT1 Pin (NMI) 44 | #define LAPIC_REG_ERRINT 0x37 //< Local: Error Interrupt 45 | #define LAPIC_REG_TIMER_INIT 0x38 //< Timer: Initial Count 46 | #define LAPIC_REG_TIMER_CUR 0x39 //< Timer: Current Count 47 | #define LAPIC_REG_TIMER_DIV 0x3E //< Timer: Divisor 48 | 49 | // LAPIC MSRs 50 | #define LAPIC_MSR_BASE 0x01B 51 | #define LAPIC_MSR_REGS 0x800 52 | 53 | // LAPIC Base MSR 54 | #define LAPIC_MSR_BASE_EN (1 << 11) 55 | #define LAPIC_MSR_BASE_EXTD (1 << 10) 56 | 57 | // Interrupt Command Register structure 58 | #define LAPIC_ICR_VECTOR 0 59 | #define LAPIC_ICR_DVL_MODE 8 60 | #define LAPIC_ICR_DEST_MODE 11 61 | #define LAPIC_ICR_DLV_STATUS 12 62 | #define LAPIC_ICR_LEVEL 14 63 | #define LAPIC_ICR_TRIGGER 15 64 | #define LAPIC_ICR_SHORTHAND 18 65 | #define LAPIC_ICR_DEST 56 66 | 67 | // LAPIC timer LVT structure 68 | #define LAPIC_TIMER_VECTOR 0 69 | #define LAPIC_TIMER_MASK 16 70 | #define LAPIC_TIMER_TRIGGER 17 71 | 72 | // Default value for registers 73 | #define LAPIC_TPR 0x0 74 | #define LAPIC_PCINT (1 << 16) 75 | #define LAPIC_SVR 0x20 | (1 << 8) 76 | #define LAPIC_LINT0 (0b111 << 8) | (1 << 15) 77 | #define LAPIC_LINT1 (0b100 << 8) 78 | #define LAPIC_ERRINT (1 << 16) 79 | #define LAPIC_LDR (1 << (lapic_id() % 8)) 80 | 81 | // INIT IPI 82 | #define LAPIC_IPI_INIT ( \ 83 | (APIC_DELIVERY_INIT << LAPIC_ICR_DVL_MODE) | \ 84 | (APIC_SHORT_NONE << LAPIC_ICR_SHORTHAND) | \ 85 | (APIC_TRIGGER_EDGE << LAPIC_ICR_TRIGGER) | \ 86 | (APIC_LEVEL_ASSERT << LAPIC_ICR_LEVEL) | \ 87 | (APIC_MODE_PHYSICAL << LAPIC_ICR_DEST_MODE) ) 88 | 89 | // STARTUP IPI 90 | #define LAPIC_IPI_STARTUP(entry_point) ( \ 91 | (APIC_DELIVERY_STARTUP << LAPIC_ICR_DVL_MODE) | \ 92 | (APIC_SHORT_NONE << LAPIC_ICR_SHORTHAND) | \ 93 | (APIC_TRIGGER_EDGE << LAPIC_ICR_TRIGGER) | \ 94 | (APIC_LEVEL_ASSERT << LAPIC_ICR_LEVEL) | \ 95 | (APIC_MODE_PHYSICAL << LAPIC_ICR_DEST_MODE) | \ 96 | ((entry_point >> 12) << LAPIC_ICR_VECTOR) ) 97 | 98 | /** 99 | * Reads a register of the CPU's LAPIC, given its . 100 | * 101 | * Uses the LAPIC address stored in the info tables. 102 | * Behavior is undefined when called for an invalid register. 103 | * 104 | * @param index the index of the register 105 | * @return value of the register 106 | */ 107 | uint32_t lapic_register_read(uint16_t index); 108 | 109 | /** 110 | * Writes a to a register of the CPU's LAPIC, given its . 111 | * 112 | * Uses the LAPIC address stored in the info tables. 113 | * Behavior is undefined when called for an invalid register. 114 | * 115 | * @param index the index of the register to write 116 | * @param value the new value of the register 117 | */ 118 | void lapic_register_write(uint16_t index, uint32_t value); 119 | 120 | /** 121 | * Detects the CPU's APIC capabilities (x2APIC/xAPIC). 122 | * 123 | * Sets the lapic_x2apic_mode flag, when the x2APIC is present and should 124 | * be used (see kernel header), or panics if a x2APIC is required but none 125 | * is present. Also sets the HY_INFO_FLAG_X2APIC flag in the info tables 126 | * when the x2APIC is used. 127 | * 128 | * As it is assumed that all CPUs either have or do not have an x2APIC 129 | * this function should only be run once on the BSP before lapic_setup() 130 | * is called. 131 | */ 132 | void lapic_detect(void); 133 | 134 | /** 135 | * Enables the CPU's LAPIC and configures it to reasonable defaults. 136 | */ 137 | void lapic_setup(void); 138 | 139 | /** 140 | * Returns the APIC id of the CPU's LAPIC. 141 | * 142 | * @return APIC id 143 | */ 144 | uint32_t lapic_id(void); 145 | 146 | /** 147 | * Signals an EOI to the CPU's LAPIC. 148 | */ 149 | void lapic_eoi(void); 150 | 151 | /** 152 | * Sends an IPI to the given destination and the lower DWORD of the ICR. 153 | * 154 | * In xAPIC mode, pass the physical or logical ID in the destination register 155 | * without shifting it to bit 24. 156 | * 157 | * @param icr_low the lower DWORD for configuring the ICR for this IPI. 158 | * @param destination the destination to send the IPI to. 159 | */ 160 | void lapic_ipi(uint32_t icr_low, uint32_t destination); 161 | 162 | /** 163 | * Updates the LAPIC's timer configuration. 164 | * 165 | * Writes the initial count, the interrupt vector, the interrupt mask and defines, whether 166 | * the timer should restart itself periodically. 167 | * 168 | * @param init_count the timer's initial counter value 169 | * @param vector the vector the timer should raise an interrupt on 170 | * @param mask true, when no interrupts should be raised, false otherwise 171 | * @param periodic whether the timer should fire periodically 172 | */ 173 | void lapic_timer_update(uint32_t init_count, uint8_t vector, bool mask, bool periodic); 174 | 175 | /** 176 | * Calibrates the timer using the PIT and writes the results to the info tables. 177 | */ 178 | void lapic_timer_calibrate(void); 179 | 180 | /** 181 | * Waits for the specified time (in micro seconds) using the LAPIC timer. 182 | * 183 | * Will reset the LAPIC timer and will temporarily change an IDT entry. Make sure 184 | * all other interrupts are masked. 185 | * 186 | * @param time the time to wait in micro seconds 187 | */ 188 | void lapic_timer_wait(uint64_t time); 189 | -------------------------------------------------------------------------------- /loader/inc/main.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Sets up the system to the desired state, which includes: 31 | * 32 | * - creating an info table (from sources like the multiboot table and ACPI) 33 | * - configuring devices (such as the PIC or the IO APIC) 34 | * - moving multiboot modules to a known location in physical memory 35 | * - loading and mapping the kernel binary 36 | * - booting up application processors 37 | */ 38 | 39 | /** 40 | * A barrier used to synchronize BSP and AP entry to the kernel binary. Is one 41 | * as long main_bsp has not finished and is changed to zero when startup is 42 | * complete. 43 | */ 44 | extern volatile uint8_t main_entry_barrier; 45 | 46 | /** 47 | * The long mode entry point for the bootstrap processor. 48 | * 49 | * Sets up the system and triggers application processor startup. 50 | * 51 | * Will wait for all application processors to be booted, then release the 52 | * main_entry_barrier and enter the kernel at its entry point. 53 | */ 54 | void main_bsp(void); 55 | 56 | /** 57 | * The long mode entry point for the application processors. 58 | * 59 | * Sets up the application processor and reports successful startup to the BSP. 60 | * 61 | * When the kernel specified an AP entry point, the AP will spin on the 62 | * main_entry_barrier and then enter the kernel at said entry point; otherwise 63 | * it will halt (hlt). 64 | */ 65 | void main_ap(void); 66 | -------------------------------------------------------------------------------- /loader/inc/multiboot.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * The root multiboot v1 info table. 31 | * 32 | * Contains the address and size of both the memory map and the module list. 33 | */ 34 | typedef struct multiboot_info { 35 | uint32_t flags; 36 | uint32_t mem_lower; 37 | uint32_t mem_upper; 38 | uint32_t boot_device; 39 | uint32_t cmdline; 40 | uint32_t mods_count; 41 | uint32_t mods_addr; 42 | uint32_t aout_tabsz; 43 | uint32_t aout_strsz; 44 | uint32_t aout_addr; 45 | uint32_t aout_resv; 46 | uint32_t mmap_length; 47 | uint32_t mmap_addr; 48 | uint32_t drives_length; 49 | uint32_t config_table; 50 | uint32_t boot_loader_name; 51 | uint32_t apm_table; 52 | uint32_t vbe_control_info; 53 | uint32_t vbe_mode_info; 54 | uint32_t vbe_mode; 55 | uint32_t vbe_interface_seg; 56 | uint16_t vbe_interface_off; 57 | uint16_t vbe_interface_len; 58 | } __attribute__((packed)) multiboot_info_t; 59 | 60 | /** 61 | * An entry in the muliboot memory map. 62 | * 63 | * The size field contains the size of the structure, except for the field itself. 64 | */ 65 | typedef struct multiboot_mmap { 66 | uint32_t size; 67 | uint64_t address; 68 | uint64_t length; 69 | uint32_t type; 70 | } __attribute__((packed)) multiboot_mmap_t; 71 | 72 | /** 73 | * An entry in the multiboot module list. 74 | * 75 | * Represents a module that has been loaded from disk into memory. 76 | */ 77 | typedef struct multiboot_mod { 78 | uint32_t start; 79 | uint32_t end; 80 | uint32_t cmdline; 81 | uint32_t pad; 82 | } __attribute__((packed)) multiboot_mod_t; 83 | 84 | /** 85 | * Pointer to the multiboot info table. 86 | */ 87 | extern multiboot_info_t *multiboot_info; 88 | 89 | /** 90 | * Parses the multiboot info table and adds the gathered data to the 91 | * Hydrogen info structures. 92 | */ 93 | void multiboot_parse(); 94 | -------------------------------------------------------------------------------- /loader/inc/page.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // Page Flags 30 | #define PAGE_FLAG_PRESENT (1 << 0) //< entry is present 31 | #define PAGE_FLAG_WRITABLE (1 << 1) //< page can be written to 32 | #define PAGE_FLAG_USER (1 << 2) //< page can be accessed from DPL=3 33 | #define PAGE_FLAG_GLOBAL (1 << 8) //< page sticks in TLB on CR3 writes 34 | 35 | // Page Model Levels 36 | #define PAGE_LEVEL_PML4 4 37 | #define PAGE_LEVEL_PDP 3 38 | #define PAGE_LEVEL_PD 2 39 | #define PAGE_LEVEL_PT 1 40 | 41 | // Entry analysis 42 | #define PAGE_PHYSICAL(a) (a & (0xFFFFFFFFFFFF << 12)) 43 | #define PAGE_INDEX(a,l) ((a >> (12 + (l - 1) * 9)) & 0x1FF) 44 | 45 | // Page structures 46 | extern uint64_t page_pml4[512]; 47 | extern uint64_t page_idn_pdp[512]; 48 | extern uint64_t page_idn_pd[512 * 64]; 49 | 50 | /** 51 | * Maps the page at the given virtual address to the given physical one and 52 | * sets the provided flags. 53 | * 54 | * The required paging structures are allocated on the heap on demand. 55 | * 56 | * The physical and virtual address are aligned down to the lower page boundary. 57 | * 58 | * @param physical the physical address of the frame to map to 59 | * @param virtual the virtual address of the page to map 60 | * @param flags the flags to map with 61 | */ 62 | void page_map(uintptr_t physical, uintptr_t virtual, uint64_t flags); 63 | 64 | /** 65 | * Invalidates a page in the CPU's TLB. 66 | * 67 | * The virtual address is aligned down to the lower page boundary. 68 | * 69 | * @param virtual the virtual address of the page to invalidate 70 | */ 71 | void page_invalidate(uintptr_t virtual); 72 | -------------------------------------------------------------------------------- /loader/inc/pic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // IO ports for the master PIC 30 | #define PIC_MASTER_IO 0x20 31 | #define PIC_MASTER_CMD_IO PIC_MASTER_IO 32 | #define PIC_MASTER_DATA_IO (PIC_MASTER_IO + 1) 33 | 34 | // IO ports for the slave PIC 35 | #define PIC_SLAVE_IO 0xA0 36 | #define PIC_SLAVE_CMD_IO PIC_SLAVE_IO 37 | #define PIC_SLAVE_DATA_IO (PIC_SLAVE_IO + 1) 38 | 39 | // ICW1 40 | #define PIC_ICW1_ICW4 0x01 //< ICW4 needed 41 | #define PIC_ICW1_SINGLE 0x02 //< Single mode (default: cascade) 42 | #define PIC_ICW1_INTERVAL4 0x04 //< Call address interval 4 (default: 8) 43 | #define PIC_ICW1_LEVEL 0x08 //< Level triggered mode (default: edge) 44 | #define PIC_ICW1_INIT 0x10 //< Initialization 45 | 46 | // ICW4 47 | #define PIC_ICW4_8086 0x01 // 8086/88 mode (default: MCS-80/85) 48 | #define PIC_ICW4_AUTO 0x02 // Auto EOI (default: normal) 49 | #define PIC_ICW4_BUF_SLAVE 0x08 // Buffered mode/slave 50 | #define PIC_ICW4_BUF_MASTER 0x0C // Buffered mode/master 51 | #define PIC_ICW4_SFNM 0x10 // Special fully nested 52 | 53 | // The PIC base vector 54 | #define PIC_VECTOR 0x70 55 | 56 | /** 57 | * Initializes the PIC to a well defined state, then masks all IRQs. 58 | */ 59 | void pic_setup(void); 60 | -------------------------------------------------------------------------------- /loader/inc/pit.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // PIT constants 30 | #define PIT_IO_COUNTER 0x40 //< port to access the counter 31 | #define PIT_IO_INIT 0x43 //< port to initialize the PIT 32 | #define PIT_IRQ 0x0 //< PIT IRQ number (in non PCAT_COMPAT mode) 33 | #define PIT_IRQ_PCAT_COMPAT 0x2 //< PIT IRQ number (in PCAT_COMPAT mode) 34 | #define PIT_FREQ_BASE 1193180 //< frequency of the PIT's oscillator in Hz 35 | #define PIT_VECTOR 0x30 //< interrupt vector used by loader 36 | 37 | /** 38 | * Sets a new PIT frequency (in Hz). 39 | * 40 | * @param freq the new frequency in Hz 41 | */ 42 | void pit_freq_set(uint16_t freq); 43 | 44 | /** 45 | * Routes the PIT interrupt to the default vector (PIT_VECTOR) on the 46 | * calling processor using the IO APIC. 47 | */ 48 | void pit_route(void); 49 | 50 | /** 51 | * Masks the PIT interrupt in the IO APIC again. 52 | */ 53 | void pit_mask(void); 54 | -------------------------------------------------------------------------------- /loader/inc/ports.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Sends a byte to an output . 31 | * 32 | * @param port port to send the byte to 33 | * @param value the byte to send 34 | */ 35 | void outb(uint16_t port, uint8_t value); 36 | 37 | /** 38 | * Reads a byte from an input . 39 | * 40 | * @param port the port to read from 41 | * @return the byte read from the port 42 | */ 43 | uint8_t inb(uint16_t port); 44 | -------------------------------------------------------------------------------- /loader/inc/screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // Screen dimensions 30 | #define SCREEN_WIDTH 80 31 | #define SCREEN_HEIGHT 25 32 | 33 | // Physical address of the screen's video memory 34 | #define SCREEN_VIDEOMEM_PADDR 0xb8000 35 | 36 | // Video memory as a pointer to screen cells 37 | #define SCREEN_VIDEOMEM ((screen_cell_t *) SCREEN_VIDEOMEM_PADDR) 38 | 39 | // The attribute byte to write to all screen cells 40 | #define SCREEN_ATTRIBUTES 0x0F 41 | 42 | // Writes a message to the screen, then enters an infinite loop. 43 | #define SCREEN_PANIC(msg) do { \ 44 | screen_write("PANIC: " msg, 0, 3); \ 45 | while (true); \ 46 | } while (false); 47 | 48 | /** 49 | * A cell in the video memory that contains the displayed character and 50 | * the respective attributes. 51 | */ 52 | typedef struct screen_cell { 53 | uint8_t character; 54 | uint8_t attributes; 55 | } __attribute__((packed)) screen_cell_t; 56 | 57 | /** 58 | * Writes a to the screen, given the coordinates. 59 | * 60 | * @param message the message to write. 61 | * @param x the x coordinate to write the message to. 62 | * @param y the y coordinate to write the message to. 63 | */ 64 | void screen_write(const char *message, uint16_t x, uint16_t y); 65 | 66 | /** 67 | * Writes a to the screen, given the coordinates. 68 | * 69 | * @param number the number to write. 70 | * @param x the x coordinate to write the number to. 71 | * @param y the y coordinate to write the number to. 72 | */ 73 | void screen_write_hex(uint64_t number, uint16_t x, uint16_t y); 74 | 75 | /** 76 | * Clears the screen. 77 | */ 78 | void screen_clear(void); 79 | -------------------------------------------------------------------------------- /loader/inc/smp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * The address in physical memory the 16 bit bootstrap code should reside in. 31 | */ 32 | #define SMP_BOOT16_TARGET 0x1000 33 | 34 | /** 35 | * The number of started APs. Used by smp_boot_all() to determine, when the initialization 36 | * of an AP is complete. 37 | */ 38 | extern volatile uint64_t smp_ready_count; 39 | 40 | /** 41 | * Boots all application processors (APs) that have an entry in the info tables. 42 | * 43 | * Will return, when all APs are successfully started. 44 | */ 45 | void smp_setup(void); 46 | -------------------------------------------------------------------------------- /loader/inc/stdint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | 28 | /** 29 | * Often used type declarations for various differently sized integer types. 30 | */ 31 | 32 | typedef unsigned char uint8_t; 33 | typedef char int8_t; 34 | typedef unsigned short uint16_t; 35 | typedef short int16_t; 36 | typedef unsigned int uint32_t; 37 | typedef int int32_t; 38 | typedef unsigned long long uint64_t; 39 | typedef long long int64_t; 40 | 41 | typedef uint64_t uintptr_t; 42 | typedef int64_t intptr_t; 43 | typedef uint64_t size_t; 44 | typedef char bool; 45 | 46 | #define true 1 47 | #define TRUE 1 48 | #define false 0 49 | #define FALSE 0 50 | -------------------------------------------------------------------------------- /loader/inc/string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | size_t strlen(const int8_t *str); 30 | uint8_t strcmp(const int8_t *a, const int8_t *b); 31 | int8_t *strcpy(int8_t *dest, const int8_t *src); 32 | int8_t *strstr(const int8_t *haystack, const int8_t *needle); 33 | 34 | void memcpy(void *dest, void *src, size_t length); 35 | void memset(void *dest, uint8_t c, size_t length); 36 | uintptr_t memalign(uintptr_t address, size_t boundary); 37 | bool memcmp(void *a, void *b, size_t len); 38 | -------------------------------------------------------------------------------- /loader/inc/syscall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // Fast Syscall MSR IDs 30 | #define SYSCALL_MSR_STAR 0xC0000081 31 | #define SYSCALL_MSR_LSTAR 0xC0000082 32 | #define SYSCALL_MSR_CSTAR 0xC0000083 33 | #define SYSCALL_MSR_SFMASK 0xC0000084 34 | 35 | // Default values for fast syscall MSRs 36 | #define SYSCALL_STAR (((uint64_t) 0x8 << 32) | ((uint64_t) 0x18 << 48)) 37 | #define SYSCALL_SFMASK (1 << 9) 38 | 39 | /** 40 | * Initializes the processor's fast system call capabilities by writing 41 | * the related MSRs. The long-mode system call entry point is provided 42 | * by the kernel in the syscall_entry field of the header. 43 | */ 44 | void syscall_init(void); 45 | -------------------------------------------------------------------------------- /loader/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | ENTRY(boot32_bsp) 3 | SECTIONS { 4 | .text 0x100000 : { 5 | *(.multiboot) 6 | *(.text) 7 | *(.rodata) 8 | } 9 | 10 | .data : { 11 | *(.data) 12 | } 13 | 14 | .bss : { 15 | *(.bss) 16 | } 17 | 18 | .info 0x108000 : { 19 | idt_data = .; . += 4096; 20 | gdt_data = .; . += 4096; 21 | page_pml4 = .; . += 4096; 22 | page_idn_pdp = .; . += 4096; 23 | page_idn_pd = .; . += 4096 * 64; 24 | info_root_data = .; . += 4096; 25 | info_mmap_data = .; . += 4096; 26 | info_module_data = .; . += 4096; 27 | info_ioapic_data = .; . += 4096; 28 | info_strings_data = .; . += 4096; 29 | } 30 | 31 | /DISCARD/ : { 32 | *(.eh_frame) 33 | *(.comment) 34 | } 35 | 36 | . = ALIGN(4096); 37 | heap_mark = .; 38 | } -------------------------------------------------------------------------------- /loader/src/boot16.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text16 25 | bits 16 26 | 27 | extern boot32_ap 28 | global boot16_begin 29 | global boot16_end 30 | 31 | ; The location this code will be moved to 32 | %define TARGET 0x1000 33 | 34 | ; Marks the beginning of the 16 bit boot code 35 | boot16_begin: 36 | 37 | ; Entry point for the APs starting in real mode. 38 | boot16: 39 | jmp 0x0:.cs_cleared - boot16_begin + TARGET ; Clear CS 40 | 41 | .cs_cleared: 42 | cli ; Clear interrupts 43 | in al, 0x92 ; Activate A20 44 | or al, 2 45 | out 0x92, al 46 | lgdt [cs:boot16_gdtr - boot16_begin + TARGET] ; Load GDT 47 | mov eax, cr0 ; Enable PM 48 | or al, 1 49 | mov cr0, eax 50 | jmp 0x8:boot16_trampoline - boot16_begin + TARGET ; Jump to 32 bit trampoline 51 | 52 | boot16_gdtr: 53 | .Limit: dw 0x17 54 | .Base: dd boot16_gdt - boot16_begin + TARGET 55 | 56 | boot16_gdt: 57 | .Null: dw 0x0000, 0x0000, 0x0000, 0x0000 58 | .Code: dw 0xFFFF, 0x0000, 0x9A00, 0x00CF 59 | .Data: dw 0xFFFF, 0x0000, 0x9200, 0x00CF 60 | 61 | bits 32 62 | boot16_trampoline: 63 | mov eax, 0x10 ; Setup data segment selectors 64 | mov ds, ax 65 | mov es, ax 66 | mov fs, ax 67 | mov gs, ax 68 | mov ss, ax 69 | mov eax, boot32_ap ; Jump to 32 bit bootstrap 70 | jmp eax 71 | 72 | boot16_end: 73 | -------------------------------------------------------------------------------- /loader/src/boot32.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text 25 | bits 32 26 | 27 | global boot32_bsp 28 | global boot32_ap 29 | extern heap_top 30 | extern multiboot_info 31 | extern main_bsp 32 | extern main_ap 33 | extern gdt_data 34 | extern gdt_pointer 35 | extern page_pml4 36 | extern page_idn_pdp 37 | extern page_idn_pd 38 | 39 | ; Protected mode entry point for the BSP. 40 | ; 41 | ; Directly entered by the multiboot bootloader; a pointer to the multiboot info 42 | ; tables is stored in EBX. 43 | boot32_bsp: 44 | cli ; Clear interrupts 45 | mov dword [multiboot_info], ebx ; Store multiboot pointer 46 | 47 | mov esp, boot32_stack_bsp ; Load BSP stack 48 | add esp, 0x1000 ; Advance to top of stack 49 | 50 | call boot32_gdt ; Setup 64 bit GDT 51 | call boot32_map ; Setup mapping 52 | call boot32_common ; Common bootstrap 53 | 54 | mov ax, 0x10 ; Setup data segment selectors 55 | mov ds, ax 56 | mov ss, ax 57 | mov gs, ax 58 | mov fs, ax 59 | mov es, ax 60 | 61 | jmp 0x8:main_bsp ; Far jump 62 | 63 | ; Protected mode entry point for the APs. 64 | ; 65 | ; Entered by the real mode bootstrap code. 66 | boot32_ap: 67 | cli ; Clear interrupts 68 | 69 | add dword [heap_top], 0x1000 ; Allocate stack from heap 70 | mov esp, dword [heap_top] ; Load top of allocated stack 71 | 72 | call boot32_common ; Common bootstrap 73 | jmp 0x8:main_ap ; Far jump 74 | 75 | ; Common initialization for both, the BSP and the APs. 76 | boot32_common: 77 | mov eax, 0x80000001 ; Check for long mode support 78 | cpuid ; using CPUID 79 | and edx, (1 << 29) 80 | cmp edx, 0 81 | jne .long_mode_supported ; Long mode supported 82 | 83 | mov edi, boot32_msg_nolm ; Panic 84 | call boot32_panic 85 | 86 | .long_mode_supported: 87 | mov eax, cr4 ; Enable PAE 88 | or eax, 1 << 5 89 | mov cr4, eax 90 | 91 | in al, 0x92 ; Enable A20 92 | or al, 2 93 | out 0x92, al 94 | 95 | mov ecx, 0xC0000080 ; Enable LM in MSR 96 | rdmsr 97 | or eax, 1 << 8 98 | wrmsr 99 | 100 | mov eax, gdt_pointer ; Load the 64 bit GDT pointer 101 | lgdt [eax] ; Load the 64 bit GDT 102 | 103 | mov eax, page_pml4 ; Load PML4 address 104 | mov cr3, eax ; Load the PML4 105 | 106 | mov eax, cr0 ; Enable paging 107 | or eax, 1 << 31 108 | mov cr0, eax 109 | ret 110 | 111 | ; Sets up 64 bit GDT. 112 | boot32_gdt: 113 | mov edi, gdt_data ; Target pointer 114 | mov esi, boot32_gdt_data ; Source pointer 115 | mov ecx, boot32_gdt_data.end ; Length 116 | sub ecx, esi 117 | .next: 118 | lodsb 119 | stosb 120 | dec ecx 121 | cmp ecx, 0 122 | jne .next 123 | ret 124 | 125 | ; Sets up identity mapping. 126 | boot32_map: 127 | mov eax, page_idn_pdp ; Map identity PDP in PML4 128 | or eax, 0b11 ; Present + Writable 129 | mov dword [page_pml4], eax ; First entry in PML4 130 | 131 | mov edi, page_idn_pdp ; Map PDPEs to PDs 132 | mov ecx, 64 ; Write 64 entries 133 | mov eax, page_idn_pd 134 | or eax, 0b11 135 | 136 | .next_pdpe: 137 | stosd ; Write lower DWORD of entry 138 | add edi, 4 ; Skip upper DWORD 139 | add eax, 0x1000 ; Advance by one page 140 | dec ecx ; Decrease number of remaining entries 141 | 142 | cmp ecx, 0 ; Entries left? 143 | jne .next_pdpe 144 | 145 | mov eax, 0b10000011 ; Present + Writable + 2MB pages; start at 0x0 146 | mov edi, page_idn_pd ; Identity map PDs to memory 147 | mov ecx, 512 * 64 ; 512 entries in 64 PDs 148 | 149 | .next_pde: 150 | stosd ; Write lower DWORD of entry 151 | add edi, 4 ; Skip upper DWORD 152 | add eax, 0x200000 ; Advance by one 2MB page 153 | dec ecx ; Decrease number of remaining entries 154 | 155 | cmp ecx, 0 ; Entries left? 156 | jne .next_pde 157 | ret 158 | 159 | ; Writes a message to the screen, then enters an infinite loop. 160 | ; 161 | ; Parameters: 162 | ; ESI pointer to the message to write. 163 | boot32_panic: 164 | mov edi, 0xb8000 ; Write to VGA video memory 165 | .next_byte: 166 | lodsb ; Load character 167 | cmp al, 0 ; Null? 168 | je .end 169 | or ax, 0x00F0 ; Black on white 170 | stosb ; Write to screen 171 | jmp .next_byte ; Continue with next byte 172 | 173 | .end: 174 | jmp $ ; Infinite loop 175 | 176 | section .rodata 177 | boot32_msg_nolm: db "64 bit long mode not supported on this CPU.", 0 178 | 179 | boot32_gdt_data: 180 | .null: 181 | dd 0x0 182 | dd 0x0 183 | .kernel_code: 184 | dd 0x0 185 | dd 0x209800 186 | .kernel_data: 187 | dd 0x0 188 | dd 0x209200 189 | .user_code: 190 | dd 0x0 191 | dd 0x20F800 192 | .user_data: 193 | dd 0x0 194 | dd 0x20F200 195 | .end: 196 | 197 | section .bss 198 | 199 | align 4096 200 | boot32_stack_bsp: resb 0x1000 201 | -------------------------------------------------------------------------------- /loader/src/cpu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | uint64_t cpu_msr_read(uint32_t msr) 30 | { 31 | uint32_t a, d; 32 | asm volatile ("rdmsr" : "=a" (a), "=d" (d) : "c" (msr)); 33 | 34 | return (((uint64_t) d) << 32) | a; 35 | } 36 | 37 | void cpu_msr_write(uint32_t msr, uint64_t value) 38 | { 39 | uint32_t a = value; 40 | uint32_t d = (value >> 32); 41 | 42 | asm volatile ("wrmsr" :: "c" (msr), "a" (a), "d" (d)); 43 | } 44 | 45 | void cpu_cpuid(uint32_t code, cpu_cpuid_result_t *result) 46 | { 47 | asm volatile ( 48 | "cpuid" : 49 | "=a" (result->a), 50 | "=b" (result->b), 51 | "=c" (result->c), 52 | "=d" (result->d) : 53 | "a" (code)); 54 | } 55 | -------------------------------------------------------------------------------- /loader/src/elf64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | uint64_t elf64_hash(const char *name) 35 | { 36 | uint64_t h = 0, g; 37 | 38 | while (*name) { 39 | h = (h << 4) + *name++; 40 | g = h & 0xf0000000; 41 | 42 | if (g != 0) 43 | h ^= g >> 24; 44 | 45 | h &= 0x0fffffff; 46 | } 47 | 48 | return h; 49 | } 50 | 51 | elf64_shdr_t *elf64_shdr_find(uint32_t type, void *binary) 52 | { 53 | elf64_ehdr_t *ehdr = (elf64_ehdr_t *) binary; 54 | elf64_shdr_t *shdr_list = (elf64_shdr_t *) ((uintptr_t) binary + ehdr->e_shoff); 55 | 56 | size_t i; 57 | for (i = 0; i < ehdr->e_shnum; ++i) { 58 | elf64_shdr_t *shdr = &shdr_list[i]; 59 | 60 | if (type == shdr->sh_type) { 61 | return shdr; 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | elf64_sym_t *elf64_sym_find(const char *name, void *binary) 69 | { 70 | elf64_ehdr_t *ehdr = (elf64_ehdr_t *) binary; 71 | elf64_shdr_t *symtab_hdr = elf64_shdr_find(ELF_SHT_SYMTAB, binary); 72 | 73 | if (0 == symtab_hdr) { 74 | return 0; 75 | } 76 | 77 | elf64_shdr_t *strtab_hdr = (elf64_shdr_t *) ( 78 | ehdr->e_shoff + 79 | symtab_hdr->sh_link * ehdr->e_shentsize + 80 | (uintptr_t) binary); 81 | 82 | char *strtab = (char *) (strtab_hdr->sh_offset + (uintptr_t) binary); 83 | elf64_sym_t *symtab = (elf64_sym_t *) (symtab_hdr->sh_offset + (uintptr_t) binary); 84 | 85 | size_t i; 86 | size_t symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize; 87 | for (i = 0; i < symbol_count; ++i) { 88 | elf64_sym_t *symbol = (elf64_sym_t *) ((uintptr_t) symtab + i * symtab_hdr->sh_entsize); 89 | char *symname = &strtab[symbol->st_name]; 90 | 91 | if (strcmp(symname, name)) { 92 | return symbol; 93 | } 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | void elf64_load(void *binary) 100 | { 101 | elf64_ehdr_t *ehdr = (elf64_ehdr_t *) binary; 102 | 103 | size_t i; 104 | for (i = 0; i < ehdr->e_phnum; ++i) { 105 | elf64_phdr_t *phdr = (elf64_phdr_t *) ((uintptr_t) binary + ehdr->e_phoff + i * ehdr->e_phsize); 106 | 107 | if (ELF_PT_LOAD != phdr->p_type) 108 | continue; 109 | 110 | uintptr_t source = (uintptr_t) binary + phdr->p_offset; 111 | uintptr_t target = (uintptr_t) heap_alloc(phdr->p_memsz); 112 | 113 | memcpy((void *) target, (void *) source, phdr->p_filesz); 114 | memset((void *) (target + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz); 115 | 116 | size_t offset; 117 | for (offset = 0; offset < phdr->p_memsz; offset += 0x1000) { 118 | page_map(target + offset, phdr->p_vaddr + offset, PAGE_FLAG_WRITABLE | PAGE_FLAG_GLOBAL); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /loader/src/gdt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | gdt_pointer_t gdt_pointer = {GDT_LENGTH - 1, (uintptr_t) &gdt_data}; 31 | -------------------------------------------------------------------------------- /loader/src/heap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | uintptr_t heap_top = 0; 32 | 33 | /** 34 | * Sorts the modules in the info tables by their address in ascending order. 35 | * 36 | * This procedure is required in order to prevent clobbering the modules when 37 | * moving them to an area that is intersecting with the area the modules were 38 | * originally stored in. 39 | */ 40 | static void heap_modules_sort(void) 41 | { 42 | size_t count = info_root->module_count; 43 | size_t i, j; 44 | 45 | if (count > 1) { 46 | for (i = 0; i < count - 1; ++i) { 47 | uintptr_t min_addr = 0; 48 | size_t min_idx = -1; 49 | 50 | for (j = i; i < count; ++j) { 51 | hy_info_module_t *mod = &info_module[j]; 52 | if (mod->address < min_addr) { 53 | min_idx = j; 54 | min_addr = mod->address; 55 | } 56 | } 57 | 58 | if (i != min_idx) { 59 | hy_info_module_t tmp; 60 | memcpy(&tmp, &info_module[i], sizeof(hy_info_module_t)); 61 | memcpy(&info_module[i], &info_module[min_idx], sizeof(hy_info_module_t)); 62 | memcpy(&info_module[min_idx], &tmp, sizeof(hy_info_module_t)); 63 | } 64 | } 65 | } 66 | } 67 | 68 | /** 69 | * Moves the modules to the end of the heap. 70 | */ 71 | static void heap_modules_move(void) 72 | { 73 | size_t i; 74 | for (i = 0; i < info_root->module_count; ++i) { 75 | hy_info_module_t *mod = &info_module[i]; 76 | void *buffer = heap_alloc(mod->length); 77 | 78 | memcpy((void *) buffer, (void *) mod->address, mod->length); 79 | 80 | mod->address = (uintptr_t) buffer; 81 | } 82 | } 83 | 84 | void heap_init(void) 85 | { 86 | extern uint8_t heap_mark; 87 | heap_top = (uintptr_t) &heap_mark; 88 | 89 | heap_modules_sort(); 90 | heap_modules_move(); 91 | } 92 | 93 | void *heap_alloc(size_t size) 94 | { 95 | size = (size + 0xFFF) & ~0xFFF; 96 | uintptr_t chunk = heap_top; 97 | heap_top += size; 98 | 99 | return (void *) chunk; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /loader/src/idt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | uintptr_t idt_address = (uintptr_t) &idt_data; 34 | 35 | static void idt_fault_pf(void) 36 | { 37 | asm volatile ("cli"); 38 | SCREEN_PANIC("Page fault."); 39 | } 40 | 41 | static void idt_fault_gp(void) 42 | { 43 | asm volatile ("cli"); 44 | SCREEN_PANIC("General Protection fault."); 45 | } 46 | 47 | void idt_load(uintptr_t address, size_t length) 48 | { 49 | idt_pointer_t pointer = {length - 1, address}; 50 | asm volatile ("lidt (%0)" :: "a" (&pointer)); 51 | } 52 | 53 | void idt_intgate(idt_entry_t *entry, uintptr_t handler, uint16_t cs, uint8_t dpl) 54 | { 55 | entry->handlerLow = handler & 0xFFFF; 56 | entry->handlerMiddle = (handler >> 16) & 0xFFFF; 57 | entry->handlerHigh = (handler >> 32) & 0xFFFFFFFF; 58 | 59 | entry->cs = cs; 60 | 61 | entry->flags = 0xE; // interrupt gate 62 | entry->flags |= (dpl & 0b11) << 5; // dpl 63 | entry->flags |= (1 << 7); // present 64 | 65 | entry->ist = 0; 66 | entry->zero = 0; 67 | } 68 | 69 | void idt_setup_loader(void) 70 | { 71 | size_t i; 72 | for (i = 0; i < IDT_MAX; ++i) { 73 | idt_intgate(&idt_data[i], (uintptr_t) &idt_null_handler, 0x8, 0x0); 74 | } 75 | 76 | idt_intgate(&idt_data[14], (uintptr_t) &idt_fault_pf, 0x8, 0x0); 77 | idt_intgate(&idt_data[13], (uintptr_t) &idt_fault_gp, 0x8, 0x0); 78 | } 79 | 80 | void idt_setup_kernel(void) 81 | { 82 | bool present = (0 != kernel_header->isr_entry_table); 83 | uint64_t *table = (uint64_t *) kernel_header->isr_entry_table; 84 | 85 | size_t i; 86 | for (i = 0; i < IDT_MAX; ++i) { 87 | uint64_t handler = (present ? table[i] : 0); 88 | idt_intgate(&idt_data[i], handler, 0x8, 0x0); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /loader/src/idt.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text 25 | bits 64 26 | 27 | global idt_null_handler 28 | 29 | idt_null_handler: 30 | iretq 31 | -------------------------------------------------------------------------------- /loader/src/info.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | extern uint8_t info_root_data INFO_SECTION; 34 | extern uint8_t info_mmap_data INFO_SECTION; 35 | extern uint8_t info_module_data INFO_SECTION; 36 | extern uint8_t info_ioapic_data INFO_SECTION; 37 | extern uint8_t info_strings_data INFO_SECTION; 38 | 39 | hy_info_root_t *info_root = (hy_info_root_t *) &info_root_data; 40 | hy_info_cpu_t *info_cpu = 0; 41 | hy_info_ioapic_t *info_ioapic = (hy_info_ioapic_t *) &info_ioapic_data; 42 | hy_info_mmap_t *info_mmap = (hy_info_mmap_t *) &info_mmap_data; 43 | hy_info_module_t *info_module = (hy_info_module_t *) &info_module_data; 44 | 45 | char *info_strings = (char *) &info_strings_data; 46 | char *info_strings_next = (char *) &info_strings_data; 47 | uint32_t info_string_space = 0x1000; 48 | 49 | void info_init(void) 50 | { 51 | info_root->magic = HY_MAGIC; 52 | info_root->length = 0x5000; 53 | 54 | info_root->idt_paddr = (uintptr_t) &idt_data; 55 | info_root->gdt_paddr = (uintptr_t) &gdt_data; 56 | 57 | info_root->mmap_offset = ((uintptr_t) info_mmap - (uintptr_t) info_root); 58 | info_root->module_offset = ((uintptr_t) info_module - (uintptr_t) info_root); 59 | info_root->string_offset = ((uintptr_t) info_strings - (uintptr_t) info_root); 60 | info_root->ioapic_offset = ((uintptr_t) info_ioapic - (uintptr_t) info_root); 61 | 62 | size_t i; 63 | for (i = 0; i < 16; ++i) { 64 | info_root->irq_gsi[i] = i; 65 | } 66 | } 67 | 68 | char *info_string_alloc(size_t length) 69 | { 70 | ++length; 71 | 72 | if (length > info_string_space) { 73 | // TODO: PANIC 74 | } 75 | 76 | char *allocated = info_strings_next; 77 | info_strings_next = &info_strings_next[length]; 78 | info_string_space -= length; 79 | 80 | return allocated; 81 | } 82 | -------------------------------------------------------------------------------- /loader/src/ioapic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static int8_t ioapic_irq_by_gsi(uint32_t gsi) 34 | { 35 | size_t irq; 36 | for (irq = 0; irq < 16; ++irq) { 37 | if (info_root->irq_gsi[irq] == gsi) { 38 | return irq; 39 | } 40 | } 41 | 42 | return -1; 43 | } 44 | 45 | static void ioapic_setup(bool kernel) 46 | { 47 | size_t i, j; 48 | for (i = 0; i < info_root->ioapic_count; ++i) { 49 | hy_info_ioapic_t *ioapic = &info_ioapic[i]; 50 | 51 | for (j = 0; j < ioapic->gsi_count; ++j) { 52 | uint32_t gsi = ioapic->gsi_base + j; 53 | ioapic_redir_set(j, ioapic_redir_forge(gsi, kernel), ioapic); 54 | } 55 | } 56 | } 57 | 58 | hy_info_ioapic_t *ioapic_get_by_gsi(uint32_t gsi) 59 | { 60 | size_t i; 61 | 62 | for (i = 0; i < info_root->ioapic_count; ++i) { 63 | hy_info_ioapic_t *ioapic = &info_ioapic[i]; 64 | 65 | uint32_t start = ioapic->gsi_base; 66 | uint32_t end = start + ioapic->gsi_count; 67 | 68 | if (gsi >= start && gsi < end) 69 | return ioapic; 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | uint32_t ioapic_register_read(uint16_t index, hy_info_ioapic_t *ioapic) 76 | { 77 | *IOAPIC_MMIO_REGSEL_PTR(ioapic) = index; 78 | return *IOAPIC_MMIO_IOWIN_PTR(ioapic); 79 | } 80 | 81 | uint32_t ioapic_register_write(uint16_t index, uint32_t value, hy_info_ioapic_t *ioapic) 82 | { 83 | *IOAPIC_MMIO_REGSEL_PTR(ioapic) = index; 84 | uint32_t old = *IOAPIC_MMIO_IOWIN_PTR(ioapic); 85 | *IOAPIC_MMIO_IOWIN_PTR(ioapic) = value; 86 | 87 | return old; 88 | } 89 | 90 | uint64_t ioapic_redir_get(uint16_t index, hy_info_ioapic_t *ioapic) 91 | { 92 | uint16_t register_index = IOAPIC_REG_REDTBL + index * 2; 93 | 94 | uint32_t low = ioapic_register_read(register_index, ioapic); 95 | uint32_t high = ioapic_register_read(register_index + 1, ioapic); 96 | 97 | return low | ((uint64_t) high << 32); 98 | } 99 | 100 | void ioapic_redir_set(uint16_t index, uint64_t redir, hy_info_ioapic_t *ioapic) 101 | { 102 | uint16_t register_index = IOAPIC_REG_REDTBL + index * 2; 103 | 104 | ioapic_register_write(register_index, redir, ioapic); 105 | ioapic_register_write(register_index + 1, redir >> 32, ioapic); 106 | } 107 | 108 | void ioapic_analyze(void) 109 | { 110 | size_t i; 111 | 112 | for (i = 0; i < info_root->ioapic_count; ++i) { 113 | hy_info_ioapic_t *ioapic = &info_ioapic[i]; 114 | 115 | uint32_t version_reg = ioapic_register_read(IOAPIC_REG_VERSION, ioapic); 116 | 117 | uint8_t version = version_reg & 0xFF; 118 | uint8_t max_entry = (version_reg >> 16) & 0xFF; 119 | 120 | ioapic->version = version; 121 | ioapic->gsi_count = max_entry + 1; 122 | } 123 | } 124 | 125 | uint64_t ioapic_redir_forge(uint32_t gsi, bool kernel) 126 | { 127 | uint64_t redir = IOAPIC_REDIR_LOADER; 128 | 129 | if (kernel) { 130 | redir = (0 == (kernel_header->flags & HY_HEADER_FLAG_IOAPIC_BSP)) 131 | ? IOAPIC_REDIR_KERNEL : IOAPIC_REDIR_KERNEL_BSP; 132 | } 133 | 134 | int8_t irq = ioapic_irq_by_gsi(gsi); 135 | 136 | if (irq >= 0) { 137 | uint8_t flags = info_root->irq_flags[(size_t) irq]; 138 | 139 | if (0 != (HY_INFO_IRQ_FLAG_ACTIVE_LOW & flags)) { 140 | redir |= (APIC_POLARITY_LOW << IOAPIC_REDIR_POL); 141 | } else { 142 | redir |= (APIC_POLARITY_HIGH << IOAPIC_REDIR_POL); 143 | } 144 | 145 | redir |= (APIC_POLARITY_HIGH << IOAPIC_REDIR_POL); 146 | 147 | if (0 != (HY_INFO_IRQ_FLAG_LEVEL & flags)) { 148 | redir |= (APIC_TRIGGER_LEVEL << IOAPIC_REDIR_TRIGGER); 149 | } else { 150 | redir |= (APIC_TRIGGER_EDGE << IOAPIC_REDIR_TRIGGER); 151 | } 152 | } else { 153 | // Assume its a PCI-like interrupt line then 154 | redir |= (APIC_TRIGGER_LEVEL << IOAPIC_REDIR_TRIGGER); 155 | redir |= (APIC_POLARITY_LOW << IOAPIC_REDIR_POL); 156 | } 157 | 158 | if (kernel) { 159 | bool mask = 1; 160 | uint8_t vector = 0; 161 | 162 | if (irq >= 0) { 163 | hy_header_irq_t *config = &kernel_header->irqs[(size_t) irq]; 164 | mask = (0 != (config->flags & HY_HEADER_IRQ_FLAG_MASK)); 165 | vector = config->vector; 166 | } 167 | 168 | redir |= ((uint64_t) mask << IOAPIC_REDIR_MASK); 169 | redir |= vector; 170 | 171 | } else { 172 | redir |= (1 << IOAPIC_REDIR_MASK); 173 | } 174 | 175 | return redir; 176 | } 177 | 178 | void ioapic_setup_kernel(void) 179 | { 180 | ioapic_setup(true); 181 | } 182 | 183 | void ioapic_setup_loader(void) 184 | { 185 | ioapic_setup(false); 186 | } 187 | -------------------------------------------------------------------------------- /loader/src/kernel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | void *kernel_binary = 0; 39 | hy_header_root_t *kernel_header = 0; 40 | 41 | void kernel_find(void) 42 | { 43 | size_t i; 44 | 45 | for (i = 0; i < info_root->module_count; ++i) { 46 | hy_info_module_t *mod = &info_module[i]; 47 | char *name = &info_strings[mod->name]; 48 | 49 | if (strstr(name, KERNEL_NAME) == name) { 50 | kernel_binary = (void *) mod->address; 51 | return; 52 | } 53 | } 54 | 55 | SCREEN_PANIC("Could not find kernel binary."); 56 | } 57 | 58 | void kernel_check(void) 59 | { 60 | elf64_ehdr_t *ehdr = (elf64_ehdr_t *) kernel_binary; 61 | 62 | if (ehdr->e_ident_mag != ELFMAG || 63 | ehdr->e_ident_class != ELFCLASS64 || 64 | ehdr->e_type != ELF_ET_EXEC) { 65 | SCREEN_PANIC("Kernel is not an ELF64 executable."); 66 | } 67 | } 68 | 69 | void kernel_analyze(void) 70 | { 71 | elf64_sym_t *sym = elf64_sym_find(HY_HEADER_SYMNAME, kernel_binary); 72 | 73 | if (0 == sym) { 74 | SCREEN_PANIC("The kernel binary does not provide a Hydrogen header."); 75 | } 76 | 77 | kernel_header = (hy_header_root_t *) sym->st_value; 78 | 79 | if (kernel_header->magic != HY_MAGIC) { 80 | SCREEN_PANIC("Invalid magic value in kernel header."); 81 | } 82 | } 83 | 84 | void kernel_map_stack(void) 85 | { 86 | if (0 == kernel_header->stack_vaddr) 87 | return; 88 | 89 | if (0 != (kernel_header->stack_vaddr & 0xFFF)) { 90 | SCREEN_PANIC("Virtual stack address in kernel header not page-aligned."); 91 | } 92 | 93 | uintptr_t stack_begin, stack_address, stack_offset; 94 | asm volatile ("mov %%rsp, %0" : "=a" (stack_address)); 95 | stack_begin = (stack_address - 1) & ~0xFFF; 96 | stack_offset = stack_address - stack_begin; 97 | 98 | uintptr_t stack_target = kernel_header->stack_vaddr + 0x1000 * lapic_id(); 99 | page_map(stack_address, stack_target, PAGE_FLAG_WRITABLE | PAGE_FLAG_GLOBAL); 100 | 101 | asm volatile ("mov %0, %%rsp" :: "a" (stack_target + stack_offset)); 102 | } 103 | 104 | void kernel_map_info(void) 105 | { 106 | if (0 == kernel_header->info_vaddr) 107 | return; 108 | 109 | size_t length = info_root->length; 110 | size_t offset; 111 | 112 | uintptr_t physical = (uintptr_t) info_root; 113 | uintptr_t virtual = kernel_header->info_vaddr; 114 | 115 | for (offset = 0; offset < length; offset += 0x1000) { 116 | page_map(physical + offset, virtual + offset, PAGE_FLAG_WRITABLE | PAGE_FLAG_GLOBAL); 117 | } 118 | } 119 | 120 | void kernel_map_idt(void) 121 | { 122 | if (0 == kernel_header->idt_vaddr) 123 | return; 124 | 125 | uintptr_t phys = (uintptr_t) &idt_data; 126 | 127 | page_map( 128 | phys, 129 | kernel_header->idt_vaddr, 130 | PAGE_FLAG_WRITABLE | PAGE_FLAG_GLOBAL); 131 | 132 | idt_address = kernel_header->idt_vaddr; 133 | } 134 | 135 | void kernel_map_gdt(void) 136 | { 137 | if (0 == kernel_header->gdt_vaddr) 138 | return; 139 | 140 | uintptr_t phys = gdt_pointer.address; 141 | 142 | page_map( 143 | phys, 144 | kernel_header->gdt_vaddr, 145 | PAGE_FLAG_WRITABLE | PAGE_FLAG_GLOBAL); 146 | 147 | gdt_pointer.address = kernel_header->gdt_vaddr; 148 | } 149 | 150 | extern void kernel_enter(uintptr_t address); 151 | 152 | void kernel_enter_bsp(void) 153 | { 154 | kernel_enter(((elf64_ehdr_t *) kernel_binary)->e_entry); 155 | } 156 | 157 | void kernel_enter_ap(void) 158 | { 159 | if (0 == kernel_header->ap_entry) { 160 | while (1) { asm volatile ("hlt"); } 161 | } else { 162 | kernel_enter(kernel_header->ap_entry); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /loader/src/kernel.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text 25 | bits 64 26 | 27 | global kernel_enter 28 | extern gdt_pointer 29 | extern idt_address 30 | extern idt_load 31 | 32 | ; Resets the stack and jumps to the kernel, given the entry address. 33 | ; 34 | ; Parameters: 35 | ; RDI the entry address 36 | ; 37 | kernel_enter: 38 | push rdi ; Save RDI 39 | 40 | mov rax, gdt_pointer ; Reload GDT 41 | lgdt [rax] 42 | 43 | mov rdi, qword [idt_address] ; Reload IDT 44 | mov rsi, 0xFFF 45 | call idt_load 46 | 47 | pop rdi ; Reload RDI 48 | 49 | mov rax, rsp ; Reset the stack 50 | sub rax, 1 51 | and rax, ~0xFFF 52 | add rax, 0x1000 53 | mov rsp, rax 54 | 55 | push rdi ; Push rdi as a return address 56 | 57 | xor rax, rax ; Clear registers 58 | xor rbx, rbx 59 | xor rcx, rcx 60 | xor rdx, rdx 61 | xor rsi, rsi 62 | xor rdi, rdi 63 | xor rbp, rbp 64 | xor r8, r8 65 | xor r9, r9 66 | xor r10, r10 67 | xor r11, r11 68 | xor r12, r12 69 | xor r13, r13 70 | xor r14, r14 71 | xor r15, r15 72 | 73 | ret ; "return" to the kernel 74 | -------------------------------------------------------------------------------- /loader/src/lapic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define LAPIC_X2APIC_MODE (0 != (HY_INFO_FLAG_X2APIC & info_root->flags)) 38 | 39 | void lapic_detect(void) 40 | { 41 | cpu_cpuid_result_t cpuid; 42 | cpu_cpuid(0x1, &cpuid); 43 | bool x2apic_supported = (0 != ((1 << 21) & cpuid.c)); 44 | 45 | if (0 != (kernel_header->flags & HY_HEADER_FLAG_X2APIC_ALLOW)) { 46 | if (x2apic_supported) { 47 | info_root->flags |= HY_INFO_FLAG_X2APIC; 48 | 49 | } else if (0 != (kernel_header->flags & HY_HEADER_FLAG_X2APIC_REQUIRE)) { 50 | SCREEN_PANIC("x2APIC required but not supported."); 51 | } 52 | } 53 | } 54 | 55 | uint32_t lapic_register_read(uint16_t index) 56 | { 57 | if (!LAPIC_X2APIC_MODE) { 58 | return *((uint32_t *) (info_root->lapic_paddr + index * 0x10)); 59 | } else { 60 | return cpu_msr_read(LAPIC_MSR_REGS + index); 61 | } 62 | } 63 | 64 | void lapic_register_write(uint16_t index, uint32_t value) 65 | { 66 | if (!LAPIC_X2APIC_MODE) { 67 | *((uint32_t *) (info_root->lapic_paddr + index * 0x10)) = value; 68 | } else { 69 | cpu_msr_write(LAPIC_MSR_REGS + index, value); 70 | } 71 | } 72 | 73 | void lapic_setup(void) 74 | { 75 | uint64_t base_msr = cpu_msr_read(LAPIC_MSR_BASE); 76 | 77 | bool en = (0 != (base_msr & LAPIC_MSR_BASE_EN)); 78 | bool extd = (0 != (base_msr & LAPIC_MSR_BASE_EXTD)); 79 | 80 | if (!en) { 81 | base_msr |= LAPIC_MSR_BASE_EN; 82 | cpu_msr_write(LAPIC_MSR_BASE, base_msr); 83 | } 84 | 85 | if (LAPIC_X2APIC_MODE && !extd) { 86 | base_msr |= LAPIC_MSR_BASE_EXTD; 87 | cpu_msr_write(LAPIC_MSR_BASE, base_msr); 88 | } 89 | 90 | lapic_timer_update(0xFFFFFFFF, 0, 1, 0); 91 | lapic_register_write(LAPIC_REG_TPR, LAPIC_TPR); 92 | lapic_register_write(LAPIC_REG_PCINT, LAPIC_PCINT); 93 | lapic_register_write(LAPIC_REG_LINT0, LAPIC_LINT0); 94 | lapic_register_write(LAPIC_REG_LINT1, LAPIC_LINT1); 95 | lapic_register_write(LAPIC_REG_ERRINT, LAPIC_ERRINT); 96 | 97 | if (!LAPIC_X2APIC_MODE) { 98 | lapic_register_write(LAPIC_REG_LDR, LAPIC_LDR); 99 | } 100 | 101 | lapic_register_write(LAPIC_REG_SVR, LAPIC_SVR); 102 | } 103 | 104 | uint32_t lapic_id(void) 105 | { 106 | uint32_t id = lapic_register_read(LAPIC_REG_ID); 107 | return (LAPIC_X2APIC_MODE) ? id : (id >> 24); 108 | } 109 | 110 | void lapic_eoi(void) 111 | { 112 | lapic_register_write(LAPIC_REG_EOI, 0); 113 | } 114 | 115 | void lapic_ipi(uint32_t icr_low, uint32_t destination) 116 | { 117 | if (!LAPIC_X2APIC_MODE) { 118 | lapic_register_write(LAPIC_REG_ICR_HIGH, (destination & 0xFF) << 24); 119 | lapic_register_write(LAPIC_REG_ICR_LOW, icr_low); 120 | } else { 121 | uint64_t icr = icr_low | ((uint64_t) destination << 32); 122 | cpu_msr_write(LAPIC_MSR_REGS + LAPIC_REG_ICR_X2APIC, icr); 123 | } 124 | } 125 | 126 | void lapic_timer_update(uint32_t init_count, uint8_t vector, bool mask, bool periodic) 127 | { 128 | uint32_t lvt = vector | (mask << LAPIC_TIMER_MASK) | (periodic << LAPIC_TIMER_TRIGGER); 129 | 130 | lapic_register_write(LAPIC_REG_TIMER_DIV, 0xB); 131 | lapic_register_write(LAPIC_REG_TIMER, lvt); 132 | lapic_register_write(LAPIC_REG_TIMER_INIT, init_count); 133 | } 134 | 135 | void lapic_timer_calibrate(void) 136 | { 137 | extern uint32_t lapic_timer_calibrate_worker(void); 138 | extern void lapic_timer_calibrate_handler(void); 139 | 140 | uint8_t vector = PIT_VECTOR; 141 | 142 | idt_intgate(&idt_data[vector], (uintptr_t) &lapic_timer_calibrate_handler, 0x08, 0x0); 143 | pit_freq_set(100); 144 | pit_route(); 145 | 146 | uint32_t ticks_per_second = lapic_timer_calibrate_worker(); 147 | 148 | info_cpu[lapic_id()].lapic_timer_freq = ticks_per_second; 149 | 150 | pit_mask(); 151 | idt_setup_loader(); 152 | } 153 | 154 | void lapic_timer_wait(uint64_t time) 155 | { 156 | extern void lapic_timer_wait_handler(void); 157 | extern void lapic_timer_wait_worker(void); 158 | 159 | uint8_t vector = 0x40; 160 | idt_intgate(&idt_data[vector], (uintptr_t) &lapic_timer_wait_handler, 0x8, 0x0); 161 | 162 | uint64_t ticks = ((uint64_t) info_cpu[lapic_id()].lapic_timer_freq * time) / 1000000; 163 | lapic_timer_update(ticks, vector, 0, 0); 164 | 165 | lapic_timer_wait_worker(); 166 | 167 | idt_setup_loader(); 168 | } 169 | -------------------------------------------------------------------------------- /loader/src/lapic.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text 25 | bits 64 26 | 27 | global lapic_timer_calibrate_worker 28 | global lapic_timer_calibrate_handler 29 | global lapic_timer_wait_handler 30 | global lapic_timer_wait_worker 31 | extern lapic_timer_update 32 | extern lapic_register_read 33 | extern lapic_eoi 34 | 35 | ; Auxiliary function for LAPIC timer calibration. 36 | ; 37 | ; Enables interrupts, waits for the calibration to complete, then 38 | ; returns the result (counter ticks per second) in RAX. 39 | ; 40 | ; An assembly function is required, as the interrupt handler does 41 | ; not store nor restore the registers. The current phase of calibration 42 | ; is stored in rdx, the result in rax. 43 | ; 44 | ; Requires the PIT to be configured to 100Hz and the IRQ to be 45 | ; routed to the lapic_timer_calibrate_handler ISR using the IO APIC. 46 | ; 47 | lapic_timer_calibrate_worker: 48 | xor rdx, rdx ; Set phase to zero 49 | sti ; Start interrupts 50 | 51 | .wait: 52 | cmp rdx, 2 ; Wait until in phase 2 53 | jl .wait 54 | 55 | cli ; Disable interrupts 56 | ret 57 | 58 | ; Auxiliary function for LAPIC timer calibration. 59 | ; 60 | ; Handles the PIT timer IRQ and measures the ticks of the LAPIC timer 61 | ; that elapse in between two PIT timer ticks. As it is assumed that 62 | ; the PIT runs at 100Hz, the result is multiplied with 100 and then 63 | ; stored in rax when finished. 64 | ; 65 | ; Defines two phases, which are stored in the rdx register. Assumes 66 | ; that rdx is zero when the ISR is called the first time. 67 | ; 68 | ; First phase: The LAPIC timer is started, with an initial count set 69 | ; to the maximum value and masked interrupts in one-shot mode. 70 | ; 71 | ; Second phase: The LAPIC timer's tick count is read and stored as 72 | ; a result. 73 | ; 74 | ; All subsequent calls of this ISR will have no effect. 75 | lapic_timer_calibrate_handler: 76 | cli ; Disable interrupts 77 | cmp rdx, 0 ; First phase? 78 | je .phase_first 79 | cmp rdx, 1 ; Second phase? 80 | je .phase_second 81 | jmp .end ; Already complete 82 | 83 | .phase_first: ; First phase 84 | push rax 85 | push rdx 86 | mov rdi, 0xFFFFFFFF ; Max initial count 87 | mov rsi, 0 ; Some vector 88 | mov rdx, 1 ; Mask 89 | mov r8, 0 ; One-shot 90 | call lapic_timer_update 91 | pop rdx 92 | pop rax 93 | jmp .end 94 | 95 | .phase_second: ; Second phase 96 | push rdx 97 | mov rdi, 0x39 ; Current timer count 98 | call lapic_register_read 99 | pop rdx 100 | 101 | mov rbx, rax ; Subtract timer count from 102 | mov rax, 0xFFFFFFFF ; initial timer count to 103 | sub rax, rbx ; get the difference 104 | 105 | mov rbx, 100 ; Multiply with 100 to get 106 | push rdx ; timer ticks per second 107 | mul ebx 108 | pop rdx 109 | 110 | .end: 111 | inc rdx ; Next phase 112 | push rax 113 | push rdx 114 | call lapic_eoi ; EOI 115 | pop rdx 116 | pop rax 117 | sti ; Enable interrupts 118 | iretq ; Return from ISR 119 | 120 | ; Enables interrupts, waits for a barrier, then disables interrupts again. 121 | lapic_timer_wait_worker: 122 | xor r15, r15 ; Barrier in R15 123 | 124 | sti 125 | .wait: 126 | cmp r15, 1 127 | jne .wait 128 | 129 | cli 130 | ret 131 | 132 | ; ISR for lapic_timer_wait that sets the lapic_timer_wait_barrier on IRQ. 133 | lapic_timer_wait_handler: 134 | call lapic_eoi 135 | mov r15, 1 136 | iretq 137 | -------------------------------------------------------------------------------- /loader/src/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | volatile uint8_t main_entry_barrier = 1; 45 | 46 | void main_bsp(void) 47 | { 48 | // Print header 49 | screen_write("Hydrogen v0.2b - http://github.com/farok/H2", 0, 0); 50 | screen_write("Copyright (c) 2012 by Lukas Heidemann", 0, 1); 51 | screen_write("-------------------------------------------------", 0, 2); 52 | 53 | // Load the IDT 54 | idt_load(idt_address, IDT_LENGTH); 55 | idt_setup_loader(); 56 | 57 | // Initialize Hydrogen info tables and parse the multiboot tables 58 | info_init(); 59 | multiboot_parse(); 60 | 61 | // Setup the heap 62 | heap_init(); 63 | 64 | // Now parse the ACPI tables and analyze the IO APICs 65 | acpi_parse(); 66 | ioapic_analyze(); 67 | 68 | // Find, check and load the kernel binary 69 | kernel_find(); 70 | kernel_check(); 71 | elf64_load(kernel_binary); 72 | kernel_analyze(); 73 | 74 | // Initialize interrupt controllers 75 | lapic_detect(); 76 | lapic_setup(); 77 | ioapic_setup_loader(); 78 | pic_setup(); 79 | 80 | // Calibrate the LAPIC timer 81 | lapic_timer_calibrate(); 82 | 83 | // Boot APs 84 | info_cpu[lapic_id()].flags |= HY_INFO_CPU_FLAG_BSP; 85 | smp_setup(); 86 | 87 | // Setup IDT and IOAPIC according to kernel header 88 | idt_setup_kernel(); 89 | ioapic_setup_kernel(); 90 | 91 | // Setup fast syscall support 92 | syscall_init(); 93 | 94 | // Setup mapping 95 | kernel_map_info(); 96 | kernel_map_stack(); 97 | kernel_map_idt(); 98 | kernel_map_gdt(); 99 | 100 | // Set free address 101 | info_root->free_paddr = (heap_top + 0xFFF) & ~0xFFF; 102 | 103 | // Lower main entry barrier and jump to the kernel entry point 104 | main_entry_barrier = 0; 105 | kernel_enter_bsp(); 106 | } 107 | 108 | void main_ap(void) 109 | { 110 | // Load the IDT 111 | idt_load((uintptr_t) &idt_data, IDT_LENGTH); 112 | 113 | // Enable LAPIC and calibrate the timer 114 | lapic_setup(); 115 | lapic_timer_calibrate(); 116 | 117 | // Setup stack mapping 118 | kernel_map_stack(); 119 | 120 | // Setup fast syscall support 121 | syscall_init(); 122 | 123 | // Signal complete AP startup 124 | ++smp_ready_count; 125 | 126 | // Wait for main entry barrier, then enter the kernel (or halt) 127 | while (main_entry_barrier == 1); 128 | kernel_enter_ap(); 129 | } 130 | -------------------------------------------------------------------------------- /loader/src/multiboot.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | multiboot_info_t *multiboot_info; 32 | 33 | /** 34 | * Aligns a memory map entry to page boundaries. 35 | * 36 | * Always aligns available entries to the smaller boundaries, that is increasing 37 | * the address and decreasing the length and unavailable to the larger. 38 | * 39 | * @param entry the entry to align 40 | */ 41 | static void multiboot_align_mmap(hy_info_mmap_t *entry) 42 | { 43 | uintptr_t aligned_addr; 44 | 45 | if (entry->available) { 46 | aligned_addr = (entry->address + 0xFFF) & ~0xFFF; 47 | 48 | entry->length -= (entry->address - aligned_addr); 49 | entry->length &= ~0xFFF; 50 | 51 | } else { 52 | aligned_addr = entry->address & ~0xFFF; 53 | 54 | entry->length += (aligned_addr - entry->address); 55 | entry->length = (entry->length + 0xFFF) & ~0xFFF; 56 | } 57 | 58 | entry->address = aligned_addr; 59 | } 60 | 61 | static void multiboot_parse_mmap(multiboot_mmap_t *mmap, size_t length) 62 | { 63 | while (0 != length) { 64 | hy_info_mmap_t *hyentry = &info_mmap[info_root->mmap_count++]; 65 | 66 | hyentry->address = mmap->address; 67 | hyentry->length = mmap->length; 68 | hyentry->available = mmap->type == 1; 69 | 70 | multiboot_align_mmap(hyentry); 71 | 72 | length -= mmap->size + sizeof(uint32_t); 73 | mmap = (multiboot_mmap_t *) ((uintptr_t) mmap + mmap->size + sizeof(uint32_t)); 74 | } 75 | } 76 | 77 | static void multiboot_parse_mods(multiboot_mod_t *mods, size_t count) 78 | { 79 | size_t i; 80 | 81 | for (i = 0; i < count; ++i) { 82 | multiboot_mod_t *mod = &mods[i]; 83 | 84 | hy_info_module_t *hymod = &info_module[info_root->module_count++]; 85 | hymod->address = mod->start; 86 | hymod->length = mod->end - mod->start; 87 | 88 | char *name = (char *) (uintptr_t) mod->cmdline; 89 | size_t name_len = strlen(name); 90 | char *name_tbl = info_string_alloc(name_len); 91 | memcpy(name_tbl, name, name_len); 92 | 93 | hymod->name = ((uintptr_t) name_tbl - (uintptr_t) info_strings); 94 | } 95 | } 96 | 97 | void multiboot_parse() 98 | { 99 | multiboot_mmap_t *mmap = (multiboot_mmap_t *) (uintptr_t) multiboot_info->mmap_addr; 100 | multiboot_mod_t *mods = (multiboot_mod_t *) (uintptr_t) multiboot_info->mods_addr; 101 | 102 | multiboot_parse_mmap(mmap, multiboot_info->mmap_length); 103 | multiboot_parse_mods(mods, multiboot_info->mods_count); 104 | } 105 | -------------------------------------------------------------------------------- /loader/src/multiboot.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .multiboot 25 | bits 32 26 | 27 | MULTIBOOT_FLAG_PAGE_ALIGN EQU 0x0001 28 | MULTIBOOT_FLAG_MEMORY_INFO EQU 0x0002 29 | MULTIBOOT_FLAG_VIDEO_MODE EQU 0x0004 30 | MULTIBOOT_FLAG_AOUT_KLUDGE EQU 0x0008 31 | 32 | MULTIBOOT_MAGIC EQU 0x1BADB002 33 | MULTIBOOT_FLAGS EQU MULTIBOOT_FLAG_PAGE_ALIGN | \ 34 | MULTIBOOT_FLAG_MEMORY_INFO 35 | MULTIBOOT_CHECKSUM EQU -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) 36 | 37 | multiboot_header: 38 | .Magic: 39 | dd MULTIBOOT_MAGIC 40 | .Flags: 41 | dd MULTIBOOT_FLAGS 42 | .Checksum: 43 | dd MULTIBOOT_CHECKSUM 44 | -------------------------------------------------------------------------------- /loader/src/page.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static uint64_t *page_struct_get(uintptr_t, uint8_t, bool); 33 | static uint64_t *page_entry_get(uintptr_t, uint8_t, bool); 34 | 35 | /** 36 | * Returns the physical address of the currently active PML4. 37 | * 38 | * @return physical address of current PML4 39 | */ 40 | static uint64_t page_pml4_get(void) 41 | { 42 | uint64_t pml4; 43 | asm volatile ("mov %%cr3, %0" : "=a" (pml4)); 44 | return pml4; 45 | } 46 | 47 | /** 48 | * Returns the page structure of level that covers the virtual 49 | * address . 50 | * 51 | * If is true, the structure and all higher level ones will be 52 | * created, if they do not exist. Otherwise a null pointer is returned, 53 | * if one of them does not exist. 54 | * 55 | * @param virtual The virtual address covered by the structure. 56 | * @param level The level of the structure to return. 57 | * @param create Whether to create the structure and higher level structures. 58 | * @return pointer to the structure or null pointer if is false and 59 | * there is no such structure 60 | */ 61 | static uint64_t *page_struct_get(uintptr_t virtual, uint8_t level, bool create) 62 | { 63 | if (PAGE_LEVEL_PML4 == level) 64 | return (uint64_t *) page_pml4_get(); 65 | 66 | uint64_t *parent_entry = page_entry_get(virtual, level + 1, create); 67 | 68 | if (0 == parent_entry) 69 | return 0; 70 | 71 | if (0 == (*parent_entry & PAGE_FLAG_PRESENT)) { 72 | if (create) { 73 | uintptr_t frame = (uintptr_t) heap_alloc(0x1000); 74 | uint64_t flags = PAGE_FLAG_PRESENT | PAGE_FLAG_WRITABLE | PAGE_FLAG_USER; 75 | 76 | *parent_entry = frame | flags; 77 | 78 | memset((void *) frame, 0, 0x1000); 79 | 80 | } else { 81 | return 0; 82 | } 83 | } 84 | 85 | return (uint64_t *) PAGE_PHYSICAL(*parent_entry); 86 | } 87 | 88 | /** 89 | * Returns the entry in the page structure of level that covers the 90 | * virtual address . 91 | * 92 | * See page_struct_get for . 93 | * 94 | * @param virt The virtual address covered by the entry. 95 | * @param level The level of the structure the entry is stored in. 96 | * @param create Whether to create the containing structure and the higher level ones. 97 | * @return pointer to entry in a page structure or null pointer if is false 98 | * and there is no such structure 99 | */ 100 | static uint64_t *page_entry_get(uintptr_t virtual, uint8_t level, bool create) 101 | { 102 | uint64_t *pstruct = page_struct_get(virtual, level, create); 103 | 104 | if (0 == pstruct) 105 | return 0; 106 | 107 | return &pstruct[PAGE_INDEX(virtual, level)]; 108 | } 109 | 110 | void page_map(uintptr_t physical, uintptr_t virtual, uint64_t flags) 111 | { 112 | physical &= ~0xFFF; 113 | virtual &= ~0xFFF; 114 | 115 | uint64_t *pte = page_entry_get(virtual, PAGE_LEVEL_PT, true); 116 | *pte = PAGE_FLAG_PRESENT | flags | physical; 117 | 118 | page_invalidate(virtual); 119 | } 120 | 121 | void page_invalidate(uintptr_t virtual) 122 | { 123 | virtual &= ~0xFFF; 124 | asm volatile ("invlpg %0" :: "m" (virtual)); 125 | } 126 | -------------------------------------------------------------------------------- /loader/src/pic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | void pic_setup(void) 31 | { 32 | // Initialize PIC 33 | outb(PIC_MASTER_CMD_IO, PIC_ICW1_INIT + PIC_ICW1_ICW4); 34 | outb(PIC_SLAVE_CMD_IO, PIC_ICW1_INIT + PIC_ICW1_ICW4); 35 | outb(PIC_MASTER_DATA_IO, PIC_VECTOR); 36 | outb(PIC_SLAVE_DATA_IO, PIC_VECTOR + 8); 37 | outb(PIC_MASTER_DATA_IO, 4); 38 | outb(PIC_SLAVE_DATA_IO, 2); 39 | outb(PIC_MASTER_DATA_IO, PIC_ICW4_8086); 40 | outb(PIC_SLAVE_DATA_IO, PIC_ICW4_8086); 41 | 42 | // Mask all IRQs 43 | outb(PIC_MASTER_DATA_IO, 0xFF); 44 | outb(PIC_SLAVE_DATA_IO, 0xFF); 45 | } 46 | -------------------------------------------------------------------------------- /loader/src/pit.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | void pit_freq_set(uint16_t freq) 36 | { 37 | uint16_t divisor = PIT_FREQ_BASE / freq; 38 | outb(PIT_IO_COUNTER, divisor); 39 | outb(PIT_IO_COUNTER, divisor >> 8); 40 | } 41 | 42 | static void pit_set_redir(uint64_t redir) 43 | { 44 | uint8_t irq = (0 == (info_root->flags & HY_INFO_FLAG_PCAT_COMPAT)) ? PIT_IRQ : PIT_IRQ_PCAT_COMPAT; 45 | uint32_t gsi = info_root->irq_gsi[irq]; 46 | hy_info_ioapic_t *ioapic = ioapic_get_by_gsi(gsi); 47 | uint32_t index = gsi - ioapic->gsi_base; 48 | ioapic_redir_set(index, redir, ioapic); 49 | } 50 | 51 | void pit_route(void) 52 | { 53 | uint64_t redir = PIT_VECTOR | ((uint64_t) lapic_id() << IOAPIC_REDIR_DEST); 54 | pit_set_redir(redir); 55 | } 56 | 57 | void pit_mask(void) 58 | { 59 | uint64_t redir = (1 << IOAPIC_REDIR_MASK); 60 | pit_set_redir(redir); 61 | } 62 | -------------------------------------------------------------------------------- /loader/src/ports.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | void outb(uint16_t port, uint8_t value) 30 | { 31 | asm volatile ("outb %1, %0" :: "dN" (port), "a" (value)); 32 | } 33 | 34 | uint8_t inb(uint16_t port) 35 | { 36 | uint8_t value; 37 | asm volatile ("inb %1, %0" : "=a" (value) : "dN" (port)); 38 | return value; 39 | } 40 | -------------------------------------------------------------------------------- /loader/src/screen.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | void screen_write(const char *message, uint16_t x, uint16_t y) 30 | { 31 | size_t i; 32 | size_t position = x + y * SCREEN_WIDTH; 33 | 34 | for (i = 0; '\0' != message[i]; ++i) { 35 | SCREEN_VIDEOMEM[position++].character = message[i]; 36 | } 37 | } 38 | 39 | void screen_write_hex(uint64_t number, uint16_t x, uint16_t y) 40 | { 41 | char string[17]; 42 | string[16] = '\0'; 43 | 44 | size_t i; 45 | for (i = 0; i < 16; ++i) { 46 | uint8_t nibble = (number >> (i * 4)) & 0xF; 47 | 48 | if (nibble >= 10) { 49 | string[15 - i] = 'A' + (nibble - 10); 50 | } else { 51 | string[15 - i] = '0' + nibble; 52 | } 53 | } 54 | 55 | screen_write(string, x, y); 56 | } 57 | 58 | /** 59 | * Clears the screen. 60 | */ 61 | void screen_clear(void) 62 | { 63 | size_t i; 64 | for (i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; ++i) { 65 | screen_cell_t *cell = &SCREEN_VIDEOMEM[i]; 66 | cell->attributes = SCREEN_ATTRIBUTES; 67 | cell->character = ' '; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /loader/src/smp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | volatile uint64_t smp_ready_count; 35 | 36 | static void smp_boot(hy_info_cpu_t *cpu) 37 | { 38 | // Send INIT IPI 39 | lapic_ipi(LAPIC_IPI_INIT, cpu->apic_id); 40 | 41 | // Wait a moment (10ms) 42 | lapic_timer_wait(10 * 1000); 43 | 44 | // Backup ready count 45 | uint64_t ready_new = smp_ready_count + 1; 46 | 47 | // Send STARTUP IPI 48 | lapic_ipi(LAPIC_IPI_STARTUP(0x1000), cpu->apic_id); 49 | 50 | // Wait for the AP to become ready 51 | while (ready_new != smp_ready_count); 52 | } 53 | 54 | static void smp_prepare_boot16(void) 55 | { 56 | extern uint8_t boot16_begin; 57 | extern uint8_t boot16_end; 58 | 59 | size_t length = ((uintptr_t) &boot16_end - (uintptr_t) &boot16_begin); 60 | memcpy((void *) SMP_BOOT16_TARGET, &boot16_begin, length); 61 | } 62 | 63 | void smp_setup(void) 64 | { 65 | smp_prepare_boot16(); 66 | 67 | size_t i; 68 | for (i = 0; i < info_root->cpu_count; ++i) { 69 | hy_info_cpu_t *cpu = &info_cpu[i]; 70 | 71 | if (0 == (cpu->flags & HY_INFO_CPU_FLAG_PRESENT)) 72 | continue; 73 | 74 | if (0 != (cpu->flags & HY_INFO_CPU_FLAG_BSP)) 75 | continue; 76 | 77 | smp_boot(cpu); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /loader/src/string.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | uintptr_t memalign(uintptr_t address, size_t boundary) 30 | { 31 | size_t div = address / boundary; 32 | size_t mod = address - div * boundary; 33 | 34 | if (0 != mod) 35 | return address + boundary - mod; 36 | else 37 | return address; 38 | } 39 | 40 | bool memcmp(void *a, void *b, size_t len) 41 | { 42 | size_t i; 43 | for (i = 0; i < len; ++i) 44 | if (((uint8_t *) a)[i] != ((uint8_t *) b)[i]) return 0; 45 | 46 | return 1; 47 | } 48 | 49 | void memcpy(void *dest, void *src, size_t length) 50 | { 51 | size_t i; 52 | 53 | for (i = 0; i < length; ++i) 54 | ((uint8_t *) dest)[i] = ((uint8_t *) src)[i]; 55 | } 56 | 57 | void memset(void *dest, uint8_t c, size_t length) 58 | { 59 | size_t i; 60 | 61 | for (i = 0; i < length; ++i) 62 | ((uint8_t *) dest)[i] = c; 63 | } 64 | 65 | uint8_t strcmp(const int8_t *a, const int8_t *b) 66 | { 67 | size_t i; 68 | for (i = 0; 0 != a[i] || 0 != b[i]; ++i) 69 | if (a[i] != b[i]) return 0; 70 | 71 | return 1; 72 | } 73 | 74 | int8_t *strcpy(int8_t *dest, const int8_t *src) 75 | { 76 | size_t i; 77 | for (i = 0; 0 != src[i]; ++i) 78 | dest[i] = src[i]; 79 | 80 | dest[i] = 0; 81 | 82 | return dest; 83 | } 84 | 85 | size_t strlen(const int8_t *str) 86 | { 87 | size_t len; 88 | for (len = 0; 0 != str[len]; ++len); 89 | return len; 90 | } 91 | 92 | int8_t *strstr(const int8_t *haystack, const int8_t *needle) 93 | { 94 | size_t str_pos, substr_pos; 95 | substr_pos = 0; 96 | 97 | if (0 == needle[0]) 98 | return (int8_t *) haystack; 99 | 100 | for (str_pos = 0; 0 != haystack[str_pos]; ++str_pos) { 101 | if (needle[substr_pos] == haystack[str_pos]) { 102 | ++substr_pos; 103 | 104 | if (0 == needle[substr_pos]) 105 | return (int8_t *) 106 | (((uintptr_t) haystack) + str_pos - substr_pos + 1); 107 | } else { 108 | substr_pos = 0; 109 | } 110 | } 111 | 112 | return (int8_t *) 0; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /loader/src/syscall.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | void syscall_init(void) 32 | { 33 | cpu_msr_write(SYSCALL_MSR_STAR, SYSCALL_STAR); 34 | cpu_msr_write(SYSCALL_MSR_SFMASK, SYSCALL_SFMASK); 35 | cpu_msr_write(SYSCALL_MSR_CSTAR, 0); 36 | cpu_msr_write(SYSCALL_MSR_LSTAR, kernel_header->syscall_entry); 37 | } 38 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all build link install uninstall clean 2 | 3 | # Target 4 | TARGET := test64 5 | TARGET_BIN := $(TARGET).bin 6 | 7 | # Directories 8 | PREFIX := ./../build 9 | SOURCE_DIR := ./src 10 | BUILD_DIR := ./build 11 | INC_DIR := ./inc 12 | 13 | # Object Files 14 | OBJECTS := $(patsubst $(SOURCE_DIR)/%.c,$(BUILD_DIR)/%.c.o,$(shell find $(SOURCE_DIR) -name "*.c")) 15 | OBJECTS += $(patsubst $(SOURCE_DIR)/%.s,$(BUILD_DIR)/%.s.o,$(shell find $(SOURCE_DIR) -name "*.s")) 16 | 17 | # Toolchain 18 | CC := gcc 19 | AS := nasm 20 | LD := ld 21 | 22 | # Toolchain Flags 23 | INCFLAGS := -I$(INC_DIR) -I$(PREFIX)/include 24 | CFLAGS := -m64 -ffreestanding -Wall -Werror -mcmodel=large $(INCFLAGS) 25 | ASFLAGS := -f elf64 26 | LDFLAGS := -z max-page-size=0x1000 27 | 28 | # Link File 29 | LDFILE := link.ld 30 | 31 | # Build everything and link the target binary. 32 | all: build link 33 | 34 | # Install to prefix directory. 35 | install: all 36 | @ echo " CP" $(TARGET_BIN) 37 | @ mkdir -p $(PREFIX)/bin 38 | @ cp $(BUILD_DIR)/$(TARGET_BIN) $(PREFIX)/bin 39 | 40 | # Uninstalls from prefix directory. 41 | uninstall: 42 | @ rm $(PREFIX)/bin/$(TARGET_BIN) 43 | 44 | # Build all C and assembly files. 45 | build: $(OBJECTS) 46 | 47 | # Build an assembly file. 48 | $(BUILD_DIR)/%.s.o: $(SOURCE_DIR)/%.s 49 | @ echo " AS " $< 50 | @ mkdir -p $(@D) 51 | @ $(AS) $(ASFLAGS) $< -o $@ 52 | 53 | # Build a C file. 54 | $(BUILD_DIR)/%.c.o: $(SOURCE_DIR)/%.c 55 | @ echo " CC " $< 56 | @ mkdir -p $(@D) 57 | @ $(CC) $(CFLAGS) -c $< -o $@ 58 | 59 | # Link the target binary. 60 | link: 61 | @ echo " LD " $(TARGET_BIN) 62 | @ $(LD) $(LDFLAGS) -T $(LDFILE) -o $(BUILD_DIR)/$(TARGET_BIN) $(OBJECTS) 63 | 64 | # Cleans the build directory 65 | clean: 66 | @ rm -R $(BUILD_DIR)/* 67 | -------------------------------------------------------------------------------- /test/inc/buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | #define BSTR(str) buffer = buffer_write(str, buffer) 30 | #define BNUM(num) buffer = buffer_write_hex(num, buffer) 31 | 32 | /** 33 | * Writes a string to the buffer. 34 | * 35 | * Null-terminates the buffer on the returned position. 36 | * 37 | * @param string the string to write to the buffer. 38 | * @param buffer the buffer to write to. 39 | * @return pointer to the end of the buffer. 40 | */ 41 | char *buffer_write(const char *string, char *buffer); 42 | 43 | /** 44 | * Writes an 16 character number in base 16 to the buffer. 45 | * 46 | * Null-terminates the buffer on the returned position. 47 | * 48 | * @param number the number to write to the buffer 49 | * @param buffer the buffer to write to. 50 | * @return pointer to the end of the buffer. 51 | */ 52 | char *buffer_write_hex(uint64_t number, char *buffer); 53 | -------------------------------------------------------------------------------- /test/inc/isr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | #define ISR_COUNT 0xFF 30 | 31 | /** 32 | * Array of pointers to all interrupt gates. 33 | */ 34 | extern uint64_t isr_gates[ISR_COUNT]; 35 | 36 | /** 37 | * Array of higher-level interrupt handlers. 38 | */ 39 | extern uint64_t isr_handlers[ISR_COUNT]; 40 | 41 | /** 42 | * The state of the system before an interrupt was raised and 43 | * that can be used and manipulated by ISRs. 44 | */ 45 | typedef struct isr_state { 46 | uint64_t ds; 47 | 48 | uint64_t r15; 49 | uint64_t r14; 50 | uint64_t r13; 51 | uint64_t r12; 52 | uint64_t r11; 53 | uint64_t r10; 54 | uint64_t r9; 55 | uint64_t r8; 56 | uint64_t rbp; 57 | uint64_t rdi; 58 | uint64_t rsi; 59 | uint64_t rdx; 60 | uint64_t rcx; 61 | uint64_t rbx; 62 | uint64_t rax; 63 | 64 | uint64_t vector; 65 | uint64_t error_code; 66 | 67 | uint64_t rip; 68 | uint64_t cs; 69 | uint64_t rflags; 70 | uint64_t rsp; 71 | uint64_t ss; 72 | } __attribute__((packed)) isr_state_t; 73 | -------------------------------------------------------------------------------- /test/inc/keyboard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | #include 29 | 30 | #define KEYBOARD_CODE_ESCAPED 0xE0 31 | #define KEYBOARD_CODE_LEFT 0x4B 32 | #define KEYBOARD_CODE_RIGHT 0x4D 33 | #define KEYBOARD_CODE_UP 0x48 34 | #define KEYBOARD_CODE_DOWN 0x50 35 | 36 | #define KEYBOARD_IRQ_VECTOR 0x40 37 | 38 | /** 39 | * Whether the escape scan code has been sent and the next 40 | * scan code is escaped. 41 | */ 42 | extern bool keyboard_escaped; 43 | 44 | /** 45 | * Initializes the keyboard support. 46 | */ 47 | void keyboard_init(void); 48 | 49 | /** 50 | * Sends a command to the keyboard controller. 51 | * 52 | * @param cmd the command to send 53 | */ 54 | void keyboard_send_command(uint8_t cmd); 55 | 56 | /** 57 | * ISR for the keyboard IRQ. 58 | * 59 | * @param state state of the system 60 | */ 61 | void keyboard_handler(isr_state_t *state); 62 | -------------------------------------------------------------------------------- /test/inc/lapic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | // register indices 30 | #define LAPIC_REG_ID 0x02 //< LAPIC ID 31 | #define LAPIC_REG_EOI 0x0B //< End of Interrupt 32 | #define LAPIC_REG_ICR_LOW 0x30 //< Interrupt Command Register (lower DWORD) 33 | #define LAPIC_REG_ICR_HIGH 0x31 //< Interrupt Command Register (upper DWORD) 34 | #define LAPIC_REG_TIMER 0x32 //< Local: Timer 35 | #define LAPIC_REG_TIMER_INIT 0x38 //< Timer: Initial Count 36 | #define LAPIC_REG_TIMER_CUR 0x39 //< Timer: Current Count 37 | #define LAPIC_REG_TIMER_DIV 0x3E //< Timer: Divisor 38 | 39 | // x2APIC related 40 | #define LAPIC_MSR_REGS 0x800 41 | 42 | #define lapic_id() lapic_register_read(LAPIC_REG_ID) 43 | #define lapic_eoi() lapic_register_write(LAPIC_REG_EOI, 0) 44 | 45 | /** 46 | * Reads a register of the CPU's LAPIC, given its . 47 | * 48 | * Uses the LAPIC address stored in the info tables. 49 | * Behavior is undefined when called for an invalid register. 50 | * 51 | * @param index the index of the register 52 | * @return value of the register 53 | */ 54 | uint32_t lapic_register_read(uint16_t index); 55 | 56 | /** 57 | * Writes a to a register of the CPU's LAPIC, given its . 58 | * 59 | * Uses the LAPIC address stored in the info tables. 60 | * Behavior is undefined when called for an invalid register. 61 | * 62 | * @param index the index of the register to write 63 | * @param value the new value of the register 64 | */ 65 | void lapic_register_write(uint16_t index, uint32_t value); 66 | -------------------------------------------------------------------------------- /test/inc/ports.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Sends a byte to an output . 31 | * 32 | * @param port port to send the byte to 33 | * @param value the byte to send 34 | */ 35 | void outb(uint16_t port, uint8_t value); 36 | 37 | /** 38 | * Reads a byte from an input . 39 | * 40 | * @param port the port to read from 41 | * @return the byte read from the port 42 | */ 43 | uint8_t inb(uint16_t port); 44 | -------------------------------------------------------------------------------- /test/inc/screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | #define SCREEN_WIDTH 80 30 | #define SCREEN_HEIGHT 25 31 | #define SCREEN_ATTR 0x0F 32 | #define SCREEN_MEMORY 0xB8000 33 | 34 | /** 35 | * Writes a string to the screen, given the beginning coordinates. 36 | * 37 | * Respects line breaks ('\n'). 38 | * 39 | * @param string the string to write. 40 | * @param x the horizontal coordinate to write to. 41 | * @param y the vertical coordinate to write to. 42 | */ 43 | void screen_write(const char *string, uint16_t x, uint16_t y); 44 | 45 | /** 46 | * Clears the screen. 47 | */ 48 | void screen_clear(void); 49 | -------------------------------------------------------------------------------- /test/inc/stdint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | 28 | /** 29 | * Often used type declarations for various differently sized integer types. 30 | */ 31 | 32 | typedef unsigned char uint8_t; 33 | typedef char int8_t; 34 | typedef unsigned short uint16_t; 35 | typedef short int16_t; 36 | typedef unsigned int uint32_t; 37 | typedef int int32_t; 38 | typedef unsigned long long uint64_t; 39 | typedef long long int64_t; 40 | 41 | typedef uint64_t uintptr_t; 42 | typedef int64_t intptr_t; 43 | typedef uint64_t size_t; 44 | typedef char bool; 45 | 46 | #define true 1 47 | #define TRUE 1 48 | #define false 0 49 | #define FALSE 0 50 | -------------------------------------------------------------------------------- /test/inc/ui.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | #include 28 | 29 | /** 30 | * Number of pages in the UI. 31 | */ 32 | #define UI_PAGE_COUNT 5 33 | 34 | /** 35 | * Structure describing a page. 36 | */ 37 | typedef struct ui_page { 38 | char *title; 39 | char *body; 40 | } ui_page_t; 41 | 42 | /** 43 | * The UI's pages. 44 | */ 45 | extern ui_page_t ui_pages[]; 46 | 47 | /** 48 | * Displays a page, from the given line, and the header. 49 | * 50 | * @param page the number of the page to display. 51 | * @param line the line of the page to begin on. 52 | */ 53 | void ui_display(size_t page_nr, size_t line); 54 | 55 | /** 56 | * Switches one page left. 57 | */ 58 | void ui_switch_left(void); 59 | 60 | /** 61 | * Switches one page right. 62 | */ 63 | void ui_switch_right(void); 64 | 65 | /** 66 | * Scrolls up one line. 67 | */ 68 | void ui_scroll_up(void); 69 | 70 | /** 71 | * Scrolls down one line. 72 | */ 73 | void ui_scroll_down(void); 74 | -------------------------------------------------------------------------------- /test/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-x86-64) 2 | ENTRY(kmain_bsp) 3 | SECTIONS { 4 | .text 0xFFFFFF0000000000 : { 5 | *(.text) 6 | *(.rodata) 7 | } 8 | 9 | .data : { 10 | *(.data) 11 | } 12 | 13 | .bss : { 14 | *(.bss) 15 | } 16 | 17 | /DISCARD/ : { 18 | *(.comment) 19 | } 20 | } -------------------------------------------------------------------------------- /test/src/buffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | char *buffer_write(const char *string, char *buffer) 30 | { 31 | size_t i; 32 | for (i = 0; '\0' != string[i]; ++i) { 33 | buffer[i] = string[i]; 34 | } 35 | 36 | buffer[i] = '\0'; 37 | return &buffer[i]; 38 | } 39 | 40 | char *buffer_write_hex(uint64_t number, char *buffer) 41 | { 42 | char string[17]; 43 | string[16] = '\0'; 44 | 45 | size_t i; 46 | for (i = 0; i < 16; ++i) { 47 | uint8_t nibble = (number >> (i * 4)) & 0xF; 48 | 49 | if (nibble >= 10) { 50 | string[15 - i] = 'A' + (nibble - 10); 51 | } else { 52 | string[15 - i] = '0' + nibble; 53 | } 54 | } 55 | 56 | return buffer_write(string, buffer); 57 | } 58 | -------------------------------------------------------------------------------- /test/src/hydrogen.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #define FLAGS ( \ 31 | HY_HEADER_FLAG_IOAPIC_BSP | \ 32 | HY_HEADER_FLAG_X2APIC_ALLOW ) 33 | 34 | hy_header_root_t hydrogen_header = { 35 | HY_MAGIC, // magic 36 | FLAGS, // flags 37 | 0xFFFFFF0000200000, // stack_vaddr 38 | 0xFFFFFF0000100000, // info_vaddr 39 | 0, // idt_vaddr 40 | 0, // gdt_vaddr 41 | 0, // ap_entry 42 | 0, // syscall_entry 43 | (uintptr_t) &isr_gates, // isr_entry_table 44 | 45 | { 46 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ0 47 | {0, KEYBOARD_IRQ_VECTOR}, // IRQ1 48 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ2 49 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ3 50 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ4 51 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ5 52 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ6 53 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ7 54 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ8 55 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ9 56 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ10 57 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ11 58 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ12 59 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ13 60 | {HY_HEADER_IRQ_FLAG_MASK, 0}, // IRQ14 61 | {HY_HEADER_IRQ_FLAG_MASK, 0} // IRQ15 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /test/src/isr.s: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012 by Lukas Heidemann 2 | ; All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions 6 | ; are met: 7 | ; 1. Redistributions of source code must retain the above copyright 8 | ; notice, this list of conditions and the following disclaimer. 9 | ; 2. Redistributions in binary form must reproduce the above copyright 10 | ; notice, this list of conditions and the following disclaimer in the 11 | ; documentation and/or other materials provided with the distribution. 12 | ; 13 | ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 | ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 | ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | section .text 25 | bits 64 26 | 27 | global isr_gates 28 | global isr_handlers 29 | 30 | isr_dispatch: 31 | mov rax, rdi ; Get vector 32 | add rax, 16 * 8 33 | mov rax, qword [rax] 34 | 35 | mov rbx, rax ; Get handler 36 | mov rax, isr_handlers 37 | shl rbx, 3 38 | add rax, rbx 39 | mov rax, qword [rax] 40 | 41 | cmp rax, 0 ; No handler? 42 | je .no_handler 43 | 44 | call rax ; Call handler 45 | 46 | .no_handler: 47 | ret 48 | 49 | isr_stub_common: 50 | push rax ; Store registers on stack 51 | push rbx 52 | push rcx 53 | push rdx 54 | push rbp 55 | push rdi 56 | push rsi 57 | push r8 58 | push r9 59 | push r10 60 | push r11 61 | push r12 62 | push r13 63 | push r14 64 | push r15 65 | 66 | xor rax, rax ; Store data segment 67 | mov ax, ds 68 | push rax 69 | 70 | mov ax, 0x10 ; Load kernel data segment 71 | mov ds, ax 72 | mov es, ax 73 | mov fs, ax 74 | mov gs, ax 75 | 76 | mov rdi, rsp ; Stack pointer as parameter 77 | call isr_dispatch ; Dispatch to right ISR 78 | 79 | pop rax ; Restore data segment 80 | mov ds, ax 81 | mov es, ax 82 | mov fs, ax 83 | mov gs, ax 84 | 85 | pop r15 ; Restore registers 86 | pop r14 87 | pop r13 88 | pop r12 89 | pop r11 90 | pop r10 91 | pop r9 92 | pop r8 93 | pop rsi 94 | pop rdi 95 | pop rbp 96 | pop rdx 97 | pop rcx 98 | pop rbx 99 | pop rax 100 | add rsp, 16 ; Remove error code and vector number 101 | sti 102 | iretq 103 | 104 | %macro ISR_NOERRCODE 1 105 | isr_stub%1: 106 | cli 107 | push qword 0 108 | push qword %1 109 | jmp isr_stub_common 110 | %endmacro 111 | 112 | %macro ISR_ERRCODE 1 113 | isr_stub%1: 114 | cli 115 | push qword %1 116 | jmp isr_stub_common 117 | %endmacro 118 | 119 | ISR_NOERRCODE 0 120 | ISR_NOERRCODE 1 121 | ISR_NOERRCODE 2 122 | ISR_NOERRCODE 3 123 | ISR_NOERRCODE 4 124 | ISR_NOERRCODE 5 125 | ISR_NOERRCODE 6 126 | ISR_NOERRCODE 7 127 | ISR_ERRCODE 8 128 | ISR_NOERRCODE 9 129 | ISR_ERRCODE 10 130 | ISR_ERRCODE 11 131 | ISR_ERRCODE 12 132 | ISR_ERRCODE 13 133 | ISR_ERRCODE 14 134 | ISR_NOERRCODE 15 135 | ISR_NOERRCODE 16 136 | ISR_NOERRCODE 17 137 | ISR_NOERRCODE 18 138 | ISR_NOERRCODE 19 139 | ISR_NOERRCODE 20 140 | ISR_NOERRCODE 21 141 | ISR_NOERRCODE 22 142 | ISR_NOERRCODE 23 143 | ISR_NOERRCODE 24 144 | ISR_NOERRCODE 25 145 | ISR_NOERRCODE 26 146 | ISR_NOERRCODE 27 147 | ISR_NOERRCODE 28 148 | ISR_NOERRCODE 29 149 | ISR_NOERRCODE 30 150 | ISR_NOERRCODE 31 151 | 152 | %assign i 32 153 | %rep 224 154 | ISR_NOERRCODE i 155 | %assign i i+1 156 | %endrep 157 | 158 | section .data 159 | 160 | isr_gates: 161 | %assign i 0 162 | %rep 256 163 | dq isr_stub %+ i 164 | %assign i i+1 165 | %endrep 166 | 167 | section .bss 168 | 169 | isr_handlers: 170 | resb 8 * 256 171 | -------------------------------------------------------------------------------- /test/src/kernel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | uint64_t pit_ticks = 0; 38 | 39 | static char *build_overview(char *buffer) 40 | { 41 | ui_pages[0].title = "Overview"; 42 | ui_pages[0].body = buffer; 43 | 44 | hy_info_root_t *root = HY_INFO_ROOT; 45 | 46 | BSTR("Welcome to the H2 Test Utility.\n"); 47 | BSTR("Use LEFT and RIGHT to switch between pages, and UP and DOWN to scroll.\n\n"); 48 | 49 | bool pic = (0 != (root->flags & HY_INFO_FLAG_PCAT_COMPAT)); 50 | bool x2apic = (0 != (root->flags & HY_INFO_FLAG_X2APIC)); 51 | 52 | BSTR("8259 PIC present: "); 53 | BSTR(pic ? "Yes" : "No"); 54 | BSTR("\nx2APIC present: "); 55 | BSTR(x2apic ? "Yes" : "No"); 56 | BSTR("\n\n"); 57 | 58 | BSTR("LAPIC MMIO: "); 59 | BNUM(root->lapic_paddr); 60 | BSTR("\nRSDP Address: "); 61 | BNUM(root->rsdp_paddr); 62 | BSTR("\nFirst Free Address: "); 63 | BNUM(root->free_paddr); 64 | BSTR("\n\n"); 65 | 66 | return buffer; 67 | } 68 | 69 | static char *build_cpu(char *buffer) 70 | { 71 | ui_pages[1].title = "CPUs"; 72 | ui_pages[1].body = buffer; 73 | 74 | size_t i; 75 | for (i = 0; i < HY_INFO_ROOT->cpu_count; ++i) { 76 | hy_info_cpu_t *cpu = &(HY_INFO_CPU[i]); 77 | 78 | if (0 == (cpu->flags & HY_INFO_CPU_FLAG_PRESENT)) 79 | continue; 80 | 81 | BSTR("APIC ID: "); 82 | BNUM(cpu->apic_id); 83 | BSTR("\nACPI ID: "); 84 | BNUM(cpu->acpi_id); 85 | BSTR("\nLAPIC Timer Freq.: "); 86 | BNUM(cpu->lapic_timer_freq); 87 | BSTR(" Hz"); 88 | BSTR("\nNUMA domain: "); 89 | BNUM(cpu->domain); 90 | BSTR("\n\n"); 91 | } 92 | 93 | return buffer; 94 | } 95 | 96 | static char *build_ioapic(char *buffer) 97 | { 98 | ui_pages[2].title = "IO APICs"; 99 | ui_pages[2].body = buffer; 100 | 101 | size_t i; 102 | for (i = 0; i < HY_INFO_ROOT->ioapic_count; ++i) { 103 | hy_info_ioapic_t *ioapic = &(HY_INFO_IOAPIC[i]); 104 | 105 | BSTR("APIC ID: "); 106 | BNUM(ioapic->apic_id); 107 | BSTR("\nVersion: "); 108 | BNUM(ioapic->version); 109 | BSTR("\nGSI Base: "); 110 | BNUM(ioapic->gsi_base); 111 | BSTR("\nGSI Count: "); 112 | BNUM(ioapic->gsi_count); 113 | BSTR("\nMMIO Address: "); 114 | BNUM(ioapic->mmio_paddr); 115 | BSTR("\n\n"); 116 | } 117 | 118 | return buffer; 119 | } 120 | 121 | static char *build_memory(char *buffer) 122 | { 123 | ui_pages[3].title = "Memory Map"; 124 | ui_pages[3].body = buffer; 125 | 126 | size_t i; 127 | for (i = 0; i < HY_INFO_ROOT->mmap_count; ++i) { 128 | hy_info_mmap_t *mmap = &HY_INFO_MMAP[i]; 129 | 130 | BSTR("Address: "); 131 | BNUM(mmap->address); 132 | BSTR("\nLength: "); 133 | BNUM(mmap->length); 134 | BSTR("\nAvailable: "); 135 | BSTR((1 == mmap->available) ? "Yes" : "No"); 136 | BSTR("\n\n"); 137 | } 138 | 139 | return buffer; 140 | } 141 | 142 | static char *build_modules(char *buffer) 143 | { 144 | ui_pages[4].title = "Modules"; 145 | ui_pages[4].body = buffer; 146 | 147 | size_t i; 148 | for (i = 0; i < HY_INFO_ROOT->module_count; ++i) { 149 | hy_info_module_t *mod = &HY_INFO_MODULE[i]; 150 | 151 | BSTR("Name: "); 152 | BSTR(&HY_INFO_STRING[mod->name]); 153 | BSTR("\nAddress: "); 154 | BNUM(mod->address); 155 | BSTR("\nLength: "); 156 | BNUM(mod->length); 157 | BSTR("\n\n"); 158 | } 159 | 160 | return buffer; 161 | } 162 | 163 | static void fault_gp(isr_state_t *state) 164 | { 165 | char buffer_data[50]; 166 | char *buffer = (char *) &buffer_data; 167 | buffer = buffer_write("INT#", buffer); 168 | buffer = buffer_write_hex(state->vector, buffer); 169 | screen_write(buffer, 10, 20); 170 | } 171 | 172 | void kmain_bsp(void); 173 | void kmain_bsp(void) 174 | { 175 | size_t i = 0; 176 | for (i = 0; i < 256; ++i) { 177 | isr_handlers[i] = (uintptr_t) &fault_gp; 178 | } 179 | isr_handlers[KEYBOARD_IRQ_VECTOR] = (uintptr_t) &keyboard_handler; 180 | 181 | char *buffer = (char *) HY_INFO_ROOT->free_paddr; 182 | buffer = build_overview(buffer); 183 | buffer = build_cpu(&buffer[1]); 184 | buffer = build_ioapic(&buffer[1]); 185 | buffer = build_memory(&buffer[1]); 186 | buffer = build_modules(&buffer[1]); 187 | 188 | ui_display(0, 0); 189 | asm volatile ("sti"); 190 | keyboard_init(); 191 | while (1); 192 | } 193 | -------------------------------------------------------------------------------- /test/src/keyboard.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | bool keyboard_escaped = false; 34 | 35 | void keyboard_init(void) 36 | { 37 | while (inb(0x64) & 0x1) { 38 | inb(0x60); 39 | } 40 | 41 | keyboard_send_command(0xF4); 42 | } 43 | 44 | void keyboard_send_command(uint8_t cmd) 45 | { 46 | while (0 != (inb(0x64) & 0x2)) {} 47 | outb(0x60, cmd); 48 | } 49 | 50 | void keyboard_handler(isr_state_t *state) 51 | { 52 | uint8_t code = inb(0x60); 53 | outb(0x61, inb(0x61)); 54 | 55 | if (KEYBOARD_CODE_ESCAPED == code) { 56 | keyboard_escaped = true; 57 | 58 | } else if (keyboard_escaped) { 59 | switch (code) { 60 | case KEYBOARD_CODE_LEFT: 61 | ui_switch_left(); 62 | break; 63 | 64 | case KEYBOARD_CODE_RIGHT: 65 | ui_switch_right(); 66 | break; 67 | 68 | case KEYBOARD_CODE_UP: 69 | ui_scroll_up(); 70 | break; 71 | 72 | case KEYBOARD_CODE_DOWN: 73 | ui_scroll_down(); 74 | break; 75 | } 76 | 77 | keyboard_escaped = false; 78 | } 79 | 80 | lapic_eoi(); 81 | } 82 | -------------------------------------------------------------------------------- /test/src/lapic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #define LAPIC_X2APIC_MODE (0 != (HY_INFO_ROOT->flags & HY_INFO_FLAG_X2APIC)) 33 | 34 | static uint64_t __msr_read(uint32_t msr) 35 | { 36 | uint32_t a, d; 37 | asm volatile ("rdmsr" : "=a" (a), "=d" (d) : "c" (msr)); 38 | 39 | return (((uint64_t) d) << 32) | a; 40 | } 41 | 42 | static void __msr_write(uint32_t msr, uint64_t value) 43 | { 44 | uint32_t a = value; 45 | uint32_t d = (value >> 32); 46 | 47 | asm volatile ("wrmsr" :: "c" (msr), "a" (a), "d" (d)); 48 | } 49 | 50 | uint32_t lapic_register_read(uint16_t index) 51 | { 52 | if (!LAPIC_X2APIC_MODE) { 53 | return *((uint32_t *) (index * 0x10 + HY_INFO_ROOT->lapic_paddr)); 54 | } else { 55 | return __msr_read(LAPIC_MSR_REGS + index); 56 | } 57 | } 58 | 59 | void lapic_register_write(uint16_t index, uint32_t value) 60 | { 61 | if (!LAPIC_X2APIC_MODE) { 62 | *((uint32_t *) (index * 0x10 + HY_INFO_ROOT->lapic_paddr)) = value; 63 | } else { 64 | __msr_write(LAPIC_MSR_REGS + index, value); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/src/ports.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | void outb(uint16_t port, uint8_t value) 30 | { 31 | asm volatile ("outb %1, %0" :: "dN" (port), "a" (value)); 32 | } 33 | 34 | uint8_t inb(uint16_t port) 35 | { 36 | uint8_t value; 37 | asm volatile ("inb %1, %0" : "=a" (value) : "dN" (port)); 38 | return value; 39 | } 40 | -------------------------------------------------------------------------------- /test/src/screen.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | void screen_write(const char *string, uint16_t x, uint16_t y) 30 | { 31 | char *video = (char *) SCREEN_MEMORY; 32 | size_t screen_max = SCREEN_WIDTH * SCREEN_HEIGHT; 33 | 34 | size_t pos_screen = x + y * SCREEN_WIDTH; 35 | size_t pos_str; 36 | 37 | for (pos_str = 0; '\0' != string[pos_str] && pos_screen < screen_max; ++pos_str) { 38 | if ('\n' == string[pos_str]) { 39 | pos_screen = ((pos_screen / SCREEN_WIDTH) + 1) * SCREEN_WIDTH; 40 | } else { 41 | video[pos_screen * 2 ] = string[pos_str]; 42 | video[pos_screen * 2 + 1] = SCREEN_ATTR; 43 | ++pos_screen; 44 | } 45 | } 46 | } 47 | 48 | void screen_clear(void) 49 | { 50 | char *video = (char *) SCREEN_MEMORY; 51 | size_t screen_max = SCREEN_WIDTH * SCREEN_HEIGHT; 52 | 53 | size_t i; 54 | for (i = 0; i < screen_max; ++i) { 55 | video[i * 2 ] = ' '; 56 | video[i * 2 + 1] = SCREEN_ATTR; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/src/ui.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 by Lukas Heidemann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | ui_page_t ui_pages[UI_PAGE_COUNT]; 31 | 32 | size_t ui_page_current = 0; 33 | size_t ui_line_current = 0; 34 | 35 | static char *ui_get_line(char *string, size_t line) { 36 | size_t line_cur = 0; 37 | size_t i; 38 | 39 | for (i = 0; '\0' != string[i] && line_cur < line; ++i) { 40 | if ('\n' == string[i]) { 41 | ++line_cur; 42 | } 43 | } 44 | 45 | return &string[i]; 46 | } 47 | 48 | static void ui_display_header(ui_page_t *page) { 49 | screen_write("H2 Test Utility - ", 0, 0); 50 | screen_write(page->title, 18, 0); 51 | screen_write("----------------------------------------", 0, 1); 52 | screen_write("----------------------------------------", 40, 1); 53 | } 54 | 55 | static void ui_display_body(ui_page_t *page, size_t line) { 56 | char *body = ui_get_line(page->body, line); 57 | screen_write(body, 0, 2); 58 | } 59 | 60 | void ui_display(size_t page_nr, size_t line) 61 | { 62 | ui_page_t *page = &ui_pages[page_nr % UI_PAGE_COUNT]; 63 | 64 | screen_clear(); 65 | ui_display_header(page); 66 | ui_display_body(page, line); 67 | } 68 | 69 | void ui_switch_left(void) 70 | { 71 | if (0 != ui_page_current) { 72 | ui_line_current = 0; 73 | --ui_page_current; 74 | ui_display(ui_page_current, ui_line_current); 75 | } 76 | } 77 | 78 | void ui_switch_right(void) 79 | { 80 | if (ui_page_current < UI_PAGE_COUNT - 1) { 81 | ui_line_current = 0; 82 | ++ui_page_current; 83 | ui_display(ui_page_current, ui_line_current); 84 | } 85 | } 86 | 87 | void ui_scroll_up(void) 88 | { 89 | if (0 != ui_line_current) { 90 | ui_display(ui_page_current, --ui_line_current); 91 | } 92 | } 93 | 94 | void ui_scroll_down(void) 95 | { 96 | ui_display(ui_page_current, ++ui_line_current); 97 | } 98 | --------------------------------------------------------------------------------