Add kaem-optional.S
This commit is contained in:
parent
9af7fdf9bb
commit
bb9ff366a5
|
@ -62,7 +62,6 @@ efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system
|
||||||
system->boot->allocate_pool(EFI_LOADER_DATA, 2 * max_string, (void **) &command);
|
system->boot->allocate_pool(EFI_LOADER_DATA, 2 * max_string, (void **) &command);
|
||||||
|
|
||||||
unsigned int command_length = 0; /* length of command without arguments */
|
unsigned int command_length = 0; /* length of command without arguments */
|
||||||
unsigned int options_length = 0; /* length of command with arguments */
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
efi_uint_t size = 1;
|
efi_uint_t size = 1;
|
||||||
|
@ -103,7 +102,6 @@ efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system
|
||||||
if (command_length == 0 ) {
|
if (command_length == 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
options_length = i;
|
|
||||||
command[i] = 0;
|
command[i] = 0;
|
||||||
|
|
||||||
system->out->output_string(system->out, L" +> ");
|
system->out->output_string(system->out, L" +> ");
|
||||||
|
@ -121,6 +119,9 @@ efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Deal with command line arguments */
|
||||||
|
command[command_length] = ' ';
|
||||||
|
|
||||||
struct efi_file_info *file_info;
|
struct efi_file_info *file_info;
|
||||||
file_size = sizeof(struct efi_file_info);
|
file_size = sizeof(struct efi_file_info);
|
||||||
system->boot->allocate_pool(EFI_LOADER_DATA, file_size, (void **) &file_info);
|
system->boot->allocate_pool(EFI_LOADER_DATA, file_size, (void **) &file_info);
|
||||||
|
@ -148,12 +149,10 @@ efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system
|
||||||
system->boot->free_pool(device_path);
|
system->boot->free_pool(device_path);
|
||||||
system->boot->free_pool(executable);
|
system->boot->free_pool(executable);
|
||||||
|
|
||||||
/* Deal with command line arguments */
|
|
||||||
command[command_length] = ' ';
|
|
||||||
system->boot->open_protocol(child_ih, &guid1, (void **) &child_image, child_ih, 0,
|
system->boot->open_protocol(child_ih, &guid1, (void **) &child_image, child_ih, 0,
|
||||||
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
||||||
child_image->load_options = command;
|
child_image->load_options = command;
|
||||||
child_image->load_options_size = options_length;
|
child_image->load_options_size = i;
|
||||||
child_image->device = image->device;
|
child_image->device = image->device;
|
||||||
|
|
||||||
/* Run command */
|
/* Run command */
|
||||||
|
|
|
@ -0,0 +1,485 @@
|
||||||
|
# SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
|
||||||
|
# SPDX-FileCopyrightText: 2017 Jeremiah Orians <jeremiah@pdp10.guru>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# efi_main(void *image_handle, struct efi_system_table *system)
|
||||||
|
_start:
|
||||||
|
mov rbp, rsp # save stack pointer
|
||||||
|
mov [rip+image_handle], rcx # save image_handle
|
||||||
|
mov rax, [rdx+64] # system->out
|
||||||
|
mov [rip+system_out], rax # save system->out
|
||||||
|
mov r14, [rdx+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
|
||||||
|
sub rsp, 32 # allocate shadow stack space for UEFI function
|
||||||
|
call [r14+240] # system->boot->set_watchdog_timer
|
||||||
|
|
||||||
|
# Open Loaded Image protocol
|
||||||
|
push rax # allocate stack for image
|
||||||
|
mov r8, rsp # arg3 = &image
|
||||||
|
mov rdx, [rip+LOADED_IMAGE_PROTOCOL+8] # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits)
|
||||||
|
push rdx # push last 64 bits onto stack
|
||||||
|
mov rdx, [rip+LOADED_IMAGE_PROTOCOL] # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits)
|
||||||
|
push rdx # push first 64 bits onto stack
|
||||||
|
mov rdx, rsp # arg2 = &guid
|
||||||
|
push 1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
|
||||||
|
push 0 # arg5 = NULL
|
||||||
|
mov r9, [rip+image_handle] # arg4 = image_handle
|
||||||
|
mov rcx, r9 # arg1 = image_handle
|
||||||
|
sub rsp, 32 # allocate shadow stack space for UEFI function
|
||||||
|
call [r14+280] # system->boot->open_protocol(image_handle, &guid, &image, image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)
|
||||||
|
mov rax, [rsp+64] # get image
|
||||||
|
|
||||||
|
# Command line args
|
||||||
|
mov [rip+image], rax # save image
|
||||||
|
mov rcx, rax # copy image to rcx
|
||||||
|
mov rbx, [rax+56] # options = image->load_options
|
||||||
|
|
||||||
|
# Skip application name
|
||||||
|
loop_options1:
|
||||||
|
add rbx, 2 # ++options
|
||||||
|
mov al, [rbx] # *options
|
||||||
|
cmp al, 0x20 # if *options == ' '
|
||||||
|
je loop_options2 # then jump
|
||||||
|
test al, al # if options != 0
|
||||||
|
jne loop_options1 # then loop
|
||||||
|
|
||||||
|
# Use default_file
|
||||||
|
lea r12, [rip+default_file] # Use "kaem.amd64"
|
||||||
|
jmp root_fs # jump
|
||||||
|
|
||||||
|
loop_options2:
|
||||||
|
add rbx, 2 # ++options
|
||||||
|
mov r12, rbx # save script file
|
||||||
|
|
||||||
|
root_fs:
|
||||||
|
# Get root file system
|
||||||
|
push rax # allocate stack for rootfs
|
||||||
|
mov r8, rsp # arg3 = &rootfs
|
||||||
|
mov rdx, [rip+SIMPLE_FS_PROTOCOL+8] # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (last 64 bits)
|
||||||
|
push rdx # push last 64 bits onto stack
|
||||||
|
mov rdx, [rip+SIMPLE_FS_PROTOCOL] # EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID (first 64 bits)
|
||||||
|
push rdx # push first 64 bits onto stack
|
||||||
|
mov rdx, rsp # arg2 = &guid
|
||||||
|
push 1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
|
||||||
|
push 0 # arg5 = NULL
|
||||||
|
mov r9, [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);
|
||||||
|
mov rcx, [rsp+64] # get rootfs
|
||||||
|
|
||||||
|
# Get root directory
|
||||||
|
push rdx # allocate stack for rootdir
|
||||||
|
mov rdx, rsp # arg2 = &rootdir
|
||||||
|
push rax # allocate shadow stack space for UEFI function
|
||||||
|
push rax # allocate shadow stack space for UEFI function
|
||||||
|
call [rcx+8] # rootfs->open_volume(rootfs, &rootdir)
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop r13 # save &rootdir
|
||||||
|
|
||||||
|
## Open file for reading
|
||||||
|
push rdx # allocate stack for fin
|
||||||
|
mov rdx, rsp # arg2 = &fin
|
||||||
|
push 1 # arg5 = EFI_FILE_READ_ONLY
|
||||||
|
push 1 # prepare to set arg4 to EFI_FILE_MODE_READ
|
||||||
|
pop r9 # arg4 = EFI_FILE_MODE_READ
|
||||||
|
mov r8, r12 # arg3 = script
|
||||||
|
mov rcx, r13 # arg1 = rootdir
|
||||||
|
sub rsp, 32 # allocate shadow stack space for UEFI function
|
||||||
|
call [rcx+8] # rootdir->open()
|
||||||
|
test eax, eax # if status != EFI_SUCCESS
|
||||||
|
jne abort # then exit without closing file
|
||||||
|
mov r12, [rsp+40] # get fin
|
||||||
|
|
||||||
|
# Allocate pool for command
|
||||||
|
push rdx # allocate stack for command
|
||||||
|
mov r8, rsp # arg3 = &command
|
||||||
|
xor edx, edx # zero rdx
|
||||||
|
mov 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+64] # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand)
|
||||||
|
mov rbx, [rsp+24] # get command
|
||||||
|
|
||||||
|
next_command:
|
||||||
|
xor esi, esi # i = 0
|
||||||
|
xor r15, r15 # command_length = 0
|
||||||
|
|
||||||
|
read_command:
|
||||||
|
call read_byte # read another byte c
|
||||||
|
|
||||||
|
cmp al, 0xa # if c == '\n'
|
||||||
|
je read_command_done # then we are done with this command
|
||||||
|
|
||||||
|
cmp al, 0x20 # if c == ' '
|
||||||
|
jne read_command_comments
|
||||||
|
test r15, r15 # and command_length == 0
|
||||||
|
jne read_command_comments
|
||||||
|
mov r15, rsi # command_length = i
|
||||||
|
|
||||||
|
read_command_comments:
|
||||||
|
cmp al, 0x23 # if c = '#' then process comment
|
||||||
|
jne read_command_store_char # else store char
|
||||||
|
|
||||||
|
read_command_skip_comment:
|
||||||
|
call read_byte # get another char
|
||||||
|
cmp al, 0xa # if c != '\n'
|
||||||
|
jne read_command_skip_comment # continue reading until newline
|
||||||
|
|
||||||
|
jmp next_command # deal with another line
|
||||||
|
|
||||||
|
read_command_store_char:
|
||||||
|
add rbx, rsi # rbx = &command[i]
|
||||||
|
mov [rbx], ax # command[i] = c
|
||||||
|
sub rbx, rsi # rbx = &command[0]
|
||||||
|
add rsi, 2 # location of the next char
|
||||||
|
jmp read_command # continue looping
|
||||||
|
|
||||||
|
read_command_done:
|
||||||
|
test r15, r15 # if command_length == 0
|
||||||
|
je next_command # deal with another line
|
||||||
|
|
||||||
|
add rbx, rsi # rbx = &command[i]
|
||||||
|
mov WORD PTR [rbx], 0 # command[i] = 0
|
||||||
|
sub rbx, rsi # rbx = &command[0]
|
||||||
|
|
||||||
|
shr rsi # divide i by 2 to go from char to wchar length
|
||||||
|
|
||||||
|
lea rdx, [rip+prefix] # get prefix "+>"
|
||||||
|
call File_Print # print it
|
||||||
|
mov rdx, rbx # get command
|
||||||
|
call File_Print # print it
|
||||||
|
lea rdx, [rip+suffix] # get suffix "\n\r"
|
||||||
|
call File_Print # print it
|
||||||
|
|
||||||
|
# Remove command line options
|
||||||
|
add r15, rbx # go to the space separating command and its options
|
||||||
|
mov WORD PTR [r15], 0 # zero it to hide command line options
|
||||||
|
|
||||||
|
# Open executable file for reading
|
||||||
|
push rdx # allocate stack for fcmd
|
||||||
|
mov rdx, rsp # 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
|
||||||
|
mov r8, rbx # arg3 = command
|
||||||
|
mov rcx, r13 # arg1 = rootdir
|
||||||
|
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
|
||||||
|
|
||||||
|
# Restore command line arguments
|
||||||
|
mov WORD PTR [r15], 0x20 # restore command line options by readding ' '
|
||||||
|
|
||||||
|
# Allocate pool for file_info
|
||||||
|
push rdx # allocate stack for file_info
|
||||||
|
mov r8, rsp # arg3 = &file_info
|
||||||
|
xor edx, edx # zero rdx
|
||||||
|
mov 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+64] # system->boot->allocate_pool(EFI_LOADER_DATA, 4096, &commmand)
|
||||||
|
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
|
||||||
|
mov r8, rsp # arg3 = &file_size
|
||||||
|
mov QWORD PTR [r8], 0x1000 # file_size = 0x1000
|
||||||
|
mov rdx, [rip+SIMPLE_FS_PROTOCOL+8] # EFI_FILE_INFO_PROTOCOL (last 64 bits)
|
||||||
|
push rdx # push last 64 bits onto stack
|
||||||
|
mov rdx, [rip+FILE_INFO_PROTOCOL] # EFI_FILE_INFO_PROTOCOL (first 64 bits)
|
||||||
|
push rdx # push first 64 bits onto stack
|
||||||
|
mov rdx, rsp # arg2 = &guid
|
||||||
|
mov rcx, rdi # arg1 = fcmd
|
||||||
|
sub rsp, 32 # allocate shadow stack space for UEFI function
|
||||||
|
call [rcx+64] # fcmd->get_info(fcmd, &guid, &file_size, file_info)
|
||||||
|
add rsp, 56 # deallocate stack
|
||||||
|
pop rcx # restore file_info
|
||||||
|
mov rdx, [rcx+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+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
|
||||||
|
mov r8, rsp # arg3 = &executable
|
||||||
|
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+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 to memory
|
||||||
|
push rdx # save file_size onto stack
|
||||||
|
mov r8, r15 # arg3 = executable
|
||||||
|
mov rdx, rsp # arg2 = &file_size
|
||||||
|
mov rcx, rdi # arg1 = fcmd
|
||||||
|
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] # fcmd->read(fcmd, &file_size, executable)
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
|
||||||
|
# Close fcmd
|
||||||
|
push rax # allocate stack
|
||||||
|
mov rcx, rdi # arg1 = fcmd
|
||||||
|
call [rcx+16] # fin->close()
|
||||||
|
pop rax # restore stack
|
||||||
|
|
||||||
|
pop rdi # restore file_size
|
||||||
|
|
||||||
|
# Allocate memory for device_path struct
|
||||||
|
push rdx # allocate stack for device_path
|
||||||
|
mov r8, rsp # 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 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, 28, &device_path)
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop r8 # get device_path
|
||||||
|
|
||||||
|
# Initialize struct
|
||||||
|
mov rax, r8 # Make a pointer to device_path members
|
||||||
|
mov BYTE PTR [rax], 1 # device_path->type = HARDWARE_DEVICE_PATH
|
||||||
|
inc rax # next member
|
||||||
|
mov BYTE PTR [rax], 3 # device_path->subtype = MEMORY_MAPPED
|
||||||
|
inc rax # next member
|
||||||
|
mov WORD PTR [rax], 24 # device_path->length = 24
|
||||||
|
add rax, 2 # next member
|
||||||
|
mov DWORD PTR [rax], 1 # device_path->memory_type = EFI_LOADER_CODE
|
||||||
|
add rax, 4 # next member
|
||||||
|
mov QWORD PTR [rax], r15 # device_path->start_address = executable
|
||||||
|
add rax, 8 # next member
|
||||||
|
add r15, rdi # end_address = executable + file_size
|
||||||
|
mov QWORD PTR [rax], r15 # device_path->end_address = end_address
|
||||||
|
sub r15, rdi # restore r15 = executable
|
||||||
|
add rax, 8 # next member
|
||||||
|
mov BYTE PTR [rax], 0x7f # device_path[1].type = END_HARDWARE_DEVICE_PATH
|
||||||
|
inc rax # next member
|
||||||
|
mov BYTE PTR [rax], 0xff # device_path[1].subtype = END_ENTIRE_DEVICE_PATH
|
||||||
|
inc rax # next member
|
||||||
|
mov WORD PTR [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
|
||||||
|
mov r9, r15 # arg4 = executable
|
||||||
|
# arg3 = device_path
|
||||||
|
mov rdx, [rip+image_handle] # arg2 = image_handle
|
||||||
|
xor ecx, ecx # arg1 = 0
|
||||||
|
sub rsp, 32 # allocate shadow stack space for UEFI function
|
||||||
|
call [r14+200] # system->boot->load_image()
|
||||||
|
add 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+72] # system->boot->free_pool(device_path)
|
||||||
|
pop rax # deallocate stack
|
||||||
|
|
||||||
|
# Free executable pool
|
||||||
|
mov rcx, r15 # arg1 = executable
|
||||||
|
push rax # allocate shadow stack space for UEFI function
|
||||||
|
call [r14+72] # system->boot->free_pool(executable)
|
||||||
|
pop rax # deallocate stack
|
||||||
|
|
||||||
|
# Open Child Image
|
||||||
|
push rax # allocate stack for child_image
|
||||||
|
mov r8, rsp # arg3 = &child_image
|
||||||
|
mov rdx, [rip+LOADED_IMAGE_PROTOCOL+8] # EFI_LOADED_IMAGE_PROTOCOL_GUID (last 64 bits)
|
||||||
|
push rdx # push last 64 bits onto stack
|
||||||
|
mov rdx, [rip+LOADED_IMAGE_PROTOCOL] # EFI_LOADED_IMAGE_PROTOCOL_GUID (first 64 bits)
|
||||||
|
push rdx # push first 64 bits onto stack
|
||||||
|
mov rdx, rsp # arg2 = &guid
|
||||||
|
push 1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
|
||||||
|
push 0 # arg5 = NULL
|
||||||
|
mov r9, 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)
|
||||||
|
add rsp, 64 # deallocate stack
|
||||||
|
pop rax # get image
|
||||||
|
|
||||||
|
mov [rax+56], rbx # child_image->load_options = command
|
||||||
|
mov [rax+48], rsi # set child_image->load_options_size
|
||||||
|
mov rcx, [rip+image] # get image
|
||||||
|
mov rcx, [rcx+24] # image->device
|
||||||
|
mov [rax+24], rcx # child_image->device = image->device
|
||||||
|
|
||||||
|
# Run command
|
||||||
|
xor r8, r8 # arg3 = 0
|
||||||
|
xor rdx, rdx # arg2 = 0
|
||||||
|
mov rcx, rdi # arg1 = child_ih
|
||||||
|
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+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
|
||||||
|
jne print_error
|
||||||
|
jmp next_command
|
||||||
|
|
||||||
|
print_error:
|
||||||
|
push rax # save exit code
|
||||||
|
lea rdx, [rip+subprocess_error] # get error message
|
||||||
|
call File_Print # print it
|
||||||
|
pop rax # restore exit code
|
||||||
|
|
||||||
|
# Close script file and exit
|
||||||
|
terminate:
|
||||||
|
# Free pool
|
||||||
|
mov rcx, rbx # arg1 = command
|
||||||
|
mov rbx, 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
|
||||||
|
|
||||||
|
# Exit without closing script file
|
||||||
|
abort:
|
||||||
|
mov rsp, rbp # restore stack
|
||||||
|
ret
|
||||||
|
|
||||||
|
# File_Print function
|
||||||
|
# Receives WCHAR* in RDX
|
||||||
|
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*);
|
||||||
|
pop rax # deallocate stack
|
||||||
|
pop rax # deallocate stack
|
||||||
|
ret
|
||||||
|
|
||||||
|
# read_byte function
|
||||||
|
# reads a single character
|
||||||
|
read_byte:
|
||||||
|
mov rcx, r12 # arg1 = fin
|
||||||
|
push 1 # size = 1
|
||||||
|
mov rdx, rsp # arg2 = &size
|
||||||
|
push rsi # allocate stack
|
||||||
|
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
|
||||||
|
|
||||||
|
# If the file ended (0 bytes read) terminate
|
||||||
|
test ecx, ecx # if size == 0
|
||||||
|
je terminate # then we are done
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
# Protocol GUIDs
|
||||||
|
LOADED_IMAGE_PROTOCOL:
|
||||||
|
.long 0x5b1b31a1
|
||||||
|
.short 0x9562
|
||||||
|
.short 0x11d2
|
||||||
|
.byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
|
||||||
|
|
||||||
|
SIMPLE_FS_PROTOCOL:
|
||||||
|
.long 0x0964e5b22
|
||||||
|
.short 0x6459
|
||||||
|
.short 0x11d2
|
||||||
|
.byte 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
|
||||||
|
|
||||||
|
FILE_INFO_PROTOCOL:
|
||||||
|
.long 0x09576e92
|
||||||
|
.short 0x6d3f
|
||||||
|
.short 0x11d2
|
||||||
|
# last 64-bits of GUID are identical to SIMPLE_FS_PROTOCOL
|
||||||
|
|
||||||
|
default_file:
|
||||||
|
.byte 0x6B, 0, 0x61, 0, 0x65, 0, 0x6D, 0, 0x2E, 0
|
||||||
|
.byte 0x61, 0, 0x6D, 0, 0x64, 0, 0x36, 0, 0x34, 0, 0, 0 # L"kaem.amd64"
|
||||||
|
|
||||||
|
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
|
||||||
|
.byte 0x0A, 0, 0x0D, 0, 0, 0 # L"Subprocess error\n\r"
|
||||||
|
|
||||||
|
image_handle:
|
||||||
|
.long 0, 0
|
||||||
|
|
||||||
|
image:
|
||||||
|
.long 0, 0
|
||||||
|
|
||||||
|
system_out:
|
||||||
|
.long 0, 0
|
||||||
|
|
Loading…
Reference in New Issue