]>
Commit | Line | Data |
---|---|---|
a64b9449 CC |
1 | ## @file\r |
2 | # This file is used to define the FMMT dependent external tool management class.\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 | import glob\r | |
8 | import logging\r | |
9 | import os\r | |
10 | import shutil\r | |
11 | import sys\r | |
12 | import tempfile\r | |
13 | import uuid\r | |
14 | from FirmwareStorageFormat.Common import *\r | |
15 | from utils.FmmtLogger import FmmtLogger as logger\r | |
16 | import subprocess\r | |
17 | \r | |
18 | def ExecuteCommand(cmd: list) -> None:\r | |
19 | subprocess.run(cmd,stdout=subprocess.DEVNULL)\r | |
20 | \r | |
21 | class GUIDTool:\r | |
22 | def __init__(self, guid: str, short_name: str, command: str) -> None:\r | |
23 | self.guid: str = guid\r | |
24 | self.short_name: str = short_name\r | |
25 | self.command: str = command\r | |
26 | self.ifexist: bool = False\r | |
27 | \r | |
28 | def pack(self, buffer: bytes) -> bytes:\r | |
29 | """\r | |
30 | compress file.\r | |
31 | """\r | |
32 | tool = self.command\r | |
33 | if tool:\r | |
34 | tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))\r | |
35 | ToolInputFile = os.path.join(tmp, "pack_uncompress_sec_file")\r | |
36 | ToolOuputFile = os.path.join(tmp, "pack_sec_file")\r | |
37 | try:\r | |
38 | file = open(ToolInputFile, "wb")\r | |
39 | file.write(buffer)\r | |
40 | file.close()\r | |
41 | command = [tool, '-e', '-o', ToolOuputFile,\r | |
42 | ToolInputFile]\r | |
43 | ExecuteCommand(command)\r | |
44 | buf = open(ToolOuputFile, "rb")\r | |
45 | res_buffer = buf.read()\r | |
46 | except Exception as msg:\r | |
47 | logger.error(msg)\r | |
48 | return ""\r | |
49 | else:\r | |
50 | buf.close()\r | |
51 | if os.path.exists(tmp):\r | |
52 | shutil.rmtree(tmp)\r | |
53 | return res_buffer\r | |
54 | else:\r | |
55 | logger.error(\r | |
56 | "Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")\r | |
57 | logger.info("Its GUID is: %s" % self.guid)\r | |
58 | return ""\r | |
59 | \r | |
60 | \r | |
61 | def unpack(self, buffer: bytes) -> bytes:\r | |
62 | """\r | |
63 | buffer: remove common header\r | |
64 | uncompress file\r | |
65 | """\r | |
66 | tool = self.command\r | |
67 | if tool:\r | |
68 | tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))\r | |
69 | ToolInputFile = os.path.join(tmp, "unpack_sec_file")\r | |
70 | ToolOuputFile = os.path.join(tmp, "unpack_uncompress_sec_file")\r | |
71 | try:\r | |
72 | file = open(ToolInputFile, "wb")\r | |
73 | file.write(buffer)\r | |
74 | file.close()\r | |
75 | command = [tool, '-d', '-o', ToolOuputFile, ToolInputFile]\r | |
76 | ExecuteCommand(command)\r | |
77 | buf = open(ToolOuputFile, "rb")\r | |
78 | res_buffer = buf.read()\r | |
79 | except Exception as msg:\r | |
80 | logger.error(msg)\r | |
81 | return ""\r | |
82 | else:\r | |
83 | buf.close()\r | |
84 | if os.path.exists(tmp):\r | |
85 | shutil.rmtree(tmp)\r | |
86 | return res_buffer\r | |
87 | else:\r | |
88 | logger.error("Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")\r | |
89 | logger.info("Its GUID is: %s" % self.guid)\r | |
90 | return ""\r | |
91 | \r | |
92 | class GUIDTools:\r | |
93 | '''\r | |
94 | GUIDTools is responsible for reading FMMTConfig.ini, verify the tools and provide interfaces to access those tools.\r | |
95 | '''\r | |
96 | default_tools = {\r | |
97 | struct2stream(ModifyGuidFormat("a31280ad-481e-41b6-95e8-127f4c984779")): GUIDTool("a31280ad-481e-41b6-95e8-127f4c984779", "TIANO", "TianoCompress"),\r | |
98 | struct2stream(ModifyGuidFormat("ee4e5898-3914-4259-9d6e-dc7bd79403cf")): GUIDTool("ee4e5898-3914-4259-9d6e-dc7bd79403cf", "LZMA", "LzmaCompress"),\r | |
99 | struct2stream(ModifyGuidFormat("fc1bcdb0-7d31-49aa-936a-a4600d9dd083")): GUIDTool("fc1bcdb0-7d31-49aa-936a-a4600d9dd083", "CRC32", "GenCrc32"),\r | |
100 | struct2stream(ModifyGuidFormat("d42ae6bd-1352-4bfb-909a-ca72a6eae889")): GUIDTool("d42ae6bd-1352-4bfb-909a-ca72a6eae889", "LZMAF86", "LzmaF86Compress"),\r | |
101 | struct2stream(ModifyGuidFormat("3d532050-5cda-4fd0-879e-0f7f630d5afb")): GUIDTool("3d532050-5cda-4fd0-879e-0f7f630d5afb", "BROTLI", "BrotliCompress"),\r | |
102 | }\r | |
103 | \r | |
104 | def __init__(self, tooldef_file: str=None) -> None:\r | |
105 | self.dir = os.path.join(os.path.dirname(__file__), "..")\r | |
106 | self.tooldef_file = tooldef_file if tooldef_file else os.path.join(self.dir, "FmmtConf.ini")\r | |
107 | self.tooldef = dict()\r | |
108 | \r | |
109 | def SetConfigFile(self) -> None:\r | |
110 | if os.environ['FmmtConfPath']:\r | |
111 | self.tooldef_file = os.path.join(os.environ['FmmtConfPath'], 'FmmtConf.ini')\r | |
112 | else:\r | |
113 | PathList = os.environ['PATH']\r | |
114 | for CurrentPath in PathList:\r | |
115 | if os.path.exists(os.path.join(CurrentPath, 'FmmtConf.ini')):\r | |
116 | self.tooldef_file = os.path.join(CurrentPath, 'FmmtConf.ini')\r | |
117 | break\r | |
118 | \r | |
119 | def VerifyTools(self, guidtool) -> None:\r | |
120 | """\r | |
121 | Verify Tools and Update Tools path.\r | |
122 | """\r | |
123 | path_env = os.environ.get("PATH")\r | |
124 | path_env_list = path_env.split(os.pathsep)\r | |
125 | path_env_list.append(os.path.dirname(__file__))\r | |
126 | path_env_list = list(set(path_env_list))\r | |
127 | cmd = guidtool.command\r | |
128 | if os.path.isabs(cmd):\r | |
129 | if not os.path.exists(cmd):\r | |
130 | if guidtool not in self.default_tools:\r | |
131 | logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)\r | |
132 | logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")\r | |
133 | else:\r | |
134 | logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)\r | |
135 | else:\r | |
136 | guidtool.ifexist = True\r | |
137 | else:\r | |
138 | for syspath in path_env_list:\r | |
139 | if glob.glob(os.path.join(syspath, cmd+"*")):\r | |
140 | guidtool.ifexist = True\r | |
141 | break\r | |
142 | else:\r | |
143 | if guidtool not in self.default_tools:\r | |
144 | logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)\r | |
145 | logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")\r | |
146 | else:\r | |
147 | logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)\r | |
148 | \r | |
149 | def LoadingTools(self) -> None:\r | |
150 | self.SetConfigFile()\r | |
151 | if os.path.exists(self.tooldef_file):\r | |
152 | with open(self.tooldef_file, "r") as fd:\r | |
153 | config_data = fd.readlines()\r | |
154 | for line in config_data:\r | |
155 | try:\r | |
156 | if not line.startswith("#"):\r | |
157 | guid, short_name, command = line.split()\r | |
158 | new_format_guid = struct2stream(ModifyGuidFormat(guid.strip()))\r | |
159 | self.tooldef[new_format_guid] = GUIDTool(\r | |
160 | guid.strip(), short_name.strip(), command.strip())\r | |
161 | except:\r | |
162 | logger.error("GuidTool load error!")\r | |
163 | continue\r | |
164 | else:\r | |
165 | self.tooldef.update(self.default_tools)\r | |
166 | \r | |
167 | def __getitem__(self, guid):\r | |
168 | if not self.tooldef:\r | |
169 | self.LoadingTools()\r | |
170 | guid_tool = self.tooldef.get(guid)\r | |
171 | if guid_tool:\r | |
172 | self.VerifyTools(guid_tool)\r | |
173 | return guid_tool\r | |
174 | else:\r | |
175 | logger.error("{} GuidTool is not defined!".format(guid))\r | |
176 | raise Exception("Process Failed: is not defined!")\r | |
177 | \r | |
178 | guidtools = GUIDTools()\r | |
179 | \r |