]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Capsule.py
BaseTools: Replace BSD License with BSD+Patent License
[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 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ##
10 # Import Modules
11 #
12 from __future__ import absolute_import
13 from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool
14 from CommonDataClass.FdfClass import CapsuleClassObject
15 import Common.LongFilePathOs as os
16 from io import BytesIO
17 from Common.Misc import SaveFileOnChange, PackGUID
18 import uuid
19 from struct import pack
20 from Common import EdkLogger
21 from Common.BuildToolError import GENFDS_ERROR
22 from Common.DataType import TAB_LINE_BREAK
23
24 WIN_CERT_REVISION = 0x0200
25 WIN_CERT_TYPE_EFI_GUID = 0x0EF1
26 EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')
27 EFI_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 #
32 class 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