mirror of https://github.com/acidanthera/audk.git
180 lines
7.5 KiB
Python
180 lines
7.5 KiB
Python
## @file
|
|
# This file is used to define the FMMT dependent external tool management class.
|
|
#
|
|
# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
|
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
##
|
|
import glob
|
|
import logging
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import uuid
|
|
from FirmwareStorageFormat.Common import *
|
|
from utils.FmmtLogger import FmmtLogger as logger
|
|
import subprocess
|
|
|
|
def ExecuteCommand(cmd: list) -> None:
|
|
subprocess.run(cmd,stdout=subprocess.DEVNULL)
|
|
|
|
class GUIDTool:
|
|
def __init__(self, guid: str, short_name: str, command: str) -> None:
|
|
self.guid: str = guid
|
|
self.short_name: str = short_name
|
|
self.command: str = command
|
|
self.ifexist: bool = False
|
|
|
|
def pack(self, buffer: bytes) -> bytes:
|
|
"""
|
|
compress file.
|
|
"""
|
|
tool = self.command
|
|
if tool:
|
|
tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
|
|
ToolInputFile = os.path.join(tmp, "pack_uncompress_sec_file")
|
|
ToolOuputFile = os.path.join(tmp, "pack_sec_file")
|
|
try:
|
|
file = open(ToolInputFile, "wb")
|
|
file.write(buffer)
|
|
file.close()
|
|
command = [tool, '-e', '-o', ToolOuputFile,
|
|
ToolInputFile]
|
|
ExecuteCommand(command)
|
|
buf = open(ToolOuputFile, "rb")
|
|
res_buffer = buf.read()
|
|
except Exception as msg:
|
|
logger.error(msg)
|
|
return ""
|
|
else:
|
|
buf.close()
|
|
if os.path.exists(tmp):
|
|
shutil.rmtree(tmp)
|
|
return res_buffer
|
|
else:
|
|
logger.error(
|
|
"Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
|
|
logger.info("Its GUID is: %s" % self.guid)
|
|
return ""
|
|
|
|
|
|
def unpack(self, buffer: bytes) -> bytes:
|
|
"""
|
|
buffer: remove common header
|
|
uncompress file
|
|
"""
|
|
tool = self.command
|
|
if tool:
|
|
tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
|
|
ToolInputFile = os.path.join(tmp, "unpack_sec_file")
|
|
ToolOuputFile = os.path.join(tmp, "unpack_uncompress_sec_file")
|
|
try:
|
|
file = open(ToolInputFile, "wb")
|
|
file.write(buffer)
|
|
file.close()
|
|
command = [tool, '-d', '-o', ToolOuputFile, ToolInputFile]
|
|
ExecuteCommand(command)
|
|
buf = open(ToolOuputFile, "rb")
|
|
res_buffer = buf.read()
|
|
except Exception as msg:
|
|
logger.error(msg)
|
|
return ""
|
|
else:
|
|
buf.close()
|
|
if os.path.exists(tmp):
|
|
shutil.rmtree(tmp)
|
|
return res_buffer
|
|
else:
|
|
logger.error("Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
|
|
logger.info("Its GUID is: %s" % self.guid)
|
|
return ""
|
|
|
|
class GUIDTools:
|
|
'''
|
|
GUIDTools is responsible for reading FMMTConfig.ini, verify the tools and provide interfaces to access those tools.
|
|
'''
|
|
default_tools = {
|
|
struct2stream(ModifyGuidFormat("a31280ad-481e-41b6-95e8-127f4c984779")): GUIDTool("a31280ad-481e-41b6-95e8-127f4c984779", "TIANO", "TianoCompress"),
|
|
struct2stream(ModifyGuidFormat("ee4e5898-3914-4259-9d6e-dc7bd79403cf")): GUIDTool("ee4e5898-3914-4259-9d6e-dc7bd79403cf", "LZMA", "LzmaCompress"),
|
|
struct2stream(ModifyGuidFormat("fc1bcdb0-7d31-49aa-936a-a4600d9dd083")): GUIDTool("fc1bcdb0-7d31-49aa-936a-a4600d9dd083", "CRC32", "GenCrc32"),
|
|
struct2stream(ModifyGuidFormat("d42ae6bd-1352-4bfb-909a-ca72a6eae889")): GUIDTool("d42ae6bd-1352-4bfb-909a-ca72a6eae889", "LZMAF86", "LzmaF86Compress"),
|
|
struct2stream(ModifyGuidFormat("3d532050-5cda-4fd0-879e-0f7f630d5afb")): GUIDTool("3d532050-5cda-4fd0-879e-0f7f630d5afb", "BROTLI", "BrotliCompress"),
|
|
}
|
|
|
|
def __init__(self, tooldef_file: str=None) -> None:
|
|
self.dir = os.path.join(os.path.dirname(__file__), "..")
|
|
self.tooldef_file = tooldef_file if tooldef_file else os.path.join(self.dir, "FmmtConf.ini")
|
|
self.tooldef = dict()
|
|
|
|
def SetConfigFile(self) -> None:
|
|
if os.environ['FmmtConfPath']:
|
|
self.tooldef_file = os.path.join(os.environ['FmmtConfPath'], 'FmmtConf.ini')
|
|
else:
|
|
PathList = os.environ['PATH']
|
|
for CurrentPath in PathList:
|
|
if os.path.exists(os.path.join(CurrentPath, 'FmmtConf.ini')):
|
|
self.tooldef_file = os.path.join(CurrentPath, 'FmmtConf.ini')
|
|
break
|
|
|
|
def VerifyTools(self, guidtool) -> None:
|
|
"""
|
|
Verify Tools and Update Tools path.
|
|
"""
|
|
path_env = os.environ.get("PATH")
|
|
path_env_list = path_env.split(os.pathsep)
|
|
path_env_list.append(os.path.dirname(__file__))
|
|
path_env_list = list(set(path_env_list))
|
|
cmd = guidtool.command
|
|
if os.path.isabs(cmd):
|
|
if not os.path.exists(cmd):
|
|
if guidtool not in self.default_tools:
|
|
logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
|
|
logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
|
|
else:
|
|
logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
|
|
else:
|
|
guidtool.ifexist = True
|
|
else:
|
|
for syspath in path_env_list:
|
|
if glob.glob(os.path.join(syspath, cmd+"*")):
|
|
guidtool.ifexist = True
|
|
break
|
|
else:
|
|
if guidtool not in self.default_tools:
|
|
logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
|
|
logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
|
|
else:
|
|
logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
|
|
|
|
def LoadingTools(self) -> None:
|
|
self.SetConfigFile()
|
|
if os.path.exists(self.tooldef_file):
|
|
with open(self.tooldef_file, "r") as fd:
|
|
config_data = fd.readlines()
|
|
for line in config_data:
|
|
try:
|
|
if not line.startswith("#"):
|
|
guid, short_name, command = line.split()
|
|
new_format_guid = struct2stream(ModifyGuidFormat(guid.strip()))
|
|
self.tooldef[new_format_guid] = GUIDTool(
|
|
guid.strip(), short_name.strip(), command.strip())
|
|
except:
|
|
logger.error("GuidTool load error!")
|
|
continue
|
|
else:
|
|
self.tooldef.update(self.default_tools)
|
|
|
|
def __getitem__(self, guid):
|
|
if not self.tooldef:
|
|
self.LoadingTools()
|
|
guid_tool = self.tooldef.get(guid)
|
|
if guid_tool:
|
|
self.VerifyTools(guid_tool)
|
|
return guid_tool
|
|
else:
|
|
logger.error("{} GuidTool is not defined!".format(guid))
|
|
raise Exception("Process Failed: is not defined!")
|
|
|
|
guidtools = GUIDTools()
|
|
|