mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
+70
-20
@@ -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"]
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'
|
||||
]
|
||||
]
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
@@ -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__ = [
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user