4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
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
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
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}')
29 ## create inf file describes what goes into capsule and call GenFv to generate capsule
32 class Capsule (CapsuleClassObject
):
35 # @param self The object pointer
38 CapsuleClassObject
.__init
__(self
)
43 self
.CapsuleName
= None
45 ## Generate FMP capsule
47 # @retval string Generated Capsule file path
49 def GenFmpCapsule(self
):
51 # Generate capsule header
53 # EFI_GUID CapsuleGuid;
56 # UINT32 CapsuleImageSize;
57 # } EFI_CAPSULE_HEADER;
61 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
63 Header
.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
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)
69 Header
.write(pack('=I', 0x20))
72 if 'CAPSULE_FLAGS' in self
.TokensDict
:
73 for flag
in self
.TokensDict
['CAPSULE_FLAGS'].split(','):
75 if flag
== 'PopulateSystemTable':
76 Flags |
= 0x00010000 |
0x00020000
77 elif flag
== 'PersistAcrossReset':
79 elif flag
== 'InitiateReset':
81 Header
.write(pack('=I', Flags
))
85 # UINT16 EmbeddedDriverCount;
86 # UINT16 PayloadItemCount;
87 # // UINT64 ItemOffsetList[];
88 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
91 if 'CAPSULE_HEADER_INIT_VERSION' in self
.TokensDict
:
92 FwMgrHdr
.write(pack('=I', int(self
.TokensDict
['CAPSULE_HEADER_INIT_VERSION'], 16)))
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
))
99 # typedef struct _WIN_CERTIFICATE {
102 # UINT16 wCertificateType;
103 # //UINT8 bCertificate[ANYSIZE_ARRAY];
106 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
107 # WIN_CERTIFICATE Hdr;
109 # //UINT8 CertData[ANYSIZE_ARRAY];
110 # } WIN_CERTIFICATE_UEFI_GUID;
113 # UINT64 MonotonicCount;
114 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
115 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
117 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
119 # UINT8 PublicKey[256];
120 # UINT8 Signature[256];
121 # } EFI_CERT_BLOCK_RSA_2048_SHA256;
124 PreSize
= FwMgrHdrSize
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())
133 for fmp
in self
.FmpPayloadList
:
135 FwMgrHdr
.write(pack('=Q', PreSize
))
136 PreSize
+= len(fmp
.Buffer
)
137 Content
.write(fmp
.Buffer
)
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
)
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
)
155 CmdOption
+= ExternalTool
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
)
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
)
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
))
176 # The real capsule header structure is 28 bytes
178 Header
.write(b
'\x00'*(HdrSize
-28))
179 Header
.write(FwMgrHdr
.getvalue())
180 Header
.write(Content
.getvalue())
182 # Generate FMP capsule file
184 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.Cap'
185 SaveFileOnChange(CapOutputFile
, Header
.getvalue(), True)
190 # @param self The object pointer
191 # @retval string Generated Capsule file path
193 def GenCapsule(self
):
194 if self
.UiCapsuleName
.upper() + 'cap' in GenFdsGlobalVariable
.ImageBinDict
:
195 return GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap']
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()
202 CapInfFile
= self
.GenCapInf()
203 CapInfFile
.append("[files]" + TAB_LINE_BREAK
)
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 = " + \
213 SaveFileOnChange(self
.CapInfFileName
, ''.join(CapInfFile
), False)
215 # Call GenFv tool to generate capsule
217 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
)
218 CapOutputFile
= CapOutputFile
+ '.Cap'
219 GenFdsGlobalVariable
.GenerateFirmwareVolume(
221 [self
.CapInfFileName
],
226 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s Capsule Successfully" %self
.UiCapsuleName
)
227 GenFdsGlobalVariable
.SharpCounter
= 0
228 GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap'] = CapOutputFile
231 ## Generate inf file for capsule
233 # @param self The object pointer
234 # @retval file inf file object
237 self
.CapInfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
238 self
.UiCapsuleName
+ "_Cap" + '.inf')
241 CapInfFile
.append("[options]" + TAB_LINE_BREAK
)
243 for Item
in self
.TokensDict
:
244 CapInfFile
.append("EFI_" + \
247 self
.TokensDict
[Item
] + \