]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/Capsule.py
BaseTools: Handle the bytes and str difference
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Capsule.py
CommitLineData
30fdf114
LG
1## @file\r
2# generate capsule\r
3#\r
9eb87141 4# Copyright (c) 2007 - 2018, 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
1ccc4d89 18from __future__ import absolute_import\r
9e47e6f9 19from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool\r
30fdf114 20from CommonDataClass.FdfClass import CapsuleClassObject\r
1be2ed90 21import Common.LongFilePathOs as os\r
86379ac4 22from io import BytesIO\r
5c5ca9f1 23from Common.Misc import SaveFileOnChange, PackGUID\r
a3251d84
YL
24import uuid\r
25from struct import pack\r
91ae2988 26from Common import EdkLogger\r
9e47e6f9
CJ
27from Common.BuildToolError import GENFDS_ERROR\r
28from Common.DataType import TAB_LINE_BREAK\r
30fdf114 29\r
9e47e6f9 30WIN_CERT_REVISION = 0x0200\r
91ae2988
YZ
31WIN_CERT_TYPE_EFI_GUID = 0x0EF1\r
32EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')\r
33EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')\r
30fdf114
LG
34\r
35## create inf file describes what goes into capsule and call GenFv to generate capsule\r
36#\r
37#\r
9e47e6f9 38class Capsule (CapsuleClassObject):\r
30fdf114
LG
39 ## The constructor\r
40 #\r
41 # @param self The object pointer\r
42 #\r
43 def __init__(self):\r
44 CapsuleClassObject.__init__(self)\r
45 # For GenFv\r
46 self.BlockSize = None\r
47 # For GenFv\r
48 self.BlockNum = None\r
fd171542 49 self.CapsuleName = None\r
30fdf114 50\r
a3251d84
YL
51 ## Generate FMP capsule\r
52 #\r
53 # @retval string Generated Capsule file path\r
54 #\r
55 def GenFmpCapsule(self):\r
56 #\r
57 # Generate capsule header\r
58 # typedef struct {\r
59 # EFI_GUID CapsuleGuid;\r
60 # UINT32 HeaderSize;\r
61 # UINT32 Flags;\r
62 # UINT32 CapsuleImageSize;\r
63 # } EFI_CAPSULE_HEADER;\r
64 #\r
86379ac4 65 Header = BytesIO()\r
a3251d84
YL
66 #\r
67 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A\r
68 #\r
5c5ca9f1 69 Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))\r
a3251d84
YL
70 HdrSize = 0\r
71 if 'CAPSULE_HEADER_SIZE' in self.TokensDict:\r
72 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))\r
73 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)\r
74 else:\r
75 Header.write(pack('=I', 0x20))\r
76 HdrSize = 0x20\r
77 Flags = 0\r
78 if 'CAPSULE_FLAGS' in self.TokensDict:\r
79 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):\r
80 flag = flag.strip()\r
81 if flag == 'PopulateSystemTable':\r
82 Flags |= 0x00010000 | 0x00020000\r
83 elif flag == 'PersistAcrossReset':\r
84 Flags |= 0x00010000\r
85 elif flag == 'InitiateReset':\r
86 Flags |= 0x00040000\r
87 Header.write(pack('=I', Flags))\r
88 #\r
89 # typedef struct {\r
90 # UINT32 Version;\r
91 # UINT16 EmbeddedDriverCount;\r
92 # UINT16 PayloadItemCount;\r
93 # // UINT64 ItemOffsetList[];\r
94 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;\r
95 #\r
86379ac4 96 FwMgrHdr = BytesIO()\r
a3251d84
YL
97 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:\r
98 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))\r
99 else:\r
100 FwMgrHdr.write(pack('=I', 0x00000001))\r
101 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))\r
102 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))\r
103\r
91ae2988
YZ
104 #\r
105 # typedef struct _WIN_CERTIFICATE {\r
106 # UINT32 dwLength;\r
107 # UINT16 wRevision;\r
108 # UINT16 wCertificateType;\r
109 # //UINT8 bCertificate[ANYSIZE_ARRAY];\r
110 # } WIN_CERTIFICATE;\r
111 #\r
112 # typedef struct _WIN_CERTIFICATE_UEFI_GUID {\r
113 # WIN_CERTIFICATE Hdr;\r
114 # EFI_GUID CertType;\r
115 # //UINT8 CertData[ANYSIZE_ARRAY];\r
116 # } WIN_CERTIFICATE_UEFI_GUID;\r
117 #\r
118 # typedef struct {\r
119 # UINT64 MonotonicCount;\r
120 # WIN_CERTIFICATE_UEFI_GUID AuthInfo;\r
121 # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;\r
122 #\r
123 # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {\r
124 # EFI_GUID HashType;\r
125 # UINT8 PublicKey[256];\r
126 # UINT8 Signature[256];\r
127 # } EFI_CERT_BLOCK_RSA_2048_SHA256;\r
128 #\r
129\r
a3251d84 130 PreSize = FwMgrHdrSize\r
86379ac4 131 Content = BytesIO()\r
a3251d84
YL
132 for driver in self.CapsuleDataList:\r
133 FileName = driver.GenCapsuleSubItem()\r
134 FwMgrHdr.write(pack('=Q', PreSize))\r
135 PreSize += os.path.getsize(FileName)\r
136 File = open(FileName, 'rb')\r
137 Content.write(File.read())\r
138 File.close()\r
139 for fmp in self.FmpPayloadList:\r
d4c558e8
YZ
140 if fmp.Existed:\r
141 FwMgrHdr.write(pack('=Q', PreSize))\r
142 PreSize += len(fmp.Buffer)\r
143 Content.write(fmp.Buffer)\r
144 continue\r
19e3aa7a
YZ
145 if fmp.ImageFile:\r
146 for Obj in fmp.ImageFile:\r
147 fmp.ImageFile = Obj.GenCapsuleSubItem()\r
148 if fmp.VendorCodeFile:\r
149 for Obj in fmp.VendorCodeFile:\r
150 fmp.VendorCodeFile = Obj.GenCapsuleSubItem()\r
91ae2988
YZ
151 if fmp.Certificate_Guid:\r
152 ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)\r
153 CmdOption = ''\r
154 CapInputFile = fmp.ImageFile\r
155 if not os.path.isabs(fmp.ImageFile):\r
156 CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)\r
157 CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'\r
4231a819 158 if ExternalTool is None:\r
91ae2988
YZ
159 EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)\r
160 else:\r
161 CmdOption += ExternalTool\r
162 if ExternalOption:\r
163 CmdOption = CmdOption + ' ' + ExternalOption\r
164 CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile\r
165 CmdList = CmdOption.split()\r
166 GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")\r
167 if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:\r
168 dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)\r
169 else:\r
170 dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256\r
5f53a7aa
YZ
171 fmp.ImageFile = CapOutputTmp\r
172 AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]\r
d4c558e8 173 fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)\r
91ae2988 174 else:\r
d4c558e8 175 fmp.Buffer = fmp.GenCapsuleSubItem()\r
5f53a7aa 176 FwMgrHdr.write(pack('=Q', PreSize))\r
d4c558e8
YZ
177 PreSize += len(fmp.Buffer)\r
178 Content.write(fmp.Buffer)\r
a3251d84
YL
179 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())\r
180 Header.write(pack('=I', HdrSize + BodySize))\r
181 #\r
182 # The real capsule header structure is 28 bytes\r
183 #\r
d943b0c3 184 Header.write(b'\x00'*(HdrSize-28))\r
a3251d84
YL
185 Header.write(FwMgrHdr.getvalue())\r
186 Header.write(Content.getvalue())\r
187 #\r
188 # Generate FMP capsule file\r
189 #\r
190 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'\r
191 SaveFileOnChange(CapOutputFile, Header.getvalue(), True)\r
192 return CapOutputFile\r
193\r
30fdf114
LG
194 ## Generate capsule\r
195 #\r
196 # @param self The object pointer\r
fd171542 197 # @retval string Generated Capsule file path\r
30fdf114
LG
198 #\r
199 def GenCapsule(self):\r
7de00838
GL
200 if self.UiCapsuleName.upper() + 'cap' in GenFdsGlobalVariable.ImageBinDict:\r
201 return GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap']\r
fd171542 202\r
203 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)\r
f7496d71 204 if ('CAPSULE_GUID' in self.TokensDict and\r
a3251d84
YL
205 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):\r
206 return self.GenFmpCapsule()\r
207\r
30fdf114 208 CapInfFile = self.GenCapInf()\r
d943b0c3 209 CapInfFile.append("[files]" + TAB_LINE_BREAK)\r
fd171542 210 CapFileList = []\r
9e47e6f9 211 for CapsuleDataObj in self.CapsuleDataList:\r
fd171542 212 CapsuleDataObj.CapsuleName = self.CapsuleName\r
30fdf114 213 FileName = CapsuleDataObj.GenCapsuleSubItem()\r
fd171542 214 CapsuleDataObj.CapsuleName = None\r
215 CapFileList.append(FileName)\r
d943b0c3 216 CapInfFile.append("EFI_FILE_NAME = " + \\r
30fdf114 217 FileName + \\r
9e47e6f9 218 TAB_LINE_BREAK)\r
d943b0c3 219 SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False)\r
30fdf114
LG
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
fd171542 228 Capsule=True,\r
229 FfsList=CapFileList\r
30fdf114 230 )\r
fd171542 231\r
232 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)\r
30fdf114 233 GenFdsGlobalVariable.SharpCounter = 0\r
7de00838 234 GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile\r
fd171542 235 return CapOutputFile\r
30fdf114
LG
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
d943b0c3 245 CapInfFile = []\r
30fdf114 246\r
d943b0c3 247 CapInfFile.append("[options]" + TAB_LINE_BREAK)\r
30fdf114 248\r
9eb87141 249 for Item in self.TokensDict:\r
d943b0c3 250 CapInfFile.append("EFI_" + \\r
30fdf114
LG
251 Item + \\r
252 ' = ' + \\r
9eb87141 253 self.TokensDict[Item] + \\r
9e47e6f9 254 TAB_LINE_BREAK)\r
30fdf114
LG
255\r
256 return CapInfFile\r