protos: Drop stivale and stivale2 support
This commit is contained in:
parent
564044ec36
commit
746d0ad529
|
@ -20,7 +20,6 @@
|
||||||
/bochsout.txt
|
/bochsout.txt
|
||||||
/bx_enh_dbg.ini
|
/bx_enh_dbg.ini
|
||||||
/.vscode
|
/.vscode
|
||||||
/stivale
|
|
||||||
/test_image
|
/test_image
|
||||||
!/common/font.bin
|
!/common/font.bin
|
||||||
/configure
|
/configure
|
||||||
|
|
17
CONFIG.md
17
CONFIG.md
|
@ -97,7 +97,7 @@ Editor control options.
|
||||||
|
|
||||||
*Locally assignable (non protocol specific)* keys are:
|
*Locally assignable (non protocol specific)* keys are:
|
||||||
* `COMMENT` - An optional comment string that will be displayed by the bootloader on the menu when an entry is selected.
|
* `COMMENT` - An optional comment string that will be displayed by the bootloader on the menu when an entry is selected.
|
||||||
* `PROTOCOL` - The boot protocol that will be used to boot the kernel. Valid protocols are: `linux`, `limine`, `stivale`, `stivale2`, `chainload`, `multiboot` or `multiboot1` and `multiboot2`. If the protocol is omitted, Limine will try to autodetect it, following this list of protocols, in this order: `stivale2 -> stivale1 -> multiboot2 -> multiboot1 -> limine -> linux -> failure`.
|
* `PROTOCOL` - The boot protocol that will be used to boot the kernel. Valid protocols are: `linux`, `limine`, `chainload`, `multiboot` or `multiboot1` and `multiboot2`. If the protocol is omitted, Limine will try to autodetect it, following this list of protocols, in this order: `multiboot2 -> multiboot1 -> limine -> linux -> failure`.
|
||||||
* `CMDLINE` - The command line string to be passed to the kernel. Can be omitted.
|
* `CMDLINE` - The command line string to be passed to the kernel. Can be omitted.
|
||||||
* `KERNEL_CMDLINE` - Alias of `CMDLINE`.
|
* `KERNEL_CMDLINE` - Alias of `CMDLINE`.
|
||||||
|
|
||||||
|
@ -128,21 +128,6 @@ Editor control options.
|
||||||
* Chainload protocol on UEFI:
|
* Chainload protocol on UEFI:
|
||||||
* `IMAGE_PATH` - URI of the EFI application to chainload.
|
* `IMAGE_PATH` - URI of the EFI application to chainload.
|
||||||
* `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
|
* `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
|
||||||
* stivale and stivale2 protocols:
|
|
||||||
* `KERNEL_PATH` - The URI path of the kernel.
|
|
||||||
* `MODULE_PATH` - The URI path to a module.
|
|
||||||
* `MODULE_STRING` - A string to be passed to a module.
|
|
||||||
|
|
||||||
**Note:** One can define these 2 last variable multiple times to specify multiple
|
|
||||||
modules.
|
|
||||||
The entries will be matched in order. E.g.: The 1st module path entry will be matched
|
|
||||||
to the 1st module string entry that appear, and so on.
|
|
||||||
|
|
||||||
**Note**: If `MODULE_STRING` is not specified for an entry, the `MODULE_STRING` will default to the `MODULE_PATH`.
|
|
||||||
|
|
||||||
* `RESOLUTION` - The resolution to be used should the kernel request a graphical framebuffer. This setting takes the form of `<width>x<height>x<bpp>` and *overrides* any resolution requested by the kernel, or automatic resolution requests. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
|
|
||||||
* `KASLR` - For relocatable kernels, if set to `no`, disable kernel address space layout randomisation. KASLR is enabled by default.
|
|
||||||
* `TEXTMODE` - If set to `yes`, prefer text mode if the kernel has no video mode requirements. (Only for stivale2)
|
|
||||||
* Chainload protocol on BIOS:
|
* Chainload protocol on BIOS:
|
||||||
* `DRIVE` - The 1-based BIOS drive to chainload, if omitted, assume boot drive.
|
* `DRIVE` - The 1-based BIOS drive to chainload, if omitted, assume boot drive.
|
||||||
* `PARTITION` - The 1-based BIOS partition to chainload, if omitted, chainload drive (MBR).
|
* `PARTITION` - The 1-based BIOS partition to chainload, if omitted, chainload drive (MBR).
|
||||||
|
|
|
@ -199,7 +199,6 @@ dist:
|
||||||
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && NOCONFIGURE=yes ./autogen.sh
|
cd '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)" && NOCONFIGURE=yes ./autogen.sh
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/freestanding_headers/.git"
|
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/freestanding_headers/.git"
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/reduced-gnu-efi/.git"
|
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/reduced-gnu-efi/.git"
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/stivale/.git"
|
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/.git"
|
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/.git"
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/autom4te.cache"
|
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/autom4te.cache"
|
||||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/test"
|
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)/test"
|
||||||
|
@ -215,10 +214,10 @@ distclean: clean
|
||||||
|
|
||||||
.PHONY: maintainer-clean
|
.PHONY: maintainer-clean
|
||||||
maintainer-clean: distclean
|
maintainer-clean: distclean
|
||||||
cd '$(call SHESCAPE,$(SRCDIR))' && rm -rf freestanding_headers stivale reduced-gnu-efi configure build-aux *'~' autom4te.cache *.tar.xz *.tar.gz
|
cd '$(call SHESCAPE,$(SRCDIR))' && rm -rf freestanding_headers reduced-gnu-efi configure build-aux *'~' autom4te.cache *.tar.xz *.tar.gz
|
||||||
|
|
||||||
.PHONY: common-uefi64
|
.PHONY: common-uefi64
|
||||||
common-uefi64: $(call MKESCAPE,$(SRCDIR))/stivale
|
common-uefi64:
|
||||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=uefi64 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi64'
|
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=uefi64 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi64'
|
||||||
|
|
||||||
.PHONY: common-uefi64-clean
|
.PHONY: common-uefi64-clean
|
||||||
|
@ -226,7 +225,7 @@ common-uefi64-clean:
|
||||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' clean TARGET=uefi64 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi64'
|
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' clean TARGET=uefi64 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi64'
|
||||||
|
|
||||||
.PHONY: common-uefi32
|
.PHONY: common-uefi32
|
||||||
common-uefi32: $(call MKESCAPE,$(SRCDIR))/stivale
|
common-uefi32:
|
||||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=uefi32 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi32'
|
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=uefi32 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi32'
|
||||||
|
|
||||||
.PHONY: common-uefi32-clean
|
.PHONY: common-uefi32-clean
|
||||||
|
@ -234,7 +233,7 @@ common-uefi32-clean:
|
||||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' clean TARGET=uefi32 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi32'
|
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' clean TARGET=uefi32 BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi32'
|
||||||
|
|
||||||
.PHONY: common-bios
|
.PHONY: common-bios
|
||||||
common-bios: $(call MKESCAPE,$(SRCDIR))/stivale
|
common-bios:
|
||||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=bios BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-bios'
|
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all TARGET=bios BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-bios'
|
||||||
|
|
||||||
.PHONY: common-bios-clean
|
.PHONY: common-bios-clean
|
||||||
|
|
|
@ -14,7 +14,6 @@ as the reference implementation for the [Limine boot protocol](/PROTOCOL.md).
|
||||||
### Supported boot protocols
|
### Supported boot protocols
|
||||||
* Linux
|
* Linux
|
||||||
* [Limine](/PROTOCOL.md)
|
* [Limine](/PROTOCOL.md)
|
||||||
* stivale and stivale2 (see [their specifications](https://github.com/stivale) for details)
|
|
||||||
* Multiboot 1
|
* Multiboot 1
|
||||||
* Multiboot 2
|
* Multiboot 2
|
||||||
* Chainloading
|
* Chainloading
|
||||||
|
|
|
@ -10,7 +10,6 @@ test -z "$srcdir" && srcdir=.
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
|
|
||||||
[ -d freestanding_headers ] || git clone https://github.com/mintsuki/freestanding_headers.git
|
[ -d freestanding_headers ] || git clone https://github.com/mintsuki/freestanding_headers.git
|
||||||
[ -d stivale ] || git clone https://github.com/stivale/stivale.git
|
|
||||||
[ -d reduced-gnu-efi ] || git clone https://github.com/limine-bootloader/reduced-gnu-efi.git
|
[ -d reduced-gnu-efi ] || git clone https://github.com/limine-bootloader/reduced-gnu-efi.git
|
||||||
|
|
||||||
automake_libdir="$(automake --print-libdir)"
|
automake_libdir="$(automake --print-libdir)"
|
||||||
|
|
|
@ -67,7 +67,6 @@ override INTERNAL_CFLAGS := \
|
||||||
-I'$(call SHESCAPE,$(BUILDDIR))/..' \
|
-I'$(call SHESCAPE,$(BUILDDIR))/..' \
|
||||||
-I. \
|
-I. \
|
||||||
-I.. \
|
-I.. \
|
||||||
-I../stivale \
|
|
||||||
-I'$(call SHESCAPE,$(BUILDDIR))/tinf'
|
-I'$(call SHESCAPE,$(BUILDDIR))/tinf'
|
||||||
|
|
||||||
ifeq ($(TARGET), bios)
|
ifeq ($(TARGET), bios)
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include <fs/file.h>
|
#include <fs/file.h>
|
||||||
#include <lib/elf.h>
|
#include <lib/elf.h>
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <protos/stivale.h>
|
|
||||||
#include <protos/stivale2.h>
|
|
||||||
#include <protos/linux.h>
|
#include <protos/linux.h>
|
||||||
#include <protos/chainload.h>
|
#include <protos/chainload.h>
|
||||||
#include <menu.h>
|
#include <menu.h>
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <drivers/vbe.h>
|
#include <drivers/vbe.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
#include <protos/stivale.h>
|
|
||||||
#include <protos/stivale2.h>
|
|
||||||
#include <protos/linux.h>
|
#include <protos/linux.h>
|
||||||
#include <protos/chainload.h>
|
#include <protos/chainload.h>
|
||||||
#include <protos/multiboot1.h>
|
#include <protos/multiboot1.h>
|
||||||
|
@ -917,8 +915,6 @@ noreturn void boot(char *config) {
|
||||||
if (proto == NULL) {
|
if (proto == NULL) {
|
||||||
printv("PROTOCOL not specified, using autodetection...\n");
|
printv("PROTOCOL not specified, using autodetection...\n");
|
||||||
autodetect:
|
autodetect:
|
||||||
stivale2_load(config, cmdline);
|
|
||||||
stivale_load(config, cmdline);
|
|
||||||
multiboot2_load(config, cmdline);
|
multiboot2_load(config, cmdline);
|
||||||
multiboot1_load(config, cmdline);
|
multiboot1_load(config, cmdline);
|
||||||
limine_load(config, cmdline);
|
limine_load(config, cmdline);
|
||||||
|
@ -928,10 +924,10 @@ autodetect:
|
||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
if (!strcmp(proto, "stivale1") || !strcmp(proto, "stivale")) {
|
if (!strcmp(proto, "stivale1") || !strcmp(proto, "stivale") || !strcmp(proto, "stivale2")) {
|
||||||
ret = stivale_load(config, cmdline);
|
print("The stivale and stivale2 protocols is no longer supported as of Limine 4.x\n");
|
||||||
} else if (!strcmp(proto, "stivale2")) {
|
print("Please notify kernel maintainers to move to the Limine boot protocol or\n");
|
||||||
ret = stivale2_load(config, cmdline);
|
print("roll back to Limine 3.x.\n\n");
|
||||||
} else if (!strcmp(proto, "limine")) {
|
} else if (!strcmp(proto, "limine")) {
|
||||||
ret = limine_load(config, cmdline);
|
ret = limine_load(config, cmdline);
|
||||||
} else if (!strcmp(proto, "linux")) {
|
} else if (!strcmp(proto, "linux")) {
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdnoreturn.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
|
||||||
|
noreturn void limine_spinup_32(
|
||||||
|
bool level5pg, uint32_t pagemap_top_lv,
|
||||||
|
uint32_t entry_point_lo, uint32_t entry_point_hi,
|
||||||
|
uint32_t stack_lo, uint32_t stack_hi,
|
||||||
|
uint32_t local_gdt) {
|
||||||
|
uint64_t casted_to_64[] = {
|
||||||
|
(uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32),
|
||||||
|
(uint64_t)stack_lo | ((uint64_t)stack_hi << 32),
|
||||||
|
(uint64_t)local_gdt
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enable NX
|
||||||
|
asm volatile (
|
||||||
|
"movl $0xc0000080, %%ecx\n\t"
|
||||||
|
"rdmsr\n\t"
|
||||||
|
"btsl $11, %%eax\n\t"
|
||||||
|
"wrmsr\n\t"
|
||||||
|
::: "eax", "ecx", "edx", "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (level5pg) {
|
||||||
|
// Enable CR4.LA57
|
||||||
|
asm volatile (
|
||||||
|
"movl %%cr4, %%eax\n\t"
|
||||||
|
"btsl $12, %%eax\n\t"
|
||||||
|
"movl %%eax, %%cr4\n\t"
|
||||||
|
::: "eax", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable WP
|
||||||
|
asm volatile (
|
||||||
|
"movl %%cr0, %%eax\n\t"
|
||||||
|
"btsl $16, %%eax\n\t"
|
||||||
|
"movl %%eax, %%cr0\n\t"
|
||||||
|
::: "eax", "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"cld\n\t"
|
||||||
|
"movl %%eax, %%cr3\n\t"
|
||||||
|
"movl %%cr4, %%eax\n\t"
|
||||||
|
"btsl $5, %%eax\n\t"
|
||||||
|
"movl %%eax, %%cr4\n\t"
|
||||||
|
"movl $0xc0000080, %%ecx\n\t"
|
||||||
|
"rdmsr\n\t"
|
||||||
|
"btsl $8, %%eax\n\t"
|
||||||
|
"wrmsr\n\t"
|
||||||
|
"movl %%cr0, %%eax\n\t"
|
||||||
|
"btsl $31, %%eax\n\t"
|
||||||
|
"movl %%eax, %%cr0\n\t"
|
||||||
|
"call 1f\n\t"
|
||||||
|
"1: popl %%eax\n\t"
|
||||||
|
"addl $8, %%eax\n\t"
|
||||||
|
"pushl $0x28\n\t"
|
||||||
|
"pushl %%eax\n\t"
|
||||||
|
"lret\n\t"
|
||||||
|
".code64\n\t"
|
||||||
|
"movl $0x30, %%eax\n\t"
|
||||||
|
"movl %%eax, %%ds\n\t"
|
||||||
|
"movl %%eax, %%es\n\t"
|
||||||
|
"movl %%eax, %%fs\n\t"
|
||||||
|
"movl %%eax, %%gs\n\t"
|
||||||
|
"movl %%eax, %%ss\n\t"
|
||||||
|
|
||||||
|
// Since we don't really know what is now present in the upper
|
||||||
|
// 32 bits of the 64 bit registers, clear up the upper bits
|
||||||
|
// of the register that points to the 64-bit casted value array.
|
||||||
|
"movl %%esi, %%esi\n\t"
|
||||||
|
|
||||||
|
// Move in 64-bit values
|
||||||
|
"movq 0x00(%%rsi), %%rbx\n\t"
|
||||||
|
"movq 0x10(%%rsi), %%rax\n\t"
|
||||||
|
"movq 0x08(%%rsi), %%rsi\n\t"
|
||||||
|
|
||||||
|
// Load 64 bit GDT
|
||||||
|
"lgdt (%%rax)\n\t"
|
||||||
|
|
||||||
|
// Let's pretend we push a return address
|
||||||
|
"subq $8, %%rsi\n\t"
|
||||||
|
"movq $0, (%%rsi)\n\t"
|
||||||
|
|
||||||
|
"pushq $0x30\n\t"
|
||||||
|
"pushq %%rsi\n\t"
|
||||||
|
"pushfq\n\t"
|
||||||
|
"pushq $0x28\n\t"
|
||||||
|
"pushq %%rbx\n\t"
|
||||||
|
|
||||||
|
"xorl %%eax, %%eax\n\t"
|
||||||
|
"xorl %%ebx, %%ebx\n\t"
|
||||||
|
"xorl %%ecx, %%ecx\n\t"
|
||||||
|
"xorl %%edx, %%edx\n\t"
|
||||||
|
"xorl %%esi, %%esi\n\t"
|
||||||
|
"xorl %%edi, %%edi\n\t"
|
||||||
|
"xorl %%ebp, %%ebp\n\t"
|
||||||
|
"xorl %%r8d, %%r8d\n\t"
|
||||||
|
"xorl %%r9d, %%r9d\n\t"
|
||||||
|
"xorl %%r10d, %%r10d\n\t"
|
||||||
|
"xorl %%r11d, %%r11d\n\t"
|
||||||
|
"xorl %%r12d, %%r12d\n\t"
|
||||||
|
"xorl %%r13d, %%r13d\n\t"
|
||||||
|
"xorl %%r14d, %%r14d\n\t"
|
||||||
|
"xorl %%r15d, %%r15d\n\t"
|
||||||
|
|
||||||
|
"iretq\n\t"
|
||||||
|
".code32\n\t"
|
||||||
|
:
|
||||||
|
: "a" (pagemap_top_lv), "S" (casted_to_64)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
|
@ -2,8 +2,6 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <protos/stivale.h>
|
|
||||||
#include <protos/stivale2.h>
|
|
||||||
#include <lib/elf.h>
|
#include <lib/elf.h>
|
||||||
#include <lib/blib.h>
|
#include <lib/blib.h>
|
||||||
#include <lib/acpi.h>
|
#include <lib/acpi.h>
|
||||||
|
@ -21,9 +19,9 @@
|
||||||
#include <lib/term.h>
|
#include <lib/term.h>
|
||||||
#include <sys/pic.h>
|
#include <sys/pic.h>
|
||||||
#include <sys/lapic.h>
|
#include <sys/lapic.h>
|
||||||
|
#include <sys/idt.h>
|
||||||
#include <fs/file.h>
|
#include <fs/file.h>
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <stivale2.h>
|
|
||||||
#include <pxe/tftp.h>
|
#include <pxe/tftp.h>
|
||||||
#include <drivers/edid.h>
|
#include <drivers/edid.h>
|
||||||
#include <drivers/vga_textmode.h>
|
#include <drivers/vga_textmode.h>
|
||||||
|
@ -35,6 +33,132 @@
|
||||||
#define MAX_REQUESTS 128
|
#define MAX_REQUESTS 128
|
||||||
#define MAX_MEMMAP 256
|
#define MAX_MEMMAP 256
|
||||||
|
|
||||||
|
pagemap_t build_pagemap(bool level5pg, struct elf_range *ranges, size_t ranges_count,
|
||||||
|
uint64_t physical_base, uint64_t virtual_base,
|
||||||
|
uint64_t direct_map_offset) {
|
||||||
|
pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
|
||||||
|
|
||||||
|
if (ranges_count == 0) {
|
||||||
|
// Map 0 to 2GiB at 0xffffffff80000000
|
||||||
|
for (uint64_t i = 0; i < 0x80000000; i += 0x40000000) {
|
||||||
|
map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, Size1GiB);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < ranges_count; i++) {
|
||||||
|
uint64_t virt = ranges[i].base;
|
||||||
|
uint64_t phys;
|
||||||
|
|
||||||
|
if (virt & ((uint64_t)1 << 63)) {
|
||||||
|
phys = physical_base + (virt - virtual_base);
|
||||||
|
} else {
|
||||||
|
panic(false, "limine: Protected memory ranges are only supported for higher half kernels");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t pf = VMM_FLAG_PRESENT |
|
||||||
|
(ranges[i].permissions & ELF_PF_X ? 0 : VMM_FLAG_NOEXEC) |
|
||||||
|
(ranges[i].permissions & ELF_PF_W ? VMM_FLAG_WRITE : 0);
|
||||||
|
|
||||||
|
for (uint64_t j = 0; j < ranges[i].length; j += 0x1000) {
|
||||||
|
map_page(pagemap, virt + j, phys + j, pf, Size4KiB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub 2MiB mappings
|
||||||
|
for (uint64_t i = 0; i < 0x200000; i += 0x1000) {
|
||||||
|
if (i != 0) {
|
||||||
|
map_page(pagemap, i, i, 0x03, Size4KiB);
|
||||||
|
}
|
||||||
|
map_page(pagemap, direct_map_offset + i, i, 0x03, Size4KiB);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map 2MiB to 4GiB at higher half base and 0
|
||||||
|
//
|
||||||
|
// NOTE: We cannot just directly map from 2MiB to 4GiB with 1GiB
|
||||||
|
// pages because if you do the math.
|
||||||
|
//
|
||||||
|
// start = 0x200000
|
||||||
|
// end = 0x40000000
|
||||||
|
//
|
||||||
|
// pages_required = (end - start) / (4096 * 512 * 512)
|
||||||
|
//
|
||||||
|
// So we map 2MiB to 1GiB with 2MiB pages and then map the rest
|
||||||
|
// with 1GiB pages :^)
|
||||||
|
for (uint64_t i = 0x200000; i < 0x40000000; i += 0x200000) {
|
||||||
|
map_page(pagemap, i, i, 0x03, Size2MiB);
|
||||||
|
map_page(pagemap, direct_map_offset + i, i, 0x03, Size2MiB);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint64_t i = 0x40000000; i < 0x100000000; i += 0x40000000) {
|
||||||
|
map_page(pagemap, i, i, 0x03, Size1GiB);
|
||||||
|
map_page(pagemap, direct_map_offset + i, i, 0x03, Size1GiB);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _memmap_entries = memmap_entries;
|
||||||
|
struct e820_entry_t *_memmap =
|
||||||
|
ext_mem_alloc(_memmap_entries * sizeof(struct e820_entry_t));
|
||||||
|
for (size_t i = 0; i < _memmap_entries; i++)
|
||||||
|
_memmap[i] = memmap[i];
|
||||||
|
|
||||||
|
// Map any other region of memory from the memmap
|
||||||
|
for (size_t i = 0; i < _memmap_entries; i++) {
|
||||||
|
uint64_t base = _memmap[i].base;
|
||||||
|
uint64_t length = _memmap[i].length;
|
||||||
|
uint64_t top = base + length;
|
||||||
|
|
||||||
|
if (base < 0x100000000)
|
||||||
|
base = 0x100000000;
|
||||||
|
|
||||||
|
if (base >= top)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint64_t aligned_base = ALIGN_DOWN(base, 0x40000000);
|
||||||
|
uint64_t aligned_top = ALIGN_UP(top, 0x40000000);
|
||||||
|
uint64_t aligned_length = aligned_top - aligned_base;
|
||||||
|
|
||||||
|
for (uint64_t j = 0; j < aligned_length; j += 0x40000000) {
|
||||||
|
uint64_t page = aligned_base + j;
|
||||||
|
map_page(pagemap, page, page, 0x03, Size1GiB);
|
||||||
|
map_page(pagemap, direct_map_offset + page, page, 0x03, Size1GiB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagemap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if uefi == 1
|
||||||
|
extern symbol ImageBase;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern symbol limine_spinup_32;
|
||||||
|
|
||||||
|
static noreturn void spinup(bool level5pg, pagemap_t *pagemap,
|
||||||
|
uint64_t entry_point, uint64_t stack,
|
||||||
|
uint32_t local_gdt) {
|
||||||
|
#if bios == 1
|
||||||
|
// If we're going 64, we might as well call this BIOS interrupt
|
||||||
|
// to tell the BIOS that we are entering Long Mode, since it is in
|
||||||
|
// the specification.
|
||||||
|
struct rm_regs r = {0};
|
||||||
|
r.eax = 0xec00;
|
||||||
|
r.ebx = 0x02; // Long mode only
|
||||||
|
rm_int(0x15, &r, &r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vmm_assert_nx();
|
||||||
|
|
||||||
|
pic_mask_all();
|
||||||
|
io_apic_mask_all();
|
||||||
|
|
||||||
|
irq_flush_type = IRQ_PIC_APIC_FLUSH;
|
||||||
|
|
||||||
|
common_spinup(limine_spinup_32, 7,
|
||||||
|
level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
|
||||||
|
(uint32_t)entry_point, (uint32_t)(entry_point >> 32),
|
||||||
|
(uint32_t)stack, (uint32_t)(stack >> 32),
|
||||||
|
local_gdt);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t physical_base, virtual_base, slide, direct_map_offset;
|
static uint64_t physical_base, virtual_base, slide, direct_map_offset;
|
||||||
static size_t requests_count;
|
static size_t requests_count;
|
||||||
static void **requests;
|
static void **requests;
|
||||||
|
@ -111,11 +235,11 @@ static void *_get_request(uint64_t id[4]) {
|
||||||
#define FEAT_END } while (0);
|
#define FEAT_END } while (0);
|
||||||
|
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
extern symbol stivale2_term_write_entry;
|
extern symbol limine_term_write_entry;
|
||||||
extern void *stivale2_rt_stack;
|
void *limine_rt_stack = NULL;
|
||||||
extern uint64_t stivale2_term_callback_ptr;
|
uint64_t limine_term_callback_ptr = 0;
|
||||||
extern uint64_t stivale2_term_write_ptr;
|
uint64_t limine_term_write_ptr = 0;
|
||||||
void stivale2_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
void limine_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void term_write_shim(uint64_t context, uint64_t buf, uint64_t count) {
|
static void term_write_shim(uint64_t context, uint64_t buf, uint64_t count) {
|
||||||
|
@ -505,8 +629,8 @@ FEAT_START
|
||||||
|
|
||||||
if (terminal_request->callback != 0) {
|
if (terminal_request->callback != 0) {
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
term_callback = stivale2_term_callback;
|
term_callback = limine_term_callback;
|
||||||
stivale2_term_callback_ptr = terminal_request->callback;
|
limine_term_callback_ptr = terminal_request->callback;
|
||||||
#elif defined (__x86_64__)
|
#elif defined (__x86_64__)
|
||||||
term_callback = (void *)terminal_request->callback;
|
term_callback = (void *)terminal_request->callback;
|
||||||
#endif
|
#endif
|
||||||
|
@ -515,12 +639,12 @@ FEAT_START
|
||||||
term_arg = reported_addr(terminal);
|
term_arg = reported_addr(terminal);
|
||||||
|
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
if (stivale2_rt_stack == NULL) {
|
if (limine_rt_stack == NULL) {
|
||||||
stivale2_rt_stack = ext_mem_alloc(16384) + 16384;
|
limine_rt_stack = ext_mem_alloc(16384) + 16384;
|
||||||
}
|
}
|
||||||
|
|
||||||
stivale2_term_write_ptr = (uintptr_t)term_write_shim;
|
limine_term_write_ptr = (uintptr_t)term_write_shim;
|
||||||
terminal_response->write = (uintptr_t)(void *)stivale2_term_write_entry;
|
terminal_response->write = (uintptr_t)(void *)limine_term_write_entry;
|
||||||
#elif defined (__x86_64__)
|
#elif defined (__x86_64__)
|
||||||
terminal_response->write = (uintptr_t)term_write_shim;
|
terminal_response->write = (uintptr_t)term_write_shim;
|
||||||
#endif
|
#endif
|
||||||
|
@ -571,8 +695,8 @@ FEAT_START
|
||||||
|
|
||||||
if (terminal_request->callback != 0) {
|
if (terminal_request->callback != 0) {
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
term_callback = stivale2_term_callback;
|
term_callback = limine_term_callback;
|
||||||
stivale2_term_callback_ptr = terminal_request->callback;
|
limine_term_callback_ptr = terminal_request->callback;
|
||||||
#elif defined (__x86_64__)
|
#elif defined (__x86_64__)
|
||||||
term_callback = (void *)terminal_request->callback;
|
term_callback = (void *)terminal_request->callback;
|
||||||
#endif
|
#endif
|
||||||
|
@ -581,12 +705,12 @@ FEAT_START
|
||||||
term_arg = reported_addr(terminal);
|
term_arg = reported_addr(terminal);
|
||||||
|
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
if (stivale2_rt_stack == NULL) {
|
if (limine_rt_stack == NULL) {
|
||||||
stivale2_rt_stack = ext_mem_alloc(16384) + 16384;
|
limine_rt_stack = ext_mem_alloc(16384) + 16384;
|
||||||
}
|
}
|
||||||
|
|
||||||
stivale2_term_write_ptr = (uintptr_t)term_write_shim;
|
limine_term_write_ptr = (uintptr_t)term_write_shim;
|
||||||
terminal_response->write = (uintptr_t)(void *)stivale2_term_write_entry;
|
terminal_response->write = (uintptr_t)(void *)limine_term_write_entry;
|
||||||
#elif defined (__x86_64__)
|
#elif defined (__x86_64__)
|
||||||
terminal_response->write = (uintptr_t)term_write_shim;
|
terminal_response->write = (uintptr_t)term_write_shim;
|
||||||
#endif
|
#endif
|
||||||
|
@ -744,7 +868,7 @@ FEAT_END
|
||||||
void *stack = ext_mem_alloc(stack_size) + stack_size;
|
void *stack = ext_mem_alloc(stack_size) + stack_size;
|
||||||
|
|
||||||
pagemap_t pagemap = {0};
|
pagemap_t pagemap = {0};
|
||||||
pagemap = stivale_build_pagemap(want_5lv, true, ranges, ranges_count, true,
|
pagemap = build_pagemap(want_5lv, ranges, ranges_count,
|
||||||
physical_base, virtual_base, direct_map_offset);
|
physical_base, virtual_base, direct_map_offset);
|
||||||
|
|
||||||
#if uefi == 1
|
#if uefi == 1
|
||||||
|
@ -866,8 +990,8 @@ FEAT_END
|
||||||
|
|
||||||
term_runtime = true;
|
term_runtime = true;
|
||||||
|
|
||||||
stivale_spinup(64, want_5lv, &pagemap, entry_point, 0,
|
spinup(want_5lv, &pagemap, entry_point,
|
||||||
reported_addr(stack), true, true, (uintptr_t)local_gdt);
|
reported_addr(stack), (uintptr_t)local_gdt);
|
||||||
|
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,12 @@ user_ss: resq 1
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
extern term_write
|
extern term_write
|
||||||
extern stivale2_rt_stack
|
extern limine_rt_stack
|
||||||
extern stivale2_term_callback_ptr
|
extern limine_term_callback_ptr
|
||||||
extern stivale2_term_write_ptr
|
extern limine_term_write_ptr
|
||||||
|
|
||||||
global stivale2_term_callback
|
global limine_term_callback
|
||||||
stivale2_term_callback:
|
limine_term_callback:
|
||||||
bits 32
|
bits 32
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -53,7 +53,7 @@ bits 64
|
||||||
|
|
||||||
mov rbx, rsp
|
mov rbx, rsp
|
||||||
mov rsp, [rax + user_stack wrt ..gotoff]
|
mov rsp, [rax + user_stack wrt ..gotoff]
|
||||||
call [rax + stivale2_term_callback_ptr wrt ..gotoff]
|
call [rax + limine_term_callback_ptr wrt ..gotoff]
|
||||||
mov rsp, rbx
|
mov rsp, rbx
|
||||||
|
|
||||||
; Go 32
|
; Go 32
|
||||||
|
@ -77,8 +77,8 @@ bits 32
|
||||||
ret
|
ret
|
||||||
|
|
||||||
bits 64
|
bits 64
|
||||||
global stivale2_term_write_entry
|
global limine_term_write_entry
|
||||||
stivale2_term_write_entry:
|
limine_term_write_entry:
|
||||||
push rbx
|
push rbx
|
||||||
push rbp
|
push rbp
|
||||||
push r12
|
push r12
|
||||||
|
@ -92,7 +92,7 @@ stivale2_term_write_entry:
|
||||||
add ebx, _GLOBAL_OFFSET_TABLE_ + $$ - .get_got wrt ..gotpc
|
add ebx, _GLOBAL_OFFSET_TABLE_ + $$ - .get_got wrt ..gotpc
|
||||||
|
|
||||||
mov [rbx + user_stack wrt ..gotoff], rsp
|
mov [rbx + user_stack wrt ..gotoff], rsp
|
||||||
mov esp, [rbx + stivale2_rt_stack wrt ..gotoff]
|
mov esp, [rbx + limine_rt_stack wrt ..gotoff]
|
||||||
|
|
||||||
mov word [rbx + user_cs wrt ..gotoff], cs
|
mov word [rbx + user_cs wrt ..gotoff], cs
|
||||||
mov word [rbx + user_ds wrt ..gotoff], ds
|
mov word [rbx + user_ds wrt ..gotoff], ds
|
||||||
|
@ -115,7 +115,7 @@ bits 32
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
|
||||||
call [ebx + stivale2_term_write_ptr wrt ..gotoff]
|
call [ebx + limine_term_write_ptr wrt ..gotoff]
|
||||||
add esp, 24
|
add esp, 24
|
||||||
|
|
||||||
push dword [ebx + user_cs wrt ..gotoff]
|
push dword [ebx + user_cs wrt ..gotoff]
|
|
@ -11,12 +11,12 @@ user_ss: resq 1
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
extern term_write
|
extern term_write
|
||||||
extern stivale2_rt_stack
|
extern limine_rt_stack
|
||||||
extern stivale2_term_callback_ptr
|
extern limine_term_callback_ptr
|
||||||
extern stivale2_term_write_ptr
|
extern limine_term_write_ptr
|
||||||
|
|
||||||
global stivale2_term_callback
|
global limine_term_callback
|
||||||
stivale2_term_callback:
|
limine_term_callback:
|
||||||
bits 32
|
bits 32
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -44,7 +44,7 @@ bits 64
|
||||||
|
|
||||||
mov rbx, rsp
|
mov rbx, rsp
|
||||||
mov rsp, [user_stack]
|
mov rsp, [user_stack]
|
||||||
call [stivale2_term_callback_ptr]
|
call [limine_term_callback_ptr]
|
||||||
mov rsp, rbx
|
mov rsp, rbx
|
||||||
|
|
||||||
; Go 32
|
; Go 32
|
||||||
|
@ -65,8 +65,8 @@ bits 32
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global stivale2_term_write_entry
|
global limine_term_write_entry
|
||||||
stivale2_term_write_entry:
|
limine_term_write_entry:
|
||||||
bits 64
|
bits 64
|
||||||
push rbx
|
push rbx
|
||||||
push rbp
|
push rbp
|
||||||
|
@ -76,7 +76,7 @@ bits 64
|
||||||
push r15
|
push r15
|
||||||
|
|
||||||
mov [user_stack], rsp
|
mov [user_stack], rsp
|
||||||
mov esp, [stivale2_rt_stack]
|
mov esp, [limine_rt_stack]
|
||||||
|
|
||||||
mov word [user_cs], cs
|
mov word [user_cs], cs
|
||||||
mov word [user_ds], ds
|
mov word [user_ds], ds
|
||||||
|
@ -97,7 +97,7 @@ bits 32
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
|
||||||
call [stivale2_term_write_ptr]
|
call [limine_term_write_ptr]
|
||||||
add esp, 24
|
add esp, 24
|
||||||
|
|
||||||
push dword [user_cs]
|
push dword [user_cs]
|
|
@ -1,156 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdnoreturn.h>
|
|
||||||
#include <mm/vmm.h>
|
|
||||||
|
|
||||||
noreturn void stivale_spinup_32(
|
|
||||||
int bits, bool level5pg, bool enable_nx, bool wp, uint32_t pagemap_top_lv,
|
|
||||||
uint32_t entry_point_lo, uint32_t entry_point_hi,
|
|
||||||
uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
|
|
||||||
uint32_t stack_lo, uint32_t stack_hi,
|
|
||||||
uint32_t local_gdt) {
|
|
||||||
uint64_t casted_to_64[] = {
|
|
||||||
(uint64_t)stivale_struct_lo | ((uint64_t)stivale_struct_hi << 32),
|
|
||||||
(uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32),
|
|
||||||
(uint64_t)stack_lo | ((uint64_t)stack_hi << 32),
|
|
||||||
(uint64_t)local_gdt
|
|
||||||
};
|
|
||||||
|
|
||||||
if (bits == 64) {
|
|
||||||
if (enable_nx) {
|
|
||||||
asm volatile (
|
|
||||||
"movl $0xc0000080, %%ecx\n\t"
|
|
||||||
"rdmsr\n\t"
|
|
||||||
"btsl $11, %%eax\n\t"
|
|
||||||
"wrmsr\n\t"
|
|
||||||
::: "eax", "ecx", "edx", "memory"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level5pg) {
|
|
||||||
// Enable CR4.LA57
|
|
||||||
asm volatile (
|
|
||||||
"movl %%cr4, %%eax\n\t"
|
|
||||||
"btsl $12, %%eax\n\t"
|
|
||||||
"movl %%eax, %%cr4\n\t"
|
|
||||||
::: "eax", "memory"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp) {
|
|
||||||
asm volatile (
|
|
||||||
"movl %%cr0, %%eax\n\t"
|
|
||||||
"btsl $16, %%eax\n\t"
|
|
||||||
"movl %%eax, %%cr0\n\t"
|
|
||||||
::: "eax", "memory"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
asm volatile (
|
|
||||||
"cld\n\t"
|
|
||||||
"movl %%eax, %%cr3\n\t"
|
|
||||||
"movl %%cr4, %%eax\n\t"
|
|
||||||
"btsl $5, %%eax\n\t"
|
|
||||||
"movl %%eax, %%cr4\n\t"
|
|
||||||
"movl $0xc0000080, %%ecx\n\t"
|
|
||||||
"rdmsr\n\t"
|
|
||||||
"btsl $8, %%eax\n\t"
|
|
||||||
"wrmsr\n\t"
|
|
||||||
"movl %%cr0, %%eax\n\t"
|
|
||||||
"btsl $31, %%eax\n\t"
|
|
||||||
"movl %%eax, %%cr0\n\t"
|
|
||||||
"call 1f\n\t"
|
|
||||||
"1: popl %%eax\n\t"
|
|
||||||
"addl $8, %%eax\n\t"
|
|
||||||
"pushl $0x28\n\t"
|
|
||||||
"pushl %%eax\n\t"
|
|
||||||
"lret\n\t"
|
|
||||||
".code64\n\t"
|
|
||||||
"movl $0x30, %%eax\n\t"
|
|
||||||
"movl %%eax, %%ds\n\t"
|
|
||||||
"movl %%eax, %%es\n\t"
|
|
||||||
"movl %%eax, %%fs\n\t"
|
|
||||||
"movl %%eax, %%gs\n\t"
|
|
||||||
"movl %%eax, %%ss\n\t"
|
|
||||||
|
|
||||||
// Since we don't really know what is now present in the upper
|
|
||||||
// 32 bits of the 64 bit registers, clear up the upper bits
|
|
||||||
// of the register that points to the 64-bit casted value array.
|
|
||||||
"movl %%esi, %%esi\n\t"
|
|
||||||
|
|
||||||
// Move in 64-bit values
|
|
||||||
"movq 0x00(%%rsi), %%rdi\n\t"
|
|
||||||
"movq 0x08(%%rsi), %%rbx\n\t"
|
|
||||||
"movq 0x18(%%rsi), %%rax\n\t"
|
|
||||||
"movq 0x10(%%rsi), %%rsi\n\t"
|
|
||||||
|
|
||||||
// Load 64 bit GDT
|
|
||||||
"lgdt (%%rax)\n\t"
|
|
||||||
|
|
||||||
// Let's pretend we push a return address
|
|
||||||
"testq %%rsi, %%rsi\n\t"
|
|
||||||
"jz 1f\n\t"
|
|
||||||
|
|
||||||
"subq $8, %%rsi\n\t"
|
|
||||||
"movq $0, (%%rsi)\n\t"
|
|
||||||
|
|
||||||
"1:\n\t"
|
|
||||||
"pushq $0x30\n\t"
|
|
||||||
"pushq %%rsi\n\t"
|
|
||||||
"pushfq\n\t"
|
|
||||||
"pushq $0x28\n\t"
|
|
||||||
"pushq %%rbx\n\t"
|
|
||||||
|
|
||||||
"xorl %%eax, %%eax\n\t"
|
|
||||||
"xorl %%ebx, %%ebx\n\t"
|
|
||||||
"xorl %%ecx, %%ecx\n\t"
|
|
||||||
"xorl %%edx, %%edx\n\t"
|
|
||||||
"xorl %%esi, %%esi\n\t"
|
|
||||||
"xorl %%ebp, %%ebp\n\t"
|
|
||||||
"xorl %%r8d, %%r8d\n\t"
|
|
||||||
"xorl %%r9d, %%r9d\n\t"
|
|
||||||
"xorl %%r10d, %%r10d\n\t"
|
|
||||||
"xorl %%r11d, %%r11d\n\t"
|
|
||||||
"xorl %%r12d, %%r12d\n\t"
|
|
||||||
"xorl %%r13d, %%r13d\n\t"
|
|
||||||
"xorl %%r14d, %%r14d\n\t"
|
|
||||||
"xorl %%r15d, %%r15d\n\t"
|
|
||||||
|
|
||||||
"iretq\n\t"
|
|
||||||
".code32\n\t"
|
|
||||||
:
|
|
||||||
: "a" (pagemap_top_lv), "S" (casted_to_64)
|
|
||||||
: "memory"
|
|
||||||
);
|
|
||||||
} else if (bits == 32) {
|
|
||||||
asm volatile (
|
|
||||||
"cld\n\t"
|
|
||||||
|
|
||||||
"movl %%esi, %%esp\n\t"
|
|
||||||
"pushl %%edi\n\t"
|
|
||||||
"pushl $0\n\t"
|
|
||||||
|
|
||||||
"pushfl\n\t"
|
|
||||||
"pushl $0x18\n\t"
|
|
||||||
"pushl %%ebx\n\t"
|
|
||||||
|
|
||||||
"xorl %%eax, %%eax\n\t"
|
|
||||||
"xorl %%ebx, %%ebx\n\t"
|
|
||||||
"xorl %%ecx, %%ecx\n\t"
|
|
||||||
"xorl %%edx, %%edx\n\t"
|
|
||||||
"xorl %%esi, %%esi\n\t"
|
|
||||||
"xorl %%edi, %%edi\n\t"
|
|
||||||
"xorl %%ebp, %%ebp\n\t"
|
|
||||||
|
|
||||||
"iretl\n\t"
|
|
||||||
:
|
|
||||||
: "D" ((uint32_t)casted_to_64[0]),
|
|
||||||
"b" ((uint32_t)casted_to_64[1]),
|
|
||||||
"S" ((uint32_t)casted_to_64[2])
|
|
||||||
: "memory"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
|
@ -1,521 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdnoreturn.h>
|
|
||||||
#include <protos/stivale.h>
|
|
||||||
#include <lib/libc.h>
|
|
||||||
#include <lib/elf.h>
|
|
||||||
#include <lib/blib.h>
|
|
||||||
#include <lib/acpi.h>
|
|
||||||
#include <lib/config.h>
|
|
||||||
#include <lib/time.h>
|
|
||||||
#include <lib/print.h>
|
|
||||||
#include <lib/real.h>
|
|
||||||
#include <lib/uri.h>
|
|
||||||
#include <lib/fb.h>
|
|
||||||
#include <lib/term.h>
|
|
||||||
#include <sys/pic.h>
|
|
||||||
#include <sys/cpu.h>
|
|
||||||
#include <sys/gdt.h>
|
|
||||||
#include <sys/idt.h>
|
|
||||||
#include <sys/lapic.h>
|
|
||||||
#include <fs/file.h>
|
|
||||||
#include <mm/vmm.h>
|
|
||||||
#include <mm/pmm.h>
|
|
||||||
#include <stivale.h>
|
|
||||||
#include <drivers/vga_textmode.h>
|
|
||||||
#include <drivers/gop.h>
|
|
||||||
|
|
||||||
#define REPORTED_ADDR(PTR) \
|
|
||||||
((PTR) + ((stivale_hdr.flags & (1 << 3)) ? \
|
|
||||||
direct_map_offset : 0))
|
|
||||||
|
|
||||||
bool stivale_load_by_anchor(void **_anchor, const char *magic,
|
|
||||||
uint8_t *file, uint64_t filesize) {
|
|
||||||
struct stivale_anchor *anchor = NULL;
|
|
||||||
size_t magiclen = strlen(magic);
|
|
||||||
for (size_t i = 0; i < filesize; i += 16) {
|
|
||||||
if (memcmp(file + i, magic, magiclen) == 0) {
|
|
||||||
anchor = (void *)(file + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (anchor == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memmap_alloc_range(anchor->phys_load_addr, filesize, MEMMAP_KERNEL_AND_MODULES,
|
|
||||||
true, true, false, false);
|
|
||||||
memcpy((void *)(uintptr_t)anchor->phys_load_addr, file, filesize);
|
|
||||||
|
|
||||||
size_t bss_size = anchor->phys_bss_end - anchor->phys_bss_start;
|
|
||||||
memmap_alloc_range(anchor->phys_bss_start, bss_size, MEMMAP_KERNEL_AND_MODULES,
|
|
||||||
true, true, false, false);
|
|
||||||
memset((void *)(uintptr_t)anchor->phys_bss_start, 0, bss_size);
|
|
||||||
|
|
||||||
*_anchor = anchor;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stivale_load(char *config, char *cmdline) {
|
|
||||||
struct stivale_struct *stivale_struct = ext_mem_alloc(sizeof(struct stivale_struct));
|
|
||||||
|
|
||||||
// BIOS or UEFI?
|
|
||||||
#if bios == 1
|
|
||||||
stivale_struct->flags |= (1 << 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stivale_struct->flags |= (1 << 1); // we give colour information
|
|
||||||
stivale_struct->flags |= (1 << 2); // we give SMBIOS information
|
|
||||||
|
|
||||||
struct file_handle *kernel_file;
|
|
||||||
|
|
||||||
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
|
|
||||||
if (kernel_path == NULL)
|
|
||||||
panic(true, "stivale: KERNEL_PATH not specified");
|
|
||||||
|
|
||||||
if ((kernel_file = uri_open(kernel_path)) == NULL)
|
|
||||||
panic(true, "stivale: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
|
|
||||||
|
|
||||||
char *kaslr_s = config_get_value(config, 0, "KASLR");
|
|
||||||
bool kaslr = true;
|
|
||||||
if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
|
|
||||||
kaslr = false;
|
|
||||||
|
|
||||||
struct stivale_header stivale_hdr;
|
|
||||||
|
|
||||||
bool level5pg = false;
|
|
||||||
uint64_t slide = 0;
|
|
||||||
uint64_t entry_point = 0;
|
|
||||||
|
|
||||||
uint8_t *kernel = freadall(kernel_file, STIVALE_MMAP_BOOTLOADER_RECLAIMABLE);
|
|
||||||
int bits = elf_bits(kernel);
|
|
||||||
bool loaded_by_anchor = false;
|
|
||||||
|
|
||||||
size_t kernel_file_size = kernel_file->size;
|
|
||||||
|
|
||||||
fclose(kernel_file);
|
|
||||||
|
|
||||||
if (bits == -1) {
|
|
||||||
struct stivale_anchor *anchor;
|
|
||||||
if (!stivale_load_by_anchor((void **)&anchor, "STIVALE1 ANCHOR", kernel, kernel_file_size)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bits = anchor->bits;
|
|
||||||
|
|
||||||
memcpy(&stivale_hdr, (void *)(uintptr_t)anchor->phys_stivalehdr,
|
|
||||||
sizeof(struct stivale_header));
|
|
||||||
|
|
||||||
loaded_by_anchor = true;
|
|
||||||
} else {
|
|
||||||
switch (bits) {
|
|
||||||
case 64:
|
|
||||||
if (elf64_load_section(kernel, &stivale_hdr, ".stivalehdr",
|
|
||||||
sizeof(struct stivale_header), slide)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
if (elf32_load_section(kernel, &stivale_hdr, ".stivalehdr",
|
|
||||||
sizeof(struct stivale_header))) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print("stivale: Loading kernel `%s`...\n", kernel_path);
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
switch (bits) {
|
|
||||||
case 64: {
|
|
||||||
// Check if 64 bit CPU
|
|
||||||
uint32_t eax, ebx, ecx, edx;
|
|
||||||
if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
|
|
||||||
panic(true, "stivale: This CPU does not support 64-bit mode.");
|
|
||||||
}
|
|
||||||
// Check if 5-level paging is available
|
|
||||||
if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
|
|
||||||
printv("stivale: CPU has 5-level paging support\n");
|
|
||||||
level5pg = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loaded_by_anchor) {
|
|
||||||
if (elf64_load(kernel, &entry_point, NULL, &slide,
|
|
||||||
STIVALE_MMAP_KERNEL_AND_MODULES, kaslr, false,
|
|
||||||
NULL, NULL, false, NULL, NULL, NULL, NULL))
|
|
||||||
panic(true, "stivale: ELF64 load failure");
|
|
||||||
|
|
||||||
ret = elf64_load_section(kernel, &stivale_hdr, ".stivalehdr",
|
|
||||||
sizeof(struct stivale_header), slide);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 32: {
|
|
||||||
if (!loaded_by_anchor) {
|
|
||||||
if (elf32_load(kernel, (uint32_t *)&entry_point, NULL, STIVALE_MMAP_KERNEL_AND_MODULES))
|
|
||||||
panic(true, "stivale: ELF32 load failure");
|
|
||||||
|
|
||||||
ret = elf32_load_section(kernel, &stivale_hdr, ".stivalehdr",
|
|
||||||
sizeof(struct stivale_header));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(true, "stivale: Not 32 nor 64-bit kernel. What is this?");
|
|
||||||
}
|
|
||||||
|
|
||||||
printv("stivale: %u-bit kernel detected\n", bits);
|
|
||||||
|
|
||||||
switch (ret) {
|
|
||||||
case 1:
|
|
||||||
panic(true, "stivale: File is not a valid ELF.");
|
|
||||||
case 2:
|
|
||||||
panic(true, "stivale: Section .stivalehdr not found.");
|
|
||||||
case 3:
|
|
||||||
panic(true, "stivale: Section .stivalehdr exceeds the size of the struct.");
|
|
||||||
case 4:
|
|
||||||
panic(true, "stivale: Section .stivalehdr is smaller than size of the struct.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((stivale_hdr.flags & (1 << 3)) && bits == 32) {
|
|
||||||
panic(true, "stivale: Higher half addresses header flag not supported in 32-bit mode.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1));
|
|
||||||
|
|
||||||
uint64_t direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000;
|
|
||||||
|
|
||||||
struct gdtr *local_gdt = ext_mem_alloc(sizeof(struct gdtr));
|
|
||||||
local_gdt->limit = gdt.limit;
|
|
||||||
uint64_t local_gdt_base = (uint64_t)gdt.ptr;
|
|
||||||
if (stivale_hdr.flags & (1 << 3)) {
|
|
||||||
local_gdt_base += direct_map_offset;
|
|
||||||
}
|
|
||||||
local_gdt->ptr = local_gdt_base;
|
|
||||||
#if defined (__i386__)
|
|
||||||
local_gdt->ptr_hi = local_gdt_base >> 32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (stivale_hdr.entry_point != 0)
|
|
||||||
entry_point = stivale_hdr.entry_point;
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
print("stivale: Kernel slide: %X\n", slide);
|
|
||||||
|
|
||||||
print("stivale: Entry point at: %X\n", entry_point);
|
|
||||||
print("stivale: Requested stack at: %X\n", stivale_hdr.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The spec says the stack has to be 16-byte aligned
|
|
||||||
if ((stivale_hdr.stack & (16 - 1)) != 0) {
|
|
||||||
print("stivale: WARNING: Requested stack is not 16-byte aligned\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// It also says the stack cannot be NULL for 32-bit kernels
|
|
||||||
if (bits == 32 && stivale_hdr.stack == 0) {
|
|
||||||
panic(true, "stivale: The stack cannot be 0 for 32-bit kernels");
|
|
||||||
}
|
|
||||||
|
|
||||||
stivale_struct->module_count = 0;
|
|
||||||
uint64_t *prev_mod_ptr = &stivale_struct->modules;
|
|
||||||
for (int i = 0; ; i++) {
|
|
||||||
struct conf_tuple conf_tuple =
|
|
||||||
config_get_tuple(config, i, "MODULE_PATH", "MODULE_STRING");
|
|
||||||
|
|
||||||
char *module_path = conf_tuple.value1;
|
|
||||||
char *module_string = conf_tuple.value2;
|
|
||||||
|
|
||||||
if (module_path == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
stivale_struct->module_count++;
|
|
||||||
|
|
||||||
struct stivale_module *m = ext_mem_alloc(sizeof(struct stivale_module));
|
|
||||||
|
|
||||||
// TODO: perhaps change the module string to to be a pointer.
|
|
||||||
//
|
|
||||||
// NOTE: By default, the module string is the file name.
|
|
||||||
if (module_string == NULL) {
|
|
||||||
size_t str_len = strlen(module_path);
|
|
||||||
|
|
||||||
if (str_len > 127)
|
|
||||||
str_len = 127;
|
|
||||||
|
|
||||||
memcpy(m->string, module_path, str_len);
|
|
||||||
} else {
|
|
||||||
// TODO perhaps change this to be a pointer
|
|
||||||
size_t str_len = strlen(module_string);
|
|
||||||
|
|
||||||
if (str_len > 127)
|
|
||||||
str_len = 127;
|
|
||||||
|
|
||||||
memcpy(m->string, module_string, str_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
print("stivale: Loading module `%s`...\n", module_path);
|
|
||||||
|
|
||||||
struct file_handle *f;
|
|
||||||
if ((f = uri_open(module_path)) == NULL)
|
|
||||||
panic(true, "stivale: Failed to open module with path `%s`. Is the path correct?", module_path);
|
|
||||||
|
|
||||||
m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(f, STIVALE_MMAP_KERNEL_AND_MODULES));
|
|
||||||
m->end = m->begin + f->size;
|
|
||||||
m->next = 0;
|
|
||||||
|
|
||||||
*prev_mod_ptr = REPORTED_ADDR((uint64_t)(size_t)m);
|
|
||||||
prev_mod_ptr = &m->next;
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
print("stivale: Requested module %u:\n", i);
|
|
||||||
print(" Path: %s\n", module_path);
|
|
||||||
print(" String: %s\n", m->string);
|
|
||||||
print(" Begin: %X\n", m->begin);
|
|
||||||
print(" End: %X\n", m->end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
|
||||||
|
|
||||||
if (rsdp)
|
|
||||||
stivale_struct->rsdp = REPORTED_ADDR(rsdp);
|
|
||||||
|
|
||||||
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
|
|
||||||
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
|
|
||||||
|
|
||||||
if (smbios_entry_32)
|
|
||||||
stivale_struct->smbios_entry_32 = REPORTED_ADDR(smbios_entry_32);
|
|
||||||
if (smbios_entry_64)
|
|
||||||
stivale_struct->smbios_entry_64 = REPORTED_ADDR(smbios_entry_64);
|
|
||||||
|
|
||||||
stivale_struct->cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
|
|
||||||
|
|
||||||
stivale_struct->epoch = time();
|
|
||||||
printv("stivale: Current epoch: %U\n", stivale_struct->epoch);
|
|
||||||
|
|
||||||
term_deinit();
|
|
||||||
|
|
||||||
if (stivale_hdr.flags & (1 << 0)) {
|
|
||||||
size_t req_width = stivale_hdr.framebuffer_width;
|
|
||||||
size_t req_height = stivale_hdr.framebuffer_height;
|
|
||||||
size_t req_bpp = stivale_hdr.framebuffer_bpp;
|
|
||||||
|
|
||||||
char *resolution = config_get_value(config, 0, "RESOLUTION");
|
|
||||||
if (resolution != NULL)
|
|
||||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
|
||||||
|
|
||||||
struct fb_info fbinfo;
|
|
||||||
#if uefi == 1
|
|
||||||
gop_force_16 = true;
|
|
||||||
#endif
|
|
||||||
if (!fb_init(&fbinfo, req_width, req_height, req_bpp))
|
|
||||||
panic(true, "stivale: Unable to set video mode");
|
|
||||||
|
|
||||||
memmap_alloc_range(fbinfo.framebuffer_addr,
|
|
||||||
(uint64_t)fbinfo.framebuffer_pitch * fbinfo.framebuffer_height,
|
|
||||||
MEMMAP_FRAMEBUFFER, false, false, false, true);
|
|
||||||
|
|
||||||
stivale_struct->framebuffer_addr = REPORTED_ADDR((uint64_t)fbinfo.framebuffer_addr);
|
|
||||||
stivale_struct->framebuffer_width = fbinfo.framebuffer_width;
|
|
||||||
stivale_struct->framebuffer_height = fbinfo.framebuffer_height;
|
|
||||||
stivale_struct->framebuffer_bpp = fbinfo.framebuffer_bpp;
|
|
||||||
stivale_struct->framebuffer_pitch = fbinfo.framebuffer_pitch;
|
|
||||||
stivale_struct->fb_memory_model = STIVALE_FBUF_MMODEL_RGB;
|
|
||||||
stivale_struct->fb_red_mask_size = fbinfo.red_mask_size;
|
|
||||||
stivale_struct->fb_red_mask_shift = fbinfo.red_mask_shift;
|
|
||||||
stivale_struct->fb_green_mask_size = fbinfo.green_mask_size;
|
|
||||||
stivale_struct->fb_green_mask_shift = fbinfo.green_mask_shift;
|
|
||||||
stivale_struct->fb_blue_mask_size = fbinfo.blue_mask_size;
|
|
||||||
stivale_struct->fb_blue_mask_shift = fbinfo.blue_mask_shift;
|
|
||||||
} else {
|
|
||||||
#if uefi == 1
|
|
||||||
panic(true, "stivale: Cannot use text mode with UEFI.");
|
|
||||||
#elif bios == 1
|
|
||||||
size_t rows, cols;
|
|
||||||
init_vga_textmode(&rows, &cols, false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if uefi == 1
|
|
||||||
efi_exit_boot_services();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pagemap_t pagemap = {0};
|
|
||||||
if (bits == 64)
|
|
||||||
pagemap = stivale_build_pagemap(want_5lv, false, NULL, 0, false, 0, 0, direct_map_offset);
|
|
||||||
|
|
||||||
// Reserve 32K at 0x70000 if possible
|
|
||||||
if (!memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, false, false, false)) {
|
|
||||||
if ((stivale_hdr.flags & (1 << 4)) == 0) {
|
|
||||||
panic(false, "stivale: Could not allocate low memory area");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct e820_entry_t *mmap_copy = ext_mem_alloc(256 * sizeof(struct e820_entry_t));
|
|
||||||
|
|
||||||
size_t mmap_entries;
|
|
||||||
struct e820_entry_t *mmap = get_memmap(&mmap_entries);
|
|
||||||
|
|
||||||
if (mmap_entries > 256) {
|
|
||||||
panic(false, "stivale: Too many memory map entries!");
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(mmap_copy, mmap, mmap_entries * sizeof(struct e820_entry_t));
|
|
||||||
|
|
||||||
stivale_struct->memory_map_entries = (uint64_t)mmap_entries;
|
|
||||||
stivale_struct->memory_map_addr = REPORTED_ADDR((uint64_t)(size_t)mmap_copy);
|
|
||||||
|
|
||||||
stivale_spinup(bits, want_5lv, &pagemap,
|
|
||||||
entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)stivale_struct),
|
|
||||||
stivale_hdr.stack, false, false, (uintptr_t)local_gdt);
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
|
|
||||||
fail:
|
|
||||||
pmm_free(kernel, kernel_file_size);
|
|
||||||
pmm_free(stivale_struct, sizeof(struct stivale_struct));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count,
|
|
||||||
bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base,
|
|
||||||
uint64_t direct_map_offset) {
|
|
||||||
pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
|
|
||||||
|
|
||||||
if (ranges_count == 0) {
|
|
||||||
// Map 0 to 2GiB at 0xffffffff80000000
|
|
||||||
for (uint64_t i = 0; i < 0x80000000; i += 0x40000000) {
|
|
||||||
map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, Size1GiB);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i < ranges_count; i++) {
|
|
||||||
uint64_t virt = ranges[i].base;
|
|
||||||
uint64_t phys;
|
|
||||||
|
|
||||||
if (virt & ((uint64_t)1 << 63)) {
|
|
||||||
if (want_fully_virtual) {
|
|
||||||
phys = physical_base + (virt - virtual_base);
|
|
||||||
} else {
|
|
||||||
phys = virt - FIXED_HIGHER_HALF_OFFSET_64;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic(false, "stivale2: Protected memory ranges are only supported for higher half kernels");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t pf = VMM_FLAG_PRESENT |
|
|
||||||
(ranges[i].permissions & ELF_PF_X ? 0 : VMM_FLAG_NOEXEC) |
|
|
||||||
(ranges[i].permissions & ELF_PF_W ? VMM_FLAG_WRITE : 0);
|
|
||||||
|
|
||||||
for (uint64_t j = 0; j < ranges[i].length; j += 0x1000) {
|
|
||||||
map_page(pagemap, virt + j, phys + j, pf, Size4KiB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sub 2MiB mappings
|
|
||||||
for (uint64_t i = 0; i < 0x200000; i += 0x1000) {
|
|
||||||
if (!(i == 0 && unmap_null))
|
|
||||||
map_page(pagemap, i, i, 0x03, Size4KiB);
|
|
||||||
map_page(pagemap, direct_map_offset + i, i, 0x03, Size4KiB);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map 2MiB to 4GiB at higher half base and 0
|
|
||||||
//
|
|
||||||
// NOTE: We cannot just directly map from 2MiB to 4GiB with 1GiB
|
|
||||||
// pages because if you do the math.
|
|
||||||
//
|
|
||||||
// start = 0x200000
|
|
||||||
// end = 0x40000000
|
|
||||||
//
|
|
||||||
// pages_required = (end - start) / (4096 * 512 * 512)
|
|
||||||
//
|
|
||||||
// So we map 2MiB to 1GiB with 2MiB pages and then map the rest
|
|
||||||
// with 1GiB pages :^)
|
|
||||||
for (uint64_t i = 0x200000; i < 0x40000000; i += 0x200000) {
|
|
||||||
map_page(pagemap, i, i, 0x03, Size2MiB);
|
|
||||||
map_page(pagemap, direct_map_offset + i, i, 0x03, Size2MiB);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint64_t i = 0x40000000; i < 0x100000000; i += 0x40000000) {
|
|
||||||
map_page(pagemap, i, i, 0x03, Size1GiB);
|
|
||||||
map_page(pagemap, direct_map_offset + i, i, 0x03, Size1GiB);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t _memmap_entries = memmap_entries;
|
|
||||||
struct e820_entry_t *_memmap =
|
|
||||||
ext_mem_alloc(_memmap_entries * sizeof(struct e820_entry_t));
|
|
||||||
for (size_t i = 0; i < _memmap_entries; i++)
|
|
||||||
_memmap[i] = memmap[i];
|
|
||||||
|
|
||||||
// Map any other region of memory from the memmap
|
|
||||||
for (size_t i = 0; i < _memmap_entries; i++) {
|
|
||||||
uint64_t base = _memmap[i].base;
|
|
||||||
uint64_t length = _memmap[i].length;
|
|
||||||
uint64_t top = base + length;
|
|
||||||
|
|
||||||
if (base < 0x100000000)
|
|
||||||
base = 0x100000000;
|
|
||||||
|
|
||||||
if (base >= top)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint64_t aligned_base = ALIGN_DOWN(base, 0x40000000);
|
|
||||||
uint64_t aligned_top = ALIGN_UP(top, 0x40000000);
|
|
||||||
uint64_t aligned_length = aligned_top - aligned_base;
|
|
||||||
|
|
||||||
for (uint64_t j = 0; j < aligned_length; j += 0x40000000) {
|
|
||||||
uint64_t page = aligned_base + j;
|
|
||||||
map_page(pagemap, page, page, 0x03, Size1GiB);
|
|
||||||
map_page(pagemap, direct_map_offset + page, page, 0x03, Size1GiB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pagemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if uefi == 1
|
|
||||||
extern symbol ImageBase;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
noreturn void stivale_spinup_32(
|
|
||||||
int bits, bool level5pg, uint32_t pagemap_top_lv,
|
|
||||||
uint32_t entry_point_lo, uint32_t entry_point_hi,
|
|
||||||
uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
|
|
||||||
uint32_t stack_lo, uint32_t stack_hi, uint32_t local_gdt);
|
|
||||||
|
|
||||||
noreturn void stivale_spinup(
|
|
||||||
int bits, bool level5pg, pagemap_t *pagemap,
|
|
||||||
uint64_t entry_point, uint64_t _stivale_struct, uint64_t stack,
|
|
||||||
bool enable_nx, bool wp, uint32_t local_gdt) {
|
|
||||||
#if bios == 1
|
|
||||||
if (bits == 64) {
|
|
||||||
// If we're going 64, we might as well call this BIOS interrupt
|
|
||||||
// to tell the BIOS that we are entering Long Mode, since it is in
|
|
||||||
// the specification.
|
|
||||||
struct rm_regs r = {0};
|
|
||||||
r.eax = 0xec00;
|
|
||||||
r.ebx = 0x02; // Long mode only
|
|
||||||
rm_int(0x15, &r, &r);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (enable_nx) {
|
|
||||||
vmm_assert_nx();
|
|
||||||
}
|
|
||||||
|
|
||||||
pic_mask_all();
|
|
||||||
io_apic_mask_all();
|
|
||||||
|
|
||||||
irq_flush_type = IRQ_PIC_APIC_FLUSH;
|
|
||||||
|
|
||||||
common_spinup(stivale_spinup_32, 12,
|
|
||||||
bits, level5pg, enable_nx, wp, (uint32_t)(uintptr_t)pagemap->top_level,
|
|
||||||
(uint32_t)entry_point, (uint32_t)(entry_point >> 32),
|
|
||||||
(uint32_t)_stivale_struct, (uint32_t)(_stivale_struct >> 32),
|
|
||||||
(uint32_t)stack, (uint32_t)(stack >> 32), local_gdt);
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef __PROTOS__STIVALE_H__
|
|
||||||
#define __PROTOS__STIVALE_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdnoreturn.h>
|
|
||||||
#include <mm/vmm.h>
|
|
||||||
#include <lib/elf.h>
|
|
||||||
|
|
||||||
bool stivale_load(char *config, char *cmdline);
|
|
||||||
|
|
||||||
bool stivale_load_by_anchor(void **_anchor, const char *magic,
|
|
||||||
uint8_t *file, uint64_t filesize);
|
|
||||||
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count,
|
|
||||||
bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base,
|
|
||||||
uint64_t direct_map_offset);
|
|
||||||
noreturn void stivale_spinup(
|
|
||||||
int bits, bool level5pg, pagemap_t *pagemap,
|
|
||||||
uint64_t entry_point, uint64_t stivale_struct, uint64_t stack,
|
|
||||||
bool enable_nx, bool wp, uint32_t local_gdt);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,856 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <protos/stivale.h>
|
|
||||||
#include <protos/stivale2.h>
|
|
||||||
#include <lib/elf.h>
|
|
||||||
#include <lib/blib.h>
|
|
||||||
#include <lib/acpi.h>
|
|
||||||
#include <lib/config.h>
|
|
||||||
#include <lib/time.h>
|
|
||||||
#include <lib/print.h>
|
|
||||||
#include <lib/real.h>
|
|
||||||
#include <lib/libc.h>
|
|
||||||
#include <lib/gterm.h>
|
|
||||||
#include <lib/uri.h>
|
|
||||||
#include <sys/smp.h>
|
|
||||||
#include <sys/cpu.h>
|
|
||||||
#include <sys/gdt.h>
|
|
||||||
#include <lib/fb.h>
|
|
||||||
#include <lib/term.h>
|
|
||||||
#include <sys/pic.h>
|
|
||||||
#include <sys/lapic.h>
|
|
||||||
#include <fs/file.h>
|
|
||||||
#include <mm/pmm.h>
|
|
||||||
#include <stivale2.h>
|
|
||||||
#include <pxe/tftp.h>
|
|
||||||
#include <drivers/edid.h>
|
|
||||||
#include <drivers/vga_textmode.h>
|
|
||||||
#include <drivers/gop.h>
|
|
||||||
#include <lib/rand.h>
|
|
||||||
|
|
||||||
#define REPORTED_ADDR(PTR) \
|
|
||||||
((PTR) + ((stivale2_hdr.flags & (1 << 1)) ? \
|
|
||||||
direct_map_offset : 0))
|
|
||||||
|
|
||||||
#define get_phys_addr(addr) ({ \
|
|
||||||
uintptr_t r1; \
|
|
||||||
if ((addr) & ((uint64_t)1 << 63)) { \
|
|
||||||
if (want_fully_virtual) { \
|
|
||||||
r1 = physical_base + ((addr) - virtual_base); \
|
|
||||||
} else { \
|
|
||||||
r1 = (addr) - FIXED_HIGHER_HALF_OFFSET_64; \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
r1 = addr; \
|
|
||||||
} \
|
|
||||||
r1; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define get_tag(s, id) ({ \
|
|
||||||
void *r; \
|
|
||||||
struct stivale2_tag *tag = (void *)get_phys_addr((s)->tags); \
|
|
||||||
for (;;) { \
|
|
||||||
if (tag == NULL) { \
|
|
||||||
r = NULL; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
if (tag->identifier == (id)) { \
|
|
||||||
r = tag; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
tag = (void *)get_phys_addr(tag->next); \
|
|
||||||
} \
|
|
||||||
r; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define append_tag(S, TAG) ({ \
|
|
||||||
(TAG)->next = (S)->tags; \
|
|
||||||
(S)->tags = REPORTED_ADDR((uint64_t)(uintptr_t)TAG); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#if defined (__i386__)
|
|
||||||
extern symbol stivale2_term_write_entry;
|
|
||||||
void *stivale2_rt_stack = NULL;
|
|
||||||
uint64_t stivale2_term_callback_ptr = 0;
|
|
||||||
uint64_t stivale2_term_write_ptr = 0;
|
|
||||||
void stivale2_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool stivale2_load(char *config, char *cmdline) {
|
|
||||||
struct stivale2_struct *stivale2_struct = ext_mem_alloc(sizeof(struct stivale2_struct));
|
|
||||||
|
|
||||||
struct file_handle *kernel_file;
|
|
||||||
|
|
||||||
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
|
|
||||||
if (kernel_path == NULL)
|
|
||||||
panic(true, "stivale2: KERNEL_PATH not specified");
|
|
||||||
|
|
||||||
if ((kernel_file = uri_open(kernel_path)) == NULL)
|
|
||||||
panic(true, "stivale2: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
|
|
||||||
|
|
||||||
char *kaslr_s = config_get_value(config, 0, "KASLR");
|
|
||||||
bool kaslr = true;
|
|
||||||
if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
|
|
||||||
kaslr = false;
|
|
||||||
|
|
||||||
struct stivale2_header stivale2_hdr;
|
|
||||||
|
|
||||||
bool level5pg = false;
|
|
||||||
uint64_t slide = 0;
|
|
||||||
uint64_t entry_point = 0;
|
|
||||||
|
|
||||||
struct elf_range *ranges;
|
|
||||||
uint64_t ranges_count;
|
|
||||||
|
|
||||||
uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
|
|
||||||
int bits = elf_bits(kernel);
|
|
||||||
bool loaded_by_anchor = false;
|
|
||||||
|
|
||||||
size_t kernel_file_size = kernel_file->size;
|
|
||||||
|
|
||||||
struct volume *kernel_volume = kernel_file->vol;
|
|
||||||
|
|
||||||
fclose(kernel_file);
|
|
||||||
|
|
||||||
if (bits == -1) {
|
|
||||||
struct stivale2_anchor *anchor;
|
|
||||||
if (!stivale_load_by_anchor((void **)&anchor, "STIVALE2 ANCHOR", kernel, kernel_file_size)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bits = anchor->bits;
|
|
||||||
|
|
||||||
memcpy(&stivale2_hdr, (void *)(uintptr_t)anchor->phys_stivale2hdr,
|
|
||||||
sizeof(struct stivale2_header));
|
|
||||||
|
|
||||||
loaded_by_anchor = true;
|
|
||||||
} else {
|
|
||||||
switch (bits) {
|
|
||||||
case 64:
|
|
||||||
if (elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
||||||
sizeof(struct stivale2_header), slide)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
if (elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
||||||
sizeof(struct stivale2_header))) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print("stivale2: Loading kernel `%s`...\n", kernel_path);
|
|
||||||
|
|
||||||
bool want_pmrs = false;
|
|
||||||
bool want_fully_virtual = false;
|
|
||||||
|
|
||||||
uint64_t physical_base, virtual_base;
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
switch (bits) {
|
|
||||||
case 64: {
|
|
||||||
// Check if 64 bit CPU
|
|
||||||
uint32_t eax, ebx, ecx, edx;
|
|
||||||
if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
|
|
||||||
panic(true, "stivale2: This CPU does not support 64-bit mode.");
|
|
||||||
}
|
|
||||||
// Check if 5-level paging is available
|
|
||||||
if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
|
|
||||||
printv("stivale2: CPU has 5-level paging support\n");
|
|
||||||
level5pg = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loaded_by_anchor && (stivale2_hdr.flags & (1 << 2))) {
|
|
||||||
panic(true, "stivale2: PMRs are not supported for anchored kernels");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loaded_by_anchor) {
|
|
||||||
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
||||||
sizeof(struct stivale2_header), 0);
|
|
||||||
if (ret) {
|
|
||||||
goto failed_to_load_header_section;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((stivale2_hdr.flags & (1 << 2))) {
|
|
||||||
if (bits == 32) {
|
|
||||||
panic(true, "stivale2: PMRs are not supported for 32-bit kernels");
|
|
||||||
}
|
|
||||||
want_pmrs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (want_pmrs && (stivale2_hdr.flags & (1 << 3))) {
|
|
||||||
want_fully_virtual = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elf64_load(kernel, &entry_point, NULL, &slide,
|
|
||||||
STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr, false,
|
|
||||||
want_pmrs ? &ranges : NULL,
|
|
||||||
want_pmrs ? &ranges_count : NULL,
|
|
||||||
want_fully_virtual, &physical_base, &virtual_base,
|
|
||||||
NULL, NULL))
|
|
||||||
panic(true, "stivale2: ELF64 load failure");
|
|
||||||
|
|
||||||
if (want_fully_virtual) {
|
|
||||||
printv("stivale2: Physical base: %X\n", physical_base);
|
|
||||||
printv("stivale2: Virtual base: %X\n", virtual_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
||||||
sizeof(struct stivale2_header), slide);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 32: {
|
|
||||||
if (!loaded_by_anchor) {
|
|
||||||
if (elf32_load(kernel, (uint32_t *)&entry_point, NULL, STIVALE2_MMAP_KERNEL_AND_MODULES))
|
|
||||||
panic(true, "stivale2: ELF32 load failure");
|
|
||||||
|
|
||||||
ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
||||||
sizeof(struct stivale2_header));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(true, "stivale2: Not 32 nor 64-bit kernel. What is this?");
|
|
||||||
}
|
|
||||||
|
|
||||||
printv("stivale2: %u-bit kernel detected\n", bits);
|
|
||||||
|
|
||||||
failed_to_load_header_section:
|
|
||||||
switch (ret) {
|
|
||||||
case 1:
|
|
||||||
panic(true, "stivale2: File is not a valid ELF.");
|
|
||||||
case 2:
|
|
||||||
panic(true, "stivale2: Section .stivale2hdr not found.");
|
|
||||||
case 3:
|
|
||||||
panic(true, "stivale2: Section .stivale2hdr exceeds the size of the struct.");
|
|
||||||
case 4:
|
|
||||||
panic(true, "stivale2: Section .stivale2hdr is smaller than size of the struct.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((stivale2_hdr.flags & (1 << 1)) && bits == 32) {
|
|
||||||
panic(true, "stivale2: Higher half addresses header flag not supported in 32-bit mode.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool want_5lv = (get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_5LV_PAGING_ID) ? true : false) && level5pg;
|
|
||||||
|
|
||||||
uint64_t direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000;
|
|
||||||
|
|
||||||
{
|
|
||||||
struct stivale2_header_tag_slide_hhdm *slt = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_SLIDE_HHDM_ID);
|
|
||||||
if (slt != NULL) {
|
|
||||||
if (slt->alignment % 0x200000 != 0 || slt->alignment == 0) {
|
|
||||||
panic(true, "stivale2: Requested HHDM slide alignment is not a multiple of 2MiB");
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: Assert that slt->alignment is not larger than 1GiB and ignore the value altogether.
|
|
||||||
// This is required for 1GiB pages.
|
|
||||||
if (((uint64_t)0x40000000 % slt->alignment) != 0) {
|
|
||||||
panic(true, "stivale2: 1 GiB is not a multiple of HHDM slide alignment");
|
|
||||||
}
|
|
||||||
|
|
||||||
direct_map_offset += (rand64() & ~((uint64_t)0x40000000 - 1)) & 0xfffffffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct gdtr *local_gdt = ext_mem_alloc(sizeof(struct gdtr));
|
|
||||||
local_gdt->limit = gdt.limit;
|
|
||||||
uint64_t local_gdt_base = (uint64_t)gdt.ptr;
|
|
||||||
if (stivale2_hdr.flags & (1 << 1)) {
|
|
||||||
local_gdt_base += direct_map_offset;
|
|
||||||
}
|
|
||||||
local_gdt->ptr = local_gdt_base;
|
|
||||||
#if defined (__i386__)
|
|
||||||
local_gdt->ptr_hi = local_gdt_base >> 32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (stivale2_hdr.entry_point != 0)
|
|
||||||
entry_point = stivale2_hdr.entry_point;
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
print("stivale2: Kernel slide: %X\n", slide);
|
|
||||||
|
|
||||||
print("stivale2: Entry point at: %X\n", entry_point);
|
|
||||||
print("stivale2: Requested stack at: %X\n", stivale2_hdr.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The spec says the stack has to be 16-byte aligned
|
|
||||||
if ((stivale2_hdr.stack & (16 - 1)) != 0) {
|
|
||||||
print("stivale2: WARNING: Requested stack is not 16-byte aligned\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// It also says the stack cannot be NULL for 32-bit kernels
|
|
||||||
if (bits == 32 && stivale2_hdr.stack == 0) {
|
|
||||||
panic(true, "stivale2: The stack cannot be 0 for 32-bit kernels");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(stivale2_struct->bootloader_brand, "Limine");
|
|
||||||
strcpy(stivale2_struct->bootloader_version, LIMINE_VERSION);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create boot volume tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_boot_volume *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_boot_volume));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_BOOT_VOLUME_ID;
|
|
||||||
|
|
||||||
if (kernel_volume->guid_valid) {
|
|
||||||
tag->flags |= (1 << 0);
|
|
||||||
memcpy(&tag->guid, &kernel_volume->guid, sizeof(struct stivale2_guid));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kernel_volume->part_guid_valid) {
|
|
||||||
tag->flags |= (1 << 1);
|
|
||||||
memcpy(&tag->part_guid, &kernel_volume->part_guid, sizeof(struct stivale2_guid));
|
|
||||||
}
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create kernel file struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_kernel_file *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_file));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_FILE_ID;
|
|
||||||
|
|
||||||
tag->kernel_file = REPORTED_ADDR((uint64_t)(uintptr_t)kernel);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create kernel file v2 struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_kernel_file_v2 *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_file_v2));
|
|
||||||
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_FILE_V2_ID;
|
|
||||||
tag->kernel_file = REPORTED_ADDR((uint64_t)(uintptr_t)kernel);
|
|
||||||
tag->kernel_size = kernel_file_size;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create kernel slide struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_kernel_slide *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_slide));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_SLIDE_ID;
|
|
||||||
|
|
||||||
tag->kernel_slide = slide;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create firmware struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_firmware *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_firmware));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_FIRMWARE_ID;
|
|
||||||
|
|
||||||
#if bios == 1
|
|
||||||
tag->flags = 1 << 0; // bit 0 = BIOS boot
|
|
||||||
#endif
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create modules struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
size_t module_count;
|
|
||||||
for (module_count = 0; ; module_count++) {
|
|
||||||
char *module_file = config_get_value(config, module_count, "MODULE_PATH");
|
|
||||||
if (module_file == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stivale2_struct_tag_modules *tag =
|
|
||||||
ext_mem_alloc(sizeof(struct stivale2_struct_tag_modules)
|
|
||||||
+ sizeof(struct stivale2_module) * module_count);
|
|
||||||
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_MODULES_ID;
|
|
||||||
tag->module_count = module_count;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < module_count; i++) {
|
|
||||||
struct conf_tuple conf_tuple =
|
|
||||||
config_get_tuple(config, i, "MODULE_PATH", "MODULE_STRING");
|
|
||||||
|
|
||||||
char *module_path = conf_tuple.value1;
|
|
||||||
char *module_string = conf_tuple.value2;
|
|
||||||
|
|
||||||
struct stivale2_module *m = &tag->modules[i];
|
|
||||||
|
|
||||||
// TODO: perhaps change the module string to to be a pointer.
|
|
||||||
//
|
|
||||||
// NOTE: By default, the module string is the file name.
|
|
||||||
if (module_string == NULL) {
|
|
||||||
size_t str_len = strlen(module_path);
|
|
||||||
|
|
||||||
if (str_len > 127)
|
|
||||||
str_len = 127;
|
|
||||||
|
|
||||||
memcpy(m->string, module_path, str_len);
|
|
||||||
} else {
|
|
||||||
size_t str_len = strlen(module_string);
|
|
||||||
|
|
||||||
if (str_len > 127)
|
|
||||||
str_len = 127;
|
|
||||||
|
|
||||||
memcpy(m->string, module_string, str_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
print("stivale2: Loading module `%s`...\n", module_path);
|
|
||||||
|
|
||||||
struct file_handle *f;
|
|
||||||
if ((f = uri_open(module_path)) == NULL)
|
|
||||||
panic(true, "stivale2: Failed to open module with path `%s`. Is the path correct?", module_path);
|
|
||||||
|
|
||||||
m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(f, STIVALE2_MMAP_KERNEL_AND_MODULES));
|
|
||||||
m->end = m->begin + f->size;
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
print("stivale2: Requested module %u:\n", i);
|
|
||||||
print(" Path: %s\n", module_path);
|
|
||||||
print(" String: %s\n", m->string);
|
|
||||||
print(" Begin: %X\n", m->begin);
|
|
||||||
print(" End: %X\n", m->end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create RSDP struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_rsdp *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_rsdp));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_RSDP_ID;
|
|
||||||
|
|
||||||
uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
|
||||||
if (rsdp)
|
|
||||||
tag->rsdp = REPORTED_ADDR(rsdp);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create SMBIOS struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_smbios *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_smbios));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_SMBIOS_ID;
|
|
||||||
|
|
||||||
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
|
|
||||||
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
|
|
||||||
|
|
||||||
if (smbios_entry_32)
|
|
||||||
tag->smbios_entry_32 = REPORTED_ADDR(smbios_entry_32);
|
|
||||||
if (smbios_entry_64)
|
|
||||||
tag->smbios_entry_64 = REPORTED_ADDR(smbios_entry_64);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create cmdline struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_cmdline *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_cmdline));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_CMDLINE_ID;
|
|
||||||
|
|
||||||
tag->cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create epoch struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_epoch *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_epoch));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_EPOCH_ID;
|
|
||||||
|
|
||||||
tag->epoch = time();
|
|
||||||
printv("stivale2: Current epoch: %U\n", tag->epoch);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create framebuffer struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
|
|
||||||
struct fb_info *fb = NULL;
|
|
||||||
struct fb_info _fb;
|
|
||||||
|
|
||||||
struct stivale2_header_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FRAMEBUFFER_ID);
|
|
||||||
|
|
||||||
size_t req_width = 0, req_height = 0, req_bpp = 0;
|
|
||||||
|
|
||||||
if (hdrtag != NULL) {
|
|
||||||
req_width = hdrtag->framebuffer_width;
|
|
||||||
req_height = hdrtag->framebuffer_height;
|
|
||||||
req_bpp = hdrtag->framebuffer_bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *resolution = config_get_value(config, 0, "RESOLUTION");
|
|
||||||
if (resolution != NULL)
|
|
||||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
|
||||||
|
|
||||||
struct stivale2_header_tag_any_video *avtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_ANY_VIDEO_ID);
|
|
||||||
|
|
||||||
#if uefi == 1
|
|
||||||
if (hdrtag == NULL && avtag == NULL) {
|
|
||||||
panic(true, "stivale2: Cannot use text mode with UEFI.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *textmode_str = config_get_value(config, 0, "TEXTMODE");
|
|
||||||
bool textmode = textmode_str != NULL && strcmp(textmode_str, "yes") == 0;
|
|
||||||
|
|
||||||
int preference = 0;
|
|
||||||
if (avtag != NULL) {
|
|
||||||
preference = textmode ? 1 : avtag->preference;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stivale2_header_tag_terminal *terminal_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_TERMINAL_ID);
|
|
||||||
|
|
||||||
if (bits == 64 && terminal_hdr_tag != NULL) {
|
|
||||||
quiet = false;
|
|
||||||
serial = false;
|
|
||||||
|
|
||||||
if (bios &&
|
|
||||||
((avtag == NULL && hdrtag == NULL) || (avtag != NULL && preference == 1))) {
|
|
||||||
term_textmode();
|
|
||||||
textmode = true;
|
|
||||||
} else {
|
|
||||||
#if uefi == 1
|
|
||||||
gop_force_16 = true;
|
|
||||||
#endif
|
|
||||||
term_vbe(req_width, req_height);
|
|
||||||
|
|
||||||
if (current_video_mode < 0) {
|
|
||||||
panic(true, "stivale2: Failed to initialise terminal");
|
|
||||||
}
|
|
||||||
|
|
||||||
fb = &fbinfo;
|
|
||||||
|
|
||||||
textmode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stivale2_struct_tag_terminal *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_terminal));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_TERMINAL_ID;
|
|
||||||
|
|
||||||
if (terminal_hdr_tag->flags & (1 << 0)) {
|
|
||||||
// We provide callback
|
|
||||||
tag->flags |= (1 << 2);
|
|
||||||
if (terminal_hdr_tag->callback != 0) {
|
|
||||||
#if defined (__i386__)
|
|
||||||
term_callback = stivale2_term_callback;
|
|
||||||
stivale2_term_callback_ptr = terminal_hdr_tag->callback;
|
|
||||||
#elif defined (__x86_64__)
|
|
||||||
term_callback = (void *)terminal_hdr_tag->callback;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We provide max allowed string length
|
|
||||||
tag->flags |= (1 << 1);
|
|
||||||
tag->max_length = 0;
|
|
||||||
|
|
||||||
// We provide context control
|
|
||||||
tag->flags |= (1 << 3);
|
|
||||||
|
|
||||||
#if defined (__i386__)
|
|
||||||
if (stivale2_rt_stack == NULL) {
|
|
||||||
stivale2_rt_stack = ext_mem_alloc(8192) + 8192;
|
|
||||||
}
|
|
||||||
|
|
||||||
stivale2_term_write_ptr = (uintptr_t)term_write;
|
|
||||||
tag->term_write = (uintptr_t)(void *)stivale2_term_write_entry;
|
|
||||||
#elif defined (__x86_64__)
|
|
||||||
tag->term_write = (uintptr_t)term_write;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// We provide rows and cols
|
|
||||||
tag->flags |= (1 << 0);
|
|
||||||
tag->cols = term_cols;
|
|
||||||
tag->rows = term_rows;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
|
|
||||||
if (textmode) {
|
|
||||||
#if bios == 1
|
|
||||||
goto have_tm_tag;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
goto have_fb_tag;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fb = &_fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
term_deinit();
|
|
||||||
|
|
||||||
if (hdrtag != NULL || (avtag != NULL && uefi) || (avtag != NULL && preference == 0)) {
|
|
||||||
term_deinit();
|
|
||||||
|
|
||||||
#if uefi == 1
|
|
||||||
gop_force_16 = true;
|
|
||||||
#endif
|
|
||||||
if (fb_init(fb, req_width, req_height, req_bpp)) {
|
|
||||||
have_fb_tag:;
|
|
||||||
struct stivale2_struct_tag_framebuffer *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_framebuffer));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID;
|
|
||||||
|
|
||||||
memmap_alloc_range(fb->framebuffer_addr,
|
|
||||||
(uint64_t)fb->framebuffer_pitch * fb->framebuffer_height,
|
|
||||||
MEMMAP_FRAMEBUFFER, false, false, false, true);
|
|
||||||
|
|
||||||
tag->memory_model = STIVALE2_FBUF_MMODEL_RGB;
|
|
||||||
tag->framebuffer_addr = REPORTED_ADDR(fb->framebuffer_addr);
|
|
||||||
tag->framebuffer_width = fb->framebuffer_width;
|
|
||||||
tag->framebuffer_height = fb->framebuffer_height;
|
|
||||||
tag->framebuffer_bpp = fb->framebuffer_bpp;
|
|
||||||
tag->framebuffer_pitch = fb->framebuffer_pitch;
|
|
||||||
tag->red_mask_size = fb->red_mask_size;
|
|
||||||
tag->red_mask_shift = fb->red_mask_shift;
|
|
||||||
tag->green_mask_size = fb->green_mask_size;
|
|
||||||
tag->green_mask_shift = fb->green_mask_shift;
|
|
||||||
tag->blue_mask_size = fb->blue_mask_size;
|
|
||||||
tag->blue_mask_shift = fb->blue_mask_shift;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#if bios == 1
|
|
||||||
size_t rows, cols;
|
|
||||||
init_vga_textmode(&rows, &cols, false);
|
|
||||||
|
|
||||||
have_tm_tag:;
|
|
||||||
struct stivale2_struct_tag_textmode *tmtag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_textmode));
|
|
||||||
tmtag->tag.identifier = STIVALE2_STRUCT_TAG_TEXTMODE_ID;
|
|
||||||
|
|
||||||
tmtag->address = 0xb8000;
|
|
||||||
tmtag->rows = 25;
|
|
||||||
tmtag->cols = 80;
|
|
||||||
tmtag->bytes_per_char = 2;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tmtag);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create EDID struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct edid_info_struct *edid_info = get_edid_info();
|
|
||||||
|
|
||||||
if (edid_info != NULL) {
|
|
||||||
struct stivale2_struct_tag_edid *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_edid) + sizeof(struct edid_info_struct));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_EDID_ID;
|
|
||||||
|
|
||||||
tag->edid_size = sizeof(struct edid_info_struct);
|
|
||||||
|
|
||||||
memcpy(tag->edid_information, edid_info, sizeof(struct edid_info_struct));
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create HHDM struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_hhdm *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_hhdm));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_HHDM_ID;
|
|
||||||
|
|
||||||
tag->addr = direct_map_offset;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if bios == 1
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create PXE struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
if (boot_volume->pxe) {
|
|
||||||
struct stivale2_struct_tag_pxe_server_info *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_pxe_server_info));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_PXE_SERVER_INFO;
|
|
||||||
tag->server_ip = get_boot_server_info();
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create PMRs struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
if (want_pmrs) {
|
|
||||||
struct stivale2_struct_tag_pmrs *tag =
|
|
||||||
ext_mem_alloc(sizeof(struct stivale2_struct_tag_pmrs)
|
|
||||||
+ ranges_count * sizeof(struct stivale2_pmr));
|
|
||||||
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_PMRS_ID;
|
|
||||||
|
|
||||||
tag->entries = ranges_count;
|
|
||||||
|
|
||||||
memcpy(tag->pmrs, ranges, ranges_count * sizeof(struct stivale2_pmr));
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create PMRs struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
if (want_fully_virtual) {
|
|
||||||
struct stivale2_struct_tag_kernel_base_address *tag =
|
|
||||||
ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_base_address));
|
|
||||||
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_BASE_ADDRESS_ID;
|
|
||||||
|
|
||||||
tag->physical_base_address = physical_base;
|
|
||||||
tag->virtual_base_address = virtual_base;
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create EFI system table struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
#if uefi == 1
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_efi_system_table *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_efi_system_table));
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID;
|
|
||||||
|
|
||||||
tag->system_table = REPORTED_ADDR((uint64_t)(uintptr_t)gST);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool unmap_null = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_UNMAP_NULL_ID) ? true : false;
|
|
||||||
|
|
||||||
pagemap_t pagemap = {0};
|
|
||||||
if (bits == 64)
|
|
||||||
pagemap = stivale_build_pagemap(want_5lv, unmap_null,
|
|
||||||
want_pmrs ? ranges : NULL,
|
|
||||||
want_pmrs ? ranges_count : 0,
|
|
||||||
want_fully_virtual, physical_base, virtual_base,
|
|
||||||
direct_map_offset);
|
|
||||||
|
|
||||||
#if uefi == 1
|
|
||||||
efi_exit_boot_services();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create SMP struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_header_tag_smp *smp_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_SMP_ID);
|
|
||||||
if (smp_hdr_tag != NULL) {
|
|
||||||
struct stivale2_struct_tag_smp *tag;
|
|
||||||
struct smp_information *smp_info;
|
|
||||||
size_t cpu_count;
|
|
||||||
uint32_t bsp_lapic_id;
|
|
||||||
smp_info = init_smp(sizeof(struct stivale2_struct_tag_smp), (void **)&tag,
|
|
||||||
&cpu_count, &bsp_lapic_id,
|
|
||||||
bits == 64, want_5lv,
|
|
||||||
pagemap, smp_hdr_tag->flags & 1, want_pmrs,
|
|
||||||
stivale2_hdr.flags & (1 << 1) ? direct_map_offset : 0,
|
|
||||||
want_pmrs);
|
|
||||||
|
|
||||||
if (smp_info != NULL) {
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
|
|
||||||
tag->bsp_lapic_id = bsp_lapic_id;
|
|
||||||
tag->cpu_count = cpu_count;
|
|
||||||
tag->flags |= (smp_hdr_tag->flags & 1) && x2apic_check();
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Create memmap struct tag
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
{
|
|
||||||
struct stivale2_struct_tag_memmap *tag =
|
|
||||||
ext_mem_alloc(sizeof(struct stivale2_struct_tag_memmap) +
|
|
||||||
sizeof(struct e820_entry_t) * 256);
|
|
||||||
|
|
||||||
// Reserve 32K at 0x70000, if possible
|
|
||||||
if (!memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, false, false, false)) {
|
|
||||||
if ((stivale2_hdr.flags & (1 << 4)) == 0) {
|
|
||||||
panic(false, "stivale2: Could not allocate low memory area");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t mmap_entries;
|
|
||||||
struct e820_entry_t *mmap = get_memmap(&mmap_entries);
|
|
||||||
|
|
||||||
if (mmap_entries > 256) {
|
|
||||||
panic(false, "stivale2: Too many memory map entries!");
|
|
||||||
}
|
|
||||||
|
|
||||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_MEMMAP_ID;
|
|
||||||
tag->entries = (uint64_t)mmap_entries;
|
|
||||||
|
|
||||||
memcpy((void*)tag + sizeof(struct stivale2_struct_tag_memmap),
|
|
||||||
mmap, sizeof(struct e820_entry_t) * mmap_entries);
|
|
||||||
|
|
||||||
append_tag(stivale2_struct, (struct stivale2_tag *)tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// List tags
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
if (verbose) {
|
|
||||||
print("stivale2: Generated tags:\n");
|
|
||||||
struct stivale2_tag *taglist =
|
|
||||||
(void*)(uintptr_t)(stivale2_struct->tags - ((stivale2_hdr.flags & (1 << 1)) ? direct_map_offset : 0));
|
|
||||||
for (size_t i = 0; ; i++) {
|
|
||||||
print(" Tag #%u ID: %X\n", i, taglist->identifier);
|
|
||||||
if (taglist->next) {
|
|
||||||
taglist = (void*)(uintptr_t)(taglist->next - ((stivale2_hdr.flags & (1 << 1)) ? direct_map_offset : 0));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear terminal for kernels that will use the stivale2 terminal
|
|
||||||
term_write((uint64_t)(uintptr_t)("\e[2J\e[H"), 7);
|
|
||||||
|
|
||||||
term_runtime = true;
|
|
||||||
|
|
||||||
stivale_spinup(bits, want_5lv, &pagemap, entry_point,
|
|
||||||
REPORTED_ADDR((uint64_t)(uintptr_t)stivale2_struct),
|
|
||||||
stivale2_hdr.stack, want_pmrs, want_pmrs, (uintptr_t)local_gdt);
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
|
|
||||||
fail:
|
|
||||||
pmm_free(kernel, kernel_file_size);
|
|
||||||
pmm_free(stivale2_struct, sizeof(struct stivale2_struct));
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#ifndef __PROTOS__STIVALE2_H__
|
|
||||||
#define __PROTOS__STIVALE2_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
bool stivale2_load(char *config, char *cmdline);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -29,7 +29,6 @@ INTERNAL_LD_FLAGS_MULTIBOOT1 := \
|
||||||
--no-dynamic-linker \
|
--no-dynamic-linker \
|
||||||
|
|
||||||
INTERNALCFLAGS := \
|
INTERNALCFLAGS := \
|
||||||
-I../stivale \
|
|
||||||
-I. \
|
-I. \
|
||||||
-I.. \
|
-I.. \
|
||||||
-std=c11 \
|
-std=c11 \
|
||||||
|
@ -46,7 +45,7 @@ INTERNALCFLAGS := \
|
||||||
|
|
||||||
all: test.elf multiboot2.elf multiboot.elf
|
all: test.elf multiboot2.elf multiboot.elf
|
||||||
|
|
||||||
test.elf: stivale.o stivale2.o limine.o e9print.o memory.o
|
test.elf: limine.o e9print.o memory.o
|
||||||
$(LD) $^ $(LDFLAGS) $(INTERNALLDFLAGS) -o $@
|
$(LD) $^ $(LDFLAGS) $(INTERNALLDFLAGS) -o $@
|
||||||
|
|
||||||
multiboot2.elf: multiboot2_trampoline.o
|
multiboot2.elf: multiboot2_trampoline.o
|
||||||
|
@ -66,6 +65,6 @@ multiboot.elf: multiboot_trampoline.o
|
||||||
nasm -felf32 $< -o $@
|
nasm -felf32 $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf test.elf limine.o stivale.o stivale2.o e9print.o memory.o
|
rm -rf test.elf limine.o e9print.o memory.o
|
||||||
rm -rf multiboot2.o multiboot2.elf multiboot2_trampoline.o
|
rm -rf multiboot2.o multiboot2.elf multiboot2_trampoline.o
|
||||||
rm -rf multiboot.o multiboot_trampoline.o multiboot.elf
|
rm -rf multiboot.o multiboot_trampoline.o multiboot.elf
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#include <e9print.h>
|
#include <e9print.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void (*stivale2_print)(const char *buf, size_t size) = NULL;
|
void (*limine_print)(const char *buf, size_t size) = NULL;
|
||||||
|
|
||||||
static const char CONVERSION_TABLE[] = "0123456789abcdef";
|
static const char CONVERSION_TABLE[] = "0123456789abcdef";
|
||||||
|
|
||||||
void e9_putc(char c) {
|
void e9_putc(char c) {
|
||||||
if (stivale2_print != NULL)
|
if (limine_print != NULL)
|
||||||
stivale2_print(&c, 1);
|
limine_print(&c, 1);
|
||||||
__asm__ __volatile__ ("outb %0, %1" :: "a" (c), "Nd" (0xe9) : "memory");
|
__asm__ __volatile__ ("outb %0, %1" :: "a" (c), "Nd" (0xe9) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
extern void (*stivale2_print)(const char *buf, size_t size);
|
extern void (*limine_print)(const char *buf, size_t size);
|
||||||
|
|
||||||
void e9_putc(char c);
|
void e9_putc(char c);
|
||||||
void e9_print(const char *msg);
|
void e9_print(const char *msg);
|
||||||
|
|
|
@ -11,10 +11,7 @@ BACKDROP_COLOUR=008080
|
||||||
|
|
||||||
:fwcfg:// test
|
:fwcfg:// test
|
||||||
|
|
||||||
COMMENT=Test of the stivale2 boot protocol.
|
|
||||||
|
|
||||||
# Let's use autodetection
|
# Let's use autodetection
|
||||||
#PROTOCOL=stivale2
|
|
||||||
RESOLUTION=800x600
|
RESOLUTION=800x600
|
||||||
KERNEL_PATH=fwcfg:///opt/org.limine-bootloader.kernel
|
KERNEL_PATH=fwcfg:///opt/org.limine-bootloader.kernel
|
||||||
KERNEL_CMDLINE=Woah! Another example!
|
KERNEL_CMDLINE=Woah! Another example!
|
||||||
|
@ -24,5 +21,5 @@ MODULE_STRING=yooooo
|
||||||
|
|
||||||
# Test that the module string provided to the kernel will be
|
# Test that the module string provided to the kernel will be
|
||||||
# the module path since a module string is not specified.
|
# the module path since a module string is not specified.
|
||||||
# (cc CONFIG.md stivale2.`MODULE_STRING` section)
|
# (cc CONFIG.md limine.`MODULE_STRING` section)
|
||||||
MODULE_PATH=fwcfg:///opt/org.limine-bootloader.background
|
MODULE_PATH=fwcfg:///opt/org.limine-bootloader.background
|
||||||
|
|
|
@ -201,9 +201,9 @@ static void write_shim(const char *s, uint64_t l) {
|
||||||
_terminal_request.response->write(terminal, s, l);
|
_terminal_request.response->write(terminal, s, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void limine_main(void) {
|
void limine_main(void) {
|
||||||
if (_terminal_request.response) {
|
if (_terminal_request.response) {
|
||||||
stivale2_print = write_shim;
|
limine_print = write_shim;
|
||||||
}
|
}
|
||||||
|
|
||||||
e9_printf("\nWe're alive");
|
e9_printf("\nWe're alive");
|
||||||
|
|
|
@ -47,32 +47,6 @@ TERM_BACKDROP=008080
|
||||||
:+Legacy
|
:+Legacy
|
||||||
COMMENT=Directory containing legacy entries.
|
COMMENT=Directory containing legacy entries.
|
||||||
|
|
||||||
::Stivale Test
|
|
||||||
COMMENT=Stivale1 test.
|
|
||||||
|
|
||||||
PROTOCOL=stivale
|
|
||||||
KERNEL_PATH=boot:///boot/test.elf
|
|
||||||
KERNEL_CMDLINE=This is an example kernel command line.
|
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot/test.elf
|
|
||||||
MODULE_STRING=This is the first module.
|
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot/bg.bmp
|
|
||||||
MODULE_STRING=This is the second module.
|
|
||||||
|
|
||||||
::Stivale2 Test
|
|
||||||
COMMENT=Stivale2 test.
|
|
||||||
|
|
||||||
PROTOCOL=stivale2
|
|
||||||
KERNEL_PATH=boot:///boot/test.elf
|
|
||||||
KERNEL_CMDLINE=This is an example kernel command line.
|
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot/test.elf
|
|
||||||
MODULE_STRING=This is the first module.
|
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot/bg.bmp
|
|
||||||
MODULE_STRING=This is the second module.
|
|
||||||
|
|
||||||
::Multiboot1 Test
|
::Multiboot1 Test
|
||||||
COMMENT=Test of the multiboot1 boot protocol.
|
COMMENT=Test of the multiboot1 boot protocol.
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
ENTRY(stivale_main)
|
ENTRY(limine_main)
|
||||||
|
|
||||||
PHDRS
|
PHDRS
|
||||||
{
|
{
|
||||||
null PT_NULL FLAGS(0) ; /* Null segment */
|
|
||||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||||
|
@ -25,14 +24,6 @@ SECTIONS
|
||||||
QUAD(0)
|
QUAD(0)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
.stivalehdr : {
|
|
||||||
KEEP(*(.stivalehdr))
|
|
||||||
} :rodata
|
|
||||||
|
|
||||||
.stivale2hdr : {
|
|
||||||
KEEP(*(.stivale2hdr))
|
|
||||||
} :rodata
|
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata*)
|
*(.rodata*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <stivale.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <e9print.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
static uint8_t stack[4096] = {0};
|
|
||||||
void stivale_main(struct stivale_struct *info);
|
|
||||||
|
|
||||||
__attribute__((section(".stivalehdr"), used))
|
|
||||||
struct stivale_header header = {
|
|
||||||
.stack = (uint64_t)(uintptr_t)stack + sizeof(stack),
|
|
||||||
.framebuffer_bpp = 0,
|
|
||||||
.framebuffer_width = 0,
|
|
||||||
.framebuffer_height = 0,
|
|
||||||
.flags = (1 << 3) | (1 << 4),
|
|
||||||
.entry_point = (uint64_t)(uintptr_t)stivale_main
|
|
||||||
};
|
|
||||||
|
|
||||||
void stivale_main(struct stivale_struct *info) {
|
|
||||||
e9_printf("Stivale struct at %x", info);
|
|
||||||
|
|
||||||
e9_puts("Stivale information passed to the kernel:");
|
|
||||||
e9_printf("Cmdline: %s", (char*)info->cmdline);
|
|
||||||
e9_printf("Memory map at %x with contents:", info->memory_map_addr);
|
|
||||||
|
|
||||||
struct stivale_mmap_entry *memmap = ((struct stivale_mmap_entry *)(info->memory_map_addr));
|
|
||||||
for (size_t i = 0; i < info->memory_map_entries; i++) {
|
|
||||||
struct stivale_mmap_entry e = memmap[i];
|
|
||||||
e9_printf("\tEntry %d: [%x+%x] %x", i, e.base, e.length, e.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
e9_printf("Framebuffer at %x with specifics:", info->framebuffer_addr);
|
|
||||||
e9_printf("\tPitch: %d", info->framebuffer_pitch);
|
|
||||||
e9_printf("\tWidth: %d", info->framebuffer_width);
|
|
||||||
e9_printf("\tHeight: %d", info->framebuffer_height);
|
|
||||||
e9_printf("\tBPP: %d", info->framebuffer_bpp);
|
|
||||||
if (info->flags & (1 << 1)) {
|
|
||||||
e9_printf("\tExtended colour information provided:");
|
|
||||||
e9_printf("\t\tMemory model: %d", info->fb_memory_model);
|
|
||||||
e9_printf("\t\tRed mask size: %d", info->fb_red_mask_size);
|
|
||||||
e9_printf("\t\tRed mask shift: %d", info->fb_red_mask_shift);
|
|
||||||
e9_printf("\t\tGreen mask size: %d", info->fb_green_mask_size);
|
|
||||||
e9_printf("\t\tGreen mask shift: %d", info->fb_green_mask_shift);
|
|
||||||
e9_printf("\t\tBlue mask size: %d", info->fb_blue_mask_size);
|
|
||||||
e9_printf("\t\tBlue mask shift: %d", info->fb_blue_mask_shift);
|
|
||||||
}
|
|
||||||
if (info->flags & (1 << 2)) {
|
|
||||||
e9_printf("\tSMBIOS information provided:");
|
|
||||||
e9_printf("\t\t32-bit entry: %x", info->smbios_entry_32);
|
|
||||||
e9_printf("\t\t64-bit entry: %x", info->smbios_entry_64);
|
|
||||||
}
|
|
||||||
|
|
||||||
e9_printf("RSDP at %x", info->rsdp);
|
|
||||||
|
|
||||||
e9_printf("Module map at %x with modules:", info->modules);
|
|
||||||
struct stivale_module *modules = ((struct stivale_module *)(info->modules));
|
|
||||||
for (size_t i = 0; i < info->module_count; i++) {
|
|
||||||
struct stivale_module e = *modules;
|
|
||||||
e9_printf("\tModule %d: [%x->%x] %s", i, e.begin, e.end, e.string);
|
|
||||||
modules = (struct stivale_module *)e.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
e9_printf("Epoch is %x", info->epoch);
|
|
||||||
e9_printf("Flags are %x", info->flags);
|
|
||||||
|
|
||||||
// Guru meditation.
|
|
||||||
for (;;);
|
|
||||||
}
|
|
281
test/stivale2.c
281
test/stivale2.c
|
@ -1,281 +0,0 @@
|
||||||
#include <stivale2.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <e9print.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef uint8_t stack[4096];
|
|
||||||
static stack stacks[64] = {0};
|
|
||||||
void stivale2_main(struct stivale2_struct *info);
|
|
||||||
|
|
||||||
struct stivale2_header_tag_slide_hhdm slide_hhdm = {
|
|
||||||
.tag = {
|
|
||||||
.identifier = STIVALE2_HEADER_TAG_SLIDE_HHDM_ID,
|
|
||||||
.next = 0
|
|
||||||
},
|
|
||||||
.flags = 0,
|
|
||||||
.alignment = 0x10000000
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stivale2_header_tag_terminal terminal_request = {
|
|
||||||
.tag = {
|
|
||||||
.identifier = STIVALE2_HEADER_TAG_TERMINAL_ID,
|
|
||||||
.next = (uint64_t)&slide_hhdm
|
|
||||||
},
|
|
||||||
.flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stivale2_header_tag_smp smp_request = {
|
|
||||||
.tag = {
|
|
||||||
.identifier = STIVALE2_HEADER_TAG_SMP_ID,
|
|
||||||
.next = (uint64_t)&terminal_request
|
|
||||||
},
|
|
||||||
.flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stivale2_tag unmap_null_request = {
|
|
||||||
.identifier = STIVALE2_HEADER_TAG_UNMAP_NULL_ID,
|
|
||||||
.next = (uint64_t)&smp_request
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stivale2_header_tag_any_video any_video_request = {
|
|
||||||
.tag = {
|
|
||||||
.identifier = STIVALE2_HEADER_TAG_ANY_VIDEO_ID,
|
|
||||||
.next = (uint64_t)&unmap_null_request
|
|
||||||
},
|
|
||||||
.preference = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((section(".stivale2hdr"), used))
|
|
||||||
struct stivale2_header header2 = {
|
|
||||||
.entry_point = (uint64_t)stivale2_main,
|
|
||||||
.stack = (uintptr_t)stacks[0] + sizeof(stack),
|
|
||||||
.flags = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4),
|
|
||||||
.tags = (uint64_t)&any_video_request
|
|
||||||
};
|
|
||||||
|
|
||||||
static volatile int cpu_up = 0;
|
|
||||||
|
|
||||||
static void ap_entry(struct stivale2_smp_info *s) {
|
|
||||||
e9_printf(" AP %d started", s->lapic_id);
|
|
||||||
cpu_up = 1;
|
|
||||||
for (;;) __asm__("hlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_guid(struct stivale2_guid guid) {
|
|
||||||
e9_printf("\t\ta: %x", guid.a);
|
|
||||||
e9_printf("\t\tb: %x", guid.b);
|
|
||||||
e9_printf("\t\tc: %x", guid.c);
|
|
||||||
e9_puts("\t\td: [");
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
|
||||||
e9_printf("\t\t\t%x,", guid.d[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
e9_puts("\t\t]\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void stivale2_main(struct stivale2_struct *info) {
|
|
||||||
// Print the tags.
|
|
||||||
struct stivale2_tag *tag = (struct stivale2_tag *)info->tags;
|
|
||||||
|
|
||||||
while (tag != NULL) {
|
|
||||||
if (tag->identifier == STIVALE2_STRUCT_TAG_TERMINAL_ID) {
|
|
||||||
struct stivale2_struct_tag_terminal *t = (void *)tag;
|
|
||||||
stivale2_print = (void *)(uintptr_t)t->term_write;
|
|
||||||
}
|
|
||||||
tag = (void *)tag->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print stuff.
|
|
||||||
e9_puts("Stivale2 info passed to the kernel:");
|
|
||||||
e9_printf("Bootloader brand: %s", info->bootloader_brand);
|
|
||||||
e9_printf("Bootloader version: %s", info->bootloader_version);
|
|
||||||
|
|
||||||
// Print the tags.
|
|
||||||
tag = (struct stivale2_tag *)info->tags;
|
|
||||||
|
|
||||||
while (tag != NULL) {
|
|
||||||
switch (tag->identifier) {
|
|
||||||
case STIVALE2_STRUCT_TAG_CMDLINE_ID: {
|
|
||||||
struct stivale2_struct_tag_cmdline *c = (struct stivale2_struct_tag_cmdline *)tag;
|
|
||||||
e9_puts("Commandline tag:");
|
|
||||||
e9_printf("\tCmdline: %s", (char*)(c->cmdline));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_MEMMAP_ID: {
|
|
||||||
struct stivale2_struct_tag_memmap *m = (struct stivale2_struct_tag_memmap *)tag;
|
|
||||||
e9_puts("Memmap tag:");
|
|
||||||
e9_printf("\tEntries: %d", m->entries);
|
|
||||||
size_t total_mem = 0;
|
|
||||||
for (size_t i = 0; i < m->entries; i++) {
|
|
||||||
struct stivale2_mmap_entry me = m->memmap[i];
|
|
||||||
e9_printf("\t\t[%x+%x] %x", me.base, me.length, me.type);
|
|
||||||
if (m->memmap[i].type == 1) {
|
|
||||||
total_mem += m->memmap[i].length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e9_printf("\tTotal usable memory: %d", total_mem);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID: {
|
|
||||||
struct stivale2_struct_tag_framebuffer *f = (struct stivale2_struct_tag_framebuffer *)tag;
|
|
||||||
e9_puts("Framebuffer tag:");
|
|
||||||
e9_printf("\tAddress: %x", f->framebuffer_addr);
|
|
||||||
e9_printf("\tWidth: %d", f->framebuffer_width);
|
|
||||||
e9_printf("\tHeight: %d", f->framebuffer_height);
|
|
||||||
e9_printf("\tPitch: %d", f->framebuffer_pitch);
|
|
||||||
e9_printf("\tBPP: %d", f->framebuffer_bpp);
|
|
||||||
e9_printf("\tMemory model: %d", f->memory_model);
|
|
||||||
e9_printf("\tRed mask size: %d", f->red_mask_size);
|
|
||||||
e9_printf("\tRed mask size: %d", f->red_mask_shift);
|
|
||||||
e9_printf("\tGreen mask size: %d", f->green_mask_size);
|
|
||||||
e9_printf("\tGreen mask size: %d", f->green_mask_shift);
|
|
||||||
e9_printf("\tBlue mask size: %d", f->blue_mask_size);
|
|
||||||
e9_printf("\tBlue mask size: %d", f->blue_mask_shift);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_TEXTMODE_ID: {
|
|
||||||
struct stivale2_struct_tag_textmode *tm = (struct stivale2_struct_tag_textmode *)tag;
|
|
||||||
e9_puts("Textmode tag");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_EDID_ID: {
|
|
||||||
struct stivale2_struct_tag_edid *edid = (struct stivale2_struct_tag_edid *)tag;
|
|
||||||
|
|
||||||
e9_printf("EDID information at %x:", edid->edid_information);
|
|
||||||
e9_printf("\tSize: %d", edid->edid_size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_FB_MTRR_ID: {
|
|
||||||
e9_puts("Framebuffer WC MTRR tag:");
|
|
||||||
e9_puts("\tFramebuffer WC MTRR enabled");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_TERMINAL_ID: {
|
|
||||||
struct stivale2_struct_tag_terminal *term = (struct stivale2_struct_tag_terminal *)tag;
|
|
||||||
|
|
||||||
e9_puts("Terminal tag:");
|
|
||||||
e9_printf("\tTerminal write entry point at: %x", term->term_write);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_MODULES_ID: {
|
|
||||||
struct stivale2_struct_tag_modules *m = (struct stivale2_struct_tag_modules *)tag;
|
|
||||||
e9_puts("Modules tag:");
|
|
||||||
e9_printf("\tCount: %d", m->module_count);
|
|
||||||
for (size_t i = 0; i < m->module_count; i++) {
|
|
||||||
struct stivale2_module me = m->modules[i];
|
|
||||||
e9_printf("\t\t[%x+%x] %s", me.begin, me.end, me.string);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_RSDP_ID: {
|
|
||||||
struct stivale2_struct_tag_rsdp *r = (struct stivale2_struct_tag_rsdp *)tag;
|
|
||||||
e9_puts("RSDP tag:");
|
|
||||||
e9_printf("\tRSDP: %x", r->rsdp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_SMBIOS_ID: {
|
|
||||||
struct stivale2_struct_tag_smbios *r = (struct stivale2_struct_tag_smbios *)tag;
|
|
||||||
e9_puts("SMBIOS tag:");
|
|
||||||
e9_printf("\tFlags: %x", r->flags);
|
|
||||||
e9_printf("\tSMBIOS 32-bit entry point: %x", r->smbios_entry_32);
|
|
||||||
e9_printf("\tSMBIOS 64-bit entry point: %x", r->smbios_entry_64);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_EPOCH_ID: {
|
|
||||||
struct stivale2_struct_tag_epoch *e = (struct stivale2_struct_tag_epoch *)tag;
|
|
||||||
e9_puts("Epoch tag:");
|
|
||||||
e9_printf("\tEpoch: %x", e->epoch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_FIRMWARE_ID: {
|
|
||||||
struct stivale2_struct_tag_firmware *f = (struct stivale2_struct_tag_firmware *)tag;
|
|
||||||
e9_puts("Firmware tag:");
|
|
||||||
e9_printf("\tFlags: %x", f->flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID: {
|
|
||||||
struct stivale2_struct_tag_efi_system_table *t = (struct stivale2_struct_tag_efi_system_table *)tag;
|
|
||||||
e9_printf("EFI system table at: %x", t->system_table);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_KERNEL_FILE_ID: {
|
|
||||||
struct stivale2_struct_tag_kernel_file *t = (struct stivale2_struct_tag_kernel_file *)tag;
|
|
||||||
e9_printf("Raw kernel file loaded at: %x", t->kernel_file);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_KERNEL_FILE_V2_ID: {
|
|
||||||
struct stivale2_struct_tag_kernel_file_v2 *t = (struct stivale2_struct_tag_kernel_file_v2 *)tag;
|
|
||||||
e9_puts("Kernel file V2 tag:");
|
|
||||||
e9_printf("\tkernel_file: %x", t->kernel_file);
|
|
||||||
e9_printf("\tkernel_size: %x", t->kernel_size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_KERNEL_SLIDE_ID: {
|
|
||||||
struct stivale2_struct_tag_kernel_slide *t = (struct stivale2_struct_tag_kernel_slide *)tag;
|
|
||||||
e9_printf("Kernel slide: %x", t->kernel_slide);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_PMRS_ID: {
|
|
||||||
struct stivale2_struct_tag_pmrs *t = (struct stivale2_struct_tag_pmrs *)tag;
|
|
||||||
e9_puts("PMRs tag:");
|
|
||||||
e9_printf("\t%d ranges:", t->entries);
|
|
||||||
for (size_t i = 0; i < t->entries; i++) {
|
|
||||||
e9_printf("\t\tBase: %x Length: %x Perms: %x",
|
|
||||||
t->pmrs[i].base, t->pmrs[i].length, t->pmrs[i].permissions);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_HHDM_ID: {
|
|
||||||
struct stivale2_struct_tag_hhdm *t = (struct stivale2_struct_tag_hhdm *)tag;
|
|
||||||
e9_printf("Higher half direct map at: %x", t->addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_KERNEL_BASE_ADDRESS_ID: {
|
|
||||||
struct stivale2_struct_tag_kernel_base_address *t = (void *)tag;
|
|
||||||
e9_puts("Kernel base address:");
|
|
||||||
e9_printf("\tPhysical base address: %x", t->physical_base_address);
|
|
||||||
e9_printf("\tVirtual base address: %x", t->virtual_base_address);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_BOOT_VOLUME_ID: {
|
|
||||||
struct stivale2_struct_tag_boot_volume *t = (void *)tag;
|
|
||||||
e9_puts("Boot volume:");
|
|
||||||
e9_printf("\tGUID:");
|
|
||||||
print_guid(t->guid);
|
|
||||||
e9_printf("\tPartition GUID:");
|
|
||||||
print_guid(t->part_guid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STIVALE2_STRUCT_TAG_SMP_ID: {
|
|
||||||
struct stivale2_struct_tag_smp *s = (struct stivale2_struct_tag_smp *)tag;
|
|
||||||
e9_puts("SMP tag:");
|
|
||||||
e9_printf("\tFlags: %x", s->flags);
|
|
||||||
e9_printf("\tBSP LAPIC ID: %d", s->bsp_lapic_id);
|
|
||||||
e9_printf("\tCPU Count: %d", s->cpu_count);
|
|
||||||
for (size_t i = 0; i < s->cpu_count; i++) {
|
|
||||||
struct stivale2_smp_info *in = &s->smp_info[i];
|
|
||||||
e9_printf("\t\tProcessor ID: %d", in->processor_id);
|
|
||||||
e9_printf("\t\tLAPIC ID: %d", in->lapic_id);
|
|
||||||
e9_printf("\t\tTarget Stack: %x", in->target_stack);
|
|
||||||
e9_printf("\t\tGOTO Address: %x", in->goto_address);
|
|
||||||
e9_printf("\t\tExtra Argument: %x", in->extra_argument);
|
|
||||||
if (in->lapic_id != s->bsp_lapic_id) {
|
|
||||||
in->target_stack = (uintptr_t)stacks[in->lapic_id] + sizeof(stack);
|
|
||||||
in->goto_address = (uintptr_t)ap_entry;
|
|
||||||
while (cpu_up == 0);
|
|
||||||
cpu_up = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
e9_printf("BUG: Unidentified tag %x", tag->identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = (struct stivale2_tag *)tag->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enter our sublime pale slumber.
|
|
||||||
for (;;) __asm__("hlt");
|
|
||||||
}
|
|
Loading…
Reference in New Issue