BaseTools: Supported FMP capsule image.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Capsule.py
CommitLineData
30fdf114
LG
1## @file\r
2# generate capsule\r
3#\r
1be2ed90 4# Copyright (c) 2007 - 2014, 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
30fdf114
LG
28\r
29\r
30T_CHAR_LF = '\n'\r
31\r
32## create inf file describes what goes into capsule and call GenFv to generate capsule\r
33#\r
34#\r
35class Capsule (CapsuleClassObject) :\r
36 ## The constructor\r
37 #\r
38 # @param self The object pointer\r
39 #\r
40 def __init__(self):\r
41 CapsuleClassObject.__init__(self)\r
42 # For GenFv\r
43 self.BlockSize = None\r
44 # For GenFv\r
45 self.BlockNum = None\r
fd171542 46 self.CapsuleName = None\r
30fdf114 47\r
a3251d84
YL
48 ## Generate FMP capsule\r
49 #\r
50 # @retval string Generated Capsule file path\r
51 #\r
52 def GenFmpCapsule(self):\r
53 #\r
54 # Generate capsule header\r
55 # typedef struct {\r
56 # EFI_GUID CapsuleGuid;\r
57 # UINT32 HeaderSize;\r
58 # UINT32 Flags;\r
59 # UINT32 CapsuleImageSize;\r
60 # } EFI_CAPSULE_HEADER;\r
61 #\r
62 Header = StringIO.StringIO()\r
63 #\r
64 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A\r
65 #\r
66 Header.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'))\r
67 HdrSize = 0\r
68 if 'CAPSULE_HEADER_SIZE' in self.TokensDict:\r
69 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))\r
70 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)\r
71 else:\r
72 Header.write(pack('=I', 0x20))\r
73 HdrSize = 0x20\r
74 Flags = 0\r
75 if 'CAPSULE_FLAGS' in self.TokensDict:\r
76 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):\r
77 flag = flag.strip()\r
78 if flag == 'PopulateSystemTable':\r
79 Flags |= 0x00010000 | 0x00020000\r
80 elif flag == 'PersistAcrossReset':\r
81 Flags |= 0x00010000\r
82 elif flag == 'InitiateReset':\r
83 Flags |= 0x00040000\r
84 Header.write(pack('=I', Flags))\r
85 #\r
86 # typedef struct {\r
87 # UINT32 Version;\r
88 # UINT16 EmbeddedDriverCount;\r
89 # UINT16 PayloadItemCount;\r
90 # // UINT64 ItemOffsetList[];\r
91 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;\r
92 #\r
93 FwMgrHdr = StringIO.StringIO()\r
94 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:\r
95 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))\r
96 else:\r
97 FwMgrHdr.write(pack('=I', 0x00000001))\r
98 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))\r
99 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))\r
100\r
101 PreSize = FwMgrHdrSize\r
102 Content = StringIO.StringIO()\r
103 for driver in self.CapsuleDataList:\r
104 FileName = driver.GenCapsuleSubItem()\r
105 FwMgrHdr.write(pack('=Q', PreSize))\r
106 PreSize += os.path.getsize(FileName)\r
107 File = open(FileName, 'rb')\r
108 Content.write(File.read())\r
109 File.close()\r
110 for fmp in self.FmpPayloadList:\r
111 payload = fmp.GenCapsuleSubItem()\r
112 FwMgrHdr.write(pack('=Q', PreSize))\r
113 PreSize += len(payload)\r
114 Content.write(payload)\r
115 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())\r
116 Header.write(pack('=I', HdrSize + BodySize))\r
117 #\r
118 # The real capsule header structure is 28 bytes\r
119 #\r
120 Header.write('\x00'*(HdrSize-28))\r
121 Header.write(FwMgrHdr.getvalue())\r
122 Header.write(Content.getvalue())\r
123 #\r
124 # Generate FMP capsule file\r
125 #\r
126 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'\r
127 SaveFileOnChange(CapOutputFile, Header.getvalue(), True)\r
128 return CapOutputFile\r
129\r
30fdf114
LG
130 ## Generate capsule\r
131 #\r
132 # @param self The object pointer\r
fd171542 133 # @retval string Generated Capsule file path\r
30fdf114
LG
134 #\r
135 def GenCapsule(self):\r
fd171542 136 if self.UiCapsuleName.upper() + 'cap' in GenFds.ImageBinDict.keys():\r
137 return GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap']\r
138\r
139 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)\r
a3251d84
YL
140 if ('CAPSULE_GUID' in self.TokensDict and \r
141 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):\r
142 return self.GenFmpCapsule()\r
143\r
30fdf114
LG
144 CapInfFile = self.GenCapInf()\r
145 CapInfFile.writelines("[files]" + T_CHAR_LF)\r
fd171542 146 CapFileList = []\r
30fdf114 147 for CapsuleDataObj in self.CapsuleDataList :\r
fd171542 148 CapsuleDataObj.CapsuleName = self.CapsuleName\r
30fdf114 149 FileName = CapsuleDataObj.GenCapsuleSubItem()\r
fd171542 150 CapsuleDataObj.CapsuleName = None\r
151 CapFileList.append(FileName)\r
30fdf114
LG
152 CapInfFile.writelines("EFI_FILE_NAME = " + \\r
153 FileName + \\r
154 T_CHAR_LF)\r
155 SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False)\r
156 CapInfFile.close()\r
157 #\r
158 # Call GenFv tool to generate capsule\r
159 #\r
160 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)\r
161 CapOutputFile = CapOutputFile + '.Cap'\r
162 GenFdsGlobalVariable.GenerateFirmwareVolume(\r
163 CapOutputFile,\r
164 [self.CapInfFileName],\r
fd171542 165 Capsule=True,\r
166 FfsList=CapFileList\r
30fdf114 167 )\r
fd171542 168\r
169 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)\r
30fdf114 170 GenFdsGlobalVariable.SharpCounter = 0\r
fd171542 171 GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile\r
172 return CapOutputFile\r
30fdf114
LG
173\r
174 ## Generate inf file for capsule\r
175 #\r
176 # @param self The object pointer\r
177 # @retval file inf file object\r
178 #\r
179 def GenCapInf(self):\r
180 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,\r
181 self.UiCapsuleName + "_Cap" + '.inf')\r
182 CapInfFile = StringIO.StringIO() #open (self.CapInfFileName , 'w+')\r
183\r
184 CapInfFile.writelines("[options]" + T_CHAR_LF)\r
185\r
186 for Item in self.TokensDict.keys():\r
187 CapInfFile.writelines("EFI_" + \\r
188 Item + \\r
189 ' = ' + \\r
190 self.TokensDict.get(Item) + \\r
191 T_CHAR_LF)\r
192\r
193 return CapInfFile\r