summaryrefslogtreecommitdiffstats
path: root/BaseTools/Source/Python/FMMT/core/FMMTOperation.py
blob: d4aa3397036d44435e1133ae14d070defb0877dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
## @file
# This file is used to define the functions to operate bios binary file.
#
# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
from core.FMMTParser import *
from core.FvHandler import *
from utils.FvLayoutPrint import *
from utils.FmmtLogger import FmmtLogger as logger

global Fv_count
Fv_count = 0

# The ROOT_TYPE can be 'ROOT_TREE', 'ROOT_FV_TREE', 'ROOT_FFS_TREE', 'ROOT_SECTION_TREE'
def ViewFile(inputfile: str, ROOT_TYPE: str, layoutfile: str=None, outputfile: str=None) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TYPE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    # 3. Log Output
    InfoDict = FmmtParser.WholeFvTree.ExportTree()
    logger.debug('BinaryTree created, start parsing BinaryTree data......')
    FmmtParser.WholeFvTree.parserTree(InfoDict, FmmtParser.BinaryInfo)
    logger.debug('Done!')
    GetFormatter("").LogPrint(FmmtParser.BinaryInfo)
    if layoutfile:
        if os.path.splitext(layoutfile)[1]:
            layoutfilename = layoutfile
            layoutfileformat = os.path.splitext(layoutfile)[1][1:].lower()
        else:
            layoutfilename = "Layout_{}{}".format(os.path.basename(inputfile),".{}".format(layoutfile.lower()))
            layoutfileformat = layoutfile.lower()
        GetFormatter(layoutfileformat).dump(InfoDict, FmmtParser.BinaryInfo, layoutfilename)
    # 4. Data Encapsulation
    if outputfile:
        logger.debug('Start encapsulating data......')
        FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
        with open(outputfile, "wb") as f:
            f.write(FmmtParser.FinalData)
        logger.debug('Encapsulated data is saved in {}.'.format(outputfile))

def DeleteFfs(inputfile: str, TargetFfs_name: str, outputfile: str, Fv_name: str=None) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TREE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    # 3. Data Modify
    FmmtParser.WholeFvTree.FindNode(TargetFfs_name, FmmtParser.WholeFvTree.Findlist)
    # Choose the Specfic DeleteFfs with Fv info
    if Fv_name:
        FindNum = len(FmmtParser.WholeFvTree.Findlist)
        for index in range(FindNum-1, -1, -1):
            if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
    Status = False
    if FmmtParser.WholeFvTree.Findlist != []:
        for Delete_Ffs in FmmtParser.WholeFvTree.Findlist:
            FfsMod = FvHandler(None, Delete_Ffs)
            Status = FfsMod.DeleteFfs()
    else:
        logger.error('Target Ffs not found!!!')
    # 4. Data Encapsulation
    if Status:
        logger.debug('Start encapsulating data......')
        FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
        with open(outputfile, "wb") as f:
            f.write(FmmtParser.FinalData)
        logger.debug('Encapsulated data is saved in {}.'.format(outputfile))

def AddNewFfs(inputfile: str, Fv_name: str, newffsfile: str, outputfile: str) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    if not os.path.exists(newffsfile):
        logger.error("Invalid ffsfile, can not open {}.".format(newffsfile))
        raise Exception("Process Failed: Invalid ffs file!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TREE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    # Get Target Fv and Target Ffs_Pad
    FmmtParser.WholeFvTree.FindNode(Fv_name, FmmtParser.WholeFvTree.Findlist)
    # Create new ffs Tree
    with open(newffsfile, "rb") as f:
        new_ffs_data = f.read()
    NewFmmtParser = FMMTParser(newffsfile, ROOT_FFS_TREE)
    Status = False
    # 3. Data Modify
    if FmmtParser.WholeFvTree.Findlist:
        for TargetFv in FmmtParser.WholeFvTree.Findlist:
            TargetFfsPad = TargetFv.Child[-1]
            logger.debug('Parsing newffsfile data......')
            if TargetFfsPad.type == FFS_FREE_SPACE:
                NewFmmtParser.ParserFromRoot(NewFmmtParser.WholeFvTree, new_ffs_data, TargetFfsPad.Data.HOffset)
            else:
                NewFmmtParser.ParserFromRoot(NewFmmtParser.WholeFvTree, new_ffs_data, TargetFfsPad.Data.HOffset+TargetFfsPad.Data.Size)
            logger.debug('Done!')
            FfsMod = FvHandler(NewFmmtParser.WholeFvTree.Child[0], TargetFfsPad)
            Status = FfsMod.AddFfs()
    else:
        logger.error('Target Fv not found!!!')
    # 4. Data Encapsulation
    if Status:
        logger.debug('Start encapsulating data......')
        FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
        with open(outputfile, "wb") as f:
            f.write(FmmtParser.FinalData)
        logger.debug('Encapsulated data is saved in {}.'.format(outputfile))

def ReplaceFfs(inputfile: str, Ffs_name: str, newffsfile: str, outputfile: str, Fv_name: str=None) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TREE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    with open(newffsfile, "rb") as f:
        new_ffs_data = f.read()
    newFmmtParser = FMMTParser(newffsfile, FV_TREE)
    logger.debug('Parsing newffsfile data......')
    newFmmtParser.ParserFromRoot(newFmmtParser.WholeFvTree, new_ffs_data)
    logger.debug('Done!')
    Status = False
    # 3. Data Modify
    new_ffs = newFmmtParser.WholeFvTree.Child[0]
    new_ffs.Data.PadData = GetPadSize(new_ffs.Data.Size, FFS_COMMON_ALIGNMENT) * b'\xff'
    FmmtParser.WholeFvTree.FindNode(Ffs_name, FmmtParser.WholeFvTree.Findlist)
    if Fv_name:
        FindNum = len(FmmtParser.WholeFvTree.Findlist)
        for index in range(FindNum-1, -1, -1):
            if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
    if FmmtParser.WholeFvTree.Findlist != []:
        for TargetFfs in FmmtParser.WholeFvTree.Findlist:
            FfsMod = FvHandler(newFmmtParser.WholeFvTree.Child[0], TargetFfs)
            Status = FfsMod.ReplaceFfs()
    else:
        logger.error('Target Ffs not found!!!')
    # 4. Data Encapsulation
    if Status:
        logger.debug('Start encapsulating data......')
        FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
        with open(outputfile, "wb") as f:
            f.write(FmmtParser.FinalData)
        logger.debug('Encapsulated data is saved in {}.'.format(outputfile))

def ExtractFfs(inputfile: str, Ffs_name: str, outputfile: str, Fv_name: str=None) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TREE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    FmmtParser.WholeFvTree.FindNode(Ffs_name, FmmtParser.WholeFvTree.Findlist)
    if Fv_name:
        FindNum = len(FmmtParser.WholeFvTree.Findlist)
        for index in range(FindNum-1, -1, -1):
            if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
    if FmmtParser.WholeFvTree.Findlist != []:
        TargetNode = FmmtParser.WholeFvTree.Findlist[0]
        if TargetNode.type == FV_TREE or TargetNode.type == SEC_FV_TREE or TargetNode.type == DATA_FV_TREE:
            FinalData = struct2stream(TargetNode.Data.Header) + TargetNode.Data.Data
            with open(outputfile, "wb") as f:
                f.write(FinalData)
            logger.debug('Extract fv data is saved in {}.'.format(outputfile))
        else:
            TargetFv = TargetNode.Parent
            if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
                TargetNode.Data.Header.State = c_uint8(
                    ~TargetNode.Data.Header.State)
            FinalData = struct2stream(TargetNode.Data.Header) + TargetNode.Data.Data
            with open(outputfile, "wb") as f:
                f.write(FinalData)
            logger.debug('Extract ffs data is saved in {}.'.format(outputfile))
    else:
        logger.error('Target Ffs/Fv not found!!!')

def ShrinkFv(inputfile: str, outputfile: str) -> None:
    if not os.path.exists(inputfile):
        logger.error("Invalid inputfile, can not open {}.".format(inputfile))
        raise Exception("Process Failed: Invalid inputfile!")
    # 1. Data Prepare
    with open(inputfile, "rb") as f:
        whole_data = f.read()
    FmmtParser = FMMTParser(inputfile, ROOT_TREE)
    # 2. DataTree Create
    logger.debug('Parsing inputfile data......')
    FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
    logger.debug('Done!')
    TargetFv = FmmtParser.WholeFvTree.Child[0]
    if TargetFv:
        FvMod = FvHandler(TargetFv)
        Status = FvMod.ShrinkFv()
    else:
        logger.error('Target Fv not found!!!')
    # 4. Data Encapsulation
    if Status:
        logger.debug('Start encapsulating data......')
        FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
        with open(outputfile, "wb") as f:
            f.write(FmmtParser.FinalData)
        logger.debug('Encapsulated data is saved in {}.'.format(outputfile))