Skip to content

Commit 1173013

Browse files
committed
IntelFsp2Pkg/Tools/ConfigEditor: Fixed data difference issue
Problem Description: load_default_from_bin caused data difference errors when loading fsp.bsf and fsp.fd, due to multiple identical UPD signatures. The original string search picked the first match, which could be the wrong region. Solution Description: Updated GenYamlCfg.py to locate UPD data by FFS GUID FSP_T, FSP_M, FSP_S_UPD_FFS_GUID before searching UPD signatures. This ensures correct region matching and retains the old string search as a fallback. Signed-off-by: Hsu JasonX <[email protected]>
1 parent 1c74842 commit 1173013

File tree

1 file changed

+100
-11
lines changed

1 file changed

+100
-11
lines changed

IntelFsp2Pkg/Tools/ConfigEditor/GenYamlCfg.py

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,42 @@
1818
from CommonUtility import value_to_bytearray, value_to_bytes, \
1919
bytes_to_value, get_bits_from_bytes, set_bits_to_bytes
2020

21+
# FFS file structure constants
22+
FFS_GUID_SIZE = 16
23+
FFS_HEADER_SIZE = 24
24+
FFS_SEARCH_RANGE = 4096 # Search within 4KB after GUID
25+
26+
# FSP UPD FFS GUID definitions
27+
FSP_T_UPD_FFS_GUID = '70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA'
28+
FSP_M_UPD_FFS_GUID = 'D5B86AEA-6AF7-40D4-8014-982301BC3D89'
29+
FSP_S_UPD_FFS_GUID = 'E3CD9B18-998C-4F76-B65E-98B154E5446F'
30+
31+
def guid_str_to_bytes(guid_str):
32+
"""Convert GUID string to bytes in EFI GUID format (mixed endian)"""
33+
# Remove dashes and convert to bytes
34+
guid_str = guid_str.replace('-', '')
35+
36+
# EFI GUID format: first 3 fields are little-endian, last 2 are big-endian
37+
# Parse: DWORD-WORD-WORD-BYTE[2]-BYTE[6]
38+
data1 = bytes.fromhex(guid_str[0:8])[::-1] # DWORD (4 bytes) - little endian
39+
data2 = bytes.fromhex(guid_str[8:12])[::-1] # WORD (2 bytes) - little endian
40+
data3 = bytes.fromhex(guid_str[12:16])[::-1] # WORD (2 bytes) - little endian
41+
data4 = bytes.fromhex(guid_str[16:20]) # BYTE[2] (2 bytes) - big endian
42+
data5 = bytes.fromhex(guid_str[20:32]) # BYTE[6] (6 bytes) - big endian
43+
44+
return data1 + data2 + data3 + data4 + data5
45+
46+
# UPD signature to GUID mapping
47+
def get_upd_guid(upd_signature):
48+
"""Get FFS GUID for a given UPD signature based on suffix"""
49+
if upd_signature.endswith('UPD_T'):
50+
return FSP_T_UPD_FFS_GUID
51+
elif upd_signature.endswith('UPD_M'):
52+
return FSP_M_UPD_FFS_GUID
53+
elif upd_signature.endswith('UPD_S'):
54+
return FSP_S_UPD_FFS_GUID
55+
return None
56+
2157
# Generated file copyright header
2258
__copyright_tmp__ = """/** @file
2359
@@ -1639,6 +1675,46 @@ def _get_cfg_segment(name, cfgs, level):
16391675

16401676
return cfg_segs
16411677

1678+
def find_upd_in_ffs_by_guid(self, bin_data, upd_signature, ffs_guid):
1679+
"""
1680+
Find UPD signature within a specific FFS file identified by GUID.
1681+
1682+
Args:
1683+
bin_data: Binary data to search in
1684+
upd_signature: UPD signature string (e.g., 'XXXUPD_M')
1685+
ffs_guid: GUID string of the FFS file to search in
1686+
1687+
Returns:
1688+
Position of UPD signature if found, -1 otherwise
1689+
"""
1690+
if not ffs_guid:
1691+
return -1
1692+
1693+
# Convert GUID string to bytes for searching
1694+
guid_bytes = guid_str_to_bytes(ffs_guid)
1695+
sig_bytes = upd_signature.encode()
1696+
1697+
# Search for all occurrences of the GUID
1698+
search_pos = 0
1699+
while True:
1700+
guid_pos = bin_data.find(guid_bytes, search_pos)
1701+
if guid_pos < 0:
1702+
break
1703+
1704+
# Search for UPD signature within FFS_SEARCH_RANGE after GUID
1705+
search_start = guid_pos
1706+
search_end = min(guid_pos + FFS_SEARCH_RANGE, len(bin_data))
1707+
1708+
sig_pos = bin_data.find(sig_bytes, search_start, search_end)
1709+
if sig_pos >= 0:
1710+
print(f"Found {upd_signature} at offset 0x{sig_pos:X} within FFS GUID {ffs_guid}")
1711+
return sig_pos
1712+
1713+
# Continue searching for next occurrence of this GUID
1714+
search_pos = guid_pos + FFS_GUID_SIZE
1715+
1716+
return -1
1717+
16421718
def import_tkinter(self):
16431719
try:
16441720
import tkinter
@@ -1656,16 +1732,28 @@ def get_bin_segment(self, bin_data):
16561732
if key == 0:
16571733
bin_segs.append([seg[0], 0, len(bin_data)])
16581734
break
1659-
pos = bin_data.find(key)
1660-
if pos >= 0:
1661-
# ensure no other match for the key
1662-
next_pos = bin_data.find(key, pos + len(seg[0]))
1663-
if next_pos >= 0:
1664-
if key == b'$SKLFSP$' or key == b'$BSWFSP$':
1665-
string = ('Multiple matches for %s in '
1666-
'binary!\n\nA workaround applied to such '
1667-
'FSP 1.x binary to use second'
1668-
' match instead of first match!' % key)
1735+
1736+
pos = -1
1737+
1738+
# Check if this UPD signature has a corresponding FFS GUID
1739+
ffs_guid = get_upd_guid(seg[0])
1740+
if ffs_guid:
1741+
pos = self.find_upd_in_ffs_by_guid(bin_data, seg[0], ffs_guid)
1742+
if pos >= 0:
1743+
print(f"Using GUID-based search: found {seg[0]} at 0x{pos:X}")
1744+
1745+
# Fallback to original search if GUID-based search fails
1746+
if pos < 0:
1747+
pos = bin_data.find(key)
1748+
if pos >= 0:
1749+
# Check for multiple matches
1750+
next_pos = bin_data.find(key, pos + len(seg[0]))
1751+
if next_pos >= 0:
1752+
if key == b'$SKLFSP$' or key == b'$BSWFSP$':
1753+
string = ('Warning: Multiple matches for %s in '
1754+
'binary!\n\nA workaround applied to such '
1755+
'FSP 1.x binary to use second'
1756+
' match instead of first match!' % key)
16691757
if self._tk:
16701758
self._tk.messagebox.showwarning('Warning: ', string)
16711759
else:
@@ -1675,12 +1763,13 @@ def get_bin_segment(self, bin_data):
16751763
print("Warning: Multiple matches for '%s' "
16761764
"in binary, the 1st instance will be used !"
16771765
% seg[0])
1766+
1767+
if pos >= 0:
16781768
bin_segs.append([seg[0], pos, seg[2]])
16791769
self.binseg_dict[seg[0]] = pos
16801770
else:
16811771
bin_segs.append([seg[0], -1, seg[2]])
16821772
self.binseg_dict[seg[0]] = -1
1683-
continue
16841773

16851774
return bin_segs
16861775

0 commit comments

Comments
 (0)