Merge pull request #1488 from elicn/dev-uefi

Periodic maintenance PR
This commit is contained in:
xwings
2024-10-11 10:34:02 +08:00
committed by GitHub
25 changed files with 1492 additions and 1409 deletions
+70 -20
View File
@@ -3,8 +3,11 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from pefile import PE
import os
from typing import Any, Mapping, Optional, Sequence
from pefile import PE
from unicorn.unicorn_const import UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
from qiling import Qiling
from qiling.const import QL_ARCH
@@ -96,17 +99,64 @@ class QlLoaderPE_UEFI(QlLoader):
# use image base only if it does not point to NULL
image_base = pe.OPTIONAL_HEADER.ImageBase or context.next_image_base
image_size = ql.mem.align_up(pe.OPTIONAL_HEADER.SizeOfImage)
image_name = os.path.basename(path)
assert (image_base % ql.mem.pagesize) == 0, 'image base is expected to be page-aligned'
if image_base != pe.OPTIONAL_HEADER.ImageBase:
pe.relocate_image(image_base)
pe.parse_data_directories()
data = bytes(pe.get_memory_mapped_image())
# pe.parse_data_directories()
sec_alignment = pe.OPTIONAL_HEADER.SectionAlignment
def __map_sections():
"""Load file sections to memory, each in its own memory region protected by
its defined permissions. That allows separation of code and data, which makes
it easier to detect abnomal behavior or memory corruptions.
"""
# load the header
hdr_data = bytes(pe.header)
hdr_base = image_base
hdr_size = ql.mem.align_up(len(hdr_data), sec_alignment)
hdr_perm = UC_PROT_READ
ql.mem.map(hdr_base, hdr_size, hdr_perm, image_name)
ql.mem.write(hdr_base, hdr_data)
# load sections
for section in pe.sections:
if not section.IMAGE_SCN_MEM_DISCARDABLE:
sec_name = section.Name.rstrip(b'\x00').decode()
sec_data = bytes(section.get_data(ignore_padding=True))
sec_base = image_base + section.get_VirtualAddress_adj()
sec_size = ql.mem.align_up(len(sec_data), sec_alignment)
sec_perm = sum((
section.IMAGE_SCN_MEM_READ * UC_PROT_READ,
section.IMAGE_SCN_MEM_WRITE * UC_PROT_WRITE,
section.IMAGE_SCN_MEM_EXECUTE * UC_PROT_EXEC
))
ql.mem.map(sec_base, sec_size, sec_perm, f'{image_name} ({sec_name})')
ql.mem.write(sec_base, sec_data)
def __map_all():
"""Load the entire file to memory as a single memory region.
"""
data = bytes(pe.get_memory_mapped_image())
ql.mem.map(image_base, image_size, info=image_name)
ql.mem.write(image_base, data)
# if sections are aligned to page, we can map them separately
if (sec_alignment % ql.mem.pagesize) == 0:
__map_sections()
else:
__map_all()
ql.mem.map(image_base, image_size, info="[module]")
ql.mem.write(image_base, data)
ql.log.info(f'Module {path} loaded to {image_base:#x}')
entry_point = image_base + pe.OPTIONAL_HEADER.AddressOfEntryPoint
@@ -120,7 +170,7 @@ class QlLoaderPE_UEFI(QlLoader):
self.install_loaded_image_protocol(image_base, image_size)
# this would be used later be loader.find_containing_image
self.images.append(Image(image_base, image_base + image_size, path))
self.images.append(Image(image_base, image_base + image_size, os.path.abspath(path)))
# update next memory slot to allow sequencial loading. its availability
# is unknown though
@@ -160,7 +210,7 @@ class QlLoaderPE_UEFI(QlLoader):
for handle in context.loaded_image_protocol_modules:
struct_addr = context.protocols[handle][self.loaded_image_protocol_guid]
loaded_image_protocol = EfiLoadedImageProtocol.EFI_LOADED_IMAGE_PROTOCOL.loadFrom(self.ql, struct_addr)
loaded_image_protocol = EfiLoadedImageProtocol.EFI_LOADED_IMAGE_PROTOCOL.load_from(self.ql.mem, struct_addr)
unload_ptr = loaded_image_protocol.Unload.value
@@ -223,19 +273,19 @@ class QlLoaderPE_UEFI(QlLoader):
context = DxeContext(ql)
# initialize and locate heap
heap_base = int(profile['heap_address'], 0)
heap_size = int(profile['heap_size'], 0)
heap_base = profile.getint('heap_address')
heap_size = profile.getint('heap_size')
context.init_heap(heap_base, heap_size)
ql.log.info(f'DXE heap at {heap_base:#010x}')
# initialize and locate stack
stack_base = int(profile['stack_address'], 0)
stack_size = int(profile['stack_size'], 0)
stack_base = profile.getint('stack_address')
stack_size = profile.getint('stack_size')
context.init_stack(stack_base, stack_size)
ql.log.info(f'DXE stack at {context.top_of_stack:#010x}')
# base address for next image
context.next_image_base = int(profile['image_address'], 0)
context.next_image_base = profile.getint('image_address')
# statically allocating 4 KiB for ST, RT, BS, DS and about 100 configuration table entries.
# the actual size needed was rounded up to the nearest page boundary.
@@ -272,23 +322,23 @@ class QlLoaderPE_UEFI(QlLoader):
context = SmmContext(ql)
# set smram boundaries
context.smram_base = int(profile["smram_base"], 0)
context.smram_size = int(profile["smram_size"], 0)
context.smram_base = profile.getint('smram_base')
context.smram_size = profile.getint('smram_size')
# initialize and locate heap
heap_base = int(profile["heap_address"], 0)
heap_size = int(profile["heap_size"], 0)
heap_base = profile.getint('heap_address')
heap_size = profile.getint('heap_size')
context.init_heap(heap_base, heap_size)
ql.log.info(f"SMM heap at {heap_base:#010x}")
# initialize and locate stack
stack_base = int(profile['stack_address'], 0)
stack_size = int(profile['stack_size'], 0)
stack_base = profile.getint('stack_address')
stack_size = profile.getint('stack_size')
context.init_stack(stack_base, stack_size)
ql.log.info(f'SMM stack at {context.top_of_stack:#010x}')
# base address for next image
context.next_image_base = int(profile['image_address'], 0)
context.next_image_base = profile.getint('image_address')
# statically allocating 4 KiB for SMM ST and about 100 configuration table entries
# the actual size needed was rounded up to the nearest page boundary.
@@ -325,7 +375,7 @@ class QlLoaderPE_UEFI(QlLoader):
raise QlErrorArch("Unsupported architecture")
# x86-64 arch only
if ql.arch.type != QL_ARCH.X8664:
if ql.arch.type is not QL_ARCH.X8664:
raise QlErrorArch("Only 64-bit modules are supported at the moment")
self.loaded_image_protocol_guid = ql.os.profile["LOADED_IMAGE_PROTOCOL"]["Guid"]
+31 -14
View File
@@ -1,29 +1,46 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from .UefiBaseType import *
from .ProcessorBind import *
from .UefiBaseType import EFI_PHYSICAL_ADDRESS
from .ProcessorBind import UINT64, STRUCT, ENUM_UC
EFI_SMRAM_OPEN = 0x00000001
EFI_SMRAM_CLOSED = 0x00000002
EFI_SMRAM_LOCKED = 0x00000004
EFI_CACHEABLE = 0x00000008
EFI_ALLOCATED = 0x00000010
EFI_NEEDS_TESTING = 0x00000020
EFI_NEEDS_ECC_INITIALIZATION = 0x00000040
EFI_SMRAM_OPEN = 0x00000001
EFI_SMRAM_CLOSED = 0x00000002
EFI_SMRAM_LOCKED = 0x00000004
EFI_CACHEABLE = 0x00000008
EFI_ALLOCATED = 0x00000010
EFI_NEEDS_TESTING = 0x00000020
EFI_NEEDS_ECC_INITIALIZATION = 0x00000040
class EFI_SMRAM_DESCRIPTOR(STRUCT):
_fields_ = [
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('CpuStart', EFI_PHYSICAL_ADDRESS),
('PhysicalSize', UINT64),
('RegionState', UINT64)
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('CpuStart', EFI_PHYSICAL_ADDRESS),
('PhysicalSize', UINT64),
('RegionState', UINT64)
]
class EFI_VARIABLE(ENUM_UC):
_members_ = {
'NON_VOLATILE': 0x00000001,
'BOOTSERVICE_ACCESS': 0x00000002,
'RUNTIME_ACCESS': 0x00000004,
'HARDWARE_ERROR_RECORD': 0x00000008,
'AUTHENTICATED_WRITE_ACCESS': 0x00000010,
'TIME_BASED_AUTHENTICATED_WRITE_ACCESS': 0x00000020,
'APPEND_WRITE': 0x00000040,
'ENHANCED_AUTHENTICATED_ACCESS': 0x00000080
}
__all__ = [
'EFI_SMRAM_DESCRIPTOR',
'EFI_VARIABLE',
'EFI_SMRAM_OPEN',
'EFI_SMRAM_CLOSED',
'EFI_SMRAM_LOCKED',
+26 -74
View File
@@ -1,31 +1,37 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
import ctypes
from contextlib import contextmanager
from typing import Mapping, MutableMapping, Sequence, Optional
from functools import lru_cache
from typing import Mapping, Sequence, Union
from qiling.os.struct import BaseStructEL
from qiling import Qiling
bits = 64
psize = bits // 8
dummy_ptr_type = {
32 : ctypes.c_uint32,
64 : ctypes.c_uint64
}[bits]
@lru_cache(maxsize=None)
def PTR(ptype: Union[type, None]) -> type:
"""Generate a pseudo pointer type.
"""
_pointer_type_cache: MutableMapping[str, type] = {}
def PTR(ptype: Optional[type]) -> type:
pname = 'c_void' if ptype is None else ptype.__name__
if pname not in _pointer_type_cache:
_pointer_type_cache[pname] = type(f'LP_{psize}_{pname}', (dummy_ptr_type,), {})
return type(f'LP_{psize}_{pname}', (UINTN,), {})
def FUNCPTR(rettype: Union[type, None], *argtypes: type) -> type:
"""Generate a pseudo function pointer type.
"""
return PTR(ctypes.CFUNCTYPE(rettype, *argtypes))
return _pointer_type_cache[pname]
VOID = None
INT8 = ctypes.c_int8
@@ -44,75 +50,18 @@ BOOLEAN = UINT8
CHAR8 = UINT8
CHAR16 = UINT16
FUNCPTR = lambda *args: PTR(ctypes.CFUNCTYPE(*args))
STRUCT = BaseStructEL
UNION = ctypes.Union
CPU_STACK_ALIGNMENT = 16
PAGE_SIZE = 0x1000
class STRUCT(ctypes.LittleEndianStructure):
"""An abstract class for C structures.
"""
# Structures are packed by default; when needed, padding should be added
# manually through placeholder fields
_pack_ = 1
def __init__(self):
pass
def saveTo(self, ql: Qiling, address: int) -> None:
"""Store self contents to a specified memory address.
"""
data = bytes(self)
ql.mem.write(address, data)
@classmethod
def loadFrom(cls, ql: Qiling, address: int) -> 'STRUCT':
"""Construct an instance of the structure from saved contents.
"""
data = bytes(ql.mem.read(address, cls.sizeof()))
return cls.from_buffer_copy(data)
@classmethod
@contextmanager
def bindTo(cls, ql: Qiling, address: int):
instance = cls.loadFrom(ql, address)
try:
yield instance
finally:
instance.saveTo(ql, address)
@classmethod
def sizeof(cls) -> int:
"""Get the C structure size in bytes.
"""
return ctypes.sizeof(cls)
@classmethod
def offsetof(cls, fname: str) -> int:
"""Get the offset of a field in the C structure.
"""
return getattr(cls, fname).offset
@classmethod
def memberat(cls, offset: int) -> Optional[str]:
"""Get the member name at a given offset.
"""
return next((fname for fname, *_ in cls._fields_ if cls.offsetof(fname) == offset), None)
class EnumMeta(type(ctypes.c_int)):
def __getattr__(self, key):
return self._members_.index(key)
class ENUM(ctypes.c_int, metaclass=EnumMeta):
"""An abstract class for continuous C enums.
"""
@@ -121,10 +70,12 @@ class ENUM(ctypes.c_int, metaclass=EnumMeta):
# names will be enumerate by their corresponding index in the list
_members_: Sequence[str] = []
class EnumUCMeta(type(ctypes.c_int)):
def __getattr__(self, key):
return self._members_[key]
class ENUM_UC(ctypes.c_int, metaclass=EnumUCMeta):
"""An abstract class for uncontinuous C enums.
"""
@@ -133,6 +84,7 @@ class ENUM_UC(ctypes.c_int, metaclass=EnumUCMeta):
# names will be enumerate by their paired value
_members_: Mapping[str, int] = {}
__all__ = [
'VOID',
'INT8',
@@ -158,4 +110,4 @@ __all__ = [
'CPU_STACK_ALIGNMENT',
'PAGE_SIZE'
]
]
+17 -13
View File
@@ -1,9 +1,10 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from qiling.os.uefi.ProcessorBind import *
from qiling.os.uefi.ProcessorBind import VOID, UINT8, UINT16, UINT32, UINT64, UINTN, STRUCT, PTR
class EFI_GUID(STRUCT):
_fields_ = [
@@ -13,6 +14,7 @@ class EFI_GUID(STRUCT):
('Data4', UINT8 * 8)
]
EFI_STATUS = UINTN
EFI_HANDLE = PTR(VOID)
EFI_EVENT = PTR(VOID)
@@ -21,21 +23,23 @@ EFI_LBA = UINT64
EFI_PHYSICAL_ADDRESS = UINT64
EFI_VIRTUAL_ADDRESS = UINT64
class EFI_TIME(STRUCT):
_fields_ = [
('Year', UINT16),
('Month', UINT8),
('Day', UINT8),
('Hour', UINT8),
('Minute', UINT8),
('Second', UINT8),
('Pad1', UINT8),
('Nanosecond', UINT32),
('TimeZone', UINT16),
('Daylight', UINT8),
('Pad2', UINT8)
('Year', UINT16),
('Month', UINT8),
('Day', UINT8),
('Hour', UINT8),
('Minute', UINT8),
('Second', UINT8),
('Pad1', UINT8),
('Nanosecond', UINT32),
('TimeZone', UINT16),
('Daylight', UINT8),
('Pad2', UINT8)
]
__all__ = [
'EFI_GUID',
'EFI_STATUS',
+12 -8
View File
@@ -1,20 +1,22 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from .ProcessorBind import *
from .ProcessorBind import UINT32, UINT64, STRUCT, ENUM
# @see: MdePkg\Include\Uefi\UefiMultiPhase.h
class EFI_TABLE_HEADER(STRUCT):
_fields_ = [
('Signature', UINT64),
('Revision', UINT32),
('HeaderSize', UINT32),
('CRC32', UINT32),
('Reserved', UINT32)
('Signature', UINT64),
('Revision', UINT32),
('HeaderSize', UINT32),
('CRC32', UINT32),
('Reserved', UINT32)
]
class EFI_RESET_TYPE(ENUM):
_members_ = [
'EfiResetCold',
@@ -23,6 +25,7 @@ class EFI_RESET_TYPE(ENUM):
'EfiResetPlatformSpecific',
]
class EFI_MEMORY_TYPE(ENUM):
_members_ = [
'EfiReservedMemoryType',
@@ -43,8 +46,9 @@ class EFI_MEMORY_TYPE(ENUM):
'EfiMaxMemoryType'
]
__all__ = [
'EFI_TABLE_HEADER',
'EFI_RESET_TYPE',
'EFI_MEMORY_TYPE'
]
]
+148 -148
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -48,62 +48,62 @@ class EFI_TIME_CAPABILITIES(STRUCT):
_pack_ = 8
_fields_ = [
('Resolution', UINT32),
('Accuracy', UINT32),
('SetsToZero', BOOLEAN),
('Resolution', UINT32),
('Accuracy', UINT32),
('SetsToZero', BOOLEAN),
]
class EFI_MEMORY_DESCRIPTOR(STRUCT):
_pack_ = 8
_fields_ = [
('Type', UINT32),
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('VirtualStart', EFI_VIRTUAL_ADDRESS),
('NumberOfPages', UINT64),
('Attribute', UINT64)
('Type', UINT32),
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('VirtualStart', EFI_VIRTUAL_ADDRESS),
('NumberOfPages', UINT64),
('Attribute', UINT64)
]
class EFI_CAPSULE_HEADER(STRUCT):
_fields_ = [
('CapsuleGuid', EFI_GUID),
('HeaderSize', UINT32),
('Flags', UINT32),
('CapsuleImageSize', UINT32)
('CapsuleGuid', EFI_GUID),
('HeaderSize', UINT32),
('Flags', UINT32),
('CapsuleImageSize', UINT32)
]
EFI_GET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME), PTR(EFI_TIME_CAPABILITIES))
EFI_SET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME))
EFI_GET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, PTR(BOOLEAN), PTR(BOOLEAN), PTR(EFI_TIME))
EFI_SET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, BOOLEAN, PTR(EFI_TIME))
EFI_SET_VIRTUAL_ADDRESS_MAP = FUNCPTR(EFI_STATUS, UINTN, UINTN, UINT32, PTR(EFI_MEMORY_DESCRIPTOR))
EFI_CONVERT_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(PTR(VOID)))
EFI_GET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), PTR(UINT32), PTR(UINTN), PTR(VOID))
EFI_GET_NEXT_VARIABLE_NAME = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(CHAR16), PTR(EFI_GUID))
EFI_SET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), UINT32, UINTN, PTR(VOID))
EFI_GET_NEXT_HIGH_MONO_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT32))
EFI_RESET_SYSTEM = FUNCPTR(VOID, EFI_RESET_TYPE, EFI_STATUS, UINTN, PTR(VOID))
EFI_UPDATE_CAPSULE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, EFI_PHYSICAL_ADDRESS)
EFI_QUERY_CAPSULE_CAPABILITIES = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, PTR(UINT64), PTR(EFI_RESET_TYPE))
EFI_QUERY_VARIABLE_INFO = FUNCPTR(EFI_STATUS, UINT32, PTR(UINT64), PTR(UINT64), PTR(UINT64))
EFI_GET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME), PTR(EFI_TIME_CAPABILITIES))
EFI_SET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME))
EFI_GET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, PTR(BOOLEAN), PTR(BOOLEAN), PTR(EFI_TIME))
EFI_SET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, BOOLEAN, PTR(EFI_TIME))
EFI_SET_VIRTUAL_ADDRESS_MAP = FUNCPTR(EFI_STATUS, UINTN, UINTN, UINT32, PTR(EFI_MEMORY_DESCRIPTOR))
EFI_CONVERT_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(PTR(VOID)))
EFI_GET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), PTR(UINT32), PTR(UINTN), PTR(VOID))
EFI_GET_NEXT_VARIABLE_NAME = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(CHAR16), PTR(EFI_GUID))
EFI_SET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), UINT32, UINTN, PTR(VOID))
EFI_GET_NEXT_HIGH_MONO_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT32))
EFI_RESET_SYSTEM = FUNCPTR(VOID, EFI_RESET_TYPE, EFI_STATUS, UINTN, PTR(VOID))
EFI_UPDATE_CAPSULE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, EFI_PHYSICAL_ADDRESS)
EFI_QUERY_CAPSULE_CAPABILITIES = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, PTR(UINT64), PTR(EFI_RESET_TYPE))
EFI_QUERY_VARIABLE_INFO = FUNCPTR(EFI_STATUS, UINT32, PTR(UINT64), PTR(UINT64), PTR(UINT64))
class EFI_RUNTIME_SERVICES(STRUCT):
_fields_ = [
('Hdr', EFI_TABLE_HEADER),
('GetTime', EFI_GET_TIME),
('SetTime', EFI_SET_TIME),
('GetWakeupTime', EFI_GET_WAKEUP_TIME),
('SetWakeupTime', EFI_SET_WAKEUP_TIME),
('SetVirtualAddressMap', EFI_SET_VIRTUAL_ADDRESS_MAP),
('ConvertPointer', EFI_CONVERT_POINTER),
('GetVariable', EFI_GET_VARIABLE),
('GetNextVariableName', EFI_GET_NEXT_VARIABLE_NAME),
('SetVariable', EFI_SET_VARIABLE),
('GetNextHighMonotonicCount', EFI_GET_NEXT_HIGH_MONO_COUNT),
('ResetSystem', EFI_RESET_SYSTEM),
('UpdateCapsule', EFI_UPDATE_CAPSULE),
('QueryCapsuleCapabilities', EFI_QUERY_CAPSULE_CAPABILITIES),
('QueryVariableInfo', EFI_QUERY_VARIABLE_INFO)
('Hdr', EFI_TABLE_HEADER),
('GetTime', EFI_GET_TIME),
('SetTime', EFI_SET_TIME),
('GetWakeupTime', EFI_GET_WAKEUP_TIME),
('SetWakeupTime', EFI_SET_WAKEUP_TIME),
('SetVirtualAddressMap', EFI_SET_VIRTUAL_ADDRESS_MAP),
('ConvertPointer', EFI_CONVERT_POINTER),
('GetVariable', EFI_GET_VARIABLE),
('GetNextVariableName', EFI_GET_NEXT_VARIABLE_NAME),
('SetVariable', EFI_SET_VARIABLE),
('GetNextHighMonotonicCount', EFI_GET_NEXT_HIGH_MONO_COUNT),
('ResetSystem', EFI_RESET_SYSTEM),
('UpdateCapsule', EFI_UPDATE_CAPSULE),
('QueryCapsuleCapabilities', EFI_QUERY_CAPSULE_CAPABILITIES),
('QueryVariableInfo', EFI_QUERY_VARIABLE_INFO)
]
EFI_EVENT_NOTIFY = FUNCPTR(VOID, EFI_EVENT, PTR(VOID))
@@ -112,109 +112,109 @@ EFI_EVENT_NOTIFY = FUNCPTR(VOID, EFI_EVENT, PTR(VOID))
class EFI_DEVICE_PATH_PROTOCOL(STRUCT):
_fields_ = [
('Type', UINT8),
('SubType', UINT8),
('Length', UINT8 * 2)
('SubType', UINT8),
('Length', UINT8 * 2)
]
class EFI_OPEN_PROTOCOL_INFORMATION_ENTRY(STRUCT):
_fields_ = [
('AgentHandle', EFI_HANDLE),
('ControllerHandle',EFI_HANDLE),
('Attributes', UINT32),
('AgentHandle', EFI_HANDLE),
('ControllerHandle', EFI_HANDLE),
('Attributes', UINT32),
('OpenCount', UINT32)
]
EFI_RAISE_TPL = FUNCPTR(EFI_TPL, EFI_TPL)
EFI_RESTORE_TPL = FUNCPTR(VOID, EFI_TPL)
EFI_ALLOCATE_PAGES = FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))
EFI_FREE_PAGES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)
EFI_GET_MEMORY_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(EFI_MEMORY_DESCRIPTOR), PTR(UINTN), PTR(UINTN), PTR(UINT32))
EFI_ALLOCATE_POOL = FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))
EFI_FREE_POOL = FUNCPTR(EFI_STATUS, PTR(VOID))
EFI_CREATE_EVENT = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_EVENT))
EFI_SET_TIMER = FUNCPTR(EFI_STATUS, EFI_EVENT, EFI_TIMER_DELAY, UINT64)
EFI_WAIT_FOR_EVENT = FUNCPTR(EFI_STATUS, UINTN, PTR(EFI_EVENT), PTR(UINTN))
EFI_SIGNAL_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_CLOSE_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_CHECK_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_INSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))
EFI_REINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID), PTR(VOID))
EFI_UNINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID))
EFI_HANDLE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)))
EFI_REGISTER_PROTOCOL_NOTIFY = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_EVENT, PTR(PTR(VOID)))
EFI_LOCATE_HANDLE = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))
EFI_LOCATE_DEVICE_PATH = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)), PTR(EFI_HANDLE))
EFI_INSTALL_CONFIGURATION_TABLE = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID))
EFI_IMAGE_LOAD = FUNCPTR(EFI_STATUS, BOOLEAN, EFI_HANDLE, PTR(EFI_DEVICE_PATH_PROTOCOL), PTR(VOID) , UINTN, PTR(EFI_HANDLE))
EFI_IMAGE_START = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(UINTN), PTR(PTR(CHAR16)))
EFI_EXIT = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_STATUS, UINTN, PTR(CHAR16))
EFI_IMAGE_UNLOAD = FUNCPTR(EFI_STATUS, EFI_HANDLE)
EFI_EXIT_BOOT_SERVICES = FUNCPTR(EFI_STATUS, EFI_HANDLE, UINTN)
EFI_GET_NEXT_MONOTONIC_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT64))
EFI_STALL = FUNCPTR(EFI_STATUS, UINTN)
EFI_SET_WATCHDOG_TIMER = FUNCPTR(EFI_STATUS, UINTN, UINT64, UINTN, PTR(CHAR16))
EFI_CONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_HANDLE), PTR(EFI_DEVICE_PATH_PROTOCOL), BOOLEAN)
EFI_DISCONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_HANDLE, EFI_HANDLE)
EFI_OPEN_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)), EFI_HANDLE, EFI_HANDLE, UINT32)
EFI_CLOSE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), EFI_HANDLE, EFI_HANDLE)
EFI_OPEN_PROTOCOL_INFORMATION = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)), PTR(UINTN))
EFI_PROTOCOLS_PER_HANDLE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(PTR(PTR(EFI_GUID))), PTR(UINTN))
EFI_LOCATE_HANDLE_BUFFER = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(PTR(EFI_HANDLE)))
EFI_LOCATE_PROTOCOL = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE)) # ...
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, EFI_HANDLE) # ...
EFI_CALCULATE_CRC32 = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(UINT32))
EFI_COPY_MEM = FUNCPTR(VOID, PTR(VOID), PTR(VOID), UINTN)
EFI_SET_MEM = FUNCPTR(VOID, PTR(VOID), UINTN, UINT8)
EFI_CREATE_EVENT_EX = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_GUID), PTR(EFI_EVENT))
EFI_RAISE_TPL = FUNCPTR(EFI_TPL, EFI_TPL)
EFI_RESTORE_TPL = FUNCPTR(VOID, EFI_TPL)
EFI_ALLOCATE_PAGES = FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))
EFI_FREE_PAGES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)
EFI_GET_MEMORY_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(EFI_MEMORY_DESCRIPTOR), PTR(UINTN), PTR(UINTN), PTR(UINT32))
EFI_ALLOCATE_POOL = FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))
EFI_FREE_POOL = FUNCPTR(EFI_STATUS, PTR(VOID))
EFI_CREATE_EVENT = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_EVENT))
EFI_SET_TIMER = FUNCPTR(EFI_STATUS, EFI_EVENT, EFI_TIMER_DELAY, UINT64)
EFI_WAIT_FOR_EVENT = FUNCPTR(EFI_STATUS, UINTN, PTR(EFI_EVENT), PTR(UINTN))
EFI_SIGNAL_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_CLOSE_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_CHECK_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT)
EFI_INSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))
EFI_REINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID), PTR(VOID))
EFI_UNINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID))
EFI_HANDLE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)))
EFI_REGISTER_PROTOCOL_NOTIFY = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_EVENT, PTR(PTR(VOID)))
EFI_LOCATE_HANDLE = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))
EFI_LOCATE_DEVICE_PATH = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)), PTR(EFI_HANDLE))
EFI_INSTALL_CONFIGURATION_TABLE = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID))
EFI_IMAGE_LOAD = FUNCPTR(EFI_STATUS, BOOLEAN, EFI_HANDLE, PTR(EFI_DEVICE_PATH_PROTOCOL), PTR(VOID) , UINTN, PTR(EFI_HANDLE))
EFI_IMAGE_START = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(UINTN), PTR(PTR(CHAR16)))
EFI_EXIT = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_STATUS, UINTN, PTR(CHAR16))
EFI_IMAGE_UNLOAD = FUNCPTR(EFI_STATUS, EFI_HANDLE)
EFI_EXIT_BOOT_SERVICES = FUNCPTR(EFI_STATUS, EFI_HANDLE, UINTN)
EFI_GET_NEXT_MONOTONIC_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT64))
EFI_STALL = FUNCPTR(EFI_STATUS, UINTN)
EFI_SET_WATCHDOG_TIMER = FUNCPTR(EFI_STATUS, UINTN, UINT64, UINTN, PTR(CHAR16))
EFI_CONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_HANDLE), PTR(EFI_DEVICE_PATH_PROTOCOL), BOOLEAN)
EFI_DISCONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_HANDLE, EFI_HANDLE)
EFI_OPEN_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)), EFI_HANDLE, EFI_HANDLE, UINT32)
EFI_CLOSE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), EFI_HANDLE, EFI_HANDLE)
EFI_OPEN_PROTOCOL_INFORMATION = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)), PTR(UINTN))
EFI_PROTOCOLS_PER_HANDLE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(PTR(PTR(EFI_GUID))), PTR(UINTN))
EFI_LOCATE_HANDLE_BUFFER = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(PTR(EFI_HANDLE)))
EFI_LOCATE_PROTOCOL = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE)) # ...
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, EFI_HANDLE) # ...
EFI_CALCULATE_CRC32 = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(UINT32))
EFI_COPY_MEM = FUNCPTR(VOID, PTR(VOID), PTR(VOID), UINTN)
EFI_SET_MEM = FUNCPTR(VOID, PTR(VOID), UINTN, UINT8)
EFI_CREATE_EVENT_EX = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_GUID), PTR(EFI_EVENT))
class EFI_BOOT_SERVICES(STRUCT):
_fields_ = [
('Hdr', EFI_TABLE_HEADER),
('RaiseTPL', EFI_RAISE_TPL),
('RestoreTPL', EFI_RESTORE_TPL),
('AllocatePages', EFI_ALLOCATE_PAGES),
('FreePages', EFI_FREE_PAGES),
('GetMemoryMap', EFI_GET_MEMORY_MAP),
('AllocatePool', EFI_ALLOCATE_POOL),
('FreePool', EFI_FREE_POOL),
('CreateEvent', EFI_CREATE_EVENT),
('SetTimer', EFI_SET_TIMER),
('WaitForEvent', EFI_WAIT_FOR_EVENT),
('SignalEvent', EFI_SIGNAL_EVENT),
('CloseEvent', EFI_CLOSE_EVENT),
('CheckEvent', EFI_CHECK_EVENT),
('InstallProtocolInterface', EFI_INSTALL_PROTOCOL_INTERFACE),
('ReinstallProtocolInterface', EFI_REINSTALL_PROTOCOL_INTERFACE),
('UninstallProtocolInterface', EFI_UNINSTALL_PROTOCOL_INTERFACE),
('HandleProtocol', EFI_HANDLE_PROTOCOL),
('Reserved', PTR(VOID)),
('RegisterProtocolNotify', EFI_REGISTER_PROTOCOL_NOTIFY),
('LocateHandle', EFI_LOCATE_HANDLE),
('LocateDevicePath', EFI_LOCATE_DEVICE_PATH),
('InstallConfigurationTable', EFI_INSTALL_CONFIGURATION_TABLE),
('LoadImage', EFI_IMAGE_LOAD),
('StartImage', EFI_IMAGE_START),
('Exit', EFI_EXIT),
('UnloadImage', EFI_IMAGE_UNLOAD),
('ExitBootServices', EFI_EXIT_BOOT_SERVICES),
('GetNextMonotonicCount', EFI_GET_NEXT_MONOTONIC_COUNT),
('Stall', EFI_STALL),
('SetWatchdogTimer', EFI_SET_WATCHDOG_TIMER),
('ConnectController', EFI_CONNECT_CONTROLLER),
('DisconnectController', EFI_DISCONNECT_CONTROLLER),
('OpenProtocol', EFI_OPEN_PROTOCOL),
('CloseProtocol', EFI_CLOSE_PROTOCOL),
('OpenProtocolInformation', EFI_OPEN_PROTOCOL_INFORMATION),
('ProtocolsPerHandle', EFI_PROTOCOLS_PER_HANDLE),
('LocateHandleBuffer', EFI_LOCATE_HANDLE_BUFFER),
('LocateProtocol', EFI_LOCATE_PROTOCOL),
('InstallMultipleProtocolInterfaces', EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES),
('UninstallMultipleProtocolInterfaces', EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES),
('CalculateCrc32', EFI_CALCULATE_CRC32),
('CopyMem', EFI_COPY_MEM),
('SetMem', EFI_SET_MEM),
('CreateEventEx', EFI_CREATE_EVENT_EX)
('Hdr', EFI_TABLE_HEADER),
('RaiseTPL', EFI_RAISE_TPL),
('RestoreTPL', EFI_RESTORE_TPL),
('AllocatePages', EFI_ALLOCATE_PAGES),
('FreePages', EFI_FREE_PAGES),
('GetMemoryMap', EFI_GET_MEMORY_MAP),
('AllocatePool', EFI_ALLOCATE_POOL),
('FreePool', EFI_FREE_POOL),
('CreateEvent', EFI_CREATE_EVENT),
('SetTimer', EFI_SET_TIMER),
('WaitForEvent', EFI_WAIT_FOR_EVENT),
('SignalEvent', EFI_SIGNAL_EVENT),
('CloseEvent', EFI_CLOSE_EVENT),
('CheckEvent', EFI_CHECK_EVENT),
('InstallProtocolInterface', EFI_INSTALL_PROTOCOL_INTERFACE),
('ReinstallProtocolInterface', EFI_REINSTALL_PROTOCOL_INTERFACE),
('UninstallProtocolInterface', EFI_UNINSTALL_PROTOCOL_INTERFACE),
('HandleProtocol', EFI_HANDLE_PROTOCOL),
('Reserved', PTR(VOID)),
('RegisterProtocolNotify', EFI_REGISTER_PROTOCOL_NOTIFY),
('LocateHandle', EFI_LOCATE_HANDLE),
('LocateDevicePath', EFI_LOCATE_DEVICE_PATH),
('InstallConfigurationTable', EFI_INSTALL_CONFIGURATION_TABLE),
('LoadImage', EFI_IMAGE_LOAD),
('StartImage', EFI_IMAGE_START),
('Exit', EFI_EXIT),
('UnloadImage', EFI_IMAGE_UNLOAD),
('ExitBootServices', EFI_EXIT_BOOT_SERVICES),
('GetNextMonotonicCount', EFI_GET_NEXT_MONOTONIC_COUNT),
('Stall', EFI_STALL),
('SetWatchdogTimer', EFI_SET_WATCHDOG_TIMER),
('ConnectController', EFI_CONNECT_CONTROLLER),
('DisconnectController', EFI_DISCONNECT_CONTROLLER),
('OpenProtocol', EFI_OPEN_PROTOCOL),
('CloseProtocol', EFI_CLOSE_PROTOCOL),
('OpenProtocolInformation', EFI_OPEN_PROTOCOL_INFORMATION),
('ProtocolsPerHandle', EFI_PROTOCOLS_PER_HANDLE),
('LocateHandleBuffer', EFI_LOCATE_HANDLE_BUFFER),
('LocateProtocol', EFI_LOCATE_PROTOCOL),
('InstallMultipleProtocolInterfaces', EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES),
('UninstallMultipleProtocolInterfaces', EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES),
('CalculateCrc32', EFI_CALCULATE_CRC32),
('CopyMem', EFI_COPY_MEM),
('SetMem', EFI_SET_MEM),
('CreateEventEx', EFI_CREATE_EVENT_EX)
]
class EFI_CONFIGURATION_TABLE(STRUCT):
@@ -235,19 +235,19 @@ class EFI_SYSTEM_TABLE(STRUCT):
_pack_ = 8
_fields_ = [
('Hdr', EFI_TABLE_HEADER),
('FirmwareVendor', PTR(CHAR16)),
('FirmwareRevision', UINT32),
('ConsoleInHandle', EFI_HANDLE),
('ConIn', PTR(EFI_SIMPLE_TEXT_INPUT_PROTOCOL)),
('ConsoleOutHandle', EFI_HANDLE),
('ConOut', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)),
('StandardErrorHandle', EFI_HANDLE),
('StdErr', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)),
('RuntimeServices', PTR(EFI_RUNTIME_SERVICES)),
('BootServices', PTR(EFI_BOOT_SERVICES)),
('NumberOfTableEntries', UINTN),
('ConfigurationTable', PTR(EFI_CONFIGURATION_TABLE))
('Hdr', EFI_TABLE_HEADER),
('FirmwareVendor', PTR(CHAR16)),
('FirmwareRevision', UINT32),
('ConsoleInHandle', EFI_HANDLE),
('ConIn', PTR(EFI_SIMPLE_TEXT_INPUT_PROTOCOL)),
('ConsoleOutHandle', EFI_HANDLE),
('ConOut', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)),
('StandardErrorHandle', EFI_HANDLE),
('StdErr', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)),
('RuntimeServices', PTR(EFI_RUNTIME_SERVICES)),
('BootServices', PTR(EFI_BOOT_SERVICES)),
('NumberOfTableEntries', UINTN),
('ConfigurationTable', PTR(EFI_CONFIGURATION_TABLE))
]
__all__ = [
+5 -3
View File
@@ -1,13 +1,15 @@
import csv
from typing import Mapping
import inspect
from typing import Dict
from pathlib import Path
def __init_guids_db() -> Mapping[str, str]:
def __init_guids_db() -> Dict[str, str]:
"""Initialize GUIDs dictionary from a local database.
"""
csv_path = Path(inspect.getfile(inspect.currentframe())).parent / 'guids.csv'
csv_path = Path(inspect.getfile(__init_guids_db)).parent / 'guids.csv'
with csv_path.open('r') as guids_file:
guids_reader = csv.reader(guids_file)
+206 -201
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
from typing import TYPE_CHECKING
from binascii import crc32
from qiling.const import QL_ENDIAN
from qiling.os.const import *
from qiling.os.uefi import guids_db
from qiling.os.uefi.const import *
@@ -15,8 +16,12 @@ from qiling.os.uefi.ProcessorBind import *
from qiling.os.uefi.UefiSpec import *
from qiling.os.uefi.protocols import common
if TYPE_CHECKING:
from qiling import Qiling
@dxeapi(params = {
"NewTpl" : ULONGLONG # EFI_TPL
"NewTpl": ULONGLONG # EFI_TPL
})
def hook_RaiseTPL(ql: Qiling, address: int, params):
prev_tpl = ql.loader.tpl
@@ -25,22 +30,22 @@ def hook_RaiseTPL(ql: Qiling, address: int, params):
return prev_tpl
@dxeapi(params = {
"OldTpl": ULONGLONG # EFI_TPL
"OldTpl": ULONGLONG # EFI_TPL
})
def hook_RestoreTPL(ql: Qiling, address: int, params):
ql.loader.tpl = params["OldTpl"]
@dxeapi(params = {
"type" : INT, # EFI_ALLOCATE_TYPE
"MemoryType": INT, # EFI_MEMORY_TYPE
"Pages" : ULONGLONG, # UINTN
"Memory" : POINTER # PTR(EFI_PHYSICAL_ADDRESS)
"type": INT, # EFI_ALLOCATE_TYPE
"MemoryType": INT, # EFI_MEMORY_TYPE
"Pages": ULONGLONG, # UINTN
"Memory": POINTER # PTR(EFI_PHYSICAL_ADDRESS)
})
def hook_AllocatePages(ql: Qiling, address: int, params):
alloc_size = params["Pages"] * PAGE_SIZE
if params['type'] == EFI_ALLOCATE_TYPE.AllocateAddress:
address = read_int64(ql, params["Memory"])
address = ql.mem.read_ptr(params["Memory"])
# TODO: check the range [address, address + alloc_size] is available first
ql.mem.map(address, alloc_size)
@@ -51,13 +56,13 @@ def hook_AllocatePages(ql: Qiling, address: int, params):
if address == 0:
return EFI_OUT_OF_RESOURCES
write_int64(ql, params["Memory"], address)
ql.mem.write_ptr(params["Memory"], address)
return EFI_SUCCESS
@dxeapi(params = {
"Memory" : ULONGLONG, # EFI_PHYSICAL_ADDRESS
"Pages" : ULONGLONG # UINTN
"Memory": ULONGLONG, # EFI_PHYSICAL_ADDRESS
"Pages": ULONGLONG # UINTN
})
def hook_FreePages(ql: Qiling, address: int, params):
address = params["Memory"]
@@ -67,19 +72,19 @@ def hook_FreePages(ql: Qiling, address: int, params):
return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER
@dxeapi(params = {
"MemoryMapSize" : POINTER, # PTR(UINTN)
"MemoryMap" : POINTER, # PTR(EFI_MEMORY_DESCRIPTOR)
"MapKey" : POINTER, # PTR(UINTN)
"DescriptorSize" : POINTER, # PTR(UINTN)
"DescriptorVersion" : POINTER # PTR(UINT32)
"MemoryMapSize": POINTER, # PTR(UINTN)
"MemoryMap": POINTER, # PTR(EFI_MEMORY_DESCRIPTOR)
"MapKey": POINTER, # PTR(UINTN)
"DescriptorSize": POINTER, # PTR(UINTN)
"DescriptorVersion": POINTER # PTR(UINT32)
})
def hook_GetMemoryMap(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"PoolType" : INT, # EFI_MEMORY_TYPE
"Size" : INT, # UINTN
"Buffer" : POINTER # PTR(PTR(VOID))
"PoolType": INT, # EFI_MEMORY_TYPE
"Size": INT, # UINTN
"Buffer": POINTER # PTR(PTR(VOID))
})
def hook_AllocatePool(ql: Qiling, address: int, params):
# TODO: allocate memory acording to "PoolType"
@@ -87,12 +92,12 @@ def hook_AllocatePool(ql: Qiling, address: int, params):
Buffer = params["Buffer"]
address = ql.loader.dxe_context.heap.alloc(Size)
write_int64(ql, Buffer, address)
ql.mem.write_ptr(Buffer, address)
return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES
@dxeapi(params = {
"Buffer": POINTER # PTR(VOID)
"Buffer": POINTER # PTR(VOID)
})
def hook_FreePool(ql: Qiling, address: int, params):
Buffer = params["Buffer"]
@@ -102,33 +107,33 @@ def hook_FreePool(ql: Qiling, address: int, params):
return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER
@dxeapi(params = {
"Type" : UINT, # UINT32
"NotifyTpl" : UINT, # EFI_TPL
"NotifyFunction": POINTER, # EFI_EVENT_NOTIFY
"NotifyContext" : POINTER, # PTR(VOID)
"Event" : POINTER # PTR(EFI_EVENT)
"Type": UINT, # UINT32
"NotifyTpl": UINT, # EFI_TPL
"NotifyFunction": POINTER, # EFI_EVENT_NOTIFY
"NotifyContext": POINTER, # PTR(VOID)
"Event": POINTER # PTR(EFI_EVENT)
})
def hook_CreateEvent(ql: Qiling, address: int, params):
return CreateEvent(ql, params)
@dxeapi(params = {
"Event" : POINTER, # EFI_EVENT
"Type" : ULONGLONG, # EFI_TIMER_DELAY
"TriggerTime" : ULONGLONG # UINT64
"Event": POINTER, # EFI_EVENT
"Type": ULONGLONG, # EFI_TIMER_DELAY
"TriggerTime": ULONGLONG # UINT64
})
def hook_SetTimer(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"NumberOfEvents": ULONGLONG, # UINTN
"Event" : POINTER, # PTR(EFI_EVENT)
"Index" : POINTER, # PTR(UINTN)
"Event": POINTER, # PTR(EFI_EVENT)
"Index": POINTER, # PTR(UINTN)
})
def hook_WaitForEvent(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Event": POINTER # EFI_EVENT
"Event": POINTER # EFI_EVENT
})
def hook_SignalEvent(ql: Qiling, address: int, params):
event_id = params["Event"]
@@ -141,7 +146,7 @@ def hook_SignalEvent(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Event": POINTER # EFI_EVENT
"Event": POINTER # EFI_EVENT
})
def hook_CloseEvent(ql: Qiling, address: int, params):
event_id = params["Event"]
@@ -154,7 +159,7 @@ def hook_CloseEvent(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Event": POINTER # EFI_EVENT
"Event": POINTER # EFI_EVENT
})
def hook_CheckEvent(ql: Qiling, address: int, params):
event_id = params["Event"]
@@ -162,19 +167,19 @@ def hook_CheckEvent(ql: Qiling, address: int, params):
return EFI_SUCCESS if ql.loader.events[event_id]["Set"] else EFI_NOT_READY
@dxeapi(params = {
"Handle" : POINTER, # PTR(EFI_HANDLE)
"Protocol" : GUID, # PTR(EFI_GUID)
"InterfaceType" : ULONGLONG, # EFI_INTERFACE_TYPE
"Interface" : POINTER, # PTR(VOID)
"Handle": POINTER, # PTR(EFI_HANDLE)
"Protocol": GUID, # PTR(EFI_GUID)
"InterfaceType": ULONGLONG, # EFI_INTERFACE_TYPE
"Interface": POINTER, # PTR(VOID)
})
def hook_InstallProtocolInterface(ql: Qiling, address: int, params):
return common.InstallProtocolInterface(ql.loader.dxe_context, params)
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"OldInterface" : POINTER, # PTR(VOID)
"NewInterface" : POINTER # PTR(VOID)
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"OldInterface": POINTER, # PTR(VOID)
"NewInterface": POINTER # PTR(VOID)
})
def hook_ReinstallProtocolInterface(ql: Qiling, address: int, params):
handle = params["Handle"]
@@ -193,25 +198,25 @@ def hook_ReinstallProtocolInterface(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"Interface" : POINTER # PTR(VOID)
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"Interface": POINTER # PTR(VOID)
})
def hook_UninstallProtocolInterface(ql: Qiling, address: int, params):
return common.UninstallProtocolInterface(ql.loader.dxe_context, params)
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"Interface" : POINTER # PTR(PTR(VOID))
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"Interface": POINTER # PTR(PTR(VOID))
})
def hook_HandleProtocol(ql: Qiling, address: int, params):
return common.HandleProtocol(ql.loader.dxe_context, params)
@dxeapi(params = {
"Protocol" : GUID, # PTR(EFI_GUID)
"Event" : POINTER, # EFI_EVENT
"Registration" : POINTER # PTR(PTR(VOID))
"Protocol": GUID, # PTR(EFI_GUID)
"Event": POINTER, # EFI_EVENT
"Registration": POINTER # PTR(PTR(VOID))
})
def hook_RegisterProtocolNotify(ql: Qiling, address: int, params):
event = params['Event']
@@ -225,54 +230,54 @@ def hook_RegisterProtocolNotify(ql: Qiling, address: int, params):
return EFI_INVALID_PARAMETER
@dxeapi(params = {
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol" : GUID, # PTR(EFI_GUID)
"SearchKey" : POINTER, # PTR(VOID)
"BufferSize": POINTER, # PTR(UINTN)
"Buffer" : POINTER # PTR(EFI_HANDLE)
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol": GUID, # PTR(EFI_GUID)
"SearchKey": POINTER, # PTR(VOID)
"BufferSize": POINTER, # PTR(UINTN)
"Buffer": POINTER # PTR(EFI_HANDLE)
})
def hook_LocateHandle(ql: Qiling, address: int, params):
return common.LocateHandle(ql.loader.dxe_context, params)
@dxeapi(params = {
"Protocol" : GUID, # PTR(EFI_GUID)
"DevicePath": POINTER, # PTR(PTR(EFI_DEVICE_PATH_PROTOCOL))
"Device" : POINTER # PTR(EFI_HANDLE)
"Protocol": GUID, # PTR(EFI_GUID)
"DevicePath": POINTER, # PTR(PTR(EFI_DEVICE_PATH_PROTOCOL))
"Device": POINTER # PTR(EFI_HANDLE)
})
def hook_LocateDevicePath(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Guid" : GUID, # PTR(EFI_GUID)
"Table" : POINTER # PTR(VOID)
"Guid": GUID, # PTR(EFI_GUID)
"Table": POINTER # PTR(VOID)
})
def hook_InstallConfigurationTable(ql: Qiling, address: int, params):
return common.InstallConfigurationTable(ql.loader.dxe_context, params)
@dxeapi(params = {
"BootPolicy" : BOOL, # BOOLEAN
"ParentImageHandle" : POINTER, # EFI_HANDLE
"DevicePath" : POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL)
"SourceBuffer" : POINTER, # PTR(VOID)
"SourceSize" : ULONGLONG, # UINTN
"ImageHandle" : POINTER # PTR(EFI_HANDLE)
"BootPolicy": BOOL, # BOOLEAN
"ParentImageHandle": POINTER, # EFI_HANDLE
"DevicePath": POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL)
"SourceBuffer": POINTER, # PTR(VOID)
"SourceSize": ULONGLONG, # UINTN
"ImageHandle": POINTER # PTR(EFI_HANDLE)
})
def hook_LoadImage(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ImageHandle" : POINTER, # EFI_HANDLE
"ExitDataSize" : POINTER, # PTR(UINTN)
"ExitData" : POINTER # PTR(PTR(CHAR16))
"ImageHandle": POINTER, # EFI_HANDLE
"ExitDataSize": POINTER, # PTR(UINTN)
"ExitData": POINTER # PTR(PTR(CHAR16))
})
def hook_StartImage(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ImageHandle" : POINTER, # EFI_HANDLE
"ExitStatus" : ULONGLONG, # EFI_STATUS
"ExitDataSize" : ULONGLONG, # UINTN
"ExitData" : POINTER # PTR(CHAR16)
"ImageHandle": POINTER, # EFI_HANDLE
"ExitStatus": ULONGLONG, # EFI_STATUS
"ExitDataSize": ULONGLONG, # UINTN
"ExitData": POINTER # PTR(CHAR16)
})
def hook_Exit(ql: Qiling, address: int, params):
ql.emu_stop()
@@ -280,143 +285,143 @@ def hook_Exit(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ImageHandle" : POINTER # EFI_HANDLE
"ImageHandle": POINTER # EFI_HANDLE
})
def hook_UnloadImage(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ImageHandle" : POINTER, # EFI_HANDLE
"MapKey" : ULONGLONG # UINTN
"ImageHandle": POINTER, # EFI_HANDLE
"MapKey": ULONGLONG # UINTN
})
def hook_ExitBootServices(ql: Qiling, address: int, params):
ql.emu_stop()
# TODO: cleanup BS tableas and data, and notify signal list gEfiEventExitBootServicesGuid
# TODO: cleanup BS tables and data, and notify signal list gEfiEventExitBootServicesGuid
# @see: MdeModulePkg\Core\Dxe\DxeMain\DxeMain.c, CoreExitBootServices
return EFI_SUCCESS
@dxeapi(params = {
"Count": POINTER # PTR(UINT64)
"Count": POINTER # PTR(UINT64)
})
def hook_GetNextMonotonicCount(ql: Qiling, address: int, params):
out = params["Count"]
ql.os.monotonic_count += 1
write_int64(ql, out, ql.os.monotonic_count)
ql.mem.write_ptr(out, ql.os.monotonic_count, 8)
return EFI_SUCCESS
@dxeapi(params = {
"Microseconds": ULONGLONG # UINTN
"Microseconds": ULONGLONG # UINTN
})
def hook_Stall(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Timeout" : ULONGLONG, # UINTN
"WatchdogCode" : ULONGLONG, # UINT64
"DataSize" : ULONGLONG, # UINTN
"WatchdogData" : POINTER # PTR(CHAR16)
"Timeout": ULONGLONG, # UINTN
"WatchdogCode": ULONGLONG, # UINT64
"DataSize": ULONGLONG, # UINTN
"WatchdogData": POINTER # PTR(CHAR16)
})
def hook_SetWatchdogTimer(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ControllerHandle" : POINTER, # EFI_HANDLE
"DriverImageHandle" : POINTER, #PTR(EFI_HANDLE)
"RemainingDevicePath" : POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL)
"Recursive" : BOOL # BOOLEAN
"ControllerHandle": POINTER, # EFI_HANDLE
"DriverImageHandle": POINTER, #PTR(EFI_HANDLE)
"RemainingDevicePath": POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL)
"Recursive": BOOL # BOOLEAN
})
def hook_ConnectController(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"ControllerHandle" : POINTER, # EFI_HANDLE
"DriverImageHandle" : POINTER, # EFI_HANDLE
"ChildHandle" : POINTER # EFI_HANDLE
"ControllerHandle": POINTER, # EFI_HANDLE
"DriverImageHandle": POINTER, # EFI_HANDLE
"ChildHandle": POINTER # EFI_HANDLE
})
def hook_DisconnectController(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"Interface" : POINTER, # PTR(PTR(VOID))
"AgentHandle" : POINTER, # EFI_HANDLE
"ControllerHandle" : POINTER, # EFI_HANDLE
"Attributes" : UINT # UINT32
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"Interface": POINTER, # PTR(PTR(VOID))
"AgentHandle": POINTER, # EFI_HANDLE
"ControllerHandle": POINTER, # EFI_HANDLE
"Attributes": UINT # UINT32
})
def hook_OpenProtocol(ql: Qiling, address: int, params):
return common.LocateProtocol(ql.loader.dxe_context, params)
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"AgentHandle" : POINTER, # EFI_HANDLE
"ControllerHandle" : POINTER # EFI_HANDLE
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"AgentHandle": POINTER, # EFI_HANDLE
"ControllerHandle": POINTER # EFI_HANDLE
})
def hook_CloseProtocol(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"EntryBuffer" : POINTER, # PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY))
"EntryCount" : POINTER # PTR(UINTN)
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"EntryBuffer": POINTER, # PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY))
"EntryCount": POINTER # PTR(UINTN)
})
def hook_OpenProtocolInformation(ql: Qiling, address: int, params):
return EFI_NOT_FOUND
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"ProtocolBuffer" : POINTER, # PTR(PTR(PTR(EFI_GUID)))
"ProtocolBufferCount" : POINTER # PTR(UINTN)
"Handle": POINTER, # EFI_HANDLE
"ProtocolBuffer": POINTER, # PTR(PTR(PTR(EFI_GUID)))
"ProtocolBufferCount": POINTER # PTR(UINTN)
})
def hook_ProtocolsPerHandle(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol" : GUID, # PTR(EFI_GUID)
"SearchKey" : POINTER, # PTR(VOID)
"NoHandles" : POINTER, # PTR(UINTN)
"Buffer" : POINTER # PTR(PTR(EFI_HANDLE))
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol": GUID, # PTR(EFI_GUID)
"SearchKey": POINTER, # PTR(VOID)
"NoHandles": POINTER, # PTR(UINTN)
"Buffer": POINTER # PTR(PTR(EFI_HANDLE))
})
def hook_LocateHandleBuffer(ql: Qiling, address: int, params):
buffer_size, handles = common.LocateHandles(ql.loader.dxe_context, params)
write_int64(ql, params["NoHandles"], len(handles))
ql.mem.write_ptr(params["NoHandles"], len(handles))
if len(handles) == 0:
return EFI_NOT_FOUND
address = ql.loader.dxe_context.heap.alloc(buffer_size)
write_int64(ql, params["Buffer"], address)
ql.mem.write_ptr(params["Buffer"], address)
if address == 0:
return EFI_OUT_OF_RESOURCES
for handle in handles:
write_int64(ql, address, handle)
ql.mem.write_ptr(address, handle)
address += ql.arch.pointersize
return EFI_SUCCESS
@dxeapi(params = {
"Protocol" : GUID, # PTR(EFI_GUID)
"Registration" : POINTER, # PTR(VOID)
"Interface" : POINTER # PTR(PTR(VOID))
"Protocol": GUID, # PTR(EFI_GUID)
"Registration": POINTER, # PTR(VOID)
"Interface": POINTER # PTR(PTR(VOID))
})
def hook_LocateProtocol(ql: Qiling, address: int, params):
return common.LocateProtocol(ql.loader.dxe_context, params)
@dxeapi(params = {
"Handle" : POINTER # PTR(EFI_HANDLE)
"Handle": POINTER # PTR(EFI_HANDLE)
# ...
})
def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params):
handle = read_int64(ql, params["Handle"])
handle = ql.mem.read_ptr(params["Handle"])
if handle == 0:
handle = ql.loader.dxe_context.heap.alloc(ql.arch.pointersize)
@@ -426,23 +431,23 @@ def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params):
# process elipsiss arguments
index = 1
while ql.os.fcall.cc.getRawParam(index) != 0:
GUID_ptr = ql.os.fcall.cc.getRawParam(index)
guid_ptr = ql.os.fcall.cc.getRawParam(index)
protocol_ptr = ql.os.fcall.cc.getRawParam(index + 1)
GUID = str(ql.os.utils.read_guid(GUID_ptr))
dic[GUID] = protocol_ptr
guid = str(ql.os.utils.read_guid(guid_ptr))
dic[guid] = protocol_ptr
ql.log.info(f'Installing protocol interface {guids_db.get(GUID.upper(), GUID)} to {protocol_ptr:#x}')
ql.log.info(f'Installing protocol interface {guids_db.get(guid.upper(), guid)} to {protocol_ptr:#x}')
index += 2
ql.loader.dxe_context.protocols[handle] = dic
execute_protocol_notifications(ql, True)
write_int64(ql, params["Handle"], handle)
ql.mem.write_ptr(params["Handle"], handle)
return EFI_SUCCESS
@dxeapi(params = {
"Handle" : POINTER # EFI_HANDLE
"Handle": POINTER # EFI_HANDLE
# ...
})
def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params):
@@ -459,33 +464,33 @@ def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params):
GUID_ptr = ql.os.fcall.cc.getRawParam(index)
protocol_ptr = ql.os.fcall.cc.getRawParam(index + 1)
GUID = str(ql.os.utils.read_guid(GUID_ptr))
guid = str(ql.os.utils.read_guid(GUID_ptr))
if GUID not in dic:
if guid not in dic:
return EFI_INVALID_PARAMETER
del dic[GUID]
del dic[guid]
ql.log.info(f'Uninstalling protocol interface {guids_db.get(GUID.upper(), GUID)} from {protocol_ptr:#x}')
ql.log.info(f'Uninstalling protocol interface {guids_db.get(guid.upper(), guid)} from {protocol_ptr:#x}')
index += 2
return EFI_SUCCESS
@dxeapi(params = {
"Data" : POINTER, # PTR(VOID)
"DataSize" : ULONGLONG, # UINTN
"Crc32" : POINTER # PTR(UINT32)
"Data": POINTER, # PTR(VOID)
"DataSize": ULONGLONG, # UINTN
"Crc32": POINTER # PTR(UINT32)
})
def hook_CalculateCrc32(ql: Qiling, address: int, params):
data = bytes(ql.mem.read(params['Data'], params['DataSize']))
write_int32(ql, params['Crc32'], crc32(data))
data = ql.mem.read(params['Data'], params['DataSize'])
ql.mem.write_ptr(params['Crc32'], crc32(data), 4)
return EFI_SUCCESS
@dxeapi(params = {
"Destination" : POINTER, # PTR(VOID)
"Source" : POINTER, # PTR(VOID)
"Length" : SIZE_T # UINTN
"Destination": POINTER, # PTR(VOID)
"Source": POINTER, # PTR(VOID)
"Length": SIZE_T # UINTN
})
def hook_CopyMem(ql: Qiling, address: int, params):
dst = params["Destination"]
@@ -495,9 +500,9 @@ def hook_CopyMem(ql: Qiling, address: int, params):
ql.mem.write(dst, bytes(ql.mem.read(src, length)))
@dxeapi(params = {
"Buffer": POINTER, # PTR(VOID)
"Size" : SIZE_T, # UINTN
"Value" : BYTE # UINT8
"Buffer": POINTER, # PTR(VOID)
"Size": SIZE_T, # UINTN
"Value": BYTE # UINT8
})
def hook_SetMem(ql: Qiling, address: int, params):
buffer = params["Buffer"]
@@ -507,12 +512,12 @@ def hook_SetMem(ql: Qiling, address: int, params):
ql.mem.write(buffer, bytes([value]) * size)
@dxeapi(params = {
"Type" : UINT, # UINT32
"NotifyTpl" : ULONGLONG,# EFI_TPL
"NotifyFunction": POINTER, # EFI_EVENT_NOTIFY
"NotifyContext" : POINTER, # PTR(VOID)
"EventGroup" : GUID, # PTR(EFI_GUID)
"Event" : POINTER # PTR(EFI_EVENT)
"Type": UINT, # UINT32
"NotifyTpl": ULONGLONG, # EFI_TPL
"NotifyFunction": POINTER, # EFI_EVENT_NOTIFY
"NotifyContext": POINTER, # PTR(VOID)
"EventGroup": GUID, # PTR(EFI_GUID)
"Event": POINTER # PTR(EFI_EVENT)
})
def hook_CreateEventEx(ql: Qiling, address: int, params):
return CreateEvent(ql, params)
@@ -521,16 +526,16 @@ def CreateEvent(ql: Qiling, params):
event_id = len(ql.loader.events)
event_dic = {
"NotifyFunction": params["NotifyFunction"],
"CallbackArgs" : [event_id, params["NotifyContext"]],
"Guid" : "",
"Set" : False
"CallbackArgs": [event_id, params["NotifyContext"]],
"Guid": "",
"Set": False
}
if "EventGroup" in params:
event_dic["EventGroup"] = params["EventGroup"]
ql.loader.events[event_id] = event_dic
write_int64(ql, params["Event"], event_id)
ql.mem.write_ptr(params["Event"], event_id)
return EFI_SUCCESS
@@ -538,59 +543,59 @@ def initialize(ql: Qiling, gBS: int):
descriptor = {
'struct' : EFI_BOOT_SERVICES,
'fields' : (
('Hdr', None),
('RaiseTPL', hook_RaiseTPL),
('RestoreTPL', hook_RestoreTPL),
('AllocatePages', hook_AllocatePages),
('FreePages', hook_FreePages),
('GetMemoryMap', hook_GetMemoryMap),
('AllocatePool', hook_AllocatePool),
('FreePool', hook_FreePool),
('CreateEvent', hook_CreateEvent),
('SetTimer', hook_SetTimer),
('WaitForEvent', hook_WaitForEvent),
('SignalEvent', hook_SignalEvent),
('CloseEvent', hook_CloseEvent),
('CheckEvent', hook_CheckEvent),
('InstallProtocolInterface', hook_InstallProtocolInterface),
('ReinstallProtocolInterface', hook_ReinstallProtocolInterface),
('UninstallProtocolInterface', hook_UninstallProtocolInterface),
('HandleProtocol', hook_HandleProtocol),
('Reserved', None),
('RegisterProtocolNotify', hook_RegisterProtocolNotify),
('LocateHandle', hook_LocateHandle),
('LocateDevicePath', hook_LocateDevicePath),
('InstallConfigurationTable', hook_InstallConfigurationTable),
('LoadImage', hook_LoadImage),
('StartImage', hook_StartImage),
('Exit', hook_Exit),
('UnloadImage', hook_UnloadImage),
('ExitBootServices', hook_ExitBootServices),
('GetNextMonotonicCount', hook_GetNextMonotonicCount),
('Stall', hook_Stall),
('SetWatchdogTimer', hook_SetWatchdogTimer),
('ConnectController', hook_ConnectController),
('DisconnectController', hook_DisconnectController),
('OpenProtocol', hook_OpenProtocol),
('CloseProtocol', hook_CloseProtocol),
('OpenProtocolInformation', hook_OpenProtocolInformation),
('ProtocolsPerHandle', hook_ProtocolsPerHandle),
('LocateHandleBuffer', hook_LocateHandleBuffer),
('LocateProtocol', hook_LocateProtocol),
('InstallMultipleProtocolInterfaces', hook_InstallMultipleProtocolInterfaces),
('UninstallMultipleProtocolInterfaces', hook_UninstallMultipleProtocolInterfaces),
('CalculateCrc32', hook_CalculateCrc32),
('CopyMem', hook_CopyMem),
('SetMem', hook_SetMem),
('CreateEventEx', hook_CreateEventEx)
('Hdr', None),
('RaiseTPL', hook_RaiseTPL),
('RestoreTPL', hook_RestoreTPL),
('AllocatePages', hook_AllocatePages),
('FreePages', hook_FreePages),
('GetMemoryMap', hook_GetMemoryMap),
('AllocatePool', hook_AllocatePool),
('FreePool', hook_FreePool),
('CreateEvent', hook_CreateEvent),
('SetTimer', hook_SetTimer),
('WaitForEvent', hook_WaitForEvent),
('SignalEvent', hook_SignalEvent),
('CloseEvent', hook_CloseEvent),
('CheckEvent', hook_CheckEvent),
('InstallProtocolInterface', hook_InstallProtocolInterface),
('ReinstallProtocolInterface', hook_ReinstallProtocolInterface),
('UninstallProtocolInterface', hook_UninstallProtocolInterface),
('HandleProtocol', hook_HandleProtocol),
('Reserved', None),
('RegisterProtocolNotify', hook_RegisterProtocolNotify),
('LocateHandle', hook_LocateHandle),
('LocateDevicePath', hook_LocateDevicePath),
('InstallConfigurationTable', hook_InstallConfigurationTable),
('LoadImage', hook_LoadImage),
('StartImage', hook_StartImage),
('Exit', hook_Exit),
('UnloadImage', hook_UnloadImage),
('ExitBootServices', hook_ExitBootServices),
('GetNextMonotonicCount', hook_GetNextMonotonicCount),
('Stall', hook_Stall),
('SetWatchdogTimer', hook_SetWatchdogTimer),
('ConnectController', hook_ConnectController),
('DisconnectController', hook_DisconnectController),
('OpenProtocol', hook_OpenProtocol),
('CloseProtocol', hook_CloseProtocol),
('OpenProtocolInformation', hook_OpenProtocolInformation),
('ProtocolsPerHandle', hook_ProtocolsPerHandle),
('LocateHandleBuffer', hook_LocateHandleBuffer),
('LocateProtocol', hook_LocateProtocol),
('InstallMultipleProtocolInterfaces', hook_InstallMultipleProtocolInterfaces),
('UninstallMultipleProtocolInterfaces', hook_UninstallMultipleProtocolInterfaces),
('CalculateCrc32', hook_CalculateCrc32),
('CopyMem', hook_CopyMem),
('SetMem', hook_SetMem),
('CreateEventEx', hook_CreateEventEx)
)
}
ql.os.monotonic_count = 0
instance = init_struct(ql, gBS, descriptor)
instance.saveTo(ql, gBS)
instance.save_to(ql.mem, gBS)
__all__ = [
'initialize'
]
]
+37 -36
View File
@@ -1,46 +1,47 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
EFI_MAX_BIT = (1 << 63)
EFI_SUCCESS = 0
EFI_LOAD_ERROR = EFI_MAX_BIT | 1
EFI_INVALID_PARAMETER = EFI_MAX_BIT | 2
EFI_UNSUPPORTED = EFI_MAX_BIT | 3
EFI_BAD_BUFFER_SIZE = EFI_MAX_BIT | 4
EFI_BUFFER_TOO_SMALL = EFI_MAX_BIT | 5
EFI_NOT_READY = EFI_MAX_BIT | 6
EFI_DEVICE_ERROR = EFI_MAX_BIT | 7
EFI_WRITE_PROTECTED = EFI_MAX_BIT | 8
EFI_OUT_OF_RESOURCES = EFI_MAX_BIT | 9
EFI_VOLUME_CORRUPTED = EFI_MAX_BIT | 10
EFI_VOLUME_FULL = EFI_MAX_BIT | 11
EFI_NO_MEDIA = EFI_MAX_BIT | 12
EFI_MEDIA_CHANGED = EFI_MAX_BIT | 13
EFI_NOT_FOUND = EFI_MAX_BIT | 14
EFI_ACCESS_DENIED = EFI_MAX_BIT | 15
EFI_NO_RESPONSE = EFI_MAX_BIT | 16
EFI_NO_MAPPING = EFI_MAX_BIT | 17
EFI_TIMEOUT = EFI_MAX_BIT | 18
EFI_NOT_STARTED = EFI_MAX_BIT | 19
EFI_ALREADY_STARTED = EFI_MAX_BIT | 20
EFI_ABORTED = EFI_MAX_BIT | 21
EFI_ICMP_ERROR = EFI_MAX_BIT | 22
EFI_TFTP_ERROR = EFI_MAX_BIT | 23
EFI_PROTOCOL_ERROR = EFI_MAX_BIT | 24
EFI_INCOMPATIBLE_VERSION = EFI_MAX_BIT | 25
EFI_SECURITY_VIOLATION = EFI_MAX_BIT | 26
EFI_CRC_ERROR = EFI_MAX_BIT | 27
EFI_END_OF_MEDIA = EFI_MAX_BIT | 28
EFI_END_OF_FILE = EFI_MAX_BIT | 31
EFI_INVALID_LANGUAGE = EFI_MAX_BIT | 32
EFI_LOAD_ERROR = EFI_MAX_BIT | 1
EFI_INVALID_PARAMETER = EFI_MAX_BIT | 2
EFI_UNSUPPORTED = EFI_MAX_BIT | 3
EFI_BAD_BUFFER_SIZE = EFI_MAX_BIT | 4
EFI_BUFFER_TOO_SMALL = EFI_MAX_BIT | 5
EFI_NOT_READY = EFI_MAX_BIT | 6
EFI_DEVICE_ERROR = EFI_MAX_BIT | 7
EFI_WRITE_PROTECTED = EFI_MAX_BIT | 8
EFI_OUT_OF_RESOURCES = EFI_MAX_BIT | 9
EFI_VOLUME_CORRUPTED = EFI_MAX_BIT | 10
EFI_VOLUME_FULL = EFI_MAX_BIT | 11
EFI_NO_MEDIA = EFI_MAX_BIT | 12
EFI_MEDIA_CHANGED = EFI_MAX_BIT | 13
EFI_NOT_FOUND = EFI_MAX_BIT | 14
EFI_ACCESS_DENIED = EFI_MAX_BIT | 15
EFI_NO_RESPONSE = EFI_MAX_BIT | 16
EFI_NO_MAPPING = EFI_MAX_BIT | 17
EFI_TIMEOUT = EFI_MAX_BIT | 18
EFI_NOT_STARTED = EFI_MAX_BIT | 19
EFI_ALREADY_STARTED = EFI_MAX_BIT | 20
EFI_ABORTED = EFI_MAX_BIT | 21
EFI_ICMP_ERROR = EFI_MAX_BIT | 22
EFI_TFTP_ERROR = EFI_MAX_BIT | 23
EFI_PROTOCOL_ERROR = EFI_MAX_BIT | 24
EFI_INCOMPATIBLE_VERSION = EFI_MAX_BIT | 25
EFI_SECURITY_VIOLATION = EFI_MAX_BIT | 26
EFI_CRC_ERROR = EFI_MAX_BIT | 27
EFI_END_OF_MEDIA = EFI_MAX_BIT | 28
EFI_END_OF_FILE = EFI_MAX_BIT | 31
EFI_INVALID_LANGUAGE = EFI_MAX_BIT | 32
EFI_WARN_UNKNOWN_GLYPH = EFI_MAX_BIT | 1
EFI_WARN_DELETE_FAILURE = EFI_MAX_BIT | 2
EFI_WARN_WRITE_FAILURE = EFI_MAX_BIT | 3
EFI_WARN_BUFFER_TOO_SMALL = EFI_MAX_BIT | 4
EFI_WARN_UNKNOWN_GLYPH = EFI_MAX_BIT | 1
EFI_WARN_DELETE_FAILURE = EFI_MAX_BIT | 2
EFI_WARN_WRITE_FAILURE = EFI_MAX_BIT | 3
EFI_WARN_BUFFER_TOO_SMALL = EFI_MAX_BIT | 4
# @see: MdePkg\Include\Base.h
EFI_ERROR = lambda status: (status & EFI_MAX_BIT) != 0
def EFI_ERROR(status: int) -> bool:
return (status & EFI_MAX_BIT) != 0
+32 -42
View File
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Any, Mapping, MutableSequence, Optional, Tuple
from typing import Any, Mapping, Dict, MutableSequence, Optional, Tuple, Type
from qiling import Qiling
from qiling.os.memory import QlMemoryHeap
@@ -8,12 +8,13 @@ from qiling.os.uefi.UefiSpec import EFI_CONFIGURATION_TABLE, EFI_SYSTEM_TABLE
from qiling.os.uefi.smst import EFI_SMM_SYSTEM_TABLE2
from qiling.os.uefi import utils
class UefiContext(ABC):
def __init__(self, ql: Qiling):
self.ql = ql
self.heap: QlMemoryHeap
self.top_of_stack: int
self.protocols = {}
self.protocols: Dict[int, Dict[str, int]] = {}
self.loaded_image_protocol_modules: MutableSequence[int] = []
self.next_image_base: int
@@ -39,7 +40,7 @@ class UefiContext(ABC):
self.ql.mem.map(base, size, info='[stack]')
self.top_of_stack = (base + size - 1) & ~(CPU_STACK_ALIGNMENT - 1)
def install_protocol(self, proto_desc: Mapping, handle: int, address: int = None, from_hook: bool = False):
def install_protocol(self, proto_desc: Mapping, handle: int, address: Optional[int] = None, from_hook: bool = False):
guid = proto_desc['guid']
if handle not in self.protocols:
@@ -53,7 +54,7 @@ class UefiContext(ABC):
address = self.heap.alloc(struct_class.sizeof())
instance = utils.init_struct(self.ql, address, proto_desc)
instance.saveTo(self.ql, address)
instance.save_to(self.ql.mem, address)
self.protocols[handle][guid] = address
return self.notify_protocol(handle, guid, address, from_hook)
@@ -61,12 +62,12 @@ class UefiContext(ABC):
def notify_protocol(self, handle: int, protocol: str, interface: int, from_hook: bool):
for (event_id, event_dic) in self.ql.loader.events.items():
if event_dic['Guid'] == protocol:
if event_dic['CallbackArgs'] == None:
# To support smm notification, we use None for CallbackArgs on SmmRegisterProtocolNotify
# and updare it here.
if event_dic['CallbackArgs'] is None:
# To support smm notification, we use None for CallbackArgs on SmmRegisterProtocolNotify
# and update it here.
guid = utils.str_to_guid(protocol)
guid_ptr = self.heap.alloc(guid.sizeof())
guid.saveTo(self.ql, guid_ptr)
guid.save_to(self.ql.mem, guid_ptr)
event_dic['CallbackArgs'] = [guid_ptr, interface, handle]
@@ -75,12 +76,14 @@ class UefiContext(ABC):
return utils.execute_protocol_notifications(self.ql, from_hook)
class DxeContext(UefiContext):
def __init__(self, ql: Qiling):
super().__init__(ql)
self.conftable = DxeConfTable(ql)
class SmmContext(UefiContext):
def __init__(self, ql: Qiling):
super().__init__(ql)
@@ -90,25 +93,16 @@ class SmmContext(UefiContext):
self.smram_base: int
self.smram_size: int
# assume tseg is inaccessible to non-smm
self.tseg_open = False
# assume tseg is locked
self.tseg_locked = True
# registered sw smi handlers
self.swsmi_handlers: Mapping[int, Tuple[int, Mapping]] = {}
class UefiConfTable:
_struct_systbl: STRUCT
_fname_arrptr: str
_fname_nitems: str
def __init__(self, ql: Qiling):
class UefiConfTable:
def __init__(self, ql: Qiling, systbl_type: Type[STRUCT], fname_arrptr: str, fname_nitems: str):
self.ql = ql
self.__arrptr_off = self._struct_systbl.offsetof(self._fname_arrptr)
self.__nitems_off = self._struct_systbl.offsetof(self._fname_nitems)
self.__arrptr_off = systbl_type.offsetof(fname_arrptr)
self.__nitems_off = systbl_type.offsetof(fname_nitems)
@property
@abstractmethod
@@ -119,43 +113,39 @@ class UefiConfTable:
def baseptr(self) -> int:
addr = self.system_table + self.__arrptr_off
return utils.read_int64(self.ql, addr)
return self.ql.mem.read_ptr(addr)
@property
def nitems(self) -> int:
addr = self.system_table + self.__nitems_off
return utils.read_int64(self.ql, addr) # UINTN
return self.ql.mem.read_ptr(addr) # UINTN
@nitems.setter
def nitems(self, value: int):
addr = self.system_table + self.__nitems_off
utils.write_int64(self.ql, addr, value)
self.ql.mem.write_ptr(addr, value)
def install(self, guid: str, table: int):
ptr = self.find(guid)
append = ptr is None
if append:
if ptr is None:
ptr = self.baseptr + self.nitems * EFI_CONFIGURATION_TABLE.sizeof()
append = True
instance = EFI_CONFIGURATION_TABLE()
instance.VendorGuid = utils.str_to_guid(guid)
instance.VendorTable = table
instance.saveTo(self.ql, ptr)
if append:
self.nitems += 1
EFI_CONFIGURATION_TABLE(
VendorGuid = utils.str_to_guid(guid),
VendorTable = table
).save_to(self.ql.mem, ptr)
def find(self, guid: str) -> Optional[int]:
ptr = self.baseptr
nitems = self.nitems
efi_guid = utils.str_to_guid(guid)
for _ in range(nitems):
entry = EFI_CONFIGURATION_TABLE.loadFrom(self.ql, ptr)
entry = EFI_CONFIGURATION_TABLE.load_from(self.ql.mem, ptr)
if utils.CompareGuid(entry.VendorGuid, efi_guid):
return ptr
@@ -168,26 +158,26 @@ class UefiConfTable:
ptr = self.find(guid)
if ptr is not None:
entry = EFI_CONFIGURATION_TABLE.loadFrom(self.ql, ptr)
entry = EFI_CONFIGURATION_TABLE.load_from(self.ql.mem, ptr)
return entry.VendorTable.value
# not found
return None
class DxeConfTable(UefiConfTable):
_struct_systbl = EFI_SYSTEM_TABLE
_fname_arrptr = 'ConfigurationTable'
_fname_nitems = 'NumberOfTableEntries'
def __init__(self, ql: Qiling):
super().__init__(ql, EFI_SYSTEM_TABLE, 'ConfigurationTable', 'NumberOfTableEntries')
@property
def system_table(self) -> int:
return self.ql.loader.gST
class SmmConfTable(UefiConfTable):
_struct_systbl = EFI_SMM_SYSTEM_TABLE2
_fname_arrptr = 'SmmConfigurationTable'
_fname_nitems = 'NumberOfTableEntries'
def __init__(self, ql: Qiling):
super().__init__(ql, EFI_SMM_SYSTEM_TABLE2, 'SmmConfigurationTable', 'NumberOfTableEntries')
@property
def system_table(self) -> int:
+86 -86
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -28,13 +28,13 @@ class EFI_GCD_MEMORY_SPACE_DESCRIPTOR(STRUCT):
_pack_ = 8
_fields_ = [
('BaseAddress', EFI_PHYSICAL_ADDRESS),
('Length', UINT64),
('Capabilities', UINT64),
('Attributes', UINT64),
('GcdMemoryType', EFI_GCD_MEMORY_TYPE),
('ImageHandle', EFI_HANDLE),
('DeviceHandle', EFI_HANDLE)
('BaseAddress', EFI_PHYSICAL_ADDRESS),
('Length', UINT64),
('Capabilities', UINT64),
('Attributes', UINT64),
('GcdMemoryType', EFI_GCD_MEMORY_TYPE),
('ImageHandle', EFI_HANDLE),
('DeviceHandle', EFI_HANDLE)
]
class EFI_GCD_IO_TYPE(ENUM):
@@ -49,11 +49,11 @@ class EFI_GCD_IO_SPACE_DESCRIPTOR(STRUCT):
_pack_ = 8
_fields_ = [
('BaseAddress', EFI_PHYSICAL_ADDRESS),
('Length', UINT64),
('GcdIoType', EFI_GCD_IO_TYPE),
('ImageHandle', EFI_HANDLE),
('DeviceHandle', EFI_HANDLE)
('BaseAddress', EFI_PHYSICAL_ADDRESS),
('Length', UINT64),
('GcdIoType', EFI_GCD_IO_TYPE),
('ImageHandle', EFI_HANDLE),
('DeviceHandle', EFI_HANDLE)
]
class EFI_GCD_ALLOCATE_TYPE(ENUM):
@@ -66,46 +66,46 @@ class EFI_GCD_ALLOCATE_TYPE(ENUM):
'EfiGcdMaxAllocateType'
]
EFI_ADD_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_MEMORY_TYPE, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
EFI_ALLOCATE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_MEMORY_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE)
EFI_FREE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_REMOVE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_GET_MEMORY_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR))
EFI_SET_MEMORY_SPACE_ATTRIBUTES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
EFI_GET_MEMORY_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)))
EFI_ADD_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_IO_TYPE, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_ALLOCATE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_IO_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE)
EFI_FREE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_REMOVE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_GET_IO_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_IO_SPACE_DESCRIPTOR))
EFI_GET_IO_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_IO_SPACE_DESCRIPTOR)))
EFI_DISPATCH = FUNCPTR(EFI_STATUS)
EFI_SCHEDULE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID))
EFI_TRUST = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID))
EFI_PROCESS_FIRMWARE_VOLUME = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(EFI_HANDLE))
EFI_SET_MEMORY_SPACE_CAPABILITIES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
EFI_ADD_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_MEMORY_TYPE, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
EFI_ALLOCATE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_MEMORY_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE)
EFI_FREE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_REMOVE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_GET_MEMORY_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR))
EFI_SET_MEMORY_SPACE_ATTRIBUTES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
EFI_GET_MEMORY_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)))
EFI_ADD_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_IO_TYPE, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_ALLOCATE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_IO_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE)
EFI_FREE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_REMOVE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64)
EFI_GET_IO_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_IO_SPACE_DESCRIPTOR))
EFI_GET_IO_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_IO_SPACE_DESCRIPTOR)))
EFI_DISPATCH = FUNCPTR(EFI_STATUS)
EFI_SCHEDULE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID))
EFI_TRUST = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID))
EFI_PROCESS_FIRMWARE_VOLUME = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(EFI_HANDLE))
EFI_SET_MEMORY_SPACE_CAPABILITIES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64)
class EFI_DXE_SERVICES(STRUCT):
_fields_ = [
('Hdr', EFI_TABLE_HEADER),
('AddMemorySpace', EFI_ADD_MEMORY_SPACE),
('AllocateMemorySpace', EFI_ALLOCATE_MEMORY_SPACE),
('FreeMemorySpace', EFI_FREE_MEMORY_SPACE),
('RemoveMemorySpace', EFI_REMOVE_MEMORY_SPACE),
('GetMemorySpaceDescriptor', EFI_GET_MEMORY_SPACE_DESCRIPTOR),
('SetMemorySpaceAttributes', EFI_SET_MEMORY_SPACE_ATTRIBUTES),
('GetMemorySpaceMap', EFI_GET_MEMORY_SPACE_MAP),
('AddIoSpace', EFI_ADD_IO_SPACE),
('AllocateIoSpace', EFI_ALLOCATE_IO_SPACE),
('FreeIoSpace', EFI_FREE_IO_SPACE),
('RemoveIoSpace', EFI_REMOVE_IO_SPACE),
('GetIoSpaceDescriptor', EFI_GET_IO_SPACE_DESCRIPTOR),
('GetIoSpaceMap', EFI_GET_IO_SPACE_MAP),
('Dispatch', EFI_DISPATCH),
('Schedule', EFI_SCHEDULE),
('Trust', EFI_TRUST),
('ProcessFirmwareVolume', EFI_PROCESS_FIRMWARE_VOLUME),
('SetMemorySpaceCapabilities', EFI_SET_MEMORY_SPACE_CAPABILITIES)
('Hdr', EFI_TABLE_HEADER),
('AddMemorySpace', EFI_ADD_MEMORY_SPACE),
('AllocateMemorySpace', EFI_ALLOCATE_MEMORY_SPACE),
('FreeMemorySpace', EFI_FREE_MEMORY_SPACE),
('RemoveMemorySpace', EFI_REMOVE_MEMORY_SPACE),
('GetMemorySpaceDescriptor', EFI_GET_MEMORY_SPACE_DESCRIPTOR),
('SetMemorySpaceAttributes', EFI_SET_MEMORY_SPACE_ATTRIBUTES),
('GetMemorySpaceMap', EFI_GET_MEMORY_SPACE_MAP),
('AddIoSpace', EFI_ADD_IO_SPACE),
('AllocateIoSpace', EFI_ALLOCATE_IO_SPACE),
('FreeIoSpace', EFI_FREE_IO_SPACE),
('RemoveIoSpace', EFI_REMOVE_IO_SPACE),
('GetIoSpaceDescriptor', EFI_GET_IO_SPACE_DESCRIPTOR),
('GetIoSpaceMap', EFI_GET_IO_SPACE_MAP),
('Dispatch', EFI_DISPATCH),
('Schedule', EFI_SCHEDULE),
('Trust', EFI_TRUST),
('ProcessFirmwareVolume', EFI_PROCESS_FIRMWARE_VOLUME),
('SetMemorySpaceCapabilities', EFI_SET_MEMORY_SPACE_CAPABILITIES)
]
@dxeapi(params={
@@ -122,9 +122,9 @@ def hook_AddMemorySpace(ctx, address, params):
"a1": ULONGLONG,
"a2": ULONGLONG,
"a3": ULONGLONG,
"a4": POINTER, #POINTER_T(ctypes.c_uint64)
"a5": POINTER, #POINTER_T(None)
"a6": POINTER, #POINTER_T(None)
"a4": POINTER, # POINTER_T(ctypes.c_uint64)
"a5": POINTER, # POINTER_T(None)
"a6": POINTER, # POINTER_T(None)
})
def hook_AllocateMemorySpace(ctx, address, params):
return EFI_OUT_OF_RESOURCES
@@ -145,7 +145,7 @@ def hook_RemoveMemorySpace(ctx, address, params):
@dxeapi(params={
"a0": ULONGLONG,
"a1": POINTER, #POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR)
"a1": POINTER, # POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR)
})
def hook_GetMemorySpaceDescriptor(ctx, address, params):
return EFI_UNSUPPORTED
@@ -159,8 +159,8 @@ def hook_SetMemorySpaceAttributes(ctx, address, params):
return EFI_UNSUPPORTED
@dxeapi(params={
"a0": POINTER, #POINTER_T(ctypes.c_uint64)
"a1": POINTER, #POINTER_T(POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR))
"a0": POINTER, # POINTER_T(ctypes.c_uint64)
"a1": POINTER, # POINTER_T(POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR))
})
def hook_GetMemorySpaceMap(ctx, address, params):
return EFI_UNSUPPORTED
@@ -178,9 +178,9 @@ def hook_AddIoSpace(ctx, address, params):
"a1": ULONGLONG,
"a2": ULONGLONG,
"a3": ULONGLONG,
"a4": POINTER, #POINTER_T(ctypes.c_uint64)
"a5": POINTER, #POINTER_T(None)
"a6": POINTER, #POINTER_T(None)
"a4": POINTER, # POINTER_T(ctypes.c_uint64)
"a5": POINTER, # POINTER_T(None)
"a6": POINTER, # POINTER_T(None)
})
def hook_AllocateIoSpace(ctx, address, params):
return EFI_OUT_OF_RESOURCES
@@ -201,14 +201,14 @@ def hook_RemoveIoSpace(ctx, address, params):
@dxeapi(params={
"a0": ULONGLONG,
"a1": POINTER, #POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR)
"a1": POINTER, # POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR)
})
def hook_GetIoSpaceDescriptor(ctx, address, params):
return EFI_NOT_FOUND
@dxeapi(params={
"a0": POINTER, #POINTER_T(ctypes.c_uint64)
"a1": POINTER, #POINTER_T(POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR))
"a0": POINTER, # POINTER_T(ctypes.c_uint64)
"a1": POINTER, # POINTER_T(POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR))
})
def hook_GetIoSpaceMap(ctx, address, params):
return EFI_OUT_OF_RESOURCES
@@ -219,23 +219,23 @@ def hook_Dispatch(ctx, address, params):
return EFI_SUCCESS
@dxeapi(params={
"a0": POINTER, #POINTER_T(None)
"a0": POINTER, # POINTER_T(None)
"a1": GUID,
})
def hook_Schedule(ctx, address, params):
return EFI_SUCCESS
@dxeapi(params={
"a0": POINTER, #POINTER_T(None)
"a0": POINTER, # POINTER_T(None)
"a1": GUID,
})
def hook_Trust(ctx, address, params):
return EFI_NOT_FOUND
@dxeapi(params={
"a0": POINTER, #POINTER_T(None)
"a0": POINTER, # POINTER_T(None)
"a1": ULONGLONG,
"a2": POINTER, #POINTER_T(POINTER_T(None))
"a2": POINTER, # POINTER_T(POINTER_T(None))
})
def hook_ProcessFirmwareVolume(ctx, address, params):
return EFI_OUT_OF_RESOURCES
@@ -252,30 +252,30 @@ def initialize(ql: Qiling, gDS: int):
descriptor = {
'struct' : EFI_DXE_SERVICES,
'fields' : (
('Hdr', None),
('AddMemorySpace', hook_AddMemorySpace),
('AllocateMemorySpace', hook_AllocateMemorySpace),
('FreeMemorySpace', hook_FreeMemorySpace),
('RemoveMemorySpace', hook_RemoveMemorySpace),
('GetMemorySpaceDescriptor', hook_GetMemorySpaceDescriptor),
('SetMemorySpaceAttributes', hook_SetMemorySpaceAttributes),
('GetMemorySpaceMap', hook_GetMemorySpaceMap),
('AddIoSpace', hook_AddIoSpace),
('AllocateIoSpace', hook_AllocateIoSpace),
('FreeIoSpace', hook_FreeIoSpace),
('RemoveIoSpace', hook_RemoveIoSpace),
('GetIoSpaceDescriptor', hook_GetIoSpaceDescriptor),
('GetIoSpaceMap', hook_GetIoSpaceMap),
('Dispatch', hook_Dispatch),
('Schedule', hook_Schedule),
('Trust', hook_Trust),
('ProcessFirmwareVolume', hook_ProcessFirmwareVolume),
('SetMemorySpaceCapabilities', hook_SetMemorySpaceCapabilities)
('Hdr', None),
('AddMemorySpace', hook_AddMemorySpace),
('AllocateMemorySpace', hook_AllocateMemorySpace),
('FreeMemorySpace', hook_FreeMemorySpace),
('RemoveMemorySpace', hook_RemoveMemorySpace),
('GetMemorySpaceDescriptor', hook_GetMemorySpaceDescriptor),
('SetMemorySpaceAttributes', hook_SetMemorySpaceAttributes),
('GetMemorySpaceMap', hook_GetMemorySpaceMap),
('AddIoSpace', hook_AddIoSpace),
('AllocateIoSpace', hook_AllocateIoSpace),
('FreeIoSpace', hook_FreeIoSpace),
('RemoveIoSpace', hook_RemoveIoSpace),
('GetIoSpaceDescriptor', hook_GetIoSpaceDescriptor),
('GetIoSpaceMap', hook_GetIoSpaceMap),
('Dispatch', hook_Dispatch),
('Schedule', hook_Schedule),
('Trust', hook_Trust),
('ProcessFirmwareVolume', hook_ProcessFirmwareVolume),
('SetMemorySpaceCapabilities', hook_SetMemorySpaceCapabilities)
)
}
instance = init_struct(ql, gDS, descriptor)
instance.saveTo(ql, gDS)
instance.save_to(ql.mem, gDS)
__all__ = [
'EFI_DXE_SERVICES',
+16 -16
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -9,20 +9,20 @@ from qiling.os.uefi.utils import GetEfiConfigurationTable, CompareGuid, str_to_g
from qiling.os.uefi.UefiBaseType import STRUCT, EFI_GUID, UINT32, UINT16
EFI_HOB_TYPE_HANDOFF = 0x0001
EFI_HOB_TYPE_GUID_EXTENSION = 0x0004
EFI_HOB_TYPE_GUID_EXTENSION = 0x0004
EFI_HOB_TYPE_END_OF_HOB_LIST = 0xffff
class EFI_HOB_GENERIC_HEADER(STRUCT):
_fields_ = [
('HobType', UINT16),
('HobLength', UINT16),
('Reserved', UINT32)
('HobType', UINT16),
('HobLength', UINT16),
('Reserved', UINT32)
]
class EFI_HOB_GUID_TYPE(STRUCT):
_fields_ = [
('Header', EFI_HOB_GENERIC_HEADER),
('Name', EFI_GUID)
('Header', EFI_HOB_GENERIC_HEADER),
('Name', EFI_GUID)
]
def GetHobList(ql: Qiling, context: UefiContext) -> int:
@@ -36,7 +36,7 @@ def GetHobList(ql: Qiling, context: UefiContext) -> int:
return hoblist_vend
def CreateHob(ql: Qiling, context: UefiContext, hob) -> int:
def CreateHob(ql: Qiling, context: UefiContext, hob: STRUCT) -> int:
"""Add a HOB to the end of the HOB list.
"""
@@ -48,15 +48,15 @@ def CreateHob(ql: Qiling, context: UefiContext, hob) -> int:
# overwrite end marker with the hob
pHob = hoblist
hob.saveTo(ql, pHob)
hob.save_to(ql.mem, pHob)
hoblist += hob.sizeof()
# create a new end marker istead, following the hob
marker = EFI_HOB_GENERIC_HEADER()
marker.HobType = EFI_HOB_TYPE_END_OF_HOB_LIST
marker.HobLength = 0x0000
marker.Reserved = 0x00000000
marker.saveTo(ql, hoblist)
EFI_HOB_GENERIC_HEADER(
HobType = EFI_HOB_TYPE_END_OF_HOB_LIST,
HobLength = 0x0000,
Reserved = 0x00000000
).save_to(ql.mem, hoblist)
# return the address the hob was written to; it might be useful
return pHob
@@ -68,7 +68,7 @@ def GetNextHob(ql: Qiling, hobtype: int, hoblist: int) -> int:
hobaddr = hoblist
while True:
header = EFI_HOB_GENERIC_HEADER.loadFrom(ql, hobaddr)
header = EFI_HOB_GENERIC_HEADER.load_from(ql.mem, hobaddr)
# found the hob?
if header.HobType == hobtype:
@@ -95,7 +95,7 @@ def GetNextGuidHob(ql: Qiling, guid: str, hoblist: int) -> int:
if not hobaddr:
return 0
hob = EFI_HOB_GUID_TYPE.loadFrom(ql, hobaddr)
hob = EFI_HOB_GUID_TYPE.load_from(ql.mem, hobaddr)
if CompareGuid(hob.Name, hobguid):
break
@@ -1,32 +1,34 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from ..ProcessorBind import *
from ..UefiBaseType import *
from ..ProcessorBind import VOID, UINT32, UINT64, PTR, STRUCT
from ..UefiBaseType import EFI_HANDLE
from ..UefiSpec import EFI_SYSTEM_TABLE, EFI_DEVICE_PATH_PROTOCOL, EFI_IMAGE_UNLOAD
from ..UefiMultiPhase import EFI_MEMORY_TYPE
class EFI_LOADED_IMAGE_PROTOCOL(STRUCT):
_pack_ = 8
_fields_ = [
('Revision', UINT32),
('ParentHandle', EFI_HANDLE),
('SystemTable', PTR(EFI_SYSTEM_TABLE)),
('SystemTable', PTR(EFI_SYSTEM_TABLE)),
('DeviceHandle', EFI_HANDLE),
('FilePath', PTR(EFI_DEVICE_PATH_PROTOCOL)),
('Reserved', PTR(VOID)),
('LoadOptionsSize', UINT32),
('LoadOptions', PTR(VOID)),
('ImageBase', PTR(VOID)),
('ImageSize', UINT64),
('ImageCodeType', EFI_MEMORY_TYPE),
('ImageDataType', EFI_MEMORY_TYPE),
('Unload', EFI_IMAGE_UNLOAD)
('Reserved', PTR(VOID)),
('LoadOptionsSize', UINT32),
('LoadOptions', PTR(VOID)),
('ImageBase', PTR(VOID)),
('ImageSize', UINT64),
('ImageCodeType', EFI_MEMORY_TYPE),
('ImageDataType', EFI_MEMORY_TYPE),
('Unload', EFI_IMAGE_UNLOAD)
]
def make_descriptor(fields):
descriptor = {
"guid" : "5b1b31a1-9562-11d2-8e3f-00a0c969723b",
@@ -34,22 +36,23 @@ def make_descriptor(fields):
"fields" : (
('Revision', 0x1000),
('ParentHandle', 0),
('SystemTable', fields['gST']),
('SystemTable', fields['gST']),
('DeviceHandle', fields['image_base']),
('FilePath', 0), # This is a handle to a complex path object, skip it for now.
('LoadOptionsSize', 0),
('LoadOptions', 0),
('ImageBase', fields['image_base']),
('ImageSize', fields['image_size']),
('ImageCodeType', EFI_MEMORY_TYPE.EfiLoaderCode),
('ImageDataType', EFI_MEMORY_TYPE.EfiLoaderData),
('Unload', 0)
('LoadOptionsSize', 0),
('LoadOptions', 0),
('ImageBase', fields['image_base']),
('ImageSize', fields['image_size']),
('ImageCodeType', EFI_MEMORY_TYPE.EfiLoaderCode),
('ImageDataType', EFI_MEMORY_TYPE.EfiLoaderData),
('Unload', 0)
)
}
return descriptor
__all__ = [
'EFI_LOADED_IMAGE_PROTOCOL',
'make_descriptor'
]
]
@@ -1,24 +1,30 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from qiling import Qiling
from qiling.os.const import *
from __future__ import annotations
from typing import TYPE_CHECKING
from qiling.os.const import POINTER
from qiling.os.uefi.const import *
from ..fncc import *
from ..fncc import dxeapi
from ..ProcessorBind import *
from ..UefiBaseType import *
from ..UefiBaseType import EFI_PHYSICAL_ADDRESS, EFI_STATUS
from ..PiMultiPhase import *
from .. import utils
if TYPE_CHECKING:
from qiling import Qiling
# @see: MdePkg\Include\Pi\PiMultiPhase.h
class EFI_MMRAM_DESCRIPTOR(STRUCT):
_fields_ = [
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('CpuStart', EFI_PHYSICAL_ADDRESS),
('PhysicalSize', UINT64),
('RegionState', UINT64)
('PhysicalStart', EFI_PHYSICAL_ADDRESS),
('CpuStart', EFI_PHYSICAL_ADDRESS),
('PhysicalSize', UINT64),
('RegionState', UINT64)
]
# @see: MdePkg\Include\Protocol\MmAccess.h
@@ -28,34 +34,43 @@ class EFI_SMM_ACCESS2_PROTOCOL(STRUCT):
_fields_ = [
('Open', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))),
('Close', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))),
('Close', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))),
('Lock', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))),
('GetCapabilities', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL), PTR(UINTN), PTR(EFI_MMRAM_DESCRIPTOR))),
('LockState', BOOLEAN),
('OpenState', BOOLEAN)
('GetCapabilities', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL), PTR(UINTN), PTR(EFI_MMRAM_DESCRIPTOR))),
('LockState', BOOLEAN),
('OpenState', BOOLEAN)
]
@dxeapi(params = {
"This" : POINTER
"This": POINTER
})
def hook_Open(ql: Qiling, address: int, params):
ql.loader.smm_context.tseg_open = True
this = params["This"]
with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct:
struct.OpenState = True
return EFI_SUCCESS
@dxeapi(params = {
"This" : POINTER
"This": POINTER
})
def hook_Close(ql: Qiling, address: int, params):
ql.loader.smm_context.tseg_open = False
this = params["This"]
with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct:
struct.OpenState = False
return EFI_SUCCESS
@dxeapi(params = {
"This" : POINTER
"This": POINTER
})
def hook_Lock(ql: Qiling, address: int, params):
ql.loader.smm_context.tseg_locked = True
this = params["This"]
with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct:
struct.LockState = True
return EFI_SUCCESS
@@ -81,9 +96,9 @@ def _coalesce(seq):
return res
@dxeapi(params = {
"This" : POINTER, # PTR(EFI_SMM_ACCESS2_PROTOCOL)
"MmramMapSize" : POINTER, # IN OUT PTR(UINTN)
"MmramMap" : POINTER # OUT PTR(EFI_MMRAM_DESCRIPTOR)
"This": POINTER, # PTR(EFI_SMM_ACCESS2_PROTOCOL)
"MmramMapSize": POINTER, # IN OUT PTR(UINTN)
"MmramMap": POINTER # OUT PTR(EFI_MMRAM_DESCRIPTOR)
})
def hook_GetCapabilities(ql: Qiling, address: int, params):
heap = ql.loader.smm_context.heap
@@ -108,7 +123,7 @@ def hook_GetCapabilities(ql: Qiling, address: int, params):
size = len(chunks) * EFI_SMRAM_DESCRIPTOR.sizeof()
MmramMapSize = params["MmramMapSize"]
if utils.read_int64(ql, MmramMapSize) < size:
if ql.mem.read_ptr(MmramMapSize) < size:
# since the caller cannot predict how much memory would be required for storing
# the memory map, this method is normally called twice. the first one passes a
# zero size only to determine the expected size, then the caller allocates the
@@ -124,33 +139,38 @@ def hook_GetCapabilities(ql: Qiling, address: int, params):
# have, to compensate on the coming allocation.
extra = 2 * EFI_SMRAM_DESCRIPTOR.sizeof()
utils.write_int64(ql, MmramMapSize, size + extra)
ql.mem.write_ptr(MmramMapSize, size + extra)
return EFI_BUFFER_TOO_SMALL
this = params["This"]
struct = EFI_SMM_ACCESS2_PROTOCOL.load_from(ql.mem, this)
state = EFI_CACHEABLE
state |= EFI_SMRAM_OPEN if struct.OpenState else EFI_SMRAM_CLOSED
state |= EFI_SMRAM_LOCKED if struct.LockState else 0
MmramMap = params["MmramMap"]
state = EFI_CACHEABLE
state |= EFI_SMRAM_OPEN if ql.loader.smm_context.tseg_open else EFI_SMRAM_CLOSED
state |= EFI_SMRAM_LOCKED if ql.loader.smm_context.tseg_locked else 0
for i, ch in enumerate(chunks):
desc = EFI_SMRAM_DESCRIPTOR()
desc.PhysicalStart = ch[0]
desc.CpuStart = ch[0]
desc.PhysicalSize = ch[1] - ch[0]
desc.RegionState = state | (EFI_ALLOCATED if ch[2] else 0)
desc.saveTo(ql, MmramMap + (i * desc.sizeof()))
EFI_SMRAM_DESCRIPTOR(
PhysicalStart = ch[0],
CpuStart = ch[0],
PhysicalSize = ch[1] - ch[0],
RegionState = state | (EFI_ALLOCATED if ch[2] else 0)
).save_to(ql.mem, MmramMap + (i * EFI_SMRAM_DESCRIPTOR.sizeof()))
return EFI_SUCCESS
descriptor = {
"guid" : "c2702b74-800c-4131-8746-8fb5b89ce4ac",
"struct" : EFI_SMM_ACCESS2_PROTOCOL,
"fields" : (
("Open", hook_Open),
("Close", hook_Close),
("Close", hook_Close),
("Lock", hook_Lock),
("GetCapabilities", hook_GetCapabilities)
("GetCapabilities", hook_GetCapabilities),
("LockState", True), # lock tseg
("OpenState", False) # make tseg inaccessible to non-smm
)
}
+11 -12
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -8,7 +8,6 @@ from qiling.os.const import *
from ..const import EFI_SUCCESS, EFI_INVALID_PARAMETER
from ..fncc import *
from ..utils import *
from ..ProcessorBind import *
from ..UefiBaseType import *
from ..smst import *
@@ -18,24 +17,24 @@ class EFI_SMM_BASE2_PROTOCOL(STRUCT):
EFI_SMM_BASE2_PROTOCOL = STRUCT
_fields_ = [
('InSmm', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(BOOLEAN))),
('GetSmstLocation', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(PTR(EFI_SMM_SYSTEM_TABLE2)))),
('InSmm', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(BOOLEAN))),
('GetSmstLocation', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(PTR(EFI_SMM_SYSTEM_TABLE2)))),
]
@dxeapi(params = {
"This" : POINTER,
"InSmram" : POINTER
"This": POINTER,
"InSmram": POINTER
})
def hook_InSmm(ql: Qiling, address: int, params):
ql.log.debug(f'InSmram = {ql.os.smm.active}')
write_int8(ql, params["InSmram"], int(ql.os.smm.active))
ql.mem.write_ptr(params["InSmram"], int(ql.os.smm.active), 1)
return EFI_SUCCESS
@dxeapi(params = {
"This" : POINTER,
"Smst" : POINTER
"This": POINTER,
"Smst": POINTER
})
def hook_GetSmstLocation(ql: Qiling, address: int, params):
Smst = params["Smst"]
@@ -43,7 +42,7 @@ def hook_GetSmstLocation(ql: Qiling, address: int, params):
if Smst == 0:
return EFI_INVALID_PARAMETER
write_int64(ql, Smst, ql.loader.gSmst)
ql.mem.write_ptr(Smst, ql.loader.gSmst)
return EFI_SUCCESS
@@ -51,7 +50,7 @@ descriptor = {
"guid" : "f4ccbfb7-f6e0-47fd-9dd4-10a8f150c191",
"struct" : EFI_SMM_BASE2_PROTOCOL,
"fields" : (
("InSmm", hook_InSmm),
("GetSmstLocation", hook_GetSmstLocation)
("InSmm", hook_InSmm),
("GetSmstLocation", hook_GetSmstLocation)
)
}
+91 -91
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -12,96 +12,96 @@ from ..const import *
# @see: MdePkg/Include/Protocol/MmCpu.h
class EFI_SMM_SAVE_STATE_REGISTER(ENUM_UC):
_members_ = {
# note: members names were shorten from 'EFI_SMM_SAVE_STATE_REGISTER_regname' to just 'regname'
'GDTBASE' : 4,
'IDTBASE' : 5,
'LDTBASE' : 6,
'GDTLIMIT' : 7,
'IDTLIMIT' : 8,
'LDTLIMIT' : 9,
'LDTINFO' : 10,
# note: members names were shorten from 'EFI_SMM_SAVE_STATE_REGISTER_regname' to just 'regname'
'GDTBASE': 4,
'IDTBASE': 5,
'LDTBASE': 6,
'GDTLIMIT': 7,
'IDTLIMIT': 8,
'LDTLIMIT': 9,
'LDTINFO': 10,
'ES' : 20,
'CS' : 21,
'SS' : 22,
'DS' : 23,
'FS' : 24,
'GS' : 25,
'LDTR_SEL' : 26,
'TR_SEL' : 27,
'DR7' : 28,
'DR6' : 29,
'R8' : 30,
'R9' : 31,
'R10' : 32,
'R11' : 33,
'R12' : 34,
'R13' : 35,
'R14' : 36,
'R15' : 37,
'RAX' : 38,
'RBX' : 39,
'RCX' : 40,
'RDX' : 41,
'RSP' : 42,
'RBP' : 43,
'RSI' : 44,
'RDI' : 45,
'RIP' : 46,
'ES': 20,
'CS': 21,
'SS': 22,
'DS': 23,
'FS': 24,
'GS': 25,
'LDTR_SEL': 26,
'TR_SEL': 27,
'DR7': 28,
'DR6': 29,
'R8': 30,
'R9': 31,
'R10': 32,
'R11': 33,
'R12': 34,
'R13': 35,
'R14': 36,
'R15': 37,
'RAX': 38,
'RBX': 39,
'RCX': 40,
'RDX': 41,
'RSP': 42,
'RBP': 43,
'RSI': 44,
'RDI': 45,
'RIP': 46,
'RFLAGS' : 51,
'CR0' : 52,
'CR3' : 53,
'CR4' : 54,
'RFLAGS': 51,
'CR0': 52,
'CR3': 53,
'CR4': 54,
'FCW' : 256,
'FSW' : 257,
'FTW' : 258,
'OPCODE' : 259,
'FP_EIP' : 260,
'FP_CS' : 261,
'FCW': 256,
'FSW': 257,
'FTW': 258,
'OPCODE': 259,
'FP_EIP': 260,
'FP_CS': 261,
'DATAOFFSET': 262,
'FP_DS' : 263,
'MM0' : 264,
'MM1' : 265,
'MM2' : 266,
'MM3' : 267,
'MM4' : 268,
'MM5' : 269,
'MM6' : 270,
'MM7' : 271,
'XMM0' : 272,
'XMM1' : 273,
'XMM2' : 274,
'XMM3' : 275,
'XMM4' : 276,
'XMM5' : 277,
'XMM6' : 278,
'XMM7' : 279,
'XMM8' : 280,
'XMM9' : 281,
'XMM10' : 282,
'XMM11' : 283,
'XMM12' : 284,
'XMM13' : 285,
'XMM14' : 286,
'XMM15' : 287,
'FP_DS': 263,
'MM0': 264,
'MM1': 265,
'MM2': 266,
'MM3': 267,
'MM4': 268,
'MM5': 269,
'MM6': 270,
'MM7': 271,
'XMM0': 272,
'XMM1': 273,
'XMM2': 274,
'XMM3': 275,
'XMM4': 276,
'XMM5': 277,
'XMM6': 278,
'XMM7': 279,
'XMM8': 280,
'XMM9': 281,
'XMM10': 282,
'XMM11': 283,
'XMM12': 284,
'XMM13': 285,
'XMM14': 286,
'XMM15': 287,
'IO' : 512,
'LMA' : 513,
'PROCESSOR_ID' : 514
'IO': 512,
'LMA': 513,
'PROCESSOR_ID': 514
}
# EFI_SUCCESS The register was written from Save State
# EFI_NOT_FOUND The register is not defined for the Save State of Processor
# EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct
# EFI_SUCCESS The register was written from Save State
# EFI_NOT_FOUND The register is not defined for the Save State of Processor
# EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct
@dxeapi(params = {
"This" : POINTER, # EFI_SMM_CPU_PROTOCOL
"Width" : ULONGLONG,# UINTN
"Register" : INT, # EFI_SMM_SAVE_STATE_REGISTER
"CpuIndex" : ULONGLONG,# UINTN
"Buffer" : POINTER # PTR(VOID)
"This": POINTER, # EFI_SMM_CPU_PROTOCOL
"Width": ULONGLONG, # UINTN
"Register": INT, # EFI_SMM_SAVE_STATE_REGISTER
"CpuIndex": ULONGLONG, # UINTN
"Buffer": POINTER # PTR(VOID)
})
def hook_SmmReadSaveState(ql: Qiling, address: int, params):
Width = params['Width']
@@ -119,11 +119,11 @@ def hook_SmmReadSaveState(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"This" : POINTER, # EFI_SMM_CPU_PROTOCOL
"Width" : ULONGLONG,# UINTN
"Register" : INT, # EFI_SMM_SAVE_STATE_REGISTER
"CpuIndex" : ULONGLONG,# UINTN
"Buffer" : POINTER # PTR(VOID)
"This": POINTER, # EFI_SMM_CPU_PROTOCOL
"Width": ULONGLONG, # UINTN
"Register": INT, # EFI_SMM_SAVE_STATE_REGISTER
"CpuIndex": ULONGLONG, # UINTN
"Buffer": POINTER # PTR(VOID)
})
def hook_SmmWriteSaveState(ql: Qiling, address: int, params):
Width = params['Width']
@@ -144,15 +144,15 @@ class EFI_SMM_CPU_PROTOCOL(STRUCT):
EFI_SMM_CPU_PROTOCOL = STRUCT
_fields_ = [
('SmmReadSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))),
('SmmWriteSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID)))
('SmmReadSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))),
('SmmWriteSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID)))
]
descriptor = {
"guid" : "eb346b97-975f-4a9f-8b22-f8e92bb3d569",
"struct" : EFI_SMM_CPU_PROTOCOL,
"fields" : (
("SmmReadSaveState", hook_SmmReadSaveState),
("SmmWriteSaveState", hook_SmmWriteSaveState)
("SmmReadSaveState", hook_SmmReadSaveState),
("SmmWriteSaveState", hook_SmmWriteSaveState)
)
}
@@ -1,15 +1,20 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from qiling import Qiling
from typing import TYPE_CHECKING
from qiling.os.const import *
from ..const import *
from ..fncc import *
from ..ProcessorBind import *
from ..UefiBaseType import *
from .. import utils
if TYPE_CHECKING:
from qiling import Qiling
MAXIMUM_SWI_VALUE = 0xff
@@ -17,9 +22,9 @@ class EFI_SMM_SW_CONTEXT(STRUCT):
_pack_ = 8
_fields_ = [
('SwSmiCpuIndex', UINTN), # index of the cpu which generated the swsmi
('CommandPort', UINT8), # port number used to trigger the swsmi
('DataPort', UINT8) # irrelevant
('SwSmiCpuIndex', UINTN), # index of the cpu which generated the swsmi
('CommandPort', UINT8), # port number used to trigger the swsmi
('DataPort', UINT8) # irrelevant
]
# @file: MdePkg\Include\Protocol\SmmSwDispatch2.h
@@ -36,15 +41,15 @@ class EFI_SMM_SW_DISPATCH2_PROTOCOL(STRUCT):
_fields_ = [
('Register', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_SMM_HANDLER_ENTRY_POINT2, PTR(EFI_SMM_SW_REGISTER_CONTEXT), PTR(EFI_HANDLE))),
('UnRegister', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_HANDLE)),
('MaximumSwiValue', UINTN)
('UnRegister', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_HANDLE)),
('MaximumSwiValue', UINTN)
]
@dxeapi(params = {
"This" : POINTER, # PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL)
"DispatchFunction" : POINTER, # EFI_SMM_HANDLER_ENTRY_POINT2
"RegisterContext" : POINTER, # PTR(EFI_SMM_SW_REGISTER_CONTEXT)
"DispatchHandle" : POINTER # PTR(EFI_HANDLE)
"This": POINTER, # PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL)
"DispatchFunction": POINTER, # EFI_SMM_HANDLER_ENTRY_POINT2
"RegisterContext": POINTER, # PTR(EFI_SMM_SW_REGISTER_CONTEXT)
"DispatchHandle": POINTER # PTR(EFI_HANDLE)
})
def hook_Register(ql: Qiling, address: int, params):
DispatchFunction: int = params['DispatchFunction']
@@ -56,22 +61,22 @@ def hook_Register(ql: Qiling, address: int, params):
handlers = ql.loader.smm_context.swsmi_handlers
SwRegisterContext = EFI_SMM_SW_REGISTER_CONTEXT.loadFrom(ql, RegisterContext)
SwRegisterContext = EFI_SMM_SW_REGISTER_CONTEXT.load_from(ql.mem, RegisterContext)
idx = SwRegisterContext.SwSmiInputValue
# a value of -1 indicates that the swsmi index for this handler is flexible and
# should be assigned by the protocol
if idx == ((1 << ql.arch.bits) - 1):
idx = next((i for i in range(1, MAXIMUM_SWI_VALUE) if i not in handlers), None)
if idx is None:
try:
idx = next(i for i in range(1, MAXIMUM_SWI_VALUE) if i not in handlers)
except StopIteration:
return EFI_OUT_OF_RESOURCES
SwRegisterContext.SwSmiInputValue = idx
SwRegisterContext.saveTo(ql, RegisterContext)
SwRegisterContext.save_to(ql.mem, RegisterContext)
else:
This = EFI_SMM_SW_DISPATCH2_PROTOCOL.loadFrom(ql, params['This'])
This = EFI_SMM_SW_DISPATCH2_PROTOCOL.load_from(ql.mem, params['This'])
if idx in handlers:
return EFI_INVALID_PARAMETER
@@ -81,11 +86,11 @@ def hook_Register(ql: Qiling, address: int, params):
# allocate handle and return it through out parameter
Handle = ql.loader.smm_context.heap.alloc(ql.arch.pointersize)
utils.write_int64(ql, DispatchHandle, Handle)
ql.mem.write_ptr(DispatchHandle, Handle)
args = {
'DispatchHandle' : Handle,
'RegisterContext' : SwRegisterContext
'DispatchHandle': Handle,
'RegisterContext': SwRegisterContext
}
handlers[idx] = (DispatchFunction, args)
@@ -93,8 +98,8 @@ def hook_Register(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params = {
"This" : POINTER,
"DispatchHandle" : POINTER
"This": POINTER,
"DispatchHandle": POINTER
})
def hook_UnRegister(ql: Qiling, address: int, params):
DispatchHandle: int = params['DispatchHandle']
@@ -102,9 +107,9 @@ def hook_UnRegister(ql: Qiling, address: int, params):
handlers = ql.loader.smm_context.swsmi_handlers
heap = ql.loader.smm_context.heap
idx = next((idx for idx, (_, args) in handlers.items() if args['DispatchHandle'] == DispatchHandle), None)
if idx is None:
try:
idx = next(idx for idx, (_, args) in handlers.items() if args['DispatchHandle'] == DispatchHandle)
except StopIteration:
return EFI_INVALID_PARAMETER
heap.free(DispatchHandle)
@@ -117,7 +122,7 @@ descriptor = {
"struct" : EFI_SMM_SW_DISPATCH2_PROTOCOL,
"fields" : (
("Register", hook_Register),
("UnRegister", hook_UnRegister),
('MaximumSwiValue', MAXIMUM_SWI_VALUE)
("UnRegister", hook_UnRegister),
('MaximumSwiValue', MAXIMUM_SWI_VALUE)
)
}
+195 -184
View File
@@ -1,334 +1,345 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
from typing import TYPE_CHECKING
from qiling.os.const import *
from ..fncc import *
from ..fncc import dxeapi
from ..ProcessorBind import *
from ..UefiBaseType import *
from ..UefiBaseType import EFI_GUID, EFI_STATUS
if TYPE_CHECKING:
from qiling import Qiling
PCD_PROTOCOL_CALLBACK = FUNCPTR(VOID, PTR(EFI_GUID), UINTN, PTR(VOID), UINTN)
PCD_PROTOCOL_SET_SKU = FUNCPTR(VOID, UINTN)
PCD_PROTOCOL_SET_SKU = FUNCPTR(VOID, UINTN)
PCD_PROTOCOL_GET8 = FUNCPTR(UINT8, UINTN)
PCD_PROTOCOL_GET16 = FUNCPTR(UINT16, UINTN)
PCD_PROTOCOL_GET32 = FUNCPTR(UINT32, UINTN)
PCD_PROTOCOL_GET64 = FUNCPTR(UINT64, UINTN)
PCD_PROTOCOL_GET_POINTER = FUNCPTR(PTR(VOID), UINTN)
PCD_PROTOCOL_GET_BOOLEAN = FUNCPTR(BOOLEAN, UINTN)
PCD_PROTOCOL_GET16 = FUNCPTR(UINT16, UINTN)
PCD_PROTOCOL_GET32 = FUNCPTR(UINT32, UINTN)
PCD_PROTOCOL_GET64 = FUNCPTR(UINT64, UINTN)
PCD_PROTOCOL_GET_POINTER = FUNCPTR(PTR(VOID), UINTN)
PCD_PROTOCOL_GET_BOOLEAN = FUNCPTR(BOOLEAN, UINTN)
PCD_PROTOCOL_GET_SIZE = FUNCPTR(UINTN, UINTN)
PCD_PROTOCOL_GET_EX_8 = FUNCPTR(UINT8, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_16 = FUNCPTR(UINT16, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_32 = FUNCPTR(UINT32, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_64 = FUNCPTR(UINT64, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_POINTER = FUNCPTR(PTR(VOID), PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_BOOLEAN = FUNCPTR(BOOLEAN, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_SIZE = FUNCPTR(UINTN, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_16 = FUNCPTR(UINT16, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_32 = FUNCPTR(UINT32, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_64 = FUNCPTR(UINT64, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_POINTER = FUNCPTR(PTR(VOID), PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_BOOLEAN = FUNCPTR(BOOLEAN, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_GET_EX_SIZE = FUNCPTR(UINTN, PTR(EFI_GUID), UINTN)
PCD_PROTOCOL_SET8 = FUNCPTR(EFI_STATUS, UINTN, UINT8)
PCD_PROTOCOL_SET16 = FUNCPTR(EFI_STATUS, UINTN, UINT16)
PCD_PROTOCOL_SET32 = FUNCPTR(EFI_STATUS, UINTN, UINT32)
PCD_PROTOCOL_SET64 = FUNCPTR(EFI_STATUS, UINTN, UINT64)
PCD_PROTOCOL_SET_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(UINTN), PTR(VOID))
PCD_PROTOCOL_SET_BOOLEAN = FUNCPTR(EFI_STATUS, UINTN, BOOLEAN)
PCD_PROTOCOL_SET16 = FUNCPTR(EFI_STATUS, UINTN, UINT16)
PCD_PROTOCOL_SET32 = FUNCPTR(EFI_STATUS, UINTN, UINT32)
PCD_PROTOCOL_SET64 = FUNCPTR(EFI_STATUS, UINTN, UINT64)
PCD_PROTOCOL_SET_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(UINTN), PTR(VOID))
PCD_PROTOCOL_SET_BOOLEAN = FUNCPTR(EFI_STATUS, UINTN, BOOLEAN)
PCD_PROTOCOL_SET_EX_8 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT8)
PCD_PROTOCOL_SET_EX_16 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT16)
PCD_PROTOCOL_SET_EX_32 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT32)
PCD_PROTOCOL_SET_EX_64 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT64)
PCD_PROTOCOL_SET_EX_POINTER = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PTR(UINTN), PTR(VOID))
PCD_PROTOCOL_SET_EX_BOOLEAN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, BOOLEAN)
PCD_PROTOCOL_CALLBACK_ONSET = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK)
PCD_PROTOCOL_CANCEL_CALLBACK= FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK)
PCD_PROTOCOL_GET_NEXT_TOKEN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(UINTN))
PCD_PROTOCOL_SET_EX_16 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT16)
PCD_PROTOCOL_SET_EX_32 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT32)
PCD_PROTOCOL_SET_EX_64 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT64)
PCD_PROTOCOL_SET_EX_POINTER = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PTR(UINTN), PTR(VOID))
PCD_PROTOCOL_SET_EX_BOOLEAN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, BOOLEAN)
PCD_PROTOCOL_CALLBACK_ONSET = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK)
PCD_PROTOCOL_CANCEL_CALLBACK = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK)
PCD_PROTOCOL_GET_NEXT_TOKEN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(UINTN))
PCD_PROTOCOL_GET_NEXT_TOKENSPACE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_GUID)))
class PCD_PROTOCOL(STRUCT):
_fields_ = [
('SetSku', PCD_PROTOCOL_SET_SKU),
('Get8', PCD_PROTOCOL_GET8),
('Get16', PCD_PROTOCOL_GET16),
('Get32', PCD_PROTOCOL_GET32),
('Get64', PCD_PROTOCOL_GET64),
('GetPtr', PCD_PROTOCOL_GET_POINTER),
('GetBool', PCD_PROTOCOL_GET_BOOLEAN),
('GetSize', PCD_PROTOCOL_GET_SIZE),
('Get8Ex', PCD_PROTOCOL_GET_EX_8),
('Get16Ex', PCD_PROTOCOL_GET_EX_16),
('Get32Ex', PCD_PROTOCOL_GET_EX_32),
('Get64Ex', PCD_PROTOCOL_GET_EX_64),
('GetPtrEx', PCD_PROTOCOL_GET_EX_POINTER),
('GetBoolEx', PCD_PROTOCOL_GET_EX_BOOLEAN),
('GetSizeEx', PCD_PROTOCOL_GET_EX_SIZE),
('Set8', PCD_PROTOCOL_SET8),
('Set16', PCD_PROTOCOL_SET16),
('Set32', PCD_PROTOCOL_SET32),
('Set64', PCD_PROTOCOL_SET64),
('SetPtr', PCD_PROTOCOL_SET_POINTER),
('SetBool', PCD_PROTOCOL_SET_BOOLEAN),
('Set8Ex', PCD_PROTOCOL_SET_EX_8),
('Set16Ex', PCD_PROTOCOL_SET_EX_16),
('Set32Ex', PCD_PROTOCOL_SET_EX_32),
('Set64Ex', PCD_PROTOCOL_SET_EX_64),
('SetPtrEx', PCD_PROTOCOL_SET_EX_POINTER),
('SetBoolEx', PCD_PROTOCOL_SET_EX_BOOLEAN),
('CallbackOnSet', PCD_PROTOCOL_CALLBACK_ONSET),
('CancelCallback', PCD_PROTOCOL_CANCEL_CALLBACK),
('GetNextToken', PCD_PROTOCOL_GET_NEXT_TOKEN),
('GetNextTokenSpace', PCD_PROTOCOL_GET_NEXT_TOKENSPACE)
('SetSku', PCD_PROTOCOL_SET_SKU),
('Get8', PCD_PROTOCOL_GET8),
('Get16', PCD_PROTOCOL_GET16),
('Get32', PCD_PROTOCOL_GET32),
('Get64', PCD_PROTOCOL_GET64),
('GetPtr', PCD_PROTOCOL_GET_POINTER),
('GetBool', PCD_PROTOCOL_GET_BOOLEAN),
('GetSize', PCD_PROTOCOL_GET_SIZE),
('Get8Ex', PCD_PROTOCOL_GET_EX_8),
('Get16Ex', PCD_PROTOCOL_GET_EX_16),
('Get32Ex', PCD_PROTOCOL_GET_EX_32),
('Get64Ex', PCD_PROTOCOL_GET_EX_64),
('GetPtrEx', PCD_PROTOCOL_GET_EX_POINTER),
('GetBoolEx', PCD_PROTOCOL_GET_EX_BOOLEAN),
('GetSizeEx', PCD_PROTOCOL_GET_EX_SIZE),
('Set8', PCD_PROTOCOL_SET8),
('Set16', PCD_PROTOCOL_SET16),
('Set32', PCD_PROTOCOL_SET32),
('Set64', PCD_PROTOCOL_SET64),
('SetPtr', PCD_PROTOCOL_SET_POINTER),
('SetBool', PCD_PROTOCOL_SET_BOOLEAN),
('Set8Ex', PCD_PROTOCOL_SET_EX_8),
('Set16Ex', PCD_PROTOCOL_SET_EX_16),
('Set32Ex', PCD_PROTOCOL_SET_EX_32),
('Set64Ex', PCD_PROTOCOL_SET_EX_64),
('SetPtrEx', PCD_PROTOCOL_SET_EX_POINTER),
('SetBoolEx', PCD_PROTOCOL_SET_EX_BOOLEAN),
('CallbackOnSet', PCD_PROTOCOL_CALLBACK_ONSET),
('CancelCallback', PCD_PROTOCOL_CANCEL_CALLBACK),
('GetNextToken', PCD_PROTOCOL_GET_NEXT_TOKEN),
('GetNextTokenSpace', PCD_PROTOCOL_GET_NEXT_TOKENSPACE)
]
@dxeapi(params = {
"SkuId" : UINT
"SkuId": UINT
})
def hook_SetSku(ql, address, params):
def hook_SetSku(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_Get8(ql, address, params):
def hook_Get8(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_Get16(ql, address, params):
def hook_Get16(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_Get32(ql, address, params):
def hook_Get32(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_Get64(ql, address, params):
def hook_Get64(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_GetPtr(ql, address, params):
def hook_GetPtr(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_GetBool(ql, address, params):
def hook_GetBool(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT
"TokenNumber": UINT
})
def hook_GetSize(ql, address, params):
def hook_GetSize(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_Get8Ex(ql, address, params):
def hook_Get8Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_Get16Ex(ql, address, params):
def hook_Get16Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_Get32Ex(ql, address, params):
def hook_Get32Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_Get64Ex(ql, address, params):
def hook_Get64Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_GetPtrEx(ql, address, params):
def hook_GetPtrEx(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_GetBoolEx(ql, address, params):
def hook_GetBoolEx(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT
"Guid": GUID,
"TokenNumber": UINT
})
def hook_GetSizeEx(ql, address, params):
def hook_GetSizeEx(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"Value" : INT
"TokenNumber": UINT,
"Value": INT
})
def hook_Set8(ql, address, params):
def hook_Set8(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"Value" : INT
"TokenNumber": UINT,
"Value": INT
})
def hook_Set16(ql, address, params):
def hook_Set16(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"Value" : INT
"TokenNumber": UINT,
"Value": INT
})
def hook_Set32(ql, address, params):
def hook_Set32(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"Value" : INT
"TokenNumber": UINT,
"Value": INT
})
def hook_Set64(ql, address, params):
def hook_Set64(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"SizeOfValue" : POINTER,
"Buffer" : POINTER
"TokenNumber": UINT,
"SizeOfValue": POINTER,
"Buffer": POINTER
})
def hook_SetPtr(ql, address, params):
def hook_SetPtr(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"TokenNumber" : UINT,
"Value" : INT
"TokenNumber": UINT,
"Value": INT
})
def hook_SetBool(ql, address, params):
def hook_SetBool(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"Value" : INT
"Guid": GUID,
"TokenNumber": UINT,
"Value": INT
})
def hook_Set8Ex(ql, address, params):
def hook_Set8Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"Value" : INT
"Guid": GUID,
"TokenNumber": UINT,
"Value": INT
})
def hook_Set16Ex(ql, address, params):
def hook_Set16Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"Value" : INT
"Guid": GUID,
"TokenNumber": UINT,
"Value": INT
})
def hook_Set32Ex(ql, address, params):
def hook_Set32Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"Value" : INT
"Guid": GUID,
"TokenNumber": UINT,
"Value": INT
})
def hook_Set64Ex(ql, address, params):
def hook_Set64Ex(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"SizeOfValue" : POINTER,
"Buffer" : POINTER
"Guid": GUID,
"TokenNumber": UINT,
"SizeOfValue": POINTER,
"Buffer": POINTER
})
def hook_SetPtrEx(ql, address, params):
def hook_SetPtrEx(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"Value" : INT
"Guid": GUID,
"TokenNumber": UINT,
"Value": INT
})
def hook_SetBoolEx(ql, address, params):
def hook_SetBoolEx(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"CallBackFunction" : POINTER
"Guid": GUID,
"TokenNumber": UINT,
"CallBackFunction": POINTER
})
def hook_CallbackOnSet(ql, address, params):
def hook_CallbackOnSet(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : UINT,
"CallBackFunction" : POINTER
"Guid": GUID,
"TokenNumber": UINT,
"CallBackFunction": POINTER
})
def hook_CancelCallback(ql, address, params):
def hook_CancelCallback(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : GUID,
"TokenNumber" : POINTER
"Guid": GUID,
"TokenNumber": POINTER
})
def hook_GetNextToken(ql, address, params):
def hook_GetNextToken(ql: Qiling, address: int, params):
pass
@dxeapi(params = {
"Guid" : POINTER
"Guid": POINTER
})
def hook_GetNextTokenSpace(ql, address, params):
def hook_GetNextTokenSpace(ql: Qiling, address: int, params):
pass
descriptor = {
"guid" : "11b34006-d85b-4d0a-a290-d5a571310ef7",
"struct" : PCD_PROTOCOL,
"fields" : (
('SetSku', hook_SetSku),
('Get8', hook_Get8),
('Get16', hook_Get16),
('Get32', hook_Get32),
('Get64', hook_Get64),
('GetPtr', hook_GetPtr),
('GetBool', hook_GetBool),
('GetSize', hook_GetSize),
('Get8Ex', hook_Get8Ex),
('Get16Ex', hook_Get16Ex),
('Get32Ex', hook_Get32Ex),
('Get64Ex', hook_Get64Ex),
('GetPtrEx', hook_GetPtrEx),
('GetBoolEx', hook_GetBoolEx),
('GetSizeEx', hook_GetSizeEx),
('Set8', hook_Set8),
('Set16', hook_Set16),
('Set32', hook_Set32),
('Set64', hook_Set64),
('SetPtr', hook_SetPtr),
('SetBool', hook_SetBool),
('Set8Ex', hook_Set8Ex),
('Set16Ex', hook_Set16Ex),
('Set32Ex', hook_Set32Ex),
('Set64Ex', hook_Set64Ex),
('SetPtrEx', hook_SetPtrEx),
('SetBoolEx', hook_SetBoolEx),
('CallbackOnSet', hook_CallbackOnSet),
('CancelCallback', hook_CancelCallback),
('GetNextToken', hook_GetNextToken),
('GetNextTokenSpace', hook_GetNextTokenSpace)
('SetSku', hook_SetSku),
('Get8', hook_Get8),
('Get16', hook_Get16),
('Get32', hook_Get32),
('Get64', hook_Get64),
('GetPtr', hook_GetPtr),
('GetBool', hook_GetBool),
('GetSize', hook_GetSize),
('Get8Ex', hook_Get8Ex),
('Get16Ex', hook_Get16Ex),
('Get32Ex', hook_Get32Ex),
('Get64Ex', hook_Get64Ex),
('GetPtrEx', hook_GetPtrEx),
('GetBoolEx', hook_GetBoolEx),
('GetSizeEx', hook_GetSizeEx),
('Set8', hook_Set8),
('Set16', hook_Set16),
('Set32', hook_Set32),
('Set64', hook_Set64),
('SetPtr', hook_SetPtr),
('SetBool', hook_SetBool),
('Set8Ex', hook_Set8Ex),
('Set16Ex', hook_Set16Ex),
('Set32Ex', hook_Set32Ex),
('Set64Ex', hook_Set64Ex),
('SetPtrEx', hook_SetPtrEx),
('SetBoolEx', hook_SetBoolEx),
('CallbackOnSet', hook_CallbackOnSet),
('CancelCallback', hook_CancelCallback),
('GetNextToken', hook_GetNextToken),
('GetNextTokenSpace', hook_GetNextTokenSpace)
)
}
+22 -17
View File
@@ -1,13 +1,18 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
from typing import TYPE_CHECKING
from qiling.os.uefi.const import EFI_SUCCESS, EFI_NOT_FOUND, EFI_UNSUPPORTED, EFI_BUFFER_TOO_SMALL, EFI_INVALID_PARAMETER
from qiling.os.uefi.utils import read_int64, write_int64
from qiling.os.uefi.UefiSpec import EFI_LOCATE_SEARCH_TYPE
def LocateHandles(context, params):
if TYPE_CHECKING:
from qiling.os.uefi.context import UefiContext
def LocateHandles(context: UefiContext, params):
SearchType = params["SearchType"]
Protocol = params["Protocol"]
@@ -24,8 +29,8 @@ def LocateHandles(context, params):
return len(handles) * context.ql.arch.pointersize, handles
def InstallProtocolInterface(context, params):
handle = read_int64(context.ql, params["Handle"])
def InstallProtocolInterface(context: UefiContext, params):
handle = context.ql.mem.read_ptr(params["Handle"])
if handle == 0:
handle = context.heap.alloc(1)
@@ -35,12 +40,12 @@ def InstallProtocolInterface(context, params):
dic[params["Protocol"]] = params["Interface"]
context.protocols[handle] = dic
write_int64(context.ql, params["Handle"], handle)
context.ql.mem.write_ptr(params["Handle"], handle)
context.notify_protocol(params['Handle'], params['Protocol'], params['Interface'], True)
return EFI_SUCCESS
def ReinstallProtocolInterface(context, params):
def ReinstallProtocolInterface(context: UefiContext, params):
handle = params["Handle"]
if handle not in context.protocols:
@@ -56,7 +61,7 @@ def ReinstallProtocolInterface(context, params):
return EFI_SUCCESS
def UninstallProtocolInterface(context, params):
def UninstallProtocolInterface(context: UefiContext, params):
handle = params["Handle"]
if handle not in context.protocols:
@@ -72,7 +77,7 @@ def UninstallProtocolInterface(context, params):
return EFI_SUCCESS
def HandleProtocol(context, params):
def HandleProtocol(context: UefiContext, params):
handle = params["Handle"]
protocol = params["Protocol"]
interface = params['Interface']
@@ -81,13 +86,13 @@ def HandleProtocol(context, params):
supported = context.protocols[handle]
if protocol in supported:
write_int64(context.ql, interface, supported[protocol])
context.ql.mem.write_ptr(interface, supported[protocol])
return EFI_SUCCESS
return EFI_UNSUPPORTED
def LocateHandle(context, params):
def LocateHandle(context: UefiContext, params):
buffer_size, handles = LocateHandles(context, params)
if len(handles) == 0:
@@ -95,20 +100,20 @@ def LocateHandle(context, params):
ret = EFI_BUFFER_TOO_SMALL
if read_int64(context.ql, params["BufferSize"]) >= buffer_size:
if context.ql.mem.read_ptr(params["BufferSize"]) >= buffer_size:
ptr = params["Buffer"]
for handle in handles:
write_int64(context.ql, ptr, handle)
context.ql.mem.write_ptr(ptr, handle)
ptr += context.ql.arch.pointersize
ret = EFI_SUCCESS
write_int64(context.ql, params["BufferSize"], buffer_size)
context.ql.mem.write_ptr(params["BufferSize"], buffer_size)
return ret
def LocateProtocol(context, params):
def LocateProtocol(context: UefiContext, params):
protocol = params['Protocol']
for handle, guid_dic in context.protocols.items():
@@ -117,12 +122,12 @@ def LocateProtocol(context, params):
if protocol in guid_dic:
# write protocol address to out variable Interface
write_int64(context.ql, params['Interface'], guid_dic[protocol])
context.ql.mem.write_ptr(params['Interface'], guid_dic[protocol])
return EFI_SUCCESS
return EFI_NOT_FOUND
def InstallConfigurationTable(context, params):
def InstallConfigurationTable(context: UefiContext, params):
guid = params["Guid"]
table = params["Table"]
+165 -103
View File
@@ -1,22 +1,30 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from __future__ import annotations
from typing import TYPE_CHECKING
import time
from qiling import Qiling
from qiling.os.const import *
from .const import *
from .utils import *
from .fncc import *
from .utils import init_struct
from .fncc import dxeapi
from .ProcessorBind import *
from .PiMultiPhase import EFI_VARIABLE
from .UefiBaseType import EFI_TIME
from .UefiSpec import *
from .UefiSpec import EFI_UNSPECIFIED_TIMEZONE, EFI_RUNTIME_SERVICES
if TYPE_CHECKING:
from qiling import Qiling
@dxeapi(params={
"Time" : POINTER, # OUT PTR(EFI_TIME)
"Capabilities" : POINTER # OUT PTR(EFI_TIME_CAPABILITIES)
"Time": POINTER, # OUT PTR(EFI_TIME)
"Capabilities": POINTER # OUT PTR(EFI_TIME_CAPABILITIES)
})
def hook_GetTime(ql: Qiling, address: int, params):
Time = params['Time']
@@ -26,126 +34,140 @@ def hook_GetTime(ql: Qiling, address: int, params):
localtime = time.localtime()
efitime = EFI_TIME()
efitime.Year = localtime.tm_year
efitime.Month = localtime.tm_mon
efitime.Day = localtime.tm_mday
efitime.Hour = localtime.tm_hour
efitime.Minute = localtime.tm_min
efitime.Second = localtime.tm_sec
efitime.Nanosecond = 0
EFI_TIME(
Year = localtime.tm_year,
Month = localtime.tm_mon,
Day = localtime.tm_mday,
Hour = localtime.tm_hour,
Minute = localtime.tm_min,
Second = localtime.tm_sec,
Nanosecond = 0,
# tz and dst settings are stored in the "RtcTimeSettings" nvram variable.
# we just use the default settings instead
efitime.TimeZone = EFI_UNSPECIFIED_TIMEZONE
efitime.Daylight = 0
efitime.saveTo(ql, Time)
# tz and dst settings are stored in the "RtcTimeSettings" nvram variable.
# we just use the default settings instead
TimeZone = EFI_UNSPECIFIED_TIMEZONE,
Daylight = 0
).save_to(ql.mem, Time)
return EFI_SUCCESS
@dxeapi(params={
"Time": POINTER # IN PTR(EFI_TIME)
"Time": POINTER # IN PTR(EFI_TIME)
})
def hook_SetTime(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"Enabled" : POINTER, # OUT PTR(BOOLEAN)
"Pending" : POINTER, # OUT PTR(BOOLEAN)
"Time" : POINTER # OUT PTR(EFI_TIME)
"Enabled": POINTER, # OUT PTR(BOOLEAN)
"Pending": POINTER, # OUT PTR(BOOLEAN)
"Time": POINTER # OUT PTR(EFI_TIME)
})
def hook_GetWakeupTime(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"Enable": BOOL, # BOOLEAN
"Time" : POINTER # PTR(EFI_TIME)
"Enable": BOOL, # BOOLEAN
"Time": POINTER # PTR(EFI_TIME)
})
def hook_SetWakeupTime(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"MemoryMapSize" : UINT, # UINTN
"DescriptorSize" : UINT, # UINTN
"DescriptorVersion" : UINT, # UINT32
"VirtualMap" : POINTER # PTR(EFI_MEMORY_DESCRIPTOR)
"MemoryMapSize": UINT, # UINTN
"DescriptorSize": UINT, # UINTN
"DescriptorVersion": UINT, # UINT32
"VirtualMap": POINTER # PTR(EFI_MEMORY_DESCRIPTOR)
})
def hook_SetVirtualAddressMap(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"DebugDisposition" : UINT, # UINTN
"Address" : POINTER # OUT PTR(PTR(VOID))
"DebugDisposition": UINT, # UINTN
"Address": POINTER # OUT PTR(PTR(VOID))
})
def hook_ConvertPointer(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"VariableName" : WSTRING, # PTR(CHAR16)
"VendorGuid" : GUID, # PTR(EFI_GUID)
"Attributes" : POINTER, # OUT PTR(UINT32)
"DataSize" : POINTER, # IN OUT PTR(UINTN)
"Data" : POINTER # OUT PTR(VOID)
"VariableName": WSTRING, # PTR(CHAR16)
"VendorGuid": GUID, # PTR(EFI_GUID)
"Attributes": POINTER, # OUT PTR(UINT32)
"DataSize": POINTER, # IN OUT PTR(UINTN)
"Data": POINTER # OUT PTR(VOID)
})
def hook_GetVariable(ql: Qiling, address: int, params):
name = params['VariableName']
var_name = params["VariableName"]
vendor_guid = params["VendorGuid"]
attr_ptr = params["Attributes"]
data_size_ptr = params["DataSize"]
data_ptr = params["Data"]
if name in ql.env:
var = ql.env[name]
read_len = read_int64(ql, params['DataSize'])
if (not var_name) or (not vendor_guid) or (not data_size_ptr):
return EFI_INVALID_PARAMETER
if params['Attributes'] != 0:
write_int64(ql, params['Attributes'], 0)
if var_name not in ql.env:
return EFI_NOT_FOUND
write_int64(ql, params['DataSize'], len(var))
var_data = ql.env[var_name]
data_size = len(var_data)
buff_size = ql.mem.read_ptr(data_size_ptr)
if read_len < len(var):
return EFI_BUFFER_TOO_SMALL
if attr_ptr:
# FIXME: until we manage variables with their attributes, provide a default set
attributes = (
EFI_VARIABLE.NON_VOLATILE |
EFI_VARIABLE.BOOTSERVICE_ACCESS |
EFI_VARIABLE.RUNTIME_ACCESS
)
if params['Data'] != 0:
ql.mem.write(params['Data'], var)
ql.mem.write_ptr(attr_ptr, attributes, 4)
return EFI_SUCCESS
ql.mem.write_ptr(data_size_ptr, data_size)
ql.log.warning(f'variable with name {name} not found')
if buff_size < data_size:
return EFI_BUFFER_TOO_SMALL
if data_ptr:
ql.mem.write(data_ptr, var_data)
return EFI_SUCCESS
return EFI_NOT_FOUND
@dxeapi(params={
"VariableNameSize" : POINTER, # IN OUT PTR(UINTN)
"VariableName" : POINTER, # IN OUT PTR(CHAR16)
"VendorGuid" : GUID # IN OUT PTR(EFI_GUID)
"VariableNameSize": POINTER, # IN OUT PTR(UINTN)
"VariableName": POINTER, # IN OUT PTR(CHAR16)
"VendorGuid": GUID # IN OUT PTR(EFI_GUID)
})
def hook_GetNextVariableName(ql: Qiling, address: int, params):
var_name_size = params["VariableNameSize"]
var_name = params["VariableName"]
vendor_guid = params["VendorGuid"]
if (var_name_size == 0) or (var_name == 0):
if (not var_name_size) or (not var_name) or (not vendor_guid):
return EFI_INVALID_PARAMETER
name_size = read_int64(ql, var_name_size)
last_name = ql.os.utils.read_wstring(var_name)
name_size = ql.mem.read_ptr(var_name_size)
last_name = ql.os.utils.read_wstring(var_name, name_size)
vars = ql.env['Names'] # This is a list of variable names in correct order.
nvvars = ql.env['Names'] # This is a list of variable names in correct order.
if last_name not in vars:
if last_name not in nvvars:
return EFI_NOT_FOUND
idx = vars.index(last_name)
idx = nvvars.index(last_name)
# make sure it is not the last one (i.e. we have a next one to pull)
if idx == len(vars) - 1:
if idx == len(nvvars) - 1:
return EFI_NOT_FOUND
# get next var name, and add null terminator
new_name = vars[idx + 1] + '\x00'
new_name = nvvars[idx + 1] + '\x00'
# turn it into a wide string
new_name = ''.join(f'{c}\x00' for c in new_name)
if len(new_name) > name_size:
write_int64(ql, var_name_size, len(new_name))
ql.mem.write_ptr(var_name_size, len(new_name))
return EFI_BUFFER_TOO_SMALL
ql.mem.write(var_name, new_name.encode('ascii'))
@@ -153,14 +175,52 @@ def hook_GetNextVariableName(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"VariableName" : WSTRING, # PTR(CHAR16)
"VendorGuid" : GUID, # PTR(EFI_GUID)
"Attributes" : UINT, # UINT32
"DataSize" : UINT, # UINTN
"Data" : POINTER # PTR(VOID)
"VariableName": WSTRING, # PTR(CHAR16)
"VendorGuid": GUID, # PTR(EFI_GUID)
"Attributes": UINT, # UINT32
"DataSize": UINT, # UINTN
"Data": POINTER # PTR(VOID)
})
def hook_SetVariable(ql: Qiling, address: int, params):
ql.env[params['VariableName']] = bytes(ql.mem.read(params['Data'], params['DataSize']))
var_name = params["VariableName"]
vendor_guid = params["VendorGuid"]
attributes = params["Attributes"]
data_size = params["DataSize"]
data_ptr = params["Data"]
if not var_name:
return EFI_INVALID_PARAMETER
# deprecated
if attributes & EFI_VARIABLE.AUTHENTICATED_WRITE_ACCESS:
return EFI_UNSUPPORTED
append = attributes & EFI_VARIABLE.APPEND_WRITE
auth = attributes & (
EFI_VARIABLE.TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE.ENHANCED_AUTHENTICATED_ACCESS
)
# TODO: manage variables with namespaces (guids)
# TODO: manage variables according to their access attributes
# when data size is set to zero and this is not auth or append access, delete the var
if data_size == 0 and not (auth or append):
if var_name not in ql.env:
return EFI_NOT_FOUND
del ql.env[var_name]
data = bytes(ql.mem.read(data_ptr, data_size))
if append:
if var_name not in ql.env:
return EFI_NOT_FOUND
data = ql.env[var_name] + data
ql.env[var_name] = data
return EFI_SUCCESS
@dxeapi(params={
@@ -170,14 +230,16 @@ def hook_GetNextHighMonotonicCount(ql: Qiling, address: int, params):
ql.os.monotonic_count += 0x0000000100000000
hmc = ql.os.monotonic_count
hmc = (hmc >> 32) & 0xffffffff
write_int32(ql, params["HighCount"], hmc)
ql.mem.write_ptr(params["HighCount"], hmc, 4)
return EFI_SUCCESS
@dxeapi(params={
"ResetType" : INT, # EFI_RESET_TYPE
"ResetStatus" : INT, # EFI_STATUS
"DataSize" : UINT, # UINTN
"ResetData" : POINTER # PTR(VOID)
"ResetType": INT, # EFI_RESET_TYPE
"ResetStatus": INT, # EFI_STATUS
"DataSize": UINT, # UINTN
"ResetData": POINTER # PTR(VOID)
})
def hook_ResetSystem(ql: Qiling, address: int, params):
ql.emu_stop()
@@ -185,27 +247,27 @@ def hook_ResetSystem(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER))
"CapsuleCount" : UINT, # UINTN
"ScatterGatherList" : ULONGLONG # EFI_PHYSICAL_ADDRESS
"CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER))
"CapsuleCount": UINT, # UINTN
"ScatterGatherList": ULONGLONG # EFI_PHYSICAL_ADDRESS
})
def hook_UpdateCapsule(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER))
"CapsuleCount" : UINT, # UINTN
"MaximumCapsuleSize": POINTER, # OUT PTR(UINT64)
"ResetType" : POINTER # OUT PTR(EFI_RESET_TYPE)
"CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER))
"CapsuleCount": UINT, # UINTN
"MaximumCapsuleSize": POINTER, # OUT PTR(UINT64)
"ResetType": POINTER # OUT PTR(EFI_RESET_TYPE)
})
def hook_QueryCapsuleCapabilities(ql: Qiling, address: int, params):
return EFI_SUCCESS
@dxeapi(params={
"Attributes" : UINT, # UINT32
"MaximumVariableStorageSize" : POINTER, # OUT PTR(UINT64)
"RemainingVariableStorageSize" : POINTER, # OUT PTR(UINT64)
"MaximumVariableSize" : POINTER # OUT PTR(UINT64)
"Attributes": UINT, # UINT32
"MaximumVariableStorageSize": POINTER, # OUT PTR(UINT64)
"RemainingVariableStorageSize": POINTER, # OUT PTR(UINT64)
"MaximumVariableSize": POINTER # OUT PTR(UINT64)
})
def hook_QueryVariableInfo(ql: Qiling, address: int, params):
return EFI_SUCCESS
@@ -214,27 +276,27 @@ def initialize(ql: Qiling, gRT: int):
descriptor = {
'struct' : EFI_RUNTIME_SERVICES,
'fields' : (
('Hdr', None),
('GetTime', hook_GetTime),
('SetTime', hook_SetTime),
('GetWakeupTime', hook_GetWakeupTime),
('SetWakeupTime', hook_SetWakeupTime),
('SetVirtualAddressMap', hook_SetVirtualAddressMap),
('ConvertPointer', hook_ConvertPointer),
('GetVariable', hook_GetVariable),
('GetNextVariableName', hook_GetNextVariableName),
('SetVariable', hook_SetVariable),
('GetNextHighMonotonicCount', hook_GetNextHighMonotonicCount),
('ResetSystem', hook_ResetSystem),
('UpdateCapsule', hook_UpdateCapsule),
('QueryCapsuleCapabilities', hook_QueryCapsuleCapabilities),
('QueryVariableInfo', hook_QueryVariableInfo)
('Hdr', None),
('GetTime', hook_GetTime),
('SetTime', hook_SetTime),
('GetWakeupTime', hook_GetWakeupTime),
('SetWakeupTime', hook_SetWakeupTime),
('SetVirtualAddressMap', hook_SetVirtualAddressMap),
('ConvertPointer', hook_ConvertPointer),
('GetVariable', hook_GetVariable),
('GetNextVariableName', hook_GetNextVariableName),
('SetVariable', hook_SetVariable),
('GetNextHighMonotonicCount', hook_GetNextHighMonotonicCount),
('ResetSystem', hook_ResetSystem),
('UpdateCapsule', hook_UpdateCapsule),
('QueryCapsuleCapabilities', hook_QueryCapsuleCapabilities),
('QueryVariableInfo', hook_QueryVariableInfo)
)
}
instance = init_struct(ql, gRT, descriptor)
instance.saveTo(ql, gRT)
instance.save_to(ql.mem, gRT)
__all__ = [
'initialize'
]
]
+53 -54
View File
@@ -8,7 +8,6 @@ from unicorn.x86_const import *
from qiling import Qiling
from qiling.os.const import POINTER
from qiling.os.memory import QlMemoryHeap
from qiling.os.uefi import utils
from qiling.os.uefi.context import SmmContext
from qiling.os.uefi.protocols.EfiSmmCpuProtocol import EFI_SMM_SAVE_STATE_REGISTER
from qiling.os.uefi.protocols.EfiSmmSwDispatch2Protocol import EFI_SMM_SW_REGISTER_CONTEXT, EFI_SMM_SW_CONTEXT
@@ -19,46 +18,46 @@ class SaveStateArea:
#
# see: Intel SDM vol. 3 chapter 30.4.1.1
offsets = {
EFI_SMM_SAVE_STATE_REGISTER.GDTBASE : 0x7E8C,
EFI_SMM_SAVE_STATE_REGISTER.IDTBASE : 0x7E94,
EFI_SMM_SAVE_STATE_REGISTER.LDTBASE : 0x7E9C,
EFI_SMM_SAVE_STATE_REGISTER.GDTBASE: 0x7E8C,
EFI_SMM_SAVE_STATE_REGISTER.IDTBASE: 0x7E94,
EFI_SMM_SAVE_STATE_REGISTER.LDTBASE: 0x7E9C,
EFI_SMM_SAVE_STATE_REGISTER.GDTLIMIT: 0x7DD0,
EFI_SMM_SAVE_STATE_REGISTER.IDTLIMIT: 0x7DD8,
EFI_SMM_SAVE_STATE_REGISTER.LDTLIMIT: 0x7DD4,
# EFI_SMM_SAVE_STATE_REGISTER.LDTINFO : ?,
# EFI_SMM_SAVE_STATE_REGISTER.LDTINFO: ?,
EFI_SMM_SAVE_STATE_REGISTER.ES : 0x7FA8,
EFI_SMM_SAVE_STATE_REGISTER.CS : 0x7FAC,
EFI_SMM_SAVE_STATE_REGISTER.SS : 0x7FB0,
EFI_SMM_SAVE_STATE_REGISTER.DS : 0x7FB4,
EFI_SMM_SAVE_STATE_REGISTER.FS : 0x7FB8,
EFI_SMM_SAVE_STATE_REGISTER.GS : 0x7FBC,
EFI_SMM_SAVE_STATE_REGISTER.ES: 0x7FA8,
EFI_SMM_SAVE_STATE_REGISTER.CS: 0x7FAC,
EFI_SMM_SAVE_STATE_REGISTER.SS: 0x7FB0,
EFI_SMM_SAVE_STATE_REGISTER.DS: 0x7FB4,
EFI_SMM_SAVE_STATE_REGISTER.FS: 0x7FB8,
EFI_SMM_SAVE_STATE_REGISTER.GS: 0x7FBC,
EFI_SMM_SAVE_STATE_REGISTER.LDTR_SEL: 0x7FC0,
EFI_SMM_SAVE_STATE_REGISTER.TR_SEL : 0x7FC4,
EFI_SMM_SAVE_STATE_REGISTER.DR7 : 0x7FC8,
EFI_SMM_SAVE_STATE_REGISTER.DR6 : 0x7FD0,
EFI_SMM_SAVE_STATE_REGISTER.R8 : 0x7F54,
EFI_SMM_SAVE_STATE_REGISTER.R9 : 0x7F4C,
EFI_SMM_SAVE_STATE_REGISTER.R10 : 0x7F44,
EFI_SMM_SAVE_STATE_REGISTER.R11 : 0x7F3C,
EFI_SMM_SAVE_STATE_REGISTER.R12 : 0x7F34,
EFI_SMM_SAVE_STATE_REGISTER.R13 : 0x7F2C,
EFI_SMM_SAVE_STATE_REGISTER.R14 : 0x7F24,
EFI_SMM_SAVE_STATE_REGISTER.R15 : 0x7F1C,
EFI_SMM_SAVE_STATE_REGISTER.RAX : 0x7F5C,
EFI_SMM_SAVE_STATE_REGISTER.RBX : 0x7F74,
EFI_SMM_SAVE_STATE_REGISTER.RCX : 0x7F64,
EFI_SMM_SAVE_STATE_REGISTER.RDX : 0x7F6C,
EFI_SMM_SAVE_STATE_REGISTER.RSP : 0x7F7C,
EFI_SMM_SAVE_STATE_REGISTER.RBP : 0x7F84,
EFI_SMM_SAVE_STATE_REGISTER.RSI : 0x7F8C,
EFI_SMM_SAVE_STATE_REGISTER.RDI : 0x7F94,
EFI_SMM_SAVE_STATE_REGISTER.RIP : 0x7FD8,
EFI_SMM_SAVE_STATE_REGISTER.TR_SEL: 0x7FC4,
EFI_SMM_SAVE_STATE_REGISTER.DR7: 0x7FC8,
EFI_SMM_SAVE_STATE_REGISTER.DR6: 0x7FD0,
EFI_SMM_SAVE_STATE_REGISTER.R8: 0x7F54,
EFI_SMM_SAVE_STATE_REGISTER.R9: 0x7F4C,
EFI_SMM_SAVE_STATE_REGISTER.R10: 0x7F44,
EFI_SMM_SAVE_STATE_REGISTER.R11: 0x7F3C,
EFI_SMM_SAVE_STATE_REGISTER.R12: 0x7F34,
EFI_SMM_SAVE_STATE_REGISTER.R13: 0x7F2C,
EFI_SMM_SAVE_STATE_REGISTER.R14: 0x7F24,
EFI_SMM_SAVE_STATE_REGISTER.R15: 0x7F1C,
EFI_SMM_SAVE_STATE_REGISTER.RAX: 0x7F5C,
EFI_SMM_SAVE_STATE_REGISTER.RBX: 0x7F74,
EFI_SMM_SAVE_STATE_REGISTER.RCX: 0x7F64,
EFI_SMM_SAVE_STATE_REGISTER.RDX: 0x7F6C,
EFI_SMM_SAVE_STATE_REGISTER.RSP: 0x7F7C,
EFI_SMM_SAVE_STATE_REGISTER.RBP: 0x7F84,
EFI_SMM_SAVE_STATE_REGISTER.RSI: 0x7F8C,
EFI_SMM_SAVE_STATE_REGISTER.RDI: 0x7F94,
EFI_SMM_SAVE_STATE_REGISTER.RIP: 0x7FD8,
EFI_SMM_SAVE_STATE_REGISTER.RFLAGS : 0x7FE8,
EFI_SMM_SAVE_STATE_REGISTER.CR0 : 0x7FF8,
EFI_SMM_SAVE_STATE_REGISTER.CR3 : 0x7FF0,
EFI_SMM_SAVE_STATE_REGISTER.CR4 : 0x7E40
EFI_SMM_SAVE_STATE_REGISTER.RFLAGS: 0x7FE8,
EFI_SMM_SAVE_STATE_REGISTER.CR0: 0x7FF8,
EFI_SMM_SAVE_STATE_REGISTER.CR3: 0x7FF0,
EFI_SMM_SAVE_STATE_REGISTER.CR4: 0x7E40
}
def __init__(self, ql: Qiling):
@@ -89,14 +88,14 @@ class SaveStateArea:
class SmmEnv:
SSA_REG_MAP = {
UC_X86_REG_ES : (4, EFI_SMM_SAVE_STATE_REGISTER.ES),
UC_X86_REG_CS : (4, EFI_SMM_SAVE_STATE_REGISTER.CS),
UC_X86_REG_SS : (4, EFI_SMM_SAVE_STATE_REGISTER.SS),
UC_X86_REG_DS : (4, EFI_SMM_SAVE_STATE_REGISTER.DS),
UC_X86_REG_FS : (4, EFI_SMM_SAVE_STATE_REGISTER.FS),
UC_X86_REG_GS : (4, EFI_SMM_SAVE_STATE_REGISTER.GS),
UC_X86_REG_R8 : (8, EFI_SMM_SAVE_STATE_REGISTER.R8),
UC_X86_REG_R9 : (8, EFI_SMM_SAVE_STATE_REGISTER.R9),
UC_X86_REG_ES : (4, EFI_SMM_SAVE_STATE_REGISTER.ES),
UC_X86_REG_CS : (4, EFI_SMM_SAVE_STATE_REGISTER.CS),
UC_X86_REG_SS : (4, EFI_SMM_SAVE_STATE_REGISTER.SS),
UC_X86_REG_DS : (4, EFI_SMM_SAVE_STATE_REGISTER.DS),
UC_X86_REG_FS : (4, EFI_SMM_SAVE_STATE_REGISTER.FS),
UC_X86_REG_GS : (4, EFI_SMM_SAVE_STATE_REGISTER.GS),
UC_X86_REG_R8 : (8, EFI_SMM_SAVE_STATE_REGISTER.R8),
UC_X86_REG_R9 : (8, EFI_SMM_SAVE_STATE_REGISTER.R9),
UC_X86_REG_R10 : (8, EFI_SMM_SAVE_STATE_REGISTER.R10),
UC_X86_REG_R11 : (8, EFI_SMM_SAVE_STATE_REGISTER.R11),
UC_X86_REG_R12 : (8, EFI_SMM_SAVE_STATE_REGISTER.R12),
@@ -214,23 +213,23 @@ class SmmEnv:
self.enter()
DispatchHandle = args['DispatchHandle']
Context = heap.alloc(EFI_SMM_SW_REGISTER_CONTEXT.sizeof())
CommBuffer = heap.alloc(EFI_SMM_SW_CONTEXT.sizeof())
CommBufferSize = heap.alloc(ql.arch.pointersize)
DispatchHandle = args['DispatchHandle']
Context = heap.alloc(EFI_SMM_SW_REGISTER_CONTEXT.sizeof())
CommBuffer = heap.alloc(EFI_SMM_SW_CONTEXT.sizeof())
CommBufferSize = heap.alloc(ql.arch.pointersize)
# setup Context
args['RegisterContext'].saveTo(ql, Context)
args['RegisterContext'].save_to(ql.mem, Context)
# setup CommBuffer
SmmSwContext = EFI_SMM_SW_CONTEXT()
SmmSwContext.SwSmiCpuIndex = cpu
SmmSwContext.CommandPort = idx
SmmSwContext.DataPort = 0
SmmSwContext.saveTo(ql, CommBuffer)
EFI_SMM_SW_CONTEXT(
SwSmiCpuIndex = cpu,
CommandPort = idx,
DataPort = 0
).save_to(ql.mem, CommBuffer)
# setup CommBufferSize
utils.ptr_write64(ql, CommBufferSize, SmmSwContext.sizeof())
ql.mem.write_ptr(CommBufferSize, EFI_SMM_SW_CONTEXT.sizeof(), 8)
# clean up handler resources
def __cleanup(ql: Qiling):
+117 -109
View File
@@ -1,21 +1,27 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from qiling.const import *
from qiling.os.const import *
from __future__ import annotations
from typing import TYPE_CHECKING
from qiling.os.const import GUID, POINTER, INT, ULONGLONG
from qiling.os.uefi.const import EFI_SUCCESS, EFI_NOT_FOUND, EFI_OUT_OF_RESOURCES, EFI_INVALID_PARAMETER
from qiling.os.uefi.utils import *
from qiling.os.uefi.fncc import *
from qiling.os.uefi.utils import init_struct, install_configuration_table
from qiling.os.uefi.fncc import dxeapi
from qiling.os.uefi.ProcessorBind import *
from qiling.os.uefi.UefiBaseType import *
from qiling.os.uefi.UefiMultiPhase import *
from qiling.os.uefi.UefiSpec import *
from qiling.os.uefi.UefiSpec import EFI_ALLOCATE_TYPE, EFI_CONFIGURATION_TABLE, EFI_INTERFACE_TYPE, EFI_LOCATE_SEARCH_TYPE, EFI_RUNTIME_SERVICES
from qiling.os.uefi.protocols import common
from qiling.os.uefi import rt
if TYPE_CHECKING:
from qiling import Qiling
# @see: MdePkg\Include\Pi\PiSmmCis.h
class EFI_MM_IO_WIDTH(ENUM):
@@ -33,14 +39,14 @@ class EFI_MM_IO_ACCESS(STRUCT):
EFI_SMM_CPU_IO2_PROTOCOL = STRUCT
_fields_ = [
('Read', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))),
('Write', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))),
('Read', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))),
('Write', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))),
]
class EFI_SMM_CPU_IO2_PROTOCOL(STRUCT):
_fields_ = [
('Mem', EFI_MM_IO_ACCESS),
('Io', EFI_MM_IO_ACCESS)
('Mem', EFI_MM_IO_ACCESS),
('Io', EFI_MM_IO_ACCESS)
]
class EFI_SMM_SYSTEM_TABLE2(STRUCT):
@@ -48,51 +54,51 @@ class EFI_SMM_SYSTEM_TABLE2(STRUCT):
_pack_ = 8
_fields_ = [
('Hdr', EFI_TABLE_HEADER),
('SmmFirmwareVendor', PTR(CHAR16)),
('SmmFirmwareRevision', UINT32),
('SmmInstallConfigurationTable', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SYSTEM_TABLE2), PTR(EFI_GUID), PTR(VOID), UINTN)),
('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL),
('SmmAllocatePool', FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))),
('SmmFreePool', FUNCPTR(EFI_STATUS, PTR(VOID))),
('SmmAllocatePages', FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))),
('SmmFreePages', FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)),
('SmmStartupThisAp', FUNCPTR(EFI_STATUS, FUNCPTR(VOID, PTR(VOID)), UINTN, PTR(VOID))),
('CurrentlyExecutingCpu', UINTN),
('NumberOfCpus', UINTN),
('CpuSaveStateSize', PTR(UINTN)),
('CpuSaveState', PTR(PTR(VOID))),
('NumberOfTableEntries', UINTN),
('SmmConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)),
('SmmInstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))),
('SmmUninstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(VOID))),
('SmmHandleProtocol', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(PTR(VOID)))),
('SmmRegisterProtocolNotify', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_MM_NOTIFY_FN, PTR(PTR(VOID)))),
('SmmLocateHandle', FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))),
('SmmLocateProtocol', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))),
('SmiManage', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(VOID), PTR(UINTN))),
('SmiHandlerRegister', FUNCPTR(EFI_STATUS, EFI_MM_HANDLER_ENTRY_POINT, PTR(EFI_GUID), PTR(EFI_HANDLE))),
('SmiHandlerUnRegister', FUNCPTR(EFI_STATUS, EFI_HANDLE)),
('Hdr', EFI_TABLE_HEADER),
('SmmFirmwareVendor', PTR(CHAR16)),
('SmmFirmwareRevision', UINT32),
('SmmInstallConfigurationTable', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SYSTEM_TABLE2), PTR(EFI_GUID), PTR(VOID), UINTN)),
('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL),
('SmmAllocatePool', FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))),
('SmmFreePool', FUNCPTR(EFI_STATUS, PTR(VOID))),
('SmmAllocatePages', FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))),
('SmmFreePages', FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)),
('SmmStartupThisAp', FUNCPTR(EFI_STATUS, FUNCPTR(VOID, PTR(VOID)), UINTN, PTR(VOID))),
('CurrentlyExecutingCpu', UINTN),
('NumberOfCpus', UINTN),
('CpuSaveStateSize', PTR(UINTN)),
('CpuSaveState', PTR(PTR(VOID))),
('NumberOfTableEntries', UINTN),
('SmmConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)),
('SmmInstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))),
('SmmUninstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(VOID))),
('SmmHandleProtocol', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(PTR(VOID)))),
('SmmRegisterProtocolNotify', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_MM_NOTIFY_FN, PTR(PTR(VOID)))),
('SmmLocateHandle', FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))),
('SmmLocateProtocol', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))),
('SmiManage', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(VOID), PTR(UINTN))),
('SmiHandlerRegister', FUNCPTR(EFI_STATUS, EFI_MM_HANDLER_ENTRY_POINT, PTR(EFI_GUID), PTR(EFI_HANDLE))),
('SmiHandlerUnRegister', FUNCPTR(EFI_STATUS, EFI_HANDLE)),
]
@dxeapi(params = {
"Guid" : GUID, # PTR(EFI_GUID)
"Table" : POINTER # PTR(VOID)
"Guid": GUID, # PTR(EFI_GUID)
"Table": POINTER # PTR(VOID)
})
def hook_SmmInstallConfigurationTable(ql: Qiling, address: int, params):
return common.InstallConfigurationTable(ql.loader.smm_context, params)
@dxeapi(params = {
"type" : INT, # EFI_ALLOCATE_TYPE
"MemoryType": INT, # EFI_MEMORY_TYPE
"Pages" : ULONGLONG, # UINTN
"Memory" : POINTER # PTR(EFI_PHYSICAL_ADDRESS)
"type": INT, # EFI_ALLOCATE_TYPE
"MemoryType": INT, # EFI_MEMORY_TYPE
"Pages": ULONGLONG, # UINTN
"Memory": POINTER # PTR(EFI_PHYSICAL_ADDRESS)
})
def hook_SmmAllocatePages(ql: Qiling, address: int, params):
alloc_size = params["Pages"] * PAGE_SIZE
if params['type'] == EFI_ALLOCATE_TYPE.AllocateAddress:
address = read_int64(ql, params["Memory"])
address = ql.mem.read_ptr(params["Memory"])
# TODO: check the range [address, address + alloc_size] is available first
ql.mem.map(address, alloc_size)
@@ -103,13 +109,13 @@ def hook_SmmAllocatePages(ql: Qiling, address: int, params):
if address == 0:
return EFI_OUT_OF_RESOURCES
write_int64(ql, params["Memory"], address)
ql.mem.write_ptr(params["Memory"], address)
return EFI_SUCCESS
@dxeapi(params = {
"Memory" : ULONGLONG, # EFI_PHYSICAL_ADDRESS
"Pages" : ULONGLONG # UINTN
"Memory": ULONGLONG, # EFI_PHYSICAL_ADDRESS
"Pages": ULONGLONG # UINTN
})
def hook_SmmFreePages(ql: Qiling, address: int, params):
address = params["Memory"]
@@ -119,19 +125,19 @@ def hook_SmmFreePages(ql: Qiling, address: int, params):
return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER
@dxeapi(params = {
"PoolType" : INT, # EFI_MEMORY_TYPE
"Size" : INT, # UINTN
"Buffer" : POINTER # PTR(PTR(VOID))
"PoolType": INT, # EFI_MEMORY_TYPE
"Size": INT, # UINTN
"Buffer": POINTER # PTR(PTR(VOID))
})
def hook_SmmAllocatePool(ql: Qiling, address: int, params):
# TODO: allocate memory acording to "PoolType"
address = ql.loader.smm_context.heap.alloc(params["Size"])
write_int64(ql, params["Buffer"], address)
ql.mem.write_ptr(params["Buffer"], address)
return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES
@dxeapi(params = {
"Buffer": POINTER # PTR(VOID)
"Buffer": POINTER # PTR(VOID)
})
def hook_SmmFreePool(ql: Qiling, address: int, params):
address = params["Buffer"]
@@ -140,85 +146,87 @@ def hook_SmmFreePool(ql: Qiling, address: int, params):
return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER
@dxeapi(params = {
"Procedure" : POINTER,
"CpuNumber" : INT,
"ProcArguments" : POINTER
"Procedure": POINTER,
"CpuNumber": INT,
"ProcArguments": POINTER
})
def hook_SmmStartupThisAp(ql: Qiling, address: int, params):
return EFI_INVALID_PARAMETER
@dxeapi(params = {
"Handle" : POINTER, # PTR(EFI_HANDLE)
"Protocol" : GUID, # PTR(EFI_GUID)
"InterfaceType" : ULONGLONG, # EFI_INTERFACE_TYPE
"Interface" : POINTER, # PTR(VOID)
"Handle": POINTER, # PTR(EFI_HANDLE)
"Protocol": GUID, # PTR(EFI_GUID)
"InterfaceType": ULONGLONG, # EFI_INTERFACE_TYPE
"Interface": POINTER, # PTR(VOID)
})
def hook_SmmInstallProtocolInterface(ql: Qiling, address: int, params):
return common.InstallProtocolInterface(ql.loader.smm_context, params)
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"Interface" : POINTER # PTR(VOID)
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"Interface": POINTER # PTR(VOID)
})
def hook_SmmUninstallProtocolInterface(ql: Qiling, address: int, params):
return common.UninstallProtocolInterface(ql.loader.smm_context, params)
@dxeapi(params = {
"Handle" : POINTER, # EFI_HANDLE
"Protocol" : GUID, # PTR(EFI_GUID)
"Interface" : POINTER # PTR(PTR(VOID))
"Handle": POINTER, # EFI_HANDLE
"Protocol": GUID, # PTR(EFI_GUID)
"Interface": POINTER # PTR(PTR(VOID))
})
def hook_SmmHandleProtocol(ql: Qiling, address: int, params):
return common.HandleProtocol(ql.loader.smm_context, params)
@dxeapi(params = {
"Protocol" : GUID, # PTR(EFI_GUID)
"Function" : POINTER, # EFI_MM_NOTIFY_FN
"Registration" : POINTER # PTR(PTR(VOID))
"Protocol": GUID, # PTR(EFI_GUID)
"Function": POINTER, # EFI_MM_NOTIFY_FN
"Registration": POINTER # PTR(PTR(VOID))
})
def hook_SmmRegisterProtocolNotify(ql: Qiling, address: int, params):
event_id = len(ql.loader.events)
event_dic = {
"NotifyFunction": params["Function"],
"CallbackArgs" : None,
"Guid" : params["Protocol"],
"Set" : False
"CallbackArgs": None,
"Guid": params["Protocol"],
"Set": False
}
ql.loader.events[event_id] = event_dic
ptr_write64(ql, params["Registration"], event_id)
ql.mem.write_ptr(params["Registration"], event_id, 8)
return EFI_SUCCESS
@dxeapi(params = {
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol" : GUID, # PTR(EFI_GUID)
"SearchKey" : POINTER, # PTR(VOID)
"BufferSize": POINTER, # PTR(UINTN)
"Buffer" : POINTER # PTR(EFI_HANDLE)
"SearchType": INT, # EFI_LOCATE_SEARCH_TYPE
"Protocol": GUID, # PTR(EFI_GUID)
"SearchKey": POINTER, # PTR(VOID)
"BufferSize": POINTER, # PTR(UINTN)
"Buffer": POINTER # PTR(EFI_HANDLE)
})
def hook_SmmLocateHandle(ql: Qiling, address: int, params):
return common.LocateHandle(ql.loader.smm_context, params)
@dxeapi(params = {
"Protocol" : GUID, # PTR(EFI_GUID)
"Registration" : POINTER, # PTR(VOID)
"Interface" : POINTER # PTR(PTR(VOID))
"Protocol": GUID, # PTR(EFI_GUID)
"Registration": POINTER, # PTR(VOID)
"Interface": POINTER # PTR(PTR(VOID))
})
def hook_SmmLocateProtocol(ql: Qiling, address: int, params):
return common.LocateProtocol(ql.loader.smm_context, params)
@dxeapi(params = {
"HandlerType" : GUID,
"Context" : POINTER,
"CommBuffer" : POINTER,
"HandlerType": GUID,
"Context": POINTER,
"CommBuffer": POINTER,
"CommBufferSize": POINTER
})
def hook_SmiManage(ql: Qiling, address: int, params):
return EFI_NOT_FOUND
@dxeapi(params = {
"Handler" : POINTER,
"HandlerType" : GUID,
"Handler": POINTER,
"HandlerType": GUID,
"DispatchHandle": POINTER
})
def hook_SmiHandlerRegister(ql: Qiling, address: int, params):
@@ -241,36 +249,36 @@ def initialize(ql: Qiling, context, gSmst: int):
descriptor = {
'struct' : EFI_SMM_SYSTEM_TABLE2,
'fields' : (
('Hdr', None),
('SmmFirmwareVendor', None),
('SmmFirmwareRevision', None),
('SmmInstallConfigurationTable', hook_SmmInstallConfigurationTable),
('SmmIo', None),
('SmmAllocatePool', hook_SmmAllocatePool),
('SmmFreePool', hook_SmmFreePool),
('SmmAllocatePages', hook_SmmAllocatePages),
('SmmFreePages', hook_SmmFreePages),
('SmmStartupThisAp', hook_SmmStartupThisAp),
('CurrentlyExecutingCpu', None),
('NumberOfCpus', None),
('CpuSaveStateSize', None),
('CpuSaveState', None),
('NumberOfTableEntries', 0),
('SmmConfigurationTable', cfg),
('SmmInstallProtocolInterface', hook_SmmInstallProtocolInterface),
('SmmUninstallProtocolInterface', hook_SmmUninstallProtocolInterface),
('SmmHandleProtocol', hook_SmmHandleProtocol),
('SmmRegisterProtocolNotify', hook_SmmRegisterProtocolNotify),
('SmmLocateHandle', hook_SmmLocateHandle),
('SmmLocateProtocol', hook_SmmLocateProtocol),
('SmiManage', hook_SmiManage),
('SmiHandlerRegister', hook_SmiHandlerRegister),
('SmiHandlerUnRegister', hook_SmiHandlerUnRegister),
('Hdr', None),
('SmmFirmwareVendor', None),
('SmmFirmwareRevision', None),
('SmmInstallConfigurationTable', hook_SmmInstallConfigurationTable),
('SmmIo', None),
('SmmAllocatePool', hook_SmmAllocatePool),
('SmmFreePool', hook_SmmFreePool),
('SmmAllocatePages', hook_SmmAllocatePages),
('SmmFreePages', hook_SmmFreePages),
('SmmStartupThisAp', hook_SmmStartupThisAp),
('CurrentlyExecutingCpu', None),
('NumberOfCpus', None),
('CpuSaveStateSize', None),
('CpuSaveState', None),
('NumberOfTableEntries', 0),
('SmmConfigurationTable', cfg),
('SmmInstallProtocolInterface', hook_SmmInstallProtocolInterface),
('SmmUninstallProtocolInterface', hook_SmmUninstallProtocolInterface),
('SmmHandleProtocol', hook_SmmHandleProtocol),
('SmmRegisterProtocolNotify', hook_SmmRegisterProtocolNotify),
('SmmLocateHandle', hook_SmmLocateHandle),
('SmmLocateProtocol', hook_SmmLocateProtocol),
('SmiManage', hook_SmiManage),
('SmiHandlerRegister', hook_SmiHandlerRegister),
('SmiHandlerUnRegister', hook_SmiHandlerUnRegister),
)
}
instance = init_struct(ql, gSmst, descriptor)
instance.saveTo(ql, gSmst)
instance.save_to(ql.mem, gSmst)
install_configuration_table(context, "HOB_LIST", None)
install_configuration_table(context, "SMM_RUNTIME_SERVICES_TABLE", gSmmRT)
+15 -16
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
@@ -19,19 +19,19 @@ from qiling.os.uefi.UefiSpec import EFI_SYSTEM_TABLE, EFI_BOOT_SERVICES, EFI_RUN
# | NumberOfTableEntries |
# | ConfigurationTable* -> (4) |
# +-----------------------------+
# (1) +-- EFI_RUNTIME_SERVICES -----+
# (1) +-- EFI_RUNTIME_SERVICES -----+
# | |
# | ... |
# +-----------------------------+
# (2) +-- EFI_BOOT_SERVICES --------+
# (2) +-- EFI_BOOT_SERVICES --------+
# | |
# | ... |
# +-----------------------------+
# (3) +-- EFI_DXE_SERVICES ---------+
# (3) +-- EFI_DXE_SERVICES ---------+
# | |
# | ... |
# +-----------------------------+
# (4) +-- EFI_CONFIGURATION_TABLE --+ of HOB_LIST
# (4) +-- EFI_CONFIGURATION_TABLE --+ of HOB_LIST
# | VendorGuid |
# | VendorTable* -> (5) |
# +-----------------------------+
@@ -44,16 +44,16 @@ from qiling.os.uefi.UefiSpec import EFI_SYSTEM_TABLE, EFI_BOOT_SERVICES, EFI_RUN
# dynamically allocated (context.conf_table_data_ptr):
#
# (5) +-- VOID* --------------------+
# (5) +-- VOID* --------------------+
# | ... |
# +-----------------------------+
def initialize(ql: Qiling, context: UefiContext, gST: int):
ql.loader.gST = gST
gBS = gST + EFI_SYSTEM_TABLE.sizeof() # boot services
gRT = gBS + EFI_BOOT_SERVICES.sizeof() # runtime services
gDS = gRT + EFI_RUNTIME_SERVICES.sizeof() # dxe services
gBS = gST + EFI_SYSTEM_TABLE.sizeof() # boot services
gRT = gBS + EFI_BOOT_SERVICES.sizeof() # runtime services
gDS = gRT + EFI_RUNTIME_SERVICES.sizeof() # dxe services
cfg = gDS + ds.EFI_DXE_SERVICES.sizeof() # configuration tables array
ql.log.info(f'Global tables:')
@@ -67,13 +67,12 @@ def initialize(ql: Qiling, context: UefiContext, gST: int):
rt.initialize(ql, gRT)
ds.initialize(ql, gDS)
instance = EFI_SYSTEM_TABLE()
instance.RuntimeServices = gRT
instance.BootServices = gBS
instance.NumberOfTableEntries = 0
instance.ConfigurationTable = cfg
instance.saveTo(ql, gST)
EFI_SYSTEM_TABLE(
RuntimeServices = gRT,
BootServices = gBS,
NumberOfTableEntries = 0,
ConfigurationTable = cfg
).save_to(ql.mem, gST)
install_configuration_table(context, "HOB_LIST", None)
install_configuration_table(context, "DXE_SERVICE_TABLE", gDS)
+12 -10
View File
@@ -4,13 +4,13 @@
#
import re
from typing import Any, Callable, Iterable, Mapping, MutableSequence, Sequence, Tuple
from typing import Any, Callable, Iterable, Mapping, List, Sequence, Tuple
from unicorn import UcError
from qiling import Qiling
from qiling.cc import QlCC, intel
from qiling.const import QL_INTERCEPT, QL_OS
from qiling.os.const import *
from qiling.os.const import POINTER, STRING, WSTRING, GUID
from qiling.os.memory import QlMemoryHeap
from qiling.os.os import QlOs, QlOsUtils
from qiling.os.fcall import QlFunctionCall, TypedArg
@@ -30,8 +30,8 @@ class QlOsUefi(QlOs):
self.smm: SmmEnv
self.heap: QlMemoryHeap # Will be initialized by the loader.
self.on_module_enter: MutableSequence[Callable[[str], bool]] = []
self.on_module_exit: MutableSequence[Callable[[int], bool]] = []
self.on_module_enter: List[Callable[[str], bool]] = []
self.on_module_exit: List[Callable[[int], bool]] = []
cc: QlCC = {
32: intel.cdecl,
@@ -41,12 +41,14 @@ class QlOsUefi(QlOs):
self.fcall = QlFunctionCall(ql, cc)
def save(self):
saved_state = super(QlOsUefi, self).save()
saved_state = super().save()
saved_state['entry_point'] = self.entry_point
return saved_state
def restore(self, saved_state):
super(QlOsUefi, self).restore(saved_state)
super().restore(saved_state)
self.entry_point = saved_state['entry_point']
def process_fcall_params(self, targs: Iterable[TypedArg]) -> Sequence[Tuple[str, str]]:
@@ -70,10 +72,10 @@ class QlOsUefi(QlOs):
return super(QlOsUefi, self).process_fcall_params([(None, '', v)])[0][1]
ahandlers: Mapping[Any, Callable[[Any], str]] = {
POINTER : lambda v: f'{v:#010x}' if v else 'NULL',
STRING : lambda v: QlOsUtils.stringify(v),
WSTRING : lambda v: f'L{QlOsUtils.stringify(v)}',
GUID : lambda v: guids_db.get(v.upper(), v) if v else 'NULL'
POINTER: lambda v: f'{v:#010x}' if v else 'NULL',
STRING: lambda v: QlOsUtils.stringify(v),
WSTRING: lambda v: f'L{QlOsUtils.stringify(v)}',
GUID: lambda v: guids_db.get(v.upper(), v) if v else 'NULL'
}
return tuple((aname, ahandlers.get(atype, fallback)(avalue)) for atype, aname, avalue in targs)
+10 -65
View File
@@ -1,17 +1,20 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import binascii
from uuid import UUID
from typing import Optional, Mapping
from typing import TYPE_CHECKING, Any, Optional, Mapping
from qiling import Qiling
from qiling.os.uefi.const import EFI_SUCCESS
from qiling.os.uefi.UefiBaseType import EFI_GUID
if TYPE_CHECKING:
from qiling.os.uefi.ProcessorBind import STRUCT
def signal_event(ql: Qiling, event_id: int) -> None:
event = ql.loader.events[event_id]
@@ -63,65 +66,7 @@ def execute_protocol_notifications(ql: Qiling, from_hook: bool = False) -> bool:
return True
def ptr_read8(ql: Qiling, addr: int) -> int:
"""Read BYTE data from a pointer
"""
return ql.mem.read_ptr(addr, 1)
def ptr_write8(ql: Qiling, addr: int, val: int) -> None:
"""Write BYTE data to a pointer
"""
ql.mem.write_ptr(addr, val, 1)
def ptr_read16(ql: Qiling, addr: int) -> int:
"""Read WORD data from a pointer
"""
return ql.mem.read_ptr(addr, 2)
def ptr_write16(ql: Qiling, addr: int, val: int) -> None:
"""Write WORD data to a pointer
"""
ql.mem.write_ptr(addr, val, 2)
def ptr_read32(ql: Qiling, addr: int) -> int:
"""Read DWORD data from a pointer
"""
return ql.mem.read_ptr(addr, 4)
def ptr_write32(ql: Qiling, addr: int, val: int) -> None:
"""Write DWORD data to a pointer
"""
ql.mem.write_ptr(addr, val, 4)
def ptr_read64(ql: Qiling, addr: int) -> int:
"""Read QWORD data from a pointer
"""
return ql.mem.read_ptr(addr, 8)
def ptr_write64(ql: Qiling, addr: int, val: int) -> None:
"""Write QWORD data to a pointer
"""
ql.mem.write_ptr(addr, val, 8)
# backward comptability
read_int8 = ptr_read8
write_int8 = ptr_write8
read_int16 = ptr_read16
write_int16 = ptr_write16
read_int32 = ptr_read32
write_int32 = ptr_write32
read_int64 = ptr_read64
write_int64 = ptr_write64
def init_struct(ql: Qiling, base: int, descriptor: Mapping):
def init_struct(ql: Qiling, base: int, descriptor: Mapping[str, Any]) -> 'STRUCT':
struct_class = descriptor['struct']
struct_fields = descriptor.get('fields', [])
@@ -174,7 +119,7 @@ def install_configuration_table(context, key: str, table: Optional[int]):
# if pointer to table data was not specified, load table data
# from profile and have table pointing to it
if table is None:
data = binascii.unhexlify(cfgtable['TableData'])
data = bytes.fromhex(cfgtable['TableData'])
table = context.conf_table_data_next_ptr
context.ql.mem.write(table, data)
@@ -186,4 +131,4 @@ def GetEfiConfigurationTable(context, guid: str) -> Optional[int]:
"""Find a configuration table by its GUID.
"""
return context.conftable.get_vendor_table(guid)
return context.conftable.get_vendor_table(guid)