Skip to content

Commit

Permalink
UefiPayloadPkg/CfrSetupMenuDxe: Implement option dependencies
Browse files Browse the repository at this point in the history
Signed-off-by: Filip Brozovic <[email protected]>
  • Loading branch information
fbrozovic committed Jan 14, 2025
1 parent e83842f commit a42154f
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 1 deletion.
192 changes: 192 additions & 0 deletions UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuCfr.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ CfrConvertVarBinaryToStrings (
}
}

/**
CFR_VARBINARY records are used to store a list of dependency values.
Get a pointer to an array of enum values and its length.
**/
STATIC
VOID
EFIAPI
CfrConvertVarBinaryToUint32Array (
IN CFR_VARBINARY *CfrList,
IN OUT UINT32 **Array,
OUT UINT32 *ArrayLength
)
{
ASSERT ((CfrList != NULL) && (Array != NULL) && (ArrayLength != NULL));

*Array = (UINT32 *)CfrList->data;
*ArrayLength = CfrList->data_length / sizeof (UINT32);
}

/**
Produce unconditional HII `*_IF` for CFR flags.
Expand Down Expand Up @@ -107,6 +126,101 @@ CfrProduceHiiForFlags (
ASSERT (TempHiiBuffer != NULL);
}

/**
Produce conditional HII `SUPPRESS_IF` based on a dependency:
Caller to close each `SUPPRESS_IF` with `HiiCreateEndOpCode()`.
**/
STATIC
VOID
EFIAPI
CfrProduceHiiForDependency (
IN VOID *StartOpCodeHandle,
IN UINTN DependencyId,
IN UINT32 *DepValues,
IN UINT32 NumDepValues
)
{
EFI_IFR_OP_HEADER OpHeader;
UINT8 *TempHiiBuffer;
UINTN EqIdValListSize;
EFI_IFR_EQ_ID_VAL_LIST *EqIdValList;
EFI_IFR_EQ_ID_VAL EqIdVal;
UINTN Index;

OpHeader.OpCode = EFI_IFR_SUPPRESS_IF_OP;
OpHeader.Length = sizeof (EFI_IFR_OP_HEADER);
OpHeader.Scope = 1;

TempHiiBuffer = HiiCreateRawOpCodes (
StartOpCodeHandle,
(UINT8 *)&OpHeader,
sizeof (EFI_IFR_OP_HEADER)
);
ASSERT (TempHiiBuffer != NULL);

if (NumDepValues != 0) {
EqIdValListSize = sizeof (EFI_IFR_EQ_ID_VAL_LIST) + ((NumDepValues - 1) * sizeof (UINT16));
EqIdValList = AllocatePool (EqIdValListSize);
ASSERT (EqIdValList != NULL);

EqIdValList->Header.OpCode = EFI_IFR_EQ_ID_VAL_LIST_OP;
EqIdValList->Header.Length = EqIdValListSize;
EqIdValList->Header.Scope = 1;

EqIdValList->QuestionId = DependencyId;
EqIdValList->ListLength = NumDepValues;
for (Index = 0; Index < NumDepValues; Index++) {
EqIdValList->ValueList[Index] = (UINT16)*DepValues++;
}

TempHiiBuffer = HiiCreateRawOpCodes (
StartOpCodeHandle,
(UINT8 *)EqIdValList,
EqIdValListSize
);
ASSERT (TempHiiBuffer != NULL);

FreePool (EqIdValList);

OpHeader.OpCode = EFI_IFR_NOT_OP;
OpHeader.Length = sizeof (EFI_IFR_OP_HEADER);
OpHeader.Scope = 0;

TempHiiBuffer = HiiCreateRawOpCodes (
StartOpCodeHandle,
(UINT8 *)&OpHeader,
sizeof (EFI_IFR_OP_HEADER)
);
ASSERT (TempHiiBuffer != NULL);
} else {
EqIdVal.Header.OpCode = EFI_IFR_EQ_ID_VAL_OP;
EqIdVal.Header.Length = sizeof (EFI_IFR_EQ_ID_VAL);
EqIdVal.Header.Scope = 1;
EqIdVal.QuestionId = DependencyId;
EqIdVal.Value = 0;

TempHiiBuffer = HiiCreateRawOpCodes (
StartOpCodeHandle,
(UINT8 *)&EqIdVal,
sizeof (EFI_IFR_EQ_ID_VAL)
);
ASSERT (TempHiiBuffer != NULL);
}

OpHeader.OpCode = EFI_IFR_END_OP;
OpHeader.Length = sizeof (EFI_IFR_OP_HEADER);
OpHeader.Scope = 0;

TempHiiBuffer = HiiCreateRawOpCodes (
StartOpCodeHandle,
(UINT8 *)&OpHeader,
sizeof (EFI_IFR_OP_HEADER)
);
ASSERT (TempHiiBuffer != NULL);
}

/**
Produce variable and VARSTORE for CFR option name.
Expand Down Expand Up @@ -240,6 +354,9 @@ CfrProcessFormOption (
)
{
CFR_VARBINARY *CfrFormName;
UINT32 *DepValues;
UINT32 NumDepValues;
CFR_VARBINARY *CfrDepValues;
CHAR16 *HiiFormNameString;
EFI_STRING_ID HiiFormNameStringId;
UINT8 *TempHiiBuffer;
Expand All @@ -251,6 +368,15 @@ CfrProcessFormOption (
CfrFormName = CfrExtractVarBinary ((UINT8 *)Option, ProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME);
ASSERT (CfrFormName != NULL);

// Dependency values are optional
DepValues = NULL;
NumDepValues = 0;
CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, ProcessedLength, CB_TAG_CFR_DEP_VALUES);
if (CfrDepValues != NULL) {
ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES);
CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues);
}

DEBUG ((
DEBUG_INFO,
"CFR: Processing form \"%a\", size 0x%x\n",
Expand All @@ -261,6 +387,15 @@ CfrProcessFormOption (
CfrConvertVarBinaryToStrings (CfrFormName, &HiiFormNameString, &HiiFormNameStringId);
FreePool (HiiFormNameString);

if (Option->dependency_id) {
CfrProduceHiiForDependency (
StartOpCodeHandle,
CFR_COMPONENT_START + Option->dependency_id,
DepValues,
NumDepValues
);
}

if (Option->flags & CFR_OPTFLAG_SUPPRESS) {
CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP);
}
Expand All @@ -285,6 +420,11 @@ CfrProcessFormOption (
TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle);
ASSERT (TempHiiBuffer != NULL);
}

if (Option->dependency_id) {
TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle);
ASSERT (TempHiiBuffer != NULL);
}
}

/**
Expand All @@ -304,6 +444,9 @@ CfrProcessNumericOption (
CFR_VARBINARY *CfrOptionName;
CFR_VARBINARY *CfrDisplayName;
CFR_VARBINARY *CfrHelpText;
UINT32 *DepValues;
UINT32 NumDepValues;
CFR_VARBINARY *CfrDepValues;
UINTN QuestionIdVarStoreId;
UINT8 QuestionFlags;
VOID *DefaultOpCodeHandle;
Expand Down Expand Up @@ -334,6 +477,15 @@ CfrProcessNumericOption (
ASSERT (CfrHelpText->tag == CB_TAG_CFR_VARCHAR_UI_HELPTEXT);
}

// Dependency values are optional
DepValues = NULL;
NumDepValues = 0;
CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_DEP_VALUES);
if (CfrDepValues != NULL) {
ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES);
CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues);
}

DEBUG ((
DEBUG_INFO,
"CFR: Processing option \"%a\", size 0x%x\n",
Expand All @@ -359,6 +511,15 @@ CfrProcessNumericOption (
QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
}

if (Option->dependency_id) {
CfrProduceHiiForDependency (
StartOpCodeHandle,
CFR_COMPONENT_START + Option->dependency_id,
DepValues,
NumDepValues
);
}

if (Option->flags & CFR_OPTFLAG_SUPPRESS) {
CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP);
}
Expand Down Expand Up @@ -470,6 +631,11 @@ CfrProcessNumericOption (
ASSERT (TempHiiBuffer != NULL);
}

if (Option->dependency_id) {
TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle);
ASSERT (TempHiiBuffer != NULL);
}

if (OptionOpCodeHandle != NULL) {
HiiFreeOpCodeHandle (OptionOpCodeHandle);
}
Expand Down Expand Up @@ -497,6 +663,9 @@ CfrProcessCharacterOption (
CFR_VARBINARY *CfrDisplayName;
CFR_VARBINARY *CfrHelpText;
CFR_VARBINARY *CfrDefaultValue;
UINT32 *DepValues;
UINT32 NumDepValues;
CFR_VARBINARY *CfrDepValues;
UINTN QuestionIdVarStoreId;
CHAR16 *HiiDefaultValue;
EFI_STRING_ID HiiDefaultValueId;
Expand Down Expand Up @@ -540,6 +709,15 @@ CfrProcessCharacterOption (
ASSERT (CfrHelpText->tag == CB_TAG_CFR_VARCHAR_UI_HELPTEXT);
}

// Dependency values are optional
DepValues = NULL;
NumDepValues = 0;
CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_DEP_VALUES);
if (CfrDepValues != NULL) {
ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES);
CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues);
}

DEBUG ((
DEBUG_INFO,
"CFR: Processing option \"%a\", size 0x%x\n",
Expand Down Expand Up @@ -576,6 +754,15 @@ CfrProcessCharacterOption (
}
}

if (Option->dependency_id) {
CfrProduceHiiForDependency (
StartOpCodeHandle,
CFR_COMPONENT_START + Option->dependency_id,
DepValues,
NumDepValues
);
}

if (Option->flags & CFR_OPTFLAG_SUPPRESS) {
CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP);
}
Expand Down Expand Up @@ -649,6 +836,11 @@ CfrProcessCharacterOption (
ASSERT (TempHiiBuffer != NULL);
}

if (Option->dependency_id) {
TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle);
ASSERT (TempHiiBuffer != NULL);
}

ASSERT (OptionProcessedLength == Option->size);
*ProcessedLength += Option->size;
}
Expand Down
8 changes: 7 additions & 1 deletion UefiPayloadPkg/Include/Guid/CfrSetupMenuGuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ enum cfr_option_flags {
#define CB_TAG_CFR_VARCHAR_UI_NAME 0x0008
#define CB_TAG_CFR_VARCHAR_UI_HELPTEXT 0x0009
#define CB_TAG_CFR_VARCHAR_DEF_VALUE 0x000a
#define CB_TAG_CFR_DEP_VALUES 0x000c
#pragma pack (1)
typedef struct {
UINT32 tag; /*
* CFR_TAG_VARCHAR_OPT_NAME, CFR_TAG_VARCHAR_UI_NAME,
* CFR_TAG_VARCHAR_UI_HELPTEXT or CFR_TAG_VARCHAR_DEF_VALUE
* CFR_TAG_VARCHAR_UI_HELPTEXT, CFR_TAG_VARCHAR_DEF_VALUE
* or CFR_TAG_DEP_VALUES
*/
UINT32 size; /* Length of the entire structure */
UINT32 data_length; /* Length of data, including NULL terminator for strings */
Expand Down Expand Up @@ -81,6 +83,7 @@ typedef struct {
* CFR_VARCHAR_OPT_NAME opt_name
* CFR_VARCHAR_UI_NAME ui_name
* CFR_VARCHAR_UI_HELPTEXT ui_helptext (Optional)
* CFR_DEP_VALUES dependency_values (Optional)
* CFR_ENUM_VALUE enum_values[]
*/
} CFR_OPTION_NUMERIC;
Expand All @@ -96,6 +99,7 @@ typedef struct {
* CFR_OPT_NAME opt_name
* CFR_UI_NAME ui_name
* CFR_UI_HELPTEXT ui_helptext (Optional)
* CFR_DEP_VALUES dependency_values (Optional)
* CFR_VARCHAR default_value
*/
} CFR_OPTION_VARCHAR;
Expand All @@ -115,6 +119,7 @@ typedef struct {
/*
* CFR_UI_NAME ui_name
* CFR_UI_HELPTEXT ui_helptext (Optional)
* CFR_DEP_VALUES dependency_values (Optional)
*/
} CFR_OPTION_COMMENT;

Expand All @@ -128,6 +133,7 @@ typedef struct {
UINT32 flags; /* enum cfr_option_flags */
/*
* CFR_UI_NAME ui_name
* CFR_DEP_VALUES dependency_values (Optional)
* <T in CFR_OPTION> options[]
*/
} CFR_OPTION_FORM;
Expand Down

0 comments on commit a42154f

Please sign in to comment.