4 # Copyright (c) 2007 - 2016, 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 CommonDataClass
.FdfClass
import CapsuleClassObject
20 import Common
.LongFilePathOs
as os
23 from Common
.Misc
import SaveFileOnChange
24 from GenFds
import GenFds
25 from Common
.Misc
import PackRegistryFormatGuid
27 from struct
import pack
28 from GenFds
import FindExtendTool
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;
69 Header
= StringIO
.StringIO()
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;
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)))
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
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())
143 for fmp
in self
.FmpPayloadList
:
145 for Obj
in fmp
.ImageFile
:
146 fmp
.ImageFile
= Obj
.GenCapsuleSubItem()
147 if fmp
.VendorCodeFile
:
148 for Obj
in fmp
.VendorCodeFile
:
149 fmp
.VendorCodeFile
= Obj
.GenCapsuleSubItem()
150 if fmp
.Certificate_Guid
:
151 ExternalTool
, ExternalOption
= FindExtendTool([], GenFdsGlobalVariable
.ArchList
, fmp
.Certificate_Guid
)
153 CapInputFile
= fmp
.ImageFile
154 if not os
.path
.isabs(fmp
.ImageFile
):
155 CapInputFile
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, fmp
.ImageFile
)
156 CapOutputTmp
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.tmp'
157 if ExternalTool
== None:
158 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No tool found with GUID %s" % fmp
.Certificate_Guid
)
160 CmdOption
+= ExternalTool
162 CmdOption
= CmdOption
+ ' ' + ExternalOption
163 CmdOption
+= ' -e ' + ' --monotonic-count ' + str(fmp
.MonotonicCount
) + ' -o ' + CapOutputTmp
+ ' ' + CapInputFile
164 CmdList
= CmdOption
.split()
165 GenFdsGlobalVariable
.CallExternalTool(CmdList
, "Failed to generate FMP auth capsule")
166 if uuid
.UUID(fmp
.Certificate_Guid
) == EFI_CERT_TYPE_PKCS7_GUID
:
167 dwLength
= 4 + 2 + 2 + 16 + os
.path
.getsize(CapOutputTmp
) - os
.path
.getsize(CapInputFile
)
169 dwLength
= 4 + 2 + 2 + 16 + 16 + 256 + 256
170 fmp
.ImageFile
= CapOutputTmp
171 AuthData
= [fmp
.MonotonicCount
, dwLength
, WIN_CERT_REVISION
, WIN_CERT_TYPE_EFI_GUID
, fmp
.Certificate_Guid
]
172 Buffer
= fmp
.GenCapsuleSubItem(AuthData
)
174 Buffer
= fmp
.GenCapsuleSubItem()
175 FwMgrHdr
.write(pack('=Q', PreSize
))
176 PreSize
+= len(Buffer
)
177 Content
.write(Buffer
)
178 BodySize
= len(FwMgrHdr
.getvalue()) + len(Content
.getvalue())
179 Header
.write(pack('=I', HdrSize
+ BodySize
))
181 # The real capsule header structure is 28 bytes
183 Header
.write('\x00'*(HdrSize
-28))
184 Header
.write(FwMgrHdr
.getvalue())
185 Header
.write(Content
.getvalue())
187 # Generate FMP capsule file
189 CapOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiCapsuleName
) + '.Cap'
190 SaveFileOnChange(CapOutputFile
, Header
.getvalue(), True)
195 # @param self The object pointer
196 # @retval string Generated Capsule file path
198 def GenCapsule(self
):
199 if self
.UiCapsuleName
.upper() + 'cap' in GenFds
.ImageBinDict
.keys():
200 return GenFds
.ImageBinDict
[self
.UiCapsuleName
.upper() + 'cap']
202 GenFdsGlobalVariable
.InfLogger( "\nGenerate %s Capsule" %self
.UiCapsuleName
)
203 if ('CAPSULE_GUID' in self
.TokensDict
and
204 uuid
.UUID(self
.TokensDict
['CAPSULE_GUID']) == uuid
.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
205 return self
.GenFmpCapsule()
207 CapInfFile
= self
.GenCapInf()
208 CapInfFile
.writelines("[files]" + T_CHAR_LF
)
210 for CapsuleDataObj
in self
.CapsuleDataList
:
211 CapsuleDataObj
.CapsuleName
= self
.CapsuleName
212 FileName
= CapsuleDataObj
.GenCapsuleSubItem()
213 CapsuleDataObj
.CapsuleName
= None
214 CapFileList
.append(FileName
)
215 CapInfFile
.writelines("EFI_FILE_NAME = " + \
218 SaveFileOnChange(self
.CapInfFileName
, CapInfFile
.getvalue(), 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 GenFds
.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')
245 CapInfFile
= StringIO
.StringIO() #open (self.CapInfFileName , 'w+')
247 CapInfFile
.writelines("[options]" + T_CHAR_LF
)
249 for Item
in self
.TokensDict
.keys():
250 CapInfFile
.writelines("EFI_" + \
253 self
.TokensDict
.get(Item
) + \