Add support for 32-bit EFI boot.

This commit is contained in:
Martin Whitaker 2020-07-08 11:07:32 +01:00
parent 9fb253b3d8
commit c089a81ed1
8 changed files with 114 additions and 18 deletions

View File

@ -206,7 +206,7 @@ static efi_status_t alloc_low_memory(void **ptr, size_t size, efi_phys_addr_t mi
status = efi_call_bs(allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, num_pages, &start);
if (status == EFI_SUCCESS) {
*ptr = (void *)start;
*ptr = (void *)(uintptr_t)start;
efi_call_bs(free_pool, mem_map);
return EFI_SUCCESS;
}

View File

@ -124,7 +124,7 @@ optional_header:
.long 0 # SizeOfInitializedData
.long 0 # SizeOfUninitializedData
.long BASE_OF_CODE + 0x100 # AddressOfEntryPoint
.long BASE_OF_CODE + 0x1e0 # AddressOfEntryPoint
.long BASE_OF_CODE # BaseOfCode
#ifndef __x86_64__

View File

@ -77,7 +77,7 @@ xload_flags:
#ifdef __x86_64__
.word 0x9 # XLF_KERNEL_64,XLF_EFI_HANDOVER_64
#else
.word 0
.word 0x4 # XLF_EFI_HANDOVER_32
#endif
cmd_line_size:
.long 255

View File

@ -3,7 +3,8 @@
// startup32.S contains the 32-bit startup code for both the BSP and APs.
// It initialises stacks, memory management, and exception handling, clears
// the BSS, completes relocation, and finally calls the main application.
// It supports the 32-bit Linux boot protocol for the first boot of the BSP.
// It supports the 32-bit Linux boot protocol and EFI boot for the first
// boot of the BSP.
//
// Copyright (C) 2020 Martin Whitaker.
//
@ -30,6 +31,40 @@
startup32:
cld
cli
jmp startup
# The Linux 32-bit EFI handover point.
.org 0x10
.globl efi_handover
efi_handover:
popl %eax # the return address (discard)
popl %ecx # the EFI image handle
popl %edx # the EFI system table pointer
popl %esi # the boot params pointer
# Load the GOT pointer.
call 0f
0: popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx
# Fill out the boot params structure.
subl $12, %esp # align the stack
andl $~0xf, %esp
addl $12, %esp
pushl %esi # the boot params pointer
pushl %edx # the EFI system table pointer
pushl %ecx # the EFI image handle
call efi_setup
# Fall though to the shared 32-bit entry point with the boot
# params pointer in %esi.
movl %eax, %esi
# The 32-bit entry point for AP boot and for restart after relocation.
@ -127,10 +162,11 @@ flush: movw $KERNEL_DS, %ax
call reloc
# Disable paging (needed during restart).
# Disable paging (needed during restart). Also disable write protect
# (in case set by EFI boot).
movl %cr0, %eax
andl $0x7fffffff, %eax
andl $0x7ffeffff, %eax
movl %eax, %cr0
# Enable PAE if supported.
@ -190,6 +226,21 @@ flush: movw $KERNEL_DS, %ax
pushl $257 # vector
jmp int_handler
# The EFI PE32 boot entry point.
.org 0x1e0
.globl efi_boot
efi_boot:
popl %eax # the return address (discard)
popl %ecx # the EFI image handle
popl %edx # the EFI system table pointer
pushl $0 # the boot params pointer (0 = not yet allocated)
pushl %edx # the EFI system table pointer
pushl %ecx # the EFI image handle
call efi_handover # never returns
# Individual interrupt vector handlers. These need to be spaced equally, to
# allow the IDT initialisation loop above to work, so we use noops to pad out
# where required.

View File

@ -105,7 +105,7 @@ startup32:
# The EFI PE32+ boot entry point.
.org 0x100
.org 0x1e0
.globl efi_boot
efi_boot:
movq %rcx, %rdi # the EFI image handle

View File

@ -45,10 +45,11 @@ APP_OBJS = app/badram.o \
app/interrupt.o \
app/main.o
OBJS = boot/startup.o $(SYS_OBJS) $(LIB_OBJS) $(TST_OBJS) $(APP_OBJS)
OBJS = boot/startup.o boot/efisetup.o $(SYS_OBJS) $(LIB_OBJS) $(TST_OBJS) $(APP_OBJS)
all: memtest.bin
all: memtest.bin memtest.efi
-include boot/efisetup.d
-include $(subst .o,.d,$(SYS_OBJS))
-include $(subst .o,.d,$(LIB_OBJS))
-include $(subst .o,.d,$(TST_OBJS))
@ -65,6 +66,10 @@ boot/%.s: ../boot/%.S ../boot/boot.h
@mkdir -p boot
$(CC) -m32 -E -traditional -I../boot -o $@ $<
boot/efisetup.o: ../boot/efisetup.c
@mkdir -p boot
$(CC) -c $(CFLAGS) -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
system/reloc.o: ../system/reloc32.c
@mkdir -p system
$(CC) -c $(CFLAGS) -fno-strict-aliasing -Os $(INC_DIRS) -o $@ $< -MMD -MP -MT $@ -MF $(@:.o=.d)
@ -96,16 +101,31 @@ memtest_shared.bin: memtest_shared
objcopy -O binary $< memtest_shared.bin
memtest.bin: memtest_shared.bin boot/bootsect.o boot/setup.o ldscripts/memtest_bin.lds
$(LD) -T ldscripts/memtest_bin.lds boot/bootsect.o boot/setup.o -b binary memtest_shared.bin -o memtest.bin
$(eval SIZES=$(shell size -G -d memtest_shared | grep memtest_shared))
$(LD) --defsym=_bss_size=$(word 3,$(SIZES)) -T ldscripts/memtest_bin.lds boot/bootsect.o boot/setup.o -b binary memtest_shared.bin -o memtest.bin
memtest.img: memtest.bin
dd if=/dev/zero of=memtest.img bs=1474560 count=1
dd if=memtest.bin of=memtest.img bs=1474560 conv=notrunc
memtest.efi: memtest_shared.bin boot/header.o boot/setup.o ldscripts/memtest_efi.lds
$(eval SIZES=$(shell size -G -d memtest_shared | grep memtest_shared))
$(LD) --defsym=_bss_size=$(word 3,$(SIZES)) -T ldscripts/memtest_efi.lds boot/header.o boot/setup.o -b binary memtest_shared.bin -o memtest.efi
iso: memtest.img
floppy.img: memtest.bin
dd if=/dev/zero of=floppy.img bs=1474560 count=1
dd if=memtest.bin of=floppy.img bs=1474560 conv=notrunc
esp.img: memtest.efi
@mkdir -p iso/EFI/BOOT
cp memtest.efi iso/EFI/BOOT/bootia32.efi
@rm -f esp.img
/sbin/mkdosfs -n MEMTEST-ESP -F12 -C esp.img 4096
mcopy -s -i esp.img iso/EFI ::
iso: floppy.img esp.img
@mkdir -p iso/boot
genisoimage -b memtest.img -c boot/boot.catalog -V "PCMemTest-32" -o memtest.iso iso memtest.img
@rm -rf iso
cp floppy.img iso/boot/floppy.img
xorrisofs -pad -R -J -volid PCMemTest32 -graft-points -hide-rr-moved \
-b /boot/floppy.img --efi-boot --interval:appended_partition_2:all:: \
-part_like_isohybrid -iso_mbr_part_type 0x00 -append_partition 2 0xef ./esp.img \
-o ./memtest.iso /boot=./iso/boot
clean:
rm -rf boot system lib tests app *.iso memtest* iso
rm -rf boot system lib tests app *.img *.iso memtest* iso

View File

@ -16,5 +16,5 @@ SECTIONS {
_end = . ;
}
_sys_size = (_end - _start + 15) >> 4;
_init_size = (_end - _start);
_init_size = (_end - _start) + _bss_size;
}

View File

@ -0,0 +1,25 @@
OUTPUT_FORMAT("binary")
OUTPUT_ARCH(i386)
ENTRY(boot);
SECTIONS {
. = 0;
.header : {
*(.header)
}
.setup : {
*(.setup)
}
. = ALIGN(512);
.text : {
_text_start = . ;
*(.data)
. = ALIGN(512);
_text_end = . ;
}
_text_size = (_text_end - _text_start);
_sys_size = _text_size >> 4;
_init_size = _text_size + _bss_size;
}