--- /dev/null
+## @file\r
+# This file is used to define the BIOS Tree Node.\r
+#\r
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+##\r
+from FirmwareStorageFormat.FvHeader import *\r
+from FirmwareStorageFormat.FfsFileHeader import *\r
+from FirmwareStorageFormat.SectionHeader import *\r
+from FirmwareStorageFormat.Common import *\r
+from utils.FmmtLogger import FmmtLogger as logger\r
+import uuid\r
+\r
+SectionHeaderType = {\r
+ 0x01:'EFI_COMPRESSION_SECTION',\r
+ 0x02:'EFI_GUID_DEFINED_SECTION',\r
+ 0x03:'EFI_SECTION_DISPOSABLE',\r
+ 0x10:'EFI_SECTION_PE32',\r
+ 0x11:'EFI_SECTION_PIC',\r
+ 0x12:'EFI_SECTION_TE',\r
+ 0x13:'EFI_SECTION_DXE_DEPEX',\r
+ 0x14:'EFI_SECTION_VERSION',\r
+ 0x15:'EFI_SECTION_USER_INTERFACE',\r
+ 0x16:'EFI_SECTION_COMPATIBILITY16',\r
+ 0x17:'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',\r
+ 0x18:'EFI_FREEFORM_SUBTYPE_GUID_SECTION',\r
+ 0x19:'EFI_SECTION_RAW',\r
+ 0x1B:'EFI_SECTION_PEI_DEPEX',\r
+ 0x1C:'EFI_SECTION_MM_DEPEX'\r
+}\r
+HeaderType = [0x01, 0x02, 0x14, 0x15, 0x18]\r
+\r
+class BinaryNode:\r
+ def __init__(self, name: str) -> None:\r
+ self.Size = 0\r
+ self.Name = "BINARY" + str(name)\r
+ self.HOffset = 0\r
+ self.Data = b''\r
+\r
+class FvNode:\r
+ def __init__(self, name, buffer: bytes) -> None:\r
+ self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)\r
+ Map_num = (self.Header.HeaderLength - 56)//8\r
+ self.Header = Refine_FV_Header(Map_num).from_buffer_copy(buffer)\r
+ self.FvId = "FV" + str(name)\r
+ self.Name = "FV" + str(name)\r
+ if self.Header.ExtHeaderOffset:\r
+ self.ExtHeader = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer_copy(buffer[self.Header.ExtHeaderOffset:])\r
+ self.Name = uuid.UUID(bytes_le=struct2stream(self.ExtHeader.FvName))\r
+ self.ExtEntryOffset = self.Header.ExtHeaderOffset + 20\r
+ if self.ExtHeader.ExtHeaderSize != 20:\r
+ self.ExtEntryExist = 1\r
+ self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY.from_buffer_copy(buffer[self.ExtEntryOffset:])\r
+ self.ExtTypeExist = 1\r
+ if self.ExtEntry.ExtEntryType == 0x01:\r
+ nums = (self.ExtEntry.ExtEntrySize - 8) // 16\r
+ self.ExtEntry = Refine_FV_EXT_ENTRY_OEM_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])\r
+ elif self.ExtEntry.ExtEntryType == 0x02:\r
+ nums = self.ExtEntry.ExtEntrySize - 20\r
+ self.ExtEntry = Refine_FV_EXT_ENTRY_GUID_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])\r
+ elif self.ExtEntry.ExtEntryType == 0x03:\r
+ self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE.from_buffer_copy(buffer[self.ExtEntryOffset:])\r
+ else:\r
+ self.ExtTypeExist = 0\r
+ else:\r
+ self.ExtEntryExist = 0\r
+ self.Size = self.Header.FvLength\r
+ self.HeaderLength = self.Header.HeaderLength\r
+ self.HOffset = 0\r
+ self.DOffset = 0\r
+ self.ROffset = 0\r
+ self.Data = b''\r
+ if self.Header.Signature != 1213613663:\r
+ logger.error('Invalid Fv Header! Fv {} signature {} is not "_FVH".'.format(struct2stream(self.Header), self.Header.Signature))\r
+ raise Exception("Process Failed: Fv Header Signature!")\r
+ self.PadData = b''\r
+ self.Free_Space = 0\r
+ self.ModCheckSum()\r
+\r
+ def ModCheckSum(self) -> None:\r
+ # Fv Header Sums to 0.\r
+ Header = struct2stream(self.Header)[::-1]\r
+ Size = self.HeaderLength // 2\r
+ Sum = 0\r
+ for i in range(Size):\r
+ Sum += int(Header[i*2: i*2 + 2].hex(), 16)\r
+ if Sum & 0xffff:\r
+ self.Header.Checksum = 0x10000 - (Sum - self.Header.Checksum) % 0x10000\r
+\r
+ def ModFvExt(self) -> None:\r
+ # If used space changes and self.ExtEntry.UsedSize exists, self.ExtEntry.UsedSize need to be changed.\r
+ if self.Header.ExtHeaderOffset and self.ExtEntryExist and self.ExtTypeExist and self.ExtEntry.Hdr.ExtEntryType == 0x03:\r
+ self.ExtEntry.UsedSize = self.Header.FvLength - self.Free_Space\r
+\r
+ def ModFvSize(self) -> None:\r
+ # If Fv Size changed, self.Header.FvLength and self.Header.BlockMap[i].NumBlocks need to be changed.\r
+ BlockMapNum = len(self.Header.BlockMap)\r
+ for i in range(BlockMapNum):\r
+ if self.Header.BlockMap[i].Length:\r
+ self.Header.BlockMap[i].NumBlocks = self.Header.FvLength // self.Header.BlockMap[i].Length\r
+\r
+ def ModExtHeaderData(self) -> None:\r
+ if self.Header.ExtHeaderOffset:\r
+ ExtHeaderData = struct2stream(self.ExtHeader)\r
+ ExtHeaderDataOffset = self.Header.ExtHeaderOffset - self.HeaderLength\r
+ self.Data = self.Data[:ExtHeaderDataOffset] + ExtHeaderData + self.Data[ExtHeaderDataOffset+20:]\r
+ if self.Header.ExtHeaderOffset and self.ExtEntryExist:\r
+ ExtHeaderEntryData = struct2stream(self.ExtEntry)\r
+ ExtHeaderEntryDataOffset = self.Header.ExtHeaderOffset + 20 - self.HeaderLength\r
+ self.Data = self.Data[:ExtHeaderEntryDataOffset] + ExtHeaderEntryData + self.Data[ExtHeaderEntryDataOffset+len(ExtHeaderEntryData):]\r
+\r
+class FfsNode:\r
+ def __init__(self, buffer: bytes) -> None:\r
+ self.Header = EFI_FFS_FILE_HEADER.from_buffer_copy(buffer)\r
+ # self.Attributes = unpack("<B", buffer[21:22])[0]\r
+ if self.Header.FFS_FILE_SIZE != 0 and self.Header.Attributes != 0xff and self.Header.Attributes & 0x01 == 1:\r
+ logger.error('Error Ffs Header! Ffs {} Header Size and Attributes is not matched!'.format(uuid.UUID(bytes_le=struct2stream(self.Header.Name))))\r
+ raise Exception("Process Failed: Error Ffs Header!")\r
+ if self.Header.FFS_FILE_SIZE == 0 and self.Header.Attributes & 0x01 == 1:\r
+ self.Header = EFI_FFS_FILE_HEADER2.from_buffer_copy(buffer)\r
+ self.Name = uuid.UUID(bytes_le=struct2stream(self.Header.Name))\r
+ self.UiName = b''\r
+ self.Version = b''\r
+ self.Size = self.Header.FFS_FILE_SIZE\r
+ self.HeaderLength = self.Header.HeaderLength\r
+ self.HOffset = 0\r
+ self.DOffset = 0\r
+ self.ROffset = 0\r
+ self.Data = b''\r
+ self.PadData = b''\r
+ self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align\r
+\r
+ def ModCheckSum(self) -> None:\r
+ HeaderData = struct2stream(self.Header)\r
+ HeaderSum = 0\r
+ for item in HeaderData:\r
+ HeaderSum += item\r
+ HeaderSum -= self.Header.State\r
+ HeaderSum -= self.Header.IntegrityCheck.Checksum.File\r
+ if HeaderSum & 0xff:\r
+ Header = self.Header.IntegrityCheck.Checksum.Header + 0x100 - HeaderSum % 0x100\r
+ self.Header.IntegrityCheck.Checksum.Header = Header % 0x100\r
+\r
+class SectionNode:\r
+ def __init__(self, buffer: bytes) -> None:\r
+ if buffer[0:3] != b'\xff\xff\xff':\r
+ self.Header = EFI_COMMON_SECTION_HEADER.from_buffer_copy(buffer)\r
+ else:\r
+ self.Header = EFI_COMMON_SECTION_HEADER2.from_buffer_copy(buffer)\r
+ if self.Header.Type in SectionHeaderType:\r
+ self.Name = SectionHeaderType[self.Header.Type]\r
+ elif self.Header.Type == 0:\r
+ self.Name = "EFI_SECTION_ALL"\r
+ else:\r
+ self.Name = "SECTION"\r
+ if self.Header.Type in HeaderType:\r
+ self.ExtHeader = self.GetExtHeader(self.Header.Type, buffer[self.Header.Common_Header_Size():], (self.Header.SECTION_SIZE-self.Header.Common_Header_Size()))\r
+ self.HeaderLength = self.Header.Common_Header_Size() + self.ExtHeader.ExtHeaderSize()\r
+ else:\r
+ self.ExtHeader = None\r
+ self.HeaderLength = self.Header.Common_Header_Size()\r
+ self.Size = self.Header.SECTION_SIZE\r
+ self.Type = self.Header.Type\r
+ self.HOffset = 0\r
+ self.DOffset = 0\r
+ self.ROffset = 0\r
+ self.Data = b''\r
+ self.OriData = b''\r
+ self.OriHeader = b''\r
+ self.PadData = b''\r
+ self.IsPadSection = False\r
+ self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align\r
+\r
+ def GetExtHeader(self, Type: int, buffer: bytes, nums: int=0) -> None:\r
+ if Type == 0x01:\r
+ return EFI_COMPRESSION_SECTION.from_buffer_copy(buffer)\r
+ elif Type == 0x02:\r
+ return EFI_GUID_DEFINED_SECTION.from_buffer_copy(buffer)\r
+ elif Type == 0x14:\r
+ return Get_VERSION_Header((nums - 2)//2).from_buffer_copy(buffer)\r
+ elif Type == 0x15:\r
+ return Get_USER_INTERFACE_Header(nums//2).from_buffer_copy(buffer)\r
+ elif Type == 0x18:\r
+ return EFI_FREEFORM_SUBTYPE_GUID_SECTION.from_buffer_copy(buffer)\r
+\r
+class FreeSpaceNode:\r
+ def __init__(self, buffer: bytes) -> None:\r
+ self.Name = 'Free_Space'\r
+ self.Data = buffer\r
+ self.Size = len(buffer)\r
+ self.HOffset = 0\r
+ self.DOffset = 0\r
+ self.ROffset = 0\r
+ self.PadData = b''\r
\ No newline at end of file