]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/GenFds/Capsule.py
BaseTools: Move FindExtendTool to GenFdsGlobalVariable.py
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Capsule.py
... / ...
CommitLineData
1## @file\r
2# generate capsule\r
3#\r
4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5#\r
6# This program and the accompanying materials\r
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15##\r
16# Import Modules\r
17#\r
18from __future__ import absolute_import\r
19from .GenFdsGlobalVariable import GenFdsGlobalVariable\r
20from .GenFdsGlobalVariable import FindExtendTool\r
21from CommonDataClass.FdfClass import CapsuleClassObject\r
22import Common.LongFilePathOs as os\r
23import subprocess\r
24from io import BytesIO\r
25from Common.Misc import SaveFileOnChange\r
26from Common.Misc import PackRegistryFormatGuid\r
27import uuid\r
28from struct import pack\r
29from Common import EdkLogger\r
30from Common.BuildToolError import *\r
31\r
32\r
33T_CHAR_LF = '\n'\r
34WIN_CERT_REVISION = 0x0200\r
35WIN_CERT_TYPE_EFI_GUID = 0x0EF1\r
36EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')\r
37EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')\r
38\r
39## create inf file describes what goes into capsule and call GenFv to generate capsule\r
40#\r
41#\r
42class Capsule (CapsuleClassObject) :\r
43 ## The constructor\r
44 #\r
45 # @param self The object pointer\r
46 #\r
47 def __init__(self):\r
48 CapsuleClassObject.__init__(self)\r
49 # For GenFv\r
50 self.BlockSize = None\r
51 # For GenFv\r
52 self.BlockNum = None\r
53 self.CapsuleName = None\r
54\r
55 ## Generate FMP capsule\r
56 #\r
57 # @retval string Generated Capsule file path\r
58 #\r
59 def GenFmpCapsule(self):\r
60 #\r
61 # Generate capsule header\r
62 # typedef struct {\r
63 # EFI_GUID CapsuleGuid;\r
64 # UINT32 HeaderSize;\r
65 # UINT32 Flags;\r
66 # UINT32 CapsuleImageSize;\r
67 # } EFI_CAPSULE_HEADER;\r
68 #\r
69 Header = BytesIO()\r
70 #\r
71 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A\r
72 #\r
73 Header.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'))\r
74 HdrSize = 0\r
75 if 'CAPSULE_HEADER_SIZE' in self.TokensDict:\r
76 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))\r
77 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)\r
78 else:\r
79 Header.write(pack('=I', 0x20))\r
80 HdrSize = 0x20\r
81 Flags = 0\r
82 if 'CAPSULE_FLAGS' in self.TokensDict:\r
83 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):\r
84 flag = flag.strip()\r
85 if flag == 'PopulateSystemTable':\r
86 Flags |= 0x00010000 | 0x00020000\r
87 elif flag == 'PersistAcrossReset':\r
88 Flags |= 0x00010000\r
89 elif flag == 'InitiateReset':\r
90 Flags |= 0x00040000\r
91 Header.write(pack('=I', Flags))\r
92 #\r
93 # typedef struct {\r
94 # UINT32 Version;\r
95 # UINT16 EmbeddedDriverCount;\r
96 # UINT16 PayloadItemCount;\r
97 # // UINT64 ItemOffsetList[];\r
98 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;\r
99 #\r
100 FwMgrHdr = BytesIO()\r
101 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:\r
102 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))\r
103 else:\r
104 FwMgrHdr.write(pack('=I', 0x00000001))\r
105 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))\r
106 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))\r
107\r
108 #\r
109 # typedef struct _WIN_CERTIFICATE {\r
110 # UINT32 dwLength;\r
111 # UINT16 wRevision;\r
112 # UINT16 wCertificateType;\r
113 # //UINT8 bCertificate[ANYSIZE_ARRAY];\r
114 # } WIN_CERTIFICATE;\r
115 #\r
116 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {\r
117 # WIN_CERTIFICATE Hdr;\r
118 # EFI_GUID CertType;\r
119 # //UINT8 CertData[ANYSIZE_ARRAY];\r
120 # } WIN_CERTIFICATE_UEFI_GUID;\r
121 #\r
122 # typedef struct {\r
123 # UINT64 MonotonicCount;\r
124 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;\r
125 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;\r
126 #\r
127 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {\r
128 # EFI_GUID HashType;\r
129 # UINT8 PublicKey[256];\r
130 # UINT8 Signature[256];\r
131 # } EFI_CERT_BLOCK_RSA_2048_SHA256;\r
132 #\r
133\r
134 PreSize = FwMgrHdrSize\r
135 Content = BytesIO()\r
136 for driver in self.CapsuleDataList:\r
137 FileName = driver.GenCapsuleSubItem()\r
138 FwMgrHdr.write(pack('=Q', PreSize))\r
139 PreSize += os.path.getsize(FileName)\r
140 File = open(FileName, 'rb')\r
141 Content.write(File.read())\r
142 File.close()\r
143 for fmp in self.FmpPayloadList:\r
144 if fmp.Existed:\r
145 FwMgrHdr.write(pack('=Q', PreSize))\r
146 PreSize += len(fmp.Buffer)\r
147 Content.write(fmp.Buffer)\r
148 continue\r
149 if fmp.ImageFile:\r
150 for Obj in fmp.ImageFile:\r
151 fmp.ImageFile = Obj.GenCapsuleSubItem()\r
152 if fmp.VendorCodeFile:\r
153 for Obj in fmp.VendorCodeFile:\r
154 fmp.VendorCodeFile = Obj.GenCapsuleSubItem()\r
155 if fmp.Certificate_Guid:\r
156 ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)\r
157 CmdOption = ''\r
158 CapInputFile = fmp.ImageFile\r
159 if not os.path.isabs(fmp.ImageFile):\r
160 CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)\r
161 CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'\r
162 if ExternalTool is None:\r
163 EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)\r
164 else:\r
165 CmdOption += ExternalTool\r
166 if ExternalOption:\r
167 CmdOption = CmdOption + ' ' + ExternalOption\r
168 CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile\r
169 CmdList = CmdOption.split()\r
170 GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")\r
171 if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:\r
172 dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)\r
173 else:\r
174 dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256\r
175 fmp.ImageFile = CapOutputTmp\r
176 AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]\r
177 fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)\r
178 else:\r
179 fmp.Buffer = fmp.GenCapsuleSubItem()\r
180 FwMgrHdr.write(pack('=Q', PreSize))\r
181 PreSize += len(fmp.Buffer)\r
182 Content.write(fmp.Buffer)\r
183 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())\r
184 Header.write(pack('=I', HdrSize + BodySize))\r
185 #\r
186 # The real capsule header structure is 28 bytes\r
187 #\r
188 Header.write('\x00'*(HdrSize-28))\r
189 Header.write(FwMgrHdr.getvalue())\r
190 Header.write(Content.getvalue())\r
191 #\r
192 # Generate FMP capsule file\r
193 #\r
194 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'\r
195 SaveFileOnChange(CapOutputFile, Header.getvalue(), True)\r
196 return CapOutputFile\r
197\r
198 ## Generate capsule\r
199 #\r
200 # @param self The object pointer\r
201 # @retval string Generated Capsule file path\r
202 #\r
203 def GenCapsule(self):\r
204 from .GenFds import GenFds\r
205 if self.UiCapsuleName.upper() + 'cap' in GenFds.ImageBinDict:\r
206 return GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap']\r
207\r
208 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)\r
209 if ('CAPSULE_GUID' in self.TokensDict and\r
210 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):\r
211 return self.GenFmpCapsule()\r
212\r
213 CapInfFile = self.GenCapInf()\r
214 CapInfFile.writelines("[files]" + T_CHAR_LF)\r
215 CapFileList = []\r
216 for CapsuleDataObj in self.CapsuleDataList :\r
217 CapsuleDataObj.CapsuleName = self.CapsuleName\r
218 FileName = CapsuleDataObj.GenCapsuleSubItem()\r
219 CapsuleDataObj.CapsuleName = None\r
220 CapFileList.append(FileName)\r
221 CapInfFile.writelines("EFI_FILE_NAME = " + \\r
222 FileName + \\r
223 T_CHAR_LF)\r
224 SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False)\r
225 CapInfFile.close()\r
226 #\r
227 # Call GenFv tool to generate capsule\r
228 #\r
229 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)\r
230 CapOutputFile = CapOutputFile + '.Cap'\r
231 GenFdsGlobalVariable.GenerateFirmwareVolume(\r
232 CapOutputFile,\r
233 [self.CapInfFileName],\r
234 Capsule=True,\r
235 FfsList=CapFileList\r
236 )\r
237\r
238 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)\r
239 GenFdsGlobalVariable.SharpCounter = 0\r
240 GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile\r
241 return CapOutputFile\r
242\r
243 ## Generate inf file for capsule\r
244 #\r
245 # @param self The object pointer\r
246 # @retval file inf file object\r
247 #\r
248 def GenCapInf(self):\r
249 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,\r
250 self.UiCapsuleName + "_Cap" + '.inf')\r
251 CapInfFile = BytesIO() #open (self.CapInfFileName , 'w+')\r
252\r
253 CapInfFile.writelines("[options]" + T_CHAR_LF)\r
254\r
255 for Item in self.TokensDict:\r
256 CapInfFile.writelines("EFI_" + \\r
257 Item + \\r
258 ' = ' + \\r
259 self.TokensDict[Item] + \\r
260 T_CHAR_LF)\r
261\r
262 return CapInfFile\r