]>
Commit | Line | Data |
---|---|---|
a64b9449 CC |
1 | ## @file\r |
2 | # This file is used to define the BIOS Tree Node.\r | |
3 | #\r | |
4 | # Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>\r | |
5 | # SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
6 | ##\r | |
7 | from FirmwareStorageFormat.FvHeader import *\r | |
8 | from FirmwareStorageFormat.FfsFileHeader import *\r | |
9 | from FirmwareStorageFormat.SectionHeader import *\r | |
10 | from FirmwareStorageFormat.Common import *\r | |
11 | from utils.FmmtLogger import FmmtLogger as logger\r | |
12 | import uuid\r | |
13 | \r | |
14 | SectionHeaderType = {\r | |
15 | 0x01:'EFI_COMPRESSION_SECTION',\r | |
16 | 0x02:'EFI_GUID_DEFINED_SECTION',\r | |
17 | 0x03:'EFI_SECTION_DISPOSABLE',\r | |
18 | 0x10:'EFI_SECTION_PE32',\r | |
19 | 0x11:'EFI_SECTION_PIC',\r | |
20 | 0x12:'EFI_SECTION_TE',\r | |
21 | 0x13:'EFI_SECTION_DXE_DEPEX',\r | |
22 | 0x14:'EFI_SECTION_VERSION',\r | |
23 | 0x15:'EFI_SECTION_USER_INTERFACE',\r | |
24 | 0x16:'EFI_SECTION_COMPATIBILITY16',\r | |
25 | 0x17:'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',\r | |
26 | 0x18:'EFI_FREEFORM_SUBTYPE_GUID_SECTION',\r | |
27 | 0x19:'EFI_SECTION_RAW',\r | |
28 | 0x1B:'EFI_SECTION_PEI_DEPEX',\r | |
29 | 0x1C:'EFI_SECTION_MM_DEPEX'\r | |
30 | }\r | |
31 | HeaderType = [0x01, 0x02, 0x14, 0x15, 0x18]\r | |
32 | \r | |
33 | class BinaryNode:\r | |
34 | def __init__(self, name: str) -> None:\r | |
35 | self.Size = 0\r | |
36 | self.Name = "BINARY" + str(name)\r | |
37 | self.HOffset = 0\r | |
38 | self.Data = b''\r | |
39 | \r | |
40 | class FvNode:\r | |
41 | def __init__(self, name, buffer: bytes) -> None:\r | |
42 | self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)\r | |
43 | Map_num = (self.Header.HeaderLength - 56)//8\r | |
44 | self.Header = Refine_FV_Header(Map_num).from_buffer_copy(buffer)\r | |
45 | self.FvId = "FV" + str(name)\r | |
46 | self.Name = "FV" + str(name)\r | |
47 | if self.Header.ExtHeaderOffset:\r | |
48 | self.ExtHeader = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer_copy(buffer[self.Header.ExtHeaderOffset:])\r | |
49 | self.Name = uuid.UUID(bytes_le=struct2stream(self.ExtHeader.FvName))\r | |
50 | self.ExtEntryOffset = self.Header.ExtHeaderOffset + 20\r | |
51 | if self.ExtHeader.ExtHeaderSize != 20:\r | |
52 | self.ExtEntryExist = 1\r | |
53 | self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY.from_buffer_copy(buffer[self.ExtEntryOffset:])\r | |
54 | self.ExtTypeExist = 1\r | |
55 | if self.ExtEntry.ExtEntryType == 0x01:\r | |
56 | nums = (self.ExtEntry.ExtEntrySize - 8) // 16\r | |
57 | self.ExtEntry = Refine_FV_EXT_ENTRY_OEM_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])\r | |
58 | elif self.ExtEntry.ExtEntryType == 0x02:\r | |
59 | nums = self.ExtEntry.ExtEntrySize - 20\r | |
60 | self.ExtEntry = Refine_FV_EXT_ENTRY_GUID_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])\r | |
61 | elif self.ExtEntry.ExtEntryType == 0x03:\r | |
62 | self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE.from_buffer_copy(buffer[self.ExtEntryOffset:])\r | |
63 | else:\r | |
64 | self.ExtTypeExist = 0\r | |
65 | else:\r | |
66 | self.ExtEntryExist = 0\r | |
67 | self.Size = self.Header.FvLength\r | |
68 | self.HeaderLength = self.Header.HeaderLength\r | |
69 | self.HOffset = 0\r | |
70 | self.DOffset = 0\r | |
71 | self.ROffset = 0\r | |
72 | self.Data = b''\r | |
73 | if self.Header.Signature != 1213613663:\r | |
74 | logger.error('Invalid Fv Header! Fv {} signature {} is not "_FVH".'.format(struct2stream(self.Header), self.Header.Signature))\r | |
75 | raise Exception("Process Failed: Fv Header Signature!")\r | |
76 | self.PadData = b''\r | |
77 | self.Free_Space = 0\r | |
78 | self.ModCheckSum()\r | |
79 | \r | |
80 | def ModCheckSum(self) -> None:\r | |
81 | # Fv Header Sums to 0.\r | |
82 | Header = struct2stream(self.Header)[::-1]\r | |
83 | Size = self.HeaderLength // 2\r | |
84 | Sum = 0\r | |
85 | for i in range(Size):\r | |
86 | Sum += int(Header[i*2: i*2 + 2].hex(), 16)\r | |
87 | if Sum & 0xffff:\r | |
88 | self.Header.Checksum = 0x10000 - (Sum - self.Header.Checksum) % 0x10000\r | |
89 | \r | |
90 | def ModFvExt(self) -> None:\r | |
91 | # If used space changes and self.ExtEntry.UsedSize exists, self.ExtEntry.UsedSize need to be changed.\r | |
92 | if self.Header.ExtHeaderOffset and self.ExtEntryExist and self.ExtTypeExist and self.ExtEntry.Hdr.ExtEntryType == 0x03:\r | |
93 | self.ExtEntry.UsedSize = self.Header.FvLength - self.Free_Space\r | |
94 | \r | |
95 | def ModFvSize(self) -> None:\r | |
96 | # If Fv Size changed, self.Header.FvLength and self.Header.BlockMap[i].NumBlocks need to be changed.\r | |
97 | BlockMapNum = len(self.Header.BlockMap)\r | |
98 | for i in range(BlockMapNum):\r | |
99 | if self.Header.BlockMap[i].Length:\r | |
100 | self.Header.BlockMap[i].NumBlocks = self.Header.FvLength // self.Header.BlockMap[i].Length\r | |
101 | \r | |
102 | def ModExtHeaderData(self) -> None:\r | |
103 | if self.Header.ExtHeaderOffset:\r | |
104 | ExtHeaderData = struct2stream(self.ExtHeader)\r | |
105 | ExtHeaderDataOffset = self.Header.ExtHeaderOffset - self.HeaderLength\r | |
106 | self.Data = self.Data[:ExtHeaderDataOffset] + ExtHeaderData + self.Data[ExtHeaderDataOffset+20:]\r | |
107 | if self.Header.ExtHeaderOffset and self.ExtEntryExist:\r | |
108 | ExtHeaderEntryData = struct2stream(self.ExtEntry)\r | |
109 | ExtHeaderEntryDataOffset = self.Header.ExtHeaderOffset + 20 - self.HeaderLength\r | |
110 | self.Data = self.Data[:ExtHeaderEntryDataOffset] + ExtHeaderEntryData + self.Data[ExtHeaderEntryDataOffset+len(ExtHeaderEntryData):]\r | |
111 | \r | |
112 | class FfsNode:\r | |
113 | def __init__(self, buffer: bytes) -> None:\r | |
114 | self.Header = EFI_FFS_FILE_HEADER.from_buffer_copy(buffer)\r | |
115 | # self.Attributes = unpack("<B", buffer[21:22])[0]\r | |
116 | if self.Header.FFS_FILE_SIZE != 0 and self.Header.Attributes != 0xff and self.Header.Attributes & 0x01 == 1:\r | |
117 | logger.error('Error Ffs Header! Ffs {} Header Size and Attributes is not matched!'.format(uuid.UUID(bytes_le=struct2stream(self.Header.Name))))\r | |
118 | raise Exception("Process Failed: Error Ffs Header!")\r | |
119 | if self.Header.FFS_FILE_SIZE == 0 and self.Header.Attributes & 0x01 == 1:\r | |
120 | self.Header = EFI_FFS_FILE_HEADER2.from_buffer_copy(buffer)\r | |
121 | self.Name = uuid.UUID(bytes_le=struct2stream(self.Header.Name))\r | |
122 | self.UiName = b''\r | |
123 | self.Version = b''\r | |
124 | self.Size = self.Header.FFS_FILE_SIZE\r | |
125 | self.HeaderLength = self.Header.HeaderLength\r | |
126 | self.HOffset = 0\r | |
127 | self.DOffset = 0\r | |
128 | self.ROffset = 0\r | |
129 | self.Data = b''\r | |
130 | self.PadData = b''\r | |
131 | self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align\r | |
132 | \r | |
133 | def ModCheckSum(self) -> None:\r | |
134 | HeaderData = struct2stream(self.Header)\r | |
135 | HeaderSum = 0\r | |
136 | for item in HeaderData:\r | |
137 | HeaderSum += item\r | |
138 | HeaderSum -= self.Header.State\r | |
139 | HeaderSum -= self.Header.IntegrityCheck.Checksum.File\r | |
140 | if HeaderSum & 0xff:\r | |
141 | Header = self.Header.IntegrityCheck.Checksum.Header + 0x100 - HeaderSum % 0x100\r | |
142 | self.Header.IntegrityCheck.Checksum.Header = Header % 0x100\r | |
143 | \r | |
144 | class SectionNode:\r | |
145 | def __init__(self, buffer: bytes) -> None:\r | |
146 | if buffer[0:3] != b'\xff\xff\xff':\r | |
147 | self.Header = EFI_COMMON_SECTION_HEADER.from_buffer_copy(buffer)\r | |
148 | else:\r | |
149 | self.Header = EFI_COMMON_SECTION_HEADER2.from_buffer_copy(buffer)\r | |
150 | if self.Header.Type in SectionHeaderType:\r | |
151 | self.Name = SectionHeaderType[self.Header.Type]\r | |
152 | elif self.Header.Type == 0:\r | |
153 | self.Name = "EFI_SECTION_ALL"\r | |
154 | else:\r | |
155 | self.Name = "SECTION"\r | |
156 | if self.Header.Type in HeaderType:\r | |
157 | self.ExtHeader = self.GetExtHeader(self.Header.Type, buffer[self.Header.Common_Header_Size():], (self.Header.SECTION_SIZE-self.Header.Common_Header_Size()))\r | |
158 | self.HeaderLength = self.Header.Common_Header_Size() + self.ExtHeader.ExtHeaderSize()\r | |
159 | else:\r | |
160 | self.ExtHeader = None\r | |
161 | self.HeaderLength = self.Header.Common_Header_Size()\r | |
162 | self.Size = self.Header.SECTION_SIZE\r | |
163 | self.Type = self.Header.Type\r | |
164 | self.HOffset = 0\r | |
165 | self.DOffset = 0\r | |
166 | self.ROffset = 0\r | |
167 | self.Data = b''\r | |
168 | self.OriData = b''\r | |
169 | self.OriHeader = b''\r | |
170 | self.PadData = b''\r | |
171 | self.IsPadSection = False\r | |
172 | self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align\r | |
173 | \r | |
174 | def GetExtHeader(self, Type: int, buffer: bytes, nums: int=0) -> None:\r | |
175 | if Type == 0x01:\r | |
176 | return EFI_COMPRESSION_SECTION.from_buffer_copy(buffer)\r | |
177 | elif Type == 0x02:\r | |
178 | return EFI_GUID_DEFINED_SECTION.from_buffer_copy(buffer)\r | |
179 | elif Type == 0x14:\r | |
180 | return Get_VERSION_Header((nums - 2)//2).from_buffer_copy(buffer)\r | |
181 | elif Type == 0x15:\r | |
182 | return Get_USER_INTERFACE_Header(nums//2).from_buffer_copy(buffer)\r | |
183 | elif Type == 0x18:\r | |
184 | return EFI_FREEFORM_SUBTYPE_GUID_SECTION.from_buffer_copy(buffer)\r | |
185 | \r | |
186 | class FreeSpaceNode:\r | |
187 | def __init__(self, buffer: bytes) -> None:\r | |
188 | self.Name = 'Free_Space'\r | |
189 | self.Data = buffer\r | |
190 | self.Size = len(buffer)\r | |
191 | self.HOffset = 0\r | |
192 | self.DOffset = 0\r | |
193 | self.ROffset = 0\r | |
194 | self.PadData = b''\r |