1171 lines
40 KiB
Plaintext
1171 lines
40 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
|
|
|
|
DEFINE add_al, 04
|
|
DEFINE add_ebx, 83C3
|
|
DEFINE add_rax, 4805
|
|
DEFINE add_rbx, 4881C3
|
|
DEFINE add_rcx, 4881C1
|
|
DEFINE add_rdx, 4881C2
|
|
DEFINE add_rsp, 4883C4
|
|
DEFINE add_rax,rcx 4801C8
|
|
DEFINE add_r12,rax 4901C4
|
|
DEFINE add_rbx,[rdi+BYTE] 48035F
|
|
DEFINE and_rax, 4883E0
|
|
DEFINE cmp_al, 3C
|
|
DEFINE cmp_rax, 483D
|
|
DEFINE cmp_rbx, 4881FB
|
|
DEFINE cmp_rcx, 4881F9
|
|
DEFINE cmp_rdx, 4881FA
|
|
DEFINE cmp_rsi, 4881FE
|
|
DEFINE cmp_r8, 4983F8
|
|
DEFINE cmp_rax,rbx 4839D8
|
|
DEFINE cmp_rax,rcx 4839C8
|
|
DEFINE cmp_rax,r12 4C39E0
|
|
DEFINE cmp_rbx,rdx 4839D3
|
|
DEFINE cmp_rcx,rbx 4839D9
|
|
DEFINE call E8
|
|
DEFINE call_[rcx+BYTE] FF51
|
|
DEFINE call_[r14+BYTE] 41FF56
|
|
DEFINE call_[r14+DWORD] 41FF96
|
|
DEFINE dec_rax 48FFC8
|
|
DEFINE imul_rax, 486BC0
|
|
DEFINE jbe8 76
|
|
DEFINE je8 74
|
|
DEFINE jg8 7F
|
|
DEFINE jl8 7C
|
|
DEFINE jmp8 EB
|
|
DEFINE jne8 75
|
|
DEFINE je 0F84
|
|
DEFINE jl 0F8C
|
|
DEFINE jmp E9
|
|
DEFINE jne 0F85
|
|
DEFINE lea_rbx,[rip+DWORD] 488D1D
|
|
DEFINE lea_rdx,[rip+DWORD] 488D15
|
|
DEFINE mov_rax, 48C7C0
|
|
DEFINE mov_rcx, 48C7C1
|
|
DEFINE mov_rdx, 48C7C2
|
|
DEFINE mov_rsi, 48C7C6
|
|
DEFINE mov_rax,rbx 4889D8
|
|
DEFINE mov_rax,rcx 4889C8
|
|
DEFINE mov_rax,rdx 4889D0
|
|
DEFINE mov_rax,r13 4C89E8
|
|
DEFINE mov_rbx,rax 4889C3
|
|
DEFINE mov_rbx,rcx 4889CB
|
|
DEFINE mov_rbx,r13 4C89EB
|
|
DEFINE mov_rbp,rsp 4889E5
|
|
DEFINE mov_rcx,rax 4889C1
|
|
DEFINE mov_rcx,rbx 4889D9
|
|
DEFINE mov_rcx,r8 4C89C1
|
|
DEFINE mov_rcx,r9 4C89C9
|
|
DEFINE mov_rdi,rax 4889C7
|
|
DEFINE mov_rdx,rax 4889C2
|
|
DEFINE mov_rdx,rbx 4889DA
|
|
DEFINE mov_rdx,rsp 4889E2
|
|
DEFINE mov_rsp,rbp 4889EC
|
|
DEFINE mov_r8,rsp 4989E0
|
|
DEFINE mov_r12,rax 4989C4
|
|
DEFINE mov_r13,rax 4989C5
|
|
DEFINE mov_r13,rdx 4989D5
|
|
DEFINE mov_al,[rbx] 8A03
|
|
DEFINE mov_al,[rbx+rcx] 8A040B
|
|
DEFINE mov_al,[rdx] 8A02
|
|
DEFINE mov_al,[rcx] 8A01
|
|
DEFINE mov_bl,[rax] 8A18
|
|
DEFINE mov_bl,[rdx] 8A1A
|
|
DEFINE mov_cl,[rax] 8A08
|
|
DEFINE mov_cl,[rbx] 8A0B
|
|
DEFINE mov_cl,[rbx+BYTE] 8A4B
|
|
DEFINE mov_rax,[rax] 488B00
|
|
DEFINE mov_rax,[rcx] 488B01
|
|
DEFINE mov_rbx,[rbx] 488B1B
|
|
DEFINE mov_rcx,[rbx] 488B0B
|
|
DEFINE mov_rcx,[rcx] 488B09
|
|
DEFINE mov_rdx,[rdx] 488B12
|
|
DEFINE mov_[ebx],al 678803
|
|
DEFINE mov_[rbx], C603
|
|
DEFINE mov_[rdx],cl 880A
|
|
DEFINE mov_[rbx],rax 488903
|
|
DEFINE mov_[rcx],rax 488901
|
|
DEFINE mov_[rdx],r13 4C892A
|
|
DEFINE mov_[rax],BYTE C600
|
|
DEFINE mov_rax,[rax+BYTE] 488B40
|
|
DEFINE mov_rax,[rbx+BYTE] 488B43
|
|
DEFINE mov_rax,[rcx+BYTE] 488B41
|
|
DEFINE mov_rax,[rdx+BYTE] 488B42
|
|
DEFINE mov_rbx,[rax+BYTE] 488B58
|
|
DEFINE mov_rbx,[rcx+BYTE] 488B59
|
|
DEFINE mov_rbx,[rdi+BYTE] 488B5F
|
|
DEFINE mov_rcx,[rax+BYTE] 488B48
|
|
DEFINE mov_rcx,[rdi+BYTE] 488B4F
|
|
DEFINE mov_r14,[rdx+BYTE] 4C8B72
|
|
DEFINE mov_rcx,[rip+DWORD] 488B0D
|
|
DEFINE mov_r8,[rip+DWORD] 4C8B05
|
|
DEFINE mov_r9,[rip+DWORD] 4C8B0D
|
|
DEFINE mov_[rax+BYTE],rbx 488958
|
|
DEFINE mov_[rcx+BYTE],rax 488941
|
|
DEFINE mov_[rcx+BYTE],rbx 488959
|
|
DEFINE mov_[rdx+BYTE],rax 488942
|
|
DEFINE mov_[rdx+BYTE],rcx 48894A
|
|
DEFINE mov_[rip+DWORD],rax 488905
|
|
DEFINE mov_[rip+DWORD],rcx 48890D
|
|
DEFINE movzx_rax,al 480FB6C0
|
|
DEFINE movzx_rbx,bl 480FB6DB
|
|
DEFINE movzx_rcx,cl 480FB6C9
|
|
DEFINE popf 9D
|
|
DEFINE pop_rax 58
|
|
DEFINE pop_rbx 5B
|
|
DEFINE pop_rcx 59
|
|
DEFINE pop_rdx 5A
|
|
DEFINE pop_r8 4158
|
|
DEFINE pop_r9 4159
|
|
DEFINE pop_rsi 5E
|
|
DEFINE push 6A
|
|
DEFINE pushf 9C
|
|
DEFINE push_rax 50
|
|
DEFINE push_rbx 53
|
|
DEFINE push_rcx 51
|
|
DEFINE push_rdx 52
|
|
DEFINE push_rsi 56
|
|
DEFINE push_r12 4154
|
|
DEFINE ret C3
|
|
DEFINE ror_r9 49D1C9
|
|
DEFINE shl_rax, 48C1E0
|
|
DEFINE shr_rax, 48C1E8
|
|
DEFINE sub_rbx, 4883EB
|
|
DEFINE sub_rcx, 4883E9
|
|
DEFINE sub_rsp, 4883EC
|
|
DEFINE xchg_rax,rbx 4893
|
|
DEFINE xor_eax,eax 31C0
|
|
DEFINE xor_esi,esi 31F6
|
|
DEFINE xor_r9,r9 4D31C9
|
|
DEFINE xor_r13,r13 4D31ED
|
|
|
|
# Register usage:
|
|
# RAX, RSI, RDI => Temps
|
|
# R12 => MALLOC
|
|
# R13 => HEAD
|
|
# R14 => system->boot
|
|
|
|
# Struct format: (size 32)
|
|
# NEXT => 0
|
|
# TYPE => 8
|
|
# TEXT => 16
|
|
# EXPRESSION => 24
|
|
|
|
# Types
|
|
# None => 0
|
|
# MACRO => 1
|
|
# STRING => 2
|
|
|
|
# efi_main(void *image_handle, struct efi_system_table *system)
|
|
:_start
|
|
mov_rbp,rsp # save stack pointer
|
|
mov_[rip+DWORD],rcx %image_handle # save image_handle
|
|
mov_r14,[rdx+BYTE] !96 # system->boot
|
|
|
|
# Open Loaded Image protocol
|
|
mov_r9,[rip+DWORD] %image_handle # arg4 = image_handle
|
|
lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL
|
|
mov_rcx,r9 # arg1 = image_handle
|
|
call %open_protocol # open protocol
|
|
mov_rdi,rax # save image
|
|
|
|
# Get root file system
|
|
mov_r9,[rip+DWORD] %image_handle # arg4 = image_handle
|
|
lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL
|
|
mov_rcx,[rdi+BYTE] !24 # arg1 = root_device = image->device
|
|
mov_[rip+DWORD],rcx %root_device # save root_device
|
|
call %open_protocol # open protocol
|
|
mov_rcx,rax # get rootfs
|
|
|
|
# Get root directory
|
|
lea_rdx,[rip+DWORD] %rootdir # arg2 = &rootdir
|
|
push_rax # allocate shadow stack space for UEFI function
|
|
push_rax # allocate shadow stack space for UEFI function
|
|
call_[rcx+BYTE] !8 # rootfs->open_volume(rootfs, &rootdir)
|
|
pop_rax # deallocate stack
|
|
pop_rax # deallocate stack
|
|
|
|
# Push command line arguments onto stack
|
|
mov_rbx,[rdi+BYTE] !56 # options = image->load_options
|
|
mov_rdx,rbx # save beginning of load_options
|
|
add_rbx,[rdi+BYTE] !48 # go to the end of load_options
|
|
push !0 # Save end of arguments (NULL) onto stack
|
|
:loop_options
|
|
cmp_rbx,rdx # Check if we are done
|
|
je8 !loop_options_done # We are done
|
|
sub_rbx, !2 # --options
|
|
mov_al,[rbx] # *options
|
|
cmp_al, !0x20 # if *options != ' '
|
|
jne8 !loop_options # then continue looping
|
|
mov_[rbx], !0 # zero it
|
|
add_rbx, %2 # ++options
|
|
push_rbx # push another argument onto stack
|
|
jmp8 !loop_options # next argument
|
|
:loop_options_done
|
|
|
|
# Open file for reading
|
|
pop_r8 # arg3 = in
|
|
push !1 # Set exit code in case of failure
|
|
cmp_r8, !0 # If NULL
|
|
je %failed_input # then exit
|
|
lea_rdx,[rip+DWORD] %fin # arg2 = &fin
|
|
push !1 # arg5 = EFI_FILE_READ_ONLY
|
|
push !1 # prepare to set arg4 to EFI_FILE_MODE_READ
|
|
pop_r9 # arg4 = EFI_FILE_MODE_READ
|
|
mov_rcx,[rip+DWORD] %rootdir # arg1 = rootdir
|
|
sub_rsp, !32 # allocate shadow stack space for UEFI function
|
|
call_[rcx+BYTE] !8 # rootdir->open()
|
|
cmp_rax, %0 # If failed to open
|
|
jne %failed_input # then exit
|
|
add_rsp, !48 # deallocate stack
|
|
|
|
# Open file for writing
|
|
pop_r8 # arg3 = out
|
|
push !1 # Set exit code in case of failure
|
|
cmp_r8, !0 # If NULL
|
|
je %failed_output # then exit
|
|
lea_rdx,[rip+DWORD] %fout # arg2 = &fout
|
|
push !0 # arg5 = 0
|
|
push !7 # to get 0x8000000000000003 we set the rightmost 3 bits
|
|
pop_r9 # and then do right rotation by 1
|
|
ror_r9 # arg4 = EFI_FILE_MODE_CREATE| EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ
|
|
mov_rcx,[rip+DWORD] %rootdir # arg1 = rootdir
|
|
sub_rsp, !32 # allocate shadow stack space for UEFI function
|
|
call_[rcx+BYTE] !8 # rootdir->open()
|
|
add_rsp, !48 # deallocate stack
|
|
|
|
# Allocate ourselves 32 MiB of memory
|
|
mov_rdx, %0x2000000 # allocate 32 MiB of memory for malloc pool
|
|
call %allocate_pool # allocate memory
|
|
|
|
mov_r12,rax # save malloc pointer
|
|
mov_[rip+DWORD],rax %malloc_pool # save the beginning of malloc pool
|
|
|
|
# Zero allocated memory buffer
|
|
add_rax, %0x2000000 # end of malloc area
|
|
:zero_loop
|
|
dec_rax # next byte
|
|
mov_[rax],BYTE !0 # zero it
|
|
cmp_rax,r12 # if we are not done yet
|
|
jne8 !zero_loop # then continue looping
|
|
|
|
xor_r13,r13 # Set HEAD = NULL
|
|
call %Tokenize_Line # Process it
|
|
mov_rax,r13 # prepare for Reverse_List
|
|
call %Reverse_List # Correct order
|
|
mov_r13,rax # Update HEAD
|
|
call %Identify_Macros # Find the DEFINEs
|
|
call %Line_Macro # Apply the DEFINEs
|
|
call %Process_String # Handle strings
|
|
call %Eval_Immediates # Handle Numbers
|
|
call %Preserve_Other # Collect the remaining
|
|
call %Print_Hex # Output our results
|
|
|
|
:Done
|
|
xor_eax,eax # Set exit code 0
|
|
|
|
# Free pool
|
|
push_rax # save exit code
|
|
|
|
mov_rcx,[rip+DWORD] %malloc_pool # arg1 = malloc_pool
|
|
call %free_pool # system->boot->free_pool(malloc_pool)
|
|
|
|
mov_rcx,[rip+DWORD] %fout # get fout
|
|
call %close_file # close fout
|
|
|
|
:failed_output
|
|
mov_rcx,[rip+DWORD] %fin # get fin
|
|
call %close_file # close fin
|
|
|
|
:failed_input
|
|
mov_rcx,[rip+DWORD] %rootdir # get rootdir
|
|
call %close_file # close rootdir
|
|
|
|
mov_r8,[rip+DWORD] %image_handle # arg3 = image_handle
|
|
lea_rdx,[rip+DWORD] %SIMPLE_FS_PROTOCOL # guid = &SIMPLE_FS_PROTOCOL
|
|
mov_rcx,[rip+DWORD] %root_device # arg1 = root_device
|
|
call %close_protocol # close protocol
|
|
|
|
mov_r8,[rip+DWORD] %image_handle # arg3 = image_handle
|
|
lea_rdx,[rip+DWORD] %LOADED_IMAGE_PROTOCOL # guid = &LOADED_IMAGE_PROTOCOL
|
|
mov_rcx,r8 # arg1 = image_handle
|
|
call %close_protocol # close protocol
|
|
|
|
pop_rax # restore exit code
|
|
|
|
mov_rsp,rbp # restore stack
|
|
ret # return to UEFI
|
|
|
|
|
|
# Tokenize_Line Function
|
|
# Using input file R15 and Head R13
|
|
# Creates a linked list of structs
|
|
# Uses RBX for in_set strings, RCX for Int C and RDX for Struct Token* p
|
|
:Tokenize_Line
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
|
|
:restart
|
|
call %fgetc # Read a char
|
|
cmp_rax, %-4 # Check for EOF
|
|
je8 !done # File is collected
|
|
|
|
movzx_rax,al # We have to zero extend it to use it
|
|
mov_rcx,rax # Protect C
|
|
|
|
lea_rbx,[rip+DWORD] %comments # Get pointer to "#;"
|
|
call %In_Set # Check for comments
|
|
cmp_rax, %1 # If comments
|
|
je %Purge_LineComment # try again
|
|
|
|
mov_rax,rcx # put C in place for check
|
|
lea_rbx,[rip+DWORD] %terminators # Get pointer to "\n\t "
|
|
call %In_Set # Check for terminators
|
|
cmp_rax, %1 # If terminator
|
|
je8 !restart # try again
|
|
|
|
mov_rax, %32 # Malloc the struct P
|
|
call %malloc # Get pointer to P
|
|
mov_rdx,rax # Protect P
|
|
mov_[rdx],r13 # P->NEXT = HEAD
|
|
mov_r13,rdx # HEAD = P
|
|
|
|
mov_rax,rcx # put C in place for check
|
|
lea_rbx,[rip+DWORD] %string_char # Get pointer to "\"'"
|
|
call %In_Set # Check for string chars
|
|
cmp_rax, %1 # If string char
|
|
je %Store_String # Get string
|
|
|
|
call %Store_Atom # Get whole token
|
|
jmp8 !restart
|
|
|
|
:done
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# fgetc function
|
|
# Returns -4 (EOF) or char in RAX
|
|
:fgetc
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
|
|
mov_rcx,[rip+DWORD] %fin # arg1 = fin
|
|
push !1 # size = 1
|
|
mov_rdx,rsp # arg2 = &size
|
|
xor_esi,esi # zero rsi
|
|
push_rsi # allocate stack
|
|
mov_r8,rsp # arg3 = &input
|
|
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+BYTE] !32 # fin->read()
|
|
pop_rax # deallocate stack
|
|
pop_rax # deallocate stack
|
|
pop_rax # deallocate stack
|
|
pop_rax # save input to rax
|
|
pop_rsi # save size to rsi
|
|
|
|
# If the file ended (0 bytes read) return EOF
|
|
cmp_rsi, %0 # if size == 0
|
|
jne8 !fgetc_1
|
|
mov_rax, %-4 # Put EOF in rax
|
|
|
|
:fgetc_1
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
ret # return
|
|
|
|
|
|
# Malloc isn't actually reserving memory here.
|
|
# It just updates the pointer in our already reserved storage pool.
|
|
:malloc
|
|
push_r12 # Save current malloc pointer
|
|
add_r12,rax # Request number of desired bytes
|
|
pop_rax # Return pointer
|
|
ret
|
|
|
|
|
|
# Purge_LineComment function
|
|
# Reads chars until LF and jumps to restart
|
|
:Purge_LineComment
|
|
call %fgetc # Get a char
|
|
cmp_rax, %10 # While not LF
|
|
jne8 !Purge_LineComment # Keep reading
|
|
jmp %restart
|
|
|
|
|
|
# Store_String Function
|
|
# Receives C in RCX, HEAD in RDX and Input file in R15
|
|
# Uses RBX for terminator, RCX for C and RDX for string
|
|
:Store_String
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
|
|
mov_rax, %2 # Using TYPE STRING
|
|
mov_[rdx+BYTE],rax !8 # HEAD->TYPE = STRING
|
|
mov_rax, %256 # Malloc the string
|
|
call %malloc # Get pointer to P
|
|
mov_[rdx+BYTE],rax !16 # HEAD->TEXT = STRING
|
|
mov_rbx,rcx # Protect terminator
|
|
mov_rdx,rax # Protect string pointer
|
|
:Store_String_Loop
|
|
mov_[rdx],cl # write byte
|
|
call %fgetc # read next char
|
|
mov_rcx,rax # Update C
|
|
add_rdx, %1 # STRING = STRING + 1
|
|
cmp_rcx,rbx # See if we hit terminator
|
|
jne8 !Store_String_Loop # Otherwise keep looping
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
mov_rax,rdx # return HEAD
|
|
jmp %restart
|
|
|
|
|
|
# Store_Atom Function
|
|
# Receives C in RCX, HEAD in RDX and Input file in R15
|
|
# Uses RBX for in_set strings, RCX for C and RDX for string
|
|
:Store_Atom
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
|
|
mov_rax, %256 # Malloc the string
|
|
call %malloc # Get pointer to P
|
|
mov_[rdx+BYTE],rax !16 # HEAD->TEXT = STRING
|
|
lea_rbx,[rip+DWORD] %terminators # Get pointer to "\n\t "
|
|
mov_rdx,rax # Protect string pointer
|
|
:Store_Atom_loop
|
|
mov_[rdx],cl # write byte
|
|
call %fgetc # read next char
|
|
mov_rcx,rax # Update C
|
|
add_rdx, %1 # STRING = STRING + 1
|
|
call %In_Set # Check for terminators
|
|
cmp_rax, %0 # Check for "\n\t "
|
|
je8 !Store_Atom_loop # Loop otherwise
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
mov_rax,rdx # return HEAD
|
|
ret
|
|
|
|
|
|
# In_Set function
|
|
# Receives Char C in AL and CHAR* in RBX
|
|
# Returns 1 if true, zero if false in RAX
|
|
:In_Set
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
:In_Set_loop
|
|
mov_cl,[rbx] # Read char
|
|
movzx_rcx,cl # Zero extend it
|
|
|
|
cmp_rax,rcx # See if they match
|
|
je8 !In_Set_True # return true
|
|
|
|
cmp_rcx, %0 # Check for NULL
|
|
je8 !In_Set_False # return false
|
|
|
|
add_rbx, %1 # s = s + 1
|
|
jmp8 !In_Set_loop # Keep looping
|
|
|
|
:In_Set_True
|
|
mov_rax, %1 # Set True
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
:In_Set_False
|
|
mov_rax, %0 # Set FALSE
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
# Char sets
|
|
:terminators
|
|
!10 !9 !32 !0
|
|
|
|
:comments
|
|
!35 !59 !0
|
|
|
|
:string_char
|
|
!34 !39 !0
|
|
|
|
|
|
# Reverse_List function
|
|
# Receives List in RAX
|
|
# Returns the list reversed in RAX
|
|
:Reverse_List
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
mov_rbx,rax # Set HEAD
|
|
mov_rax, %0 # ROOT = NULL
|
|
:Reverse_List_Loop
|
|
cmp_rbx, %0 # WHILE HEAD != NULL
|
|
je8 !Reverse_List_Done # Stop otherwise
|
|
|
|
mov_rcx,[rbx] # NEXT = HEAD->NEXT
|
|
mov_[rbx],rax # HEAD->NEXT = ROOT
|
|
mov_rax,rbx # ROOT = HEAD
|
|
mov_rbx,rcx # HEAD = NEXT
|
|
jmp8 !Reverse_List_Loop # Keep Going
|
|
|
|
:Reverse_List_Done
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# Identify_Macros function
|
|
# Receives List in RAX
|
|
# Updates the list in place; does not modify registers
|
|
# Uses RBX for DEFINE, RCX for I
|
|
:Identify_Macros
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
lea_rbx,[rip+DWORD] %DEFINE_str # Setup define string
|
|
mov_rcx,rax # I = HEAD
|
|
:Identify_Macros_Loop
|
|
mov_rax,[rcx+BYTE] !16 # I->TEXT
|
|
call %match # IF "DEFINE" == I->TEXT
|
|
cmp_rax, %0 # Check if match
|
|
jne8 !Identify_Macros_Next # Skip the work
|
|
|
|
# Deal with MACRO
|
|
mov_rax, %1 # Using MACRO
|
|
mov_[rcx+BYTE],rax !8 # I->TYPE = MACRO
|
|
|
|
mov_rax,[rcx] # I->NEXT
|
|
mov_rax,[rax+BYTE] !16 # I->NEXT->TEXT
|
|
mov_[rcx+BYTE],rax !16 # I->TEXT = I->NEXT->TEXT
|
|
|
|
mov_rax,[rcx] # I->NEXT
|
|
mov_rax,[rax] # I->NEXT->NEXT
|
|
mov_rax,[rax+BYTE] !16 # I->NEXT->NEXT->TEXT
|
|
mov_[rcx+BYTE],rax !24 # I->EXPRESSION = I->NEXT->NEXT->TEXT
|
|
|
|
mov_rax,[rcx] # I->NEXT
|
|
mov_rax,[rax] # I->NEXT->NEXT
|
|
mov_rax,[rax] # I->NEXT->NEXT->NEXT
|
|
mov_[rcx],rax # I->NEXT = I->NEXT->NEXT->NEXT
|
|
|
|
:Identify_Macros_Next
|
|
mov_rcx,[rcx] # I = I->NEXT
|
|
cmp_rcx, %0 # Check for NULL
|
|
jne8 !Identify_Macros_Loop # Keep looping otherwise
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
:DEFINE_str
|
|
!68 !69 !70 !73 !78 !69 !0
|
|
|
|
|
|
# match function
|
|
# Receives CHAR* in RAX and CHAR* in RBX
|
|
# Returns 0 (TRUE) or 1 (FALSE) in RAX
|
|
:match
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rcx,rax # S1 in place
|
|
mov_rdx,rbx # S2 in place
|
|
:match_Loop
|
|
mov_al,[rcx] # S1[0]
|
|
movzx_rax,al # Make it useful
|
|
mov_bl,[rdx] # S2[0]
|
|
movzx_rbx,bl # Make it useful
|
|
cmp_rax,rbx # See if they match
|
|
jne8 !match_False # If not
|
|
|
|
add_rcx, %1 # S1 = S1 + 1
|
|
add_rdx, %1 # S2 = S2 + 1
|
|
cmp_rax, %0 # If reached end of string
|
|
je8 !match_Done # Perfect match
|
|
jmp8 !match_Loop # Otherwise keep looping
|
|
|
|
:match_False
|
|
mov_rax, %1 # Return false
|
|
:match_Done
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# Line_Macro function
|
|
# Receives List in RAX
|
|
# Updates the list in place; does not modify registers
|
|
# Uses RAX for I, RBX for I->TEXT, RCX for I->EXPRESSION
|
|
:Line_Macro
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
:Line_Macro_Loop
|
|
mov_rbx,[rax+BYTE] !8 # I->TYPE
|
|
cmp_rbx, %1 # IF MACRO == I->TYPE
|
|
jne8 !Line_Macro_Next # Otherwise move on
|
|
|
|
# Is a macro apply
|
|
mov_rbx,[rax+BYTE] !16 # I->TEXT
|
|
mov_rcx,[rax+BYTE] !24 # I->EXPRESSION
|
|
mov_rax,[rax] # I->NEXT
|
|
call %Set_Expression # Apply it
|
|
jmp8 !Line_Macro_Loop # Move on to next
|
|
|
|
:Line_Macro_Next
|
|
mov_rax,[rax] # I->NEXT
|
|
cmp_rax, %0 # Check for NULL
|
|
jne8 !Line_Macro_Loop # Keep going
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
|
|
# Set_Expression function
|
|
# Receives List in RAX, CHAR* in RBX and CHAR* in RCX
|
|
# Updates the list in place; does not modify registers
|
|
# Uses RBX for C, RCX for EXP and RDX for I
|
|
:Set_Expression
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rdx,rax # Set I
|
|
:Set_Expression_Loop
|
|
mov_rax,[rdx+BYTE] !8 # I->TYPE
|
|
cmp_rax, %1 # IF MACRO == I->TYPE
|
|
je8 !Set_Expression_Next # Ignore and move on
|
|
|
|
mov_rax,[rdx+BYTE] !16 # I->TEXT
|
|
call %match # Check for match
|
|
cmp_rax, %0 # If match
|
|
jne8 !Set_Expression_Next # Otherwise next
|
|
|
|
# We have a non-macro match
|
|
mov_[rdx+BYTE],rcx !24 # I->EXPRESSION = EXP
|
|
|
|
:Set_Expression_Next
|
|
mov_rdx,[rdx] # I = I->NEXT
|
|
cmp_rdx, %0 # IF NULL == I
|
|
jne8 !Set_Expression_Loop # Otherwise keep looping
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
|
|
# Process_String function
|
|
# Receives List in RAX
|
|
# Update the list in place; does not modify registers
|
|
# Uses RBX for I->TEXT, RCX for I and RDX for S
|
|
:Process_String
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rcx,rax # I = HEAD
|
|
:Process_String_loop
|
|
mov_rax,[rcx+BYTE] !8 # I->TYPE
|
|
cmp_rax, %2 # IF STRING == I->TYPE
|
|
jne8 !Process_String_Next # Skip to next
|
|
|
|
mov_rbx,[rcx+BYTE] !16 # I->TEXT
|
|
mov_al,[rbx] # I->TEXT[0]
|
|
movzx_rax,al # make it useful
|
|
cmp_rax, %39 # IF '\'' == I->TEXT[0]
|
|
jne8 !Process_String_Raw # Deal with '"'
|
|
|
|
# Deal with '\''
|
|
add_rbx, %1 # I->TEXT + 1
|
|
mov_[rcx+BYTE],rbx !24 # I->EXPRESSION = I->TEXT + 1
|
|
jmp8 !Process_String_Next # Move on to next
|
|
|
|
:Process_String_Raw
|
|
mov_rax,rbx # Get length of I->TEXT
|
|
call %string_length # Do it
|
|
shr_rax, !2 # LENGTH = LENGTH >> 2
|
|
add_rax, %1 # LENGTH = LENGTH + 1
|
|
shl_rax, !3 # LENGTH = LENGTH << 3
|
|
call %malloc # Get string
|
|
mov_rdx,rbx # S = I->TEXT
|
|
add_rdx, %1 # S = S + 1
|
|
mov_[rcx+BYTE],rax !24 # I->EXPRESSION = hexify
|
|
mov_rbx,rax # Put hexify buffer in rbx
|
|
|
|
:Process_String_Raw_Loop
|
|
mov_al,[rdx] # Read 1 chars
|
|
movzx_rax,al # Make it useful
|
|
add_rdx, %1 # S = S + 1
|
|
cmp_al, !0 # Check for NULL
|
|
pushf # Protect condition
|
|
call %hex8 # write them all
|
|
popf # restore condition
|
|
jne8 !Process_String_Raw_Loop # Keep looping
|
|
|
|
:Process_String_Next
|
|
mov_rcx,[rcx] # I = I->NEXT
|
|
cmp_rcx, %0 # IF NULL == I
|
|
jne8 !Process_String_loop # Otherwise keep looping
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
|
|
# string_length function
|
|
# Receives CHAR* in RAX
|
|
# Returns INT in RAX
|
|
# Uses RAX for CH, RBX for S and RCX for INDEX
|
|
:string_length
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
mov_rbx,rax # Set S
|
|
mov_rcx, %0 # INDEX = 0
|
|
:string_length_loop
|
|
mov_al,[rbx+rcx] # S[0]
|
|
movzx_rax,al # make it useful
|
|
cmp_rax, %0 # IF NULL == S[0]
|
|
je8 !string_length_done # Stop
|
|
|
|
add_rcx, %1 # INDEX = INDEX + 1
|
|
jmp8 !string_length_loop # Keep going
|
|
|
|
:string_length_done
|
|
mov_rax,rcx # RETURN INDEX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# Eval_Immediates function
|
|
# Receives List in RAX
|
|
# Updates the list in place; does not modify registers
|
|
# Uses RBX for I->TEXT[0], RCX for I->TEXT[1] and RDX for I
|
|
:Eval_Immediates
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rdx,rax # I = HEAD
|
|
:Eval_Immediates_Loop
|
|
# Check for MACRO
|
|
mov_rax,[rdx+BYTE] !8 # I->TYPE
|
|
cmp_rax, %1 # IF MACRO == I->TYPE
|
|
je8 !Eval_Immediates_Next # Skip to next
|
|
|
|
# Check for NULL EXPRESSION
|
|
mov_rax,[rdx+BYTE] !24 # I->EXPRESSION
|
|
cmp_rax, %0 # IF NULL == I->EXPRESSION
|
|
jne8 !Eval_Immediates_Next # Skip to next
|
|
|
|
# Check if number
|
|
mov_rax,[rdx+BYTE] !16 # I->TEXT
|
|
mov_bl,[rax] # I->TEXT[0]
|
|
movzx_rbx,bl # Extend to use
|
|
add_rax, %1 # I->TEXT + 1
|
|
mov_cl,[rax] # I->TEXT[1]
|
|
movzx_rcx,cl # Extend to use
|
|
call %numerate_string # Convert string to INT
|
|
cmp_rax, %0 # IF 0 == numerate_string(I->TEXT + 1)
|
|
jne8 !Eval_Immediates_value # Has a value
|
|
|
|
# Last chance for Immediate
|
|
cmp_rcx, %48 # If '0' == I->TEXT[1]
|
|
jne8 !Eval_Immediates_Next # Skip to next
|
|
|
|
:Eval_Immediates_value
|
|
call %express_number # Convert value to hex string
|
|
mov_[rdx+BYTE],rax !24 # I->EXPRESSION = express_number(value, I-TEXT[0])
|
|
|
|
:Eval_Immediates_Next
|
|
mov_rdx,[rdx] # I = I->NEXT
|
|
cmp_rdx, %0 # IF NULL == I
|
|
jne8 !Eval_Immediates_Loop # Otherwise keep looping
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
|
|
# numerate_string function
|
|
# Receives CHAR* in RAX
|
|
# Returns value of CHAR* in RAX
|
|
# Uses RAX for VALUE, RBX for S, RCX for CH and RSI for NEGATIVE?
|
|
:numerate_string
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
push_rsi # Protect RSI
|
|
mov_rbx,rax # put S in correct place
|
|
mov_rax, %0 # Initialize to Zero
|
|
:numerate_string_loop
|
|
mov_cl,[rbx+BYTE] !1 # S[1]
|
|
movzx_rcx,cl # make it useful
|
|
cmp_rcx, %120 # IF 'x' == S[1]
|
|
je8 !numerate_hex # Deal with hex input
|
|
|
|
# Assume decimal input
|
|
mov_rsi, %0 # Assume no negation
|
|
mov_cl,[rbx] # S[0]
|
|
movzx_rcx,cl # make it useful
|
|
cmp_rcx, %45 # IF '-' == S[0]
|
|
jne8 !numerate_decimal # Skip negation
|
|
|
|
mov_rsi, %1 # Set FLAG
|
|
add_rbx, %1 # S = S + 1
|
|
|
|
:numerate_decimal
|
|
mov_cl,[rbx] # S[0]
|
|
movzx_rcx,cl # make it useful
|
|
cmp_rcx, %0 # IF NULL == S[0]
|
|
je8 !numerate_decimal_done # We are done
|
|
|
|
imul_rax, !10 # VALUE = VALUE * 10
|
|
sub_rcx, !48 # CH = CH - '0'
|
|
cmp_rcx, %9 # Check for illegal
|
|
jg8 !numerate_string_fail # If CH > '9'
|
|
cmp_rcx, %0 # Check for illegal
|
|
jl8 !numerate_string_fail # IF CH < 0
|
|
add_rax,rcx # VALUE = VALUE + CH
|
|
add_rbx, %1 # S = S + 1
|
|
jmp8 !numerate_decimal # Keep looping
|
|
|
|
:numerate_decimal_done
|
|
cmp_rsi, %1 # Check if need to negate
|
|
jne8 !numerate_string_done # Nope
|
|
|
|
imul_rax, !-1 # VALUE = VALUE * -1
|
|
jmp8 !numerate_string_done # Done
|
|
|
|
:numerate_hex
|
|
add_rbx, %2 # S = S + 2
|
|
:numerate_hex_loop
|
|
mov_cl,[rbx] # S[0]
|
|
movzx_rcx,cl # make it useful
|
|
cmp_rcx, %0 # IF NULL == S[0]
|
|
je8 !numerate_string_done # We are done
|
|
|
|
shl_rax, !4 # VALUE = VALUE << 4
|
|
sub_rcx, !48 # CH = CH - '0'
|
|
cmp_rcx, %10 # IF 10 >= CH
|
|
jl8 !numerate_hex_digit # NO
|
|
sub_rcx, !7 # Push A-F into range
|
|
:numerate_hex_digit
|
|
cmp_rcx, %15 # Check for illegal
|
|
jg8 !numerate_string_fail # If CH > 'F'
|
|
cmp_rcx, %0 # Check for illegal
|
|
jl8 !numerate_string_fail # IF CH < 0
|
|
add_rax,rcx # VALUE = VALUE + CH
|
|
add_rbx, %1 # S = S + 1
|
|
jmp8 !numerate_hex_loop # Keep looping
|
|
|
|
:numerate_string_fail
|
|
mov_rax, %0 # return ZERO
|
|
|
|
:numerate_string_done
|
|
pop_rsi # Restore RSI
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# express_number function
|
|
# Receives INT in RAX and CHAR in RBX
|
|
# Allocates a string and expresses the value in hex
|
|
# Returns string in RAX
|
|
# Uses RAX for VALUE, RBX for S and RCX for CH
|
|
:express_number
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rcx,rbx # Put CH in right place
|
|
mov_rbx,rax # Protect VALUE
|
|
cmp_rcx, %37 # IF '%' == CH
|
|
jne8 !express_number2 # Otherwise try @
|
|
|
|
mov_rax, %9 # We need 9 bytes
|
|
call %malloc # Get S pointer
|
|
xchg_rax,rbx # Put S and VALUE in place
|
|
push_rbx # Protect S
|
|
call %hex32l # Store 32bits
|
|
jmp8 !express_number_done # done
|
|
|
|
:express_number2
|
|
cmp_rcx, %64 # IF '@' == CH
|
|
jne8 !express_number1 # Othrewise try !
|
|
|
|
mov_rax, %5 # We need 5 bytes
|
|
call %malloc # Get S pointer
|
|
xchg_rax,rbx # Put S and VALUE in place
|
|
push_rbx # Protect S
|
|
call %hex16l # Store 16bits
|
|
jmp8 !express_number_done # done
|
|
|
|
:express_number1
|
|
mov_rax, %3 # We need 3 bytes
|
|
call %malloc # Get S pointer
|
|
xchg_rax,rbx # Put S and VALUE in place
|
|
push_rbx # Protect S
|
|
call %hex8 # Store 8bit
|
|
|
|
:express_number_done
|
|
pop_rax # Restore S
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# HEX to ascii routine
|
|
# Receives INT in RAX and CHAR* in RBX
|
|
# Stores ascii of INT in CHAR*
|
|
# Returns only modifying RAX
|
|
:hex64l
|
|
push_rax # Protect top 32
|
|
call %hex32l # Store it
|
|
pop_rax # do top 32
|
|
shr_rax, !32 # do bottom 32 first
|
|
:hex32l
|
|
push_rax # Protect top 16
|
|
call %hex16l # Store it
|
|
pop_rax # do top 16
|
|
shr_rax, !16 # do bottom 16 first
|
|
:hex16l
|
|
push_rax # Protect top byte
|
|
call %hex8 # Store it
|
|
pop_rax # do high byte
|
|
shr_rax, !8 # do bottom byte first
|
|
:hex8
|
|
push_rax # Protect bottom nibble
|
|
shr_rax, !4 # do high nibble first
|
|
call %hex4 # Store it
|
|
pop_rax # do low nibble
|
|
:hex4
|
|
and_rax, !0xF # isolate nibble
|
|
add_al, !0x30 # convert to ascii (add '0')
|
|
cmp_al, !0x39 # valid digit? (compare to '9')
|
|
jbe8 !hex1 # yes
|
|
add_al, !7 # use alpha range
|
|
:hex1
|
|
mov_[ebx],al # store result
|
|
add_ebx, !1 # next position
|
|
ret
|
|
|
|
|
|
# Preserve_Other function
|
|
# Receives List in RAX
|
|
# Updates the list in place; does not modify registers
|
|
# Uses RAX for I, RBX for I->TEXT
|
|
:Preserve_Other
|
|
push_rax # Protect RAX
|
|
push_rbx # Protect RBX
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
:Preserve_Other_Loop
|
|
mov_rbx,[rax+BYTE] !24 # I->EXPRESSION
|
|
cmp_rbx, %0 # IF NULL == I->EXPRESSION
|
|
jne8 !Preserve_Other_Next # Otherwise next
|
|
|
|
# Needs preserving
|
|
mov_rbx,[rax+BYTE] !16 # I->TEXT
|
|
mov_[rax+BYTE],rbx !24 # I->EXPRESSION = I->TEXT
|
|
|
|
:Preserve_Other_Next
|
|
mov_rax,[rax] # I = I->NEXT
|
|
cmp_rax, %0 # IF NULL == I
|
|
jne8 !Preserve_Other_Loop # Otherwise keep looping
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
pop_rbx # Restore RBX
|
|
pop_rax # Restore RAX
|
|
ret
|
|
|
|
|
|
# Print_Hex function
|
|
# Receives list in RAX
|
|
# walks the list and prints the I->EXPRESSION for all nodes followed by newline
|
|
# Uses RBX for I
|
|
:Print_Hex
|
|
push_rbx # Protect RBX
|
|
mov_rbx,r13 # I = Head
|
|
:Print_Hex_Loop
|
|
mov_rax,[rbx+BYTE] !8 # I->TYPE
|
|
cmp_rax, %1 # IF MACRO == I->TYPE
|
|
je8 !Print_Hex_Next # Skip
|
|
|
|
mov_rax,[rbx+BYTE] !24 # Using EXPRESSION
|
|
call %File_Print # Print it
|
|
mov_rax, %10 # NEWLINE
|
|
call %fputc # Append it
|
|
|
|
:Print_Hex_Next
|
|
mov_rbx,[rbx] # Iterate to next Token
|
|
cmp_rbx, %0 # Check for NULL
|
|
jne8 !Print_Hex_Loop # Otherwise keep looping
|
|
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# File_Print function
|
|
# Receives CHAR* in RAX
|
|
# calls fputc for every non-null char
|
|
:File_Print
|
|
push_rbx # Protect RBX
|
|
mov_rbx,rax # Protect S
|
|
cmp_rax, %0 # Protect against nulls
|
|
je8 !File_Print_Done # Simply don't try to print them
|
|
:File_Print_Loop
|
|
mov_al,[rbx] # Read byte
|
|
movzx_rax,al # zero extend
|
|
cmp_rax, %0 # Check for NULL
|
|
je8 !File_Print_Done # Stop at NULL
|
|
|
|
call %fputc # write it
|
|
add_rbx, %1 # S = S + 1
|
|
jmp8 !File_Print_Loop # Keep going
|
|
|
|
:File_Print_Done
|
|
pop_rbx # Restore RBX
|
|
ret
|
|
|
|
|
|
# fputc function
|
|
# receives CHAR in RAX
|
|
# writes char and returns
|
|
:fputc
|
|
push_rcx # Protect RCX
|
|
push_rdx # Protect RDX
|
|
mov_rcx,[rip+DWORD] %fout # arg1 = fout
|
|
push !1 # set size
|
|
mov_rdx,rsp # arg2 = &size
|
|
push_rax # allocate stack
|
|
mov_r8,rsp # arg3 = &output
|
|
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+BYTE] !40 # fout->write()
|
|
add_rsp, !40 # deallocate stack
|
|
|
|
pop_rdx # Restore RDX
|
|
pop_rcx # Restore RCX
|
|
ret # return
|
|
|
|
|
|
# rcx: file handle
|
|
:close_file
|
|
push_rax # allocate shadow stack space for UEFI function
|
|
call_[rcx+BYTE] !16 # file_handle->close(file_handle)
|
|
pop_rax # deallocate stack
|
|
ret
|
|
|
|
# rcx: handle
|
|
# rdx: &guid
|
|
# r9: agent_handle
|
|
# returns interface
|
|
:open_protocol
|
|
push_rax # allocate stack for interface
|
|
mov_r8,rsp # arg3 = &interface
|
|
push !1 # arg6 = EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
|
|
push !0 # arg5 = NULL
|
|
sub_rsp, !32 # allocate shadow stack space for UEFI function
|
|
call_[r14+DWORD] %280 # system->boot->open_protocol(handle, &guid, &interface, agent_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)
|
|
add_rsp, !48 # deallocate stack
|
|
pop_rax # get interface
|
|
ret
|
|
|
|
# rcx: handle
|
|
# rdx: &guid
|
|
# r8: agent_handle
|
|
:close_protocol
|
|
xor_r9,r9 # arg4 = NULL
|
|
sub_rsp, !32 # allocate shadow stack space for UEFI function
|
|
call_[r14+DWORD] %288 # system->boot->close_protocol(handle, &guid, agent_handle, 0)
|
|
add_rsp, !32 # deallocate stack
|
|
ret
|
|
|
|
# rdx: number of bytes to allocate
|
|
# r14: system->boot
|
|
# returns pointer in rax
|
|
:allocate_pool
|
|
push_rdx # allocate stack for pool pointer
|
|
mov_r8,rsp # arg3 = &pool
|
|
push !2
|
|
pop_rcx # arg1 = EFI_LOADER_DATA
|
|
sub_rsp, !24 # allocate shadow stack space for UEFI
|
|
call_[r14+BYTE] !64 # system->boot->allocate_pool(EFI_LOADER_DATA, 2048, &pool)
|
|
add_rsp, !24 # deallocate stack
|
|
pop_rax # get pool
|
|
ret
|
|
|
|
# rcx: memory pool
|
|
# r14: system->boot
|
|
:free_pool
|
|
push_rax # allocate shadow stack space for UEFI function
|
|
call_[r14+BYTE] !72 # system->boot->free_pool(pool)
|
|
pop_rax # deallocate stack
|
|
ret
|
|
|
|
|
|
# Protocol GUIDs
|
|
:LOADED_IMAGE_PROTOCOL
|
|
%0x5B1B31A1
|
|
@0x9562
|
|
@0x11D2
|
|
!0x8E !0x3F !0 !0xA0 !0xC9 !0x69 !0x72 !0x3B
|
|
|
|
:SIMPLE_FS_PROTOCOL
|
|
%0x964E5B22
|
|
@0x6459
|
|
@0x11D2
|
|
!0x8E !0x39 !0 !0xA0 !0xC9 !0x69 !0x72 !0x3B
|
|
|
|
:malloc_pool
|
|
%0 %0
|
|
|
|
:fin
|
|
%0 %0
|
|
|
|
:fout
|
|
%0 %0
|
|
|
|
:rootdir
|
|
%0 %0
|
|
|
|
:image_handle
|
|
%0 %0
|
|
|
|
:root_device
|
|
%0 %0
|
|
|
|
:ELF_end
|