BaseTools: move PCD size calculation functions to PcdClassObject
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / ValidCheckingInfoObject.py
1 # Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
2 # This program and the accompanying materials
3 # are licensed and made available under the terms and conditions of the BSD License
4 # which accompanies this distribution. The full text of the license may be found at
5 # http://opensource.org/licenses/bsd-license.php
6 #
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
9
10 #
11 # This file is used to collect the Variable checking information
12 #
13
14 # #
15 # Import Modules
16 #
17 import os
18 from Common.RangeExpression import RangeExpression
19 from Common.Misc import *
20 from StringIO import StringIO
21 from struct import pack
22 from Common.DataType import *
23
24 class VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER(object):
25 def __init__(self):
26 self.var_check_info = []
27
28 def push_back(self, var_check_tab):
29 for tab in self.var_check_info:
30 if tab.equal(var_check_tab):
31 tab.merge(var_check_tab)
32 break
33 else:
34 self.var_check_info.append(var_check_tab)
35
36 def dump(self, dest, Phase):
37
38 FormatMap = {}
39 FormatMap[1] = "=B"
40 FormatMap[2] = "=H"
41 FormatMap[4] = "=L"
42 FormatMap[8] = "=Q"
43
44 if not os.path.isabs(dest):
45 return
46 if not os.path.exists(dest):
47 os.mkdir(dest)
48 BinFileName = "PcdVarCheck.bin"
49 BinFilePath = os.path.join(dest, BinFileName)
50 Buffer = ''
51 index = 0
52 for var_check_tab in self.var_check_info:
53 index += 1
54 realLength = 0
55 realLength += 32
56 Name = var_check_tab.Name[1:-1]
57 NameChars = Name.split(",")
58 realLength += len(NameChars)
59 if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4):
60 realLength += (4 - (realLength % 4))
61 itemIndex = 0
62 for item in var_check_tab.validtab:
63 itemIndex += 1
64 realLength += 5
65 for v_data in item.data:
66 if type(v_data) in (int, long):
67 realLength += item.StorageWidth
68 else:
69 realLength += item.StorageWidth
70 realLength += item.StorageWidth
71 if (index == len(self.var_check_info)) :
72 if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
73 realLength += (4 - (realLength % 4))
74 else:
75 if realLength % 4:
76 realLength += (4 - (realLength % 4))
77 var_check_tab.Length = realLength
78 realLength = 0
79 index = 0
80 for var_check_tab in self.var_check_info:
81 index += 1
82
83 b = pack("=H", var_check_tab.Revision)
84 Buffer += b
85 realLength += 2
86
87 b = pack("=H", var_check_tab.HeaderLength)
88 Buffer += b
89 realLength += 2
90
91 b = pack("=L", var_check_tab.Length)
92 Buffer += b
93 realLength += 4
94
95 b = pack("=B", var_check_tab.Type)
96 Buffer += b
97 realLength += 1
98
99 for i in range(0, 3):
100 b = pack("=B", var_check_tab.Reserved)
101 Buffer += b
102 realLength += 1
103
104 b = pack("=L", var_check_tab.Attributes)
105 Buffer += b
106 realLength += 4
107
108 Guid = var_check_tab.Guid
109 b = pack('=LHHBBBBBBBB',
110 Guid[0],
111 Guid[1],
112 Guid[2],
113 Guid[3],
114 Guid[4],
115 Guid[5],
116 Guid[6],
117 Guid[7],
118 Guid[8],
119 Guid[9],
120 Guid[10],
121 )
122 Buffer += b
123 realLength += 16
124
125 Name = var_check_tab.Name[1:-1]
126 NameChars = Name.split(",")
127 for NameChar in NameChars:
128 NameCharNum = int(NameChar, 16)
129 b = pack("=B", NameCharNum)
130 Buffer += b
131 realLength += 1
132
133 if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4):
134 for i in range(4 - (realLength % 4)):
135 b = pack("=B", var_check_tab.pad)
136 Buffer += b
137 realLength += 1
138 itemIndex = 0
139 for item in var_check_tab.validtab:
140 itemIndex += 1
141
142 b = pack("=B", item.Type)
143 Buffer += b
144 realLength += 1
145
146 b = pack("=B", item.Length)
147 Buffer += b
148 realLength += 1
149
150 b = pack("=H", int(item.VarOffset, 16))
151 Buffer += b
152 realLength += 2
153
154 b = pack("=B", item.StorageWidth)
155 Buffer += b
156 realLength += 1
157 for v_data in item.data:
158 if type(v_data) in (int, long):
159 b = pack(FormatMap[item.StorageWidth], v_data)
160 Buffer += b
161 realLength += item.StorageWidth
162 else:
163 b = pack(FormatMap[item.StorageWidth], v_data[0])
164 Buffer += b
165 realLength += item.StorageWidth
166 b = pack(FormatMap[item.StorageWidth], v_data[1])
167 Buffer += b
168 realLength += item.StorageWidth
169
170 if (index == len(self.var_check_info)) :
171 if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
172 for i in range(4 - (realLength % 4)):
173 b = pack("=B", var_check_tab.pad)
174 Buffer += b
175 realLength += 1
176 else:
177 if realLength % 4:
178 for i in range(4 - (realLength % 4)):
179 b = pack("=B", var_check_tab.pad)
180 Buffer += b
181 realLength += 1
182
183 DbFile = StringIO()
184 if Phase == 'DXE' and os.path.exists(BinFilePath):
185 BinFile = open(BinFilePath, "rb")
186 BinBuffer = BinFile.read()
187 BinFile.close()
188 BinBufferSize = len(BinBuffer)
189 if (BinBufferSize % 4):
190 for i in range(4 - (BinBufferSize % 4)):
191 b = pack("=B", VAR_CHECK_PCD_VARIABLE_TAB.pad)
192 BinBuffer += b
193 Buffer = BinBuffer + Buffer
194 DbFile.write(Buffer)
195 SaveFileOnChange(BinFilePath, DbFile.getvalue(), True)
196
197
198 class VAR_CHECK_PCD_VARIABLE_TAB(object):
199 pad = 0xDA
200 def __init__(self, TokenSpaceGuid, PcdCName):
201 self.Revision = 0x0001
202 self.HeaderLength = 0
203 self.Length = 0 # Length include this header
204 self.Type = 0
205 self.Reserved = 0
206 self.Attributes = 0x00000000
207 self.Guid = eval("[" + TokenSpaceGuid.replace("{", "").replace("}", "") + "]")
208 self.Name = PcdCName
209 self.validtab = []
210
211 def UpdateSize(self):
212 self.HeaderLength = 32 + len(self.Name.split(","))
213 self.Length = 32 + len(self.Name.split(",")) + self.GetValidTabLen()
214
215 def GetValidTabLen(self):
216 validtablen = 0
217 for item in self.validtab:
218 validtablen += item.Length
219 return validtablen
220
221 def SetAttributes(self, attributes):
222 self.Attributes = attributes
223
224 def push_back(self, valid_obj):
225 if valid_obj is not None:
226 self.validtab.append(valid_obj)
227
228 def equal(self, varchecktab):
229 if self.Guid == varchecktab.Guid and self.Name == varchecktab.Name:
230 return True
231 else:
232 return False
233
234 def merge(self, varchecktab):
235 for validobj in varchecktab.validtab:
236 if validobj in self.validtab:
237 continue
238 self.validtab.append(validobj)
239 self.UpdateSize()
240
241
242 class VAR_CHECK_PCD_VALID_OBJ(object):
243 def __init__(self, VarOffset, data, PcdDataType):
244 self.Type = 1
245 self.Length = 0 # Length include this header
246 self.VarOffset = VarOffset
247 self.StorageWidth = 0
248 self.PcdDataType = PcdDataType.strip()
249 self.rawdata = data
250 self.data = set()
251 self.ValidData = True
252 self.updateStorageWidth()
253
254 def updateStorageWidth(self):
255 try:
256 self.StorageWidth = MAX_SIZE_TYPE[self.PcdDataType]
257 except:
258 self.StorageWidth = 0
259 self.ValidData = False
260
261 def __eq__(self, validObj):
262 return validObj and self.VarOffset == validObj.VarOffset
263
264 class VAR_CHECK_PCD_VALID_LIST(VAR_CHECK_PCD_VALID_OBJ):
265 def __init__(self, VarOffset, validlist, PcdDataType):
266 super(VAR_CHECK_PCD_VALID_LIST, self).__init__(VarOffset, validlist, PcdDataType)
267 self.Type = 1
268 self.update_data()
269 self.update_size()
270 def update_data(self):
271 valid_num_list = []
272 data_list = []
273 for item in self.rawdata:
274 valid_num_list.extend(item.split(','))
275
276 for valid_num in valid_num_list:
277 valid_num = valid_num.strip()
278
279 if valid_num.startswith('0x') or valid_num.startswith('0X'):
280 data_list.append(int(valid_num, 16))
281 else:
282 data_list.append(int(valid_num))
283
284
285 self.data = set(data_list)
286
287 def update_size(self):
288 self.Length = 5 + len(self.data) * self.StorageWidth
289
290
291 class VAR_CHECK_PCD_VALID_RANGE(VAR_CHECK_PCD_VALID_OBJ):
292 def __init__(self, VarOffset, validrange, PcdDataType):
293 super(VAR_CHECK_PCD_VALID_RANGE, self).__init__(VarOffset, validrange, PcdDataType)
294 self.Type = 2
295 self.update_data()
296 self.update_size()
297 def update_data(self):
298 RangeExpr = ""
299 data_list = []
300 i = 0
301 for item in self.rawdata:
302 if i == 0:
303 RangeExpr = "( " + item + " )"
304 else:
305 RangeExpr = RangeExpr + "OR ( " + item + " )"
306 range_result = RangeExpression(RangeExpr, self.PcdDataType)(True)
307 for rangelist in range_result:
308 for obj in rangelist.pop():
309 data_list.append((obj.start, obj.end))
310 self.data = set(data_list)
311
312 def update_size(self):
313 self.Length = 5 + len(self.data) * 2 * self.StorageWidth
314
315
316 class VAR_VALID_OBJECT_FACTORY(object):
317 def __init__(self):
318 pass
319 @staticmethod
320 def Get_valid_object(PcdClass, VarOffset):
321 if PcdClass.validateranges:
322 return VAR_CHECK_PCD_VALID_RANGE(VarOffset, PcdClass.validateranges, PcdClass.DatumType)
323 if PcdClass.validlists:
324 return VAR_CHECK_PCD_VALID_LIST(VarOffset, PcdClass.validlists, PcdClass.DatumType)
325 else:
326 return None