fix: Setup Payload incorrectly handles config data with the refer flag

CfgDataTool de-dupes config data in some circumstances when using the
"merge" command. In such a case, the CDATA_FLAG_TYPE_REFER flag is set
in the header, and a special REFERENCE_CFG_DATA struct is added after the
conditions that points to the reference Config Data. ConfigDataLib's
BuildConfigData() triggers a config data corruption when handling these
that needed to be fixed. Instead, the setup payload will expand these
de-duped configs using the reference data so they can be modified
independently. This will cause an increase in Config Data size when
saving data from setup in these cases.

Signed-off-by: Bejean Mosher <bejean.mosher@intel.com>
This commit is contained in:
Bejean Mosher
2025-02-26 10:17:38 -05:00
committed by bejeanmo
parent c7b49e49fc
commit 49190cf578
2 changed files with 85 additions and 36 deletions

View File

@@ -363,46 +363,49 @@ BuildConfigData (
CdataCurr = ((UINT8 *)CdataHdrCurr + sizeof (CDATA_HEADER) + sizeof (CDATA_COND) * CdataHdrCurr->ConditionNum);
HdrLen = sizeof (CDATA_HEADER) + sizeof (CDATA_COND) * CdataHdr->ConditionNum;
Cdata = (UINT8 *)CdataHdr + HdrLen;
if ((CdataHdr->Flags & CDATA_FLAG_TYPE_ARRAY) != 0) {
// Handle array item specially
ArrayHdr = (ARRAY_CFG_HDR *)Cdata;
ArrayHdrCurr = (ARRAY_CFG_HDR *)CdataCurr;
BitMaskLen = (CdataHdr->Length << 2) - HdrLen - (UINT32)OFFSET_OF(ARRAY_CFG_HDR, BaseTableBitMask) \
- (ArrayHdr->ItemSize * ArrayHdr->ItemCount);
// Don't copy reference data
if ((CdataHdr->Flags & CDATA_FLAG_TYPE_REFER) == 0) {
if ((CdataHdr->Flags & CDATA_FLAG_TYPE_ARRAY) != 0) {
// Handle array item specially
ArrayHdr = (ARRAY_CFG_HDR *)Cdata;
ArrayHdrCurr = (ARRAY_CFG_HDR *)CdataCurr;
BitMaskLen = (CdataHdr->Length << 2) - HdrLen - (UINT32)OFFSET_OF(ARRAY_CFG_HDR, BaseTableBitMask) \
- (ArrayHdr->ItemSize * ArrayHdr->ItemCount);
// Update BaseTableBitMask
CopyMem (ArrayHdr->BaseTableBitMask, ArrayHdrCurr->BaseTableBitMask, BitMaskLen);
ArrayHdr->BaseTableId = 0x80;
// Update BaseTableBitMask
CopyMem (ArrayHdr->BaseTableBitMask, ArrayHdrCurr->BaseTableBitMask, BitMaskLen);
ArrayHdr->BaseTableId = 0x80;
// Update skip bit accordingly in the entry based on BaseTableBitMask
GpioTableDataOffset = (UINT32)OFFSET_OF(ARRAY_CFG_HDR, BaseTableBitMask) + BitMaskLen;
for (Index2 = 0; Index2 < ArrayHdr->ItemCount; Index2++) {
if ((ArrayHdr->BaseTableBitMask[Index2 >> 3] & (1 << (Index2 & 7))) == 0) {
// Skip one entry
Offset2 = Index2 * ArrayHdr->ItemSize;
Ptr = Cdata + GpioTableDataOffset + Offset2;
Index = ArrayHdr->ItemValidBitOff;
Ptr[Index >> 3] |= (1 << (Index & 7));
}
}
// Update extra entries
for (Index = 0; Index < ArrayHdrCurr->ItemCount; Index++) {
Offset1 = Index * ArrayHdrCurr->ItemSize;
ItemId = GetArrayItemId (ArrayHdrCurr, CdataCurr + GpioTableDataOffset + Offset1);
// Update skip bit accordingly in the entry based on BaseTableBitMask
GpioTableDataOffset = (UINT32)OFFSET_OF(ARRAY_CFG_HDR, BaseTableBitMask) + BitMaskLen;
for (Index2 = 0; Index2 < ArrayHdr->ItemCount; Index2++) {
Offset2 = Index2 * ArrayHdr->ItemSize;
if (GetArrayItemId (ArrayHdr, Cdata + GpioTableDataOffset + Offset2) == ItemId) {
// Set item as valid in BaseTableBitMask
ArrayHdr->BaseTableBitMask[Index >> 3] |= (1 << (Index & 7));
CopyMem (Cdata + GpioTableDataOffset + Offset2, CdataCurr + GpioTableDataOffset + Offset1, ArrayHdr->ItemSize);
break;
if ((ArrayHdr->BaseTableBitMask[Index2 >> 3] & (1 << (Index2 & 7))) == 0) {
// Skip one entry
Offset2 = Index2 * ArrayHdr->ItemSize;
Ptr = Cdata + GpioTableDataOffset + Offset2;
Index = ArrayHdr->ItemValidBitOff;
Ptr[Index >> 3] |= (1 << (Index & 7));
}
}
// Update extra entries
for (Index = 0; Index < ArrayHdrCurr->ItemCount; Index++) {
Offset1 = Index * ArrayHdrCurr->ItemSize;
ItemId = GetArrayItemId (ArrayHdrCurr, CdataCurr + GpioTableDataOffset + Offset1);
for (Index2 = 0; Index2 < ArrayHdr->ItemCount; Index2++) {
Offset2 = Index2 * ArrayHdr->ItemSize;
if (GetArrayItemId (ArrayHdr, Cdata + GpioTableDataOffset + Offset2) == ItemId) {
// Set item as valid in BaseTableBitMask
ArrayHdr->BaseTableBitMask[Index >> 3] |= (1 << (Index & 7));
CopyMem (Cdata + GpioTableDataOffset + Offset2, CdataCurr + GpioTableDataOffset + Offset1, ArrayHdr->ItemSize);
break;
}
}
}
} else {
// Copy full CFGDATA tag data
CopyMem (Cdata, CdataCurr, (CdataHdr->Length << 2) - HdrLen);
}
} else {
// Copy full CFGDATA tag data
CopyMem (Cdata, CdataCurr, (CdataHdr->Length << 2) - HdrLen);
}
} else {
// Set platform mask

View File

@@ -25,6 +25,11 @@ except:
import win32pipe, win32file, win32con
is_micro_py = False
CDATA_FLAG_TYPE_MASK = (3 << 0)
CDATA_FLAG_TYPE_NORMAL = (0 << 0)
CDATA_FLAG_TYPE_ARRAY = (1 << 0)
CDATA_FLAG_TYPE_REFER = (2 << 0)
class TERM:
# bit0: GFX bit1: TXT
SCREEN_MODE = 3
@@ -1871,9 +1876,20 @@ def bytes_to_cfghdr(data, offset):
for i in range(cfghdr['ConditionNum']):
condition_bytes = data[offset + 4 + (4*i):offset + 4 + (4*i) + 4]
cfghdr['Condition'].append(int.from_bytes(condition_bytes, 'little'))
if (cfghdr['Flags'] & CDATA_FLAG_TYPE_MASK) == CDATA_FLAG_TYPE_REFER:
cfghdr['Refer_Tag'] = int.from_bytes(data[offset + 4 + (4*cfghdr['ConditionNum'])+2:offset + 4 + (4*cfghdr['ConditionNum']) + 4], 'little') & 0xFFF
return cfghdr
def cfghdr_to_bytes(Length, ConditionNum, Flags, Version, Tag):
# Update Length and flags from referral cfg
Header = bytearray(4)
Header[0] = ConditionNum | (Length & 0xFC)
Header[1] = (Flags << 4) | (Length >> 8)
Header[2] = Version | ((Tag & 0xF) << 4)
Header[3] = (Tag >> 4) & 0xFF
return Header
def load_data_tree(cfg_tree, data):
cdata = []
# validate CFGD header
@@ -1906,13 +1922,39 @@ def update_values (cfg_tree, data, data_tree):
if curr_offset_delta != 0xFFFFFFFF:
cfg['offset_delta'] = curr_offset_delta
def _write_values_to_cfg():
for cfg in cfgs:
def _write_values_to_cfg(top = None):
def __write_values_to_cfg(cfg):
offset = cfg['offset']
if 'offset_delta' in cfg:
offset += cfg['offset_delta']
value = get_bits_from_bytes (data, offset, cfg['length'])
cfg['value'] = format_value_to_str (value, cfg['length'], cfg['value'])
if top is None:
top = cfgs
if isinstance(top, list):
for cfg in top:
__write_values_to_cfg(cfg)
else:
__write_values_to_cfg(top)
def _fixup_refer_cfg():
for cfg in cfgs:
if cfg['cname'] == 'CfgHeader':
for cfg_hdr in data_tree:
if cfg_hdr['Tag'] == cfg['tag']:
if 'Refer_Tag' in cfg_hdr:
for refer_cfg_hdr in data_tree:
if refer_cfg_hdr['Tag'] == cfg_hdr['Refer_Tag']:
# Update Length and flags from referral cfg
HdrBytes = cfghdr_to_bytes(refer_cfg_hdr['Length'], cfg_hdr['ConditionNum'], refer_cfg_hdr['Flags'], cfg_hdr['Version'], cfg_hdr['Tag'])
cfg['value'] = format_value_to_str(int.from_bytes(HdrBytes, 'little'), 32, '{')
for child_cfg in cfgs:
if child_cfg['path'].startswith(cfg['path'].split('.')[0]):
if child_cfg['cname'] not in ['CfgHeader', 'CondValue']:
child_cfg['offset_delta'] = refer_cfg_hdr['Offset'] - cfg['offset']
_write_values_to_cfg(child_cfg)
break
break
cfgs = cfg_tree['_cfg_list']
@@ -1920,6 +1962,10 @@ def update_values (cfg_tree, data, data_tree):
_write_values_to_cfg()
# Cfg headers with the "refer" flag set just copy data from another cfg header tag.
# These need to be expanded in setup so they can be modified independently.
_fixup_refer_cfg()
for cfg in cfgs:
if 'order' not in cfg:
cfg['order'] = cfg['offset']