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
, FindExtendTool
20 from CommonDataClass
.FdfClass
import CapsuleClassObject
21 import Common
.LongFilePathOs
as os
22 from io
import BytesIO
23 from Common
.Misc
import SaveFileOnChange
, PackGUID
25 from struct
import pack
26 from Common
import EdkLogger
27 from Common
.BuildToolError
import GENFDS_ERROR
28 from Common
.DataType
import TAB_LINE_BREAK
30 WIN_CERT_REVISION
= 0x0200
31 WIN_CERT_TYPE_EFI_GUID
= 0x0EF1
32 EFI_CERT_TYPE_PKCS7_GUID
= uuid
.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')
33 EFI_CERT_TYPE_RSA2048_SHA256_GUID
= uuid
.UUID('{a7717414-c616-4977-9420-844712a735bf}')
35 ## create inf file describes what goes into capsule and call GenFv to generate capsule
38 class Capsule (CapsuleClassObject
):
41 # @param self The object pointer
44 CapsuleClassObject
.__init
__(self
)
49 self
.CapsuleName
= None
51 ## Generate FMP capsule
53 # @retval string Generated Capsule file path
55 def GenFmpCapsule(self
):
57 # Generate capsule header
59 # EFI_GUID CapsuleGuid;
62 # UINT32 CapsuleImageSize;
63 # } EFI_CAPSULE_HEADER;
67 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
69 Header
.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
71 if 'CAPSULE_HEADER_SIZE' in self
.TokensDict
:
72 Header
.write(pack('=I', int(self
.TokensDict
['CAPSULE_HEADER_SIZE'], 16)))
73 HdrSize
= int(self
.TokensDict
['CAPSULE_HEADER_SIZE'], 16)
75 Header
.write(pack('=I', 0x20))
78 if 'CAPSULE_FLAGS' in self
.TokensDict
:
79 for flag
in self
.TokensDict
['CAPSULE_FLAGS'].split(','):
81 if flag
== 'PopulateSystemTable':
82 Flags |
= 0x00010000 |
0x00020000
83 elif flag
== 'PersistAcrossReset':
85 elif flag
== 'InitiateReset':
87 Header
.write(pack('=I', Flags
))
91 # UINT16 EmbeddedDriverCount;
92 # UINT16 PayloadItemCount;
93 # // UINT64 ItemOffsetList[];
94 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
97 if 'CAPSULE_HEADER_INIT_VERSION' in self
.TokensDict
:
98 FwMgrHdr
.write(pack('=I', int(self
.TokensDict
['CAPSULE_HEADER_INIT_VERSION'], 16)))
100 FwMgrHdr
.write(pack('=I', 0x00000001))
101 FwMgrHdr
.write(pack('=HH', len(self
.CapsuleDataList
), len(self
.FmpPayloadList
)))
102 FwMgrHdrSize
= 4+2+2+8*(len(self
.CapsuleDataList
)+len(self
.FmpPayloadList
))
105 # typedef struct _WIN_CERTIFICATE {
108 # UINT16 wCertificateType;
109 # //UINT8 bCertificate[ANYSIZE_ARRAY];
112 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
113 # WIN_CERTIFICATE Hdr;
115 # //UINT8 CertData[ANYSIZE_ARRAY];
116 # } WIN_CERTIFICATE_UEFI_GUID;
119 # UINT64 MonotonicCount;
120 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
121 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
123 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
125 # UINT8 PublicKey[256];
126 # UINT8 Signature[256];
127 # } EFI_CERT_BLOCK_RSA_2048_SHA256;
130 PreSize
= FwMgrHdrSize
132 for driver
in self
.CapsuleDataList
:
133 FileName
= driver
.GenCapsuleSubItem()
134 FwMgrHdr
.write(pack('=Q', PreSize
))
135 PreSize
+= os
.path
.getsize(FileName
)
136 File
= open(FileName
, 'rb')
137 Content
.write(File
.read())
139 for fmp
in self
.FmpPayloadList
:
141 FwMgrHdr
.write(pack('=Q', PreSize
))
142 PreSize
+= len(fmp
.Buffer
)
143 Content
.write(fmp
.Buffer
)
146 for Obj
in fmp
.ImageFile
:
147 fmp
.ImageFile
= Obj
.GenCapsuleSubItem()
148 if fmp
.VendorCodeFile
:
149 for Obj
in fmp
.VendorCodeFile
:
150 fmp
.VendorCodeFile
= Obj
.GenCapsuleSubItem()
151 if fmp
.Certificate_Guid
:
152 ExternalTool
, ExternalOption
= FindExtendTool([], GenFdsGlobalVariable
.ArchList
, fmp
.Certificate_Guid
)
154 CapInputFile
= fmp
.ImageFile
155 if not os
.path
.isabs(fmp
.ImageFile
):
156 CapInputFile
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, fmp
.ImageFile
)
157 CapOutputTmp
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.tmp'
158 if ExternalTool
is None:
159 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No tool found with GUID %s" % fmp
.Certificate_Guid
)
161 CmdOption
+= ExternalTool
163 CmdOption
= CmdOption
+ ' ' + ExternalOption
164 CmdOption
+= ' -e ' + ' --monotonic-count ' + str(fmp
.MonotonicCount
) + ' -o ' + CapOutputTmp
+ ' ' + CapInputFile
165 CmdList
= CmdOption
.split()
166 GenFdsGlobalVariable
.CallExternalTool(CmdList
, "Failed to generate FMP auth capsule")
167 if uuid
.UUID(fmp
.Certificate_Guid
) == EFI_CERT_TYPE_PKCS7_GUID
:
168 dwLength
= 4 + 2 + 2 + 16 + os
.path
.getsize(CapOutputTmp
) - os
.path
.getsize(CapInputFile
)
170 dwLength
= 4 + 2 + 2 + 16 + 16 + 256 + 256
171 fmp
.ImageFile
= CapOutputTmp
172 AuthData
= [fmp
.MonotonicCount
, dwLength
, WIN_CERT_REVISION
, WIN_CERT_TYPE_EFI_GUID
, fmp
.Certificate_Guid
]
173 fmp
.Buffer
= fmp
.GenCapsuleSubItem(AuthData
)
175 fmp
.Buffer
= fmp
.GenCapsuleSubItem()
176 FwMgrHdr
.write(pack('=Q', PreSize
))
177 PreSize
+= len(fmp
.Buffer
)
178 Content
.write(fmp
.Buffer
)
179 BodySize
= len(FwMgrHdr
.getvalue()) + len(Content
.getvalue())
180 Header
.write(pack('=I', HdrSize
+ BodySize
))
182 # The real capsule header structure is 28 bytes
184 Header
.write(b
'\x00'*(HdrSize
-28))
185 Header
.write(FwMgrHdr
.getvalue())
186 Header
.write(Content
.getvalue())
188 # Generate FMP capsule file
190 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.Cap'
191 SaveFileOnChange(CapOutputFile
, Header
.getvalue(), True)
196 # @param self The object pointer
197 # @retval string Generated Capsule file path
199 def GenCapsule(self
):
200 if self
.UiCapsuleName
.upper() + 'cap' in GenFdsGlobalVariable
.ImageBinDict
:
201 return GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap']
203 GenFdsGlobalVariable
.InfLogger( "\nGenerate %s Capsule" %self
.UiCapsuleName
)
204 if ('CAPSULE_GUID' in self
.TokensDict
and
205 uuid
.UUID(self
.TokensDict
['CAPSULE_GUID']) == uuid
.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
206 return self
.GenFmpCapsule()
208 CapInfFile
= self
.GenCapInf()
209 CapInfFile
.append("[files]" + TAB_LINE_BREAK
)
211 for CapsuleDataObj
in self
.CapsuleDataList
:
212 CapsuleDataObj
.CapsuleName
= self
.CapsuleName
213 FileName
= CapsuleDataObj
.GenCapsuleSubItem()
214 CapsuleDataObj
.CapsuleName
= None
215 CapFileList
.append(FileName
)
216 CapInfFile
.append("EFI_FILE_NAME = " + \
219 SaveFileOnChange(self
.CapInfFileName
, ''.join(CapInfFile
), False)
221 # Call GenFv tool to generate capsule
223 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
)
224 CapOutputFile
= CapOutputFile
+ '.Cap'
225 GenFdsGlobalVariable
.GenerateFirmwareVolume(
227 [self
.CapInfFileName
],
232 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s Capsule Successfully" %self
.UiCapsuleName
)
233 GenFdsGlobalVariable
.SharpCounter
= 0
234 GenFdsGlobalVariable
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap'] = CapOutputFile
237 ## Generate inf file for capsule
239 # @param self The object pointer
240 # @retval file inf file object
243 self
.CapInfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
244 self
.UiCapsuleName
+ "_Cap" + '.inf')
247 CapInfFile
.append("[options]" + TAB_LINE_BREAK
)
249 for Item
in self
.TokensDict
:
250 CapInfFile
.append("EFI_" + \
253 self
.TokensDict
[Item
] + \