From 761169b59a77ac48e122d1bf5c7f603befe82b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 13 Aug 2022 20:57:36 +0100 Subject: [PATCH] Add hex2. --- amd64/Development/Makefile | 2 +- amd64/Development/hex0.hex2 | 4 +- amd64/Development/hex2.S | 673 ++++++++++++++++++++++++++ amd64/hex0.hex0 | 4 +- amd64/hex2.hex1 | 803 +++++++++++++++++++++++++++++++ amd64/mescc-tools-mini-kaem.kaem | 9 + 6 files changed, 1490 insertions(+), 5 deletions(-) create mode 100644 amd64/Development/hex2.S create mode 100644 amd64/hex2.hex1 diff --git a/amd64/Development/Makefile b/amd64/Development/Makefile index f55dc23..1c2d83b 100644 --- a/amd64/Development/Makefile +++ b/amd64/Development/Makefile @@ -9,7 +9,7 @@ lflags = -subsystem:efi_application -nodefaultlib -dll build = build -all: $(build)/hex0.efi $(build)/kaem-minimal.efi $(build)/hex1.efi +all: $(build)/hex0.efi $(build)/kaem-minimal.efi $(build)/hex1.efi $(build)/hex2.efi $(build)/%.o : %.S mkdir -p $(build) diff --git a/amd64/Development/hex0.hex2 b/amd64/Development/hex0.hex2 index e761ddd..277fa28 100644 --- a/amd64/Development/hex0.hex2 +++ b/amd64/Development/hex0.hex2 @@ -30,9 +30,9 @@ # Open Loaded Image protocol 50 ; PUSH_RAX # allocate stack for image 4989E0 ; COPY_RSP_to_R8 # arg3 = &image - 488B15 %LOADED_IMAGE_PROTOCOL_8 ; LOAD64_rel_RDX !LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + 488B15 %LOADED_IMAGE_PROTOCOL_8 ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) 52 ; PUSH_RDX # push last 64 bits onto stack - 488B15 %LOADED_IMAGE_PROTOCOL ; LOAD64_rel_RDX !LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + 488B15 %LOADED_IMAGE_PROTOCOL ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) 52 ; PUSH_RDX # push first 64 bits onto stack 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid 6A 01 ; PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL diff --git a/amd64/Development/hex2.S b/amd64/Development/hex2.S new file mode 100644 index 0000000..1e52a45 --- /dev/null +++ b/amd64/Development/hex2.S @@ -0,0 +1,673 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2017 Jeremiah Orians +# +# SPDX-License-Identifier: GPL-3.0-or-later + +.global _start +.text + + # Register usage: + # R15 => Flag + # R14 => High bits + # R13 => IP + # R12 => MALLOC + # R11 => HEAD + + # Struct format: (size 24) + # NEXT => 0 + # TARGET => 8 + # NAME => 16 + +# efi_main(void *image_handle, struct efi_system_table *system) +_start: + mov rbp, rsp # save stack pointer + mov r15, rcx # save image_handle + mov r14, [rdx+96] # system->boot + mov [rip+SystemBoot], r14 # save system->boot + + # Allocate pool for scratch area + xor edx, edx # zero rdx + mov dh, 0x8 # arg2 = 256 * 8 = 2048 = 0x800 + call allocate_pool + mov [rip+scratch], rax # save scratch + + # Open Loaded Image protocol + push rax # allocate stack for image + mov r8, rsp # arg3 = &image + mov rdx, [rip+LOADED_IMAGE_PROTOCOL+8] # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + push rdx # push last 64 bits onto stack + mov rdx, [rip+LOADED_IMAGE_PROTOCOL] # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + push rdx # push first 64 bits onto stack + mov rdx, rsp # arg2 = &guid + push 1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + push 0 # arg5 = NULL + mov r9, r15 # arg4 = image_handle + mov rcx, r15 # arg1 = image_handle + sub rsp, 32 # allocate shadow stack space for UEFI function + call [r14+280] # system->boot->open_protocol(image_handle, &guid, &image, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + mov rax, [rsp+64] # get image + mov rcx, rax # save image + + # Command line args + mov rbx, [rax+56] # options = image->load_options + +loop_options1: # Skip application name + add rbx, 2 # ++options + mov al, [rbx] # *options + cmp al, 0x20 # if *options != ' ' + jne loop_options1 # then jump + + add rbx, 2 # ++options + mov r12, rbx # save input file + +loop_options2: # Skip argv[1] + add rbx, 2 # ++options + mov al, [rbx] # *options + cmp al, 0x20 # if *options != ' ' + jne loop_options2 # then jump + + mov byte ptr [rbx], 0 # *options = 0 + add rbx, 2 # ++options + mov r13, rbx # save output file + + # Get root file system + push rax # allocate stack for rootfs + mov r8, rsp # arg3 = &rootfs + mov rdx, [rip+SIMPLE_FS_PROTOCOL+8] # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (last 64 bits) + push rdx # push last 64 bits onto stack + mov rdx, [rip+SIMPLE_FS_PROTOCOL] # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (first 64 bits) + push rdx # push first 64 bits onto stack + mov rdx, rsp # arg2 = &guid + push 1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + push 0 # arg5 = NULL + mov r9, r15 # arg4 = image_handle + mov rcx, [rcx+24] # arg1 = root_device = image->device + sub rsp, 32 # allocate shadow stack space for UEFI function + call [r14+280] # system->boot->open_protocol(root_device, &guid, &rootfs, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + mov rcx, [rsp+64] # get rootfs + + # Get root directory + push rdx # allocate stack for rootdir + mov rdx, rsp # arg2 = &rootdir + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) + pop rax # deallocate stack + pop rax # deallocate stack + pop rbx # save &rootdir + + # Open file for reading + push rdx # allocate stack for fin + mov rdx, rsp # arg2 = &fin + push 1 # arg5 = EFI_FILE_READ_ONLY + push 1 # prepare to set arg4 to EFI_FILE_MODE_READ + pop r9 # arg4 = EFI_FILE_MODE_READ + mov r8, r12 # arg3 = in + mov rcx, rbx # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + mov rax, [rsp+40] # get fin + mov [rip+fin], rax # save fin + + # Open file for writing + push rdx # allocate stack for fout + mov rdx, rsp # arg2 = &fout + push 0 # arg5 = 0 + push 7 # to get 0x8000000000000003 we set the rightmost 3 bits + pop r9 # and then do right rotation by 1 + ror r9 # arg4 = EFI_FILE_MODE_CREATE| EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ + mov r8, r13 # arg3 = out + mov rcx, rbx # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + mov r10, [rsp+40] # get fout + + # Allocate pool for structs + mov rdx, 0x1000000 # allocate 16 MiB of memory + call allocate_pool + mov r12, rax # get structs + + call ClearScratch # Zero scratch + mov r15, -1 # Our flag for byte processing + mov r14, 0 # temp storage for the sum + mov r13, 0x00600000 # Our starting IP + mov r11, 0 # HEAD = NULL + call First_pass # Process it + + # rewind input file + push r10 # Protect r10 + push r11 # Protect r11 + mov rcx, [rip+fin] # Using our input file + xor edx, edx # Offset Zero + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + call [rcx+56] # fin->set_position(fin, 0) + pop rax # deallocate stack + pop rax # deallocate stack + pop r11 # restore r11 + pop r10 # restore r10 + + mov r15, -1 # Our flag for byte processing + mov r14, 0 # temp storage for the sum + mov r13, 0x00600000 # Our starting IP + call Second_pass # Process it + + jmp Done + + +First_pass: + call Read_byte + + # Deal with EOF + cmp rax, -4 + je First_pass_done + + # Check for : + cmp rax, 0x3a + jne First_pass_0 + + # Deal with label + call StoreLabel + +First_pass_0: + # Check for ! + cmp rax, 0x21 + je First_pass_pointer + + # Check for @ + cmp rax, 0x40 + je First_pass_pointer + + # Check for $ + cmp rax, 0x24 + je First_pass_pointer + + # Check for % + cmp rax, 0x25 + je First_pass_pointer + + # Check for & + cmp rax, 0x26 + je First_pass_pointer + + # Deal with everything else + call hex # Process our char + + # Deal with EOF + cmp rax, -4 + je First_pass_done + + # deal with -1 values + cmp rax, 0 + jl First_pass + + # deal with toggle + cmp r15, 0 + je First_pass_1 + add r13, 1 # Increment IP + +First_pass_1: + not r15 + jmp First_pass + +Update_Pointer: + # Check for ! + cmp rax, 0x21 + je Update_Pointer_1 + + # Check for @ + cmp rax, 0x40 + je Update_Pointer_2 + + # Check for $ + cmp rax, 0x24 + je Update_Pointer_2 + + # Check for % + cmp rax, 0x25 + je Update_Pointer_4 + + # Check for & + cmp rax, 0x26 + je Update_Pointer_4 + + # deal with bad input + call fail + +Update_Pointer_4: + add r13, 2 # Increment IP +Update_Pointer_2: + add r13, 1 # Increment IP +Update_Pointer_1: + add r13, 1 # Increment IP + ret + +First_pass_pointer: + # Deal with Pointer to label + call Update_Pointer # Increment IP + mov rbx, [rip+scratch] # Using scratch + call consume_token # Read token + call ClearScratch # Throw away token + cmp rax, 0x3E # check for '>' + jne First_pass # Loop again + + # Deal with %label>label case + mov rbx, [rip+scratch] # Write to scratch + call consume_token # get token + call ClearScratch # Clean up after ourselves + jmp First_pass # Loop again + +First_pass_done: + ret + +hex: + # deal with EOF + cmp rax, -4 + je EOF + # deal with line comments starting with # + cmp rax, 0x23 + je ascii_comment + # deal with line comments starting with ; + cmp rax, 0x3b + je ascii_comment + # deal all ascii less than 0 + cmp rax, 0x30 + jl ascii_other + # deal with 0-9 + cmp rax, 0x3a + jl ascii_num + # deal with all ascii less than A + cmp rax, 0x41 + jl ascii_other + # deal with A-F + cmp rax, 0x47 + jl ascii_high + # deal with all ascii less than a + cmp rax, 0x61 + jl ascii_other + # deal with a-f + cmp rax, 0x67 + jl ascii_low + # The rest that remains needs to be ignored + jmp ascii_other + +Second_pass: + call Read_byte + + # Deal with EOF + cmp rax, -4 + je Second_pass_done + + # Simply drop the label + cmp rax, 0x3a + jne Second_pass_0 + + mov rbx, [rip+scratch] # Using scratch + call consume_token # Read token + call ClearScratch # Throw away token + + jmp Second_pass + +Second_pass_0: + # Deal with % pointer + cmp rax, 0x25 + je StorePointer_rel4 + + # Deal with @ pointer + cmp rax, 0x40 + je StorePointer_rel2 + + # Deal with ! pointer + cmp rax, 0x21 + je StorePointer_rel1 + + # Deal with & pointer + cmp rax, 0x26 + je StorePointer_abs4 + + # Deal with $ pointer + cmp rax, 0x24 + je StorePointer_abs2 + +Second_pass_1: + # Deal with everything else + call hex # Process our char + + # Deal with EOF + cmp rax, -4 + je Second_pass_done + + # deal with -1 values + cmp rax, 0 + jl Second_pass + + # deal with toggle + cmp r15, 0 + je print + + # process first byte of pair + mov r14, rax + mov r15, 0 + jmp Second_pass + +Second_pass_done: +EOF: + ret +ascii_num: + sub rax, 0x30 + ret +ascii_low: + sub rax, 0x57 + ret +ascii_high: + sub rax, 0x37 + ret +ascii_other: + mov rax, -1 + ret +ascii_comment: + call Read_byte + cmp rax, 0xd + je ascii_comment_cr + cmp rax, 0xa + jne ascii_comment +ascii_comment_cr: + mov rax, -1 + ret + +# process second byte of pair +print: + # update the sum and store in output + shl r14, 4 + add rax, r14 + + # flip the toggle + not r15 # r15 = -1 + + mov rdx, 1 # set the size of chars we want + call print_chars + + add r13, 1 # Increment IP + jmp Second_pass + + +Read_byte: + push r10 # Protect r10 + push r11 # Protect r11 + mov rcx, [rip+fin] # arg1 = fin + push 1 # size = 1 + mov rdx, rsp # arg2 = &size + xor esi, esi # zero rsi + push rsi # allocate stack + mov r8, rsp # arg3 = &input + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + call [rcx+32] # fin->read() + pop rax # deallocate stack + pop rax # deallocate stack + pop rax # deallocate stack + pop rax # save input to rax + pop rsi # save size to rsi + pop r11 # restore r11 + pop r10 # restore r10 + + # If the file ended (0 bytes read) return EOF + test esi, esi # if size == 0 + jne Read_byte_1 + mov rax, -4 # Put EOF in rax + +Read_byte_1: + ret # return + +# Writes bytes stored in rax +print_chars: + push r10 # Protect r10 + push r11 # Protect r11 + mov rcx, r10 # arg1 = fout + push rdx # set size + mov rdx, rsp # arg2 = &size + push rax # allocate stack + mov r8, rsp # arg3 = &output + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + push rax # allocate shadow stack space for UEFI function + call [rcx+40] # fout->write() + add rsp, 40 # deallocate stack + pop r11 # restore r11 + pop r10 # restore r10 + + ret # return + + # Receives pointer in RBX + # Writes out char and updates RBX +consume_token: + call Read_byte # Consume_token + + # Check for \t + cmp rax, 0x09 + je consume_token_done + + # Check for \n + cmp rax, 0x0A + je consume_token_done + + # Check for ' ' + cmp rax, 0x20 + je consume_token_done + + # Check for '>' + cmp rax, 0x3E + je consume_token_done + + # Looks like we are still reading token + mov [rbx], al # Store char + add rbx, 1 # Point to next spot + jmp consume_token # loop until done + +consume_token_done: + mov rcx, 0 # Pad with nulls + mov [rbx], rcx + add rbx, 8 + ret + +StoreLabel: + mov rax, r12 # ENTRY + add r12, 24 # CALLOC + mov [rax+8], r13 # ENTRY->TARGET = IP + mov [rax], r11 # ENTRY->NEXT = JUMP_TABLE + mov r11, rax # JUMP_TABLE = ENTRY + mov [r11+16], r12 # ENTRY->NAME = TOKEN + mov rbx, r12 # Write Starting after struct + call consume_token # Collect whole string + mov r12, rbx # Update HEAP + jmp First_pass + +GetTarget: + mov rdi, [rip+scratch] # Reset scratch + mov rcx, r11 # Grab JUMP_TABLE + mov rsi, [rcx+16] # I->NAME +GetTarget_loop: + mov al, [rsi] # I->NAME[0] + mov bl, [rdi] # scratch[0] + movzx rbx, bl # Zero extend + movzx rax, al # Zero extend + cmp al, bl # IF TOKEN == I->NAME + jne GetTarget_miss # Oops + + add rsi, 1 + add rdi, 1 + cmp al, 0 + jne GetTarget_loop # Loop until + jmp GetTarget_done # Match + + # Miss +GetTarget_miss: + mov rcx, [rcx] # I = I->NEXT + cmp rcx, 0 # IF NULL == I + je fail # Abort hard + + mov rsi, [rcx+16] # I->NAME + mov rdi, [rip+scratch] # Reset scratch + jmp GetTarget_loop + +GetTarget_done: + mov rax, [rcx+8] # Get address + ret + +ClearScratch: + push rax # Protect against changes + push rbx # And overwrites + push rcx + push rdx # While we work + mov rbx, [rip+scratch] # Where our scratch area is + mov al, 0 # Using null + + mov rdx, rbx # Get scratch + add rdx, 0x800 # end of scratch area + +ClearScratch_loop: + cmp rbx, rdx # Make sure + je ClearScratch_end # we do not overflow + + mov rcx, [rbx] # Get current value + mov [rbx], al # Because we want null + add rbx, 1 # Increment + cmp rcx, 0 # Check if we hit null + jne ClearScratch_loop # Keep looping + +ClearScratch_end: + pop rdx + pop rcx # Don't Forget to + pop rbx # Restore Damage + pop rax # Entirely + ret + +StorePointer: + call Update_Pointer # Increment IP + mov rbx, [rip+scratch] # Write to scratch + call consume_token # get token + push rax # Protect base_sep_p + mov rax, [rip+scratch] # Pointer to scratch + call GetTarget # Get address of pointer + call ClearScratch # Clean up after ourselves + mov rdx, r13 # base = IP + pop rbx # Restore base_sep_p + cmp rbx, 0x3E # If base_sep_p == '>' + jne StorePointer_done # If not + + # Deal with %label>label case + push rax # We need to preserve main target + mov rbx, [rip+scratch] # Write to scratch + call consume_token # get token + mov rax, [rip+scratch] # Pointer to scratch + call GetTarget # Get address of pointer + call ClearScratch # Clean up after ourselves + mov rdx, rax # Use our new base + pop rax # Restore main target + +StorePointer_done: + ret + +StorePointer_rel4: + call StorePointer # Do Common + sub rax, rdx # target - ip + mov rdx, 4 # set the size of chars we want + call print_chars + jmp Second_pass + +StorePointer_rel2: + call StorePointer # Do Common + sub rax, rdx # target - ip + mov rdx, 2 # set the size of chars we want + call print_chars + jmp Second_pass + +StorePointer_rel1: + call StorePointer # Do Common + sub rax, rdx # target - ip + mov rdx, 1 # set the size of chars we want + call print_chars + jmp Second_pass + +StorePointer_abs4: + call StorePointer # Do Common + mov rdx, 4 # set the size of chars we want + call print_chars + jmp Second_pass + +StorePointer_abs2: + call StorePointer # Do Common + mov rdx, 2 # set the size of chars we want + call print_chars + jmp Second_pass + +fail: + mov rax, 1 # Set exit code 1 + jmp terminate + +Done: + xor eax, eax # Set exit code 0 + +terminate: + # Free pool + push rax # save exit code + push r10 # protect fout + push rax # allocate shadow stack space for UEFI function + mov r14, [rip+SystemBoot] # get system->boot + mov rcx, [rip+scratch] # arg1 = scratch + call [r14+72] # system->boot->free_pool(scratch) + + mov rcx, r12 # arg1 = structs + call [r14+72] # system->boot->free_pool(structs) + + mov rcx, [rip+fin] # arg1 = fin + call [rcx+16] # fin->close(fin) + pop rax # deallocate stack + pop rcx # restore fout + push rax # allocate shadow stack space for UEFI function + call [rcx+16] # fout->close(fout) + pop rax # deallocate stack + pop rax # restore exit code + +abort: # used for debugging only + mov rsp, rbp # restore stack + ret # return to UEFI + +# rdx: number of bytes to allocate +# r14: system->boot +# returns pointer in rax +allocate_pool: + push rdx # allocate stack for pool pointer + mov r8, rsp # arg3 = &pool + push 2 + pop rcx # arg1 = EFI_LOADER_DATA + sub rsp, 24 # allocate shadow stack space for UEFI + call [r14+64] # system->boot->allocate_pool(EFI_LOADER_DATA, 2048, &pool) + add rsp, 24 # deallocate stack + pop rax # get pool + ret + +.data + +# Protocol GUIDs +LOADED_IMAGE_PROTOCOL: +.long 0x5b1b31a1 +.short 0x9562 +.short 0x11d2 +.byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + +SIMPLE_FS_PROTOCOL: +.long 0x0964e5b22 +.short 0x6459 +.short 0x11d2 +.byte 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + +fin: +.long 0, 0 + +scratch: +.long 0, 0 + +SystemBoot: +.long 0, 0 diff --git a/amd64/hex0.hex0 b/amd64/hex0.hex0 index bedd8c3..f8154e0 100644 --- a/amd64/hex0.hex0 +++ b/amd64/hex0.hex0 @@ -158,10 +158,10 @@ A3 01 00 00 ; SizeOfRawData # Open Loaded Image protocol 50 ; PUSH_RAX # allocate stack for image 4989E0 ; COPY_RSP_to_R8 # arg3 = &image - 488B15 6F010000 ; LOAD64_rel_RDX !LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + 488B15 6F010000 ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) # [_start+0x1C] 52 ; PUSH_RDX # push last 64 bits onto stack - 488B15 5F010000 ; LOAD64_rel_RDX !LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + 488B15 5F010000 ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) # [_start+0x24] 52 ; PUSH_RDX # push first 64 bits onto stack 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid diff --git a/amd64/hex2.hex1 b/amd64/hex2.hex1 new file mode 100644 index 0000000..0583f14 --- /dev/null +++ b/amd64/hex2.hex1 @@ -0,0 +1,803 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2017 Jeremiah Orians +# +# SPDX-License-Identifier: GPL-3.0-or-later + + # Register usage: + # R15 => Flag + # R14 => High bits + # R13 => IP + # R12 => MALLOC + # R11 => HEAD + + # Struct format: (size 24) + # NEXT => 0 + # TARGET => 8 + # NAME => 16 + +# DOS MZ header +4D 5A # Signature +00 00 # Number of bytes in the last page. +00 00 # Number of whole/partial pages +00 00 # Number of entries in the relocation table. +00 00 # Header size +00 00 # Minimum allocation +00 00 # Maximum allocation +00 00 # Relocatable segment address for SS +00 00 # Initial value for SP +00 00 # Checksum (I don't think is looked at) +00 00 # Initial value for IP (Seems ignored) +00 00 # Relocatable segment address for CS (Seems ignored) +00 00 # The (absolute) offset to the relocation table. +00 00 # Value used for overlay management. If zero, this is the main executable +00 00 00 00 00 00 00 00 # Reserved in PE +00 00 # OEM identifier +00 00 # OEM info +00 00 00 00 00 00 00 00 00 00 # The required reserved 20 bytes of NULLS +00 00 00 00 00 00 00 00 00 00 +40 00 00 00 # Starting address of the PE header + +# [0x40] +# PE header +50 45 00 00 # Signature "PE" +64 86 # Machine +01 00 # number of sections +00 00 00 00 # Timestamp supposedly +00 00 00 00 # PointerToSymbolTable +00 00 00 00 # number of symbols +F0 00 # SizeOfOptionalHeader +00 00 # 'Characteristics' + +# [0x58] +# COFF header bits +0B 02 # Magic PE32+ (64 bit) +00 00 # Linker version +00 00 00 00 # size of code +00 00 00 00 # sizeOfInitializedData +00 00 00 00 # SizeOfUninitializedData +00 10 00 00 # AddressOfEntryPoint +00 10 00 00 # BaseOfCode +00 00 00 80 01 00 00 00 # ImageBase +01 00 00 00 # SectionAlignment +01 00 00 00 # FileAlignment +00 00 00 00 # OperatingSystemVersion +00 00 00 00 # ImageVersion +00 00 00 00 # SubsystemVersion +00 00 00 00 # Win32VersionValue +00 20 00 00 # SizeOfImage +70 01 00 00 # SizeOfHeaders +00 00 00 00 # CheckSum (isn't used at all) +0A 00 # Subsystem +00 00 # DllCharacteristics +00 00 00 00 # SizeOfStackReserve +00 00 00 00 # SizeOfStackCommit +00 00 00 00 # SizeOfHeapReserve +00 00 00 00 # SizeOfHeapCommit +00 00 00 00 # LoaderFlags +00 00 00 00 # NumberOfRvaAndSizes + +# [0xB8] +# Data directories (has to be 16 entries always 16bytes per entry) +00 00 00 00 # Export Table +00 00 00 00 # Size of Export Table + +00 00 00 00 # Import Table +10 00 00 00 # Size of Import Table + +00 00 00 00 # Resource Table +00 00 00 00 # Size of Resource Table + +00 00 00 00 # Exception Table +00 00 00 00 # Size of Exception Table + +00 00 00 00 # Certificate Table +00 00 00 00 # Size of Certificate Table + +00 00 00 00 # Base Relocation Table +00 00 00 00 # Size of Base Relocation Table + +00 00 00 00 # Debug Table +00 00 00 00 # Size of Debug Table + +00 00 00 00 # Architecture Data Table +00 00 00 00 # Size of Architecture Data Table + +00 00 00 00 # Global Pointer +00 00 00 00 # NULL + +00 00 00 00 # TLS Table +00 00 00 00 # Size of TLS Table + +00 00 00 00 # Load Config Table +00 00 00 00 # Size of Load Config Table + +00 00 00 00 # Bound Import Table +00 00 00 00 # Size of Bound Import Table + +00 00 00 00 # Import Address Table +00 00 00 00 # Size of Import Address Table + +00 00 00 00 # Delay Import Descriptor Table +00 00 00 00 # Size of Delay Import Descriptor Table + +00 00 00 00 # CLR Runtime header table +00 00 00 00 # Size of CLR Runtime Header table + +00 00 00 00 00 00 00 00 # MUST BE NULL + +# no idea what it is yet +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# [0x148] +# Start of section headers +00 00 00 00 00 00 00 00 ; Name of the section (empty) but could set to ".text" +5C 06 00 00 ; VirtualSize +00 10 00 00 ; VirtualAddress +5C 06 00 00 ; SizeOfRawData +70 01 00 00 ; PointerToRawData +00 00 00 00 ; PointerToRelocations +00 00 00 00 ; PointerToLinenumbers +00 00 ; NumberOfRelocations +00 00 ; NumberOfLinenumbers +00 00 00 00 ; 'Characteristics' + +# [0x170] + +#:PE32_text + +# efi_main(void *image_handle, struct efi_system_table *system) +#:_start + 4889E5 ; COPY_RSP_to_RBP # save stack pointer + 4989CF ; COPY_RCX_to_R15 # save image_handle + 4C8B72 60 ; LOAD64_into_R14_from_Address_RDX_Immediate8 !96 # system->boot + 4C8935 %1 ; STORE64_rel_R14 %SystemBoot # save system->boot + + # Allocate pool for scratch area + 31D2 ; XOR_EDX_EDX # zero rdx + B6 08 ; LOADI8_DH !0x8 # arg2 = 256 * 8 = 2048 = 0x800 + E8 %U ; CALLI32 %allocate_pool + 488905 %0 ; STORE64_rel_RAX %scratch # save scratch + + # Open Loaded Image protocol + 50 ; PUSH_RAX # allocate stack for image + 4989E0 ; COPY_RSP_to_R8 # arg3 = &image + 488B15 %W ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + 52 ; PUSH_RDX # push last 64 bits onto stack + 488B15 %V ; LOAD64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + 52 ; PUSH_RDX # push first 64 bits onto stack + 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid + 6A 01 ; PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + 6A 00 ; PUSH !0 # arg5 = NULL + 4D89F9 ; COPY_R15_to_R9 # arg4 = image_handle + 4C89F9 ; COPY_R15_to_RCX # arg1 = image_handle + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + 41FF96 18010000 ; CALL_R14_Immediate32 %280 # system->boot->open_protocol(image_handle, &guid, &image, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + 488B4424 40 ; LOAD64_into_RAX_from_Address_RSP_Immediate8 !64 # get_image + 4889C1 ; COPY_RCX_to_RAX # save image + + # Command line args + 488B58 38 ; LOAD64_into_RBX_from_Address_RAX_Immediate8 !56 # options = image->load_options + +:a #:loop_options1 # Skip application name + 4883C3 02 ; ADDI8_RBX !2 # ++options + 8A03 ; LOAD8_AL_from_Address_RBX # *options + 3C 20 ; CMPI8_AL !0x20 # if *options != ' ' + 0F85 %a ; JNE32 %loop_options1 # then jump + + 4883C3 02 ; ADDI8_RBX !2 # ++options + 4989DC ; COPY_RBX_to_R12 # save input file + +:b #:loop_options2 # Skip argv[1] + 4883C3 02 ; ADDI8_RBX !2 # ++options + 8A03 ; LOAD8_AL_from_Address_RBX # *options + 3C 20 ; CMPI8_AL !0x20 # if *options != ' ' + 0F85 %b ; JNE32 %loop_options2 # then jump + + C603 00 ; STOREI8_into_Address_RBX !0 # *options = 0; + 4883C3 02 ; ADDI8_RBX !2 # ++options + 4989DD ; COPY_RBX_to_R13 # save output file + + # Get root file system + 50 ; PUSH_RAX # allocate stack for rootfs + 4989E0 ; COPY_RSP_to_R8 # arg3 = &rootfs + 488B15 %Y ; LOAD64_rel_RDX %SIMPLE_FS_PROTOCOL_8 # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (last 64 bits) + 52 ; PUSH_RDX # push last 64 bits onto stack + 488B15 %X ; LOAD64_rel_RDX %SIMPLE_FS_PROTOCOL # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (first 64 bits) + 52 ; PUSH_RDX # push first 64 bits onto stack + 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid + 6A 01 ; PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + 6A 00 ; PUSH !0 # arg5 = NULL + 4D89F9 ; COPY_R15_to_R9 # arg4 = image_handle + 488B49 18 ; LOAD64_into_RCX_from_Address_RCX_Immediate8 !24 # arg1 = root_device = image->device + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + 41FF96 18010000 ; CALL_R14_Immediate32 %280 # system->boot->open_protocol(root_device, &guid, &rootfs, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + 488B4C24 40 ; LOAD64_into_RCX_from_Address_RSP_Immediate8 !64 # get rootfs + + # Get root directory + 52 ; PUSH_RDX # allocate stack for rootdir + 4889E2 ; COPY_RSP_to_RDX # arg2 = &rootdir + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 5B ; POP_RBX # save &rootdir + + # Open file for reading + 52 ; PUSH_RDX # allocate stack for fin + 4889E2 ; COPY_RSP_to_RDX # arg2 = &fin + 6A 01 ; PUSH !1 # arg5 = EFI_FILE_READ_ONLY + 6A 01 ; PUSH !1 # prepare to set arg4 to EFI_FILE_MODE_READ + 4159 ; POP_R9 # arg4 = EFI_FILE_MODE_READ + 4D89E0 ; COPY_R12_to_R8 # arg3 = in + 4889D9 ; COPY_RBX_to_RCX # arg1 = rootdir + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + FF51 08 ; CALL_RCX_Immediate8 !8 # rootdir->open() + 488B4424 28 ; LOAD64_into_RAX_from_Address_RSP_Immediate8 !40 # get fin + 488905 %Z ; STORE64_rel_RAX %fin # save fin + + # Open file for writing + 52 ; PUSH_RDX # allocate stack for fout + 4889E2 ; COPY_RSP_to_RDX # arg2 = &fout + 6A 00 ; PUSH !0 # arg5 = 0 + 6A 07 ; PUSH !7 # to get 0x8000000000000003 we set the rightmost 3 bits + 4159 ; POP_R9 # and then do right rotation by 1 + 49D1C9 ; ROR_R9 # arg4 = EFI_FILE_MODE_CREATE| EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ + 4D89E8 ; COPY_R13_to_R8 # arg3 = out + 4889D9 ; COPY_RBX_to_RCX # arg1 = rootdir + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + FF51 08 ; CALL_RCX_Immediate8 !8 # rootdir->open() + 4C8B5424 28 ; LOAD64_into_R10_from_Address_RSP_Immediate8 !40 # get fout + + # Allocate pool for structs + 48C7C2 00000001 ; LOADI32_RDX %0x1000000 # allocate 16 MiB of memory + E8 %U ; CALLI32 %allocate_pool + 4989C4 ; COPY_RAX_to_R12 # get structs + + E8 %H ; CALLI32 %ClearScratch # Zero scratch + 49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing + 49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum + 49C7C5 00006000 ; LOADI32_R13 %0x00600000 # Our starting IP + 49C7C3 00000000 ; LOADI32_R11 %0 # HEAD = NULL + E8 %c ; CALLI32 %First_pass # Process it + + # rewind input file + 4152 ; PUSH_R10 # Protect r10 + 4153 ; PUSH_R11 # Protect r11 + 488B0D %Z ; LOAD64_rel_RCX %fin # Using our input file + 31D2 ; XOR_EDX_EDX # Offset Zero + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + FF51 38 ; CALL_RCX_Immediate8 !56 # fin->set_position(fin, 0) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 415B ; POP_R11 # restore r11 + 415A ; POP_R10 # restore r10 + + 49C7C7 FFFFFFFF ; LOADI32_R15 %-1 # Our flag for byte processing + 49C7C6 00000000 ; LOADI32_R14 %0 # temp storage for the sum + 49C7C5 00006000 ; LOADI32_R13 %0x00600000 # Our starting IP + E8 %m ; CALLI32 %Second_pass # Process it + + E9 %S ; JMP32 %Done + +:c #:First_pass + E8 %x ; CALLI32 %Read_byte + + # Deal with EOF + 4883F8 FC ; CMP_RAX_Immediate8 !-4 + 0F84 %k ; JE32 %First_pass_done + + # Check for : + 4883F8 3A ; CMP_RAX_Immediate8 !0x3A + 0F85 %d ; JNE32 %First_pass_0 + + # Deal with label + E8 %C ; CALLI32 %StoreLabel + +:d #:First_pass_0 + # Check for ! + 4883F8 21 ; CMP_RAX_Immediate8 !0x21 + 0F84 %j ; JE32 %First_pass_pointer + + # Check for @ + 4883F8 40 ; CMP_RAX_Immediate8 !0x40 + 0F84 %j ; JE32 %First_pass_pointer + + # Check for $ + 4883F8 24 ; CMP_RAX_Immediate8 !0x24 + 0F84 %j ; JE32 %First_pass_pointer + + # Check for % + 4883F8 25 ; CMP_RAX_Immediate8 !0x25 + 0F84 %j ; JE32 %First_pass_pointer + + # Check for & + 4883F8 26 ; CMP_RAX_Immediate8 !0x26 + 0F84 %j ; JE32 %First_pass_pointer + + # Deal with everything else + E8 %l ; CALLI32 %hex # Process our char + + # Deal with EOF + 4883F8 FC ; CMP_RAX_Immediate8 !-4 + 0F84 %k ; JE32 %First_pass_done + + # deal with -1 values + 4883F8 00 ; CMP_RAX_Immediate8 !0 + 0F8C %c ; JL32 %First_pass + + # deal with toggle + 4983FF 00 ; CMP_R15_Immediate8 !0 + 0F84 %e ; JE32 %First_pass_1 + 4983C5 01 ; ADDI8_to_R13 !1 # Increment IP + +:e #:First_pass_1 + 49F7D7 ; NOT_R15 + E9 %c ; JMP32 %First_pass + +:f #:Update_Pointer + # Check for ! + 4883F8 21 ; CMP_RAX_Immediate8 !0x21 + 0F84 %i ; JE32 %Update_Pointer_1 + + # Check for @ + 4883F8 40 ; CMP_RAX_Immediate8 !0x40 + 0F84 %h ; JE32 %Update_Pointer_2 + + # Check for $ + 4883F8 24 ; CMP_RAX_Immediate8 !0x24 + 0F84 %h ; JE32 %Update_Pointer_2 + + # Check for % + 4883F8 25 ; CMP_RAX_Immediate8 !0x25 + 0F84 %g ; JE32 %Update_Pointer_4 + + # Check for & + 4883F8 26 ; CMP_RAX_Immediate8 !0x26 + 0F84 %g ; JE32 %Update_Pointer_4 + + # deal with bad input + E8 %R ; CALLI32 %fail + +:g #:Update_Pointer_4 + 4983C5 02 ; ADDI8_to_R13 !2 # Increment IP +:h #:Update_Pointer_2 + 4983C5 01 ; ADDI8_to_R13 !1 # Increment IP +:i #:Update_Pointer_1 + 4983C5 01 ; ADDI8_to_R13 !1 # Increment IP + C3 ; RET + +:j #:First_pass_pointer + # Deal with Pointer to label + E8 %f ; CALLI32 %Update_Pointer # Increment IP + 488B1D %0 ; LOAD64_rel_RBX %scratch # Using scratch + E8 %A ; CALLI32 %consume_token # Read token + E8 %H ; CALLI32 %ClearScratch # Throw away token + 4883F8 3E ; CMP_RAX_Immediate8 !0x3E # check for '>' + 0F85 %c ; JNE32 %First_pass # Loop again + + # Deal with %label>label case + 488B1D %0 ; LOAD64_rel_RBX %scratch # Write to scratch + E8 %A ; CALLI32 %consume_token # get token + E8 %H ; CALLI32 %ClearScratch # Clean up after ourselves + E9 %c ; JMP32 %First_pass # Loop again + +:k #:First_pass_done + C3 ; RET + +:l #:hex + # deal with EOF + 4883F8 FC ; CMP_RAX_Immediate8 !-4 + 0F84 %p ; JE32 %EOF + # deal with line comments starting with # + 4883F8 23 ; CMP_RAX_Immediate8 !0x23 + 0F84 %u ; JE32 %ascii_comment + # deal with line comments starting with ; + 4883F8 3B ; CMP_RAX_Immediate8 !0x3B + 0F84 %u ; JE32 %ascii_comment + # deal all ascii less than 0 + 4883F8 30 ; CMP_RAX_Immediate8 !0x30 + 0F8C %t ; JL32 %ascii_other + # deal with 0-9 + 4883F8 3A ; CMP_RAX_Immediate8 !0x3A + 0F8C %q ; JL32 %ascii_num + # deal with all ascii less than A + 4883F8 41 ; CMP_RAX_Immediate8 !0x41 + 0F8C %t ; JL32 %ascii_other + # deal with A-F + 4883F8 47 ; CMP_RAX_Immediate8 !0x47 + 0F8C %s ; JL32 %ascii_high + # deal with all ascii less than a + 4883F8 61 ; CMP_RAX_Immediate8 !0x61 + 0F8C %t ; JL32 %ascii_other + # deal with a-f + 4883F8 67 ; CMP_RAX_Immediate8 !0x67 + 0F8C %r ; JL32 %ascii_low + # The rest that remains needs to be ignored + E9 %t ; JMP32 %ascii_other + +:m #:Second_pass + E8 %x ; CALLI32 %Read_byte + + # Deal with EOF + 4883F8 FC ; CMP_RAX_Immediate8 !-4 + 0F84 %p ; JE32 %Second_pass_done + + # Simply drop the label + 4883F8 3A ; CMP_RAX_Immediate8 !0x3A + 0F85 %n ; JNE32 %Second_pass_0 + + 488B1D %0 ; LOAD64_rel_RBX %scratch # Using scratch + E8 %A ; CALLI32 %consume_token # Read token + E8 %H ; CALLI32 %ClearScratch # Throw away token + + E9 %m ; JMP32 %Second_pass + +:n #:Second_pass_0 + # Deal with % pointer + 4883F8 25 ; CMP_RAX_Immediate8 !0x25 + 0F84 %M ; JE32 %StorePointer_rel4 + + # Deal with @ pointer + 4883F8 40 ; CMP_RAX_Immediate8 !0x40 + 0F84 %N ; JE32 %StorePointer_rel2 + + # Deal with ! pointer + 4883F8 21 ; CMP_RAX_Immediate8 !0x21 + 0F84 %O ; JE32 %StorePointer_rel1 + + # Deal with & pointer + 4883F8 26 ; CMP_RAX_Immediate8 !0x26 + 0F84 %P ; JE32 %StorePointer_abs4 + + # Deal with $ pointer + 4883F8 24 ; CMP_RAX_Immediate8 !0x24 + 0F84 %Q ; JE32 %StorePointer_abs2 + +:o #:Second_pass_1 + # Deal with everything else + E8 %l ; CALLI32 %hex # Process our char + + # Deal with EOF + 4883F8 FC ; CMP_RAX_Immediate8 !-4 + 0F84 %p ; JE32 %Second_pass_done + + # deal with -1 values + 4883F8 00 ; CMP_RAX_Immediate8 !0 + 0F8C %m ; JL32 %Second_pass + + # deal with toggle + 4983FF 00 ; CMP_R15_Immediate8 !0 + 0F84 %w ; JE32 %print + + # process first byte of pair + 4989C6 ; COPY_RAX_to_R14 + 49C7C7 00000000 ; LOADI32_R15 %0 + E9 %m ; JMP32 %Second_pass + +:p #:Second_pass_done + #:EOF + C3 ; RET + +:q #:ascii_num + 83E8 30 ; SUBI8_RAX !0x30 + C3 ; RET +:r #:ascii_low + 83E8 57 ; SUBI8_RAX !0x57 + C3 ; RET +:s #:ascii_high + 83E8 37 ; SUBI8_RAX !0x37 + C3 ; RET +:t #:ascii_other + 48C7C0 FFFFFFFF ; LOADI32_RAX %-1 + C3 ; RET +:u #:ascii_comment + E8 %x ; CALLI32 %Read_byte + 4883F8 0D ; CMP_RAX_Immediate8 !0x0D + 0F84 %v ; JE32 %ascii_comment_cr + 4883F8 0A ; CMP_RAX_Immediate8 !0x0A + 0F85 %u ; JNE32 %ascii_comment +:v #:ascii_comment_cr + 48C7C0 FFFFFFFF ; LOADI32_RAX %-1 + C3 ; RET + +# process second byte of pair +:w #:print + # update the sum and store in output + 49C1E6 04 ; SHL_R14_Immediate8 !4 + 4C01F0 ; ADD_R14_to_RAX + + # flip the toggle + 49F7D7 ; NOT_R15 # r15 = -1 + + # Print our first Hex + 48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + + 4983C5 01 ; ADDI8_to_R13 !1 # Increment IP + E9 %m ; JMP32 %Second_pass + + +:x #:Read_byte + 4152 ; PUSH_R10 # Protect r10 + 4153 ; PUSH_R11 # Protect r11 + 488B0D %Z ; LOAD64_rel_RCX %fin # arg1 = fin + 6A 01 ; PUSH !1 # size = 1 + 4889E2 ; COPY_RSP_to_RDX # arg2 = &size + 31F6 ; XOR_ESI_ESI # zero rsi + 56 ; PUSH_RSI # allocate stack + 4989E0 ; COPY_RSP_to_R8 # arg3 = &input + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + FF51 20 ; CALL_RCX_Immediate8 !32 # fin->read() + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # save input to rax + 5E ; POP_RSI # save size to rsi + 415B ; POP_R11 # restore r11 + 415A ; POP_R10 # restore r10 + + # If the file ended (0 bytes read) return EOF + 85F6 ; TEST_ESI_ESI + 0F85 %y ; JNE32 %Read_byte_1 + 48C7C0 FCFFFFFF ; LOADI32_RAX %-4 # Put EOF in rax + +:y #:Read_byte_1 + C3 ; RET + +# Writes bytes stored in rax +:z #:print_chars + 4152 ; PUSH_R10 # Protect r10 + 4153 ; PUSH_R11 # Protect r11 + 4C89D1 ; COPY_R10_to_RCX # arg1 = fout + 52 ; PUSH_RDX # set size + 4889E2 ; COPY_RSP_to_RDX # arg2 = &size + 50 ; PUSH_RAX # allocate stack + 4989E0 ; COPY_RSP_to_R8 # arg3 = &output + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + FF51 28 ; CALL_RCX_Immediate8 !40 # fout->write() + 4883C4 28 ; ADDI8_RSP !40 # deallocate stack + 415B ; POP_R11 # restore r11 + 415A ; POP_R10 # restore r10 + + C3 ; RET + + # Receives pointer in RBX + # Writes out char and updates RBX +:A #:consume_token + E8 %x ; CALLI32 %Read_byte # Consume_token + + # Check for \t + 4883F8 09 ; CMP_RAX_Immediate8 !0x09 + 0F84 %B ; JE32 %consume_token_done + + # Check for \n + 4883F8 0A ; CMP_RAX_Immediate8 !0x0A + 0F84 %B ; JE32 %consume_token_done + + # Check for ' ' + 4883F8 20 ; CMP_RAX_Immediate8 !0x20 + 0F84 %B ; JE32 %consume_token_done + + # Check for '>' + 4883F8 3E ; CMP_RAX_Immediate8 !0x3E + 0F84 %B ; JE32 %consume_token_done + + # Looks like we are still reading token + 8803 ; STORE8_al_into_Address_RBX # Store char + 4883C3 01 ; ADDI8_RBX !1 # Point to next spot + E9 %A ; JMP32 %consume_token # loop until done + +:B #:consume_token_done + 48C7C1 00000000 ; LOADI32_RCX %0 # Pad with nulls + 48890B ; STORE32_RCX_into_Address_RBX + 4883C3 08 ; ADDI8_RBX !8 + C3 ; RET + +:C #:StoreLabel + 4C89E0 ; COPY_R12_to_RAX # ENTRY + 4983C4 18 ; ADDI8_to_R12 !24 # CALLOC + 4C8968 08 ; STORE32_R13_into_Address_RAX_Immediate8 !8 # ENTRY->TARGET = IP + 4C8918 ; STORE32_R11_into_Address_RAX # ENTRY->NEXT = JUMP_TABLE + 4989C3 ; COPY_RAX_to_R11 # JUMP_TABLE = ENTRY + 4D8963 10 ; STORE32_R12_into_Address_R11_Immediate8 !16 # ENTRY->NAME = TOKEN + 4C89E3 ; COPY_R12_to_RBX # Write Starting after struct + E8 %A ; CALLI32 %consume_token # Collect whole string + 4989DC ; COPY_RBX_to_R12 # Update HEAP + E9 %c ; JMP32 %First_pass + +:D #:GetTarget + 488B3D %0 ; LOAD64_rel_RDI %scratch # Reset scratch + 4C89D9 ; COPY_R11_to_RCX # Grab JUMP_TABLE + 488B71 10 ; LOAD32_into_RSI_from_Address_RCX_Immediate8 !16 # I->NAME +:E #:GetTarget_loop + 8A06 ; LOAD8_AL_from_Address_RSI # I->NAME[0] + 8A1F ; LOAD8_BL_from_Address_RDI # scratch[0] + 480FB6DB ; ZERO_EXTEND_BL # Zero extend + 480FB6C0 ; ZERO_EXTEND_AL # Zero extend + 38D8 ; CMP_AL_to_BL # IF TOKEN == I->NAME + 0F85 %F ; JNE32 %GetTarget_miss # Oops + + 4883C6 01 ; ADDI8_to_RSI !1 + 4883C7 01 ; ADDI8_to_RDI !1 + 3C 00 ; CMPI8_AL !0 + 0F85 %E ; JNE32 %GetTarget_loop # Loop until + E9 %G ; JMP32 %GetTarget_done # Match + + # Miss +:F #:GetTarget_miss + 488B09 ; LOAD32_into_RCX_from_Address_RCX # I = I->NEXT + 4883F9 00 ; CMP_RCX_Immediate8 !0 # IF NULL == I + 0F84 %R ; JE32 %fail # Abort hard + + 488B71 10 ; LOAD32_into_RSI_from_Address_RCX_Immediate8 !16 # I->NAME + 488B3D %0 ; LOAD64_rel_RDI %scratch # Reset scratch + E9 %E ; JMP32 %GetTarget_loop + +:G #:GetTarget_done + 488B41 08 ; LOAD32_into_RAX_from_Address_RCX_Immediate8 !8 # Get address + C3 ; RET + +:H #:ClearScratch + 50 ; PUSH_RAX # Protect against changes + 53 ; PUSH_RBX # And overwrites + 51 ; PUSH_RCX + 52 ; PUSH_RDX # While we work + 488B1D %0 ; LOAD64_rel_RBX %scratch # Where our table is + B0 00 ; LOADI8_AL !0 # Using null + + 4889DA ; COPY_RBX_to_RDX # Get scratch + 4881C2 00080000 ; ADDI32_RDX %0x800 # end of scratch area + +:I #:ClearScratch_loop + 4839D3 ; CMP_RBX_RDX # Make sure + 0F84 %J ; JE32 %ClearScratch_end # we do not overflow + + 488B0B ; LOAD32_into_RCX_from_Address_RBX # Get current value + 8803 ; STORE8_al_into_Address_RBX # Because we want null + 4883C3 01 ; ADDI8_RBX !1 # Increment + 4883F9 00 ; CMP_RCX_Immediate8 !0 # Check if we hit null + 0F85 %I ; JNE32 %ClearScratch_loop # Keep looping + +:J #:ClearScratch_end + 5A ; POP_RDX + 59 ; POP_RCX # Don't Forget to + 5B ; POP_RBX # Restore Damage + 58 ; POP_RAX # Entirely + C3 ; RET + +:K #:StorePointer + E8 %f ; CALLI32 %Update_Pointer # Increment IP + 488B1D %0 ; LOAD64_rel_RBX %scratch # Write to scratch + E8 %A ; CALLI32 %consume_token # get token + 50 ; PUSH_RAX # Protect base_sep_p + 488B05 %0 ; LOAD64_rel_RAX %scratch # Pointer to scratch + E8 %D ; CALLI32 %GetTarget # Get address of pointer + E8 %H ; CALLI32 %ClearScratch # Clean up after ourselves + 4C89EA ; COPY_R13_to_RDX # base = IP + 5B ; POP_RBX # Restore base_sep_p + 4883FB 3E ; CMP_RBX_Immediate8 !0x3E # If base_sep_p == '>' + 0F85 %L ; JNE32 %StorePointer_done # If not + + # Deal with %label>label case + 50 ; PUSH_RAX # We need to preserve main target + 488B1D %0 ; LOAD64_rel_RBX %scratch # Write to scratch + E8 %A ; CALLI32 %consume_token # get token + 488B05 %0 ; LOAD64_rel_RAX %scratch # Pointer to scratch + E8 %D ; CALLI32 %GetTarget # Get address of pointer + E8 %H ; CALLI32 %ClearScratch # Clean up after ourselves + 4889C2 ; COPY_RAX_to_RDX # Use our new base + 58 ; POP_RAX # Restore main target + +:L #:StorePointer_done + C3 ; RET + +:M #:StorePointer_rel4 + E8 %K ; CALLI32 %StorePointer # Do Common + 4829D0 ; SUB_RDX_from_RAX # target - ip + 48C7C2 04000000 ; LOADI32_RDX %4 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + E9 %m ; JMP32 %Second_pass + +:N #:StorePointer_rel2 + E8 %K ; CALLI32 %StorePointer # Do Common + 4829D0 ; SUB_RDX_from_RAX # target - ip + 48C7C2 02000000 ; LOADI32_RDX %2 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + E9 %m ; JMP32 %Second_pass + +:O #:StorePointer_rel1 + E8 %K ; CALLI32 %StorePointer # Do Common + 4829D0 ; SUB_RDX_from_RAX # target - ip + 48C7C2 01000000 ; LOADI32_RDX %1 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + E9 %m ; JMP32 %Second_pass + +:P #:StorePointer_abs4 + E8 %K ; CALLI32 %StorePointer # Do Common + 48C7C2 04000000 ; LOADI32_RDX %4 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + E9 %m ; JMP32 %Second_pass + +:Q #:StorePointer_abs2 + E8 %K ; CALLI32 %StorePointer # Do Common + 48C7C2 02000000 ; LOADI32_RDX %2 # set the size of chars we want + E8 %z ; CALLI32 %print_chars + E9 %m ; JMP32 %Second_pass + +:R #:fail + 48C7C0 01000000 ; LOADI32_RAX %1 # Set exit code 1 + E9 %T ; JMP32 %terminate + +:S #:Done + 31C0 ; XOR_EAX_EAX # Set exit code 0 + +:T #:terminate + 50 ; PUSH_RAX # save exit code + 4152 ; PUSH_R10 # protect fout + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 4C8B35 %1 ; LOAD64_rel_R14 %SystemBoot # get system->boot + 488B0D %0 ; LOAD64_rel_RCX %scratch # arg1 = scratch + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(scratch) + + 4C89E1 ; COPY_R12_to_RCX # arg1 = structs + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(structs) + + 488B0D %Z ; LOAD64_rel_RCX %fin # arg1 = fin + FF51 10 ; CALL_RCX_Immediate8 !16 # fin->close(fin) + 58 ; POP_RAX # deallocate stack + 59 ; POP_RCX # restore fout + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + FF51 10 ; CALL_RCX_Immediate8 !16 # fout->close(fout) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # restore exit code + + 4889EC ; COPY_RBP_to_RSP # restore stack + C3 ; RET # return to UEFI + +# rdx: number of bytes to allocate +# r14: system->boot +# returns pointer in rax +:U #:allocate_pool + 52 ; PUSH_RDX # allocate stack for pool pointer + 4989E0 ; COPY_RSP_to_R8 # arg3 = &pool + 6A 02 ; PUSH !2 + 59 ; POP_RCX # arg1 = EFI_LOADER_DATA + 4883EC 18 ; SUBI8_RSP !24 # allocate shadow stack space for UEFI + 41FF56 40 ; CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 2048, &pool) + 4883C4 18 ; ADDI8_RSP !24 # deallocate stack + 58 ; POP_RAX # get pool + C3 ; RET + + +# Protocol GUIDs +:V #:LOADED_IMAGE_PROTOCOL + A1 31 1B 5B ; %0x5b1b31a1 + 62 95 ; @0x9562 + D2 11 ; @0x11d2 +:W #:LOADED_IMAGE_PROTOCOL_8 + 8E 3F 00 A0 C9 69 72 3B ; !0x8e !0x3f !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:X #:SIMPLE_FS_PROTOCOL + 22 5B 4E 96 ; %0x0964e5b22 + 59 64 ; @0x6459 + D2 11 ; @0x11d2 +:Y #:SIMPLE_FS_PROTOCOL_8 + 8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:Z #:fin + 00000000 00000000 + +:0 #:scratch + 00000000 00000000 + +:1 #:SystemBoot + 00000000 00000000 + +# :PE32_end diff --git a/amd64/mescc-tools-mini-kaem.kaem b/amd64/mescc-tools-mini-kaem.kaem index cf809ae..00fd6d2 100644 --- a/amd64/mescc-tools-mini-kaem.kaem +++ b/amd64/mescc-tools-mini-kaem.kaem @@ -10,3 +10,12 @@ amd64\artifact\hex0.efi amd64\hex1.hex0 amd64\artifact\hex1.efi # hex1 adds support for single character labels and is available in various forms # in mescc-tools/amd64_bootstrap to allow you various ways to verify correctness + +################################# +# Phase-2 Build hex2 from hex1 # +################################# +amd64\artifact\hex1.efi amd64\hex2.hex1 amd64\artifact\hex2-0.efi +# hex2 adds support for long labels and absolute addresses thus allowing it +# to function as an effective linker for later stages of the bootstrap +# This is a minimal version which will be used to bootstrap a much more advanced +# version in a later stage.