def run(self): # intel architecture uefi implementation only if self.ql.archtype not in (QL_ARCH.X86, QL_ARCH.X8664): raise QlErrorArch("Unsupported architecture") # x86-64 arch only if self.ql.archtype != QL_ARCH.X8664: raise QlErrorArch("Only 64 bit arch is supported at the moment") self.loaded_image_protocol_guid = self.ql.os.profile[ "LOADED_IMAGE_PROTOCOL"]["Guid"] self.loaded_image_protocol_modules = [] self.tpl = 4 # TPL_APPLICATION self.user_defined_api = self.ql.os.user_defined_api self.user_defined_api_onenter = self.ql.os.user_defined_api_onenter self.user_defined_api_onexit = self.ql.os.user_defined_api_onexit arch_key = { QL_ARCH.X86: "OS32", QL_ARCH.X8664: "OS64" }[self.ql.archtype] # -------- init BS / RT / DXE data structures and protocols -------- os_profile = self.ql.os.profile[arch_key] self.dxe_context = context.DxeContext(self.ql) # initialize and locate heap heap_base = int(os_profile["heap_address"], 0) heap_size = int(os_profile["heap_size"], 0) self.dxe_context.init_heap(heap_base, heap_size) self.heap_base_address = heap_base self.ql.log.info(f"Located heap at {heap_base:#010x}") # initialize and locate stack stack_base = int(os_profile["stack_address"], 0) stack_size = int(os_profile["stack_size"], 0) self.dxe_context.init_stack(stack_base, stack_size) sp = stack_base + stack_size - CPU_STACK_ALIGNMENT self.ql.log.info(f"Located stack at {sp:#010x}") # TODO: statically allocating 256 KiB for ST, RT, BS, DS and Configuration Tables. # however, this amount of memory is rather arbitrary gST = self.dxe_context.heap.alloc(256 * 1024) st.initialize(self.ql, gST) protocols = ( EfiSmmAccess2Protocol, EfiSmmBase2Protocol, ) for proto in protocols: self.dxe_context.install_protocol(proto.descriptor, 1) # workaround self.ql.os.heap = self.dxe_context.heap # -------- init SMM data structures and protocols -------- smm_profile = self.ql.os.profile['SMRAM'] self.smm_context = context.SmmContext(self.ql) # initialize and locate SMM heap heap_base = int(smm_profile["heap_address"], 0) heap_size = int(smm_profile["heap_size"], 0) self.smm_context.init_heap(heap_base, heap_size) self.ql.log.info(f"Located SMM heap at {heap_base:#010x}") # TODO: statically allocating 256 KiB for SMM ST. # however, this amount of memory is rather arbitrary gSmst = self.smm_context.heap.alloc(256 * 1024) smst.initialize(self.ql, gSmst) self.in_smm = False protocols = (EfiSmmCpuProtocol, EfiSmmSwDispatch2Protocol) for proto in protocols: self.smm_context.install_protocol(proto.descriptor, 1) # map mmio ranges # TODO: move to somehwere more appropriate (+ hook accesses?) mmio_map = self.ql.os.profile["MMIO"] self.ql.mem.map(int(mmio_map['sbreg_base'], 0), int(mmio_map['sbreg_size'], 0)) # set stack and frame pointers self.ql.reg.rsp = sp self.ql.reg.rbp = sp self.entry_point = 0 self.load_address = 0 self.next_image_base = int(os_profile["image_address"], 0) try: for dependency in self.ql.argv: self.map_and_load(dependency) except QlMemoryMappedError: self.ql.log.critical("Couldn't map dependency") self.ql.log.info(f"Done with loading {self.ql.path}") # set up an end-of-execution hook to regain control when module is done # executing (i.e. when the entry point function returns). that should be # set on a non-executable address, so SystemTable's address was picked self.end_of_execution_ptr = gST self.ql.hook_address(hook_EndOfExecution, self.end_of_execution_ptr) self.execute_next_module()
def run(self): # intel architecture uefi implementaion only if self.ql.archtype not in (QL_ARCH.X86, QL_ARCH.X8664): raise QlErrorArch("[!] Unsupported architecture") # x86-64 arch only if self.ql.archtype != QL_ARCH.X8664: raise QlErrorArch( "[!] Only 64 bit arch is supported at the moment") self.loaded_image_protocol_guid = self.ql.os.profile[ "LOADED_IMAGE_PROTOCOL"]["guid"] self.loaded_image_protocol_modules = [] self.tpl = 4 # TPL_APPLICATION self.user_defined_api = self.ql.os.user_defined_api self.user_defined_api_onenter = self.ql.os.user_defined_api_onenter self.user_defined_api_onexit = self.ql.os.user_defined_api_onexit arch_key = { QL_ARCH.X86: "OS32", QL_ARCH.X8664: "OS64" }[self.ql.archtype] # -------- init BS / RT / DXE data structures and protocols -------- os_profile = self.ql.os.profile[arch_key] self.dxe_context = context.UefiContext(self.ql) # initialize and locate heap heap_base = int(os_profile["heap_address"], 0) heap_size = int(os_profile["heap_size"], 0) self.dxe_context.init_heap(heap_base, heap_size) self.heap_base_address = heap_base logging.info(f"[+] Located heap at {heap_base:#010x}") # initialize and locate stack stack_base = int(os_profile["stack_address"], 0) stack_size = int(os_profile["stack_size"], 0) self.dxe_context.init_stack(stack_base, stack_size) sp = stack_base + stack_size - CPU_STACK_ALIGNMENT logging.info(f"[+] Located stack at {sp:#010x}") # TODO: statically allocating 256 KiB for ST, RT, BS, DS and Configuration Tables. # however, this amount of memory is rather arbitrary gST = self.dxe_context.heap.alloc(256 * 1024) st.initialize(self.ql, gST) protocols = (EfiSmmAccess2Protocol, EfiSmmBase2Protocol, PcdProtocol) for proto in protocols: self.dxe_context.install_protocol(proto.descriptor, 1) # workaround self.ql.os.heap = self.dxe_context.heap # -------- init SMM data structures and protocols -------- smm_profile = self.ql.os.profile['SMRAM'] self.smm_context = context.SmmContext(self.ql) # initialize and locate SMM heap heap_base = int(smm_profile["heap_address"], 0) heap_size = int(smm_profile["heap_size"], 0) self.smm_context.init_heap(heap_base, heap_size) logging.info(f"[+] Located SMM heap at {heap_base:#010x}") # TODO: statically allocating 256 KiB for SMM ST. # however, this amount of memory is rather arbitrary gSmst = self.smm_context.heap.alloc(256 * 1024) smst.initialize(self.ql, gSmst) self.gST = gST self.gSmst = gSmst self.in_smm = False protocols = (EfiSmmCpuProtocol, EfiSmmSwDispatch2Protocol) for proto in protocols: self.smm_context.install_protocol(proto.descriptor, 1) # map mmio ranges # TODO: move to somehwere more appropriate (+ hook accesses?) mmio_map = self.ql.os.profile["MMIO"] self.ql.mem.map(int(mmio_map['sbreg_base'], 0), int(mmio_map['sbreg_size'], 0)) # set stack and frame pointers self.ql.reg.rsp = sp self.ql.reg.rbp = sp self.entry_point = 0 self.load_address = 0 self.next_image_base = int(os_profile["image_address"], 0) for dependency in self.ql.argv: if not self.map_and_load(dependency): raise QlErrorFileType("Can't map dependency") logging.info(f"[+] Done with loading {self.ql.path}") # hack: reuse first byte of ST to set a trap self.end_of_execution_ptr = gST self.ql.mem.write(self.end_of_execution_ptr, b'\xcc') self.ql.hook_address(hook_EndOfExecution, self.end_of_execution_ptr) self.execute_next_module()