Simplify EFI stub generation
authorJack Miller <jack@codezen.org>
Tue, 20 Sep 2016 05:42:30 +0000 (00:42 -0500)
committerJack Miller <jack@codezen.org>
Tue, 20 Sep 2016 05:42:30 +0000 (00:42 -0500)
TIL about ld -R with which another binary can be used as a symbol
reference. This lets us directly embed the proper information in the
header and directly reference kernel memory addresses in the EFI stub,
which completely obviates the need for the fixup_stub* shenanigans.

Also migrates the stub code to gettin processed by cpp.

Makefile
TODO
asm/efi.asm-bin [new file with mode: 0644]
asm/head.asm
boot/efi.asm [deleted file]
boot/fixup_stub.c [deleted file]
boot/fixup_stub.sh [deleted file]
boot/grub_sig.c [deleted file]
kernel/grub_sig.c [new file with mode: 0644]

index b51f198..521bd5c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 CC = gcc
 LD = ld
-CPP=cpp
-AS=as
+CPP = cpp
+AS = as
 
 MAJOR=0
 MINOR=1
@@ -15,13 +15,10 @@ CFLAGS = ${CPPFLAGS} -c -std=gnu99 -pedantic -Wall -nostdlib -ffreestanding -mcm
 LDFLAGS = -T linker.ld -nostdlib -n
 ASFLAGS =
 
-SRC_C = $(wildcard boot/grub_sig.c kernel/*.c kernel/platforms/*.c kernel/platforms/*/*.c mm/*.c vua/*.c)
+SRC_C = $(wildcard kernel/*.c kernel/platforms/*.c kernel/platforms/*/*.c mm/*.c vua/*.c)
 OBJ_C = ${SRC_C:.c=.o}
 
-BIN_ASM = $(wildcard asm/*.asm-bin)
 SRC_ASM = $(wildcard asm/*.asm kernel/platforms/efi/*.asm)
-
-BIN_OBJ = ${BIN_ASM:.asm-bin=.bin}
 OBJ_ASM = ${SRC_ASM:.asm=.o}
 
 SRC = ${SRC_C} ${SRC_ASM}
@@ -33,30 +30,38 @@ all: viridis-efi
        @echo CC $<
        @${CC} ${CFLAGS} $< -o $@
 
-%.bin : %.asm-bin
+asm/realmode.bin : asm/realmode.asm-bin
+       @echo AS bin $<
+       @${CPP} ${CPPFLAGS} -D__ASSEMBLY__ $< > $@.tmp
+       @${AS} ${ASFLAGS} $@.tmp -o $@.o
+       @${LD} -Ttext 0x2000 --oformat binary -o $@ $@.o
+       @rm $@.tmp $@.o
+
+asm/efi.bin : asm/efi.asm-bin
        @echo AS bin $<
        @${CPP} ${CPPFLAGS} -D__ASSEMBLY__ $< > $@.tmp
        @${AS} ${ASFLAGS} $@.tmp -o $@.o
-       @ld -Ttext 0x2000 --oformat binary -o $@ $@.o
+       @${LD} -Ttext 0x0 --oformat binary -o $@ $@.o -R viridis
        @rm $@.tmp $@.o
 
-%.o : %.asm ${BIN_OBJ}
+%.o : %.asm
        @echo AS $<
        @${CPP} ${CPPFLAGS} -D__ASSEMBLY__ $< > $@.tmp
        @${AS} ${ASFLAGS} $@.tmp -o $@
        @rm $@.tmp
 
-viridis: ${OBJ} linker.ld
+viridis: asm/realmode.bin ${OBJ} linker.ld
        @echo CC -o $@
        @${LD} ${LDFLAGS} -o viridis ${OBJ}
 
-viridis-efi: viridis
-       @echo EFISTUB -o $@
-       @boot/fixup_stub.sh
+viridis-efi: viridis asm/efi.bin
+       @echo EFI STUB $<
+       @objcopy -O binary viridis viridis.bin
+       @cat asm/efi.bin viridis.bin > viridis.efi
 
 clean-most:
        @echo cleaning
-       @rm -f ${BIN_OBJ} ${OBJ}
+       @rm -f ${BIN_OBJ} ${OBJ} asm/*.bin viridis.bin
 
 clean: clean-most
        @rm -f viridis viridis.efi
diff --git a/TODO b/TODO
index 0dba91b..76b4878 100644 (file)
--- a/TODO
+++ b/TODO
@@ -25,12 +25,6 @@ would effectively amount to "support all hardware" which goes without saying.
 - Objcache won't automatically free memory back to the page allocators when all
   of the objects have been freed. Currently, will only release on destroy().
 
-= EFI =
-
-- the EFI stub copies out the GOP information to a hard-coded offset, that
-  should instead be derived from sizeof(boot_header). More generally, we
-  should get a common header for the stub.
-
 = Vua (aside from being incomplete) =
 
 - Hex and decimal embedded escapes in the string lexer
diff --git a/asm/efi.asm-bin b/asm/efi.asm-bin
new file mode 100644 (file)
index 0000000..6cd2d9f
--- /dev/null
@@ -0,0 +1,408 @@
+// This PE header is hard coded here, and then fixed up later
+
+// Most of this taken from Linux's arch/x86/boot/header.S CONFIG_EFI_STUB code
+// UEFI spec 2.6 defines most of the special values in section 2.2.1
+
+#include <memmap.h>
+
+#define HEADER_SIZE         2048 // size of this file
+#define EXC_HEADER_SIZE     512  // size of the PE header
+
+#define RELOC_SIZE          0x20
+#define RELOC_ADDR          (HEADER_SIZE - RELOC_SIZE)
+
+#define SETUP_ADDR          EXC_HEADER_SIZE
+#define SETUP_ENTRY         SETUP_ADDR
+#define SETUP_SIZE          ((HEADER_SIZE - EXC_HEADER_SIZE) - RELOC_SIZE)
+
+#define BSS_ADDR            (HEADER_SIZE + kernel_size)
+#define BSS_SIZE            1024
+
+.code64
+.org 0
+
+// This isn't used, but it shuts up ld
+.global _start
+_start:
+
+    .byte 0x4d         // MZ - MS-DOS header
+    .byte 0x5a
+
+    .org 0x3c
+    .long pe_header
+
+pe_header:
+    .ascii "PE"
+    .word 0
+
+coff_header:
+    .word 0x8664       // x86-64 (UEFI spec)
+    .word 4            // nr_sections
+    .long 0            // TimeDateStamp
+    .long 0            // PointerToSymbolTable
+    .long 1            // NumberOfSymbols
+
+    .word section_table - optional_header  // SizeOfOptionalHeader
+
+    .word 0x206        //Characteristics
+                       //IMAGE_FILE_DEBUG_STRIPPED |
+                       //IMAGE_FILE_EXECUTABLE_IMAGE |
+                       //IMAGE_FILE_LINE_NUMS_STRIPPED
+                     
+optional_header:
+    .word 0x20b        // PE32+
+    .byte 0x02         // MajorLinkerVersion
+    .byte 0x14         // MinorLinkerVersion
+
+size_of_code:
+    .long kernel_size  // SizeOfCode fill:0x1c
+
+    .long 0            // SizeOfInitializedData
+    .long 0            // SizeOfUninitializedData
+
+    .long SETUP_ENTRY  // AddressOfEntryPoint
+    .long 0x200        // BaseOfCode
+
+extra_header_fields:
+    .quad 0            // ImageBase
+    .long 0x20         // SectionAlignment (CONFIG_PHYSICAL_ALIGN on Linux)
+    .long 0x20         // FileAlignment
+    .word 0            // MajorOperatingSystemVersion
+    .word 0            // MinorOperatingSystemVersion
+    .word 0            // MajorImageVersion
+    .word 0            // MinorImageVersion
+    .word 0            // MajorSubsystemVersion
+    .word 0            // MinorSubsystemVersion
+    .long 0            // Win32VersionValue
+
+    .long (HEADER_SIZE + kernel_size + BSS_SIZE) // SizeOfImage
+
+    .long 0x200        // SizeOfHeaders
+    .long 0            // CheckSum
+    .word 0xa          // Subsystem (EFI application)
+    .word 0            // DllCharacteristics
+
+    .quad 0            // SizeOfStackReserve
+    .quad 0            // SizeOfStackCommit
+    .quad 0            // SizeOfHeapReserve
+    .quad 0            // SizeOfHeapCommit
+
+    .long 0            // LoaderFlags
+    .long 0x6          // NumberOfRvaAndSizes
+    
+    .quad 0            // ExportTable
+    .quad 0            // ImportTable
+    .quad 0            // ResourceTable
+    .quad 0            // ExceptionTable
+    .quad 0            // CertificationTable
+    .quad 0            // BaseRelocationTable
+
+section_table:
+    .ascii ".setup"
+    .byte 0
+    .byte 0            // -- end of name --
+    .long SETUP_SIZE
+    .long SETUP_ADDR
+    .long SETUP_SIZE
+    .long SETUP_ADDR
+    .long 0            // PointerToRelocations
+    .long 0            // PointerToLineNumbers
+    .word 0            // NumberOfRelocations
+    .word 0            // NumberOfLineNumbers
+    .long 0x60500020   // Characteristics
+
+    .ascii ".reloc"
+    .byte 0
+    .byte 0            // -- end of name --
+    .long RELOC_SIZE
+    .long RELOC_ADDR
+    .long RELOC_SIZE
+    .long RELOC_ADDR
+    .long 0            // PointerToRelocations
+    .long 0            // PointerToLineNumbers
+    .word 0            // NumberOfRelocations
+    .word 0            // NumberOfLineNumbers
+    .long 0x42100040   // Characteristics
+
+    .ascii ".text"
+    .byte 0
+    .byte 0
+    .byte 0            // -- end of name --
+    .long kernel_size
+    .long HEADER_SIZE
+    .long kernel_size
+    .long HEADER_SIZE  // SizeOfRawData
+    .long 0            // PointerToRelocations
+    .long 0            // PointerToLineNumbers
+    .word 0            // NumberOfRelocations
+    .word 0            // NumberOfLineNumbers
+    .long 0x60500020   // Characteristics
+
+    .ascii ".bss"
+    .byte 0
+    .byte 0
+    .byte 0
+    .byte 0            // -- end name --
+    .long BSS_SIZE
+    .long BSS_ADDR
+    .long 0            // SizeOfRawData
+    .long 0            // PointerToRawData
+    .long 0            // PointerToRelocations
+    .long 0            // PointerToLineNumbers
+    .word 0            // NumberOfRelocations
+    .word 0            // NumberOfLineNumbers
+    .long 0x60500020   // Characteristics
+
+// Push to 510 (Linux's build.c requires this, but necessary for EFI only boot?)
+// either way, we need to know exactly where start is in the binary anyway.
+
+.org 510
+.word 0xAA55
+
+// EFI handoff (from UEFI 2.6 sec 2.3.4)
+// We're in long mode, all memory is identity mapped
+// We have a large amount of stack (>=128k)
+
+// RCX - EFI_HANDLE
+// RDX - EFI_SYSTEM_TABLE pointer
+// RSP - Return address
+
+// EFI call
+// Args: RCX, RDX, R8, R9 > stack (+32 because you must reserve stack space for register args)
+// RAX is returned
+// RBX, RBP, RDI, RSI, R12-15 are preserved by calls
+//
+// EFI table header (24 bytes)
+// u64 signature
+// u32 revision
+// u32 header_size
+// u32 crc32
+// u32 reserved
+
+//EFI system table
+// header
+// char *firmware_vendor;            24
+// u32 firmware_revision             32 <-- padded to align next val
+// u64 console_in_handle             40
+// efi_simple_text_input *func       48
+// u64 console_out_handle            56
+// efi_simple_text_output *stdout    64
+// u64 standard_error_handle         72
+// efi_simple_text_output *stderr    80
+// runtime_services *                88
+// boot_services *                   96
+// u64 number of entries             104
+// efi_configuration_table *         112
+
+//console out
+// reset                             0
+// output_string                     8
+
+//EFI boot services table
+// header
+// efi_raise_tpl *                   24
+// efi_restore_tpl *                 32
+// efi_allocate_pages *              40
+// efi_free_pages *                  48
+// efi_get_memory_map *              56
+// ...
+// handle_protocol                   152
+// ...
+// locate_handle                     176
+// ...
+// efi_exit_boot_services *          232
+// efi_get_monotonic_count *         240
+// efi_stall *                       248
+// efi_set_watchdog_timer            256
+
+.extern kernel_start
+.extern efi_entry
+.extern efi_gop_mode_phys
+
+start:
+    cli
+    call next           // This puts our return address on the stack so we
+                        // can figure out where we are.
+next:
+    mov (%rsp), %r12    // R12 = address of next in EFI
+    sub $(next), %r12   // R12 = offset from where we think we are
+
+    mov 64(%rdx), %r13  // R13 = simple text output ptr
+    mov %rdx, %r14      // R14 = copy of EFI_SYSTEM_TABLE
+    mov %rcx, %rsi      // RSI = copy of EFI_HANDLE
+
+    mov (%r13), %rbx    // Reset
+    mov %r13, %rcx
+    mov $1, %rdx
+    call *%rbx          // Reset the screen()
+
+    mov 8(%r13), %rbx   // Output String
+    mov %r13, %rcx
+    mov $(banner), %rdx
+    add %r12, %rdx
+    call *%rbx          // Print our banner
+
+    mov 96(%r14), %r13  // R13 = boot services
+    mov 40(%r13), %rbx  // allocate_pages
+    mov $2, %rcx        // AllocateAddress
+    mov $2, %rdx        // EFILoaderData
+
+    mov $(size_of_code), %rax
+    add %r12, %rax
+    mov (%eax), %r8     // R8 = size of code declared in header
+
+    add $6655, %r8      // -1536 for ignoring setup code
+                        // +4096 for mmap  page
+                        // +4095 for rounding page up
+
+    shr $12, %r8        // R8 = num pages from end of EFI header to end of kernel
+    mov %r8, %r15       // save it off so we can use it for the copy
+
+    mov $(kernel_start), %rdi
+    and $(~VIRT_BASE), %rdi
+    call *%rbx
+
+    mov %rdi, %rcx      // RCX = Start of copy dest
+    mov $(payload_data), %rax
+    add %r12, %rax      // RAX = Start of copy source
+
+    shl $12, %r15
+    add %rdi, %r15      // R15 = End of copy dest
+
+cp_loop:
+    mov (%rax), %rbx
+    mov %rbx, (%rcx)
+    add $8, %rax
+    add $8, %rcx
+    cmp %rcx, %r15
+    jne cp_loop
+
+    sub $4096, %rcx     // RCX = Address of extra page and mmap maxsize address
+    mov %rcx, %r15      // R15 = Copy of memory map header address
+    mov $0, %rdi        // Clear RDI, used to indicate whether video info is inited
+
+    // Eventually, we'll use this extra page to hold the memory map, for now
+    // use it as a scratch buffer to locate a framebuffer
+
+    mov 176(%r13), %rbx     // LocateHandle
+    mov $2, %rcx            // RCX = Search by protocol
+
+    mov $(gop_guid), %rdx   // RDX = GOP GUID
+    add %r12, %rdx
+
+    mov %r15, %r9           // Size of our buffer
+    movq $4088, (%r15)      // 4096 - 8
+
+    sub $40, %rsp
+    mov %r15, 32(%rsp)
+    addq $8, 32(%rsp)       // Stack: Address of our buffer
+    call *%rbx
+    add $40, %rsp
+
+    mov (%r15), %rbx        // If the returned size is 0, no GOP
+    cmp $0, %rbx
+    je  skip_vid
+
+    mov 152(%r13), %rbx     // HandleProtocol
+    mov 8(%r15), %rcx       // Pass in first returned EFI handle
+    mov $(gop_guid), %rdx
+    add %r12, %rdx          // GOP Guid
+    mov %r15, %r8           // Beginning of page (overwriting query return)
+
+    sub $40, %rsp
+    call *%rbx
+    add $40, %rsp
+
+    // Now that we've found the interface, copy the mode and info structs
+    // to a known location after the boot header
+
+    mov (%r15), %rbx        // RBX = protocol struct
+    mov 24(%rbx), %rcx      // RCX = mode struct
+    mov 8(%rcx), %rdx       // RDX = info struct
+
+    pushq $5                // 5 qwords
+    push %rdx               // info struct
+
+    pushq $5                // 5 qwords
+    push %rcx               // mode struct
+
+    mov $2, %rcx                    // structures to copy
+    mov $(efi_gop_mode_phys), %rdx  // beginning of copy space
+
+small_copy:
+    pop %rax                // physical address
+    pop %rbx                // qwords to copy
+scl:
+    mov (%rax), %rdi
+    mov %rdi, (%rdx)
+    add $8, %rdx
+    add $8, %rax
+    sub $1, %rbx
+    cmp $0, %rbx
+    jne scl
+
+    sub $1, %rcx
+    cmp $0, %rcx
+    jne small_copy
+
+    mov $1, %rdi            // Set RDI, video info found
+
+skip_vid:
+    mov %r15, %rcx
+
+    mov 56(%r13), %rbx      // GetMemoryMap
+    movq $4064, (%rcx)      // 4096 - 32
+    mov %rcx, %r8
+    add $8, %r8             // R8 = mapkey address
+    mov %r8, %r9
+    add $8, %r9             // R9 = descriptor size address
+    mov %r9, %rdx
+    add $8, %rdx
+
+    sub $40, %rsp
+    mov %rdx, 32(%rsp)      // Stack: descriptor version address
+    add $8, %rdx            // RDX = Memory map address (after header stuff)
+    call *%rbx
+    add $40, %rsp
+
+    // We've got our memory map, so exit boot services and stop the watchdog
+
+    mov 232(%r13), %rbx     // ExitBootServices
+    mov %rsi, %rcx          // RCX = EFI Handle
+    mov 8(%r15), %rdx       // RDX = mapkey from GetMemoryMap()
+    call *%rbx
+
+    mov %rdi, %r13
+
+    // Expected in efi_entry:
+    // R13 = video init boolean
+    // R14 = EFI_SYSTEM_TABLE address
+    // R15 = memory map address
+
+    mov $(efi_entry), %rax
+    jmp *%rax
+
+// This looks messed up, but EFI strings are 2 bytes and
+// .word "whatever" just pads byte content out to a word size
+
+banner:
+    .word  'V', 'i', 'r', 'i', 'd', 'i', 's', ' ', 'E', 'F', 'I', 0x0
+
+gop_guid:
+    .long 0x9042a9de
+    .word 0x23dc, 0x4a38
+    .byte 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a
+
+//conout_guid:
+//    .long 0x387477c2
+//    .word 0x69c7, 0x11d2
+//    .byte 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
+
+// 0x7e0 - begin of .reloc section
+.org 0x7e0
+.long 0x7ea        // reloc + 10
+.long 10           // 10
+
+// Round to a full 1k
+.org 0x800
+payload_data:
index 4574931..c86bfef 100644 (file)
@@ -86,6 +86,7 @@ hostjmp:
  * R15 = memory map address past the end of the kernel
  */
 
+.global efi_entry
 efi_entry:
     cli
     call populate_gdt64
diff --git a/boot/efi.asm b/boot/efi.asm
deleted file mode 100644 (file)
index 5e49812..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-# This PE header is hard coded here, and then fixed up later
-
-# Most of this taken from Linux's arch/x86/boot/header.S CONFIG_EFI_STUB code
-# UEFI spec 2.6 defines most of the special values in section 2.2.1
-
-.code64
-.org 0
-
-# This isn't used, but it shuts up ld
-.global _start
-_start:
-
-    .byte 0x4d         # MZ - MS-DOS header
-    .byte 0x5a
-
-    .org 0x3c
-    .long pe_header
-
-pe_header:
-    .ascii "PE"
-    .word 0
-
-coff_header:
-    .word 0x8664       # x86-64 (UEFI spec)
-    .word 4            # nr_sections
-    .long 0            # TimeDateStamp
-    .long 0            # PointerToSymbolTable
-    .long 1            # NumberOfSymbols
-
-    .word section_table - optional_header  # SizeOfOptionalHeader
-
-    .word 0x206        #Characteristics
-                       #IMAGE_FILE_DEBUG_STRIPPED |
-                       #IMAGE_FILE_EXECUTABLE_IMAGE |
-                       #IMAGE_FILE_LINE_NUMS_STRIPPED
-                     
-optional_header:
-    .word 0x20b        # PE32+
-    .byte 0x02         # MajorLinkerVersion
-    .byte 0x14         # MinorLinkerVersion
-
-size_of_code:
-    .long 0            # SizeOfCode fill:0x1c
-
-    .long 0            # SizeOfInitializedData
-    .long 0            # SizeOfUninitializedData
-
-    .long 0            # AddressOfEntryPoint
-    .long 0x200        # BaseOfCode
-
-extra_header_fields:
-    .quad 0            # ImageBase
-    .long 0x20         # SectionAlignment (CONFIG_PHYSICAL_ALIGN on Linux)
-    .long 0x20         # FileAlignment
-    .word 0            # MajorOperatingSystemVersion
-    .word 0            # MinorOperatingSystemVersion
-    .word 0            # MajorImageVersion
-    .word 0            # MinorImageVersion
-    .word 0            # MajorSubsystemVersion
-    .word 0            # MinorSubsystemVersion
-    .long 0            # Win32VersionValue
-
-    .long 0            # SizeOfImage fill:0x50
-
-    .long 0x200        # SizeOfHeaders
-    .long 0            # CheckSum
-    .word 0xa          # Subsystem (EFI application)
-    .word 0            # DllCharacteristics
-
-    .quad 0            # SizeOfStackReserve
-    .quad 0            # SizeOfStackCommit
-    .quad 0            # SizeOfHeapReserve
-    .quad 0            # SizeOfHeapCommit
-
-    .long 0            # LoaderFlags
-    .long 0x6          # NumberOfRvaAndSizes
-    
-    .quad 0            # ExportTable
-    .quad 0            # ImportTable
-    .quad 0            # ResourceTable
-    .quad 0            # ExceptionTable
-    .quad 0            # CertificationTable
-    .quad 0            # BaseRelocationTable
-
-section_table:
-    .ascii ".setup"
-    .byte 0
-    .byte 0            # -- end of name --
-    .long 0            # Size
-    .long 0            # startup_{32, 64}
-    .long 0            # Size of initialized data on disk
-    .long 0            # startup_{32, 64}
-    .long 0            # PointerToRelocations
-    .long 0            # PointerToLineNumbers
-    .word 0            # NumberOfRelocations
-    .word 0            # NumberOfLineNumbers
-    .long 0x60500020   # Characteristics
-
-    .ascii ".reloc"
-    .byte 0
-    .byte 0            # -- end of name --
-    .long 0            # Size
-    .long 0
-    .long 0            # SizeOfRawData
-    .long 0            # PointerToRawData
-    .long 0            # PointerToRelocations
-    .long 0            # PointerToLineNumbers
-    .word 0            # NumberOfRelocations
-    .word 0            # NumberOfLineNumbers
-    .long 0x42100040   # Characteristics
-
-    .ascii ".text"
-    .byte 0
-    .byte 0
-    .byte 0            # -- end of name --
-    .long 0            # Size
-    .long 0
-    .long 0            # SizeOfRawData
-    .long 0            # PointerToRawData
-    .long 0            # PointerToRelocations
-    .long 0            # PointerToLineNumbers
-    .word 0            # NumberOfRelocations
-    .word 0            # NumberOfLineNumbers
-    .long 0x60500020   # Characteristics
-
-    .ascii ".bss"
-    .byte 0
-    .byte 0
-    .byte 0
-    .byte 0            # -- end name --
-    .long 0            # Size
-    .long 0
-    .long 0            # SizeOfRawData
-    .long 0            # PointerToRawData
-    .long 0            # PointerToRelocations
-    .long 0            # PointerToLineNumbers
-    .word 0            # NumberOfRelocations
-    .word 0            # NumberOfLineNumbers
-    .long 0x60500020   # Characteristics
-
-# Push to 510 (Linux's build.c requires this, but necessary for EFI only boot?)
-# either way, we need to know exactly where start is in the binary anyway.
-
-.org 510
-.word 0xAA55
-
-# EFI handoff (from UEFI 2.6 sec 2.3.4)
-# We're in long mode, all memory is identity mapped
-# We have a large amount of stack (>=128k)
-
-# RCX - EFI_HANDLE
-# RDX - EFI_SYSTEM_TABLE pointer
-# RSP - Return address
-
-# EFI call
-# Args: RCX, RDX, R8, R9 > stack (+32 because you must reserve stack space for register args)
-# RAX is returned
-# RBX, RBP, RDI, RSI, R12-15 are preserved by calls
-#
-# EFI table header (24 bytes)
-# u64 signature
-# u32 revision
-# u32 header_size
-# u32 crc32
-# u32 reserved
-
-#EFI system table
-# header
-# char *firmware_vendor;            24
-# u32 firmware_revision             32 <-- padded to align next val
-# u64 console_in_handle             40
-# efi_simple_text_input *func       48
-# u64 console_out_handle            56
-# efi_simple_text_output *stdout    64
-# u64 standard_error_handle         72
-# efi_simple_text_output *stderr    80
-# runtime_services *                88
-# boot_services *                   96
-# u64 number of entries             104
-# efi_configuration_table *         112
-
-#console out
-# reset                             0
-# output_string                     8
-
-#EFI boot services table
-# header
-# efi_raise_tpl *                   24
-# efi_restore_tpl *                 32
-# efi_allocate_pages *              40
-# efi_free_pages *                  48
-# efi_get_memory_map *              56
-# ...
-# handle_protocol                   152
-# ...
-# locate_handle                     176
-# ...
-# efi_exit_boot_services *          232
-# efi_get_monotonic_count *         240
-# efi_stall *                       248
-# efi_set_watchdog_timer            256
-
-kernel_start:
-    .quad 0
-kernel_entry:
-    .quad 0
-boot_header:
-    .quad 0
-
-start:
-    cli
-    call next           # This puts our return address on the stack so we
-                        # can figure out where we are.
-next:
-    mov (%rsp), %r12    # R12 = address of next in EFI
-    sub $(next), %r12   # R12 = offset from where we think we are
-
-    mov 64(%rdx), %r13  # R13 = simple text output ptr
-    mov %rdx, %r14      # R14 = copy of EFI_SYSTEM_TABLE
-    mov %rcx, %rsi      # RSI = copy of EFI_HANDLE
-
-    mov (%r13), %rbx    # Reset
-    mov %r13, %rcx
-    mov $1, %rdx
-    call *%rbx          # Reset the screen()
-
-    mov 8(%r13), %rbx   # Output String
-    mov %r13, %rcx
-    mov $(banner), %rdx
-    add %r12, %rdx
-    call *%rbx          # Print our banner
-
-    mov 96(%r14), %r13  # R13 = boot services
-    mov 40(%r13), %rbx  # allocate_pages
-    mov $2, %rcx        # AllocateAddress
-    mov $2, %rdx        # EFILoaderData
-
-    mov $(size_of_code), %rax
-    add %r12, %rax
-    mov (%eax), %r8     # R8 = size of code declared in header
-
-    add $6655, %r8      # -1536 for ignoring setup code
-                        # +4096 for mmap  page
-                        # +4095 for rounding page up
-
-    shr $12, %r8        # R8 = num pages from end of EFI header to end of kernel
-    mov %r8, %r15       # save it off so we can use it for the copy
-
-    mov $(kernel_start), %r9
-    add %r12, %r9
-    mov (%r9), %rdi     # RDI = KERNEL_START
-    call *%rbx
-
-    mov %rdi, %rcx      # RCX = Start of copy dest
-    mov $(payload_data), %rax
-    add %r12, %rax      # RAX = Start of copy source
-
-    shl $12, %r15
-    add %rdi, %r15      # R15 = End of copy dest
-
-cp_loop:
-    mov (%rax), %rbx
-    mov %rbx, (%rcx)
-    add $8, %rax
-    add $8, %rcx
-    cmp %rcx, %r15
-    jne cp_loop
-
-    sub $4096, %rcx     # RCX = Address of extra page and mmap maxsize address
-    mov %rcx, %r15      # R15 = Copy of memory map header address
-    mov $0, %rdi        # Clear RDI, used to indicate whether video info is inited
-
-    # Eventually, we'll use this extra page to hold the memory map, for now
-    # use it as a scratch buffer to locate a framebuffer
-
-    mov 176(%r13), %rbx     # LocateHandle
-    mov $2, %rcx            # RCX = Search by protocol
-
-    mov $(gop_guid), %rdx   # RDX = GOP GUID
-    add %r12, %rdx
-
-    mov %r15, %r9           # Size of our buffer
-    movq $4088, (%r15)      # 4096 - 8
-
-    sub $40, %rsp
-    mov %r15, 32(%rsp)
-    addq $8, 32(%rsp)       # Stack: Address of our buffer
-    call *%rbx
-    add $40, %rsp
-
-    mov (%r15), %rbx        # If the returned size is 0, no GOP
-    cmp $0, %rbx
-    je  skip_vid
-
-    mov 152(%r13), %rbx     # HandleProtocol
-    mov 8(%r15), %rcx       # Pass in first returned EFI handle
-    mov $(gop_guid), %rdx
-    add %r12, %rdx          # GOP Guid
-    mov %r15, %r8           # Beginning of page (overwriting query return)
-
-    sub $40, %rsp
-    call *%rbx
-    add $40, %rsp
-
-    # Now that we've found the interface, copy the mode and info structs
-    # to a known location after the boot header
-
-    mov (%r15), %rbx        # RBX = protocol struct
-    mov 24(%rbx), %rcx      # RCX = mode struct
-    mov 8(%rcx), %rdx       # RDX = info struct
-
-    pushq $5                # 5 qwords
-    push %rdx               # info struct
-
-    pushq $5                # 5 qwords
-    push %rcx               # mode struct
-
-    mov $2, %rcx            # structures to copy
-    mov $(boot_header), %rdx# beginning of copy space
-    add %r12, %rdx
-    mov (%rdx), %rdx
-    add $28, %rdx           # skip to efi_gop_mode
-
-small_copy:
-    pop %rax                # physical address
-    pop %rbx                # qwords to copy
-scl:
-    mov (%rax), %rdi
-    mov %rdi, (%rdx)
-    add $8, %rdx
-    add $8, %rax
-    sub $1, %rbx
-    cmp $0, %rbx
-    jne scl
-
-    sub $1, %rcx
-    cmp $0, %rcx
-    jne small_copy
-
-    mov $1, %rdi            # Set RDI, video info found
-
-skip_vid:
-    mov %r15, %rcx
-
-    mov 56(%r13), %rbx      # GetMemoryMap
-    movq $4064, (%rcx)      # 4096 - 32
-    mov %rcx, %r8
-    add $8, %r8             # R8 = mapkey address
-    mov %r8, %r9
-    add $8, %r9             # R9 = descriptor size address
-    mov %r9, %rdx
-    add $8, %rdx
-
-    sub $40, %rsp
-    mov %rdx, 32(%rsp)      # Stack: descriptor version address
-    add $8, %rdx            # RDX = Memory map address (after header stuff)
-    call *%rbx
-    add $40, %rsp
-
-    # We've got our memory map, so exit boot services and stop the watchdog
-
-    mov 232(%r13), %rbx     # ExitBootServices
-    mov %rsi, %rcx          # RCX = EFI Handle
-    mov 8(%r15), %rdx       # RDX = mapkey from GetMemoryMap()
-    call *%rbx
-
-    mov %rdi, %r13
-
-    # Expected in efi_entry:
-    # R13 = video init boolean
-    # R14 = EFI_SYSTEM_TABLE address
-    # R15 = memory map address
-
-    mov $(kernel_entry), %rax
-    add %r12, %rax
-    jmpq *(%rax)
-
-# This looks messed up, but EFI strings are 2 bytes and
-# .word "whatever" just pads byte content out to a word size
-
-banner:
-    .word  'V', 'i', 'r', 'i', 'd', 'i', 's', ' ', 'E', 'F', 'I', 0x0
-
-gop_guid:
-    .long 0x9042a9de
-    .word 0x23dc, 0x4a38
-    .byte 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a
-
-#conout_guid:
-#    .long 0x387477c2
-#    .word 0x69c7, 0x11d2
-#    .byte 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
-
-# 0x7e0 - begin of .reloc section
-.org 0x7e0
-.long 0x7ea        # reloc + 10
-.long 10           # 10
-
-# Round to a full 1k
-.org 0x800
-payload_data:
diff --git a/boot/fixup_stub.c b/boot/fixup_stub.c
deleted file mode 100644 (file)
index df62c70..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/* vim: set ts=4 sw=4 sts=4 et : */
-
-/* Similar to build.c, take a binary PE header and an ELF kernel and
- * modify the PE header to reflect the proper sizes and offsets.
- *
- * This is super cargo-culty. For example, I'm not really sure if we need to be
- * messing with the relocations, but EFI applications are supposed to be
- * relocatable and I assume that (some?) loaders will balk if there isn't
- * actually a section. Firmwares are finicky and so I'm willing to give Linux
- * the benefit of the doubt that certain options are well chosen out of
- * pragmatism.
- *
- * Also this assumes LE host, and that HEADER_SIZE is correct.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <limits.h>
-
-#define HEADER_SIZE        2048    // efi.asm size
-#define EXC_HEADER_SIZE        512     // just the PE/COFF header part
-
-#define OUR_HEADER      (EXC_HEADER_SIZE)
-#define KERNEL_START    (OUR_HEADER)
-#define KERNEL_ENTRY    (OUR_HEADER + 8)
-#define BOOT_HEADER     (OUR_HEADER + 16)
-#define OUR_HEADER_SIZE 24
-
-#define RELOC_SIZE      0x20
-#define RELOC_ADDR      (HEADER_SIZE - RELOC_SIZE)
-
-#define SETUP_ENTRY     (EXC_HEADER_SIZE + OUR_HEADER_SIZE)
-#define SETUP_SIZE         ((HEADER_SIZE - EXC_HEADER_SIZE) - RELOC_SIZE)
-
-#define BSS_SIZE        1024
-
-#define PE_HEADER       0x3c
-
-int pe_header;
-#define NUM_SECTIONS    (pe_header + 0x6)
-#define SIZEOFCODE      (pe_header + 0x1c)
-#define SIZEUNINIT      (pe_header + 0x24)
-#define ADDRESS_ENTRY   (pe_header + 0x28)
-#define SIZEIMAGE       (pe_header + 0x50)
-
-#define SECTIONS        (pe_header + 0xb8)
-#define SECTION_SZOFF   0x8
-#define SECTION_VMAOFF  0xc
-#define SECTION_ISZOFF  0x10
-#define SECTION_OFFOFF  0x14
-#define SECTION_NEXT    0x28
-
-#define SETUP_SEC      (SECTIONS + 0*SECTION_NEXT)
-#define RELOC_SEC      (SECTIONS + 1*SECTION_NEXT)
-#define TEXT_SEC       (SECTIONS + 2*SECTION_NEXT)
-#define BSS_SEC                (SECTIONS + 3*SECTION_NEXT)
-
-/* Update a single section, pointed to by buf */
-/* First size and off = size and off of data */
-/* Second size and off = size and off of initialized data */
-/* Most of the time these are the same, but for BSS, initialized data  = 0 */
-void update_section(char *buf, int off, int size, int off2, int size2)
-{
-    *((int *) &buf[SECTION_SZOFF]) = size;
-    *((int *) &buf[SECTION_VMAOFF]) = off;
-    *((int *) &buf[SECTION_ISZOFF]) = size2;
-    *((int *) &buf[SECTION_OFFOFF]) = off2;
-}
-
-int main (int argc, char **argv)
-{
-    unsigned long kernel_start;
-    unsigned long efi_entry;
-    unsigned long boot_header;
-
-    int header_fd, kernel_fd;
-    unsigned short *sections;
-    char *buf = NULL;
-    struct stat s;
-    int total_filesize;
-
-    if (argc != 6) {
-        printf("USAGE: binheader elf-kernel kernel_start efi_entry boot_header\n");
-        return -1;
-    }
-
-    kernel_start = strtol(argv[3], NULL, 16);
-
-    if (kernel_start == LONG_MIN || kernel_start == LONG_MAX) {
-        printf("Bad kernel start %s\n", argv[3]);
-        return -1;
-    }
-
-    efi_entry = strtol(argv[4], NULL, 16);
-
-    if (efi_entry == LONG_MIN || efi_entry == LONG_MAX) {
-        printf("Bad EFI entry %s\n", argv[4]);
-        return -1;
-    }
-
-    boot_header = strtol(argv[5], NULL, 16);
-
-    if (boot_header == LONG_MIN || boot_header == LONG_MAX) {
-        printf("Bad boot_header %s\n", argv[5]);
-        return -1;
-    }
-
-    header_fd = open(argv[1], O_RDWR);
-    if (header_fd < 0) {
-        printf("Can't open header write\n");
-        return -1;
-    }
-
-    if (fstat(header_fd, &s)) {
-        printf("Failed to stat header\n");
-        return -1;
-    }
-
-    buf = malloc(1024); // 
-    if (!buf) {
-        printf("Failed to alloc buf\n");
-        return -1;
-    }
-
-    if(read(header_fd, buf, s.st_size) != s.st_size) {
-        printf("Failed to read entire header\n");
-        return -1;
-    }
-
-    kernel_fd = open(argv[2], O_RDONLY);
-    if (kernel_fd < 0) {
-        printf("Can't open kernel read\n");
-        return -1;
-    }
-
-    if (fstat(kernel_fd, &s)) {
-        printf("Failed to stat kernel\n");
-        return -1;
-    }
-
-    pe_header = *((int *) &buf[PE_HEADER]);
-
-    sections = (unsigned short *) &buf[NUM_SECTIONS];
-
-    update_section(&buf[SETUP_SEC], EXC_HEADER_SIZE, SETUP_SIZE, EXC_HEADER_SIZE, SETUP_SIZE);
-    update_section(&buf[RELOC_SEC], RELOC_ADDR, RELOC_SIZE, RELOC_ADDR, RELOC_SIZE);
-    update_section(&buf[TEXT_SEC], HEADER_SIZE, s.st_size, HEADER_SIZE, s.st_size);
-
-    total_filesize = HEADER_SIZE + s.st_size + BSS_SIZE;
-
-    /* SizeOfCode is entire kernel - the format header */
-    *((int *) &buf[SIZEOFCODE]) = total_filesize - (BSS_SIZE + EXC_HEADER_SIZE);
-
-    /* Address Entry is start_setup */
-    *((int *) &buf[ADDRESS_ENTRY]) = SETUP_ENTRY;
-
-    /* .bss is after kernel and of BSS_SIZE */
-    /* Not sure if this is just a kludge? */
-    update_section(&buf[BSS_SEC], s.st_size + HEADER_SIZE, BSS_SIZE, 0, 0);
-    
-    *((int *) &buf[SIZEUNINIT]) = BSS_SIZE;
-    *((int *) &buf[SIZEIMAGE]) = total_filesize;
-
-    *((unsigned long *) &buf[KERNEL_START]) = kernel_start;
-    *((unsigned long *) &buf[KERNEL_ENTRY]) = efi_entry;
-    *((unsigned long *) &buf[BOOT_HEADER]) = boot_header;
-
-    write(1, buf, HEADER_SIZE);
-}
diff --git a/boot/fixup_stub.sh b/boot/fixup_stub.sh
deleted file mode 100755 (executable)
index c222813..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-# Companion to fixup_stub.c to lookup symbols in the ELF kernel to insert
-
-# Must be called with CWD = root directory of a Viridis tree with a built kernel
-
-KERNEL_START=`cat include/memmap.h| grep '#define KERNEL_START' | awk '{ print $3 }'`
-EFI_ENTRY=`objdump -t viridis | grep efi_entry | awk '{ print $1 }'`
-BOOT_HEADER=`objdump -t viridis | grep boot_header | awk '{ print $1 }'`
-
-gcc -o fixup_stub boot/fixup_stub.c
-as -o efi-stub.o boot/efi.asm
-ld -Ttext 0x0 --oformat binary -nostdlib -o efi-stub efi-stub.o
-objcopy -O binary viridis viridis.bin
-./fixup_stub efi-stub viridis.bin $KERNEL_START $EFI_ENTRY $BOOT_HEADER > new-efi
-if [ ! $? -eq 0 ]; then
-       echo `cat new-efi`
-else
-       cat new-efi viridis.bin > viridis.efi
-fi
-rm fixup_stub efi-stub.o efi-stub new-efi viridis.bin
diff --git a/boot/grub_sig.c b/boot/grub_sig.c
deleted file mode 100644 (file)
index ee06100..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* vim: set ts=4 sw=4 sts=4 et : */
-
-#include <types.h>
-
-struct grub_signature {
-    u32 magic;
-    u32 flags;
-    u32 checksum;
-};
-
-#define GRUB_MAGIC 0x1BADB002
-
-#define GRUB_FLAGS_REQ_MMAP  (1 << 1)
-
-#define GRUB_FLAGS (GRUB_FLAGS_REQ_MMAP)
-#define GRUB_CHECKSUM (-1 * (GRUB_MAGIC + GRUB_FLAGS))
-
-struct grub_signature gs __attribute__ ((section(".grub_sig"))) = {
-GRUB_MAGIC, GRUB_FLAGS, GRUB_CHECKSUM};
diff --git a/kernel/grub_sig.c b/kernel/grub_sig.c
new file mode 100644 (file)
index 0000000..ee06100
--- /dev/null
@@ -0,0 +1,19 @@
+/* vim: set ts=4 sw=4 sts=4 et : */
+
+#include <types.h>
+
+struct grub_signature {
+    u32 magic;
+    u32 flags;
+    u32 checksum;
+};
+
+#define GRUB_MAGIC 0x1BADB002
+
+#define GRUB_FLAGS_REQ_MMAP  (1 << 1)
+
+#define GRUB_FLAGS (GRUB_FLAGS_REQ_MMAP)
+#define GRUB_CHECKSUM (-1 * (GRUB_MAGIC + GRUB_FLAGS))
+
+struct grub_signature gs __attribute__ ((section(".grub_sig"))) = {
+GRUB_MAGIC, GRUB_FLAGS, GRUB_CHECKSUM};