# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR> | |
# This program and the accompanying materials | |
# are licensed and made available under the terms and conditions of the BSD License | |
# which accompanies this distribution. The full text of the license may be found at | |
# http://opensource.org/licenses/bsd-license.php | |
# | |
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
# | |
# This file is used to collect the Variable checking information | |
# | |
# # | |
# Import Modules | |
# | |
import os | |
from Common.RangeExpression import RangeExpression | |
from Common.Misc import * | |
from io import BytesIO | |
from struct import pack | |
from Common.DataType import * | |
class VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER(object): | |
def __init__(self): | |
self.var_check_info = [] | |
def push_back(self, var_check_tab): | |
for tab in self.var_check_info: | |
if tab.equal(var_check_tab): | |
tab.merge(var_check_tab) | |
break | |
else: | |
self.var_check_info.append(var_check_tab) | |
def dump(self, dest, Phase): | |
if not os.path.isabs(dest): | |
return | |
if not os.path.exists(dest): | |
os.mkdir(dest) | |
BinFileName = "PcdVarCheck.bin" | |
BinFilePath = os.path.join(dest, BinFileName) | |
Buffer = '' | |
index = 0 | |
for var_check_tab in self.var_check_info: | |
index += 1 | |
realLength = 0 | |
realLength += 32 | |
Name = var_check_tab.Name[1:-1] | |
NameChars = Name.split(",") | |
realLength += len(NameChars) | |
if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4): | |
realLength += (4 - (realLength % 4)) | |
itemIndex = 0 | |
for item in var_check_tab.validtab: | |
itemIndex += 1 | |
realLength += 5 | |
for v_data in item.data: | |
if type(v_data) in (int, long): | |
realLength += item.StorageWidth | |
else: | |
realLength += item.StorageWidth | |
realLength += item.StorageWidth | |
if (index == len(self.var_check_info)) : | |
if (itemIndex < len(var_check_tab.validtab)) and realLength % 4: | |
realLength += (4 - (realLength % 4)) | |
else: | |
if realLength % 4: | |
realLength += (4 - (realLength % 4)) | |
var_check_tab.Length = realLength | |
realLength = 0 | |
index = 0 | |
for var_check_tab in self.var_check_info: | |
index += 1 | |
b = pack("=H", var_check_tab.Revision) | |
Buffer += b | |
realLength += 2 | |
b = pack("=H", var_check_tab.HeaderLength) | |
Buffer += b | |
realLength += 2 | |
b = pack("=L", var_check_tab.Length) | |
Buffer += b | |
realLength += 4 | |
b = pack("=B", var_check_tab.Type) | |
Buffer += b | |
realLength += 1 | |
for i in range(0, 3): | |
b = pack("=B", var_check_tab.Reserved) | |
Buffer += b | |
realLength += 1 | |
b = pack("=L", var_check_tab.Attributes) | |
Buffer += b | |
realLength += 4 | |
Guid = var_check_tab.Guid | |
b = PackByteFormatGUID(Guid) | |
Buffer += b | |
realLength += 16 | |
Name = var_check_tab.Name[1:-1] | |
NameChars = Name.split(",") | |
for NameChar in NameChars: | |
NameCharNum = int(NameChar, 16) | |
b = pack("=B", NameCharNum) | |
Buffer += b | |
realLength += 1 | |
if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4): | |
for i in range(4 - (realLength % 4)): | |
b = pack("=B", var_check_tab.pad) | |
Buffer += b | |
realLength += 1 | |
itemIndex = 0 | |
for item in var_check_tab.validtab: | |
itemIndex += 1 | |
b = pack("=B", item.Type) | |
Buffer += b | |
realLength += 1 | |
b = pack("=B", item.Length) | |
Buffer += b | |
realLength += 1 | |
b = pack("=H", int(item.VarOffset, 16)) | |
Buffer += b | |
realLength += 2 | |
b = pack("=B", item.StorageWidth) | |
Buffer += b | |
realLength += 1 | |
for v_data in item.data: | |
if type(v_data) in (int, long): | |
b = pack(PACK_CODE_BY_SIZE[item.StorageWidth], v_data) | |
Buffer += b | |
realLength += item.StorageWidth | |
else: | |
b = pack(PACK_CODE_BY_SIZE[item.StorageWidth], v_data[0]) | |
Buffer += b | |
realLength += item.StorageWidth | |
b = pack(PACK_CODE_BY_SIZE[item.StorageWidth], v_data[1]) | |
Buffer += b | |
realLength += item.StorageWidth | |
if (index == len(self.var_check_info)) : | |
if (itemIndex < len(var_check_tab.validtab)) and realLength % 4: | |
for i in range(4 - (realLength % 4)): | |
b = pack("=B", var_check_tab.pad) | |
Buffer += b | |
realLength += 1 | |
else: | |
if realLength % 4: | |
for i in range(4 - (realLength % 4)): | |
b = pack("=B", var_check_tab.pad) | |
Buffer += b | |
realLength += 1 | |
DbFile = BytesIO() | |
if Phase == 'DXE' and os.path.exists(BinFilePath): | |
BinFile = open(BinFilePath, "rb") | |
BinBuffer = BinFile.read() | |
BinFile.close() | |
BinBufferSize = len(BinBuffer) | |
if (BinBufferSize % 4): | |
for i in range(4 - (BinBufferSize % 4)): | |
b = pack("=B", VAR_CHECK_PCD_VARIABLE_TAB.pad) | |
BinBuffer += b | |
Buffer = BinBuffer + Buffer | |
DbFile.write(Buffer) | |
SaveFileOnChange(BinFilePath, DbFile.getvalue(), True) | |
class VAR_CHECK_PCD_VARIABLE_TAB(object): | |
pad = 0xDA | |
def __init__(self, TokenSpaceGuid, PcdCName): | |
self.Revision = 0x0001 | |
self.HeaderLength = 0 | |
self.Length = 0 # Length include this header | |
self.Type = 0 | |
self.Reserved = 0 | |
self.Attributes = 0x00000000 | |
self.Guid = eval("[" + TokenSpaceGuid.replace("{", "").replace("}", "") + "]") | |
self.Name = PcdCName | |
self.validtab = [] | |
def UpdateSize(self): | |
self.HeaderLength = 32 + len(self.Name.split(",")) | |
self.Length = 32 + len(self.Name.split(",")) + self.GetValidTabLen() | |
def GetValidTabLen(self): | |
validtablen = 0 | |
for item in self.validtab: | |
validtablen += item.Length | |
return validtablen | |
def SetAttributes(self, attributes): | |
self.Attributes = attributes | |
def push_back(self, valid_obj): | |
if valid_obj is not None: | |
self.validtab.append(valid_obj) | |
def equal(self, varchecktab): | |
if self.Guid == varchecktab.Guid and self.Name == varchecktab.Name: | |
return True | |
else: | |
return False | |
def merge(self, varchecktab): | |
for validobj in varchecktab.validtab: | |
if validobj in self.validtab: | |
continue | |
self.validtab.append(validobj) | |
self.UpdateSize() | |
class VAR_CHECK_PCD_VALID_OBJ(object): | |
def __init__(self, VarOffset, data, PcdDataType): | |
self.Type = 1 | |
self.Length = 0 # Length include this header | |
self.VarOffset = VarOffset | |
self.PcdDataType = PcdDataType.strip() | |
self.rawdata = data | |
self.data = set() | |
try: | |
self.StorageWidth = MAX_SIZE_TYPE[self.PcdDataType] | |
self.ValidData = True | |
except: | |
self.StorageWidth = 0 | |
self.ValidData = False | |
def __eq__(self, validObj): | |
return validObj and self.VarOffset == validObj.VarOffset | |
class VAR_CHECK_PCD_VALID_LIST(VAR_CHECK_PCD_VALID_OBJ): | |
def __init__(self, VarOffset, validlist, PcdDataType): | |
super(VAR_CHECK_PCD_VALID_LIST, self).__init__(VarOffset, validlist, PcdDataType) | |
self.Type = 1 | |
valid_num_list = [] | |
for item in self.rawdata: | |
valid_num_list.extend(item.split(',')) | |
for valid_num in valid_num_list: | |
valid_num = valid_num.strip() | |
if valid_num.startswith('0x') or valid_num.startswith('0X'): | |
self.data.add(int(valid_num, 16)) | |
else: | |
self.data.add(int(valid_num)) | |
self.Length = 5 + len(self.data) * self.StorageWidth | |
class VAR_CHECK_PCD_VALID_RANGE(VAR_CHECK_PCD_VALID_OBJ): | |
def __init__(self, VarOffset, validrange, PcdDataType): | |
super(VAR_CHECK_PCD_VALID_RANGE, self).__init__(VarOffset, validrange, PcdDataType) | |
self.Type = 2 | |
RangeExpr = "" | |
i = 0 | |
for item in self.rawdata: | |
if i == 0: | |
RangeExpr = "( " + item + " )" | |
else: | |
RangeExpr = RangeExpr + "OR ( " + item + " )" | |
range_result = RangeExpression(RangeExpr, self.PcdDataType)(True) | |
for rangelist in range_result: | |
for obj in rangelist.pop(): | |
self.data.add((obj.start, obj.end)) | |
self.Length = 5 + len(self.data) * 2 * self.StorageWidth | |
def GetValidationObject(PcdClass, VarOffset): | |
if PcdClass.validateranges: | |
return VAR_CHECK_PCD_VALID_RANGE(VarOffset, PcdClass.validateranges, PcdClass.DatumType) | |
if PcdClass.validlists: | |
return VAR_CHECK_PCD_VALID_LIST(VarOffset, PcdClass.validlists, PcdClass.DatumType) | |
else: | |
return None |