]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
BaseTools: Add FMMT Python Tool
[mirror_edk2.git] / BaseTools / Source / Python / FMMT / core / BiosTreeNode.py
CommitLineData
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
7from FirmwareStorageFormat.FvHeader import *\r
8from FirmwareStorageFormat.FfsFileHeader import *\r
9from FirmwareStorageFormat.SectionHeader import *\r
10from FirmwareStorageFormat.Common import *\r
11from utils.FmmtLogger import FmmtLogger as logger\r
12import uuid\r
13\r
14SectionHeaderType = {\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
31HeaderType = [0x01, 0x02, 0x14, 0x15, 0x18]\r
32\r
33class 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
40class 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
112class 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
144class 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
186class 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