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 from __future__
import absolute_import
17 import Common
.LongFilePathOs
as os
18 from io
import BytesIO
19 from . import StringTable
as st
22 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
24 from Common
.DataType
import MAX_SIZE_TYPE
, MAX_VAL_TYPE
, TAB_STAR
25 import Common
.EdkLogger
as EdkLogger
26 import Common
.BuildToolError
as BuildToolError
28 _FORMAT_CHAR
= {1: 'B',
34 ## The VPD PCD data structure for store and process each VPD PCD entry.
36 # This class contain method to format and pack pcd's value.
39 def __init__(self
, PcdCName
, SkuId
,PcdOffset
, PcdSize
, PcdValue
, Lineno
=None, FileName
=None, PcdUnpackValue
=None,
40 PcdBinOffset
=None, PcdBinSize
=None, Alignment
=None):
41 self
.PcdCName
= PcdCName
.strip()
42 self
.SkuId
= SkuId
.strip()
43 self
.PcdOffset
= PcdOffset
.strip()
44 self
.PcdSize
= PcdSize
.strip()
45 self
.PcdValue
= PcdValue
.strip()
46 self
.Lineno
= Lineno
.strip()
47 self
.FileName
= FileName
.strip()
48 self
.PcdUnpackValue
= PcdUnpackValue
49 self
.PcdBinOffset
= PcdBinOffset
50 self
.PcdBinSize
= PcdBinSize
51 self
.Alignment
= Alignment
53 if self
.PcdValue
== '' :
54 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
55 "Invalid PCD format(Name: %s File: %s line: %s) , no Value specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
57 if self
.PcdOffset
== '' :
58 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
59 "Invalid PCD format(Name: %s File: %s Line: %s) , no Offset specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
61 if self
.PcdSize
== '' :
62 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
63 "Invalid PCD format(Name: %s File: %s Line: %s), no PcdSize specified!" % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
65 self
._GenOffsetValue
()
67 ## Analyze the string value to judge the PCD's datum type equal to Boolean or not.
69 # @param ValueString PCD's value
70 # @param Size PCD's size
72 # @retval True PCD's datum type is Boolean
73 # @retval False PCD's datum type is not Boolean.
75 def _IsBoolean(self
, ValueString
, Size
):
77 if ValueString
.upper() in ["TRUE", "FALSE"]:
79 elif ValueString
in ["0", "1", "0x0", "0x1", "0x00", "0x01"]:
84 ## Convert the PCD's value from string to integer.
86 # This function will try to convert the Offset value form string to integer
87 # for both hexadecimal and decimal.
89 def _GenOffsetValue(self
):
90 if self
.PcdOffset
!= TAB_STAR
:
92 self
.PcdBinOffset
= int (self
.PcdOffset
)
95 self
.PcdBinOffset
= int(self
.PcdOffset
, 16)
97 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
98 "Invalid offset value %s for PCD %s (File: %s Line: %s)" % (self
.PcdOffset
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
100 ## Pack Boolean type VPD PCD's value form string to binary type.
102 # @param ValueString The boolean type string for pack.
105 def _PackBooleanValue(self
, ValueString
):
106 if ValueString
.upper() == "TRUE" or ValueString
in ["1", "0x1", "0x01"]:
108 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 1)
110 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
111 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
114 self
.PcdValue
= pack(_FORMAT_CHAR
[1], 0)
116 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
117 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
119 ## Pack Integer type VPD PCD's value form string to binary type.
121 # @param ValueString The Integer type string for pack.
124 def _PackIntValue(self
, IntValue
, Size
):
125 if Size
not in _FORMAT_CHAR
:
126 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
127 "Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
129 for Type
, MaxSize
in MAX_SIZE_TYPE
.items():
130 if Type
== 'BOOLEAN':
134 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
135 "PCD can't be set to negative value %d for PCD %s in %s datum type(File: %s Line: %s)." % (
136 IntValue
, self
.PcdCName
, Type
, self
.FileName
, self
.Lineno
))
137 elif IntValue
> MAX_VAL_TYPE
[Type
]:
138 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
139 "Too large PCD value %d for datum type %s for PCD %s(File: %s Line: %s)." % (
140 IntValue
, Type
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
143 self
.PcdValue
= pack(_FORMAT_CHAR
[Size
], IntValue
)
145 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
146 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
148 ## Pack VOID* type VPD PCD's value form string to binary type.
150 # The VOID* type of string divided into 3 sub-type:
151 # 1: L"String"/L'String', Unicode type string.
152 # 2: "String"/'String', Ascii type string.
153 # 3: {bytearray}, only support byte-array.
155 # @param ValueString The Integer type string for pack.
157 def _PackPtrValue(self
, ValueString
, Size
):
158 if ValueString
.startswith('L"') or ValueString
.startswith("L'"):
159 self
._PackUnicode
(ValueString
, Size
)
160 elif ValueString
.startswith('{') and ValueString
.endswith('}'):
161 self
._PackByteArray
(ValueString
, Size
)
162 elif (ValueString
.startswith('"') and ValueString
.endswith('"')) or (ValueString
.startswith("'") and ValueString
.endswith("'")):
163 self
._PackString
(ValueString
, Size
)
165 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
166 "Invalid VOID* type PCD %s value %s (File: %s Line: %s)" % (self
.PcdCName
, ValueString
, self
.FileName
, self
.Lineno
))
168 ## Pack an Ascii PCD value.
170 # An Ascii string for a PCD should be in format as ""/''.
172 def _PackString(self
, ValueString
, Size
):
174 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
175 "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
176 if (ValueString
== ""):
177 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
))
180 if ValueString
.startswith("'"):
183 ValueString
= ValueString
[1:-1]
184 # No null-terminator in 'string'
185 if (QuotedFlag
and len(ValueString
) + 1 > Size
) or (not QuotedFlag
and len(ValueString
) > Size
):
186 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
187 "PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
189 self
.PcdValue
= pack('%ds' % Size
, ValueString
)
191 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
192 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
194 ## Pack a byte-array PCD value.
196 # A byte-array for a PCD should be in format as {0x01, 0x02, ...}.
198 def _PackByteArray(self
, ValueString
, Size
):
200 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
))
201 if (ValueString
== ""):
202 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
))
204 ValueString
= ValueString
.strip()
205 ValueString
= ValueString
.lstrip('{').strip('}')
206 ValueList
= ValueString
.split(',')
207 ValueList
= [item
.strip() for item
in ValueList
]
209 if len(ValueList
) > Size
:
210 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
211 "The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
213 ReturnArray
= array
.array('B')
215 for Index
in range(len(ValueList
)):
217 if ValueList
[Index
].lower().startswith('0x'):
218 # translate hex value
220 Value
= int(ValueList
[Index
], 16)
222 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
223 "The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \
224 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
226 # translate decimal value
228 Value
= int(ValueList
[Index
], 10)
230 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
231 "The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \
232 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
235 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
236 "The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" % \
237 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
239 ReturnArray
.append(Value
)
241 for Index
in range(len(ValueList
), Size
):
242 ReturnArray
.append(0)
244 self
.PcdValue
= ReturnArray
.tolist()
246 ## Pack a unicode PCD value into byte array.
248 # A unicode string for a PCD should be in format as L""/L''.
250 def _PackUnicode(self
, UnicodeString
, Size
):
252 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % \
253 (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
256 if UnicodeString
.startswith("L'"):
258 UnicodeString
= UnicodeString
[2:-1]
260 # No null-terminator in L'string'
261 if (QuotedFlag
and (len(UnicodeString
) + 1) * 2 > Size
) or (not QuotedFlag
and len(UnicodeString
) * 2 > Size
):
262 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
263 "The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \
264 (UnicodeString
, Size
, self
.FileName
, self
.Lineno
))
266 ReturnArray
= array
.array('B')
267 for Value
in UnicodeString
:
269 ReturnArray
.append(ord(Value
))
270 ReturnArray
.append(0)
272 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
273 "Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \
274 (Value
, UnicodeString
, self
.FileName
, self
.Lineno
))
276 for Index
in range(len(UnicodeString
) * 2, Size
):
277 ReturnArray
.append(0)
279 self
.PcdValue
= ReturnArray
.tolist()
283 ## The class implementing the BPDG VPD PCD offset fix process
285 # The VPD PCD offset fix process includes:
286 # 1. Parse the input guided.txt file and store it in the data structure;
287 # 2. Format the input file data to remove unused lines;
288 # 3. Fixed offset if needed;
289 # 4. Generate output file, including guided.map and guided.bin file;
292 ## Constructor of DscBuildData
294 # Initialize object of GenVPD
295 # @Param InputFileName The filename include the vpd type pcd information
296 # @param MapFileName The filename of map file that stores vpd type pcd information.
297 # This file will be generated by the BPDG tool after fix the offset
298 # and adjust the offset to make the pcd data aligned.
299 # @param VpdFileName The filename of Vpd file that hold vpd pcd information.
301 def __init__(self
, InputFileName
, MapFileName
, VpdFileName
):
302 self
.InputFileName
= InputFileName
303 self
.MapFileName
= MapFileName
304 self
.VpdFileName
= VpdFileName
305 self
.FileLinesList
= []
306 self
.PcdFixedOffsetSizeList
= []
307 self
.PcdUnknownOffsetList
= []
309 fInputfile
= open(InputFileName
, "r", 0)
311 self
.FileLinesList
= fInputfile
.readlines()
313 EdkLogger
.error("BPDG", BuildToolError
.FILE_READ_FAILURE
, "File read failed for %s" % InputFileName
, None)
317 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % InputFileName
, None)
320 # Parser the input file which is generated by the build tool. Convert the value of each pcd's
321 # from string to it's real format. Also remove the useless line in the input file.
323 def ParserInputFile (self
):
325 for line
in self
.FileLinesList
:
326 # Strip "\r\n" generated by readlines ().
328 line
= line
.rstrip(os
.linesep
)
330 # Skip the comment line
331 if (not line
.startswith("#")) and len(line
) > 1 :
333 # Enhanced for support "|" character in the string.
335 ValueList
= ['', '', '', '', '']
337 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
338 PtrValue
= ValueRe
.findall(line
)
340 ValueUpdateFlag
= False
342 if len(PtrValue
) >= 1:
343 line
= re
.sub(ValueRe
, '', line
)
344 ValueUpdateFlag
= True
346 TokenList
= line
.split('|')
347 ValueList
[0:len(TokenList
)] = TokenList
350 ValueList
[4] = PtrValue
[0]
351 self
.FileLinesList
[count
] = ValueList
352 # Store the line number
353 self
.FileLinesList
[count
].append(str(count
+ 1))
354 elif len(line
) <= 1 :
355 # Set the blank line to "None"
356 self
.FileLinesList
[count
] = None
358 # Set the comment line to "None"
359 self
.FileLinesList
[count
] = None
362 # The line count contain usage information
364 # Delete useless lines
367 if (self
.FileLinesList
[count
] is None) :
368 del(self
.FileLinesList
[count
])
374 # After remove the useless line, if there are no data remain in the file line list,
375 # Report warning messages to user's.
377 if len(self
.FileLinesList
) == 0 :
378 EdkLogger
.warn('BPDG', BuildToolError
.RESOURCE_NOT_AVAILABLE
,
379 "There are no VPD type pcds defined in DSC file, Please check it.")
381 # Process the pcds one by one base on the pcd's value and size
383 for line
in self
.FileLinesList
:
384 if line
is not None :
385 PCD
= PcdEntry(line
[0], line
[1], line
[2], line
[3], line
[4], line
[5], self
.InputFileName
)
386 # Strip the space char
387 PCD
.PcdCName
= PCD
.PcdCName
.strip(' ')
388 PCD
.SkuId
= PCD
.SkuId
.strip(' ')
389 PCD
.PcdOffset
= PCD
.PcdOffset
.strip(' ')
390 PCD
.PcdSize
= PCD
.PcdSize
.strip(' ')
391 PCD
.PcdValue
= PCD
.PcdValue
.strip(' ')
392 PCD
.Lineno
= PCD
.Lineno
.strip(' ')
395 # Store the original pcd value.
396 # This information will be useful while generate the output map file.
398 PCD
.PcdUnpackValue
= str(PCD
.PcdValue
)
401 # Translate PCD size string to an integer value.
404 PackSize
= int(PCD
.PcdSize
, 10)
405 PCD
.PcdBinSize
= PackSize
408 PackSize
= int(PCD
.PcdSize
, 16)
409 PCD
.PcdBinSize
= PackSize
411 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid PCD size value %s at file: %s line: %s" % (PCD
.PcdSize
, self
.InputFileName
, PCD
.Lineno
))
414 # If value is Unicode string (e.g. L""), then use 2-byte alignment
415 # If value is byte array (e.g. {}), then use 8-byte alignment
417 PCD
.PcdOccupySize
= PCD
.PcdBinSize
418 if PCD
.PcdUnpackValue
.startswith("{"):
420 elif PCD
.PcdUnpackValue
.startswith("L"):
425 PCD
.Alignment
= Alignment
426 if PCD
.PcdOffset
!= TAB_STAR
:
427 if PCD
.PcdOccupySize
% Alignment
!= 0:
428 if PCD
.PcdUnpackValue
.startswith("{"):
429 EdkLogger
.warn("BPDG", "The offset value of PCD %s is not 8-byte aligned!" %(PCD
.PcdCName
), File
=self
.InputFileName
)
431 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, 'The offset value of PCD %s should be %s-byte aligned.' % (PCD
.PcdCName
, Alignment
))
433 if PCD
.PcdOccupySize
% Alignment
!= 0:
434 PCD
.PcdOccupySize
= (PCD
.PcdOccupySize
/ Alignment
+ 1) * Alignment
436 PackSize
= PCD
.PcdOccupySize
437 if PCD
._IsBoolean
(PCD
.PcdValue
, PCD
.PcdSize
):
438 PCD
._PackBooleanValue
(PCD
.PcdValue
)
439 self
.FileLinesList
[count
] = PCD
443 # Try to translate value to an integer firstly.
448 PackValue
= int(PCD
.PcdValue
)
451 PackValue
= int(PCD
.PcdValue
, 16)
456 PCD
._PackIntValue
(PackValue
, PackSize
)
458 PCD
._PackPtrValue
(PCD
.PcdValue
, PackSize
)
460 self
.FileLinesList
[count
] = PCD
466 # This function used to create a clean list only contain useful information and reorganized to make it
469 def FormatFileLine (self
) :
471 for eachPcd
in self
.FileLinesList
:
472 if eachPcd
.PcdOffset
!= TAB_STAR
:
473 # Use pcd's Offset value as key, and pcd's Value as value
474 self
.PcdFixedOffsetSizeList
.append(eachPcd
)
476 # Use pcd's CName as key, and pcd's Size as value
477 self
.PcdUnknownOffsetList
.append(eachPcd
)
481 # This function is use to fix the offset value which the not specified in the map file.
482 # Usually it use the star (meaning any offset) character in the offset field
484 def FixVpdOffset (self
):
485 # At first, the offset should start at 0
486 # Sort fixed offset list in order to find out where has free spaces for the pcd's offset
487 # value is TAB_STAR to insert into.
489 self
.PcdFixedOffsetSizeList
.sort(key
=lambda x
: x
.PcdBinOffset
)
492 # Sort the un-fixed pcd's offset by it's size.
494 self
.PcdUnknownOffsetList
.sort(key
=lambda x
: x
.PcdBinSize
)
497 for pcd
in self
.PcdUnknownOffsetList
:
499 if pcd
.PcdCName
== ".".join(("gEfiMdeModulePkgTokenSpaceGuid", "PcdNvStoreDefaultValueBuffer")):
500 if index
!= len(self
.PcdUnknownOffsetList
):
501 for i
in range(len(self
.PcdUnknownOffsetList
) - index
):
502 self
.PcdUnknownOffsetList
[index
+i
-1 ], self
.PcdUnknownOffsetList
[index
+i
] = self
.PcdUnknownOffsetList
[index
+i
], self
.PcdUnknownOffsetList
[index
+i
-1]
505 # Process all Offset value are TAB_STAR
507 if (len(self
.PcdFixedOffsetSizeList
) == 0) and (len(self
.PcdUnknownOffsetList
) != 0) :
508 # The offset start from 0
510 for Pcd
in self
.PcdUnknownOffsetList
:
511 if NowOffset
% Pcd
.Alignment
!= 0:
512 NowOffset
= (NowOffset
/ Pcd
.Alignment
+ 1) * Pcd
.Alignment
513 Pcd
.PcdBinOffset
= NowOffset
514 Pcd
.PcdOffset
= str(hex(Pcd
.PcdBinOffset
))
515 NowOffset
+= Pcd
.PcdOccupySize
517 self
.PcdFixedOffsetSizeList
= self
.PcdUnknownOffsetList
520 # Check the offset of VPD type pcd's offset start from 0.
521 if self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
!= 0 :
522 EdkLogger
.warn("BPDG", "The offset of VPD type pcd should start with 0, please check it.",
525 # Judge whether the offset in fixed pcd offset list is overlapped or not.
526 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
528 while (count
< lenOfList
- 1) :
529 PcdNow
= self
.PcdFixedOffsetSizeList
[count
]
530 PcdNext
= self
.PcdFixedOffsetSizeList
[count
+1]
531 # Two pcd's offset is same
532 if PcdNow
.PcdBinOffset
== PcdNext
.PcdBinOffset
:
533 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
534 "The offset of %s at line: %s is same with %s at line: %s in file %s" % \
535 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
539 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
> PcdNext
.PcdBinOffset
:
540 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
541 "The offset of %s at line: %s is overlapped with %s at line: %s in file %s" % \
542 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
545 # Has free space, raise a warning message
546 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
< PcdNext
.PcdBinOffset
:
547 EdkLogger
.warn("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
548 "The offsets have free space of between %s at line: %s and %s at line: %s in file %s" % \
549 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
553 LastOffset
= self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
554 FixOffsetSizeListCount
= 0
555 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
556 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
559 # Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
561 while (FixOffsetSizeListCount
< lenOfList
) :
563 eachFixedPcd
= self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
]
564 NowOffset
= eachFixedPcd
.PcdBinOffset
567 if LastOffset
< NowOffset
:
568 if lenOfUnfixedList
!= 0 :
569 countOfUnfixedList
= 0
570 while(countOfUnfixedList
< lenOfUnfixedList
) :
571 eachUnfixedPcd
= self
.PcdUnknownOffsetList
[countOfUnfixedList
]
572 needFixPcdSize
= eachUnfixedPcd
.PcdOccupySize
574 if eachUnfixedPcd
.PcdOffset
== TAB_STAR
:
575 if LastOffset
% eachUnfixedPcd
.Alignment
!= 0:
576 LastOffset
= (LastOffset
/ eachUnfixedPcd
.Alignment
+ 1) * eachUnfixedPcd
.Alignment
577 # The offset un-fixed pcd can write into this free space
578 if needFixPcdSize
<= (NowOffset
- LastOffset
) :
579 # Change the offset value of un-fixed pcd
580 eachUnfixedPcd
.PcdOffset
= str(hex(LastOffset
))
581 eachUnfixedPcd
.PcdBinOffset
= LastOffset
582 # Insert this pcd into fixed offset pcd list.
583 self
.PcdFixedOffsetSizeList
.insert(FixOffsetSizeListCount
, eachUnfixedPcd
)
585 # Delete the item's offset that has been fixed and added into fixed offset list
586 self
.PcdUnknownOffsetList
.pop(countOfUnfixedList
)
588 # After item added, should enlarge the length of fixed pcd offset list
590 FixOffsetSizeListCount
+= 1
592 # Decrease the un-fixed pcd offset list's length
593 lenOfUnfixedList
-= 1
595 # Modify the last offset value
596 LastOffset
+= needFixPcdSize
598 # It can not insert into those two pcds, need to check still has other space can store it.
599 LastOffset
= NowOffset
+ self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
].PcdOccupySize
600 FixOffsetSizeListCount
+= 1
603 # Set the FixOffsetSizeListCount = lenOfList for quit the loop
605 FixOffsetSizeListCount
= lenOfList
607 # No free space, smoothly connect with previous pcd.
608 elif LastOffset
== NowOffset
:
609 LastOffset
= NowOffset
+ eachFixedPcd
.PcdOccupySize
610 FixOffsetSizeListCount
+= 1
611 # Usually it will not enter into this thunk, if so, means it overlapped.
613 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
,
614 "The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" % \
615 (eachFixedPcd
.PcdCName
, eachFixedPcd
.PcdOffset
, eachFixedPcd
.InputFileName
, eachFixedPcd
.Lineno
),
617 FixOffsetSizeListCount
+= 1
619 # Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
620 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
621 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
622 while (lenOfUnfixedList
> 0) :
623 # Still has items need to process
624 # The last pcd instance
625 LastPcd
= self
.PcdFixedOffsetSizeList
[lenOfList
-1]
626 NeedFixPcd
= self
.PcdUnknownOffsetList
[0]
628 NeedFixPcd
.PcdBinOffset
= LastPcd
.PcdBinOffset
+ LastPcd
.PcdOccupySize
629 if NeedFixPcd
.PcdBinOffset
% NeedFixPcd
.Alignment
!= 0:
630 NeedFixPcd
.PcdBinOffset
= (NeedFixPcd
.PcdBinOffset
/ NeedFixPcd
.Alignment
+ 1) * NeedFixPcd
.Alignment
632 NeedFixPcd
.PcdOffset
= str(hex(NeedFixPcd
.PcdBinOffset
))
634 # Insert this pcd into fixed offset pcd list's tail.
635 self
.PcdFixedOffsetSizeList
.insert(lenOfList
, NeedFixPcd
)
636 # Delete the item's offset that has been fixed and added into fixed offset list
637 self
.PcdUnknownOffsetList
.pop(0)
640 lenOfUnfixedList
-= 1
642 # Write the final data into output files.
644 def GenerateVpdFile (self
, MapFileName
, BinFileName
):
645 #Open an VPD file to process
648 fVpdFile
= open(BinFileName
, "wb", 0)
651 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.VpdFileName
, None)
654 fMapFile
= open(MapFileName
, "w", 0)
657 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.MapFileName
, None)
659 # Use a instance of BytesIO to cache data
660 fStringIO
= BytesIO('')
662 # Write the header of map file.
664 fMapFile
.write (st
.MAP_FILE_COMMENT_TEMPLATE
+ "\n")
666 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)
668 for eachPcd
in self
.PcdFixedOffsetSizeList
:
671 fMapFile
.write("%s | %s | %s | %s | %s \n" % (eachPcd
.PcdCName
, eachPcd
.SkuId
, eachPcd
.PcdOffset
, eachPcd
.PcdSize
, eachPcd
.PcdUnpackValue
))
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
.MapFileName
, None)
675 # Write Vpd binary file
676 fStringIO
.seek (eachPcd
.PcdBinOffset
)
677 if isinstance(eachPcd
.PcdValue
, list):
678 ValueList
= [chr(Item
) for Item
in eachPcd
.PcdValue
]
679 fStringIO
.write(''.join(ValueList
))
681 fStringIO
.write (eachPcd
.PcdValue
)
684 fVpdFile
.write (fStringIO
.getvalue())
686 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)