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