Add kaem-optional M1 and hex2 development prototypes.

This commit is contained in:
Andrius Štikonas 2022-08-06 21:54:11 +01:00
parent bb9ff366a5
commit fc79b4a153
7 changed files with 1203 additions and 47 deletions

View File

@ -343,3 +343,5 @@ DEFINE TEST_ESI_ESI 85F6
@0x11d2
:SIMPLE_FS_PROTOCOL_8
!0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b
:PE32_end

View File

@ -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

View File

@ -0,0 +1,572 @@
# SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2017 Jeremiah Orians <jeremiah@pdp10.guru>
#
# 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

View File

@ -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

View File

@ -0,0 +1,466 @@
# SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
# SPDX-FileCopyrightText: 2017 Jeremiah Orians <jeremiah@pdp10.guru>
#
# 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

130
amd64/PE32-amd64.hex2 Normal file
View File

@ -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

View File

@ -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]