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