1## @file 2# generate capsule 3# 4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 5# 6# This program and the accompanying materials 7# are licensed and made available under the terms and conditions of the BSD License 8# which accompanies this distribution. The full text of the license may be found at 9# http://opensource.org/licenses/bsd-license.php 10# 11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13# 14 15## 16# Import Modules 17# 18from GenFdsGlobalVariable import GenFdsGlobalVariable 19from CommonDataClass.FdfClass import CapsuleClassObject 20import Common.LongFilePathOs as os 21import subprocess 22import StringIO 23from Common.Misc import SaveFileOnChange 24from GenFds import GenFds 25from Common.Misc import PackRegistryFormatGuid 26import uuid 27from struct import pack 28 29 30T_CHAR_LF = '\n' 31 32## create inf file describes what goes into capsule and call GenFv to generate capsule 33# 34# 35class Capsule (CapsuleClassObject) : 36 ## The constructor 37 # 38 # @param self The object pointer 39 # 40 def __init__(self): 41 CapsuleClassObject.__init__(self) 42 # For GenFv 43 self.BlockSize = None 44 # For GenFv 45 self.BlockNum = None 46 self.CapsuleName = None 47 48 ## Generate FMP capsule 49 # 50 # @retval string Generated Capsule file path 51 # 52 def GenFmpCapsule(self): 53 # 54 # Generate capsule header 55 # typedef struct { 56 # EFI_GUID CapsuleGuid; 57 # UINT32 HeaderSize; 58 # UINT32 Flags; 59 # UINT32 CapsuleImageSize; 60 # } EFI_CAPSULE_HEADER; 61 # 62 Header = StringIO.StringIO() 63 # 64 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A 65 # 66 Header.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')) 67 HdrSize = 0 68 if 'CAPSULE_HEADER_SIZE' in self.TokensDict: 69 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16))) 70 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16) 71 else: 72 Header.write(pack('=I', 0x20)) 73 HdrSize = 0x20 74 Flags = 0 75 if 'CAPSULE_FLAGS' in self.TokensDict: 76 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','): 77 flag = flag.strip() 78 if flag == 'PopulateSystemTable': 79 Flags |= 0x00010000 | 0x00020000 80 elif flag == 'PersistAcrossReset': 81 Flags |= 0x00010000 82 elif flag == 'InitiateReset': 83 Flags |= 0x00040000 84 Header.write(pack('=I', Flags)) 85 # 86 # typedef struct { 87 # UINT32 Version; 88 # UINT16 EmbeddedDriverCount; 89 # UINT16 PayloadItemCount; 90 # // UINT64 ItemOffsetList[]; 91 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER; 92 # 93 FwMgrHdr = StringIO.StringIO() 94 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict: 95 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16))) 96 else: 97 FwMgrHdr.write(pack('=I', 0x00000001)) 98 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList))) 99 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList)) 100 101 PreSize = FwMgrHdrSize 102 Content = StringIO.StringIO() 103 for driver in self.CapsuleDataList: 104 FileName = driver.GenCapsuleSubItem() 105 FwMgrHdr.write(pack('=Q', PreSize)) 106 PreSize += os.path.getsize(FileName) 107 File = open(FileName, 'rb') 108 Content.write(File.read()) 109 File.close() 110 for fmp in self.FmpPayloadList: 111 payload = fmp.GenCapsuleSubItem() 112 FwMgrHdr.write(pack('=Q', PreSize)) 113 PreSize += len(payload) 114 Content.write(payload) 115 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue()) 116 Header.write(pack('=I', HdrSize + BodySize)) 117 # 118 # The real capsule header structure is 28 bytes 119 # 120 Header.write('\x00'*(HdrSize-28)) 121 Header.write(FwMgrHdr.getvalue()) 122 Header.write(Content.getvalue()) 123 # 124 # Generate FMP capsule file 125 # 126 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap' 127 SaveFileOnChange(CapOutputFile, Header.getvalue(), True) 128 return CapOutputFile 129 130 ## Generate capsule 131 # 132 # @param self The object pointer 133 # @retval string Generated Capsule file path 134 # 135 def GenCapsule(self): 136 if self.UiCapsuleName.upper() + 'cap' in GenFds.ImageBinDict.keys(): 137 return GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] 138 139 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName) 140 if ('CAPSULE_GUID' in self.TokensDict and 141 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')): 142 return self.GenFmpCapsule() 143 144 CapInfFile = self.GenCapInf() 145 CapInfFile.writelines("[files]" + T_CHAR_LF) 146 CapFileList = [] 147 for CapsuleDataObj in self.CapsuleDataList : 148 CapsuleDataObj.CapsuleName = self.CapsuleName 149 FileName = CapsuleDataObj.GenCapsuleSubItem() 150 CapsuleDataObj.CapsuleName = None 151 CapFileList.append(FileName) 152 CapInfFile.writelines("EFI_FILE_NAME = " + \ 153 FileName + \ 154 T_CHAR_LF) 155 SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False) 156 CapInfFile.close() 157 # 158 # Call GenFv tool to generate capsule 159 # 160 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) 161 CapOutputFile = CapOutputFile + '.Cap' 162 GenFdsGlobalVariable.GenerateFirmwareVolume( 163 CapOutputFile, 164 [self.CapInfFileName], 165 Capsule=True, 166 FfsList=CapFileList 167 ) 168 169 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName) 170 GenFdsGlobalVariable.SharpCounter = 0 171 GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile 172 return CapOutputFile 173 174 ## Generate inf file for capsule 175 # 176 # @param self The object pointer 177 # @retval file inf file object 178 # 179 def GenCapInf(self): 180 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir, 181 self.UiCapsuleName + "_Cap" + '.inf') 182 CapInfFile = StringIO.StringIO() #open (self.CapInfFileName , 'w+') 183 184 CapInfFile.writelines("[options]" + T_CHAR_LF) 185 186 for Item in self.TokensDict.keys(): 187 CapInfFile.writelines("EFI_" + \ 188 Item + \ 189 ' = ' + \ 190 self.TokensDict.get(Item) + \ 191 T_CHAR_LF) 192 193 return CapInfFile 194