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