BaseTools: Supported FMP capsule image.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Capsule.py
1 ## @file
2 # generate capsule
3 #
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 #
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14
15 ##
16 # Import Modules
17 #
18 from GenFdsGlobalVariable import GenFdsGlobalVariable
19 from CommonDataClass.FdfClass import CapsuleClassObject
20 import Common.LongFilePathOs as os
21 import subprocess
22 import StringIO
23 from Common.Misc import SaveFileOnChange
24 from GenFds import GenFds
25 from Common.Misc import PackRegistryFormatGuid
26 import uuid
27 from struct import pack
28
29
30 T_CHAR_LF = '\n'
31
32 ## create inf file describes what goes into capsule and call GenFv to generate capsule
33 #
34 #
35 class Capsule (CapsuleClassObject) :
36 ## The constructor
37 #
38 # @param self The object pointer
39 #
40 def __init__(self):
41 CapsuleClassObject.__init__(self)
42 # For GenFv
43 self.BlockSize = None
44 # For GenFv
45 self.BlockNum = None
46 self.CapsuleName = None
47
48 ## Generate FMP capsule
49 #
50 # @retval string Generated Capsule file path
51 #
52 def GenFmpCapsule(self):
53 #
54 # Generate capsule header
55 # typedef struct {
56 # EFI_GUID CapsuleGuid;
57 # UINT32 HeaderSize;
58 # UINT32 Flags;
59 # UINT32 CapsuleImageSize;
60 # } EFI_CAPSULE_HEADER;
61 #
62 Header = StringIO.StringIO()
63 #
64 # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
65 #
66 Header.write(PackRegistryFormatGuid('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'))
67 HdrSize = 0
68 if 'CAPSULE_HEADER_SIZE' in self.TokensDict:
69 Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))
70 HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)
71 else:
72 Header.write(pack('=I', 0x20))
73 HdrSize = 0x20
74 Flags = 0
75 if 'CAPSULE_FLAGS' in self.TokensDict:
76 for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):
77 flag = flag.strip()
78 if flag == 'PopulateSystemTable':
79 Flags |= 0x00010000 | 0x00020000
80 elif flag == 'PersistAcrossReset':
81 Flags |= 0x00010000
82 elif flag == 'InitiateReset':
83 Flags |= 0x00040000
84 Header.write(pack('=I', Flags))
85 #
86 # typedef struct {
87 # UINT32 Version;
88 # UINT16 EmbeddedDriverCount;
89 # UINT16 PayloadItemCount;
90 # // UINT64 ItemOffsetList[];
91 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
92 #
93 FwMgrHdr = StringIO.StringIO()
94 if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:
95 FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))
96 else:
97 FwMgrHdr.write(pack('=I', 0x00000001))
98 FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))
99 FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))
100
101 PreSize = FwMgrHdrSize
102 Content = StringIO.StringIO()
103 for driver in self.CapsuleDataList:
104 FileName = driver.GenCapsuleSubItem()
105 FwMgrHdr.write(pack('=Q', PreSize))
106 PreSize += os.path.getsize(FileName)
107 File = open(FileName, 'rb')
108 Content.write(File.read())
109 File.close()
110 for fmp in self.FmpPayloadList:
111 payload = fmp.GenCapsuleSubItem()
112 FwMgrHdr.write(pack('=Q', PreSize))
113 PreSize += len(payload)
114 Content.write(payload)
115 BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
116 Header.write(pack('=I', HdrSize + BodySize))
117 #
118 # The real capsule header structure is 28 bytes
119 #
120 Header.write('\x00'*(HdrSize-28))
121 Header.write(FwMgrHdr.getvalue())
122 Header.write(Content.getvalue())
123 #
124 # Generate FMP capsule file
125 #
126 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'
127 SaveFileOnChange(CapOutputFile, Header.getvalue(), True)
128 return CapOutputFile
129
130 ## Generate capsule
131 #
132 # @param self The object pointer
133 # @retval string Generated Capsule file path
134 #
135 def GenCapsule(self):
136 if self.UiCapsuleName.upper() + 'cap' in GenFds.ImageBinDict.keys():
137 return GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap']
138
139 GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)
140 if ('CAPSULE_GUID' in self.TokensDict and
141 uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
142 return self.GenFmpCapsule()
143
144 CapInfFile = self.GenCapInf()
145 CapInfFile.writelines("[files]" + T_CHAR_LF)
146 CapFileList = []
147 for CapsuleDataObj in self.CapsuleDataList :
148 CapsuleDataObj.CapsuleName = self.CapsuleName
149 FileName = CapsuleDataObj.GenCapsuleSubItem()
150 CapsuleDataObj.CapsuleName = None
151 CapFileList.append(FileName)
152 CapInfFile.writelines("EFI_FILE_NAME = " + \
153 FileName + \
154 T_CHAR_LF)
155 SaveFileOnChange(self.CapInfFileName, CapInfFile.getvalue(), False)
156 CapInfFile.close()
157 #
158 # Call GenFv tool to generate capsule
159 #
160 CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)
161 CapOutputFile = CapOutputFile + '.Cap'
162 GenFdsGlobalVariable.GenerateFirmwareVolume(
163 CapOutputFile,
164 [self.CapInfFileName],
165 Capsule=True,
166 FfsList=CapFileList
167 )
168
169 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)
170 GenFdsGlobalVariable.SharpCounter = 0
171 GenFds.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile
172 return CapOutputFile
173
174 ## Generate inf file for capsule
175 #
176 # @param self The object pointer
177 # @retval file inf file object
178 #
179 def GenCapInf(self):
180 self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
181 self.UiCapsuleName + "_Cap" + '.inf')
182 CapInfFile = StringIO.StringIO() #open (self.CapInfFileName , 'w+')
183
184 CapInfFile.writelines("[options]" + T_CHAR_LF)
185
186 for Item in self.TokensDict.keys():
187 CapInfFile.writelines("EFI_" + \
188 Item + \
189 ' = ' + \
190 self.TokensDict.get(Item) + \
191 T_CHAR_LF)
192
193 return CapInfFile