From fc79b4a1534218d7db76d6aa8b55e59c7ad0313d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 6 Aug 2022 21:54:11 +0100 Subject: [PATCH] Add kaem-optional M1 and hex2 development prototypes. --- amd64/Development/hex0.M1 | 2 + amd64/Development/hex0.hex2 | 2 + amd64/Development/kaem-optional.M1 | 572 +++++++++++++++++++++++++++ amd64/Development/kaem-optional.S | 76 ++-- amd64/Development/kaem-optional.hex2 | 466 ++++++++++++++++++++++ amd64/PE32-amd64.hex2 | 130 ++++++ amd64/hex0.hex0 | 2 +- 7 files changed, 1203 insertions(+), 47 deletions(-) create mode 100644 amd64/Development/kaem-optional.M1 create mode 100644 amd64/Development/kaem-optional.hex2 create mode 100644 amd64/PE32-amd64.hex2 diff --git a/amd64/Development/hex0.M1 b/amd64/Development/hex0.M1 index 10149fe..5caff18 100644 --- a/amd64/Development/hex0.M1 +++ b/amd64/Development/hex0.M1 @@ -343,3 +343,5 @@ DEFINE TEST_ESI_ESI 85F6 @0x11d2 :SIMPLE_FS_PROTOCOL_8 !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:PE32_end diff --git a/amd64/Development/hex0.hex2 b/amd64/Development/hex0.hex2 index f7ad5c0..fac0838 100644 --- a/amd64/Development/hex0.hex2 +++ b/amd64/Development/hex0.hex2 @@ -281,3 +281,5 @@ D2 11 ; @0x11d2 :SIMPLE_FS_PROTOCOL_8 8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:PE32_end diff --git a/amd64/Development/kaem-optional.M1 b/amd64/Development/kaem-optional.M1 new file mode 100644 index 0000000..ba4bc9f --- /dev/null +++ b/amd64/Development/kaem-optional.M1 @@ -0,0 +1,572 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2017 Jeremiah Orians +# +# SPDX-License-Identifier: GPL-3.0-or-later + +DEFINE ADD_RBX_to_R15 4901DF +DEFINE ADD_RDI_to_R15 4901FF +DEFINE ADD_RSI_to_RBX 4801F3 +DEFINE ADDI8_RAX 4883C0 +DEFINE ADDI8_RBX 4883C3 +DEFINE ADDI8_RSI 4883C6 +DEFINE ADDI8_RSP 4883C4 +DEFINE CALLI32 E8 +DEFINE CALL_RCX_Immediate8 FF51 +DEFINE CALL_R14_Immediate8 41FF56 +DEFINE CALL_R14_Immediate32 41FF96 +DEFINE CMPI8_AL 3C +DEFINE COPY_RAX_to_RCX 4889C1 +DEFINE COPY_RBX_to_RCX 4889C3 +DEFINE COPY_RBX_to_RDX 4889DA +DEFINE COPY_RBX_to_R8 4989D8 +DEFINE COPY_RBX_to_R12 4989DC +DEFINE COPY_RBP_to_RSP 4889EC +DEFINE COPY_RDI_to_RCX 4889F9 +DEFINE COPY_RDI_to_R9 4989F9 +DEFINE COPY_RSI_to_R15 4989F7 +DEFINE COPY_RSP_to_RDX 4889E2 +DEFINE COPY_RSP_to_RBP 4889E5 +DEFINE COPY_RSP_to_R8 4989E0 +DEFINE COPY_R8_to_RAX 4C89C0 +DEFINE COPY_R9_to_RCX 4C89C9 +DEFINE COPY_R12_to_RCX 4C89E1 +DEFINE COPY_R12_to_R8 4D89E0 +DEFINE COPY_R13_to_RCX 4C89E9 +DEFINE COPY_R15_to_RCX 4C89F9 +DEFINE COPY_R15_to_R8 4D89F8 +DEFINE COPY_R15_to_R9 4D89F9 +DEFINE INC_RAX 48FFC0 +DEFINE JE8 74 +DEFINE JMP8 EB +DEFINE JMP32 E9 +DEFINE JNE8 75 +DEFINE JNE32 0F85 +DEFINE LEA_RDX_rel 488D15 +DEFINE LEA_R12_rel 4C8D25 +DEFINE LOAD64_into_RAX_from_Address_RDX_Immediate8 488B42 +DEFINE LOAD64_into_RAX_from_Address_RSP_Immediate8 488B4424 +DEFINE LOAD64_into_RBX_from_Address_RAX_Immediate8 488B58 +DEFINE LOAD64_into_RBX_from_Address_RSP_Immediate8 488B5C24 +DEFINE LOAD64_into_RCX_from_Address_RCX_Immediate8 488B49 +DEFINE LOAD64_into_RCX_from_Address_RSP_Immediate8 488B4C24 +DEFINE LOAD64_into_RDX_from_Address_RCX_Immediate8 488B51 +DEFINE LOAD64_into_R14_from_Address_RDX_Immediate8 4C8B72 +DEFINE LOAD64_into_R12_from_Address_RSP_Immediate8 4C8B6424 +DEFINE LOAD64_into_RDX_rel32 488B15 +DEFINE LOAD64_into_R9_rel32 4C8B0D +DEFINE LOAD8_AL_from_Address_RBX 8A03 +DEFINE LOADI8_DH B6 +DEFINE LOADI64_rel_RCX 488B0D +DEFINE LOADI64_rel_RDX 488B15 +DEFINE POP_RAX 58 +DEFINE POP_RBX 5B +DEFINE POP_RCX 59 +DEFINE POP_RDX 5A +DEFINE POP_RSI 5E +DEFINE POP_RDI 5F +DEFINE POP_R8 4158 +DEFINE POP_R9 4159 +DEFINE POP_R13 415D +DEFINE POP_R14 415E +DEFINE POP_R15 415F +DEFINE PUSH 6A +DEFINE PUSH_RAX 50 +DEFINE PUSH_RDX 52 +DEFINE PUSH_RBX 53 +DEFINE PUSH_RSP 54 +DEFINE PUSH_RSI 56 +DEFINE PUSH_RDI 57 +DEFINE PUSH_R8 4150 +DEFINE PUSH_R9 4151 +DEFINE RET C3 +DEFINE SHR_RSI 48D1EE +DEFINE STORE16_AX_into_Address_RBX 668903 +DEFINE STORE64_R15_into_Address_RAX 4C8938 +DEFINE STORE64_from_RAX_rel32 488905 +DEFINE STORE64_from_RCX_rel32 48890D +DEFINE STORE64_from_RBX_into_Address_RAX_Immediate8 488958 +DEFINE STORE64_from_RCX_into_Address_RCX_Immediate8 488948 +DEFINE STORE64_from_RSI_into_Address_RAX_Immediate8 488970 +DEFINE STOREI8_into_Address_RAX C600 +DEFINE STOREI16_into_Address_RAX 66C700 +DEFINE STOREI32_into_Address_RAX C700 +DEFINE STOREI16_into_Address_RBX 66C703 +DEFINE STOREI16_into_Address_R15 6641C707 +DEFINE STOREI32_into_Address_R8 49C700 +DEFINE SUBI8_RSP 4883EC +DEFINE SUB_RDI_from_R15 4929FF +DEFINE SUB_RSI_from_RBX 4829F3 +DEFINE TEST_AL_AL 84C0 +DEFINE TEST_EAX_EAX 85C0 +DEFINE TEST_ECX_ECX 85C9 +DEFINE TEST_R15_R15 4D85FF +DEFINE XOR_ECX_ECX 31C9 +DEFINE XOR_EDX_EDX 31D2 +DEFINE XOR_ESI_ESI 31F6 +DEFINE XOR_R8_R8 4D31C0 +DEFINE XOR_R9_R9 4D31C9 +DEFINE XOR_R15_R15 4D31FF + +# efi_main(void *image_handle, struct efi_system_table *system) +:_start + COPY_RSP_to_RBP # save stack pointer + STORE64_from_RCX_rel32 %image_handle # save image_handle + LOAD64_into_RAX_from_Address_RDX_Immediate8 !64 # system->out + STORE64_from_RAX_rel32 %system_out # save system->out + LOAD64_into_R14_from_Address_RDX_Immediate8 !96 # system->boot + + XOR_ECX_ECX # timeout = 0 + XOR_EDX_EDX # watchdog_code = 0 + XOR_R8_R8 # data_size = 0 + XOR_R9_R9 # watchdog_data = 0 + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_R14_Immediate32 %240 # system->boot->set_watchdog_timer + + # Open Loaded Image protocol + PUSH_RAX # allocate stack for image + COPY_RSP_to_R8 # arg3 = &image + LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + PUSH_RDX # push last 64 bits onto stack + LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + PUSH_RDX # push first 64 bits onto stack + COPY_RSP_to_RDX # arg2 = &guid + PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + PUSH !0 # arg5 = NULL + LOAD64_into_R9_rel32 %image_handle # arg4 = image_handle + COPY_R9_to_RCX # arg1 = image_handle + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_R14_Immediate32 %280 # system->boot->open_protocol(image_handle, &guid, &image, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + LOAD64_into_RAX_from_Address_RSP_Immediate8 !64 # get_image + STORE64_from_RAX_rel32 %image # save image + + # Command line args + COPY_RAX_to_RCX # copy image to rcx + LOAD64_into_RBX_from_Address_RAX_Immediate8 !56 # options = image->load_options + + # Skip application name +:loop_options1 + ADDI8_RBX !2 # ++options + LOAD8_AL_from_Address_RBX # *options + CMPI8_AL !0x20 # if *options == ' ' + JE8 !loop_options2 # then jump + TEST_AL_AL # if options != 0 + JNE8 !loop_options1 # then loop + + # Use default file + LEA_R12_rel %default_file # Use "kaem.amd64" + JMP8 !root_fs # jump + +:loop_options2 + ADDI8_RBX !2 # ++options + COPY_RBX_to_R12 # save input file + +:root_fs + # Get root file system + PUSH_RAX # allocate stack for rootfs + COPY_RSP_to_R8 # arg3 = &rootfs + LOADI64_rel_RDX %SIMPLE_FS_PROTOCOL_8 # SIMPLE_FS_PROTOCOL (last 64 bits) + PUSH_RDX # push last 64 bits onto stack + LOADI64_rel_RDX %SIMPLE_FS_PROTOCOL # SIMPLE_FS_PROTOCOL (first 64 bits) + PUSH_RDX # push first 64 bits onto stack + COPY_RSP_to_RDX # arg2 = &guid + PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + PUSH !0 # arg5 = NULL + LOAD64_into_R9_rel32 %image_handle # arg4 = image_handle + LOAD64_into_RCX_from_Address_RCX_Immediate8 !24 # arg1 = root_device = image->device + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_R14_Immediate32 %280 # system->boot->open_protocol(root_device, &guid, &rootfs, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + LOAD64_into_RCX_from_Address_RSP_Immediate8 !64 # get rootfs + + # Get root directory + PUSH_RDX # allocate stack for rootdir + COPY_RSP_to_RDX # arg2 = &rootdir + PUSH_RAX # allocate shadow stack space for UEFI function + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_RCX_Immediate8 !8 # rootfs->open_volume(rootfs, &rootdir) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_R13 # save &rootdir + + # Open file for reading + PUSH_RDX # allocate stack for fin + COPY_RSP_to_RDX # 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 + COPY_R12_to_R8 # arg3 = in + COPY_R13_to_RCX # arg1 = rootdir + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_RCX_Immediate8 !8 # rootdir->open() + TEST_EAX_EAX # if status != EFI_SUCCESS + JNE32 %abort # then exit without closing file + LOAD64_into_R12_from_Address_RSP_Immediate8 !40 # get fin + + # Allocate pool for command + PUSH_RDX # allocate stack for command + COPY_RSP_to_R8 # arg3 = &command + XOR_EDX_EDX # zero RDX + LOADI8_DH !0x10 # arg2 = 4096 = 0x1000 + PUSH !2 + POP_RCX # arg1 = EFI_LOADER_DATA + 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_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand) + LOAD64_into_RBX_from_Address_RSP_Immediate8 !24 # get command + +:next_command + XOR_ESI_ESI # i = 0 + XOR_R15_R15 # command_length = 0 + +:read_command + CALLI32 %read_byte # read another byte c + + CMPI8_AL !0xa # if c == '\n' + JE8 !read_command_done # then we are done with this command + + CMPI8_AL !0x20 # if c == ' ' + JNE8 !read_command_comments + TEST_R15_R15 # and command_length == 0 + JNE8 !read_command_comments + COPY_RSI_to_R15 # command_length = i + +:read_command_comments + CMPI8_AL !0x23 # if c == '#' then process comment + JNE8 !read_command_store_char # else store char + +:read_command_skip_comment + CALLI32 %read_byte # get another char + CMPI8_AL !0xa # if c == '\n' + JNE8 !read_command_skip_comment # continue reading until newline + + JMP8 !next_command # deal with another line + +:read_command_store_char + ADD_RSI_to_RBX # rbx = &command[i] + STORE16_AX_into_Address_RBX # command[i] = c + SUB_RSI_from_RBX # rbx = &command[0] + ADDI8_RSI !2 # location of the next char + JMP8 !read_command # continue looping + +:read_command_done + TEST_R15_R15 # if command_length == 0 + JE8 !next_command # deal with another line + + ADD_RSI_to_RBX # rbx = &command[i] + STOREI16_into_Address_RBX @0 # command[i] = 0 + SUB_RSI_from_RBX # rbx = &command[0] + + SHR_RSI # divide i by 2 to go from char to wchar length + + LEA_RDX_rel %prefix # get prefix " +> " + CALLI32 %File_Print # print it + COPY_RBX_to_RDX # get command + CALLI32 %File_Print # print it + LEA_RDX_rel %suffix # get suffix "\n\r" + CALLI32 %File_Print # print it + + # Remove command line options + ADD_RBX_to_R15 # go to the space separating command and its options + STOREI16_into_Address_R15 @0 # zero it to hide command line options + + # Open executable file for reading + PUSH_RDX # allocate stack for fcmd + COPY_RSP_to_RDX # arg2 = &fcmd + 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 + COPY_RBX_to_R8 # arg3 = command + COPY_R13_to_RCX # arg1 = rootdir + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_RCX_Immediate8 !8 # rootdir->open() + TEST_EAX_EAX # if status != EFI_SUCCESS + JNE32 %print_error # then exit + ADDI8_RSP !40 # deallocate stack + POP_RDI # get fcmd + + # Restore command line arguments + STOREI16_into_Address_R15 @0x20 # restore command line options by readding ' ' + + # Allocate pool for file_info + PUSH_RDX # allocate stack for file_info + COPY_RSP_to_R8 # arg3 = &file_info + XOR_EDX_EDX # zero RDX + LOADI8_DH !0x10 # arg2 = 4096 = 0x1000 + PUSH !2 + POP_RCX # arg1 = EFI_LOADER_DATA + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &file_info) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_R9 # get file_info (arg4 for get_info) + + # Get file info + PUSH_R9 # save file_info + PUSH_RAX # allocate stack for file_size + COPY_RSP_to_R8 # arg3 = &file_size + STOREI32_into_Address_R8 %0x1000 # file_size = 0x1000 + LOADI64_rel_RDX %SIMPLE_FS_PROTOCOL_8 # EFI_FILE_INFO_PROTOCOL (last 64 bits) + PUSH_RDX # push last 64 bits onto stack + LOADI64_rel_RDX %FILE_INFO_PROTOCOL # EFI_FILE_INFO_PROTOCOL (first 64 bits) + PUSH_RDX # push first 64 bits onto stack + COPY_RSP_to_RDX # arg2 = &guid + COPY_RDI_to_RCX # arg1 = fcmd + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_RCX_Immediate8 !64 # fcmd->get_info(fcmd, &guid, &file_size, file_info) + ADDI8_RSP !56 # deallocate stack + POP_RCX # restore file_info + LOAD64_into_RDX_from_Address_RCX_Immediate8 !8 # get file_size + + # Free file_info pool + PUSH_RDX # save file_size onto stack + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_R14_Immediate8 !72 # system->boot->free_pool(file_info) + POP_RAX # deallocate stack + POP_RDX # restore file_size from stack (arg2 for allocate_pool) + + # Allocate pool for executable + PUSH_RDX # save file_size onto stack + PUSH_RDX # allocate stack for executable + COPY_RSP_to_R8 # arg3 = &executable + PUSH !2 + POP_RCX # arg1 = EFI_LOADER_DATA + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, file_size, &executable) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_R15 # get executable + POP_RDX # restore file_size + + # Load executable into memory + PUSH_RDX # save file_size onto stack + COPY_R15_to_R8 # arg3 = executable + COPY_RSP_to_RDX # arg2 = &file_size + COPY_RDI_to_RCX # arg1 = fcmd + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + CALL_RCX_Immediate8 !32 # fcmd->read(fcmd, &file_size, executable) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # deallocate stack + + # Close fcmd + PUSH_RAX # allocate stack + COPY_RDI_to_RCX # arg1 = fcmd + CALL_RCX_Immediate8 !16 # fcmd->close(fcmd) + POP_RAX # restore stack + + POP_RDI # restore file_size + + # Allocate memory for device_path struct + PUSH_RDX # allocate stack for device_path + COPY_RSP_to_R8 # arg3 = &device_path + PUSH !28 # 4 + sizeof(struct efi_device_path_protocol) + POP_RDX # arg2 = 28 + PUSH !2 + POP_RCX # arg1 = EFI_LOADER_DATA + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 28, &device_path) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_R8 # get device_path + + # Initialize struct + COPY_R8_to_RAX # Make a pointer to device_path members + STOREI8_into_Address_RAX !1 # device_path->type = HARDWARE_DEVICE_PATH + INC_RAX # next member + STOREI8_into_Address_RAX !3 # device_path->subtype = MEMORY_MAPPED + INC_RAX # next member + STOREI16_into_Address_RAX @24 # device_path->length = 24 + ADDI8_RAX !2 # next member + STOREI32_into_Address_RAX %1 # device_path->memory_type = EFI_LOADER_CODE + ADDI8_RAX !4 # next member + STORE64_R15_into_Address_RAX # device_path->start_address = executable + ADDI8_RAX !8 # next member + ADD_RDI_to_R15 # end_address = executable + file_size + STORE64_R15_into_Address_RAX # device_path->end_address = end_address + SUB_RDI_from_R15 # restore r15 = executable + ADDI8_RAX !8 # next member + STOREI8_into_Address_RAX !0x7f # device_path[1].type = END_HARDWARE_DEVICE_PATH + INC_RAX # next member + STOREI8_into_Address_RAX !0xff # device_path[1].subtype = END_ENTIRE_DEVICE_PATH + INC_RAX # next member + STOREI16_into_Address_RAX @4 # device_path[1].length = 4 + + # Load image + PUSH_R8 # save device_path + PUSH_RAX # allocate stack for child_ih + PUSH_RSP # arg6 = &child_ih + PUSH_RDI # arg5 = file size + COPY_R15_to_R9 # arg4 = executable + # arg3 = device_path + LOAD64_into_RDX_rel32 %image_handle # arg2 = image_handle + XOR_ECX_ECX # arg1 = 0 + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_R14_Immediate32 %200 # system->boot->load_image() + ADDI8_RSP !48 # deallocate stack + POP_RDI # save child_ih + + # Free device_path pool + POP_RCX # arg1 = device_path + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_R14_Immediate8 !72 # system->boot->free_pool(device_path) + POP_RAX # deallocate stack + + # Free executable pool + COPY_R15_to_RCX # arg1 = executable + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_R14_Immediate8 !72 # system->boot->free_pool(executable) + POP_RAX # deallocate stack + + # Open Child Image + PUSH_RAX # allocate stack for child_image + COPY_RSP_to_R8 # arg3 = &child_image + LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL_8 # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits) + PUSH_RDX # push last 64 bits onto stack + LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + PUSH_RDX # push first 64 bits onto stack + COPY_RSP_to_RDX # arg2 = &guid + PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + PUSH !0 # arg5 = NULL + COPY_RDI_to_R9 # arg4 = child_ih + COPY_RDI_to_RCX # arg1 = child_ih + SUBI8_RSP !32 # allocate shadow stack space for UEFI function + CALL_R14_Immediate32 %280 # system->boot->open_protocol(child_ih, &guid, &child_image, child_ih, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + ADDI8_RSP !64 # deallocate stack + POP_RAX # get child_image + + STORE64_from_RBX_into_Address_RAX_Immediate8 !56 # child_image->load_options = command + STORE64_from_RSI_into_Address_RAX_Immediate8 !48 # set child_image->load_options_size + LOADI64_rel_RCX %image # get image + LOAD64_into_RCX_from_Address_RCX_Immediate8 !24 # image->device + STORE64_from_RCX_into_Address_RCX_Immediate8 !24 # child_image->device = image->device + + # Run command + XOR_R8_R8 # arg3 = 0 (ExitData) + XOR_EDX_EDX # arg2 = 0 (ExitData size) + COPY_RDI_to_RCX # arg1 = child_ih + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + PUSH_RAX # allocate shadow stack space for UEFI + CALL_R14_Immediate32 %208 # system->boot->start_image() + POP_RCX # deallocate stack + POP_RCX # deallocate stack + POP_RCX # deallocate stack + + TEST_EAX_EAX # check if return code is 0 + JNE8 !print_error # print error and exit + JMP32 %next_command # process another line from kaem script + +:print_error + PUSH_RAX # save exit code + LOAD64_into_RDX_rel32 %subprocess_error # get error message + CALLI32 %File_Print # print it + POP_RAX # restore exit code + +# Close script file and exit +:terminate + # Free pool + COPY_RBX_to_RCX # arg1 = command + PUSH_RAX # save exit code + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_R14_Immediate8 !72 # system->boot->free_pool(commmand) + + COPY_R12_to_RCX # arg1 = fin + CALL_RCX_Immediate8 !16 # fin->close(fin) + POP_RAX # deallocate stack + POP_RAX # restore exit code + +# Exit without closing script file +:abort + COPY_RBP_to_RSP # restore stack + RET + +# File_Print function +# Receives WCHAR* in RDX +:File_Print + LOADI64_rel_RCX %system_out # get system_out + PUSH_RAX # allocate shadow stack space for UEFI function + PUSH_RAX # allocate shadow stack space for UEFI function + CALL_RCX_Immediate8 !8 # system->out->output_string(system->out, WCHAR*) + POP_RAX # deallocate stack + POP_RAX # deallocate stack + RET + +# read_byte function +# reads a single character +:read_byte + COPY_R12_to_RCX # arg1 = fin + PUSH !1 # size = 1 + COPY_RSP_to_RDX # arg2 = &size + PUSH_RSI # allocate stack + COPY_RSP_to_R8 # arg3 = &c + 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_Immediate8 !32 # fin->read() + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # deallocate stack + POP_RAX # save c to rax + POP_RCX # save size to rcx + + # If the file ended (0 bytes read) terminate + TEST_ECX_ECX # if size = 0 + JE8 !terminate # then we are done + + RET # return + + +# Protocol GUIDs +:LOADED_IMAGE_PROTOCOL + %0x5b1b31a1 + @0x9562 + @0x11d2 +:LOADED_IMAGE_PROTOCOL_8 + !0x8e !0x3f !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:SIMPLE_FS_PROTOCOL + %0x0964e5b22 + @0x6459 + @0x11d2 +:SIMPLE_FS_PROTOCOL_8 + !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:FILE_INFO_PROTOCOL + %0x09576e92 + @0x6d3f + @0x11d2 +# last 64-bits of GUID are identical to SIMPLE_FS_PROTOCOL + +:default_file + "k" "a" "e" "m" "." "a" "m" "d" "6" "4" @0 + +:prefix + " " "+" ">" " " @0 + +:subprocess_error + "S" "u" "b" "p" "r" "o" "c" "e" "s" "s" " " + "e" "r" "r" "o" "r" +:suffix + !0xa !0 !0xd !0 @0 # L"\n\r" + +:image_handle + %0 %0 + +:image + %0 %0 + +:system_out + %0 %0 + +:PE32_end diff --git a/amd64/Development/kaem-optional.S b/amd64/Development/kaem-optional.S index b15aa5d..f39fdd0 100644 --- a/amd64/Development/kaem-optional.S +++ b/amd64/Development/kaem-optional.S @@ -3,19 +3,6 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -# Usage: hex0 file.hex0 file -# Does not validate the arguments or check for success - -# Calling convention: -# First four arguments are passed via registers rcx, rdx, r8, r9 (if they fit in 64-bits) -# but we need to leave stack space -# rax, rcx, rdx, r8, r9, r10 and r11 are volatile and can be changed by called function - -# Registers: -# r12 script/fin: first output file name, later reused for script file handle -# r13 rootdir -# r14 system->boot from UEFI - .global _start .text @@ -49,9 +36,9 @@ _start: 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 [rip+image], rax # save image # Command line args - mov [rip+image], rax # save image mov rcx, rax # copy image to rcx mov rbx, [rax+56] # options = image->load_options @@ -86,7 +73,7 @@ root_fs: mov r9, [rip+image_handle] # 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); + 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 @@ -99,7 +86,7 @@ root_fs: pop rax # deallocate stack pop r13 # save &rootdir - ## Open file for reading + # Open file for reading push rdx # allocate stack for fin mov rdx, rsp # arg2 = &fin push 1 # arg5 = EFI_FILE_READ_ONLY @@ -170,7 +157,7 @@ read_command_done: shr rsi # divide i by 2 to go from char to wchar length - lea rdx, [rip+prefix] # get prefix "+>" + lea rdx, [rip+prefix] # get prefix " +> " call File_Print # print it mov rdx, rbx # get command call File_Print # print it @@ -192,9 +179,9 @@ read_command_done: sub rsp, 32 # allocate shadow stack space for UEFI function call [rcx+8] # rootdir->open() test eax, eax # if status != EFI_SUCCESS - jne terminate # then exit - add rsp, 32 # deallocate stack - mov rdi, [rsp+8] # get fcmd + jne print_error # then exit + add rsp, 40 # deallocate stack + pop rdi # get fcmd # Restore command line arguments mov WORD PTR [r15], 0x20 # restore command line options by readding ' ' @@ -209,7 +196,7 @@ read_command_done: 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 [r14+64] # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand) + call [r14+64] # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &file_info) pop rax # deallocate stack pop rax # deallocate stack pop rax # deallocate stack @@ -255,7 +242,7 @@ read_command_done: pop r15 # get executable pop rdx # restore file_size - # Load executable to memory + # Load executable into memory push rdx # save file_size onto stack mov r8, r15 # arg3 = executable mov rdx, rsp # arg2 = &file_size @@ -271,7 +258,7 @@ read_command_done: # Close fcmd push rax # allocate stack mov rcx, rdi # arg1 = fcmd - call [rcx+16] # fin->close() + call [rcx+16] # fcmd->close(fcmd) pop rax # restore stack pop rdi # restore file_size @@ -353,9 +340,9 @@ read_command_done: mov r9, rdi # arg4 = child_ih mov rcx, rdi # arg1 = child_ih sub rsp, 32 # allocate shadow stack space for UEFI function - call [r14+280] # system->boot->open_protocol(child_ih, &guid, &image, child_ih, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + call [r14+280] # system->boot->open_protocol(child_ih, &guid, &child_image, child_ih, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) add rsp, 64 # deallocate stack - pop rax # get image + pop rax # get child_image mov [rax+56], rbx # child_image->load_options = command mov [rax+48], rsi # set child_image->load_options_size @@ -364,8 +351,8 @@ read_command_done: mov [rax+24], rcx # child_image->device = image->device # Run command - xor r8, r8 # arg3 = 0 - xor rdx, rdx # arg2 = 0 + xor r8, r8 # arg3 = 0 (ExitData) + xor edx, edx # arg2 = 0 (ExitData size) mov rcx, rdi # arg1 = child_ih push rax # allocate shadow stack space for UEFI function push rax # allocate shadow stack space for UEFI function @@ -376,8 +363,8 @@ read_command_done: pop rcx # deallocate stack test eax, eax # check if return code is 0 - jne print_error - jmp next_command + jne print_error # print error and exit + jmp next_command # process another line from kaem script print_error: push rax # save exit code @@ -389,14 +376,14 @@ print_error: terminate: # Free pool mov rcx, rbx # arg1 = command - mov rbx, rax # save exit code + push rax # save exit code push rax # allocate shadow stack space for UEFI function call [r14+72] # system->boot->free_pool(commmand) - push rax # allocate stack mov rcx, r12 # arg1 = fin - call [rcx+16] # fin->close() - mov rax, rbx # restore exit code + call [rcx+16] # fin->close(fin) + pop rax # deallocate stack + pop rax # restore exit code # Exit without closing script file abort: @@ -409,7 +396,7 @@ File_Print: mov rcx, [rip+system_out] # get system_out push rax # allocate shadow stack space for UEFI function push rax # allocate shadow stack space for UEFI function - call [rcx+8] # system->out->output_string(system->out, WCHAR*); + call [rcx+8] # system->out->output_string(system->out, WCHAR*) pop rax # deallocate stack pop rax # deallocate stack ret @@ -417,20 +404,20 @@ File_Print: # read_byte function # reads a single character read_byte: - mov rcx, r12 # arg1 = fin + mov rcx, r12 # arg1 = fin push 1 # size = 1 - mov rdx, rsp # arg2 = &size + mov rdx, rsp # arg2 = &size push rsi # allocate stack - mov r8, rsp # arg3 = &c + mov r8, rsp # arg3 = &c 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 c to rax - pop rcx # save size to rcx + pop rax # deallocate stack + pop rax # deallocate stack + pop rax # deallocate stack + pop rax # save c to rax + pop rcx # save size to rcx # If the file ended (0 bytes read) terminate test ecx, ecx # if size == 0 @@ -466,12 +453,10 @@ default_file: prefix: .byte 0x20, 0, 0x2B, 0, 0x3E, 0, 0x20, 0, 0, 0 # L" +> " -suffix: -.byte 0x0a, 0, 0x0d, 0, 0, 0 # L"\n\r" - subprocess_error: .byte 0x53, 0, 0x75, 0, 0x62, 0, 0x70, 0, 0x72, 0, 0x6F, 0, 0x63, 0, 0x65, 0 .byte 0x73, 0, 0x73, 0, 0x20, 0, 0x65, 0, 0x72, 0, 0x72, 0, 0x6F, 0, 0x72, 0 +suffix: .byte 0x0A, 0, 0x0D, 0, 0, 0 # L"Subprocess error\n\r" image_handle: @@ -482,4 +467,3 @@ image: system_out: .long 0, 0 - diff --git a/amd64/Development/kaem-optional.hex2 b/amd64/Development/kaem-optional.hex2 new file mode 100644 index 0000000..aae23d3 --- /dev/null +++ b/amd64/Development/kaem-optional.hex2 @@ -0,0 +1,466 @@ +# SPDX-FileCopyrightText: 2022 Andrius Štikonas +# SPDX-FileCopyrightText: 2017 Jeremiah Orians +# +# SPDX-License-Identifier: GPL-3.0-or-later + +# efi_main(void *image_handle, struct efi_system_table *system) +:_start + 4889E5 ; COPY_RSP_to_RBP # save stack pointer + 48890D %image_handle ; STORE64_from_RCX_rel32 %image_handle # save image_handle + 488B42 40 ; LOAD64_into_RAX_from_Address_RDX_Immediate8 !64 # system->out + 488905 %system_out ; STORE64_from_RAX_rel32 %system_out # save system->out + 4C8B72 60 ; LOAD64_into_R14_from_Address_RDX_Immediate8 !96 # system->boot + + 31C9 ; XOR_ECX_ECX # timeout = 0 + 31D2 ; XOR_EDX_EDX # watchdog_code = 0 + 4D31C0 ; XOR_R8_R8 # data_size = 0 + 4D31C9 ; XOR_R9_R9 # watchdog_data = 0 + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + 41FF96 F0000000 ; CALL_R14_Immediate32 %240 # system->boot->set_watchdog_timer + + # Open Loaded Image protocol + 50 ; PUSH_RAX # allocate stack for image + 4989E0 ; COPY_RSP_to_R8 # arg3 = &image + 488B15 %LOADED_IMAGE_PROTOCOL_8 ; LOADI64_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 ; LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + 52 ; PUSH_RDX # push first 64 bits onto + 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid + 6A 01 ; PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + 6A 00 ; PUSH !0 # arg5 = NULL + 4C8B0D %image_handle ; LOAD64_into_R9_rel32 %image_handle # arg4 = image_handle + 4C89C9 ; COPY_R9_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 + 488905 %image ; STORE64_from_RAX_rel32 %image # save image + + # Command line args + 4889C1 ; COPY_RAX_to_RCX # copy image to rcx + 488B58 38 ; LOAD64_into_RBX_from_Address_RAX_Immediate8 !56 # options = image->load_options + + # Skip application name +:loop_options1 + 4883C3 02 ; ADDI8_RBX !2 # ++options + 8A03 ; LOAD8_AL_from_Address_RBX # *options + 3C 20 ; CMPI8_AL !0x20 # if *options == ' ' + 74 !loop_options2 ; JE8 !loop_options2 # then jump + 84C0 ; TEST_AL_AL # if options != 0 + 75 !loop_options1 ; JNE8 !loop_options1 # then loop + + # Use default file + 4C8D25 %default_file ; LEA_R12_rel %default_file # Use "kaem.amd64" + EB !root_fs ; JMP8 !root_fs # jump + +:loop_options2 + 4883C3 02 ; ADDI8_RBX !2 # ++options + 4989DC ; COPY_RBX_to_R12 # save input file + +:root_fs + # Get root file system + 50 ; PUSH_RAX # allocate stack for rootfs + 4989E0 ; COPY_RSP_to_R8 # arg3 = &rootfs + 488B15 %SIMPLE_FS_PROTOCOL_8 ; LOADI64_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 %SIMPLE_FS_PROTOCOL ; LOADI64_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 + 4C8B0D %image_handle ; LOAD64_into_R9_rel32 %image_handle # 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 # arg3 = &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 + 415D ; POP_R13 # 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 + 4C89E9 ; COPY_R13_to_RCX # arg1 = rootdir + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + FF51 08 ; CALL_RCX_Immediate8 !8 # rootdir->open() + 85C0 ; TEST_EAX_EAX # if status != EFI_SUCCESS + 0F85 %abort ; JNE32 %abort # then exit without closing file + 4C8B6424 28 ; LOAD64_into_R12_from_Address_RSP_Immediate8 !40 # get fin + + # Allocate pool for command + 52 ; PUSH_RDX # allocate stack for command + 4989E0 ; COPY_RSP_to_R8 # arg3 = &command + 31D2 ; XOR_EDX_EDX # zero RDX + B6 10 ; LOADI8_DH !0x10 # arg2 = 4096 = 0x1000 + 6A 02 ; PUSH !2 + 59 ; POP_RCX # arg1 = EFI_LOADER_DATA + 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 + 41FF56 40 ; CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand) + 488B5C24 18 ; LOAD64_into_RBX_from_Address_RSP_Immediate8 !24 # get command + +:next_command + 31F6 ; XOR_ESI_ESI # i = 0 + 4D31FF ; XOR_R15_R15 # command_length = 0 + +:read_command + E8 %read_byte ; CALLI32 %read_byte # read another byte c + + 3C 0A ; CMPI8_AL !0xa # if c == '\n' + 74 !read_command_done ; JE8 !read_command_done # then we are done with this command + + 3C 20 ; CMPI8_AL !0x20 # if c == ' ' + 75 !read_command_comments ; JNE8 !read_command_comments + 4D85FF ; TEST_R15_R15 # and command_length == 0 + 75 !read_command_comments ; JNE8 !read_command_comments + 4989F7 ; COPY_RSI_to_R15 # command_length = i + +:read_command_comments + 3C 23 ; CMPI8_AL !0x23 # if c == '#' then process comment + 75 !read_command_store_char ; JNE8 !read_command_store_char # else store char + +:read_command_skip_comment + E8 %read_byte ; CALLI32 %read_byte # get another char + 3C 0A ; CMPI8_AL !0xa # if c == '\n' + 75 !read_command_skip_comment ; JNE8 !read_command_skip_comment # continue reading until newline + + EB !next_command ; JMP8 !next_command # deal with another line + +:read_command_store_char + 4801F3 ; ADD_RSI_to_RBX # rbx = &command[i] + 668903 ; STORE16_AX_into_Address_RBX # command[i] = c + 4829F3 ; SUB_RSI_from_RBX # rbx = &command[0] + 4883C6 02 ; ADDI8_RSI !2 # location of the next char + EB !read_command ; JMP8 !read_command # continue looping + +:read_command_done + 4D85FF ; TEST_R15_R15 # if command_length == 0 + 74 !next_command ; JE8 !next_command # deal with another line + + 4801F3 ; ADD_RSI_to_RBX # rbx = &command[i] + 66C703 0000 ; STOREI16_into_Address_RBX @0 # command[i] = 0 + 4829F3 ; SUB_RSI_from_RBX # rbx = &command[0] + + 48D1EE ; SHR_RSI # divide i by 2 to go from char to wchar length + + 488D15 %prefix ; LEA_RDX_rel %prefix # get prefix " +> " + E8 %File_Print ; CALLI32 %File_Print # print it + 4889DA ; COPY_RBX_to_RDX # get command + E8 %File_Print ; CALLI32 %File_Print # print it + 488D15 %suffix ; LEA_RDX_rel %suffix # get suffix "\n\r" + E8 %File_Print ; CALLI32 %File_Print # print it + + # Remove command line options + 4901DF ; ADD_RBX_to_R15 # go to the space separating command and its options + 6641C707 0000 ; STOREI16_into_Address_R15 @0 # zero it to hide command line options + + # Open executable file for reading + 52 ; PUSH_RDX # allocate stack for fcmd + 4889E2 ; COPY_RSP_to_RDX # arg2 = &fcmd + 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 + 4989D8 ; COPY_RBX_to_R8 # arg3 = command + 4C89E9 ; COPY_R13_to_RCX # arg1 = rootdir + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + FF51 08 ; CALL_RCX_Immediate8 !8 # rootdir->open() + 85C0 ; TEST_EAX_EAX # if status != EFI_SUCCESS + 0F85 %print_error ; JNE32 %print_error # then exit + 4883C4 28 ; ADDI8_RSP !40 # deallocate stack + 5F ; POP_RDI # get fcmd + + # Restore command line arguments + 6641C707 2000 ; STOREI16_into_Address_R15 @0x20 # restore command line options by readding ' ' + + # Allocate pool for file_info + 52 ; PUSH_RDX # allocate stack for file_info + 4989E0 ; COPY_RSP_to_R8 # arg3 = &file_info + 31D2 ; XOR_EDX_EDX # zero RDX + B6 10 ; LOADI8_DH !0x10 # arg2 = 4096 = 0x1000 + 6A 02 ; PUSH !2 + 59 ; POP_RCX # arg1 = EFI_LOADER_DATA + 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 + 41FF56 40 ; CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 4159 ; POP_R9 # get file_info (arg4 for get_info) + + # Get file info + 4151 ; PUSH_R9 # save file_info + 50 ; PUSH_RAX # allocate stack for file_size + 4989E0 ; COPY_RSP_to_R8 # arg3 = &file_size + 49C700 00100000 ; STOREI32_into_Address_R8 %0x1000 # file_size = 0x1000 + 488B15 %SIMPLE_FS_PROTOCOL_8 ; LOADI64_rel_RDX %SIMPLE_FS_PROTOCOL_8 # EFI_FILE_INFO_PROTOCOL (last 64 bits) + 52 ; PUSH_RDX # push last 64 bits onto stack + 488B15 %FILE_INFO_PROTOCOL ; LOADI64_rel_RDX %FILE_INFO_PROTOCOL # EFI_FILE_INFO_PROTOCOL (first 64 bits) + 52 ; PUSH_RDX # push first 64 bits onto stack + 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid + 4889F9 ; COPY_RDI_to_RCX # arg1 = fcmd + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + FF51 40 ; CALL_RCX_Immediate8 !64 # fcmd->get_info(fcmd, &guid, &file_size, file_info) + 4883C4 38 ; ADDI8_RSP !56 # deallocate stack + 59 ; POP_RCX # restore file_info + 488B51 08 ; LOAD64_into_RDX_from_Address_RCX_Immediate8 !8 # get file_size + + # Free file_info pool + 52 ; PUSH_RDX # save file_size onto stack + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(file_info) + 58 ; POP_RAX # deallocate stack + 5A ; POP_RDX # restore file_size from stack (arg2 for allocate_pool) + + # Allocate pool for executable + 52 ; PUSH_RDX # save file_size onto stack + 52 ; PUSH_RDX # allocate stack for executable + 4989E0 ; COPY_RSP_to_R8 # arg3 = &executable + 6A 02 ; PUSH !2 + 59 ; POP_RCX # arg1 = EFI_LOADER_DATA + 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 + 41FF56 40 ; CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, file_size, &executable) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 415F ; POP_R15 # get executable + 5A ; POP_RDX # restore file_size + + # Load executable into memory + 52 ; PUSH_RDX # save file_size onto stack + 4D89F8 ; COPY_R15_to_R8 # arg3 = executable + 4889E2 ; COPY_RSP_to_RDX # arg2 = &file_size + 4889F9 ; COPY_RDI_to_RCX # arg1 = fcmd + 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 # fcmd->read(fcmd, &file_size, executable) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + + # Close fcmd + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 4889F9 ; COPY_RDI_to_RCX # arg1 = fcmd + FF51 10 ; CALL_RCX_Immediate8 !16 # fcmd->close(fcmd) + 58 ; POP_RAX # deallocate stack + + 5F ; POP_RDI # restore file_size + + # Allocate memory for device_path struct + 52 ; PUSH_RDX # allocate stack for device_path + 4989E0 ; COPY_RSP_to_R8 # arg3 = &device_path + 6A 1C ; PUSH !28 # 4 + sizeof(struct efi_device_path_protocol) + 5A ; POP_RDX # arg2 = 28 + 6A 02 ; PUSH !2 + 59 ; POP_RCX # arg1 = EFI_LOADER_DATA + 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 + 41FF56 40 ; CALL_R14_Immediate8 !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 28, &device_path) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + 4158 ; POP_R8 # get device_path + + # Initialize struct + 4C89C0 ; COPY_R8_to_RAX # Make a pointer to device_path members + C600 01 ; STOREI8_into_Address_RAX !1 # device_path->type = HARDWARE_DEVICE_PATH + 48FFC0 ; INC_RAX # next member + C600 03 ; STOREI8_into_Address_RAX !3 # device_path->subtype = MEMORY_MAPPED + 48FFC0 ; INC_RAX # next member + 66C700 1800 ; STOREI16_into_Address_RAX @24 # device_path->length = 24 + 4883C0 02 ; ADDI8_RAX !2 # next member + C700 01000000 ; STOREI32_into_Address_RAX %1 # device_path->memory_type = EFI_LOADER_CODE + 4883C0 04 ; ADDI8_RAX !4 # next member + 4C8938 ; STORE64_R15_into_Address_RAX # device_path->start_address = executable + 4883C0 08 ; ADDI8_RAX !8 # next member + 4901FF ; ADD_RDI_to_R15 # end_address = executable + file_size + 4C8938 ; STORE64_R15_into_Address_RAX # device_path->end_address = end_address + 4929FF ; SUB_RDI_from_R15 # restore r15 = executable + 4883C0 08 ; ADDI8_RAX !8 # next member + C600 7F ; STOREI8_into_Address_RAX !0x7f # device_path[1].type = END_HARDWARE_DEVICE_PATH + 48FFC0 ; INC_RAX # next member + C600 FF ; STOREI8_into_Address_RAX !0xff # device_path[1].subtype = END_ENTIRE_DEVICE_PATH + 48FFC0 ; INC_RAX # next member + 66C700 0400 ; STOREI16_into_Address_RAX @4 # device_path[1].length = 4 + + # Load image + 4150 ; PUSH_R8 # save device_path + 50 ; PUSH_RAX # allocate stack for child_ih + 54 ; PUSH_RSP # arg6 = &child_ih + 57 ; PUSH_RDI # arg5 = file size + 4D89F9 ; COPY_R15_to_R9 # arg4 = executable + # arg3 = device_path + 488B15 %image_handle ; LOAD64_into_RDX_rel32 %image_handle # arg2 = image_handle + 31C9 ; XOR_ECX_ECX # arg1 = 0 + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + 41FF96 C8000000 ; CALL_R14_Immediate32 %200 # system->boot->load_image() + 4883C4 30 ; ADDI8_RSP !48 # deallocate stack + 5F ; POP_RDI # save child_ih + + # Free device_path pool + 59 ; POP_RCX # arg1 = device_path + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(device_path) + 58 ; POP_RAX # deallocate stack + + # Free executable pool + 4C89F9 ; COPY_R15_to_RCX # arg1 = executable + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(executable) + 58 ; POP_RAX # deallocate stack + + # Open Child Image + 50 ; PUSH_RAX # allocate stack for child_image + 4989E0 ; COPY_RSP_to_R8 # arg3 = &child_image + 488B15 %LOADED_IMAGE_PROTOCOL_8 ; LOADI64_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 ; LOADI64_rel_RDX %LOADED_IMAGE_PROTOCOL # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits) + 52 ; PUSH_RDX # push first 64 bits onto + 4889E2 ; COPY_RSP_to_RDX # arg2 = &guid + 6A 01 ; PUSH !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + 6A 00 ; PUSH !0 # arg5 = NULL + 4989F9 ; COPY_RDI_to_R9 # arg4 = child_ih + 4889F9 ; COPY_RDI_to_RCX # arg1 = child_ih + 4883EC 20 ; SUBI8_RSP !32 # allocate shadow stack space for UEFI function + 41FF96 18010000 ; CALL_R14_Immediate32 %280 # system->boot->open_protocol(child_ih, &guid, &child_image, child_ih, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL) + 4883C4 40 ; ADDI8_RSP !64 # deallocate stack + 58 ; POP_RAX # get child_image + + 488958 38 ; STORE64_from_RBX_into_Address_RAX_Immediate8 !56 # child_image->load_options = command + 488970 30 ; STORE64_from_RSI_into_Address_RAX_Immediate8 !48 # set child_image->load_options_size + 488B0D %image ; LOADI64_rel_RCX %image # get image + 488B49 18 ; LOAD64_into_RCX_from_Address_RCX_Immediate8 !24 # image->device + 488948 18 ; STORE64_from_RCX_into_Address_RCX_Immediate8 !24 # child_image->device = image->device + + # Run command + 4D31C0 ; XOR_R8_R8 # arg3 = 0 (ExitData) + 31D2 ; XOR_EDX_EDX # arg2 = 0 (ExitData size) + 4889F9 ; COPY_RDI_to_RCX # arg1 = child_ih + 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 + 41FF96 D0000000 ; CALL_R14_Immediate32 %208 # system->boot->start_image() + 59 ; POP_RCX # deallocate stack + 59 ; POP_RCX # deallocate stack + 59 ; POP_RCX # deallocate stack + + 85C0 ; TEST_EAX_EAX # check if return code is 0 + 75 !print_error ; JNE8 !print_error # print error and exit + E9 %next_command ; JMP32 %next_command # process another line from kaem script + +:print_error + 50 ; PUSH_RAX # save exit code + 488B15 %subprocess_error ; LOAD64_into_RDX_rel32 %subprocess_error # get error message + E8 %File_Print ; CALLI32 %File_Print # print it + 58 ; POP_RAX # restore exit code + +# Close script file and exit +:terminate + # Free pool + 4889C3 ; COPY_RBX_to_RCX # arg1 = command + 50 ; PUSH_RAX # save exit code + 50 ; PUSH_RAX # allocate shadow stack space for UEFI function + 41FF56 48 ; CALL_R14_Immediate8 !72 # system->boot->free_pool(commmand) + + 4C89E1 ; COPY_R12_to_RCX # arg1 = fin + FF51 10 ; CALL_RCX_Immediate8 !16 # fin->close(fin) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # restore exit code + +# Exit without closing script file +:abort + 4889EC ; COPY_RBP_to_RSP # restore stack + C3 ; RET + +:File_Print + 488B0D %system_out ; LOADI64_rel_RCX %system_out # get system_out + 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 # system->out->output_string(system->out, WCHAR*) + 58 ; POP_RAX # deallocate stack + 58 ; POP_RAX # deallocate stack + C3 ; RET + +# read_byte function +# reads a single character +:read_byte + 4C89E1 ; COPY_R12_to_RCX # arg1 = fin + 6A 01 ; PUSH !1 # size = 1 + 4889E2 ; COPY_RSP_to_RDX # arg2 = &size + 56 ; PUSH_RSI # allocate stack + 4989E0 ; COPY_RSP_to_R8 # arg3 = &c + 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 c to rax + 59 ; POP_RCX # save size to rcx + + # If the file ended (0 bytes read) terminate + 85C9 ; TEST_ECX_ECX # if size = 0 + 74 !terminate ; JE8 !terminate # then we are done + + C3 ; RET # return + + +# Protocol GUIDs +:LOADED_IMAGE_PROTOCOL + A1 31 1B 5B ; %0x5b1b31a1:SIMPLE_FS_PROTOCOL + 62 95 ; @0x9562 22 5B 4E 96 ; %0x0964e5b22 + D2 11 ; @0x11d2 59 64 ; @0x6459 +:LOADED_IMAGE_PROTOCOL_8 + 8E 3F 00 A0 C9 69 72 3B ; !0x8e !0x3f !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:SIMPLE_FS_PROTOCOL + 22 5B 4E 96 ; %0x0964e5b22 + 59 64 ; @0x6459 + D2 11 ; @0x11d2 +:SIMPLE_FS_PROTOCOL_8 + 8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b + +:FILE_INFO_PROTOCOL + 92 6E 57 09 ; %0x09576e92 + 3F 6D ; @0x6d3f + D2 11 ; @0x11d2 +# last 64-bits of GUID are identical to SIMPLE_FS_PROTOCOL + +:default_file + 6B 00 61 00 65 00 6D 00 2E 00 61 00 6D 00 64 00 36 00 34 00 00 00 ; L"kaem.amd64" + +:prefix + 20 00 2B 00 3E 00 20 00 00 00 ; L" +> " + +:subprocess_error + 53 00 75 00 62 00 70 00 72 00 6F 00 63 00 65 00 + 73 00 73 00 20 00 65 00 72 00 72 00 6F 00 72 00 +:suffix + 0A 00 0D 00 00 00 ; L"Subprocess error\n\r" + +:image_handle + 00 00 00 00 00 00 00 00 + +:image + 00 00 00 00 00 00 00 00 + +:system_out + 00 00 00 00 00 00 00 00 + +:PE32_end diff --git a/amd64/PE32-amd64.hex2 b/amd64/PE32-amd64.hex2 new file mode 100644 index 0000000..46f8f6b --- /dev/null +++ b/amd64/PE32-amd64.hex2 @@ -0,0 +1,130 @@ +# 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" +%PE32_end>PE32_text ; VirtualSize +00 10 00 00 ; VirtualAddress +%PE32_end>PE32_text ; 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 diff --git a/amd64/hex0.hex0 b/amd64/hex0.hex0 index 840e3ae..3000d41 100644 --- a/amd64/hex0.hex0 +++ b/amd64/hex0.hex0 @@ -412,4 +412,4 @@ A3 01 00 00 ; SizeOfRawData # :SIMPLE_FS_PROTOCOL_8 [_start+0x19B] 8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b -# [0x1A3] +# :PE32_end [_start+0x1A3]