From edd4a8de603055fc2b5c094464f02745a76897c7 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Tue, 2 Mar 2021 10:23:43 +0100 Subject: [PATCH] Initial UEFI port --- .gitignore | 4 + Makefile | 34 ++++- make_toolchain.sh | 18 ++- stage23/Makefile | 81 +++++++++-- stage23/drivers/disk.h | 2 + stage23/drivers/disk.s2.c | 97 ++++++++++++++ stage23/drivers/gop.c | 19 +++ stage23/drivers/gop.h | 16 +++ stage23/drivers/vbe.c | 4 + stage23/drivers/vga_textmode.s2.c | 4 + stage23/entry.s2.c | 7 +- stage23/entry.s3.c | 12 ++ stage23/fs/echfs.h | 1 - stage23/fs/echfs.s2.c | 1 - stage23/fs/fat32.h | 1 - stage23/fs/fat32.s2.c | 1 - stage23/gensyms64.sh | 24 ++++ stage23/lib/acpi.c | 8 +- stage23/lib/blib.c | 6 + stage23/lib/blib.h | 12 +- stage23/lib/builtins.s2.asm | 75 ----------- stage23/lib/config.c | 2 + stage23/lib/elf.c | 10 +- stage23/lib/fb.c | 5 + stage23/lib/gterm.c | 2 +- stage23/lib/libc.s2.c | 50 +++++++ stage23/lib/panic.s2.c | 4 + stage23/lib/part.h | 15 ++- stage23/lib/part.s2.c | 126 +++++------------- stage23/lib/readline.c | 32 ++++- stage23/lib/term.c | 2 + stage23/lib/term.s2.c | 4 + stage23/lib/time.c | 18 ++- stage23/lib/trace.s2.c | 18 ++- stage23/lib/uri.c | 13 +- stage23/{linker.ld => linker_bios.ld} | 0 .../{linker_nomap.ld => linker_nomap_bios.ld} | 0 stage23/linker_nomap_uefi.ld | 33 +++++ stage23/linker_uefi.ld | 33 +++++ stage23/mm/mtrr.c | 2 +- stage23/mm/pmm.s2.c | 26 ++++ stage23/protos/chainload.c | 4 + stage23/protos/linux.c | 4 + stage23/protos/stivale.c | 9 ++ stage23/protos/stivale2.c | 6 + stage23/pxe/pxe.c | 4 + stage23/pxe/tftp.c | 8 +- stage23/sys/a20.s2.c | 4 + stage23/sys/e820.s2.c | 4 + stage23/sys/smp.c | 4 +- 50 files changed, 638 insertions(+), 231 deletions(-) create mode 100644 stage23/drivers/gop.c create mode 100644 stage23/drivers/gop.h create mode 100755 stage23/gensyms64.sh delete mode 100644 stage23/lib/builtins.s2.asm rename stage23/{linker.ld => linker_bios.ld} (100%) rename stage23/{linker_nomap.ld => linker_nomap_bios.ld} (100%) create mode 100644 stage23/linker_nomap_uefi.ld create mode 100644 stage23/linker_uefi.ld diff --git a/.gitignore b/.gitignore index 67e67357..d94bee1a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ /bin /toolchain +/gnu-efi +/ovmf /**/*.o /**/*.d /**/*.a +/**/*.EFI /**/*.bin /**/*.bin.gz /**/*.elf @@ -14,3 +17,4 @@ .vscode /stivale /test_image +!/stage23/font.bin diff --git a/Makefile b/Makefile index 518dd382..e48f3a78 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ OBJCOPY = objcopy CFLAGS = -O2 -pipe -Wall -Wextra PREFIX = /usr/local DESTDIR = +TARGET = bios PATH := $(shell pwd)/toolchain/bin:$(PATH) @@ -27,31 +28,36 @@ install: all install -m 644 bin/limine-cd.bin $(DESTDIR)$(PREFIX)/share/ install -m 644 bin/limine-pxe.bin $(DESTDIR)$(PREFIX)/share/ +ifeq ($(TARGET), bios) bootloader: | decompressor stage23 mkdir -p bin cd stage1/hdd && nasm bootsect.asm -fbin -o ../../bin/limine-hdd.bin cd stage1/cd && nasm bootsect.asm -fbin -o ../../bin/limine-cd.bin cd stage1/pxe && nasm bootsect.asm -fbin -o ../../bin/limine-pxe.bin cp stage23/limine.sys ./bin/ +else ifeq ($(TARGET), uefi) +bootloader: stage23 + mkdir -p bin + cp stage23/BOOTX64.EFI ./bin/ +endif bootloader-clean: stage23-clean decompressor-clean distclean: clean bootloader-clean test-clean rm -rf bin stivale toolchain -tinf-clean: - cd tinf && rm -rf *.o *.d - stivale: git clone https://github.com/stivale/stivale.git -stage23: tinf-clean stivale - $(MAKE) -C stage23 all +stage23: stivale + cd tinf && rm -rf *.o *.d + $(MAKE) -C stage23 all TARGET=$(TARGET) stage23-clean: $(MAKE) -C stage23 clean -decompressor: tinf-clean +decompressor: + cd tinf && rm -rf *.o *.d $(MAKE) -C decompressor all decompressor-clean: @@ -64,6 +70,14 @@ test-clean: toolchain: ./make_toolchain.sh ./toolchain -j`nproc` +gnu-efi: + git clone https://git.code.sf.net/p/gnu-efi/code --branch=3.0.12 --depth=1 $@ + +ovmf: + mkdir -p ovmf + wget https://efi.akeo.ie/OVMF/OVMF-X64.zip + cd ovmf && 7z x OVMF-X64.zip + test.hdd: rm -f test.hdd dd if=/dev/zero bs=1M count=0 seek=64 of=test.hdd @@ -109,12 +123,20 @@ fat32-test: | test-clean test.hdd bootloader all sudo mount `cat loopback_dev`p1 test_image sudo mkdir test_image/boot sudo cp -rv bin/* test/* test_image/boot/ +ifeq ($(TARGET), uefi) + sudo mkdir -p test_image/EFI/BOOT + sudo cp bin/BOOTX64.EFI test_image/EFI/BOOT/ +endif sync sudo umount test_image/ sudo losetup -d `cat loopback_dev` rm -rf test_image loopback_dev bin/limine-install test.hdd +ifeq ($(TARGET), bios) qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio +else ifeq ($(TARGET), uefi) + qemu-system-x86_64 -L ovmf -bios ovmf/OVMF.fd -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio +endif iso9660-test: | test-clean test.hdd bootloader all $(MAKE) -C test diff --git a/make_toolchain.sh b/make_toolchain.sh index e2345577..86dc2b9c 100755 --- a/make_toolchain.sh +++ b/make_toolchain.sh @@ -3,9 +3,9 @@ set -e set -x -TARGET=i386-elf +TARGET="i386-elf x86_64-elf" BINUTILSVERSION=2.36.1 -GCCVERSION=11-20210228 +GCCVERSION=10.2.0 NASMVERSION=2.15.05 GZIPVERSION=1.10 @@ -20,7 +20,7 @@ if [ ! -f binutils-$BINUTILSVERSION.tar.gz ]; then wget https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILSVERSION.tar.gz fi if [ ! -f gcc-$GCCVERSION.tar.xz ]; then - wget https://ftp.nluug.nl/languages/gcc/snapshots/$GCCVERSION/gcc-$GCCVERSION.tar.xz + wget https://ftp.gnu.org/gnu/gcc/gcc-$GCCVERSION/gcc-$GCCVERSION.tar.gz fi if [ ! -f nasm-$NASMVERSION.tar.gz ]; then wget https://www.nasm.us/pub/nasm/releasebuilds/$NASMVERSION/nasm-$NASMVERSION.tar.gz @@ -34,28 +34,34 @@ mkdir build cd build tar -xf ../binutils-$BINUTILSVERSION.tar.gz -tar -xf ../gcc-$GCCVERSION.tar.xz +tar -xf ../gcc-$GCCVERSION.tar.gz tar -xf ../nasm-$NASMVERSION.tar.gz tar -xf ../gzip-$GZIPVERSION.tar.gz +for i in $TARGET; do +rm -rf build-binutils mkdir build-binutils cd build-binutils -../binutils-$BINUTILSVERSION/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror --enable-64-bit-bfd +../binutils-$BINUTILSVERSION/configure --target=$i --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror $([ $i = "x86_64-elf" ] && echo --enable-targets=x86_64-elf,x86_64-pe) --enable-64-bit-bfd make make install cd .. +done cd gcc-$GCCVERSION contrib/download_prerequisites cd .. +for i in $TARGET; do +rm -rf build-gcc mkdir build-gcc cd build-gcc -../gcc-$GCCVERSION/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers +../gcc-$GCCVERSION/configure --target=$i --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers make all-gcc make all-target-libgcc make install-gcc make install-target-libgcc cd .. +done mkdir build-nasm cd build-nasm diff --git a/stage23/Makefile b/stage23/Makefile index c753cee3..68afb6fa 100644 --- a/stage23/Makefile +++ b/stage23/Makefile @@ -1,8 +1,18 @@ -CC = i386-elf-gcc -LD = i386-elf-gcc -OBJCOPY = i386-elf-objcopy -OBJDUMP = i386-elf-objdump -READELF = i386-elf-readelf +TARGET = bios + +ifeq ($(TARGET), bios) + TOOLCHAIN=i386-elf +else ifeq ($(TARGET), uefi) + TOOLCHAIN=x86_64-elf +else + $(error Invalid toolchain) +endif + +CC = $(TOOLCHAIN)-gcc +LD = $(TOOLCHAIN)-gcc +OBJCOPY = $(TOOLCHAIN)-objcopy +OBJDUMP = $(TOOLCHAIN)-objdump +READELF = $(TOOLCHAIN)-readelf COM_OUTPUT = false E9_OUTPUT = false @@ -19,6 +29,7 @@ INTERNAL_CFLAGS := \ -fno-stack-protector \ -fno-pic \ -fno-omit-frame-pointer \ + -fno-lto \ -Wno-address-of-packed-member \ -masm=intel \ -mgeneral-regs-only \ @@ -27,27 +38,60 @@ INTERNAL_CFLAGS := \ -DLIMINE_VERSION='"$(LIMINE_VERSION)"' \ -DCOM_OUTPUT=$(COM_OUTPUT) \ -DE9_OUTPUT=$(E9_OUTPUT) \ + -D$(TARGET)=1 \ -I. \ -I.. +ifeq ($(TARGET), uefi) + INTERNAL_CFLAGS += \ + -I../gnu-efi/inc \ + -I../gnu-efi/inc/x86_64 \ + -fpic \ + -fshort-wchar \ + -mno-red-zone \ + -mcmodel=small +endif + LDFLAGS = -Os INTERNAL_LDFLAGS := \ - -lgcc \ - -static-libgcc \ + -fno-lto \ -nostdlib \ - -no-pie \ - -z max-page-size=0x1000 \ - -static + -z max-page-size=0x1000 + +ifeq ($(TARGET), bios) + INTERNAL_LDFLAGS += \ + -static \ + -no-pie \ + -lgcc \ + -static-libgcc +else ifeq ($(TARGET), uefi) + INTERNAL_LDFLAGS += \ + -shared \ + -z nocombreloc \ + -Wl,-Bsymbolic +endif .PHONY: all clean C_FILES := $(shell find -L ./ -type f -name '*.c' | sort) +ifeq ($(TARGET), bios) ASM_FILES := $(shell find -L ./ -type f -name '*.asm' | sort) +endif OBJ := $(ASM_FILES:.asm=.o) $(C_FILES:.c=.o) +ifeq ($(TARGET), uefi) +OBJ += sys/smp_trampoline.o ../gnu-efi/lib/x86_64/efi_stub.o +endif HEADER_DEPS := $(C_FILES:.c=.d) +ifeq ($(TARGET), bios) all: limine.sys stage2.bin stage2.bin.gz +else ifeq ($(TARGET), uefi) +all: BOOTX64.EFI +endif + +BOOTX64.EFI: limine.elf + $(OBJCOPY) -I elf64-x86-64 -O efi-app-x86_64 limine.elf $@ stage2.bin.gz: stage2.bin gzip -n -9 < stage2.bin > stage2.bin.gz @@ -56,30 +100,43 @@ stage2.bin: limine.sys dd if=limine.sys bs=$$(( 0x$$($(READELF) -S limine.elf | grep .stage3.text | sed 's/^.*] //' | awk '{print $$3}' | sed 's/^0*//') - 0x8000 )) count=1 of=$@ limine.map.o: limine_nomap.elf +ifeq ($(TARGET), bios) ./gensyms.sh $(OBJDUMP) limine_nomap.elf limine +else ifeq ($(TARGET), uefi) + ./gensyms64.sh $(OBJDUMP) limine_nomap.elf limine +endif limine.sys: limine.elf $(OBJCOPY) -O binary $< $@ limine_nomap.elf: $(OBJ) - $(LD) $(OBJ) font.o $(LDFLAGS) $(INTERNAL_LDFLAGS) -Tlinker_nomap.ld -o $@ + $(LD) $(OBJ) font.o $(LDFLAGS) $(INTERNAL_LDFLAGS) -Tlinker_nomap_$(TARGET).ld -o $@ +ifeq ($(TARGET), bios) $(LD) $(OBJ) font.o $(LDFLAGS) $(INTERNAL_LDFLAGS) -Wl,--gc-sections -Tlinker_stage2only.ld -o limine_stage2only.elf || \ ( echo "This error means that stage 2 was trying to use stage 3 symbols before loading stage 3" && \ false ) +endif font.o: $(OBJCOPY) -B i8086 -I binary -O default font.bin $@ limine.elf: $(OBJ) font.o limine.map.o - $(LD) $(OBJ) font.o limine.map.o $(LDFLAGS) $(INTERNAL_LDFLAGS) -Tlinker.ld -o $@ + $(LD) $(OBJ) font.o limine.map.o $(LDFLAGS) $(INTERNAL_LDFLAGS) -Tlinker_$(TARGET).ld -o $@ -include $(HEADER_DEPS) %.o: %.c $(CC) $(CFLAGS) $(INTERNAL_CFLAGS) -c $< -o $@ +%.o: %.S + $(CC) $(CFLAGS) $(INTERNAL_CFLAGS) -c $< -o $@ +ifeq ($(TARGET), bios) %.o: %.asm nasm $< -f elf32 -o $@ +else ifeq ($(TARGET), uefi) +%.o: %.asm + nasm $< -f elf64 -o $@ +endif clean: rm -f limine.elf limine_nomap.elf limine_stage2only.elf font.o limine.map.o limine.sys stage2.bin stage2.bin.gz $(OBJ) $(HEADER_DEPS) diff --git a/stage23/drivers/disk.h b/stage23/drivers/disk.h index eade9f5f..c5a6b1fd 100644 --- a/stage23/drivers/disk.h +++ b/stage23/drivers/disk.h @@ -2,6 +2,7 @@ #define __DRIVERS__DISK_H__ #include +#include struct bios_drive_params { uint16_t buf_size; @@ -16,5 +17,6 @@ struct bios_drive_params { int disk_get_sector_size(int drive); int disk_read(int drive, void *buffer, uint64_t loc, uint64_t count); +size_t disk_create_index(struct volume **ret); #endif diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c index 1b641449..08806c71 100644 --- a/stage23/drivers/disk.s2.c +++ b/stage23/drivers/disk.s2.c @@ -1,3 +1,5 @@ +#if defined(bios) + #include #include #include @@ -103,3 +105,98 @@ int disk_read(int drive, void *buffer, uint64_t loc, uint64_t count) { return 0; } + +size_t disk_create_index(struct volume **ret) { + struct volume *volume_index; + size_t volume_count = 0, volume_index_i = 0; + + for (uint8_t drive = 0x80; drive; drive++) { + struct rm_regs r = {0}; + struct bios_drive_params drive_params; + + r.eax = 0x4800; + r.edx = drive; + r.ds = rm_seg(&drive_params); + r.esi = rm_off(&drive_params); + + drive_params.buf_size = sizeof(struct bios_drive_params); + + rm_int(0x13, &r, &r); + + if (r.eflags & EFLAGS_CF) + continue; + + print("Found BIOS drive %x\n", drive); + print(" ... %X total %u-byte sectors\n", + drive_params.lba_count, drive_params.bytes_per_sect); + + volume_count++; + + struct volume block; + + block.drive = drive; + block.sector_size = drive_params.bytes_per_sect; + block.first_sect = 0; + block.sect_count = drive_params.lba_count; + + for (int part = 0; ; part++) { + struct volume p; + int ret = part_get(&p, &block, part); + + if (ret == END_OF_TABLE || ret == INVALID_TABLE) + break; + if (ret == NO_PARTITION) + continue; + + volume_count++; + } + } + + volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count); + + for (uint8_t drive = 0x80; drive; drive++) { + struct rm_regs r = {0}; + struct bios_drive_params drive_params; + + r.eax = 0x4800; + r.edx = drive; + r.ds = rm_seg(&drive_params); + r.esi = rm_off(&drive_params); + + drive_params.buf_size = sizeof(struct bios_drive_params); + + rm_int(0x13, &r, &r); + + if (r.eflags & EFLAGS_CF) + continue; + + struct volume *block = &volume_index[volume_index_i++]; + + block->drive = drive; + block->partition = -1; + block->sector_size = drive_params.bytes_per_sect; + block->first_sect = 0; + block->sect_count = drive_params.lba_count; + + if (gpt_get_guid(&block->guid, block)) { + block->guid_valid = true; + } + + for (int part = 0; ; part++) { + struct volume p; + int ret = part_get(&p, block, part); + + if (ret == END_OF_TABLE || ret == INVALID_TABLE) + break; + if (ret == NO_PARTITION) + continue; + + volume_index[volume_index_i++] = p; + } + } + + *ret = volume_index; + return volume_count; +} + +#endif diff --git a/stage23/drivers/gop.c b/stage23/drivers/gop.c new file mode 100644 index 00000000..1acaca9f --- /dev/null +++ b/stage23/drivers/gop.c @@ -0,0 +1,19 @@ +#if defined (uefi) + +#include +#include +#include + +bool init_gop(struct fb_info *ret, + uint16_t target_width, uint16_t target_height, uint16_t target_bpp) { + (void)ret; (void)target_width; (void)target_height; (void)target_bpp; + + EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + + uefi_call_wrapper(gBS->LocateProtocol, 3, &gop_guid, NULL, (void **)&gop); + + for (;;); +} + +#endif diff --git a/stage23/drivers/gop.h b/stage23/drivers/gop.h new file mode 100644 index 00000000..704cce2f --- /dev/null +++ b/stage23/drivers/gop.h @@ -0,0 +1,16 @@ +#ifndef __DRIVERS__GOP_H__ +#define __DRIVERS__GOP_H__ + +#if defined (uefi) + +#include +#include +#include +#include + +bool init_gop(struct fb_info *ret, + uint16_t target_width, uint16_t target_height, uint16_t target_bpp); + +#endif + +#endif diff --git a/stage23/drivers/vbe.c b/stage23/drivers/vbe.c index 2cb420b5..3f2519ad 100644 --- a/stage23/drivers/vbe.c +++ b/stage23/drivers/vbe.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -263,3 +265,5 @@ retry: return false; } + +#endif diff --git a/stage23/drivers/vga_textmode.s2.c b/stage23/drivers/vga_textmode.s2.c index bd8677d1..99cad37f 100644 --- a/stage23/drivers/vga_textmode.s2.c +++ b/stage23/drivers/vga_textmode.s2.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -167,3 +169,5 @@ void text_putchar(uint8_t c) { draw_cursor(); } } + +#endif diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c index 5e009207..a78ce59e 100644 --- a/stage23/entry.s2.c +++ b/stage23/entry.s2.c @@ -22,11 +22,14 @@ extern uint64_t stage3_build_id; -uint8_t boot_drive; +drive_t boot_drive; int boot_partition = -1; bool booted_from_pxe = false; bool booted_from_cd = false; + +#if defined (bios) + bool stage3_loaded = false; extern symbol stage3_addr; @@ -105,3 +108,5 @@ void entry(uint8_t _boot_drive, int boot_from) { stage3(boot_from); } + +#endif diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index c575b5ad..ef581180 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -20,6 +20,18 @@ #include #include +#if defined (uefi) +EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { + (void)ImageHandle; + + gST = SystemTable; + gBS = SystemTable->BootServices; + gRT = SystemTable->RuntimeServices; + + for (;;); +} +#endif + __attribute__((section(".stage3_build_id"))) uint64_t stage3_build_id = BUILD_ID; diff --git a/stage23/fs/echfs.h b/stage23/fs/echfs.h index 517e71fe..92f221c9 100644 --- a/stage23/fs/echfs.h +++ b/stage23/fs/echfs.h @@ -21,7 +21,6 @@ struct echfs_dir_entry { } __attribute__((packed)); struct echfs_file_handle { - int disk; struct volume part; uint64_t block_size; uint64_t block_count; diff --git a/stage23/fs/echfs.s2.c b/stage23/fs/echfs.s2.c index 50df73d7..89a838de 100644 --- a/stage23/fs/echfs.s2.c +++ b/stage23/fs/echfs.s2.c @@ -69,7 +69,6 @@ bool echfs_get_guid(struct guid *guid, struct volume *part) { int echfs_open(struct echfs_file_handle *ret, struct volume *part, const char *path) { const char *fullpath = path; - ret->disk = part->drive; ret->part = *part; struct echfs_identity_table id_table; diff --git a/stage23/fs/fat32.h b/stage23/fs/fat32.h index a560289d..abd56adb 100644 --- a/stage23/fs/fat32.h +++ b/stage23/fs/fat32.h @@ -5,7 +5,6 @@ #include struct fat32_context { - int drive; struct volume part; uint8_t sectors_per_cluster; uint16_t reserved_sectors; diff --git a/stage23/fs/fat32.s2.c b/stage23/fs/fat32.s2.c index cc43f8f4..a9edf310 100644 --- a/stage23/fs/fat32.s2.c +++ b/stage23/fs/fat32.s2.c @@ -69,7 +69,6 @@ struct fat32_lfn_entry { static int fat32_init_context(struct fat32_context* context, struct volume *part) { context->part = *part; - context->drive = part->drive; struct fat32_bpb bpb; volume_read(&context->part, &bpb, 0, sizeof(struct fat32_bpb)); diff --git a/stage23/gensyms64.sh b/stage23/gensyms64.sh new file mode 100755 index 00000000..ffad0834 --- /dev/null +++ b/stage23/gensyms64.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -e + +TMP1=$(mktemp) +TMP2=$(mktemp) +TMP3=$(mktemp) +TMP4=$(mktemp) + +$1 -t "$2" | sed '/\bd\b/d' | sort > "$TMP1" +grep "\.text" < "$TMP1" | cut -d' ' -f1 > "$TMP2" +grep "\.text" < "$TMP1" | awk 'NF{ print $NF }' > "$TMP3" + +echo "section .map" > "$TMP4" +echo "global $3_map" >> "$TMP4" +echo "$3_map:" >> "$TMP4" + +paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dq 0x/g' | sed 's/$/", 0/g' | sed 's/\$/\ndb "/g' >> "$TMP4" + +echo "dq 0xffffffffffffffff" >> "$TMP4" + +nasm -f elf64 "$TMP4" -o $3.map.o + +rm "$TMP1" "$TMP2" "$TMP3" "$TMP4" diff --git a/stage23/lib/acpi.c b/stage23/lib/acpi.c index 15c41c6b..bd18f5a6 100644 --- a/stage23/lib/acpi.c +++ b/stage23/lib/acpi.c @@ -45,16 +45,16 @@ void *acpi_get_table(const char *signature, int index) { struct rsdt *rsdt; if (use_xsdt) - rsdt = (struct rsdt *)(size_t)rsdp->xsdt_addr; + rsdt = (struct rsdt *)(uintptr_t)rsdp->xsdt_addr; else - rsdt = (struct rsdt *)rsdp->rsdt_addr; + rsdt = (struct rsdt *)(uintptr_t)rsdp->rsdt_addr; for (size_t i = 0; i < rsdt->length - sizeof(struct sdt); i++) { struct sdt *ptr; if (use_xsdt) - ptr = (struct sdt *)(size_t)((uint64_t *)rsdt->ptrs_start)[i]; + ptr = (struct sdt *)(uintptr_t)((uint64_t *)rsdt->ptrs_start)[i]; else - ptr = (struct sdt *)((uint32_t *)rsdt->ptrs_start)[i]; + ptr = (struct sdt *)(uintptr_t)((uint32_t *)rsdt->ptrs_start)[i]; if (!memcmp(ptr->signature, signature, 4) && !acpi_checksum(ptr, ptr->length) diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c index bdd62d66..6eee5e33 100644 --- a/stage23/lib/blib.c +++ b/stage23/lib/blib.c @@ -8,6 +8,12 @@ #include #include +#if defined (uefi) +EFI_SYSTEM_TABLE *gST; +EFI_BOOT_SERVICES *gBS; +EFI_RUNTIME_SERVICES *gRT; +#endif + bool parse_resolution(int *width, int *height, int *bpp, const char *buf) { int res[3] = {0}; diff --git a/stage23/lib/blib.h b/stage23/lib/blib.h index b02c74c9..cedff14c 100644 --- a/stage23/lib/blib.h +++ b/stage23/lib/blib.h @@ -5,8 +5,18 @@ #include #include #include +#include +#if defined (uefi) +# include +#endif -extern uint8_t boot_drive; +#if defined (uefi) +extern EFI_SYSTEM_TABLE *gST; +extern EFI_BOOT_SERVICES *gBS; +extern EFI_RUNTIME_SERVICES *gRT; +#endif + +extern drive_t boot_drive; extern int boot_partition; extern bool booted_from_pxe; diff --git a/stage23/lib/builtins.s2.asm b/stage23/lib/builtins.s2.asm deleted file mode 100644 index 924cbe16..00000000 --- a/stage23/lib/builtins.s2.asm +++ /dev/null @@ -1,75 +0,0 @@ -section .text - -global memcpy -memcpy: - push esi - push edi - mov eax, dword [esp+12] - mov edi, eax - mov esi, dword [esp+16] - mov ecx, dword [esp+20] - rep movsb - pop edi - pop esi - ret - -global memset -memset: - push edi - mov edx, dword [esp+8] - mov edi, edx - mov eax, dword [esp+12] - mov ecx, dword [esp+16] - rep stosb - mov eax, edx - pop edi - ret - -global memmove -memmove: - push esi - push edi - mov eax, dword [esp+12] - mov edi, eax - mov esi, dword [esp+16] - mov ecx, dword [esp+20] - - cmp edi, esi - ja .copy_backwards - - rep movsb - jmp .done - - .copy_backwards: - lea edi, [edi+ecx-1] - lea esi, [esi+ecx-1] - std - rep movsb - cld - - .done: - pop edi - pop esi - ret - -global memcmp -memcmp: - push esi - push edi - mov edi, dword [esp+12] - mov esi, dword [esp+16] - mov ecx, dword [esp+20] - repe cmpsb - jecxz .equal - mov al, byte [edi-1] - sub al, byte [esi-1] - movsx eax, al - jmp .done - - .equal: - mov eax, ecx - - .done: - pop edi - pop esi - ret diff --git a/stage23/lib/config.c b/stage23/lib/config.c index c9c7fa9b..f4d1bc05 100644 --- a/stage23/lib/config.c +++ b/stage23/lib/config.c @@ -34,6 +34,7 @@ int init_config_disk(struct volume *part) { return init_config(config_size); } +#if defined (bios) int init_config_pxe(void) { struct tftp_file_handle cfg; if (tftp_open(&cfg, 0, 69, "limine.cfg") @@ -47,6 +48,7 @@ int init_config_pxe(void) { return init_config(cfg.file_size); } +#endif #define NOT_CHILD (-1) #define DIRECT_CHILD 0 diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c index f4c52b9c..b8b60d7d 100644 --- a/stage23/lib/elf.c +++ b/stage23/lib/elf.c @@ -311,16 +311,16 @@ int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *top, uin memmap_alloc_range((size_t)load_vaddr, (size_t)phdr.p_memsz, alloc_type, true, true); - fread(fd, (void *)(uint32_t)load_vaddr, phdr.p_offset, phdr.p_filesz); + fread(fd, (void *)(uintptr_t)load_vaddr, phdr.p_offset, phdr.p_filesz); size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz); if (to_zero) { - void *ptr = (void *)(uint32_t)(load_vaddr + phdr.p_filesz); + void *ptr = (void *)(uintptr_t)(load_vaddr + phdr.p_filesz); memset(ptr, 0, to_zero); } - if (elf64_apply_relocations(fd, &hdr, (void *)(uint32_t)load_vaddr, phdr.p_vaddr, phdr.p_memsz, slide)) + if (elf64_apply_relocations(fd, &hdr, (void *)(uintptr_t)load_vaddr, phdr.p_vaddr, phdr.p_memsz, slide)) return -1; } @@ -364,12 +364,12 @@ int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t *top, uin memmap_alloc_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz, alloc_type, true, true); - fread(fd, (void *)phdr.p_paddr, phdr.p_offset, phdr.p_filesz); + fread(fd, (void *)(uintptr_t)phdr.p_paddr, phdr.p_offset, phdr.p_filesz); size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz); if (to_zero) { - void *ptr = (void *)(phdr.p_paddr + phdr.p_filesz); + void *ptr = (void *)(uintptr_t)(phdr.p_paddr + phdr.p_filesz); memset(ptr, 0, to_zero); } } diff --git a/stage23/lib/fb.c b/stage23/lib/fb.c index 23a424b0..82ba9280 100644 --- a/stage23/lib/fb.c +++ b/stage23/lib/fb.c @@ -2,8 +2,13 @@ #include #include #include +#include bool fb_init(struct fb_info *ret, uint16_t target_width, uint16_t target_height, uint16_t target_bpp) { +#if defined (bios) return init_vbe(ret, target_width, target_height, target_bpp); +#elif defined (uefi) + return init_gop(ret, target_width, target_height, target_bpp); +#endif } diff --git a/stage23/lib/gterm.c b/stage23/lib/gterm.c index 2ef88ce5..c5798fae 100644 --- a/stage23/lib/gterm.c +++ b/stage23/lib/gterm.c @@ -363,7 +363,7 @@ bool gterm_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, int _ma || fbinfo.blue_mask_shift != 0) return false; - gterm_framebuffer = (void *)fbinfo.framebuffer_addr; + gterm_framebuffer = (void *)(uintptr_t)fbinfo.framebuffer_addr; gterm_width = fbinfo.framebuffer_width; gterm_height = fbinfo.framebuffer_height; gterm_bpp = fbinfo.framebuffer_bpp; diff --git a/stage23/lib/libc.s2.c b/stage23/lib/libc.s2.c index 56854437..3b378523 100644 --- a/stage23/lib/libc.s2.c +++ b/stage23/lib/libc.s2.c @@ -19,6 +19,56 @@ int tolower(int c) { return c; } +void *memcpy(void *dest, const void *src, size_t n) { + uint8_t *pdest = dest; + const uint8_t *psrc = src; + + for (size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + + return dest; +} + +void *memset(void *s, int c, size_t n) { + uint8_t *p = s; + + for (size_t i = 0; i < n; i++) { + p[i] = (uint8_t)c; + } + + return s; +} + +void *memmove(void *dest, const void *src, size_t n) { + uint8_t *pdest = dest; + const uint8_t *psrc = src; + + if (src > dest) { + for (size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + } else if (src < dest) { + for (size_t i = n; i > 0; i--) { + pdest[i-1] = psrc[i-1]; + } + } + + return dest; +} + +int memcmp(const void *s1, const void *s2, size_t n) { + const uint8_t *p1 = s1; + const uint8_t *p2 = s2; + + for (size_t i = 0; i < n; i++) { + if (p1[i] != p2[i]) + return p1[i] < p2[i] ? -1 : 1; + } + + return 0; +} + char *strcpy(char *dest, const char *src) { size_t i; diff --git a/stage23/lib/panic.s2.c b/stage23/lib/panic.s2.c index d86b4e5f..fbb58eb3 100644 --- a/stage23/lib/panic.s2.c +++ b/stage23/lib/panic.s2.c @@ -17,5 +17,9 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) { print("\n"); print_stacktrace(NULL); +#if defined (bios) rm_hcf(); +#elif defined (uefi) + for (;;) asm ("hlt"); +#endif } diff --git a/stage23/lib/part.h b/stage23/lib/part.h index 38dfbc7f..9243f51b 100644 --- a/stage23/lib/part.h +++ b/stage23/lib/part.h @@ -4,13 +4,22 @@ #include #include #include +#if defined (uefi) +# include +#endif #define NO_PARTITION (-1) #define INVALID_TABLE (-2) #define END_OF_TABLE (-3) +#if defined (bios) +typedef int drive_t; +#elif defined (uefi) +typedef EFI_HANDLE drive_t; +#endif + struct volume { - int drive; + drive_t drive; int partition; int sector_size; uint64_t first_sect; @@ -23,9 +32,11 @@ struct volume { void volume_create_index(void); +bool gpt_get_guid(struct guid *guid, struct volume *volume); + int part_get(struct volume *part, struct volume *volume, int partition); bool volume_get_by_guid(struct volume *part, struct guid *guid); -bool volume_get_by_coord(struct volume *part, int drive, int partition); +bool volume_get_by_coord(struct volume *part, drive_t drive, int partition); int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count); diff --git a/stage23/lib/part.s2.c b/stage23/lib/part.s2.c index 4ef76441..17af8d3e 100644 --- a/stage23/lib/part.s2.c +++ b/stage23/lib/part.s2.c @@ -1,14 +1,26 @@ #include #include #include -#include +#if defined (bios) +# include +#include +#endif #include #include -#include #include #include #include +size_t volume_get_sector_size(struct volume *volume) { +#if defined (bios) + return disk_get_sector_size(volume->drive); +#elif defined (uefi) + (void)volume; + return -1; +#endif + +} + struct gpt_table_header { // the head char signature[8]; @@ -46,10 +58,10 @@ struct gpt_entry { uint16_t partition_name[36]; } __attribute__((packed)); -static bool gpt_get_guid(struct guid *guid, struct volume *volume) { +bool gpt_get_guid(struct guid *guid, struct volume *volume) { struct gpt_table_header header = {0}; - int sector_size = disk_get_sector_size(volume->drive); + int sector_size = volume_get_sector_size(volume); // read header, located after the first block volume_read(volume, &header, sector_size * 1, sizeof(header)); @@ -69,7 +81,7 @@ static bool gpt_get_guid(struct guid *guid, struct volume *volume) { static int gpt_get_part(struct volume *ret, struct volume *volume, int partition) { struct gpt_table_header header = {0}; - int sector_size = disk_get_sector_size(volume->drive); + int sector_size = volume_get_sector_size(volume); // read header, located after the first block volume_read(volume, &header, sector_size * 1, sizeof(header)); @@ -155,7 +167,7 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part ret->drive = extended_part->drive; ret->partition = partition + 4; - ret->sector_size = disk_get_sector_size(extended_part->drive); + ret->sector_size = volume_get_sector_size(extended_part); ret->first_sect = extended_part->first_sect + ebr_sector + entry.first_sect; ret->sect_count = entry.sect_count; @@ -174,7 +186,7 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part static int mbr_get_part(struct volume *ret, struct volume *volume, int partition) { // Check if actually valid mbr - uint16_t hint; + uint16_t hint = 0; volume_read(volume, &hint, 444, sizeof(uint16_t)); if (hint && hint != 0x5a5a) return INVALID_TABLE; @@ -196,7 +208,7 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition extended_part.drive = volume->drive; extended_part.partition = i; - extended_part.sector_size = disk_get_sector_size(volume->drive); + extended_part.sector_size = volume_get_sector_size(volume); extended_part.first_sect = entry.first_sect; extended_part.sect_count = entry.sect_count; @@ -217,7 +229,7 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition ret->drive = volume->drive; ret->partition = partition; - ret->sector_size = disk_get_sector_size(volume->drive); + ret->sector_size = volume_get_sector_size(volume); ret->first_sect = entry.first_sect; ret->sect_count = entry.sect_count; @@ -252,92 +264,11 @@ static struct volume *volume_index = NULL; static size_t volume_index_i = 0; void volume_create_index(void) { - size_t volume_count = 0; +#if defined (bios) + volume_index_i = disk_create_index(&volume_index); +#elif defined (uefi) - for (uint8_t drive = 0x80; drive; drive++) { - struct rm_regs r = {0}; - struct bios_drive_params drive_params; - - r.eax = 0x4800; - r.edx = drive; - r.ds = rm_seg(&drive_params); - r.esi = rm_off(&drive_params); - - drive_params.buf_size = sizeof(struct bios_drive_params); - - rm_int(0x13, &r, &r); - - if (r.eflags & EFLAGS_CF) - continue; - - print("Found BIOS drive %x\n", drive); - print(" ... %X total %u-byte sectors\n", - drive_params.lba_count, drive_params.bytes_per_sect); - - volume_count++; - - struct volume block; - - block.drive = drive; - block.sector_size = drive_params.bytes_per_sect; - block.first_sect = 0; - block.sect_count = drive_params.lba_count; - - for (int part = 0; ; part++) { - struct volume p; - int ret = part_get(&p, &block, part); - - if (ret == END_OF_TABLE || ret == INVALID_TABLE) - break; - if (ret == NO_PARTITION) - continue; - - volume_count++; - } - } - - volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count); - - for (uint8_t drive = 0x80; drive; drive++) { - struct rm_regs r = {0}; - struct bios_drive_params drive_params; - - r.eax = 0x4800; - r.edx = drive; - r.ds = rm_seg(&drive_params); - r.esi = rm_off(&drive_params); - - drive_params.buf_size = sizeof(struct bios_drive_params); - - rm_int(0x13, &r, &r); - - if (r.eflags & EFLAGS_CF) - continue; - - struct volume *block = &volume_index[volume_index_i++]; - - block->drive = drive; - block->partition = -1; - block->sector_size = drive_params.bytes_per_sect; - block->first_sect = 0; - block->sect_count = drive_params.lba_count; - - if (gpt_get_guid(&block->guid, block)) { - block->guid_valid = true; - } - - for (int part = 0; ; part++) { - struct volume p; - int ret = part_get(&p, block, part); - - if (ret == END_OF_TABLE || ret == INVALID_TABLE) - break; - if (ret == NO_PARTITION) - continue; - - volume_index[volume_index_i++] = p; - } - } +#endif } bool volume_get_by_guid(struct volume *part, struct guid *guid) { @@ -358,7 +289,7 @@ found: return true; } -bool volume_get_by_coord(struct volume *part, int drive, int partition) { +bool volume_get_by_coord(struct volume *part, drive_t drive, int partition) { size_t i; for (i = 0; i < volume_index_i; i++) { if (volume_index[i].drive == drive @@ -373,6 +304,11 @@ found: } int volume_read(struct volume *part, void *buffer, uint64_t loc, uint64_t count) { +#if defined (bios) return disk_read(part->drive, buffer, loc + (part->first_sect * part->sector_size), count); +#elif defined (uefi) + (void)part; (void)buffer; (void)loc; (void)count; + return -1; +#endif } diff --git a/stage23/lib/readline.c b/stage23/lib/readline.c index 42713d90..8b7b5a6d 100644 --- a/stage23/lib/readline.c +++ b/stage23/lib/readline.c @@ -4,10 +4,14 @@ #include #include #include -#include +#if defined (bios) +# include +#elif defined (uefi) +# include +#endif -int getchar_internal(uint32_t eax) { - switch ((eax >> 8) & 0xff) { +int getchar_internal(uint8_t scancode, uint8_t ascii) { + switch (scancode) { case 0x44: return GETCHAR_F10; case 0x4b: @@ -29,19 +33,33 @@ int getchar_internal(uint32_t eax) { case 0x51: return GETCHAR_PGDOWN; } - char c = eax & 0xff; - switch (c) { + switch (ascii) { case '\r': return '\n'; } - return c; + return ascii; } +#if defined (bios) int getchar(void) { struct rm_regs r = {0}; rm_int(0x16, &r, &r); - return getchar_internal(r.eax); + return getchar_internal((r.eax >> 8) & 0xff, r.eax); } +#endif + +#if defined (uefi) +int getchar(void) { + EFI_INPUT_KEY key = {0}; + uefi_call_wrapper(gST->ConIn->ReadKeyStroke, 2, gST->ConIn, &key); + return getchar_internal(key.ScanCode, key.UnicodeChar); +} + +int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks) { + (void)pit_ticks; + return getchar(); +} +#endif static void reprint_string(int x, int y, const char *s) { int orig_x, orig_y; diff --git a/stage23/lib/term.c b/stage23/lib/term.c index 441c924b..dbe0d832 100644 --- a/stage23/lib/term.c +++ b/stage23/lib/term.c @@ -10,8 +10,10 @@ void term_vbe(uint32_t *colours, int margin, int margin_gradient, struct image * term_deinit(); if (!gterm_init(&term_rows, &term_cols, colours, margin, margin_gradient, background)) { +#if defined (bios) // Failed to set VBE properly, default to text mode term_textmode(); +#endif return; } diff --git a/stage23/lib/term.s2.c b/stage23/lib/term.s2.c index 2058deba..469fafe0 100644 --- a/stage23/lib/term.s2.c +++ b/stage23/lib/term.s2.c @@ -23,6 +23,7 @@ void (*term_double_buffer_flush)(void); int term_rows, term_cols; +#if defined (bios) void term_textmode(void) { term_deinit(); init_vga_textmode(&term_rows, &term_cols); @@ -41,11 +42,14 @@ void term_textmode(void) { term_backend = TEXTMODE; } +#endif void term_deinit(void) { +#if defined (bios) struct rm_regs r = {0}; r.eax = 0x0003; rm_int(0x10, &r, &r); +#endif term_backend = NOT_READY; } diff --git a/stage23/lib/time.c b/stage23/lib/time.c index 7120dc95..1660c635 100644 --- a/stage23/lib/time.c +++ b/stage23/lib/time.c @@ -1,7 +1,11 @@ #include #include #include -#include +#if defined (bios) +# include +#elif defined (uefi) +# include +#endif #include // Julian date calculation from https://en.wikipedia.org/wiki/Julian_day @@ -22,6 +26,7 @@ static uint64_t get_unix_epoch(uint8_t seconds, uint8_t minutes, uint8_t hours, return (jdn_diff * (60 * 60 * 24)) + hours * 3600 + minutes * 60 + seconds; } +#if defined (bios) uint64_t time(void) { struct rm_regs r = {0}; @@ -42,3 +47,14 @@ uint64_t time(void) { return get_unix_epoch(second, minute, hour, day, month, year); } +#endif + +#if defined (uefi) +uint64_t time(void) { + EFI_TIME time; + uefi_call_wrapper(gRT->GetTime, 2, &time, NULL); + + return get_unix_epoch(time.Second, time.Minute, time.Hour, + time.Day, time.Month, time.Year); +} +#endif diff --git a/stage23/lib/trace.s2.c b/stage23/lib/trace.s2.c index 2c502949..c4bf7183 100644 --- a/stage23/lib/trace.s2.c +++ b/stage23/lib/trace.s2.c @@ -11,33 +11,41 @@ extern symbol limine_map; char *trace_address(size_t *off, size_t addr) { +#if defined (bios) if (!stage3_loaded) return NULL; +#endif - uint32_t prev_addr = 0; - char *prev_sym = NULL; + uintptr_t prev_addr = 0; + char *prev_sym = NULL; for (size_t i = 0;;) { - if (*((uint32_t *)&limine_map[i]) >= addr) { + if (*((uintptr_t *)&limine_map[i]) >= addr) { *off = addr - prev_addr; return prev_sym; } - prev_addr = *((uint32_t *)&limine_map[i]); - i += sizeof(uint32_t); + prev_addr = *((uintptr_t *)&limine_map[i]); + i += sizeof(uintptr_t); prev_sym = &limine_map[i]; while (limine_map[i++] != 0); } } void print_stacktrace(size_t *base_ptr) { +#if defined (bios) if (!stage3_loaded) { print("trace: Stack trace omitted because stage 3 was not loaded yet.\n"); return; } +#endif if (base_ptr == NULL) { asm volatile ( +#if defined (bios) "mov %0, ebp" +#elif defined (uefi) + "mov %0, rbp" +#endif : "=g"(base_ptr) :: "memory" ); diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c index 883dc09e..d355556b 100644 --- a/stage23/lib/uri.c +++ b/stage23/lib/uri.c @@ -54,6 +54,7 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) { return true; } +#if defined (bios) // BIOS partitions are specified in the : form. // The drive may be omitted, the partition cannot. static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) { @@ -106,6 +107,7 @@ static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { return true; } +#endif static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) { struct guid guid; @@ -127,6 +129,7 @@ static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path return true; } +#if defined (bios) static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) { uint32_t ip; if (!strcmp(root, "")) { @@ -149,10 +152,13 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) { fd->size = cfg->file_size; return true; } +#endif static bool uri_boot_dispatch(struct file_handle *fd, char *s_part, char *path) { +#if defined (bios) if (booted_from_pxe) return uri_tftp_dispatch(fd, s_part, path); +#endif int partition; @@ -194,16 +200,21 @@ bool uri_open(struct file_handle *fd, char *uri) { resource++; } - if (!strcmp(resource, "bios")) { + if (0) { +#if defined (bios) + } else if (!strcmp(resource, "bios")) { ret = uri_bios_dispatch(fd, root, path); +#endif } else if (!strcmp(resource, "boot")) { ret = uri_boot_dispatch(fd, root, path); } else if (!strcmp(resource, "guid")) { ret = uri_guid_dispatch(fd, root, path); } else if (!strcmp(resource, "uuid")) { ret = uri_guid_dispatch(fd, root, path); +#if defined (bios) } else if (!strcmp(resource, "tftp")) { ret = uri_tftp_dispatch(fd, root, path); +#endif } else { panic("Resource `%s` not valid.", resource); } diff --git a/stage23/linker.ld b/stage23/linker_bios.ld similarity index 100% rename from stage23/linker.ld rename to stage23/linker_bios.ld diff --git a/stage23/linker_nomap.ld b/stage23/linker_nomap_bios.ld similarity index 100% rename from stage23/linker_nomap.ld rename to stage23/linker_nomap_bios.ld diff --git a/stage23/linker_nomap_uefi.ld b/stage23/linker_nomap_uefi.ld new file mode 100644 index 00000000..16e400d2 --- /dev/null +++ b/stage23/linker_nomap_uefi.ld @@ -0,0 +1,33 @@ +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(efi_main) + +SECTIONS +{ + . = 4K; + + .text : { + *(.text*) + } + + .data : { + *(.realmode*) + *(.data*) + } + + .rodata : { + *(.rodata*) + } + + .map : { + limine_map = .; + } + + .bss : { + *(COMMON) + *(.bss*) + } + + /DISCARD/ : { + *(*) + } +} diff --git a/stage23/linker_uefi.ld b/stage23/linker_uefi.ld new file mode 100644 index 00000000..283366d4 --- /dev/null +++ b/stage23/linker_uefi.ld @@ -0,0 +1,33 @@ +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(efi_main) + +SECTIONS +{ + . = 4K; + + .text : { + *(.text*) + } + + .data : { + *(.realmode*) + *(.data*) + } + + .rodata : { + *(.rodata*) + } + + .map : { + *(.map*) + } + + .bss : { + *(COMMON) + *(.bss*) + } + + /DISCARD/ : { + *(*) + } +} diff --git a/stage23/mm/mtrr.c b/stage23/mm/mtrr.c index 34efbea4..4c900f20 100644 --- a/stage23/mm/mtrr.c +++ b/stage23/mm/mtrr.c @@ -118,7 +118,7 @@ void mtrr_save(void) { uint8_t var_reg_count = ia32_mtrrcap & 0xff; if (!saved_mtrr) - saved_mtrr = conv_mem_alloc(var_reg_count * sizeof(struct mtrr)); + saved_mtrr = ext_mem_alloc(var_reg_count * sizeof(struct mtrr)); for (uint8_t i = 0; i < var_reg_count; i++) { saved_mtrr[i].base = rdmsr(0x200 + i * 2); diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c index 0cbda451..4baa5414 100644 --- a/stage23/mm/pmm.s2.c +++ b/stage23/mm/pmm.s2.c @@ -6,6 +6,9 @@ #include #include #include +#if defined (uefi) +# include +#endif #define PAGE_SIZE 4096 #define MEMMAP_BASE ((size_t)0x100000) @@ -183,6 +186,7 @@ struct e820_entry_t *get_memmap(size_t *entries) { return memmap; } +#if defined (bios) void init_memmap(void) { for (size_t i = 0; i < e820_entries; i++) { if (memmap_entries == MEMMAP_MAX_ENTRIES) { @@ -196,6 +200,7 @@ void init_memmap(void) { allocations_disallowed = false; } +#endif void *ext_mem_alloc(size_t count) { return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE); @@ -209,6 +214,7 @@ void *ext_mem_alloc_type(size_t count, uint32_t type) { return ext_mem_alloc_aligned_type(count, 4, type); } +#if defined (bios) // Allocate memory top down, hopefully without bumping into kernel or modules void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) { if (allocations_disallowed) @@ -251,6 +257,24 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) panic("High memory allocator: Out of memory"); } +#endif + +#if defined (uefi) +void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) { + (void)type; + + void *ret; + + if (alignment && alignment % 4096 == 0) { + uefi_call_wrapper(gBS->AllocatePages, 4, 0, 2, DIV_ROUNDUP(count, 4096), + &ret); + } else { + uefi_call_wrapper(gBS->AllocatePool, 3, 4, count, &ret); + } + + return ret; +} +#endif bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic) { uint64_t top = base + length; @@ -317,6 +341,7 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free return false; } +#if defined (bios) extern symbol bss_end; static size_t bump_allocator_base = (size_t)bss_end; static size_t bump_allocator_limit = 0x70000; @@ -338,3 +363,4 @@ void *conv_mem_alloc_aligned(size_t count, size_t alignment) { return ret; } +#endif diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c index 8bcc66eb..73092258 100644 --- a/stage23/protos/chainload.c +++ b/stage23/protos/chainload.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -84,3 +86,5 @@ void chainload(char *config) { spinup(drive); } + +#endif diff --git a/stage23/protos/linux.c b/stage23/protos/linux.c index 86cafdbe..5803942e 100644 --- a/stage23/protos/linux.c +++ b/stage23/protos/linux.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -194,3 +196,5 @@ void linux_load(char *config, char *cmdline) { spinup(real_mode_code_seg, kernel_entry_seg, real_mode_and_heap_size); } + +#endif diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c index a596f0bc..42a8db34 100644 --- a/stage23/protos/stivale.c +++ b/stage23/protos/stivale.c @@ -249,6 +249,7 @@ __attribute__((noreturn)) void stivale_spinup( uint64_t entry_point, void *stivale_struct, uint64_t stack) { mtrr_restore(); +#if defined (bios) 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 @@ -258,10 +259,12 @@ __attribute__((noreturn)) void stivale_spinup( r.ebx = 0x02; // Long mode only rm_int(0x15, &r, &r); } +#endif pic_mask_all(); pic_flush(); +#if defined (bios) if (bits == 64) { if (level5pg) { // Enable CR4.LA57 @@ -367,5 +370,11 @@ __attribute__((noreturn)) void stivale_spinup( : "memory" ); } +#elif defined (uefi) + (void)bits; (void)level5pg; (void)pagemap; (void)entry_point; + (void)stivale_struct; (void)stack; + +#endif + for (;;); } diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c index a2129035..ed0e0be7 100644 --- a/stage23/protos/stivale2.c +++ b/stage23/protos/stivale2.c @@ -327,6 +327,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe) { } } +#if defined (bios) ////////////////////////////////////////////// // Create PXE struct tag ////////////////////////////////////////////// @@ -336,7 +337,11 @@ void stivale2_load(char *config, char *cmdline, bool pxe) { tag->server_ip = get_boot_server_info(); append_tag(&stivale2_struct, (struct stivale2_tag *)tag); } +#else + (void)pxe; +#endif +#if defined (bios) ////////////////////////////////////////////// // Create memmap struct tag ////////////////////////////////////////////// @@ -356,6 +361,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe) { append_tag(&stivale2_struct, (struct stivale2_tag *)tag); } +#endif ////////////////////////////////////////////// // List tags diff --git a/stage23/pxe/pxe.c b/stage23/pxe/pxe.c index e3b5051e..60070f48 100644 --- a/stage23/pxe/pxe.c +++ b/stage23/pxe/pxe.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -41,3 +43,5 @@ void pxe_init(void) { set_pxe_fp(bangpxe->rm_entry); print("Successfully initialized pxe"); } + +#endif diff --git a/stage23/pxe/tftp.c b/stage23/pxe/tftp.c index 51693506..aab56e94 100644 --- a/stage23/pxe/tftp.c +++ b/stage23/pxe/tftp.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -23,13 +25,13 @@ int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t serv struct bootph *ph = (struct bootph*)(void *) (((((uint32_t)cachedinfo.buffer) >> 16) << 4) + (((uint32_t)cachedinfo.buffer) & 0xFFFF)); server_ip = ph->sip; } - + struct PXENV_UNDI_GET_INFORMATION undi_info = { 0 }; ret = pxe_call(UNDI_GET_INFORMATION, ((uint16_t)rm_seg(&undi_info)), (uint16_t)rm_off(&undi_info)); if (ret) { return -1; } - + //TODO figure out a more proper way to do this. uint16_t mtu = undi_info.MaxTranUnit - 48; @@ -106,3 +108,5 @@ int tftp_read(void* fd, void *buf, uint64_t loc, uint64_t count) { memcpy(buf, handle->data + loc, count); return 0; } + +#endif diff --git a/stage23/sys/a20.s2.c b/stage23/sys/a20.s2.c index 571f7d6c..e3e1f8c2 100644 --- a/stage23/sys/a20.s2.c +++ b/stage23/sys/a20.s2.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -52,3 +54,5 @@ bool a20_enable(void) { return false; } + +#endif diff --git a/stage23/sys/e820.s2.c b/stage23/sys/e820.s2.c index c275be26..3fe10629 100644 --- a/stage23/sys/e820.s2.c +++ b/stage23/sys/e820.s2.c @@ -1,3 +1,5 @@ +#if defined (bios) + #include #include #include @@ -43,3 +45,5 @@ load_up: e820_map = conv_mem_alloc(sizeof(struct e820_entry_t) * e820_entries); goto load_up; } + +#endif diff --git a/stage23/sys/smp.c b/stage23/sys/smp.c index 6b5d166f..322cc719 100644 --- a/stage23/sys/smp.c +++ b/stage23/sys/smp.c @@ -207,7 +207,7 @@ struct smp_information *init_smp(size_t header_hack_size, // Try to start the AP if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct, - longmode, lv5, (uint32_t)pagemap.top_level, + longmode, lv5, (uintptr_t)pagemap.top_level, x2apic)) { print("smp: FAILED to bring-up AP\n"); continue; @@ -244,7 +244,7 @@ struct smp_information *init_smp(size_t header_hack_size, // Try to start the AP if (!smp_start_ap(x2apic->x2apic_id, &gdtr, info_struct, - longmode, lv5, (uint32_t)pagemap.top_level, + longmode, lv5, (uintptr_t)pagemap.top_level, true)) { print("smp: FAILED to bring-up AP\n"); continue;