]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
BaseTools: Add FMMT Python Tool
[mirror_edk2.git] / BaseTools / Source / Python / FMMT / core / BiosTreeNode.py
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
new file mode 100644 (file)
index 0000000..2044776
--- /dev/null
@@ -0,0 +1,194 @@
+## @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