From 368377191b4697ac15f244bc6a9c98f74277515c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 7 Aug 2022 21:45:05 +0100 Subject: [PATCH] Add hex1.S prototype. --- Makefile | 2 +- amd64/Development/Makefile | 2 +- amd64/Development/hex0.S | 4 +- amd64/Development/hex1.S | 378 +++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+), 4 deletions(-) create mode 100644 amd64/Development/hex1.S diff --git a/Makefile b/Makefile index 9e8aff8..aa17735 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ $(build_dir)/esp.img: rootfs rootfs: rm -rf $(rootfs_dir) mkdir -p $(boot_dir) - rsync -av . $(rootfs_dir) --exclude $(build_dir) --exclude ".*" --exclude "Development/" --exclude "*/Development/" --exclude "bootstrap-seeds/" + rsync -av . $(rootfs_dir) --exclude $(build_dir) --exclude ".*" --exclude "bootstrap-seeds/" mkdir -p $(rootfs_dir)/bootstrap-seeds/UEFI/ rsync -av bootstrap-seeds/UEFI/ $(rootfs_dir)/bootstrap-seeds/UEFI/ diff --git a/amd64/Development/Makefile b/amd64/Development/Makefile index 81a3274..f55dc23 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-optional.efi +all: $(build)/hex0.efi $(build)/kaem-minimal.efi $(build)/hex1.efi $(build)/%.o : %.S mkdir -p $(build) diff --git a/amd64/Development/hex0.S b/amd64/Development/hex0.S index bb87919..16ee4bf 100644 --- a/amd64/Development/hex0.S +++ b/amd64/Development/hex0.S @@ -64,7 +64,7 @@ loop_options2: # Skip argv[1] cmp al, 0x20 # if *options != ' ' jne loop_options2 # then jump - mov byte ptr [rbx], 0 # *options = 0; + mov byte ptr [rbx], 0 # *options = 0 add rbx, 2 # ++options mov r13, rbx # save output file @@ -81,7 +81,7 @@ loop_options2: # Skip argv[1] 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 # system->boot->open_protocol(root_device, &guid, &rootfs, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + call r14 # 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 diff --git a/amd64/Development/hex1.S b/amd64/Development/hex1.S new file mode 100644 index 0000000..049e60b --- /dev/null +++ b/amd64/Development/hex1.S @@ -0,0 +1,378 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2017 Jeremiah Orians +# +# SPDX-License-Identifier: GPL-3.0-or-later + +.global _start +.text + +# 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 r14, [r14+280] # system->boot->open_protocol + + # 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, rcx # arg4 = image_handle + # arg1 = ImageHandle (already set) + sub rsp, 32 # allocate shadow stack space for UEFI function + call r14 # 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 # 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 r14 # 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, r14 # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + mov rdi, [rsp+40] # get 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, r14 # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + mov rbx, [rsp+40] # get fout + + mov r15, -1 # Our flag for byte processing + mov r14, 0 # temp storage for the sum + mov r13, 0 # Our starting IP + call First_pass # Process it + + # rewind input file + mov rcx, rdi # 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 + + mov r15, -1 # Our flag for byte processing + mov r14, 0 # temp storage for the sum + mov r13, 0 # 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, 0x25 + 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 + +First_pass_pointer: + # Deal with Pointer to label + call Read_byte # Drop the char + add r13, 4 # Increment IP + 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 + + call Read_byte + jmp Second_pass + +Second_pass_0: + # Deal with pointer + cmp rax, 0x25 + jne Second_pass_1 + + call StorePointer + jmp Second_pass + +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: + ret + +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 + dec r15 # rbx = -1 + + mov rdx, 1 # set the size of chars we want + call print_chars + + add r13, 1 # Increment IP + jmp Second_pass + + +Read_byte: + mov rcx, rdi # arg1 = fin + push 1 # size = 1 + mov rdx, rsp # arg2 = &size + 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 + + # 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 byte stored in al +print_chars: + mov rcx, rbx # arg1 = fout + push rdx # size = 1 + 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 + + ret # return + +Get_table_target: + call Read_byte # Get single char label + shl rax, 3 # Each label in table takes 8 bytes to store + add rax, table # Calculate offset + ret + +StoreLabel: + call Get_table_target + mov [rax], r13 # Write out pointer to table + ret + +StorePointer: + add r13, 4 # Increment IP + call Get_table_target # Get address of pointer + mov rax, [rax] # Get pointer + sub rax, r13 # target - ip + mov rdx, 4 # set the size of chars we want + call print_chars + ret + +Done: + push rbx # allocate stack + mov rcx, rdi # arg1 = fin + call [rcx+16] # fin->close() + mov rcx, rbx # arg1 = fout + call [rcx+16] # fout->close() +abort: # used for debugging only + mov rsp, rbp # restore stack + ret # return to UEFI + +.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 + +table: +.long 0, 0