]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/GenFds/Capsule.py
BaseTools: Enhance BaseTools supports FixedAtBuild usage in VFR file
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Capsule.py
... / ...
CommitLineData
1## @file\r
2# generate capsule\r
3#\r
4# Copyright (c) 2007 - 2016, 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 GenFdsGlobalVariable import GenFdsGlobalVariable\r
19from CommonDataClass.FdfClass import CapsuleClassObject\r
20import Common.LongFilePathOs as os\r
21import subprocess\r
22import StringIO\r
23from Common.Misc import SaveFileOnChange\r
24from GenFds import GenFds\r
25from Common.Misc import PackRegistryFormatGuid\r
26import uuid\r
27from struct import pack\r
28from GenFds import FindExtendTool\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 = StringIO.StringIO()\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 = StringIO.StringIO()\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 = StringIO.StringIO()\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.ImageFile:\r
145 for Obj in fmp.ImageFile:\r
146 fmp.ImageFile = Obj.GenCapsuleSubItem()\r
147 if fmp.VendorCodeFile:\r
148 for Obj in fmp.VendorCodeFile:\r
149 fmp.VendorCodeFile = Obj.GenCapsuleSubItem()\r
150 if fmp.Certificate_Guid:\r
151 ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)\r
152 CmdOption = ''\r
153 CapInputFile = fmp.ImageFile\r
154 if not os.path.isabs(fmp.ImageFile):\r
155 CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)\r
156 CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'\r
157 if ExternalTool == None:\r
158 EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)\r
159 else:\r
160 CmdOption += ExternalTool\r
161 if ExternalOption:\r
162 CmdOption = CmdOption + ' ' + ExternalOption\r
163 CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile\r
164 CmdList = CmdOption.split()\r
165 GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")\r
166 if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:\r
167 dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)\r
168 else:\r
169 dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256\r
170 fmp.ImageFile = CapOutputTmp\r
171 AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]\r
172 Buffer = fmp.GenCapsuleSubItem(AuthData)\r
173 else:\r
174 Buffer = fmp.GenCapsuleSubItem()\r
175 FwMgrHdr.write(pack('=Q', PreSize))\r
176 PreSize += len(Buffer)\r
177 Content.write(Buffer)\r
178 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())\r
179 Header.write(pack('=I', HdrSize + BodySize))\r
180 #\r
181 # The real capsule header structure is 28 bytes\r
182 #\r
183 Header.write('\x00'*(HdrSize-28))\r
184 Header.write(FwMgrHdr.getvalue())\r
185 Header.write(Content.getvalue())\r
186 #\r
187 # Generate FMP capsule file\r
188 #\r
189 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'\r
190 SaveFileOnChange(CapOutputFile, Header.getvalue(), True)\r
191 return CapOutputFile\r
192\r
193 ## Generate capsule\r
194 #\r
195 # @param self The object pointer\r
196 # @retval string Generated Capsule file path\r
197 #\r
198 def GenCapsule(self):\r
199 if self.UiCapsuleName.upper() + 'cap' in GenFds.ImageBinDict.keys():\r
200 return GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap']\r
201\r
202 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)\r
203 if ('CAPSULE_GUID' in self.TokensDict and \r
204 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):\r
205 return self.GenFmpCapsule()\r
206\r
207 CapInfFile = self.GenCapInf()\r
208 CapInfFile.writelines("[files]" + T_CHAR_LF)\r
209 CapFileList = []\r
210 for CapsuleDataObj in self.CapsuleDataList :\r
211 CapsuleDataObj.CapsuleName = self.CapsuleName\r
212 FileName = CapsuleDataObj.GenCapsuleSubItem()\r
213 CapsuleDataObj.CapsuleName = None\r
214 CapFileList.append(FileName)\r
215 CapInfFile.writelines("EFI_FILE_NAME = " + \\r
216 FileName + \\r
217 T_CHAR_LF)\r
218 SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False)\r
219 CapInfFile.close()\r
220 #\r
221 # Call GenFv tool to generate capsule\r
222 #\r
223 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)\r
224 CapOutputFile = CapOutputFile + '.Cap'\r
225 GenFdsGlobalVariable.GenerateFirmwareVolume(\r
226 CapOutputFile,\r
227 [self.CapInfFileName],\r
228 Capsule=True,\r
229 FfsList=CapFileList\r
230 )\r
231\r
232 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)\r
233 GenFdsGlobalVariable.SharpCounter = 0\r
234 GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile\r
235 return CapOutputFile\r
236\r
237 ## Generate inf file for capsule\r
238 #\r
239 # @param self The object pointer\r
240 # @retval file inf file object\r
241 #\r
242 def GenCapInf(self):\r
243 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,\r
244 self.UiCapsuleName + "_Cap" + '.inf')\r
245 CapInfFile = StringIO.StringIO() #open (self.CapInfFileName , 'w+')\r
246\r
247 CapInfFile.writelines("[options]" + T_CHAR_LF)\r
248\r
249 for Item in self.TokensDict.keys():\r
250 CapInfFile.writelines("EFI_" + \\r
251 Item + \\r
252 ' = ' + \\r
253 self.TokensDict.get(Item) + \\r
254 T_CHAR_LF)\r
255\r
256 return CapInfFile\r