4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
18 from .GenFdsGlobalVariable
import GenFdsGlobalVariable
19 from .GenFdsGlobalVariable
import FindExtendTool
20 from CommonDataClass
.FdfClass
import CapsuleClassObject
21 import Common
.LongFilePathOs
as os
23 from io
import BytesIO
24 from Common
.Misc
import SaveFileOnChange
25 from Common
.Misc
import PackRegistryFormatGuid
27 from struct
import pack
28 from Common
import EdkLogger
29 from Common
.BuildToolError
import *
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}')
38 ## create inf file describes what goes into capsule and call GenFv to generate capsule
41 class Capsule (CapsuleClassObject
) :
44 # @param self The object pointer
47 CapsuleClassObject
.__init
__(self
)
52 self
.CapsuleName
= None
54 ## Generate FMP capsule
56 # @retval string Generated Capsule file path
58 def GenFmpCapsule(self
):
60 # Generate capsule header
62 # EFI_GUID CapsuleGuid;
65 # UINT32 CapsuleImageSize;
66 # } EFI_CAPSULE_HEADER;
70 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
72 Header
.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'))
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)
78 Header
.write(pack('=I', 0x20))
81 if 'CAPSULE_FLAGS' in self
.TokensDict
:
82 for flag
in self
.TokensDict
['CAPSULE_FLAGS'].split(','):
84 if flag
== 'PopulateSystemTable':
85 Flags |
= 0x00010000 |
0x00020000
86 elif flag
== 'PersistAcrossReset':
88 elif flag
== 'InitiateReset':
90 Header
.write(pack('=I', Flags
))
94 # UINT16 EmbeddedDriverCount;
95 # UINT16 PayloadItemCount;
96 # // UINT64 ItemOffsetList[];
97 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
100 if 'CAPSULE_HEADER_INIT_VERSION' in self
.TokensDict
:
101 FwMgrHdr
.write(pack('=I', int(self
.TokensDict
['CAPSULE_HEADER_INIT_VERSION'], 16)))
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
))
108 # typedef struct _WIN_CERTIFICATE {
111 # UINT16 wCertificateType;
112 # //UINT8 bCertificate[ANYSIZE_ARRAY];
115 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
116 # WIN_CERTIFICATE Hdr;
118 # //UINT8 CertData[ANYSIZE_ARRAY];
119 # } WIN_CERTIFICATE_UEFI_GUID;
122 # UINT64 MonotonicCount;
123 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
124 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
126 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
128 # UINT8 PublicKey[256];
129 # UINT8 Signature[256];
130 # } EFI_CERT_BLOCK_RSA_2048_SHA256;
133 PreSize
= FwMgrHdrSize
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())
142 for fmp
in self
.FmpPayloadList
:
144 FwMgrHdr
.write(pack('=Q', PreSize
))
145 PreSize
+= len(fmp
.Buffer
)
146 Content
.write(fmp
.Buffer
)
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
)
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
)
164 CmdOption
+= ExternalTool
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
)
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
)
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
))
185 # The real capsule header structure is 28 bytes
187 Header
.write('\x00'*(HdrSize
-28))
188 Header
.write(FwMgrHdr
.getvalue())
189 Header
.write(Content
.getvalue())
191 # Generate FMP capsule file
193 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.Cap'
194 SaveFileOnChange(CapOutputFile
, Header
.getvalue(), True)
199 # @param self The object pointer
200 # @retval string Generated Capsule file path
202 def GenCapsule(self
):
203 if self
.UiCapsuleName
.upper() + 'cap' in GenFdsGlobalVariable
.ImageBinDict
:
204 return GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap']
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()
211 CapInfFile
= self
.GenCapInf()
212 CapInfFile
.writelines("[files]" + T_CHAR_LF
)
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 = " + \
222 SaveFileOnChange(self
.CapInfFileName
, CapInfFile
.getvalue(), False)
225 # Call GenFv tool to generate capsule
227 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
)
228 CapOutputFile
= CapOutputFile
+ '.Cap'
229 GenFdsGlobalVariable
.GenerateFirmwareVolume(
231 [self
.CapInfFileName
],
236 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s Capsule Successfully" %self
.UiCapsuleName
)
237 GenFdsGlobalVariable
.SharpCounter
= 0
238 GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap'] = CapOutputFile
241 ## Generate inf file for capsule
243 # @param self The object pointer
244 # @retval file inf file object
247 self
.CapInfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
248 self
.UiCapsuleName
+ "_Cap" + '.inf')
249 CapInfFile
= BytesIO() #open (self.CapInfFileName , 'w+')
251 CapInfFile
.writelines("[options]" + T_CHAR_LF
)
253 for Item
in self
.TokensDict
:
254 CapInfFile
.writelines("EFI_" + \
257 self
.TokensDict
[Item
] + \