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