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 euqal 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
.keys():
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", Unicode type string.
169 # 2: "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"'):
176 self
._PackUnicode
(ValueString
, Size
)
177 elif ValueString
.startswith('{') and ValueString
.endswith('}'):
178 self
._PackByteArray
(ValueString
, Size
)
179 elif 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
))
195 if (len(ValueString
) < 2):
196 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
))
198 ValueString
= ValueString
[1:-1]
199 if len(ValueString
) + 1 > Size
:
200 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
201 "PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
203 self
.PcdValue
= pack('%ds' % Size
, ValueString
)
205 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
206 "Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self
.PcdCName
, self
.FileName
, self
.Lineno
))
208 ## Pack a byte-array PCD value.
210 # A byte-array for a PCD should be in format as {0x01, 0x02, ...}.
212 def _PackByteArray(self
, ValueString
, Size
):
214 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
))
215 if (ValueString
== ""):
216 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
))
218 ValueString
= ValueString
.strip()
219 ValueString
= ValueString
.lstrip('{').strip('}')
220 ValueList
= ValueString
.split(',')
221 ValueList
= [item
.strip() for item
in ValueList
]
223 if len(ValueList
) > Size
:
224 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
225 "The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString
, Size
, self
.FileName
, self
.Lineno
))
227 ReturnArray
= array
.array('B')
229 for Index
in xrange(len(ValueList
)):
231 if ValueList
[Index
].lower().startswith('0x'):
232 # translate hex value
234 Value
= int(ValueList
[Index
], 16)
236 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
237 "The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \
238 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
240 # translate decimal value
242 Value
= int(ValueList
[Index
], 10)
244 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
245 "The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \
246 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
249 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
250 "The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" % \
251 (ValueList
[Index
], ValueString
, self
.FileName
, self
.Lineno
))
253 ReturnArray
.append(Value
)
255 for Index
in xrange(len(ValueList
), Size
):
256 ReturnArray
.append(0)
258 self
.PcdValue
= ReturnArray
.tolist()
260 ## Pack a unicode PCD value into byte array.
262 # A unicode string for a PCD should be in format as L"".
264 def _PackUnicode(self
, UnicodeString
, Size
):
266 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" % \
267 (self
.PcdBinSize
, self
.PcdCName
, self
.FileName
, self
.Lineno
))
268 if (len(UnicodeString
) < 3):
269 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s)" % \
270 (self
.PcdCName
, self
.PcdUnpackValue
, self
.FileName
, self
.Lineno
))
272 UnicodeString
= UnicodeString
[2:-1]
274 if (len(UnicodeString
) + 1) * 2 > Size
:
275 EdkLogger
.error("BPDG", BuildToolError
.RESOURCE_OVERFLOW
,
276 "The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \
277 (UnicodeString
, Size
, self
.FileName
, self
.Lineno
))
279 ReturnArray
= array
.array('B')
280 for Value
in UnicodeString
:
282 ReturnArray
.append(ord(Value
))
283 ReturnArray
.append(0)
285 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
,
286 "Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \
287 (Value
, UnicodeString
, self
.FileName
, self
.Lineno
))
289 for Index
in xrange(len(UnicodeString
) * 2, Size
):
290 ReturnArray
.append(0)
292 self
.PcdValue
= ReturnArray
.tolist()
296 ## The class implementing the BPDG VPD PCD offset fix process
298 # The VPD PCD offset fix process includes:
299 # 1. Parse the input guided.txt file and store it in the data structure;
300 # 2. Format the input file data to remove unused lines;
301 # 3. Fixed offset if needed;
302 # 4. Generate output file, including guided.map and guided.bin file;
305 ## Constructor of DscBuildData
307 # Initialize object of GenVPD
308 # @Param InputFileName The filename include the vpd type pcd information
309 # @param MapFileName The filename of map file that stores vpd type pcd information.
310 # This file will be generated by the BPDG tool after fix the offset
311 # and adjust the offset to make the pcd data aligned.
312 # @param VpdFileName The filename of Vpd file that hold vpd pcd information.
314 def __init__(self
, InputFileName
, MapFileName
, VpdFileName
):
315 self
.InputFileName
= InputFileName
316 self
.MapFileName
= MapFileName
317 self
.VpdFileName
= VpdFileName
318 self
.FileLinesList
= []
319 self
.PcdFixedOffsetSizeList
= []
320 self
.PcdUnknownOffsetList
= []
322 fInputfile
= open(InputFileName
, "r", 0)
324 self
.FileLinesList
= fInputfile
.readlines()
326 EdkLogger
.error("BPDG", BuildToolError
.FILE_READ_FAILURE
, "File read failed for %s" % InputFileName
, None)
330 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % InputFileName
, None)
333 # Parser the input file which is generated by the build tool. Convert the value of each pcd's
334 # from string to it's real format. Also remove the useless line in the input file.
336 def ParserInputFile (self
):
338 for line
in self
.FileLinesList
:
339 # Strip "\r\n" generated by readlines ().
341 line
= line
.rstrip(os
.linesep
)
343 # Skip the comment line
344 if (not line
.startswith("#")) and len(line
) > 1 :
346 # Enhanced for support "|" character in the string.
348 ValueList
= ['', '', '', '','']
350 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
351 PtrValue
= ValueRe
.findall(line
)
353 ValueUpdateFlag
= False
355 if len(PtrValue
) >= 1:
356 line
= re
.sub(ValueRe
, '', line
)
357 ValueUpdateFlag
= True
359 TokenList
= line
.split('|')
360 ValueList
[0:len(TokenList
)] = TokenList
363 ValueList
[4] = PtrValue
[0]
364 self
.FileLinesList
[count
] = ValueList
365 # Store the line number
366 self
.FileLinesList
[count
].append(str(count
+ 1))
367 elif len(line
) <= 1 :
368 # Set the blank line to "None"
369 self
.FileLinesList
[count
] = None
371 # Set the comment line to "None"
372 self
.FileLinesList
[count
] = None
375 # The line count contain usage information
377 # Delete useless lines
380 if (self
.FileLinesList
[count
] == None) :
381 del(self
.FileLinesList
[count
])
387 # After remove the useless line, if there are no data remain in the file line list,
388 # Report warning messages to user's.
390 if len(self
.FileLinesList
) == 0 :
391 EdkLogger
.warn('BPDG', BuildToolError
.RESOURCE_NOT_AVAILABLE
,
392 "There are no VPD type pcds defined in DSC file, Please check it.")
394 # Process the pcds one by one base on the pcd's value and size
396 for line
in self
.FileLinesList
:
398 PCD
= PcdEntry(line
[0], line
[1], line
[2], line
[3], line
[4],line
[5], self
.InputFileName
)
399 # Strip the space char
400 PCD
.PcdCName
= PCD
.PcdCName
.strip(' ')
401 PCD
.SkuId
= PCD
.SkuId
.strip(' ')
402 PCD
.PcdOffset
= PCD
.PcdOffset
.strip(' ')
403 PCD
.PcdSize
= PCD
.PcdSize
.strip(' ')
404 PCD
.PcdValue
= PCD
.PcdValue
.strip(' ')
405 PCD
.Lineno
= PCD
.Lineno
.strip(' ')
408 # Store the original pcd value.
409 # This information will be useful while generate the output map file.
411 PCD
.PcdUnpackValue
= str(PCD
.PcdValue
)
414 # Translate PCD size string to an integer value.
417 PackSize
= int(PCD
.PcdSize
, 10)
418 PCD
.PcdBinSize
= PackSize
421 PackSize
= int(PCD
.PcdSize
, 16)
422 PCD
.PcdBinSize
= PackSize
424 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, "Invalid PCD size value %s at file: %s line: %s" % (PCD
.PcdSize
, self
.InputFileName
, PCD
.Lineno
))
427 # If value is Unicode string (e.g. L""), then use 2-byte alignment
428 # If value is byte array (e.g. {}), then use 8-byte alignment
430 PCD
.PcdOccupySize
= PCD
.PcdBinSize
431 if PCD
.PcdUnpackValue
.startswith("{"):
433 elif PCD
.PcdUnpackValue
.startswith("L"):
438 PCD
.Alignment
= Alignment
439 if PCD
.PcdOffset
!= '*':
440 if PCD
.PcdOccupySize
% Alignment
!= 0:
441 if PCD
.PcdUnpackValue
.startswith("{"):
442 EdkLogger
.warn("BPDG", "The offset value of PCD %s is not 8-byte aligned!" %(PCD
.PcdCName
), File
=self
.InputFileName
)
444 EdkLogger
.error("BPDG", BuildToolError
.FORMAT_INVALID
, 'The offset value of PCD %s should be %s-byte aligned.' % (PCD
.PcdCName
, Alignment
))
446 if PCD
.PcdOccupySize
% Alignment
!= 0:
447 PCD
.PcdOccupySize
= (PCD
.PcdOccupySize
/ Alignment
+ 1) * Alignment
449 PackSize
= PCD
.PcdOccupySize
450 if PCD
._IsBoolean
(PCD
.PcdValue
, PCD
.PcdSize
):
451 PCD
._PackBooleanValue
(PCD
.PcdValue
)
452 self
.FileLinesList
[count
] = PCD
456 # Try to translate value to an integer firstly.
461 PackValue
= int(PCD
.PcdValue
)
464 PackValue
= int(PCD
.PcdValue
, 16)
469 PCD
._PackIntValue
(PackValue
, PackSize
)
471 PCD
._PackPtrValue
(PCD
.PcdValue
, PackSize
)
473 self
.FileLinesList
[count
] = PCD
479 # This function used to create a clean list only contain useful information and reorganized to make it
482 def FormatFileLine (self
) :
484 for eachPcd
in self
.FileLinesList
:
485 if eachPcd
.PcdOffset
!= '*' :
486 # Use pcd's Offset value as key, and pcd's Value as value
487 self
.PcdFixedOffsetSizeList
.append(eachPcd
)
489 # Use pcd's CName as key, and pcd's Size as value
490 self
.PcdUnknownOffsetList
.append(eachPcd
)
494 # This function is use to fix the offset value which the not specified in the map file.
495 # Usually it use the star (meaning any offset) character in the offset field
497 def FixVpdOffset (self
):
498 # At first, the offset should start at 0
499 # Sort fixed offset list in order to find out where has free spaces for the pcd's offset
500 # value is "*" to insert into.
502 self
.PcdFixedOffsetSizeList
.sort(lambda x
, y
: cmp(x
.PcdBinOffset
, y
.PcdBinOffset
))
505 # Sort the un-fixed pcd's offset by it's size.
507 self
.PcdUnknownOffsetList
.sort(lambda x
, y
: cmp(x
.PcdBinSize
, y
.PcdBinSize
))
510 for pcd
in self
.PcdUnknownOffsetList
:
512 if pcd
.PcdCName
== ".".join(("gEfiMdeModulePkgTokenSpaceGuid","PcdNvStoreDefaultValueBuffer")):
513 if index
!= len(self
.PcdUnknownOffsetList
):
514 for i
in range(len(self
.PcdUnknownOffsetList
) - index
):
515 self
.PcdUnknownOffsetList
[index
+i
-1 ] , self
.PcdUnknownOffsetList
[index
+i
] = self
.PcdUnknownOffsetList
[index
+i
] , self
.PcdUnknownOffsetList
[index
+i
-1]
518 # Process all Offset value are "*"
520 if (len(self
.PcdFixedOffsetSizeList
) == 0) and (len(self
.PcdUnknownOffsetList
) != 0) :
521 # The offset start from 0
523 for Pcd
in self
.PcdUnknownOffsetList
:
524 if NowOffset
% Pcd
.Alignment
!= 0:
525 NowOffset
= (NowOffset
/ Pcd
.Alignment
+ 1) * Pcd
.Alignment
526 Pcd
.PcdBinOffset
= NowOffset
527 Pcd
.PcdOffset
= str(hex(Pcd
.PcdBinOffset
))
528 NowOffset
+= Pcd
.PcdOccupySize
530 self
.PcdFixedOffsetSizeList
= self
.PcdUnknownOffsetList
533 # Check the offset of VPD type pcd's offset start from 0.
534 if self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
!= 0 :
535 EdkLogger
.warn("BPDG", "The offset of VPD type pcd should start with 0, please check it.",
538 # Judge whether the offset in fixed pcd offset list is overlapped or not.
539 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
541 while (count
< lenOfList
- 1) :
542 PcdNow
= self
.PcdFixedOffsetSizeList
[count
]
543 PcdNext
= self
.PcdFixedOffsetSizeList
[count
+1]
544 # Two pcd's offset is same
545 if PcdNow
.PcdBinOffset
== PcdNext
.PcdBinOffset
:
546 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
547 "The offset of %s at line: %s is same with %s at line: %s in file %s" % \
548 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
552 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
> PcdNext
.PcdBinOffset
:
553 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
554 "The offset of %s at line: %s is overlapped with %s at line: %s in file %s" % \
555 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
558 # Has free space, raise a warning message
559 if PcdNow
.PcdBinOffset
+ PcdNow
.PcdOccupySize
< PcdNext
.PcdBinOffset
:
560 EdkLogger
.warn("BPDG", BuildToolError
.ATTRIBUTE_GET_FAILURE
,
561 "The offsets have free space of between %s at line: %s and %s at line: %s in file %s" % \
562 (PcdNow
.PcdCName
, PcdNow
.Lineno
, PcdNext
.PcdCName
, PcdNext
.Lineno
, PcdNext
.FileName
),
566 LastOffset
= self
.PcdFixedOffsetSizeList
[0].PcdBinOffset
567 FixOffsetSizeListCount
= 0
568 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
569 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
572 # Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
574 while (FixOffsetSizeListCount
< lenOfList
) :
576 eachFixedPcd
= self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
]
577 NowOffset
= eachFixedPcd
.PcdBinOffset
580 if LastOffset
< NowOffset
:
581 if lenOfUnfixedList
!= 0 :
582 countOfUnfixedList
= 0
583 while(countOfUnfixedList
< lenOfUnfixedList
) :
584 eachUnfixedPcd
= self
.PcdUnknownOffsetList
[countOfUnfixedList
]
585 needFixPcdSize
= eachUnfixedPcd
.PcdOccupySize
587 if eachUnfixedPcd
.PcdOffset
== '*' :
588 if LastOffset
% eachUnfixedPcd
.Alignment
!= 0:
589 LastOffset
= (LastOffset
/ eachUnfixedPcd
.Alignment
+ 1) * eachUnfixedPcd
.Alignment
590 # The offset un-fixed pcd can write into this free space
591 if needFixPcdSize
<= (NowOffset
- LastOffset
) :
592 # Change the offset value of un-fixed pcd
593 eachUnfixedPcd
.PcdOffset
= str(hex(LastOffset
))
594 eachUnfixedPcd
.PcdBinOffset
= LastOffset
595 # Insert this pcd into fixed offset pcd list.
596 self
.PcdFixedOffsetSizeList
.insert(FixOffsetSizeListCount
,eachUnfixedPcd
)
598 # Delete the item's offset that has been fixed and added into fixed offset list
599 self
.PcdUnknownOffsetList
.pop(countOfUnfixedList
)
601 # After item added, should enlarge the length of fixed pcd offset list
603 FixOffsetSizeListCount
+= 1
605 # Decrease the un-fixed pcd offset list's length
606 lenOfUnfixedList
-= 1
608 # Modify the last offset value
609 LastOffset
+= needFixPcdSize
611 # It can not insert into those two pcds, need to check still has other space can store it.
612 LastOffset
= NowOffset
+ self
.PcdFixedOffsetSizeList
[FixOffsetSizeListCount
].PcdOccupySize
613 FixOffsetSizeListCount
+= 1
616 # Set the FixOffsetSizeListCount = lenOfList for quit the loop
618 FixOffsetSizeListCount
= lenOfList
620 # No free space, smoothly connect with previous pcd.
621 elif LastOffset
== NowOffset
:
622 LastOffset
= NowOffset
+ eachFixedPcd
.PcdOccupySize
623 FixOffsetSizeListCount
+= 1
624 # Usually it will not enter into this thunk, if so, means it overlapped.
626 EdkLogger
.error("BPDG", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
,
627 "The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" % \
628 (eachFixedPcd
.PcdCName
, eachFixedPcd
.PcdOffset
, eachFixedPcd
.InputFileName
, eachFixedPcd
.Lineno
),
630 FixOffsetSizeListCount
+= 1
632 # Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
633 lenOfUnfixedList
= len(self
.PcdUnknownOffsetList
)
634 lenOfList
= len(self
.PcdFixedOffsetSizeList
)
635 while (lenOfUnfixedList
> 0) :
636 # Still has items need to process
637 # The last pcd instance
638 LastPcd
= self
.PcdFixedOffsetSizeList
[lenOfList
-1]
639 NeedFixPcd
= self
.PcdUnknownOffsetList
[0]
641 NeedFixPcd
.PcdBinOffset
= LastPcd
.PcdBinOffset
+ LastPcd
.PcdOccupySize
642 if NeedFixPcd
.PcdBinOffset
% NeedFixPcd
.Alignment
!= 0:
643 NeedFixPcd
.PcdBinOffset
= (NeedFixPcd
.PcdBinOffset
/ NeedFixPcd
.Alignment
+ 1) * NeedFixPcd
.Alignment
645 NeedFixPcd
.PcdOffset
= str(hex(NeedFixPcd
.PcdBinOffset
))
647 # Insert this pcd into fixed offset pcd list's tail.
648 self
.PcdFixedOffsetSizeList
.insert(lenOfList
, NeedFixPcd
)
649 # Delete the item's offset that has been fixed and added into fixed offset list
650 self
.PcdUnknownOffsetList
.pop(0)
653 lenOfUnfixedList
-= 1
655 # Write the final data into output files.
657 def GenerateVpdFile (self
, MapFileName
, BinFileName
):
658 #Open an VPD file to process
661 fVpdFile
= open(BinFileName
, "wb", 0)
664 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.VpdFileName
, None)
667 fMapFile
= open(MapFileName
, "w", 0)
670 EdkLogger
.error("BPDG", BuildToolError
.FILE_OPEN_FAILURE
, "File open failed for %s" % self
.MapFileName
, None)
672 # Use a instance of StringIO to cache data
673 fStringIO
= StringIO
.StringIO('')
675 # Write the header of map file.
677 fMapFile
.write (st
.MAP_FILE_COMMENT_TEMPLATE
+ "\n")
679 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)
681 for eachPcd
in self
.PcdFixedOffsetSizeList
:
684 fMapFile
.write("%s | %s | %s | %s | %s \n" % (eachPcd
.PcdCName
, eachPcd
.SkuId
,eachPcd
.PcdOffset
, eachPcd
.PcdSize
,eachPcd
.PcdUnpackValue
))
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
.MapFileName
, None)
688 # Write Vpd binary file
689 fStringIO
.seek (eachPcd
.PcdBinOffset
)
690 if isinstance(eachPcd
.PcdValue
, list):
691 ValueList
= [chr(Item
) for Item
in eachPcd
.PcdValue
]
692 fStringIO
.write(''.join(ValueList
))
694 fStringIO
.write (eachPcd
.PcdValue
)
697 fVpdFile
.write (fStringIO
.getvalue())
699 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)