1## @file 2# generate capsule 3# 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9## 10# Import Modules 11# 12from __future__ import absolute_import 13from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool 14from CommonDataClass.FdfClass import CapsuleClassObject 15import Common.LongFilePathOs as os 16from io import BytesIO 17from Common.Misc import SaveFileOnChange, PackGUID 18import uuid 19from struct import pack 20from Common import EdkLogger 21from Common.BuildToolError import GENFDS_ERROR 22from Common.DataType import TAB_LINE_BREAK 23 24WIN_CERT_REVISION = 0x0200 25WIN_CERT_TYPE_EFI_GUID = 0x0EF1 26EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}') 27EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}') 28 29## create inf file describes what goes into capsule and call GenFv to generate capsule 30# 31# 32class Capsule (CapsuleClassObject): 33 ## The constructor 34 # 35 # @param self The object pointer 36 # 37 def __init__(self): 38 CapsuleClassObject.__init__(self) 39 # For GenFv 40 self.BlockSize = None 41 # For GenFv 42 self.BlockNum = None 43 self.CapsuleName = None 44 45 ## Generate FMP capsule 46 # 47 # @retval string Generated Capsule file path 48 # 49 def GenFmpCapsule(self): 50 # 51 # Generate capsule header 52 # typedef struct { 53 # EFI_GUID CapsuleGuid; 54 # UINT32 HeaderSize; 55 # UINT32 Flags; 56 # UINT32 CapsuleImageSize; 57 # } EFI_CAPSULE_HEADER; 58 # 59 Header = BytesIO() 60 # 61 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A 62 # 63 Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-'))) 64 HdrSize = 0 65 if 'CAPSULE_HEADER_SIZE' in self.TokensDict: 66 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16))) 67 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16) 68 else: 69 Header.write(pack('=I', 0x20)) 70 HdrSize = 0x20 71 Flags = 0 72 if 'CAPSULE_FLAGS' in self.TokensDict: 73 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','): 74 flag = flag.strip() 75 if flag == 'PopulateSystemTable': 76 Flags |= 0x00010000 | 0x00020000 77 elif flag == 'PersistAcrossReset': 78 Flags |= 0x00010000 79 elif flag == 'InitiateReset': 80 Flags |= 0x00040000 81 Header.write(pack('=I', Flags)) 82 # 83 # typedef struct { 84 # UINT32 Version; 85 # UINT16 EmbeddedDriverCount; 86 # UINT16 PayloadItemCount; 87 # // UINT64 ItemOffsetList[]; 88 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER; 89 # 90 FwMgrHdr = BytesIO() 91 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict: 92 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16))) 93 else: 94 FwMgrHdr.write(pack('=I', 0x00000001)) 95 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList))) 96 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList)) 97 98 # 99 # typedef struct _WIN_CERTIFICATE { 100 # UINT32 dwLength; 101 # UINT16 wRevision; 102 # UINT16 wCertificateType; 103 # //UINT8 bCertificate[ANYSIZE_ARRAY]; 104 # } WIN_CERTIFICATE; 105 # 106 # typedef struct _WIN_CERTIFICATE_UEFI_GUID { 107 # WIN_CERTIFICATE Hdr; 108 # EFI_GUID CertType; 109 # //UINT8 CertData[ANYSIZE_ARRAY]; 110 # } WIN_CERTIFICATE_UEFI_GUID; 111 # 112 # typedef struct { 113 # UINT64 MonotonicCount; 114 # WIN_CERTIFICATE_UEFI_GUID AuthInfo; 115 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION; 116 # 117 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 { 118 # EFI_GUID HashType; 119 # UINT8 PublicKey[256]; 120 # UINT8 Signature[256]; 121 # } EFI_CERT_BLOCK_RSA_2048_SHA256; 122 # 123 124 PreSize = FwMgrHdrSize 125 Content = BytesIO() 126 for driver in self.CapsuleDataList: 127 FileName = driver.GenCapsuleSubItem() 128 FwMgrHdr.write(pack('=Q', PreSize)) 129 PreSize += os.path.getsize(FileName) 130 File = open(FileName, 'rb') 131 Content.write(File.read()) 132 File.close() 133 for fmp in self.FmpPayloadList: 134 if fmp.Existed: 135 FwMgrHdr.write(pack('=Q', PreSize)) 136 PreSize += len(fmp.Buffer) 137 Content.write(fmp.Buffer) 138 continue 139 if fmp.ImageFile: 140 for Obj in fmp.ImageFile: 141 fmp.ImageFile = Obj.GenCapsuleSubItem() 142 if fmp.VendorCodeFile: 143 for Obj in fmp.VendorCodeFile: 144 fmp.VendorCodeFile = Obj.GenCapsuleSubItem() 145 if fmp.Certificate_Guid: 146 ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid) 147 CmdOption = '' 148 CapInputFile = fmp.ImageFile 149 if not os.path.isabs(fmp.ImageFile): 150 CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile) 151 CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp' 152 if ExternalTool is None: 153 EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid) 154 else: 155 CmdOption += ExternalTool 156 if ExternalOption: 157 CmdOption = CmdOption + ' ' + ExternalOption 158 CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile 159 CmdList = CmdOption.split() 160 GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule") 161 if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID: 162 dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile) 163 else: 164 dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256 165 fmp.ImageFile = CapOutputTmp 166 AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid] 167 fmp.Buffer = fmp.GenCapsuleSubItem(AuthData) 168 else: 169 fmp.Buffer = fmp.GenCapsuleSubItem() 170 FwMgrHdr.write(pack('=Q', PreSize)) 171 PreSize += len(fmp.Buffer) 172 Content.write(fmp.Buffer) 173 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue()) 174 Header.write(pack('=I', HdrSize + BodySize)) 175 # 176 # The real capsule header structure is 28 bytes 177 # 178 Header.write(b'\x00'*(HdrSize-28)) 179 Header.write(FwMgrHdr.getvalue()) 180 Header.write(Content.getvalue()) 181 # 182 # Generate FMP capsule file 183 # 184 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap' 185 SaveFileOnChange(CapOutputFile, Header.getvalue(), True) 186 return CapOutputFile 187 188 ## Generate capsule 189 # 190 # @param self The object pointer 191 # @retval string Generated Capsule file path 192 # 193 def GenCapsule(self): 194 if self.UiCapsuleName.upper() + 'cap' in GenFdsGlobalVariable.ImageBinDict: 195 return GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] 196 197 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName) 198 if ('CAPSULE_GUID' in self.TokensDict and 199 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')): 200 return self.GenFmpCapsule() 201 202 CapInfFile = self.GenCapInf() 203 CapInfFile.append("[files]" + TAB_LINE_BREAK) 204 CapFileList = [] 205 for CapsuleDataObj in self.CapsuleDataList: 206 CapsuleDataObj.CapsuleName = self.CapsuleName 207 FileName = CapsuleDataObj.GenCapsuleSubItem() 208 CapsuleDataObj.CapsuleName = None 209 CapFileList.append(FileName) 210 CapInfFile.append("EFI_FILE_NAME = " + \ 211 FileName + \ 212 TAB_LINE_BREAK) 213 SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False) 214 # 215 # Call GenFv tool to generate capsule 216 # 217 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) 218 CapOutputFile = CapOutputFile + '.Cap' 219 GenFdsGlobalVariable.GenerateFirmwareVolume( 220 CapOutputFile, 221 [self.CapInfFileName], 222 Capsule=True, 223 FfsList=CapFileList 224 ) 225 226 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName) 227 GenFdsGlobalVariable.SharpCounter = 0 228 GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile 229 return CapOutputFile 230 231 ## Generate inf file for capsule 232 # 233 # @param self The object pointer 234 # @retval file inf file object 235 # 236 def GenCapInf(self): 237 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir, 238 self.UiCapsuleName + "_Cap" + '.inf') 239 CapInfFile = [] 240 241 CapInfFile.append("[options]" + TAB_LINE_BREAK) 242 243 for Item in self.TokensDict: 244 CapInfFile.append("EFI_" + \ 245 Item + \ 246 ' = ' + \ 247 self.TokensDict[Item] + \ 248 TAB_LINE_BREAK) 249 250 return CapInfFile 251