2 # This file include GenVpd class for fix the Vpd type PCD offset, and PcdEntry for describe
3 # and process each entry of vpd type PCD.
5 # Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
18 import StringTable
as st
21 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
23 import Common
.EdkLogger
as EdkLogger
24 import Common
.BuildToolError
as BuildToolError
26 _FORMAT_CHAR
= {1: 'B',
32 ## The VPD PCD data structure for store and process each VPD PCD entry.
34 # This class contain method to format and pack pcd's value.
37 def __init__(self
, PcdCName
, SkuId
,PcdOffset
, PcdSize
, PcdValue
, Lineno
=None, FileName
=None, PcdUnpackValue
=None,
38 PcdBinOffset
=None, PcdBinSize
=None):
39 self
.PcdCName
= PcdCName
.strip()
40 self
.SkuId
= SkuId
.strip()
41 self
.PcdOffset
= PcdOffset
.strip()
42 self
.PcdSize
= PcdSize
.strip()
43 self
.PcdValue
= PcdValue
.strip()
44 self
.Lineno
= Lineno
.strip()
45 self
.FileName
= FileName
.strip()
46 self
.PcdUnpackValue
= PcdUnpackValue
47 self
.PcdBinOffset
= PcdBinOffset
48 self
.PcdBinSize
= PcdBinSize
50 if self
.PcdValue
== '' :
51 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
52 "Invalid PCD format(Name: %s File: %s line: %s) , no Value specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
54 if self
.PcdOffset
== '' :
55 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
56 "Invalid PCD format(Name: %s File: %s Line: %s) , no Offset specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
58 if self
.PcdSize
== '' :
59 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
60 "Invalid PCD format(Name: %s File: %s Line: %s), no PcdSize specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
62 self
._GenOffsetValue
()
64 ## Analyze the string value to judge the PCD's datum type euqal to Boolean or not.
66 # @param ValueString PCD's value
67 # @param Size PCD's size
69 # @retval True PCD's datum type is Boolean
70 # @retval False PCD's datum type is not Boolean.
72 def _IsBoolean(self
, ValueString
, Size
):
74 if ValueString
.upper() in ["TRUE", "FALSE"]:
76 elif ValueString
in ["0", "1", "0x0", "0x1", "0x00", "0x01"]:
81 ## Convert the PCD's value from string to integer.
83 # This function will try to convert the Offset value form string to integer
84 # for both hexadecimal and decimal.
86 def _GenOffsetValue(self
):
87 if self
.PcdOffset
!= "*" :
89 self
.PcdBinOffset
= int (self
.PcdOffset
)
92 self
.PcdBinOffset
= int(self
.PcdOffset
, 16)
94 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
95 "Invalid offset value %s for PCD %s (File: %s Line: %s)" % (self
.PcdOffset
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
97 ## Pack Boolean type VPD PCD's value form string to binary type.
99 # @param ValueString The boolean type string for pack.
102 def _PackBooleanValue(self
, ValueString
):
103 if ValueString
.upper() == "TRUE" or ValueString
in ["1", "0x1", "0x01"]:
105 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 1)
107 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
108 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
111 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 0)
113 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
114 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
116 ## Pack Integer type VPD PCD's value form string to binary type.
118 # @param ValueString The Integer type string for pack.
121 def _PackIntValue(self
, IntValue
, Size
):
122 if Size
not in _FORMAT_CHAR
.keys():
123 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
124 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
128 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
129 "PCD can't be set to negative value %d for PCD %s in UINT8 datum type(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
130 elif IntValue
>= 0x100:
131 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
132 "Too large PCD value %d for datum type UINT8 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
135 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
136 "PCD can't be set to negative value %d for PCD %s in UINT16 datum type(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
137 elif IntValue
>= 0x10000:
138 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
139 "Too large PCD value %d for datum type UINT16 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
142 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
143 "PCD can't be set to negative value %d for PCD %s in UINT32 datum type(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
144 elif IntValue
>= 0x100000000:
145 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
146 "Too large PCD value %d for datum type UINT32 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
149 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
150 "PCD can't be set to negative value %d for PCD %s in UINT32 datum type(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
151 elif IntValue
>= 0x10000000000000000:
152 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
153 "Too large PCD value %d for datum type UINT32 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
155 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
156 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
159 self
.PcdValue
= pack(_FORMAT_CHAR
[Size
], IntValue
)
161 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
162 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
164 ## Pack VOID* type VPD PCD's value form string to binary type.
166 # The VOID* type of string divided into 3 sub-type:
167 # 1: L"String", Unicode type string.
168 # 2: "String", Ascii type string.
169 # 3: {bytearray}, only support byte-array.
171 # @param ValueString The Integer type string for pack.
173 def _PackPtrValue(self
, ValueString
, Size
):
174 if ValueString
.startswith('L"'):
175 self
._PackUnicode
(ValueString
, Size
)
176 elif ValueString
.startswith('{') and ValueString
.endswith('}'):
177 self
._PackByteArray
(ValueString
, Size
)
178 elif ValueString
.startswith('"') and ValueString
.endswith('"'):
179 self
._PackString
(ValueString
, Size
)
181 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
182 "Invalid VOID* type PCD %s value %s (File: %s Line: %s)" % (self
.PcdCName
, ValueString
, self
.FileName
, self
.Lineno
))
184 ## Pack an Ascii PCD value.
186 # An Ascii string for a PCD should be in format as "".
188 def _PackString(self
, ValueString
, Size
):
190 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
191 "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
192 if (ValueString
== ""):
193 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
))
194 if (len(ValueString
) < 2):
195 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
))
197 ValueString
= ValueString
[1:-1]
198 if len(ValueString
) + 1 > Size
:
199 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
200 "PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
202 self
.PcdValue
= pack('%ds' % Size
, ValueString
)
204 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
205 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
207 ## Pack a byte-array PCD value.
209 # A byte-array for a PCD should be in format as {0x01, 0x02, ...}.
211 def _PackByteArray(self
, ValueString
, Size
):
213 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
))
214 if (ValueString
== ""):
215 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
))
217 ValueString
= ValueString
.strip()
218 ValueString
= ValueString
.lstrip('{').strip('}')
219 ValueList
= ValueString
.split(',')
220 ValueList
= [item
.strip() for item
in ValueList
]
222 if len(ValueList
) > Size
:
223 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
224 "The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
226 ReturnArray
= array
.array('B')
228 for Index
in xrange(len(ValueList
)):
230 if ValueList
[Index
].lower().startswith('0x'):
231 # translate hex value
233 Value
= int(ValueList
[Index
], 16)
235 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
236 "The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \
237 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
239 # translate decimal value
241 Value
= int(ValueList
[Index
], 10)
243 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
244 "The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \
245 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
248 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
249 "The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" % \
250 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
252 ReturnArray
.append(Value
)
254 for Index
in xrange(len(ValueList
), Size
):
255 ReturnArray
.append(0)
257 self
.PcdValue
= ReturnArray
.tolist()
259 ## Pack a unicode PCD value into byte array.
261 # A unicode string for a PCD should be in format as L"".
263 def _PackUnicode(self
, UnicodeString
, Size
):
265 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % \
266 (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
267 if (len(UnicodeString
) < 3):
268 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s)" % \
269 (self
.PcdCName
, self
.PcdUnpackValue
, self
.FileName
, self
.Lineno
))
271 UnicodeString
= UnicodeString
[2:-1]
273 if (len(UnicodeString
) + 1) * 2 > Size
:
274 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
275 "The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \
276 (UnicodeString
, Size
, self
.FileName
, self
.Lineno
))
278 ReturnArray
= array
.array('B')
279 for Value
in UnicodeString
:
281 ReturnArray
.append(ord(Value
))
282 ReturnArray
.append(0)
284 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
285 "Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \
286 (Value
, UnicodeString
, self
.FileName
, self
.Lineno
))
288 for Index
in xrange(len(UnicodeString
) * 2, Size
):
289 ReturnArray
.append(0)
291 self
.PcdValue
= ReturnArray
.tolist()
295 ## The class implementing the BPDG VPD PCD offset fix process
297 # The VPD PCD offset fix process includes:
298 # 1. Parse the input guided.txt file and store it in the data structure;
299 # 2. Format the input file data to remove unused lines;
300 # 3. Fixed offset if needed;
301 # 4. Generate output file, including guided.map and guided.bin file;
304 ## Constructor of DscBuildData
306 # Initialize object of GenVPD
307 # @Param InputFileName The filename include the vpd type pcd information
308 # @param MapFileName The filename of map file that stores vpd type pcd information.
309 # This file will be generated by the BPDG tool after fix the offset
310 # and adjust the offset to make the pcd data aligned.
311 # @param VpdFileName The filename of Vpd file that hold vpd pcd information.
313 def __init__(self
, InputFileName
, MapFileName
, VpdFileName
):
314 self
.InputFileName
= InputFileName
315 self
.MapFileName
= MapFileName
316 self
.VpdFileName
= VpdFileName
317 self
.FileLinesList
= []
318 self
.PcdFixedOffsetSizeList
= []
319 self
.PcdUnknownOffsetList
= []
321 fInputfile
= open(InputFileName
, "r", 0)
323 self
.FileLinesList
= fInputfile
.readlines()
325 EdkLogger
.error("BPDG", BuildToolError
.FILE_READ_FAILURE
, "File read failed for %s" % InputFileName
, None)
329 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % InputFileName
, None)
332 # Parser the input file which is generated by the build tool. Convert the value of each pcd's
333 # from string to it's real format. Also remove the useless line in the input file.
335 def ParserInputFile (self
):
337 for line
in self
.FileLinesList
:
338 # Strip "\r\n" generated by readlines ().
340 line
= line
.rstrip(os
.linesep
)
342 # Skip the comment line
343 if (not line
.startswith("#")) and len(line
) > 1 :
345 # Enhanced for support "|" character in the string.
347 ValueList
= ['', '', '', '','']
349 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
350 PtrValue
= ValueRe
.findall(line
)
352 ValueUpdateFlag
= False
354 if len(PtrValue
) >= 1:
355 line
= re
.sub(ValueRe
, '', line
)
356 ValueUpdateFlag
= True
358 TokenList
= line
.split('|')
359 ValueList
[0:len(TokenList
)] = TokenList
362 ValueList
[4] = PtrValue
[0]
363 self
.FileLinesList
[count
] = ValueList
364 # Store the line number
365 self
.FileLinesList
[count
].append(str(count
+ 1))
366 elif len(line
) <= 1 :
367 # Set the blank line to "None"
368 self
.FileLinesList
[count
] = None
370 # Set the comment line to "None"
371 self
.FileLinesList
[count
] = None
374 # The line count contain usage information
376 # Delete useless lines
379 if (self
.FileLinesList
[count
] == None) :
380 del(self
.FileLinesList
[count
])
386 # After remove the useless line, if there are no data remain in the file line list,
387 # Report warning messages to user's.
389 if len(self
.FileLinesList
) == 0 :
390 EdkLogger
.warn('BPDG', BuildToolError
.RESOURCE_NOT_AVAILABLE
,
391 "There are no VPD type pcds defined in DSC file, Please check it.")
393 # Process the pcds one by one base on the pcd's value and size
395 for line
in self
.FileLinesList
:
397 PCD
= PcdEntry(line
[0], line
[1], line
[2], line
[3], line
[4],line
[5], self
.InputFileName
)
398 # Strip the space char
399 PCD
.PcdCName
= PCD
.PcdCName
.strip(' ')
400 PCD
.SkuId
= PCD
.SkuId
.strip(' ')
401 PCD
.PcdOffset
= PCD
.PcdOffset
.strip(' ')
402 PCD
.PcdSize
= PCD
.PcdSize
.strip(' ')
403 PCD
.PcdValue
= PCD
.PcdValue
.strip(' ')
404 PCD
.Lineno
= PCD
.Lineno
.strip(' ')
407 # Store the original pcd value.
408 # This information will be useful while generate the output map file.
410 PCD
.PcdUnpackValue
= str(PCD
.PcdValue
)
413 # If value is Unicode string (e.g. L""), then use 2-byte alignment
414 # If value is byte array (e.g. {}), then use 8-byte alignment
416 PCD
.PcdOccupySize
= int(PCD
.PcdSize
)
417 if PCD
.PcdUnpackValue
.startswith("{"):
419 elif PCD
.PcdUnpackValue
.startswith("L"):
423 if PCD
.PcdOccupySize
% Alignment
!= 0:
424 PCD
.PcdOccupySize
= (PCD
.PcdOccupySize
/ Alignment
+ 1) * Alignment
427 # Translate PCD size string to an integer value.
430 PackSize
= int(PCD
.PcdSize
, 10)
431 PCD
.PcdBinSize
= PackSize
434 PackSize
= int(PCD
.PcdSize
, 16)
435 PCD
.PcdBinSize
= PackSize
437 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid PCD size value %s at file: %s line: %s" % (PCD
.PcdSize
, self
.InputFileName
, PCD
.Lineno
))
439 if PCD
._IsBoolean
(PCD
.PcdValue
, PCD
.PcdSize
):
440 PCD
._PackBooleanValue
(PCD
.PcdValue
)
441 self
.FileLinesList
[count
] = PCD
445 # Try to translate value to an integer firstly.
450 PackValue
= int(PCD
.PcdValue
)
453 PackValue
= int(PCD
.PcdValue
, 16)
458 PCD
._PackIntValue
(PackValue
, PackSize
)
460 PCD
._PackPtrValue
(PCD
.PcdValue
, PackSize
)
462 self
.FileLinesList
[count
] = PCD
468 # This function used to create a clean list only contain useful information and reorganized to make it
471 def FormatFileLine (self
) :
473 for eachPcd
in self
.FileLinesList
:
474 if eachPcd
.PcdOffset
!= '*' :
475 # Use pcd's Offset value as key, and pcd's Value as value
476 self
.PcdFixedOffsetSizeList
.append(eachPcd
)
478 # Use pcd's CName as key, and pcd's Size as value
479 self
.PcdUnknownOffsetList
.append(eachPcd
)
483 # This function is use to fix the offset value which the not specified in the map file.
484 # Usually it use the star (meaning any offset) character in the offset field
486 def FixVpdOffset (self
):
487 # At first, the offset should start at 0
488 # Sort fixed offset list in order to find out where has free spaces for the pcd's offset
489 # value is "*" to insert into.
491 self
.PcdFixedOffsetSizeList
.sort(lambda x
, y
: cmp(x
.PcdBinOffset
, y
.PcdBinOffset
))
494 # Sort the un-fixed pcd's offset by it's size.
496 self
.PcdUnknownOffsetList
.sort(lambda x
, y
: cmp(x
.PcdBinSize
, y
.PcdBinSize
))
499 # Process all Offset value are "*"
501 if (len(self
.PcdFixedOffsetSizeList
) == 0) and (len(self
.PcdUnknownOffsetList
) != 0) :
502 # The offset start from 0
504 for Pcd
in self
.PcdUnknownOffsetList
:
505 Pcd
.PcdBinOffset
= NowOffset
506 Pcd
.PcdOffset
= str(hex(Pcd
.PcdBinOffset
))
507 NowOffset
+= Pcd
.PcdOccupySize
509 self
.PcdFixedOffsetSizeList
= self
.PcdUnknownOffsetList
512 # Check the offset of VPD type pcd's offset start from 0.
513 if self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
!= 0 :
514 EdkLogger
.warn("BPDG", "The offset of VPD type pcd should start with 0, please check it.",
517 # Judge whether the offset in fixed pcd offset list is overlapped or not.
518 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
520 while (count
< lenOfList
- 1) :
521 PcdNow
= self
.PcdFixedOffsetSizeList
[count
]
522 PcdNext
= self
.PcdFixedOffsetSizeList
[count
+1]
523 # Two pcd's offset is same
524 if PcdNow
.PcdBinOffset
== PcdNext
.PcdBinOffset
:
525 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
526 "The offset of %s at line: %s is same with %s at line: %s in file %s" % \
527 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
531 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
> PcdNext
.PcdBinOffset
:
532 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
533 "The offset of %s at line: %s is overlapped with %s at line: %s in file %s" % \
534 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
537 # Has free space, raise a warning message
538 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
< PcdNext
.PcdBinOffset
:
539 EdkLogger
.warn("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
540 "The offsets have free space of between %s at line: %s and %s at line: %s in file %s" % \
541 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
545 LastOffset
= self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
546 FixOffsetSizeListCount
= 0
547 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
548 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
551 # Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
553 while (FixOffsetSizeListCount
< lenOfList
) :
555 eachFixedPcd
= self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
]
556 NowOffset
= eachFixedPcd
.PcdBinOffset
559 if LastOffset
< NowOffset
:
560 if lenOfUnfixedList
!= 0 :
561 countOfUnfixedList
= 0
562 while(countOfUnfixedList
< lenOfUnfixedList
) :
563 eachUnfixedPcd
= self
.PcdUnknownOffsetList
[countOfUnfixedList
]
564 needFixPcdSize
= eachUnfixedPcd
.PcdOccupySize
566 if eachUnfixedPcd
.PcdOffset
== '*' :
567 # The offset un-fixed pcd can write into this free space
568 if needFixPcdSize
<= (NowOffset
- LastOffset
) :
569 # Change the offset value of un-fixed pcd
570 eachUnfixedPcd
.PcdOffset
= str(hex(LastOffset
))
571 eachUnfixedPcd
.PcdBinOffset
= LastOffset
572 # Insert this pcd into fixed offset pcd list.
573 self
.PcdFixedOffsetSizeList
.insert(FixOffsetSizeListCount
,eachUnfixedPcd
)
575 # Delete the item's offset that has been fixed and added into fixed offset list
576 self
.PcdUnknownOffsetList
.pop(countOfUnfixedList
)
578 # After item added, should enlarge the length of fixed pcd offset list
580 FixOffsetSizeListCount
+= 1
582 # Decrease the un-fixed pcd offset list's length
583 lenOfUnfixedList
-= 1
585 # Modify the last offset value
586 LastOffset
+= needFixPcdSize
588 # It can not insert into those two pcds, need to check still has other space can store it.
589 LastOffset
= NowOffset
+ self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
].PcdOccupySize
590 FixOffsetSizeListCount
+= 1
593 # Set the FixOffsetSizeListCount = lenOfList for quit the loop
595 FixOffsetSizeListCount
= lenOfList
597 # No free space, smoothly connect with previous pcd.
598 elif LastOffset
== NowOffset
:
599 LastOffset
= NowOffset
+ eachFixedPcd
.PcdOccupySize
600 FixOffsetSizeListCount
+= 1
601 # Usually it will not enter into this thunk, if so, means it overlapped.
603 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
,
604 "The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" % \
605 (eachFixedPcd
.PcdCName
, eachFixedPcd
.PcdOffset
, eachFixedPcd
.InputFileName
, eachFixedPcd
.Lineno
),
607 FixOffsetSizeListCount
+= 1
609 # Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
610 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
611 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
612 while (lenOfUnfixedList
> 0) :
613 # Still has items need to process
614 # The last pcd instance
615 LastPcd
= self
.PcdFixedOffsetSizeList
[lenOfList
-1]
616 NeedFixPcd
= self
.PcdUnknownOffsetList
[0]
618 NeedFixPcd
.PcdBinOffset
= LastPcd
.PcdBinOffset
+ LastPcd
.PcdOccupySize
619 NeedFixPcd
.PcdOffset
= str(hex(NeedFixPcd
.PcdBinOffset
))
621 # Insert this pcd into fixed offset pcd list's tail.
622 self
.PcdFixedOffsetSizeList
.insert(lenOfList
, NeedFixPcd
)
623 # Delete the item's offset that has been fixed and added into fixed offset list
624 self
.PcdUnknownOffsetList
.pop(0)
627 lenOfUnfixedList
-= 1
629 # Write the final data into output files.
631 def GenerateVpdFile (self
, MapFileName
, BinFileName
):
632 #Open an VPD file to process
635 fVpdFile
= open(BinFileName
, "wb", 0)
638 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.VpdFileName
, None)
641 fMapFile
= open(MapFileName
, "w", 0)
644 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.MapFileName
, None)
646 # Use a instance of StringIO to cache data
647 fStringIO
= StringIO
.StringIO('')
649 # Write the header of map file.
651 fMapFile
.write (st
.MAP_FILE_COMMENT_TEMPLATE
+ "\n")
653 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)
655 for eachPcd
in self
.PcdFixedOffsetSizeList
:
658 fMapFile
.write("%s | %s | %s | %s | %s \n" % (eachPcd
.PcdCName
, eachPcd
.SkuId
,eachPcd
.PcdOffset
, eachPcd
.PcdSize
,eachPcd
.PcdUnpackValue
))
660 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)
662 # Write Vpd binary file
663 fStringIO
.seek (eachPcd
.PcdBinOffset
)
664 if isinstance(eachPcd
.PcdValue
, list):
665 ValueList
= [chr(Item
) for Item
in eachPcd
.PcdValue
]
666 fStringIO
.write(''.join(ValueList
))
668 fStringIO
.write (eachPcd
.PcdValue
)
671 fVpdFile
.write (fStringIO
.getvalue())
673 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)