diff --git a/amd64/Development/Makefile b/amd64/Development/Makefile index 1c2d83b..f09c175 100644 --- a/amd64/Development/Makefile +++ b/amd64/Development/Makefile @@ -2,14 +2,17 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +targets = kaem-minimal hex0 hex1 hex2 catm + cc = clang cflags = -ffreestanding -MMD -mno-red-zone -std=c11 -target x86_64-unknown-windows -masm=intel ld = lld-link lflags = -subsystem:efi_application -nodefaultlib -dll build = build +targets2 = $(addsuffix .efi, $(addprefix $(build)/, $(targets))) -all: $(build)/hex0.efi $(build)/kaem-minimal.efi $(build)/hex1.efi $(build)/hex2.efi +all: $(targets2) $(build)/%.o : %.S mkdir -p $(build) diff --git a/amd64/Development/catm.S b/amd64/Development/catm.S new file mode 100644 index 0000000..6fcc342 --- /dev/null +++ b/amd64/Development/catm.S @@ -0,0 +1,227 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2019 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 + + # 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 rdi, rax # save image + + # 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, [rdi+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 + + 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 rax # get rootdir + mov [rip+rootdir], rax # save rootdir + + # Push command line arguments onto stack + mov rbx, [rdi+56] # options = image->load_options + mov rdx, rbx # save beginning of load_options + add rbx, [rdi+48] # go to the end of load_options + + push 0 # Save end of arguments (NULL) onto stack + jmp loop_options_1 +loop_options: + push rbx # push another argument onto stack +loop_options_1: + cmp rbx, rdx # Check if we are done + je loop_options_done # We are done + sub rbx, 2 # --options + mov al, [rbx] # *options + cmp al, 0x20 # if *options != ' ' + jne loop_options_1 # then continue looping + mov BYTE PTR [rbx], 0 # zero it + add rbx, 2 # ++options + jmp loop_options # next argument +loop_options_done: + pop rdx # get output file + + # Open file for writing + mov r8, rdx + 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 rcx, [rip+rootdir] # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + add rsp, 40 # deallocate stack + pop r15 # get fout + + mov rdx, 0x100000 # Allocate 1MiB + call allocate_pool # Get memory pool + mov rbx, rax # Save it + +core: + pop r8 # Get the actual input name + cmp r8, 0 # Check for null string + je done # We are done if null string + + call open_file # Open file as read only + test eax, eax # check if successfully opened + jne core # Else go to another file + mov r13, rsi # Protect fin + +keep: + mov rdx, 0x100000 # set the size of chars we want + call read # read it + push rax # Protect the number of bytes read + + mov rdx, rax # number of bytes to write + call write # write them + + pop rax # Get bytes read + cmp rax, 0x100000 # Check if buffer was fully used + je keep # Keep looping if it was full + + mov rcx, r13 # fin + call close_file # close file + jmp core # Move to next file + +done: + mov rcx, r15 # Get output file + call close_file # close it + + mov rcx, rbx # Get buffer + call free_pool # release it + mov rax, 0 # Exit code 0 + + mov rsp, rbp # restore stack pointer + ret # return to UEFI + +# r8: input file name +# returns input file handle in rsi, status in rax +open_file: + # 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 rcx, [rip+rootdir] # arg1 = rootdir + sub rsp, 32 # allocate shadow stack space for UEFI function + call [rcx+8] # rootdir->open() + add rsp, 40 # allocate shadow stack space for UEFI function + pop rsi # get fin + ret + +# rcx: file handle +close_file: + push rax # allocate shadow stack space for UEFI function + call [rcx+16] # file_handle->close(file_handle) + pop rax # deallocate stack + ret + +# 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 + +# rcx: memory pool +# r14: system->boot +free_pool: + push rax # allocate shadow stack space for UEFI function + call [r14+72] # system->boot->free_pool(scratch) + pop rax # deallocate stack + ret + +# rdx: number of bytes to read +# rbx: buffer +# r13: input file handle +# returns number of bytes read in rax +read: + mov rcx, r13 # arg1 = fin + push rdx # set size + mov rdx, rsp # arg2 = &size + mov r8, rbx # arg3 = buffer + sub rsp, 24 # allocate shadow stack space for UEFI + call [rcx+32] # fin->read() + add rsp, 24 # deallocate stack + pop rax # save size to rax + ret + +# rdx: number of bytes to write +# rbx: buffer +# r14: output file handle +# returns number of bytes written in rax +write: + mov rcx, r15 # arg1 = fout + push rdx # set size + mov rdx, rsp # arg2 = &size + mov r8, rbx # arg3 = buffer + sub rsp, 24 # allocate shadow stack space for UEFI + call [rcx+40] # fin->write() + add rsp, 24 # deallocate stack + pop rax # save size to rax + 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 + +rootdir: +.long 0, 0 diff --git a/amd64/Development/hex0.M1 b/amd64/Development/hex0.M1 index 76a810e..4facb80 100644 --- a/amd64/Development/hex0.M1 +++ b/amd64/Development/hex0.M1 @@ -152,7 +152,7 @@ DEFINE TEST_ESI_ESI 85F6 CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) POP_RAX # deallocate stack POP_RAX # deallocate stack - POP_R14 # save &rootdir + POP_R14 # save rootdir # Open file for writing PUSH_RDX # allocate stack for fout diff --git a/amd64/Development/hex0.S b/amd64/Development/hex0.S index 75fa0ca..7ded45d 100644 --- a/amd64/Development/hex0.S +++ b/amd64/Development/hex0.S @@ -92,7 +92,7 @@ loop_options2: # Skip argv[1] call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) pop rax # deallocate stack pop rax # deallocate stack - pop r14 # save &rootdir + pop r14 # save rootdir # Open file for writing push rdx # allocate stack for fout diff --git a/amd64/Development/hex0.hex2 b/amd64/Development/hex0.hex2 index 277fa28..d15e1fb 100644 --- a/amd64/Development/hex0.hex2 +++ b/amd64/Development/hex0.hex2 @@ -90,7 +90,7 @@ FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415E ; POP_R14 # save &rootdir + 415E ; POP_R14 # save rootdir # Open file for writing 52 ; PUSH_RDX # allocate stack for fout diff --git a/amd64/Development/hex1.M1 b/amd64/Development/hex1.M1 index 41a37d9..fcca077 100644 --- a/amd64/Development/hex1.M1 +++ b/amd64/Development/hex1.M1 @@ -163,7 +163,7 @@ DEFINE TEST_ESI_ESI 85F6 CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) POP_RAX # deallocate stack POP_RAX # deallocate stack - POP_R14 # save &rootdir + POP_R14 # save rootdir # Open file for reading PUSH_RDX # allocate stack for fin diff --git a/amd64/Development/hex1.S b/amd64/Development/hex1.S index ac8f965..389410c 100644 --- a/amd64/Development/hex1.S +++ b/amd64/Development/hex1.S @@ -89,7 +89,7 @@ loop_options2: # Skip argv[1] call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) pop rax # deallocate stack pop rax # deallocate stack - pop r14 # save &rootdir + pop r14 # save rootdir # Open file for reading push rdx # allocate stack for fin diff --git a/amd64/Development/hex1.hex2 b/amd64/Development/hex1.hex2 index 822f953..a79a455 100644 --- a/amd64/Development/hex1.hex2 +++ b/amd64/Development/hex1.hex2 @@ -87,7 +87,7 @@ FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415E ; POP_R14 # save &rootdir + 415E ; POP_R14 # save rootdir # Open file for reading 52 ; PUSH_RDX # allocate stack for fin diff --git a/amd64/Development/hex2.M1 b/amd64/Development/hex2.M1 index 5329510..5eb86c0 100644 --- a/amd64/Development/hex2.M1 +++ b/amd64/Development/hex2.M1 @@ -205,7 +205,7 @@ DEFINE ZERO_EXTEND_BL 480FB6DB CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) POP_RAX # deallocate stack POP_RAX # deallocate stack - POP_RBX # save &rootdir + POP_RBX # save rootdir # Open file for reading PUSH_RDX # allocate stack for fin diff --git a/amd64/Development/hex2.S b/amd64/Development/hex2.S index 1e52a45..0573538 100644 --- a/amd64/Development/hex2.S +++ b/amd64/Development/hex2.S @@ -94,7 +94,7 @@ loop_options2: # Skip argv[1] call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) pop rax # deallocate stack pop rax # deallocate stack - pop rbx # save &rootdir + pop rbx # save rootdir # Open file for reading push rdx # allocate stack for fin diff --git a/amd64/Development/kaem-minimal.M1 b/amd64/Development/kaem-minimal.M1 index be670ed..b35afb1 100644 --- a/amd64/Development/kaem-minimal.M1 +++ b/amd64/Development/kaem-minimal.M1 @@ -184,7 +184,7 @@ DEFINE XOR_R15_R15 4D31FF CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) POP_RAX # deallocate stack POP_RAX # deallocate stack - POP_R13 # save &rootdir + POP_R13 # save rootdir # Open file for reading PUSH_RDX # allocate stack for fin diff --git a/amd64/Development/kaem-minimal.S b/amd64/Development/kaem-minimal.S index aa94a86..c7217c2 100644 --- a/amd64/Development/kaem-minimal.S +++ b/amd64/Development/kaem-minimal.S @@ -84,7 +84,7 @@ root_fs: call [rcx+8] # rootfs->open_volume(rootfs, &rootdir) pop rax # deallocate stack pop rax # deallocate stack - pop r13 # save &rootdir + pop r13 # save rootdir # Open file for reading push rdx # allocate stack for fin diff --git a/amd64/Development/kaem-minimal.hex2 b/amd64/Development/kaem-minimal.hex2 index c1225ee..4af0faa 100644 --- a/amd64/Development/kaem-minimal.hex2 +++ b/amd64/Development/kaem-minimal.hex2 @@ -81,7 +81,7 @@ FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415D ; POP_R13 # save &rootdir + 415D ; POP_R13 # save rootdir # Open file for reading 52 ; PUSH_RDX # allocate stack for fin diff --git a/amd64/hex0.hex0 b/amd64/hex0.hex0 index f8154e0..26a7a95 100644 --- a/amd64/hex0.hex0 +++ b/amd64/hex0.hex0 @@ -220,7 +220,7 @@ A3 01 00 00 ; SizeOfRawData FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415E ; POP_R14 # save &rootdir + 415E ; POP_R14 # save rootdir # Open file for writing 52 ; PUSH_RDX # allocate stack for fout diff --git a/amd64/hex1.hex0 b/amd64/hex1.hex0 index dc939aa..fbb9a38 100644 --- a/amd64/hex1.hex0 +++ b/amd64/hex1.hex0 @@ -215,7 +215,7 @@ D4 03 00 00 ; SizeOfRawData FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415E ; POP_R14 # save &rootdir + 415E ; POP_R14 # save rootdir # Open file for reading 52 ; PUSH_RDX # allocate stack for fin diff --git a/amd64/hex2.hex1 b/amd64/hex2.hex1 index 0583f14..6bca914 100644 --- a/amd64/hex2.hex1 +++ b/amd64/hex2.hex1 @@ -222,7 +222,7 @@ F0 00 # SizeOfOptionalHeader 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 + 5B ; POP_RBX # save rootdir # Open file for reading 52 ; PUSH_RDX # allocate stack for fin diff --git a/amd64/kaem-minimal.hex0 b/amd64/kaem-minimal.hex0 index 69eb434..83d2ab1 100644 --- a/amd64/kaem-minimal.hex0 +++ b/amd64/kaem-minimal.hex0 @@ -212,7 +212,7 @@ F7 03 00 00 ; SizeOfRawData FF51 08 ; CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) 58 ; POP_RAX # deallocate stack 58 ; POP_RAX # deallocate stack - 415D ; POP_R13 # save &rootdir + 415D ; POP_R13 # save rootdir # Open file for reading 52 ; PUSH_RDX # allocate stack for fin