You've already forked slimbootloader
mirror of
https://github.com/Dasharo/slimbootloader.git
synced 2026-03-06 15:26:20 -08:00
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:
@@ -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
|
||||
|
||||
@@ -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']
|
||||
|
||||
Reference in New Issue
Block a user