Initial UEFI port
This commit is contained in:
parent
a7a168a682
commit
edd4a8de60
|
@ -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
|
||||
|
|
34
Makefile
34
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __DRIVERS__DISK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <lib/part.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined(bios)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <drivers/disk.h>
|
||||
|
@ -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
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#if defined (uefi)
|
||||
|
||||
#include <efi.h>
|
||||
#include <lib/blib.h>
|
||||
#include <drivers/gop.h>
|
||||
|
||||
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
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __DRIVERS__GOP_H__
|
||||
#define __DRIVERS__GOP_H__
|
||||
|
||||
#if defined (uefi)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <efi.h>
|
||||
#include <lib/fb.h>
|
||||
|
||||
bool init_gop(struct fb_info *ret,
|
||||
uint16_t target_width, uint16_t target_height, uint16_t target_bpp);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -263,3 +265,5 @@ retry:
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -167,3 +169,5 @@ void text_putchar(uint8_t c) {
|
|||
draw_cursor();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
#include <pxe/pxe.h>
|
||||
#include <pxe/tftp.h>
|
||||
|
||||
#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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <lib/part.h>
|
||||
|
||||
struct fat32_context {
|
||||
int drive;
|
||||
struct volume part;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved_sectors;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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"
|
|
@ -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)
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
#include <lib/real.h>
|
||||
#include <fs/file.h>
|
||||
|
||||
#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};
|
||||
|
||||
|
|
|
@ -5,8 +5,18 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <fs/file.h>
|
||||
#include <lib/part.h>
|
||||
#if defined (uefi)
|
||||
# include <efi.h>
|
||||
#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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
#include <stdbool.h>
|
||||
#include <lib/fb.h>
|
||||
#include <drivers/vbe.h>
|
||||
#include <drivers/gop.h>
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -4,13 +4,22 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <lib/guid.h>
|
||||
#if defined (uefi)
|
||||
# include <efi.h>
|
||||
#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);
|
||||
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/part.h>
|
||||
#include <drivers/disk.h>
|
||||
#if defined (bios)
|
||||
# include <drivers/disk.h>
|
||||
#include <lib/real.h>
|
||||
#endif
|
||||
#include <lib/libc.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/real.h>
|
||||
#include <lib/print.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <fs/file.h>
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
#include <lib/libc.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/term.h>
|
||||
#include <lib/real.h>
|
||||
#if defined (bios)
|
||||
# include <lib/real.h>
|
||||
#elif defined (uefi)
|
||||
# include <efi.h>
|
||||
#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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/time.h>
|
||||
#include <lib/real.h>
|
||||
#if defined (bios)
|
||||
# include <lib/real.h>
|
||||
#elif defined (uefi)
|
||||
# include <efi.h>
|
||||
#endif
|
||||
#include <lib/blib.h>
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
|
|
@ -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 <BIOS drive>:<partition> 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);
|
||||
}
|
||||
|
|
|
@ -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/ : {
|
||||
*(*)
|
||||
}
|
||||
}
|
|
@ -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/ : {
|
||||
*(*)
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include <lib/blib.h>
|
||||
#include <lib/libc.h>
|
||||
#include <lib/print.h>
|
||||
#if defined (uefi)
|
||||
# include <efi.h>
|
||||
#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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <protos/chainload.h>
|
||||
|
@ -84,3 +86,5 @@ void chainload(char *config) {
|
|||
|
||||
spinup(drive);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <protos/linux.h>
|
||||
|
@ -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
|
||||
|
|
|
@ -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 (;;);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <lib/print.h>
|
||||
#include <lib/real.h>
|
||||
#include <pxe/pxe.h>
|
||||
|
@ -41,3 +43,5 @@ void pxe_init(void) {
|
|||
set_pxe_fp(bangpxe->rm_entry);
|
||||
print("Successfully initialized pxe");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <pxe/tftp.h>
|
||||
#include <pxe/pxe.h>
|
||||
#include <lib/real.h>
|
||||
|
@ -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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -52,3 +54,5 @@ bool a20_enable(void) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#if defined (bios)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/e820.h>
|
||||
|
@ -43,3 +45,5 @@ load_up:
|
|||
e820_map = conv_mem_alloc(sizeof(struct e820_entry_t) * e820_entries);
|
||||
goto load_up;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue