def _InitializeInf (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1'): # # Create FV inf file # self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.inf') self.FvInfFile = [] # # Add [Options] # self.FvInfFile.append("[options]" + TAB_LINE_BREAK) if BaseAddress is not None: self.FvInfFile.append("EFI_BASE_ADDRESS = " + \ BaseAddress + \ TAB_LINE_BREAK) if BlockSize is not None: self.FvInfFile.append("EFI_BLOCK_SIZE = " + \ '0x%X' %BlockSize + \ TAB_LINE_BREAK) if BlockNum is not None: self.FvInfFile.append("EFI_NUM_BLOCKS = " + \ ' 0x%X' %BlockNum + \ TAB_LINE_BREAK) else: if self.BlockSizeList == []: if not self._GetBlockSize(): #set default block size is 1 self.FvInfFile.append("EFI_BLOCK_SIZE = 0x1" + TAB_LINE_BREAK) for BlockSize in self.BlockSizeList: if BlockSize[0] is not None: self.FvInfFile.append("EFI_BLOCK_SIZE = " + \ '0x%X' %BlockSize[0] + \ TAB_LINE_BREAK) if BlockSize[1] is not None: self.FvInfFile.append("EFI_NUM_BLOCKS = " + \ ' 0x%X' %BlockSize[1] + \ TAB_LINE_BREAK) if self.BsBaseAddress is not None: self.FvInfFile.append('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \ '0x%X' %self.BsBaseAddress) if self.RtBaseAddress is not None: self.FvInfFile.append('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \ '0x%X' %self.RtBaseAddress) # # Add attribute # self.FvInfFile.append("[attributes]" + TAB_LINE_BREAK) self.FvInfFile.append("EFI_ERASE_POLARITY = " + \ ' %s' %ErasePloarity + \ TAB_LINE_BREAK) if not (self.FvAttributeDict is None): for FvAttribute in self.FvAttributeDict.keys(): if FvAttribute == "FvUsedSizeEnable": if self.FvAttributeDict[FvAttribute].upper() in ('TRUE', '1'): self.UsedSizeEnable = True continue self.FvInfFile.append("EFI_" + \ FvAttribute + \ ' = ' + \ self.FvAttributeDict[FvAttribute] + \ TAB_LINE_BREAK ) if self.FvAlignment is not None: self.FvInfFile.append("EFI_FVB2_ALIGNMENT_" + \ self.FvAlignment.strip() + \ " = TRUE" + \ TAB_LINE_BREAK) # # Generate FV extension header file # if not self.FvNameGuid: if len(self.FvExtEntryType) > 0 or self.UsedSizeEnable: GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName)) else: TotalSize = 16 + 4 Buffer = bytearray() if self.UsedSizeEnable: TotalSize += (4 + 4) ## define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03 #typedef struct # { # EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; # UINT32 UsedSize; # } EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE; Buffer += pack('HHL', 8, 3, 0) if self.FvNameString == 'TRUE': # # Create EXT entry for FV UI name # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C # FvUiLen = len(self.UiFvName) TotalSize += (FvUiLen + 16 + 4) Guid = FV_UI_EXT_ENTY_GUID.split('-') # # Layout: # EFI_FIRMWARE_VOLUME_EXT_ENTRY: size 4 # GUID: size 16 # FV UI name # Buffer += (pack('HH', (FvUiLen + 16 + 4), 0x0002) + PackGUID(Guid) + self.UiFvName.encode('utf-8')) for Index in range (0, len(self.FvExtEntryType)): if self.FvExtEntryType[Index] == 'FILE': # check if the path is absolute or relative if os.path.isabs(self.FvExtEntryData[Index]): FileFullPath = os.path.normpath(self.FvExtEntryData[Index]) else: FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index])) # check if the file path exists or not if not os.path.isfile(FileFullPath): GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index])) FvExtFile = open (FileFullPath, 'rb') FvExtFile.seek(0, 2) Size = FvExtFile.tell() if Size >= 0x10000: GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index])) TotalSize += (Size + 4) FvExtFile.seek(0) Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16)) Buffer += FvExtFile.read() FvExtFile.close() if self.FvExtEntryType[Index] == 'DATA': ByteList = self.FvExtEntryData[Index].split(',') Size = len (ByteList) if Size >= 0x10000: GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index])) TotalSize += (Size + 4) Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16)) for Index1 in range (0, Size): Buffer += pack('B', int(ByteList[Index1], 16)) Guid = self.FvNameGuid.split('-') Buffer = PackGUID(Guid) + pack('=L', TotalSize) + Buffer # # Generate FV extension header file if the total size is not zero # if TotalSize > 0: FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext') FvExtHeaderFile = BytesIO() FvExtHeaderFile.write(Buffer) Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True) FvExtHeaderFile.close() if Changed: if os.path.exists (self.InfFileName): os.remove (self.InfFileName) self.FvInfFile.append("EFI_FV_EXT_HEADER_FILE_NAME = " + \ FvExtHeaderFileName + \ TAB_LINE_BREAK) # # Add [Files] # self.FvInfFile.append("[files]" + TAB_LINE_BREAK)
def GenFmpCapsule(self): # # Generate capsule header # typedef struct { # EFI_GUID CapsuleGuid; # UINT32 HeaderSize; # UINT32 Flags; # UINT32 CapsuleImageSize; # } EFI_CAPSULE_HEADER; # Header = BytesIO() # # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A # Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-'))) HdrSize = 0 if 'CAPSULE_HEADER_SIZE' in self.TokensDict: Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16))) HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16) else: Header.write(pack('=I', 0x20)) HdrSize = 0x20 Flags = 0 if 'CAPSULE_FLAGS' in self.TokensDict: for flag in self.TokensDict['CAPSULE_FLAGS'].split(','): flag = flag.strip() if flag == 'PopulateSystemTable': Flags |= 0x00010000 | 0x00020000 elif flag == 'PersistAcrossReset': Flags |= 0x00010000 elif flag == 'InitiateReset': Flags |= 0x00040000 Header.write(pack('=I', Flags)) # # typedef struct { # UINT32 Version; # UINT16 EmbeddedDriverCount; # UINT16 PayloadItemCount; # // UINT64 ItemOffsetList[]; # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER; # FwMgrHdr = BytesIO() if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict: FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16))) else: FwMgrHdr.write(pack('=I', 0x00000001)) FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList))) FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList)) # # typedef struct _WIN_CERTIFICATE { # UINT32 dwLength; # UINT16 wRevision; # UINT16 wCertificateType; # //UINT8 bCertificate[ANYSIZE_ARRAY]; # } WIN_CERTIFICATE; # # typedef struct _WIN_CERTIFICATE_UEFI_GUID { # WIN_CERTIFICATE Hdr; # EFI_GUID CertType; # //UINT8 CertData[ANYSIZE_ARRAY]; # } WIN_CERTIFICATE_UEFI_GUID; # # typedef struct { # UINT64 MonotonicCount; # WIN_CERTIFICATE_UEFI_GUID AuthInfo; # } EFI_FIRMWARE_IMAGE_AUTHENTICATION; # # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 { # EFI_GUID HashType; # UINT8 PublicKey[256]; # UINT8 Signature[256]; # } EFI_CERT_BLOCK_RSA_2048_SHA256; # PreSize = FwMgrHdrSize Content = BytesIO() for driver in self.CapsuleDataList: FileName = driver.GenCapsuleSubItem() FwMgrHdr.write(pack('=Q', PreSize)) PreSize += os.path.getsize(FileName) File = open(FileName, 'rb') Content.write(File.read()) File.close() for fmp in self.FmpPayloadList: if fmp.Existed: FwMgrHdr.write(pack('=Q', PreSize)) PreSize += len(fmp.Buffer) Content.write(fmp.Buffer) continue if fmp.ImageFile: for Obj in fmp.ImageFile: fmp.ImageFile = Obj.GenCapsuleSubItem() if fmp.VendorCodeFile: for Obj in fmp.VendorCodeFile: fmp.VendorCodeFile = Obj.GenCapsuleSubItem() if fmp.Certificate_Guid: ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid) CmdOption = '' CapInputFile = fmp.ImageFile if not os.path.isabs(fmp.ImageFile): CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile) CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp' if ExternalTool is None: EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid) else: CmdOption += ExternalTool if ExternalOption: CmdOption = CmdOption + ' ' + ExternalOption CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile CmdList = CmdOption.split() GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule") if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID: dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile) else: dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256 fmp.ImageFile = CapOutputTmp AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid] fmp.Buffer = fmp.GenCapsuleSubItem(AuthData) else: fmp.Buffer = fmp.GenCapsuleSubItem() FwMgrHdr.write(pack('=Q', PreSize)) PreSize += len(fmp.Buffer) Content.write(fmp.Buffer) BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue()) Header.write(pack('=I', HdrSize + BodySize)) # # The real capsule header structure is 28 bytes # Header.write(b'\x00'*(HdrSize-28)) Header.write(FwMgrHdr.getvalue()) Header.write(Content.getvalue()) # # Generate FMP capsule file # CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap' SaveFileOnChange(CapOutputFile, Header.getvalue(), True) return CapOutputFile