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 __future__
import absolute_import
19 from .GenFdsGlobalVariable
import GenFdsGlobalVariable
20 from .GenFdsGlobalVariable
import FindExtendTool
21 from CommonDataClass
.FdfClass
import CapsuleClassObject
22 import Common
.LongFilePathOs
as os
24 from io
import BytesIO
25 from Common
.Misc
import SaveFileOnChange
26 from Common
.Misc
import PackRegistryFormatGuid
28 from struct
import pack
29 from Common
import EdkLogger
30 from Common
.BuildToolError
import *
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}')
39 ## create inf file describes what goes into capsule and call GenFv to generate capsule
42 class Capsule (CapsuleClassObject
) :
45 # @param self The object pointer
48 CapsuleClassObject
.__init
__(self
)
53 self
.CapsuleName
= None
55 ## Generate FMP capsule
57 # @retval string Generated Capsule file path
59 def GenFmpCapsule(self
):
61 # Generate capsule header
63 # EFI_GUID CapsuleGuid;
66 # UINT32 CapsuleImageSize;
67 # } EFI_CAPSULE_HEADER;
71 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
73 Header
.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'))
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)
79 Header
.write(pack('=I', 0x20))
82 if 'CAPSULE_FLAGS' in self
.TokensDict
:
83 for flag
in self
.TokensDict
['CAPSULE_FLAGS'].split(','):
85 if flag
== 'PopulateSystemTable':
86 Flags |
= 0x00010000 |
0x00020000
87 elif flag
== 'PersistAcrossReset':
89 elif flag
== 'InitiateReset':
91 Header
.write(pack('=I', Flags
))
95 # UINT16 EmbeddedDriverCount;
96 # UINT16 PayloadItemCount;
97 # // UINT64 ItemOffsetList[];
98 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
101 if 'CAPSULE_HEADER_INIT_VERSION' in self
.TokensDict
:
102 FwMgrHdr
.write(pack('=I', int(self
.TokensDict
['CAPSULE_HEADER_INIT_VERSION'], 16)))
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
))
109 # typedef struct _WIN_CERTIFICATE {
112 # UINT16 wCertificateType;
113 # //UINT8 bCertificate[ANYSIZE_ARRAY];
116 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
117 # WIN_CERTIFICATE Hdr;
119 # //UINT8 CertData[ANYSIZE_ARRAY];
120 # } WIN_CERTIFICATE_UEFI_GUID;
123 # UINT64 MonotonicCount;
124 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
125 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
127 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
129 # UINT8 PublicKey[256];
130 # UINT8 Signature[256];
131 # } EFI_CERT_BLOCK_RSA_2048_SHA256;
134 PreSize
= FwMgrHdrSize
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())
143 for fmp
in self
.FmpPayloadList
:
145 FwMgrHdr
.write(pack('=Q', PreSize
))
146 PreSize
+= len(fmp
.Buffer
)
147 Content
.write(fmp
.Buffer
)
150 for Obj
in fmp
.ImageFile
:
151 fmp
.ImageFile
= Obj
.GenCapsuleSubItem()
152 if fmp
.VendorCodeFile
:
153 for Obj
in fmp
.VendorCodeFile
:
154 fmp
.VendorCodeFile
= Obj
.GenCapsuleSubItem()
155 if fmp
.Certificate_Guid
:
156 ExternalTool
, ExternalOption
= FindExtendTool([], GenFdsGlobalVariable
.ArchList
, fmp
.Certificate_Guid
)
158 CapInputFile
= fmp
.ImageFile
159 if not os
.path
.isabs(fmp
.ImageFile
):
160 CapInputFile
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, fmp
.ImageFile
)
161 CapOutputTmp
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.tmp'
162 if ExternalTool
is None:
163 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No tool found with GUID %s" % fmp
.Certificate_Guid
)
165 CmdOption
+= ExternalTool
167 CmdOption
= CmdOption
+ ' ' + ExternalOption
168 CmdOption
+= ' -e ' + ' --monotonic-count ' + str(fmp
.MonotonicCount
) + ' -o ' + CapOutputTmp
+ ' ' + CapInputFile
169 CmdList
= CmdOption
.split()
170 GenFdsGlobalVariable
.CallExternalTool(CmdList
, "Failed to generate FMP auth capsule")
171 if uuid
.UUID(fmp
.Certificate_Guid
) == EFI_CERT_TYPE_PKCS7_GUID
:
172 dwLength
= 4 + 2 + 2 + 16 + os
.path
.getsize(CapOutputTmp
) - os
.path
.getsize(CapInputFile
)
174 dwLength
= 4 + 2 + 2 + 16 + 16 + 256 + 256
175 fmp
.ImageFile
= CapOutputTmp
176 AuthData
= [fmp
.MonotonicCount
, dwLength
, WIN_CERT_REVISION
, WIN_CERT_TYPE_EFI_GUID
, fmp
.Certificate_Guid
]
177 fmp
.Buffer
= fmp
.GenCapsuleSubItem(AuthData
)
179 fmp
.Buffer
= fmp
.GenCapsuleSubItem()
180 FwMgrHdr
.write(pack('=Q', PreSize
))
181 PreSize
+= len(fmp
.Buffer
)
182 Content
.write(fmp
.Buffer
)
183 BodySize
= len(FwMgrHdr
.getvalue()) + len(Content
.getvalue())
184 Header
.write(pack('=I', HdrSize
+ BodySize
))
186 # The real capsule header structure is 28 bytes
188 Header
.write('\x00'*(HdrSize
-28))
189 Header
.write(FwMgrHdr
.getvalue())
190 Header
.write(Content
.getvalue())
192 # Generate FMP capsule file
194 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.Cap'
195 SaveFileOnChange(CapOutputFile
, Header
.getvalue(), True)
200 # @param self The object pointer
201 # @retval string Generated Capsule file path
203 def GenCapsule(self
):
204 from .GenFds
import GenFds
205 if self
.UiCapsuleName
.upper() + 'cap' in GenFds
.ImageBinDict
:
206 return GenFds
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap']
208 GenFdsGlobalVariable
.InfLogger( "\nGenerate %s Capsule" %self
.UiCapsuleName
)
209 if ('CAPSULE_GUID' in self
.TokensDict
and
210 uuid
.UUID(self
.TokensDict
['CAPSULE_GUID']) == uuid
.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
211 return self
.GenFmpCapsule()
213 CapInfFile
= self
.GenCapInf()
214 CapInfFile
.writelines("[files]" + T_CHAR_LF
)
216 for CapsuleDataObj
in self
.CapsuleDataList
:
217 CapsuleDataObj
.CapsuleName
= self
.CapsuleName
218 FileName
= CapsuleDataObj
.GenCapsuleSubItem()
219 CapsuleDataObj
.CapsuleName
= None
220 CapFileList
.append(FileName
)
221 CapInfFile
.writelines("EFI_FILE_NAME = " + \
224 SaveFileOnChange(self
.CapInfFileName
, CapInfFile
.getvalue(), False)
227 # Call GenFv tool to generate capsule
229 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
)
230 CapOutputFile
= CapOutputFile
+ '.Cap'
231 GenFdsGlobalVariable
.GenerateFirmwareVolume(
233 [self
.CapInfFileName
],
238 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s Capsule Successfully" %self
.UiCapsuleName
)
239 GenFdsGlobalVariable
.SharpCounter
= 0
240 GenFds
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap'] = CapOutputFile
243 ## Generate inf file for capsule
245 # @param self The object pointer
246 # @retval file inf file object
249 self
.CapInfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
250 self
.UiCapsuleName
+ "_Cap" + '.inf')
251 CapInfFile
= BytesIO() #open (self.CapInfFileName , 'w+')
253 CapInfFile
.writelines("[options]" + T_CHAR_LF
)
255 for Item
in self
.TokensDict
:
256 CapInfFile
.writelines("EFI_" + \
259 self
.TokensDict
[Item
] + \