]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/BPDG/GenVpd.py
Fix the corner case when there is only "\0\0" appended and the Index is 1. Return...
[mirror_edk2.git] / BaseTools / Source / Python / BPDG / GenVpd.py
CommitLineData
111be80f 1## @file\r
2# This file include GenVpd class for fix the Vpd type PCD offset, and PcdEntry for describe\r
3# and process each entry of vpd type PCD.\r
4#\r
5# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
6#\r
7# This program and the accompanying materials\r
8# are licensed and made available under the terms and conditions of the BSD License\r
9# which accompanies this distribution. The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16import os\r
17import StringIO\r
18import StringTable as st\r
19import array\r
20\r
21from struct import *\r
22import Common.EdkLogger as EdkLogger\r
23import Common.BuildToolError as BuildToolError\r
24\r
25_FORMAT_CHAR = {1: 'B',\r
26 2: 'H',\r
27 4: 'I',\r
28 8: 'Q'\r
29 }\r
30\r
31class PcdEntry:\r
32 def __init__(self, PcdCName, PcdOffset, PcdSize, PcdValue, Lineno=None, FileName=None, PcdUnpackValue=None, \r
33 PcdBinOffset=None, PcdBinSize=None):\r
34 self.PcdCName = PcdCName.strip()\r
35 self.PcdOffset = PcdOffset.strip()\r
36 self.PcdSize = PcdSize.strip()\r
37 self.PcdValue = PcdValue.strip()\r
38 self.Lineno = Lineno.strip()\r
39 self.FileName = FileName.strip()\r
40 self.PcdUnpackValue = PcdUnpackValue\r
41 self.PcdBinOffset = PcdBinOffset\r
42 self.PcdBinSize = PcdBinSize\r
43 \r
44 if self.PcdValue == '' :\r
45 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
46 "Invalid PCD format(Name: %s File: %s line: %s) , no Value specified!" %(self.PcdCName, self.FileName, self.Lineno))\r
47 \r
48 if self.PcdOffset == '' :\r
49 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
50 "Invalid PCD format(Name: %s File: %s Line: %s) , no Offset specified!" %(self.PcdCName, self.FileName, self.Lineno))\r
51 \r
52 if self.PcdSize == '' :\r
53 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
54 "Invalid PCD format(Name: %s File: %s Line: %s), no PcdSize specified!" %(self.PcdCName, self.FileName, self.Lineno)) \r
55 \r
56 self._GenOffsetValue ()\r
57 \r
58 def _IsBoolean(self, ValueString):\r
59 if ValueString.upper() in ["TRUE", "FALSE"]:\r
60 return True\r
61 return False\r
62 \r
63 def _GenOffsetValue(self):\r
64 if self.PcdOffset != "*" :\r
65 try:\r
66 self.PcdBinOffset = int (self.PcdOffset)\r
67 except:\r
68 try:\r
69 self.PcdBinOffset = int(self.PcdOffset, 16)\r
70 except:\r
71 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
72 "Invalid offset value %s for PCD %s (File: %s Line: %s)" % (self.PcdOffset, self.PcdCName, self.FileName, self.Lineno)) \r
73 \r
74 def _PackBooleanValue(self, ValueString):\r
75 if ValueString.upper() == "TRUE":\r
76 try: \r
77 self.PcdValue = pack(_FORMAT_CHAR[1], 1)\r
78 except:\r
79 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
80 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno)) \r
81 else:\r
82 try:\r
83 self.PcdValue = pack(_FORMAT_CHAR[1], 0)\r
84 except:\r
85 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
86 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno)) \r
87 \r
88 def _PackIntValue(self, IntValue, Size):\r
89 if Size not in _FORMAT_CHAR.keys():\r
90 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
91 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size, self.PcdCName, self.FileName, self.Lineno)) \r
92 try:\r
93 self.PcdValue = pack(_FORMAT_CHAR[Size], IntValue)\r
94 except:\r
95 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
96 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno)) \r
97 \r
98 def _PackPtrValue(self, ValueString, Size):\r
99 if ValueString.startswith('L"'):\r
100 self._PackUnicode(ValueString, Size)\r
101 elif ValueString.startswith('{') and ValueString.endswith('}'):\r
102 self._PackByteArray(ValueString, Size)\r
103 elif ValueString.startswith('"') and ValueString.endswith('"'):\r
104 self._PackString(ValueString, Size)\r
105 else:\r
106 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
107 "Invalid VOID* type PCD %s value %s (File: %s Line: %s)" % (self.PcdCName, ValueString, self.FileName, self.Lineno)) \r
108 \r
109 def _PackString(self, ValueString, Size):\r
110 if (Size < 0):\r
111 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
112 "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % (self.PcdBinSize, self.PcdCName, self.FileName, self.Lineno))\r
113 if (ValueString == ""):\r
114 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid parameter ValueString %s of PCD %s!(File: %s Line: %s)" % (self.PcdUnpackValue, self.PcdCName, self.FileName, self.Lineno)) \r
115 if (len(ValueString) < 2):\r
116 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s)" % (self.PcdCName, self.PcdUnpackValue, self.FileName, self.Lineno))\r
117 \r
118 ValueString = ValueString[1:-1]\r
119 if len(ValueString) + 1 > Size:\r
120 EdkLogger.error("BPDG", BuildToolError.RESOURCE_OVERFLOW, \r
121 "PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString, Size, self.FileName, self.Lineno))\r
122 try:\r
123 self.PcdValue= pack('%ds' % Size, ValueString)\r
124 except:\r
125 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
126 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno)) \r
127 \r
128 def _PackByteArray(self, ValueString, Size):\r
129 if (Size < 0): \r
130 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % (self.PcdBinSize, self.PcdCName, self.FileName, self.Lineno))\r
131 if (ValueString == ""):\r
132 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid parameter ValueString %s of PCD %s!(File: %s Line: %s)" % (self.PcdUnpackValue, self.PcdCName, self.FileName, self.Lineno)) \r
133 \r
134 ValueString = ValueString.strip()\r
135 ValueString = ValueString.lstrip('{').strip('}')\r
136 ValueList = ValueString.split(',')\r
137 ValueList = [item.strip() for item in ValueList]\r
138 \r
139 if len(ValueList) > Size:\r
140 EdkLogger.error("BPDG", BuildToolError.RESOURCE_OVERFLOW, \r
141 "The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString, Size, self.FileName, self.Lineno))\r
142 \r
143 ReturnArray = array.array('B')\r
144 \r
145 for Index in xrange(len(ValueList)):\r
146 Value = None\r
147 if ValueList[Index].startswith('0x'):\r
148 # translate hex value\r
149 try:\r
150 Value = int(ValueList[Index], 16)\r
151 except:\r
152 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
153 "The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \\r
154 (ValueList[Index], ValueString, self.FileName, self.Lineno))\r
155 else:\r
156 # translate decimal value\r
157 try:\r
158 Value = int(ValueList[Index], 10)\r
159 except:\r
160 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID,\r
161 "The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \\r
162 (ValueList[Index], ValueString, self.FileName, self.Lineno))\r
163 \r
164 if Value > 255:\r
165 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
166 "The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" %\\r
167 (ValueList[Index], ValueString, self.FileName, self.Lineno))\r
168 \r
169 ReturnArray.append(Value)\r
170 \r
171 for Index in xrange(len(ValueList), Size):\r
172 ReturnArray.append(0)\r
173 \r
174 self.PcdValue = ReturnArray.tolist()\r
175\r
176 ## Pack a unicode PCD value into byte array.\r
177 # \r
178 # A unicode string for a PCD should be in format as L"".\r
179 #\r
180 def _PackUnicode(self, UnicodeString, Size):\r
181 if (Size < 0): \r
182 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" %\\r
183 (self.PcdBinSize, self.PcdCName, self.FileName, self.Lineno))\r
184 if (len(UnicodeString) < 3):\r
185 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s)" %\\r
186 (self.PcdCName, self.PcdUnpackValue, self.FileName, self.Lineno))\r
187 \r
188 UnicodeString = UnicodeString[2:-1]\r
189 \r
190 if (len(UnicodeString) + 1) * 2 > Size:\r
191 EdkLogger.error("BPDG", BuildToolError.RESOURCE_OVERFLOW,\r
192 "The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \\r
193 (UnicodeString, Size, self.FileName, self.Lineno))\r
194 \r
195 ReturnArray = array.array('B')\r
196 for Value in UnicodeString:\r
197 try:\r
198 ReturnArray.append(ord(Value))\r
199 ReturnArray.append(0)\r
200 except:\r
201 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, \r
202 "Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \\r
203 (Value, UnicodeString, self.FileName, self.Lineno))\r
204 \r
205 for Index in range(len(UnicodeString) * 2, Size):\r
206 ReturnArray.append(0)\r
207 \r
208 self.PcdValue = ReturnArray.tolist() \r
209 \r
210class GenVPD :\r
211 \r
212 ## Constructor of DscBuildData\r
213 #\r
214 # Initialize object of GenVPD\r
215 # @Param InputFileName The filename include the vpd type pcd information\r
216 # @param MapFileName The filename of map file that stores vpd type pcd information.\r
217 # This file will be generated by the BPDG tool after fix the offset\r
218 # and adjust the offset to make the pcd data aligned.\r
219 # @param VpdFileName The filename of Vpd file that hold vpd pcd information.\r
220 #\r
221 def __init__(self, InputFileName, MapFileName, VpdFileName):\r
222 self.InputFileName = InputFileName\r
223 self.MapFileName = MapFileName\r
224 self.VpdFileName = VpdFileName\r
225 self.FileLinesList = []\r
226 self.PcdFixedOffsetSizeList = []\r
227 self.PcdUnknownOffsetList = []\r
228 try:\r
229 fInputfile = open(InputFileName, "r", 0)\r
230 try:\r
231 self.FileLinesList = fInputfile.readlines()\r
232 except:\r
233 EdkLogger.error("BPDG", BuildToolError.FILE_READ_FAILURE, "File read failed for %s" %InputFileName,None)\r
234 finally:\r
235 fInputfile.close()\r
236 except:\r
237 EdkLogger.error("BPDG", BuildToolError.FILE_OPEN_FAILURE, "File open failed for %s" %InputFileName,None)\r
238 \r
239 ##\r
240 # Parser the input file which is generated by the build tool. Convert the value of each pcd's \r
241 # from string to it's real format. Also remove the useless line in the input file.\r
242 # \r
243 def ParserInputFile (self):\r
244 count = 0 \r
245 for line in self.FileLinesList:\r
246 # Strip "\r\n" generated by readlines ().\r
247 line = line.strip()\r
248 line = line.rstrip(os.linesep)\r
249 \r
250 # Skip the comment line\r
251 if (not line.startswith("#")) and len(line) > 1 : \r
252 self.FileLinesList[count] = line.split('|')\r
253 # Store the line number\r
254 self.FileLinesList[count].append(str(count+1))\r
255 elif len(line) <= 1 :\r
256 # Set the blank line to "None"\r
257 self.FileLinesList[count] = None\r
258 else :\r
259 # Set the comment line to "None"\r
260 self.FileLinesList[count] = None\r
261 count += 1\r
262 \r
263 # The line count contain usage information\r
264 count = 0 \r
265 # Delete useless lines\r
266 while (True) :\r
267 try :\r
268 if (self.FileLinesList[count] == None) :\r
269 del(self.FileLinesList[count])\r
270 else :\r
271 count += 1\r
272 except :\r
273 break \r
274 #\r
275 # After remove the useless line, if there are no data remain in the file line list,\r
276 # Report warning messages to user's.\r
277 # \r
278 if len(self.FileLinesList) == 0 :\r
279 EdkLogger.warn('BPDG', BuildToolError.RESOURCE_NOT_AVAILABLE, \r
280 "There are no VPD type pcds defined in DSC file, Please check it.")\r
281 \r
282 # Process the pcds one by one base on the pcd's value and size\r
283 count = 0\r
284 for line in self.FileLinesList: \r
285 if line != None :\r
286 PCD = PcdEntry(line[0], line[1], line[2], line[3], line[4], self.InputFileName) \r
287 # Strip the space char\r
288 PCD.PcdCName = PCD.PcdCName.strip(' ')\r
289 PCD.PcdOffset = PCD.PcdOffset.strip(' ')\r
290 PCD.PcdSize = PCD.PcdSize.strip(' ')\r
291 PCD.PcdValue = PCD.PcdValue.strip(' ') \r
292 PCD.Lineno = PCD.Lineno.strip(' ')\r
293 \r
294 #\r
295 # Store the original pcd value.\r
296 # This information will be useful while generate the output map file.\r
297 #\r
298 PCD.PcdUnpackValue = str(PCD.PcdValue) \r
299\r
300 #\r
301 # Translate PCD size string to an integer value.\r
302 PackSize = None\r
303 try:\r
304 PackSize = int(PCD.PcdSize, 10)\r
305 PCD.PcdBinSize = PackSize\r
306 except:\r
307 try:\r
308 PackSize = int(PCD.PcdSize, 16)\r
309 PCD.PcdBinSize = PackSize\r
310 except:\r
311 EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid PCD size value %s at file: %s line: %s" % (PCD.PcdSize, self.InputFileName, PCD.Lineno))\r
312 \r
313 if PCD._IsBoolean(PCD.PcdValue):\r
314 PCD._PackBooleanValue(PCD.PcdValue)\r
315 self.FileLinesList[count] = PCD\r
316 count += 1\r
317 continue\r
318 #\r
319 # Try to translate value to an integer firstly.\r
320 #\r
321 IsInteger = True\r
322 PackValue = None\r
323 try:\r
324 PackValue = int(PCD.PcdValue)\r
325 except:\r
326 try:\r
327 PackValue = int(PCD.PcdValue, 16)\r
328 except:\r
329 IsInteger = False\r
330 \r
331 if IsInteger:\r
332 PCD._PackIntValue(PackValue, PackSize)\r
333 else:\r
334 PCD._PackPtrValue(PCD.PcdValue, PackSize)\r
335 \r
336 self.FileLinesList[count] = PCD\r
337 count += 1\r
338 else :\r
339 continue\r
340 \r
341 ##\r
342 # This function used to create a clean list only contain useful information and reorganized to make it \r
343 # easy to be sorted\r
344 #\r
345 def FormatFileLine (self) :\r
346 \r
347 for eachPcd in self.FileLinesList :\r
348 if eachPcd.PcdOffset != '*' :\r
349 # Use pcd's Offset value as key, and pcd's Value as value \r
350 self.PcdFixedOffsetSizeList.append(eachPcd)\r
351 else :\r
352 # Use pcd's CName as key, and pcd's Size as value\r
353 self.PcdUnknownOffsetList.append(eachPcd)\r
354 \r
355 \r
356 ##\r
357 # This function is use to fix the offset value which the not specified in the map file.\r
358 # Usually it use the star (meaning any offset) character in the offset field\r
359 # \r
360 def FixVpdOffset (self): \r
361 # At first, the offset should start at 0\r
362 # Sort fixed offset list in order to find out where has free spaces for the pcd's offset\r
363 # value is "*" to insert into. \r
364 \r
365 self.PcdFixedOffsetSizeList.sort(lambda x,y: cmp(x.PcdBinOffset, y.PcdBinOffset)) \r
366 \r
367 #\r
368 # Sort the un-fixed pcd's offset by it's size.\r
369 #\r
370 self.PcdUnknownOffsetList.sort(lambda x,y: cmp(x.PcdBinSize, y.PcdBinSize))\r
371 \r
372 #\r
373 # Process all Offset value are "*"\r
374 #\r
375 if (len(self.PcdFixedOffsetSizeList) == 0) and (len(self.PcdUnknownOffsetList) != 0) :\r
376 # The offset start from 0\r
377 NowOffset = 0\r
378 for Pcd in self.PcdUnknownOffsetList : \r
379 Pcd.PcdBinOffset = NowOffset\r
380 Pcd.PcdOffset = str(hex(Pcd.PcdBinOffset))\r
381 NowOffset += Pcd.PcdBinSize\r
382 \r
383 self.PcdFixedOffsetSizeList = self.PcdUnknownOffsetList\r
384 return\r
385 \r
386 # Check the offset of VPD type pcd's offset start from 0. \r
387 if self.PcdFixedOffsetSizeList[0].PcdBinOffset != 0 :\r
388 EdkLogger.warn("BPDG", "The offset of VPD type pcd should start with 0, please check it.",\r
389 None) \r
390 \r
391 # Judge whether the offset in fixed pcd offset list is overlapped or not.\r
392 lenOfList = len(self.PcdFixedOffsetSizeList)\r
393 count = 0 \r
394 while (count < lenOfList - 1) :\r
395 PcdNow = self.PcdFixedOffsetSizeList[count]\r
396 PcdNext = self.PcdFixedOffsetSizeList[count+1]\r
397 # Two pcd's offset is same \r
398 if PcdNow.PcdBinOffset == PcdNext.PcdBinOffset :\r
399 EdkLogger.error("BPDG", BuildToolError.ATTRIBUTE_GET_FAILURE, \r
400 "The offset of %s at line: %s is same with %s at line: %s in file %s" %\\r
401 (PcdNow.PcdCName, PcdNow.Lineno, PcdNext.PcdCName, PcdNext.Lineno, PcdNext.FileName),\r
402 None)\r
403 \r
404 # Overlapped \r
405 if PcdNow.PcdBinOffset + PcdNow.PcdBinSize > PcdNext.PcdBinOffset :\r
406 EdkLogger.error("BPDG", BuildToolError.ATTRIBUTE_GET_FAILURE, \r
407 "The offset of %s at line: %s is overlapped with %s at line: %s in file %s" %\\r
408 (PcdNow.PcdCName, PcdNow.Lineno, PcdNext.PcdCName, PcdNext.Lineno, PcdNext.FileName),\r
409 None)\r
410 \r
411 # Has free space, raise a warning message \r
412 if PcdNow.PcdBinOffset + PcdNow.PcdBinSize < PcdNext.PcdBinOffset :\r
413 EdkLogger.warn("BPDG", BuildToolError.ATTRIBUTE_GET_FAILURE, \r
414 "The offsets have free space of between %s at line: %s and %s at line: %s in file %s" %\\r
415 (PcdNow.PcdCName, PcdNow.Lineno, PcdNext.PcdCName, PcdNext.Lineno, PcdNext.FileName),\r
416 None)\r
417 count += 1\r
418 \r
419 LastOffset = self.PcdFixedOffsetSizeList[0].PcdBinOffset\r
420 FixOffsetSizeListCount = 0\r
421 lenOfList = len(self.PcdFixedOffsetSizeList)\r
422 lenOfUnfixedList = len(self.PcdUnknownOffsetList)\r
423 \r
424 ##\r
425 # Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds. \r
426 # \r
427 while (FixOffsetSizeListCount < lenOfList) :\r
428 \r
429 eachFixedPcd = self.PcdFixedOffsetSizeList[FixOffsetSizeListCount] \r
430 NowOffset = eachFixedPcd.PcdBinOffset\r
431 \r
432 # Has free space \r
433 if LastOffset < NowOffset :\r
434 if lenOfUnfixedList != 0 :\r
435 countOfUnfixedList = 0\r
436 while(countOfUnfixedList < lenOfUnfixedList) : \r
437 #needFixPcdCName, needFixPcdOffset, needFixPcdSize, needFixPcdValue, needFixUnpackValue = self.PcdUnknownOffsetList[countOfUnfixedList][0:6]\r
438 eachUnfixedPcd = self.PcdUnknownOffsetList[countOfUnfixedList]\r
439 needFixPcdSize = eachUnfixedPcd.PcdBinSize\r
440 needFixPcdOffset = eachUnfixedPcd.PcdOffset\r
441 # Not been fixed\r
442 if eachUnfixedPcd.PcdOffset == '*' :\r
443 # The offset un-fixed pcd can write into this free space\r
444 if needFixPcdSize <= (NowOffset - LastOffset) :\r
445 # Change the offset value of un-fixed pcd\r
446 eachUnfixedPcd.PcdOffset = str(hex(LastOffset))\r
447 eachUnfixedPcd.PcdBinOffset = LastOffset\r
448 # Insert this pcd into fixed offset pcd list.\r
449 self.PcdFixedOffsetSizeList.insert(FixOffsetSizeListCount,eachUnfixedPcd)\r
450 \r
451 # Delete the item's offset that has been fixed and added into fixed offset list\r
452 self.PcdUnknownOffsetList.pop(countOfUnfixedList)\r
453 \r
454 # After item added, should enlarge the length of fixed pcd offset list\r
455 lenOfList += 1 \r
456 FixOffsetSizeListCount += 1\r
457 \r
458 # Decrease the un-fixed pcd offset list's length\r
459 countOfUnfixedList += 1\r
460 lenOfUnfixedList -= 1\r
461 \r
462 # Modify the last offset value \r
463 LastOffset += needFixPcdSize\r
464 continue \r
465 else :\r
466 # It can not insert into those two pcds, need to check stiil has other space can store it.\r
467 FixOffsetSizeListCount += 1\r
468 break \r
469 else :\r
470 continue\r
471 # Set the FixOffsetSizeListCount = lenOfList for quit the loop\r
472 else :\r
473 FixOffsetSizeListCount = lenOfList \r
474 \r
475 # No free space, smoothly connect with previous pcd. \r
476 elif LastOffset == NowOffset :\r
477 LastOffset = NowOffset + eachFixedPcd.PcdBinSize\r
478 FixOffsetSizeListCount += 1\r
479 # Usually it will not enter into this thunk, if so, means it overlapped. \r
480 else :\r
481 EdkLogger.error("BPDG", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, \r
482 "The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" %\\r
483 (eachFixedPcd.PcdCName, eachFixedPcd.PcdOffset, eachFixedPcd.InputFileName, eachFixedPcd.Lineno),\r
484 None)\r
485 FixOffsetSizeListCount += 1\r
486 \r
487 # Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list. \r
488 lenOfUnfixedList = len(self.PcdUnknownOffsetList)\r
489 lenOfList = len(self.PcdFixedOffsetSizeList)\r
490 while (lenOfUnfixedList > 0) :\r
491 # Still has items need to process\r
492 # The last pcd instance\r
493 LastPcd = self.PcdFixedOffsetSizeList[lenOfList-1]\r
494 NeedFixPcd = self.PcdUnknownOffsetList[0]\r
495 \r
496 NeedFixPcd.PcdBinOffset = LastPcd.PcdBinOffset + LastPcd.PcdBinSize\r
497 NeedFixPcd.PcdOffset = str(hex(NeedFixPcd.PcdBinOffset))\r
498 \r
499 # Insert this pcd into fixed offset pcd list's tail.\r
500 self.PcdFixedOffsetSizeList.insert(lenOfList, NeedFixPcd)\r
501 # Delete the item's offset that has been fixed and added into fixed offset list\r
502 self.PcdUnknownOffsetList.pop(0)\r
503 \r
504 lenOfList += 1\r
505 lenOfUnfixedList -= 1 \r
506 ##\r
507 # Write the final data into output files.\r
508 # \r
509 def GenerateVpdFile (self, MapFileName, BinFileName):\r
510 #Open an VPD file to process\r
511\r
512 try:\r
513 fVpdFile = open (BinFileName, "wb", 0) \r
514 except:\r
515 # Open failed\r
516 EdkLogger.error("BPDG", BuildToolError.FILE_OPEN_FAILURE, "File open failed for %s" %self.VpdFileName,None)\r
517 \r
518 try :\r
519 fMapFile = open (MapFileName, "w", 0)\r
520 except:\r
521 # Open failed\r
522 EdkLogger.error("BPDG", BuildToolError.FILE_OPEN_FAILURE, "File open failed for %s" %self.MapFileName,None)\r
523 \r
524 # Use a instance of StringIO to cache data\r
525 fStringIO = StringIO.StringIO('') \r
526 \r
527 # Write the header of map file.\r
528 try :\r
529 fMapFile.write (st.MAP_FILE_COMMENT_TEMPLATE + "\n")\r
530 except:\r
531 EdkLogger.error("BPDG", BuildToolError.FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %self.MapFileName,None) \r
532 \r
533 for eachPcd in self.PcdFixedOffsetSizeList :\r
534 # write map file\r
535 try :\r
536 fMapFile.write("%s | %s | %s | %s \n" % (eachPcd.PcdCName, eachPcd.PcdOffset, eachPcd.PcdSize,eachPcd.PcdUnpackValue))\r
537 except:\r
538 EdkLogger.error("BPDG", BuildToolError.FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %self.MapFileName,None) \r
539 \r
540 # Write Vpd binary file\r
541 fStringIO.seek (eachPcd.PcdBinOffset) \r
542 if isinstance(eachPcd.PcdValue, list):\r
543 ValueList = [chr(Item) for Item in eachPcd.PcdValue]\r
544 fStringIO.write(''.join(ValueList)) \r
545 else: \r
546 fStringIO.write (eachPcd.PcdValue)\r
547 \r
548 try : \r
549 fVpdFile.write (fStringIO.getvalue())\r
550 except:\r
551 EdkLogger.error("BPDG", BuildToolError.FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %self.VpdFileName,None)\r
552 \r
553 fStringIO.close ()\r
554 fVpdFile.close ()\r
555 fMapFile.close ()\r
556 \r