]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Capsule.py
BaseTools: Handle the bytes and str difference
[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, PackGUID
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(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
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(b'\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.append("[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.append("EFI_FILE_NAME = " + \
217 FileName + \
218 TAB_LINE_BREAK)
219 SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False)
220 #
221 # Call GenFv tool to generate capsule
222 #
223 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)
224 CapOutputFile = CapOutputFile + '.Cap'
225 GenFdsGlobalVariable.GenerateFirmwareVolume(
226 CapOutputFile,
227 [self.CapInfFileName],
228 Capsule=True,
229 FfsList=CapFileList
230 )
231
232 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)
233 GenFdsGlobalVariable.SharpCounter = 0
234 GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile
235 return CapOutputFile
236
237 ## Generate inf file for capsule
238 #
239 # @param self The object pointer
240 # @retval file inf file object
241 #
242 def GenCapInf(self):
243 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
244 self.UiCapsuleName + "_Cap" + '.inf')
245 CapInfFile = []
246
247 CapInfFile.append("[options]" + TAB_LINE_BREAK)
248
249 for Item in self.TokensDict:
250 CapInfFile.append("EFI_" + \
251 Item + \
252 ' = ' + \
253 self.TokensDict[Item] + \
254 TAB_LINE_BREAK)
255
256 return CapInfFile