stage0-uefi/amd64/Development/kaem-minimal.hex2

463 lines
26 KiB
Plaintext

# 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 ; mov_rbp,rsp # save stack pointer
48890D %image_handle ; mov_[rip+DWORD],rcx %image_handle # save image_handle
4889CB ; mov_rbx,rcx # save image_handle
488B42 40 ; mov_rax,[rdx+BYTE] !64 # system->out
488905 %system_out ; mov_[rip+DWORD],rax %system_out # save system->out
4C8B72 60 ; mov_r14,[rdx+BYTE] !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 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
41FF96 F0000000 ; call_[r14+DWORD] %240 # system->boot->set_watchdog_timer
# Open Loaded Image protocol
4989D9 ; mov_r9,rbx # arg4 = image_handle
488D15 %LOADED_IMAGE_PROTOCOL ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL
4889D9 ; mov_rcx,rbx # arg1 = image_handle
E8 %open_protocol ; call %open_protocol # open protocol
4889C7 ; mov_rdi,rax # save image
488905 %image ; mov_[rip+DWORD],rax %image # save image
# Get root file system
4989D9 ; mov_r9,rbx # arg4 = image_handle
488D15 %SIMPLE_FS_PROTOCOL ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL
488B4F 18 ; mov_rcx,[rdi+BYTE] !24 # arg1 = root_device = image->device
48890D %root_device ; mov_[rip+DWORD],rcx %root_device # save root_device
E8 %open_protocol ; call %open_protocol # open protocol
4889C1 ; mov_rcx,rax # get rootfs
# Get root directory
488D15 %rootdir ; lea_rdx,[rip+DWORD] %rootdir # arg2 = &rootdir
50 ; push_rax # allocate shadow stack space for UEFI function space for UEFI function
50 ; push_rax # allocate shadow stack space for UEFI function space for UEFI function
FF51 08 ; call_[rcx+BYTE] !8 # rootfs->open_volume(rootfs, &rootdir)
58 ; pop_rax # deallocate stack
58 ; pop_rax # deallocate stack
# Push command line arguments onto stack
488B5F 38 ; mov_rbx,[rdi+BYTE] !56 # options = image->load_options
4889DA ; mov_rdx,rbx # save beginning of load_options
48035F 30 ; add_rbx,[rdi+BYTE] !48 # go to the end of load_options
6A 00 ; push !0 # Save end of arguments (NULL) onto stack
:loop_options
4839D3 ; cmp_rbx,rdx # Check if we are done
74 !loop_options_done ; je8 !loop_options_done # We are done
4883EB 02 ; sub_rbx, !2 # --options
8A03 ; mov_al,[rbx] # *options
3C 20 ; cmp_al, !0x20 # if *options != ' '
75 !loop_options ; jne8 !loop_options # then continue looping
C603 00 ; mov_[rbx], !0 # zero it
4883C3 02 ; add_rbx, !2 # ++options
53 ; push_rbx # push another argument onto stack
EB !loop_options ; jmp8 !loop_options # next argument
:loop_options_done
4158 ; pop_r8 # get input file
4D85C0 ; test_r8,r8 # Check if argument is specified
75 !arg_done ; jne8 !arg_done # then use it
# Else use default_file
4C8D05 %default_file ; lea_r8,[rip+DWORD] %default_file # Use "kaem.amd64"
:arg_done
# Open file for reading
52 ; push_rdx # allocate stack for fin
4889E2 ; mov_rdx,rsp # 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
# arg3 = in
488B0D %rootdir ; mov_rcx,[rip+DWORD] %rootdir # arg1 = rootdir
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
FF51 08 ; call_[rcx+BYTE] !8 # rootdir->open()
85C0 ; test_eax,eax # if status != EFI_SUCCESS
0F85 %abort ; jne %abort # then exit without closing file
4C8B6424 28 ; mov_r12,[rsp+BYTE] !40 # get fin
# Allocate pool for command
31D2 ; xor_edx,edx # zero RDX
B6 10 ; mov_dh, !0x10 # arg2 = 4096 = 0x1000
E8 %allocate_pool ; call %allocate_pool # allocate memory
4889C3 ; mov_rbx,rax # get command
:next_command
31F6 ; xor_esi,esi # i = 0
4D31FF ; xor_r15,r15 # command_length = 0
:read_command
E8 %read_byte ; call %read_byte # read another byte c
3C 0A ; cmp_al, !0xa # if c == '\n'
74 !read_command_done ; je8 !read_command_done # then we are done with this command command
3C 20 ; cmp_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 ; mov_r15,rsi # command_length = i
:read_command_comments
3C 23 ; cmp_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 ; call %read_byte # get another char
3C 0A ; cmp_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_rbx,rsi # rbx = &command[i]
668903 ; mov_[rbx],ax # command[i] = c
4829F3 ; sub_rbx,rsi # rbx = &command[0]
4883C6 02 ; add_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_rbx,rsi # rbx = &command[i]
66C703 0000 ; mov_[rbx],WORD @0 # command[i] = 0
4829F3 ; sub_rbx,rsi # rbx = &command[0]
4883C6 02 ; add_rsi, !2 # add 2 to get string length with NULL terminator
488D15 %prefix ; lea_rdx,[rip+DWORD] %prefix # get prefix " +> "
E8 %File_Print ; call %File_Print # print it
4889DA ; mov_rdx,rbx # get command
E8 %File_Print ; call %File_Print # print it
488D15 %suffix ; lea_rdx,[rip+DWORD] %suffix # get suffix "\n\r"
E8 %File_Print ; call %File_Print # print it
# Remove command line options
4901DF ; add_r15,rbx # go to the space separating command and its options
6641C707 0000 ; mov_[r15],WORD @0 # zero it to hide command line options
# Open executable file for reading
52 ; push_rdx # allocate stack for fcmd
4889E2 ; mov_rdx,rsp # 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 ; mov_r8,rbx # arg3 = command
488B0D %rootdir ; mov_rcx,[rip+DWORD] %rootdir # arg1 = rootdir
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
FF51 08 ; call_[rcx+BYTE] !8 # rootdir->open()
85C0 ; test_eax,eax # if status != EFI_SUCCESS
0F85 %print_error ; jne %print_error # then exit
4883C4 28 ; add_rsp, !40 # deallocate stack
5F ; pop_rdi # get fcmd
# Restore command line arguments
6641C707 2000 ; mov_[r15],WORD @0x20 # restore command line options by readding ' '
# Allocate pool for file_info
31D2 ; xor_edx,edx # zero RDX
B6 10 ; mov_dh, !0x10 # arg2 = 4096 = 0x1000
E8 %allocate_pool ; call %allocate pool # allocate memory
4989C1 ; mov_r9,rax # get file_info (arg4 for get_info)
# Get file info
50 ; push_rax # save file_info
50 ; push_rax # allocate stack for file_size
4989E0 ; mov_r8,rsp # arg3 = &file_size
49C700 00100000 ; mov_[r8], %0x1000 # file_size = 0x1000
488D15 %FILE_INFO_PROTOCOL ; lea_rdx,[rip+DWORD] %FILE_INFO_PROTOCOL # arg2 = &EFI_FILE_INFO_PROTOCOL
4889F9 ; mov_rcx,rdi # arg1 = fcmd
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
FF51 40 ; call_[rcx+BYTE] !64 # fcmd->get_info(fcmd, &guid, &file_size, file_info)
4883C4 28 ; add_rsp, !40 # deallocate stack
59 ; pop_rcx # restore file_info
488B51 08 ; mov_rdx,[rcx+BYTE] !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+BYTE] !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
E8 %allocate_pool ; call %allocate_pool # allocate memory
4989C7 ; mov_r15,rax # get executable
5A ; pop_rdx # restore file_size
# Load executable into memory
52 ; push_rdx # save file_size onto stack
4D89F8 ; mov_r8,r15 # arg3 = executable
4889E2 ; mov_rdx,rsp # arg2 = &file_size
4889F9 ; mov_rcx,rdi # arg1 = fcmd
50 ; push_rax # allocate shadow stack space for UEFI
50 ; push_rax # allocate shadow stack space for UEFI
50 ; push_rax # allocate shadow stack space for UEFI
FF51 20 ; call_[rcx+BYTE] !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
4889F9 ; mov_rcx,rdi # arg1 = fcmd
FF51 10 ; call_[rcx+BYTE] !16 # fcmd->close(fcmd)
58 ; pop_rax # deallocate stack
5F ; pop_rdi # restore file_size
# Allocate memory for device_path struct
6A 1C ; push !28 # 4 + sizeof(struct efi_device_path_protocol)
5A ; pop_rdx # arg2 = 28
E8 %allocate_pool ; call %allocate_pool # allocate memory
4989C0 ; mov_r8,rax # get device_path
# Initialize struct
C600 01 ; mov_[rax],BYTE !1 # device_path->type = HARDWARE_DEVICE_PATH
48FFC0 ; inc_rax # next member
C600 03 ; mov_[rax],BYTE !3 # device_path->subtype = MEMORY_MAPPED
48FFC0 ; inc_rax # next member
66C700 1800 ; mov_[rax],WORD @24 # device_path->length = 24
4883C0 02 ; add_rax, !2 # next member
C700 01000000 ; mov_[rax], %1 # device_path->memory_type = EFI_LOADER_CODE
4883C0 04 ; add_rax, !4 # next member
4C8938 ; mov_[rax],r15 # device_path->start_address = executable
4883C0 08 ; add_rax, !8 # next member
4901FF ; add_r15,rdi # end_address = executable + file_size
4C8938 ; mov_[rax],r15 # device_path->end_address = end_address
4929FF ; sub_r15,rdi # restore r15 = executable
4883C0 08 ; add_rax, !8 # next member
C600 7F ; mov_[rax],BYTE !0x7f # device_path[1].type = END_HARDWARE_DEVICE_PATH
48FFC0 ; inc_rax # next member
C600 FF ; mov_[rax],BYTE !0xff # device_path[1].subtype = END_ENTIRE_DEVICE_PATH
48FFC0 ; inc_rax # next member
66C700 0400 ; mov_[rax],WORD @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 ; mov_r9,r15 # arg4 = executable
# arg3 = device_path
488B15 %image_handle ; mov_rdx,[rip+DWORD] %image_handle # arg2 = image_handle
31C9 ; xor_ecx,ecx # arg1 = 0
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
41FF96 C8000000 ; call_[r14+DWORD] %200 # system->boot->load_image()
4883C4 30 ; add_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+BYTE] !72 # system->boot->free_pool(device_path)
58 ; pop_rax # deallocate stack
# Free executable pool
4C89F9 ; mov_rcx,r15 # arg1 = executable
50 ; push_rax # allocate shadow stack space for UEFI function
41FF56 48 ; call_[r14+BYTE] !72 # system->boot->free_pool(executable)
58 ; pop_rax # deallocate stack
# Open Child Image
4989F9 ; mov_r9,rdi # arg4 = child_ih
488D15 %LOADED_IMAGE_PROTOCOL ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL
52 ; push_rdx # save &LOADED_IMAGE_PROTOCOL
4C89C9 ; mov_rcx,r9 # arg1 = child_ih
E8 %open_protocol ; call %open_protocol # open protocol
488958 38 ; mov_[rax+BYTE],rbx !56 # child_image->load_options = command
488970 30 ; mov_[rax+BYTE],rsi !48 # set child_image->load_options_size
488B0D %image ; mov_rcx,[rip+DWORD] %image # get image
488B49 18 ; mov_rcx,[rcx+BYTE] !24 # image->device
488948 18 ; mov_[rax+BYTE],rcx !24 # child_image->device = image->device
4989F8 ; mov_r8,rdi # arg3 = image_handle
5A ; pop_rdx # arg2 = &LOADED_IMAGE_PROTOCOL
4C89C1 ; mov_rcx,r8 # arg1 = image_handle
E8 %close_protocol ; call %close_protocol # close protocol
# Run command
4D31C0 ; xor_r8,r8 # arg3 = 0 (ExitData)
31D2 ; xor_edx,edx # arg2 = 0 (ExitData size)
4889F9 ; mov_rcx,rdi # arg1 = child_ih
50 ; push_rax # allocate shadow stack space for UEFI
50 ; push_rax # allocate shadow stack space for UEFI
50 ; push_rax # allocate shadow stack space for UEFI
41FF96 D0000000 ; call_[r14+DWORD] %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 ; jmp %next_command # process another line from kaem script
:print_error
50 ; push_rax # save exit code
488D15 %subprocess_error ; lea_rdx,[rip+DWORD] %subprocess_error # get error message
E8 %File_Print ; call %File_Print # print it
58 ; pop_rax # restore exit code
# Close script file and exit
:terminate
# Free pool
4889D9 ; mov_rcx,rbx # arg1 = command
50 ; push_rax # save exit code
50 ; push_rax # allocate shadow stack space for UEFI function
41FF56 48 ; call_[r14+BYTE] !72 # system->boot->free_pool(commmand)
4C89E1 ; mov_rcx,r12 # arg1 = fin
FF51 10 ; call_[rcx+BYTE] !16 # fin->close(fin)
488B0D %rootdir ; mov_rcx,[rip+DWORD] %rootdir # arg1 = rootdir
FF51 10 ; call_[rcx+BYTE] !16 # rootdir->close(rootdir)
58 ; pop_rax # deallocate stack
58 ; pop_rax # restore exit code
# Exit without closing script file
:terminate_2
4C8B05 %image_handle ; mov_r8,[rip+DWORD] %image_handle # arg3 = image_handle
4150 ; push_r8 # save image_handle
488D15 %SIMPLE_FS_PROTOCOL ; lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL
488B0D %root_device ; mov_rcx,[rip+DWORD] %root_device # arg1 = root_device
E8 %close_protocol ; call %close_protocol # close protocol
4158 ; pop_r8 # arg3 = image_handle
488D15 %LOADED_IMAGE_PROTOCOL ; lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL
4C89C1 ; mov_rcx,r8 # arg1 = image_handle
E8 %close_protocol ; call %close_protocol # close protocol
:abort
4889EC ; mov_rsp,rbp # restore stack
C3 ; ret # return to UEFI
:File_Print
488B0D %system_out ; mov_rcx,[rip+DWORD] %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 for UEFI function
FF51 08 ; call_[rcx+BYTE] !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 ; mov_rcx,r12 # arg1 = fin
6A 01 ; push !1 # size = 1
4889E2 ; mov_rdx,rsp # arg2 = &size
56 ; push_rsi # allocate stack
4989E0 ; mov_r8,rsp # 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+BYTE] !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
# rcx: handle
# rdx: &guid
# r9: agent_handle
# returns interface
:open_protocol
50 ; push_rax # allocate stack for interface
4989E0 ; mov_r8,rsp # arg3 = &interface
6A 01 ; push !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
6A 00 ; push !0 # arg5 = NULL
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
41FF96 18010000 ; call_[r14+DWORD] %280 # system->boot->open_protocol(handle, &guid, &interface, agent_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)
4883C4 30 ; add_rsp, !48 # deallocate stack
58 ; pop_rax # get image
C3 ; ret
# rcx: handle
# rdx: &guid
# r8: agent_handle
:close_protocol
4D31C9 ; xor_r9,r9 # arg4 = NULL
4883EC 20 ; sub_rsp, !32 # allocate shadow stack space for UEFI function
41FF96 20010000 ; call_[r14+DWORD] %288 # system->boot->close_protocol(handle, &guid, agent_handle, 0)
4883C4 20 ; add_rsp, !32 # deallocate stack
C3 ; ret
# rdx: number of bytes to allocate
# r14: system->boot
# returns pointer in rax
:allocate_pool
52 ; push_rdx # allocate stack for pool pointer
4989E0 ; mov_r8,rsp # arg3 = &pool
6A 02 ; push !2
59 ; pop_rcx # arg1 = EFI_LOADER_DATA
4883EC 18 ; sub_rsp, !24 # allocate shadow stack space for UEFI
41FF56 40 ; call_[r14+BYTE] !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 2048, &pool)
4883C4 18 ; add_rsp, !24 # deallocate stack
58 ; pop_rax # get pool
C3 ; ret
# 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
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
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
8E 39 00 A0 C9 69 72 3B ; !0x8e !0x39 !0 !0xa0 !0xc9 !0x69 !0x72 !0x3b
: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
:rootdir
00 00 00 00 00 00 00 00
:root_device
00 00 00 00 00 00 00 00
:system_out
00 00 00 00 00 00 00 00
:PE32_end