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