1# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
2# This program and the accompanying materials
3# are licensed and made available under the terms and conditions of the BSD License
4# which accompanies this distribution.  The full text of the license may be found at
5# http://opensource.org/licenses/bsd-license.php
6#
7# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
8# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
9
10#
11# This file is used to collect the Variable checking information
12#
13
14# #
15# Import Modules
16#
17import os
18from Common.RangeExpression import RangeExpression
19from Common.Misc import *
20from StringIO import StringIO
21from struct import pack
22
23class VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER(object):
24    def __init__(self):
25        self.var_check_info = []
26
27    def push_back(self, var_check_tab):
28        for tab in self.var_check_info:
29            if tab.equal(var_check_tab):
30                tab.merge(var_check_tab)
31                break
32        else:
33            self.var_check_info.append(var_check_tab)
34
35    def dump(self, dest, Phase):
36
37        FormatMap = {}
38        FormatMap[1] = "=B"
39        FormatMap[2] = "=H"
40        FormatMap[4] = "=L"
41        FormatMap[8] = "=Q"
42
43        if not os.path.isabs(dest):
44            return
45        if not os.path.exists(dest):
46            os.mkdir(dest)
47        BinFileName = "PcdVarCheck.bin"
48        BinFilePath = os.path.join(dest, BinFileName)
49        Buffer = ''
50        index = 0
51        for var_check_tab in self.var_check_info:
52            index += 1
53            realLength = 0
54            realLength += 32
55            Name = var_check_tab.Name[1:-1]
56            NameChars = Name.split(",")
57            realLength += len(NameChars)
58            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):
59                realLength += (4 - (realLength % 4))
60            itemIndex = 0
61            for item in var_check_tab.validtab:
62                itemIndex += 1
63                realLength += 5
64                for v_data in item.data:
65                    if type(v_data) in (int, long):
66                        realLength += item.StorageWidth
67                    else:
68                        realLength += item.StorageWidth
69                        realLength += item.StorageWidth
70                if (index == len(self.var_check_info)) :
71                    if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
72                        realLength += (4 - (realLength % 4))
73                else:
74                    if realLength % 4:
75                        realLength += (4 - (realLength % 4))
76            var_check_tab.Length = realLength
77        realLength = 0
78        index = 0
79        for var_check_tab in self.var_check_info:
80            index += 1
81
82            b = pack("=H", var_check_tab.Revision)
83            Buffer += b
84            realLength += 2
85
86            b = pack("=H", var_check_tab.HeaderLength)
87            Buffer += b
88            realLength += 2
89
90            b = pack("=L", var_check_tab.Length)
91            Buffer += b
92            realLength += 4
93
94            b = pack("=B", var_check_tab.Type)
95            Buffer += b
96            realLength += 1
97
98            for i in range(0, 3):
99                b = pack("=B", var_check_tab.Reserved)
100                Buffer += b
101                realLength += 1
102
103            b = pack("=L", var_check_tab.Attributes)
104            Buffer += b
105            realLength += 4
106
107            Guid = var_check_tab.Guid
108            b = pack('=LHHBBBBBBBB',
109                Guid[0],
110                Guid[1],
111                Guid[2],
112                Guid[3],
113                Guid[4],
114                Guid[5],
115                Guid[6],
116                Guid[7],
117                Guid[8],
118                Guid[9],
119                Guid[10],
120                )
121            Buffer += b
122            realLength += 16
123
124            Name = var_check_tab.Name[1:-1]
125            NameChars = Name.split(",")
126            for NameChar in NameChars:
127                NameCharNum = int(NameChar, 16)
128                b = pack("=B", NameCharNum)
129                Buffer += b
130                realLength += 1
131
132            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):
133                for i in range(4 - (realLength % 4)):
134                    b = pack("=B", var_check_tab.pad)
135                    Buffer += b
136                    realLength += 1
137            itemIndex = 0
138            for item in var_check_tab.validtab:
139                itemIndex += 1
140
141                b = pack("=B", item.Type)
142                Buffer += b
143                realLength += 1
144
145                b = pack("=B", item.Length)
146                Buffer += b
147                realLength += 1
148
149                b = pack("=H", int(item.VarOffset, 16))
150                Buffer += b
151                realLength += 2
152
153                b = pack("=B", item.StorageWidth)
154                Buffer += b
155                realLength += 1
156                for v_data in item.data:
157                    if type(v_data) in (int, long):
158                        b = pack(FormatMap[item.StorageWidth], v_data)
159                        Buffer += b
160                        realLength += item.StorageWidth
161                    else:
162                        b = pack(FormatMap[item.StorageWidth], v_data[0])
163                        Buffer += b
164                        realLength += item.StorageWidth
165                        b = pack(FormatMap[item.StorageWidth], v_data[1])
166                        Buffer += b
167                        realLength += item.StorageWidth
168
169                if (index == len(self.var_check_info)) :
170                    if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
171                        for i in range(4 - (realLength % 4)):
172                            b = pack("=B", var_check_tab.pad)
173                            Buffer += b
174                            realLength += 1
175                else:
176                    if realLength % 4:
177                        for i in range(4 - (realLength % 4)):
178                            b = pack("=B", var_check_tab.pad)
179                            Buffer += b
180                            realLength += 1
181
182        DbFile = StringIO()
183        if Phase == 'DXE' and os.path.exists(BinFilePath):
184            BinFile = open(BinFilePath, "rb")
185            BinBuffer = BinFile.read()
186            BinFile.close()
187            BinBufferSize = len(BinBuffer)
188            if (BinBufferSize % 4):
189                for i in range(4 - (BinBufferSize % 4)):
190                    b = pack("=B", VAR_CHECK_PCD_VARIABLE_TAB.pad)
191                    BinBuffer += b
192            Buffer = BinBuffer + Buffer
193        DbFile.write(Buffer)
194        SaveFileOnChange(BinFilePath, DbFile.getvalue(), True)
195
196
197class VAR_CHECK_PCD_VARIABLE_TAB(object):
198    pad = 0xDA
199    def __init__(self, TokenSpaceGuid, PcdCName):
200        self.Revision = 0x0001
201        self.HeaderLength = 0
202        self.Length = 0  # Length include this header
203        self.Type = 0
204        self.Reserved = 0
205        self.Attributes = 0x00000000
206        self.Guid = eval("[" + TokenSpaceGuid.replace("{", "").replace("}", "") + "]")
207        self.Name = PcdCName
208        self.validtab = []
209
210    def UpdateSize(self):
211        self.HeaderLength = 32 + len(self.Name.split(","))
212        self.Length = 32 + len(self.Name.split(",")) + self.GetValidTabLen()
213
214    def GetValidTabLen(self):
215        validtablen = 0
216        for item in self.validtab:
217            validtablen += item.Length
218        return validtablen
219
220    def SetAttributes(self, attributes):
221        self.Attributes = attributes
222
223    def push_back(self, valid_obj):
224        if valid_obj is not None:
225            self.validtab.append(valid_obj)
226
227    def equal(self, varchecktab):
228        if self.Guid == varchecktab.Guid and self.Name == varchecktab.Name:
229            return True
230        else:
231            return False
232
233    def merge(self, varchecktab):
234        for validobj in varchecktab.validtab:
235            if validobj in self.validtab:
236                continue
237            self.validtab.append(validobj)
238        self.UpdateSize()
239
240
241class VAR_CHECK_PCD_VALID_OBJ(object):
242    def __init__(self, VarOffset, data, PcdDataType):
243        self.Type = 1
244        self.Length = 0  # Length include this header
245        self.VarOffset = VarOffset
246        self.StorageWidth = 0
247        self.PcdDataType = PcdDataType.strip()
248        self.rawdata = data
249        self.data = set()
250        self.ValidData = True
251        self.updateStorageWidth()
252    def updateStorageWidth(self):
253        if self.PcdDataType == "UINT8" or self.PcdDataType == "BOOLEAN":
254            self.StorageWidth = 1
255        elif self.PcdDataType == "UINT16":
256            self.StorageWidth = 2
257        elif self.PcdDataType == "UINT32":
258            self.StorageWidth = 4
259        elif self.PcdDataType == "UINT64":
260            self.StorageWidth = 8
261        else:
262            self.StorageWidth = 0
263            self.ValidData = False
264
265    def __eq__(self, validObj):
266        if self.VarOffset == validObj.VarOffset:
267            return True
268        else:
269            return False
270
271class VAR_CHECK_PCD_VALID_LIST(VAR_CHECK_PCD_VALID_OBJ):
272    def __init__(self, VarOffset, validlist, PcdDataType):
273        super(VAR_CHECK_PCD_VALID_LIST, self).__init__(VarOffset, validlist, PcdDataType)
274        self.Type = 1
275        self.update_data()
276        self.update_size()
277    def update_data(self):
278        valid_num_list = []
279        data_list = []
280        for item in self.rawdata:
281            valid_num_list.extend(item.split(','))
282
283        for valid_num in valid_num_list:
284            valid_num = valid_num.strip()
285
286            if valid_num.startswith('0x') or valid_num.startswith('0X'):
287                data_list.append(int(valid_num, 16))
288            else:
289                data_list.append(int(valid_num))
290
291
292        self.data = set(data_list)
293
294    def update_size(self):
295        self.Length = 5 + len(self.data) * self.StorageWidth
296
297
298class VAR_CHECK_PCD_VALID_RANGE(VAR_CHECK_PCD_VALID_OBJ):
299    def __init__(self, VarOffset, validrange, PcdDataType):
300        super(VAR_CHECK_PCD_VALID_RANGE, self).__init__(VarOffset, validrange, PcdDataType)
301        self.Type = 2
302        self.update_data()
303        self.update_size()
304    def update_data(self):
305        RangeExpr = ""
306        data_list = []
307        i = 0
308        for item in self.rawdata:
309            if i == 0:
310                RangeExpr = "( " + item + " )"
311            else:
312                RangeExpr = RangeExpr + "OR ( " + item + " )"
313        range_result = RangeExpression(RangeExpr, self.PcdDataType)(True)
314        for rangelist in range_result:
315            for obj in rangelist.pop():
316                data_list.append((obj.start, obj.end))
317        self.data = set(data_list)
318
319    def update_size(self):
320        self.Length = 5 + len(self.data) * 2 * self.StorageWidth
321
322
323class VAR_VALID_OBJECT_FACTORY(object):
324    def __init__(self):
325        pass
326    @staticmethod
327    def Get_valid_object(PcdClass, VarOffset):
328        if PcdClass.validateranges:
329            return VAR_CHECK_PCD_VALID_RANGE(VarOffset, PcdClass.validateranges, PcdClass.DatumType)
330        if PcdClass.validlists:
331            return VAR_CHECK_PCD_VALID_LIST(VarOffset, PcdClass.validlists, PcdClass.DatumType)
332        else:
333            return None
334
335if __name__ == "__main__":
336    class TestObj(object):
337        def __init__(self, number1):
338            self.number_1 = number1
339        def __eq__(self, testobj):
340            if self.number_1 == testobj.number_1:
341                return True
342            else:
343                return False
344    test1 = TestObj(1)
345    test2 = TestObj(2)
346
347    testarr = [test1, test2]
348    print TestObj(2) in testarr
349    print TestObj(2) == test2
350
351