def calculate_new_obb_digest(ifwi_file, fv_list, digest_file): """Calculate new OBB hash for one or more firmware volumes. The assumption is all FVs are continuous in one region.""" bios = bytearray() ifwi = IFWI_IMAGE(ifwi_file) if not ifwi.is_ifwi_image(): logger.warn("Invalid IFWI descriptor signature. Assuming BIOS image") with open(ifwi_file, "rb") as fd: bios = FirmwareDevice(0, bytearray(fd.read())) else: ifwi.parse() bios_start = ifwi.region_list[1][1] bios_limit = ifwi.region_list[1][2] bios = FirmwareDevice(0, ifwi.data[bios_start:bios_limit + 1]) logger.info("Found BIOS ({}MB)...".format( len(bios.FdData) // (1024 * 1024))) bios.ParseFd() # Locate FVs (note: only the first FV index is used) fv_id_list = [] for fv in fv_list: obb_fv_idx = bios.get_fv_index_by_guid(fv.bytes_le) if not (0 < obb_fv_idx < len(bios.FvList)): raise ValueError("FV {} for OBB region is not found".format(fv)) logger.info("Found FV @ index {}".format(obb_fv_idx)) fv_id_list.append(obb_fv_idx) starting_fv_idx = fv_id_list[0] logger.info("*** OBB region starts from FV{} (len:{})".format( starting_fv_idx, len(fv_id_list))) obb_offset = bios.FvList[starting_fv_idx].Offset obb_length = 0 if bios.is_fsp_wrapper(): logger.info("FSP Wrapper BIOS") obb_fv_end = starting_fv_idx + len(fv_list) else: logger.critical("EDK2 BIOS image format is not supported any more") exit(2) # Get total length of OBB logger.info("start FV: {} end FV: {}".format(starting_fv_idx, obb_fv_end)) for fv in bios.FvList[starting_fv_idx:obb_fv_end]: logger.info("Adding FV size 0x{:x} ...".format(len(fv.FvData))) obb_length += len(fv.FvData) logger.debug("OBB offset: {:x} len {:x}".format(obb_offset, obb_length)) # Hash it digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) digest.update(bios.FdData[obb_offset:obb_offset + obb_length]) result = digest.finalize() with open(digest_file, "wb") as hash_fd: hash_fd.write(result) return
def update_obb_digest(ifwi_file, digest_file): """Calculate OBB hash according to a predefined range""" ifwi = IFWI_IMAGE(ifwi_file) if not ifwi.is_ifwi_image(): logger.critical("Bad IFWI image") exit(1) ifwi.parse() bios_start = ifwi.region_list[1][1] bios_limit = ifwi.region_list[1][2] logger.info("Parsing BIOS ...") bios = FirmwareDevice(0, ifwi.data[bios_start:bios_limit + 1]) bios.ParseFd() # Extract FVs belongs to OBB obb_fv_idx = bios.get_fv_index_by_guid(GUID_FVOSBOOT.bytes_le) if not (0 < obb_fv_idx < len(bios.FvList)): raise ValueError("Starting OBB FV is not found") logger.debug("OBB region starts from FV{}".format(obb_fv_idx)) obb_offset = bios.FvList[obb_fv_idx].Offset obb_length = 0 if bios.is_fsp_wrapper(): # FVOSBOOT + FVUEFIBOOT_PRIME + FVADVANCED + FVPOSTMEMORY + FSPS logger.info("FSP Wrapper BIOS") obb_fv_end = obb_fv_idx + 5 else: # FVOSBOOT + FVUEFIBOOT_PRIME + FVADVANCED + FVPOSTMEMORY logger.info("EDK2 BIOS") obb_fv_end = obb_fv_idx + 4 for fv in bios.FvList[obb_fv_idx:obb_fv_end]: obb_length += len(fv.FvData) logger.debug("OBB offset: {:x} len {:x}".format(obb_offset, obb_length)) # Hash it digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) digest.update(bios.FdData[obb_offset:obb_offset + obb_length]) result = digest.finalize() with open(digest_file, "wb") as hash_fd: hash_fd.write(result) return