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 - 2018, 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, Alignment
=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
49 self
.Alignment
= Alignment
51 if self
.PcdValue
== '' :
52 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
53 "Invalid PCD format(Name: %s File: %s line: %s) , no Value specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
55 if self
.PcdOffset
== '' :
56 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
57 "Invalid PCD format(Name: %s File: %s Line: %s) , no Offset specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
59 if self
.PcdSize
== '' :
60 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
61 "Invalid PCD format(Name: %s File: %s Line: %s), no PcdSize specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
63 self
._GenOffsetValue
()
65 ## Analyze the string value to judge the PCD's datum type equal to Boolean or not.
67 # @param ValueString PCD's value
68 # @param Size PCD's size
70 # @retval True PCD's datum type is Boolean
71 # @retval False PCD's datum type is not Boolean.
73 def _IsBoolean(self
, ValueString
, Size
):
75 if ValueString
.upper() in ["TRUE", "FALSE"]:
77 elif ValueString
in ["0", "1", "0x0", "0x1", "0x00", "0x01"]:
82 ## Convert the PCD's value from string to integer.
84 # This function will try to convert the Offset value form string to integer
85 # for both hexadecimal and decimal.
87 def _GenOffsetValue(self
):
88 if self
.PcdOffset
!= "*" :
90 self
.PcdBinOffset
= int (self
.PcdOffset
)
93 self
.PcdBinOffset
= int(self
.PcdOffset
, 16)
95 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
96 "Invalid offset value %s for PCD %s (File: %s Line: %s)" % (self
.PcdOffset
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
98 ## Pack Boolean type VPD PCD's value form string to binary type.
100 # @param ValueString The boolean type string for pack.
103 def _PackBooleanValue(self
, ValueString
):
104 if ValueString
.upper() == "TRUE" or ValueString
in ["1", "0x1", "0x01"]:
106 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 1)
108 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
109 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
112 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 0)
114 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
115 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
117 ## Pack Integer type VPD PCD's value form string to binary type.
119 # @param ValueString The Integer type string for pack.
122 def _PackIntValue(self
, IntValue
, Size
):
123 if Size
not in _FORMAT_CHAR
:
124 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
125 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
129 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
130 "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
))
131 elif IntValue
>= 0x100:
132 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
133 "Too large PCD value %d for datum type UINT8 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
136 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
137 "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
))
138 elif IntValue
>= 0x10000:
139 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
140 "Too large PCD value %d for datum type UINT16 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
143 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
144 "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
))
145 elif IntValue
>= 0x100000000:
146 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
147 "Too large PCD value %d for datum type UINT32 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
150 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
151 "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
))
152 elif IntValue
>= 0x10000000000000000:
153 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
154 "Too large PCD value %d for datum type UINT32 for PCD %s(File: %s Line: %s)." % (IntValue
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
156 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
157 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
160 self
.PcdValue
= pack(_FORMAT_CHAR
[Size
], IntValue
)
162 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
163 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
165 ## Pack VOID* type VPD PCD's value form string to binary type.
167 # The VOID* type of string divided into 3 sub-type:
168 # 1: L"String"/L'String', Unicode type string.
169 # 2: "String"/'String', Ascii type string.
170 # 3: {bytearray}, only support byte-array.
172 # @param ValueString The Integer type string for pack.
174 def _PackPtrValue(self
, ValueString
, Size
):
175 if ValueString
.startswith('L"') or ValueString
.startswith("L'"):
176 self
._PackUnicode
(ValueString
, Size
)
177 elif ValueString
.startswith('{') and ValueString
.endswith('}'):
178 self
._PackByteArray
(ValueString
, Size
)
179 elif (ValueString
.startswith('"') and ValueString
.endswith('"')) or (ValueString
.startswith("'") and ValueString
.endswith("'")):
180 self
._PackString
(ValueString
, Size
)
182 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
183 "Invalid VOID* type PCD %s value %s (File: %s Line: %s)" % (self
.PcdCName
, ValueString
, self
.FileName
, self
.Lineno
))
185 ## Pack an Ascii PCD value.
187 # An Ascii string for a PCD should be in format as ""/''.
189 def _PackString(self
, ValueString
, Size
):
191 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
192 "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
193 if (ValueString
== ""):
194 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
))
197 if ValueString
.startswith("'"):
200 ValueString
= ValueString
[1:-1]
201 # No null-terminator in 'string'
202 if (QuotedFlag
and len(ValueString
) + 1 > Size
) or (not QuotedFlag
and len(ValueString
) > Size
):
203 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
204 "PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
206 self
.PcdValue
= pack('%ds' % Size
, ValueString
)
208 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
209 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
211 ## Pack a byte-array PCD value.
213 # A byte-array for a PCD should be in format as {0x01, 0x02, ...}.
215 def _PackByteArray(self
, ValueString
, Size
):
217 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
))
218 if (ValueString
== ""):
219 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
))
221 ValueString
= ValueString
.strip()
222 ValueString
= ValueString
.lstrip('{').strip('}')
223 ValueList
= ValueString
.split(',')
224 ValueList
= [item
.strip() for item
in ValueList
]
226 if len(ValueList
) > Size
:
227 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
228 "The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
230 ReturnArray
= array
.array('B')
232 for Index
in xrange(len(ValueList
)):
234 if ValueList
[Index
].lower().startswith('0x'):
235 # translate hex value
237 Value
= int(ValueList
[Index
], 16)
239 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
240 "The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \
241 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
243 # translate decimal value
245 Value
= int(ValueList
[Index
], 10)
247 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
248 "The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \
249 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
252 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
253 "The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" % \
254 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
256 ReturnArray
.append(Value
)
258 for Index
in xrange(len(ValueList
), Size
):
259 ReturnArray
.append(0)
261 self
.PcdValue
= ReturnArray
.tolist()
263 ## Pack a unicode PCD value into byte array.
265 # A unicode string for a PCD should be in format as L""/L''.
267 def _PackUnicode(self
, UnicodeString
, Size
):
269 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % \
270 (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
273 if UnicodeString
.startswith("L'"):
275 UnicodeString
= UnicodeString
[2:-1]
277 # No null-terminator in L'string'
278 if (QuotedFlag
and (len(UnicodeString
) + 1) * 2 > Size
) or (not QuotedFlag
and len(UnicodeString
) * 2 > Size
):
279 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
280 "The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \
281 (UnicodeString
, Size
, self
.FileName
, self
.Lineno
))
283 ReturnArray
= array
.array('B')
284 for Value
in UnicodeString
:
286 ReturnArray
.append(ord(Value
))
287 ReturnArray
.append(0)
289 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
290 "Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \
291 (Value
, UnicodeString
, self
.FileName
, self
.Lineno
))
293 for Index
in xrange(len(UnicodeString
) * 2, Size
):
294 ReturnArray
.append(0)
296 self
.PcdValue
= ReturnArray
.tolist()
300 ## The class implementing the BPDG VPD PCD offset fix process
302 # The VPD PCD offset fix process includes:
303 # 1. Parse the input guided.txt file and store it in the data structure;
304 # 2. Format the input file data to remove unused lines;
305 # 3. Fixed offset if needed;
306 # 4. Generate output file, including guided.map and guided.bin file;
309 ## Constructor of DscBuildData
311 # Initialize object of GenVPD
312 # @Param InputFileName The filename include the vpd type pcd information
313 # @param MapFileName The filename of map file that stores vpd type pcd information.
314 # This file will be generated by the BPDG tool after fix the offset
315 # and adjust the offset to make the pcd data aligned.
316 # @param VpdFileName The filename of Vpd file that hold vpd pcd information.
318 def __init__(self
, InputFileName
, MapFileName
, VpdFileName
):
319 self
.InputFileName
= InputFileName
320 self
.MapFileName
= MapFileName
321 self
.VpdFileName
= VpdFileName
322 self
.FileLinesList
= []
323 self
.PcdFixedOffsetSizeList
= []
324 self
.PcdUnknownOffsetList
= []
326 fInputfile
= open(InputFileName
, "r", 0)
328 self
.FileLinesList
= fInputfile
.readlines()
330 EdkLogger
.error("BPDG", BuildToolError
.FILE_READ_FAILURE
, "File read failed for %s" % InputFileName
, None)
334 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % InputFileName
, None)
337 # Parser the input file which is generated by the build tool. Convert the value of each pcd's
338 # from string to it's real format. Also remove the useless line in the input file.
340 def ParserInputFile (self
):
342 for line
in self
.FileLinesList
:
343 # Strip "\r\n" generated by readlines ().
345 line
= line
.rstrip(os
.linesep
)
347 # Skip the comment line
348 if (not line
.startswith("#")) and len(line
) > 1 :
350 # Enhanced for support "|" character in the string.
352 ValueList
= ['', '', '', '','']
354 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
355 PtrValue
= ValueRe
.findall(line
)
357 ValueUpdateFlag
= False
359 if len(PtrValue
) >= 1:
360 line
= re
.sub(ValueRe
, '', line
)
361 ValueUpdateFlag
= True
363 TokenList
= line
.split('|')
364 ValueList
[0:len(TokenList
)] = TokenList
367 ValueList
[4] = PtrValue
[0]
368 self
.FileLinesList
[count
] = ValueList
369 # Store the line number
370 self
.FileLinesList
[count
].append(str(count
+ 1))
371 elif len(line
) <= 1 :
372 # Set the blank line to "None"
373 self
.FileLinesList
[count
] = None
375 # Set the comment line to "None"
376 self
.FileLinesList
[count
] = None
379 # The line count contain usage information
381 # Delete useless lines
384 if (self
.FileLinesList
[count
] is None) :
385 del(self
.FileLinesList
[count
])
391 # After remove the useless line, if there are no data remain in the file line list,
392 # Report warning messages to user's.
394 if len(self
.FileLinesList
) == 0 :
395 EdkLogger
.warn('BPDG', BuildToolError
.RESOURCE_NOT_AVAILABLE
,
396 "There are no VPD type pcds defined in DSC file, Please check it.")
398 # Process the pcds one by one base on the pcd's value and size
400 for line
in self
.FileLinesList
:
401 if line
is not None :
402 PCD
= PcdEntry(line
[0], line
[1], line
[2], line
[3], line
[4],line
[5], self
.InputFileName
)
403 # Strip the space char
404 PCD
.PcdCName
= PCD
.PcdCName
.strip(' ')
405 PCD
.SkuId
= PCD
.SkuId
.strip(' ')
406 PCD
.PcdOffset
= PCD
.PcdOffset
.strip(' ')
407 PCD
.PcdSize
= PCD
.PcdSize
.strip(' ')
408 PCD
.PcdValue
= PCD
.PcdValue
.strip(' ')
409 PCD
.Lineno
= PCD
.Lineno
.strip(' ')
412 # Store the original pcd value.
413 # This information will be useful while generate the output map file.
415 PCD
.PcdUnpackValue
= str(PCD
.PcdValue
)
418 # Translate PCD size string to an integer value.
421 PackSize
= int(PCD
.PcdSize
, 10)
422 PCD
.PcdBinSize
= PackSize
425 PackSize
= int(PCD
.PcdSize
, 16)
426 PCD
.PcdBinSize
= PackSize
428 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid PCD size value %s at file: %s line: %s" % (PCD
.PcdSize
, self
.InputFileName
, PCD
.Lineno
))
431 # If value is Unicode string (e.g. L""), then use 2-byte alignment
432 # If value is byte array (e.g. {}), then use 8-byte alignment
434 PCD
.PcdOccupySize
= PCD
.PcdBinSize
435 if PCD
.PcdUnpackValue
.startswith("{"):
437 elif PCD
.PcdUnpackValue
.startswith("L"):
442 PCD
.Alignment
= Alignment
443 if PCD
.PcdOffset
!= '*':
444 if PCD
.PcdOccupySize
% Alignment
!= 0:
445 if PCD
.PcdUnpackValue
.startswith("{"):
446 EdkLogger
.warn("BPDG", "The offset value of PCD %s is not 8-byte aligned!" %(PCD
.PcdCName
), File
=self
.InputFileName
)
448 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, 'The offset value of PCD %s should be %s-byte aligned.' % (PCD
.PcdCName
, Alignment
))
450 if PCD
.PcdOccupySize
% Alignment
!= 0:
451 PCD
.PcdOccupySize
= (PCD
.PcdOccupySize
/ Alignment
+ 1) * Alignment
453 PackSize
= PCD
.PcdOccupySize
454 if PCD
._IsBoolean
(PCD
.PcdValue
, PCD
.PcdSize
):
455 PCD
._PackBooleanValue
(PCD
.PcdValue
)
456 self
.FileLinesList
[count
] = PCD
460 # Try to translate value to an integer firstly.
465 PackValue
= int(PCD
.PcdValue
)
468 PackValue
= int(PCD
.PcdValue
, 16)
473 PCD
._PackIntValue
(PackValue
, PackSize
)
475 PCD
._PackPtrValue
(PCD
.PcdValue
, PackSize
)
477 self
.FileLinesList
[count
] = PCD
483 # This function used to create a clean list only contain useful information and reorganized to make it
486 def FormatFileLine (self
) :
488 for eachPcd
in self
.FileLinesList
:
489 if eachPcd
.PcdOffset
!= '*' :
490 # Use pcd's Offset value as key, and pcd's Value as value
491 self
.PcdFixedOffsetSizeList
.append(eachPcd
)
493 # Use pcd's CName as key, and pcd's Size as value
494 self
.PcdUnknownOffsetList
.append(eachPcd
)
498 # This function is use to fix the offset value which the not specified in the map file.
499 # Usually it use the star (meaning any offset) character in the offset field
501 def FixVpdOffset (self
):
502 # At first, the offset should start at 0
503 # Sort fixed offset list in order to find out where has free spaces for the pcd's offset
504 # value is "*" to insert into.
506 self
.PcdFixedOffsetSizeList
.sort(lambda x
, y
: cmp(x
.PcdBinOffset
, y
.PcdBinOffset
))
509 # Sort the un-fixed pcd's offset by it's size.
511 self
.PcdUnknownOffsetList
.sort(lambda x
, y
: cmp(x
.PcdBinSize
, y
.PcdBinSize
))
514 for pcd
in self
.PcdUnknownOffsetList
:
516 if pcd
.PcdCName
== ".".join(("gEfiMdeModulePkgTokenSpaceGuid","PcdNvStoreDefaultValueBuffer")):
517 if index
!= len(self
.PcdUnknownOffsetList
):
518 for i
in range(len(self
.PcdUnknownOffsetList
) - index
):
519 self
.PcdUnknownOffsetList
[index
+i
-1 ] , self
.PcdUnknownOffsetList
[index
+i
] = self
.PcdUnknownOffsetList
[index
+i
] , self
.PcdUnknownOffsetList
[index
+i
-1]
522 # Process all Offset value are "*"
524 if (len(self
.PcdFixedOffsetSizeList
) == 0) and (len(self
.PcdUnknownOffsetList
) != 0) :
525 # The offset start from 0
527 for Pcd
in self
.PcdUnknownOffsetList
:
528 if NowOffset
% Pcd
.Alignment
!= 0:
529 NowOffset
= (NowOffset
/ Pcd
.Alignment
+ 1) * Pcd
.Alignment
530 Pcd
.PcdBinOffset
= NowOffset
531 Pcd
.PcdOffset
= str(hex(Pcd
.PcdBinOffset
))
532 NowOffset
+= Pcd
.PcdOccupySize
534 self
.PcdFixedOffsetSizeList
= self
.PcdUnknownOffsetList
537 # Check the offset of VPD type pcd's offset start from 0.
538 if self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
!= 0 :
539 EdkLogger
.warn("BPDG", "The offset of VPD type pcd should start with 0, please check it.",
542 # Judge whether the offset in fixed pcd offset list is overlapped or not.
543 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
545 while (count
< lenOfList
- 1) :
546 PcdNow
= self
.PcdFixedOffsetSizeList
[count
]
547 PcdNext
= self
.PcdFixedOffsetSizeList
[count
+1]
548 # Two pcd's offset is same
549 if PcdNow
.PcdBinOffset
== PcdNext
.PcdBinOffset
:
550 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
551 "The offset of %s at line: %s is same with %s at line: %s in file %s" % \
552 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
556 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
> PcdNext
.PcdBinOffset
:
557 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
558 "The offset of %s at line: %s is overlapped with %s at line: %s in file %s" % \
559 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
562 # Has free space, raise a warning message
563 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
< PcdNext
.PcdBinOffset
:
564 EdkLogger
.warn("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
565 "The offsets have free space of between %s at line: %s and %s at line: %s in file %s" % \
566 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
570 LastOffset
= self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
571 FixOffsetSizeListCount
= 0
572 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
573 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
576 # Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
578 while (FixOffsetSizeListCount
< lenOfList
) :
580 eachFixedPcd
= self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
]
581 NowOffset
= eachFixedPcd
.PcdBinOffset
584 if LastOffset
< NowOffset
:
585 if lenOfUnfixedList
!= 0 :
586 countOfUnfixedList
= 0
587 while(countOfUnfixedList
< lenOfUnfixedList
) :
588 eachUnfixedPcd
= self
.PcdUnknownOffsetList
[countOfUnfixedList
]
589 needFixPcdSize
= eachUnfixedPcd
.PcdOccupySize
591 if eachUnfixedPcd
.PcdOffset
== '*' :
592 if LastOffset
% eachUnfixedPcd
.Alignment
!= 0:
593 LastOffset
= (LastOffset
/ eachUnfixedPcd
.Alignment
+ 1) * eachUnfixedPcd
.Alignment
594 # The offset un-fixed pcd can write into this free space
595 if needFixPcdSize
<= (NowOffset
- LastOffset
) :
596 # Change the offset value of un-fixed pcd
597 eachUnfixedPcd
.PcdOffset
= str(hex(LastOffset
))
598 eachUnfixedPcd
.PcdBinOffset
= LastOffset
599 # Insert this pcd into fixed offset pcd list.
600 self
.PcdFixedOffsetSizeList
.insert(FixOffsetSizeListCount
,eachUnfixedPcd
)
602 # Delete the item's offset that has been fixed and added into fixed offset list
603 self
.PcdUnknownOffsetList
.pop(countOfUnfixedList
)
605 # After item added, should enlarge the length of fixed pcd offset list
607 FixOffsetSizeListCount
+= 1
609 # Decrease the un-fixed pcd offset list's length
610 lenOfUnfixedList
-= 1
612 # Modify the last offset value
613 LastOffset
+= needFixPcdSize
615 # It can not insert into those two pcds, need to check still has other space can store it.
616 LastOffset
= NowOffset
+ self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
].PcdOccupySize
617 FixOffsetSizeListCount
+= 1
620 # Set the FixOffsetSizeListCount = lenOfList for quit the loop
622 FixOffsetSizeListCount
= lenOfList
624 # No free space, smoothly connect with previous pcd.
625 elif LastOffset
== NowOffset
:
626 LastOffset
= NowOffset
+ eachFixedPcd
.PcdOccupySize
627 FixOffsetSizeListCount
+= 1
628 # Usually it will not enter into this thunk, if so, means it overlapped.
630 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
,
631 "The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" % \
632 (eachFixedPcd
.PcdCName
, eachFixedPcd
.PcdOffset
, eachFixedPcd
.InputFileName
, eachFixedPcd
.Lineno
),
634 FixOffsetSizeListCount
+= 1
636 # Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
637 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
638 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
639 while (lenOfUnfixedList
> 0) :
640 # Still has items need to process
641 # The last pcd instance
642 LastPcd
= self
.PcdFixedOffsetSizeList
[lenOfList
-1]
643 NeedFixPcd
= self
.PcdUnknownOffsetList
[0]
645 NeedFixPcd
.PcdBinOffset
= LastPcd
.PcdBinOffset
+ LastPcd
.PcdOccupySize
646 if NeedFixPcd
.PcdBinOffset
% NeedFixPcd
.Alignment
!= 0:
647 NeedFixPcd
.PcdBinOffset
= (NeedFixPcd
.PcdBinOffset
/ NeedFixPcd
.Alignment
+ 1) * NeedFixPcd
.Alignment
649 NeedFixPcd
.PcdOffset
= str(hex(NeedFixPcd
.PcdBinOffset
))
651 # Insert this pcd into fixed offset pcd list's tail.
652 self
.PcdFixedOffsetSizeList
.insert(lenOfList
, NeedFixPcd
)
653 # Delete the item's offset that has been fixed and added into fixed offset list
654 self
.PcdUnknownOffsetList
.pop(0)
657 lenOfUnfixedList
-= 1
659 # Write the final data into output files.
661 def GenerateVpdFile (self
, MapFileName
, BinFileName
):
662 #Open an VPD file to process
665 fVpdFile
= open(BinFileName
, "wb", 0)
668 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.VpdFileName
, None)
671 fMapFile
= open(MapFileName
, "w", 0)
674 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.MapFileName
, None)
676 # Use a instance of StringIO to cache data
677 fStringIO
= StringIO
.StringIO('')
679 # Write the header of map file.
681 fMapFile
.write (st
.MAP_FILE_COMMENT_TEMPLATE
+ "\n")
683 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)
685 for eachPcd
in self
.PcdFixedOffsetSizeList
:
688 fMapFile
.write("%s | %s | %s | %s | %s \n" % (eachPcd
.PcdCName
, eachPcd
.SkuId
,eachPcd
.PcdOffset
, eachPcd
.PcdSize
,eachPcd
.PcdUnpackValue
))
690 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)
692 # Write Vpd binary file
693 fStringIO
.seek (eachPcd
.PcdBinOffset
)
694 if isinstance(eachPcd
.PcdValue
, list):
695 ValueList
= [chr(Item
) for Item
in eachPcd
.PcdValue
]
696 fStringIO
.write(''.join(ValueList
))
698 fStringIO
.write (eachPcd
.PcdValue
)
701 fVpdFile
.write (fStringIO
.getvalue())
703 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)