audk/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrOpCodeCreation.c

892 lines
29 KiB
C
Raw Normal View History

/** @file
Library Routines to create IFR independent of string data - assume tokens already exist
Primarily to be used for exporting op-codes at a label in pre-defined forms.
Copyright (c) 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "UefiIfrLibraryInternal.h"
/**
Check if the input question flags is a valid value.
The valid combination of question flags includes
EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY.
@param Flags The question flags to check.
@retval TRUE If the question flag is a valid combination.
@retval FALSE If the question flag is an invalid combination.
**/
BOOLEAN
IsValidQuestionFlags (
IN UINT8 Flags
)
{
return (BOOLEAN) (((Flags & QUESTION_FLAGS_MASK) != 0) ? FALSE : TRUE);
}
/**
Check if the input value type is a valid type.
The valid value type is smaller or equal than EFI_IFR_TYPE_OTHER.
@param Type The value type to check.
@retval TRUE If the value type is valid.
@retval FALSE If the value type is invalid.
**/
BOOLEAN
IsValidValueType (
IN UINT8 Type
)
{
return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE);
}
/**
Check if the input numeric flags is a valid value.
@param Flags The numeric flags to check.
@retval TRUE If the numeric flags is valid.
@retval FALSE If the numeric flags is invalid.
**/
BOOLEAN
IsValidNumricFlags (
IN UINT8 Flags
)
{
if ((Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) != 0) {
return FALSE;
}
if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) {
return FALSE;
}
return TRUE;
}
/**
Check if the checkbox flags is a valid value.
@param Flags The checkbox flags to check.
@retval TRUE If the checkbox flags is valid.
@retval FALSE If the checkbox flags is invalid.
**/
BOOLEAN
IsValidCheckboxFlags (
IN UINT8 Flags
)
{
return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE);
}
/**
Create EFI_IFR_END_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
**/
EFI_STATUS
EFIAPI
CreateEndOpCode (
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_END End;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
End.Header.Length = sizeof (EFI_IFR_END);
End.Header.OpCode = EFI_IFR_END_OP;
End.Header.Scope = 0;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_END to cover the unaligned address access.
//
CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END));
Data->Offset += sizeof (EFI_IFR_END);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_DEFAULT_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param Value Value for the default
@param Type Type for the default
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER The type is not valid.
**/
EFI_STATUS
EFIAPI
CreateDefaultOpCode (
IN EFI_IFR_TYPE_VALUE *Value,
IN UINT8 Type,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_DEFAULT Default;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if ((Value == NULL) || !IsValidValueType (Type)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Default.Header.OpCode = EFI_IFR_DEFAULT_OP;
Default.Header.Length = sizeof (EFI_IFR_DEFAULT);
Default.Header.Scope = 0;
Default.Type = Type;
Default.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE));
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_DEFAULT to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT));
Data->Offset += sizeof (EFI_IFR_DEFAULT);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_ACTION_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param QuestionConfig String ID for configuration
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateActionOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN EFI_STRING_ID QuestionConfig,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_ACTION Action;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Action.Header.OpCode = EFI_IFR_ACTION_OP;
Action.Header.Length = sizeof (EFI_IFR_ACTION);
Action.Header.Scope = 0;
Action.Question.QuestionId = QuestionId;
Action.Question.Header.Prompt = Prompt;
Action.Question.Header.Help = Help;
Action.Question.VarStoreId = INVALID_VARSTORE_ID;
Action.Question.Flags = QuestionFlags;
Action.QuestionConfig = QuestionConfig;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_ACTION to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION));
Data->Offset += sizeof (EFI_IFR_ACTION);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_SUBTITLE_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param Prompt String ID for Prompt
@param Help String ID for Help
@param Flags Subtitle opcode flags
@param Scope Subtitle Scope bit
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
**/
EFI_STATUS
EFIAPI
CreateSubTitleOpCode (
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 Flags,
IN UINT8 Scope,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_SUBTITLE Subtitle;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;
Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);
Subtitle.Header.Scope = Scope;
Subtitle.Statement.Prompt = Prompt;
Subtitle.Statement.Help = Help;
Subtitle.Flags = Flags;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_SUBTITLE to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));
Data->Offset += sizeof (EFI_IFR_SUBTITLE);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_TEXT_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param Prompt String ID for Prompt
@param Help String ID for Help
@param TextTwo String ID for text two
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
**/
EFI_STATUS
EFIAPI
CreateTextOpCode (
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN EFI_STRING_ID TextTwo,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_TEXT Text;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Text.Header.OpCode = EFI_IFR_TEXT_OP;
Text.Header.Length = sizeof (EFI_IFR_TEXT);
Text.Header.Scope = 0;
Text.Statement.Prompt = Prompt;
Text.Statement.Help = Help;
Text.TextTwo = TextTwo;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_TEXT to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT));
Data->Offset += sizeof (EFI_IFR_TEXT);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_REF_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param FormId Destination Form ID
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param QuestionId Question ID
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateGotoOpCode (
IN EFI_FORM_ID FormId,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN EFI_QUESTION_ID QuestionId,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_REF Goto;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Goto.Header.OpCode = EFI_IFR_REF_OP;
Goto.Header.Length = sizeof (EFI_IFR_REF);
Goto.Header.Scope = 0;
Goto.Question.Header.Prompt = Prompt;
Goto.Question.Header.Help = Help;
Goto.Question.VarStoreId = INVALID_VARSTORE_ID;
Goto.Question.QuestionId = QuestionId;
Goto.Question.Flags = QuestionFlags;
Goto.FormId = FormId;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_REF to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF));
Data->Offset += sizeof (EFI_IFR_REF);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_ONE_OF_OPTION_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param OptionCount The number of options.
@param OptionsList The list of Options.
@param Type The data type.
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If OptionCount is not zero but OptionsList is NULL.
**/
EFI_STATUS
EFIAPI
CreateOneOfOptionOpCode (
IN UINTN OptionCount,
IN IFR_OPTION *OptionsList,
IN UINT8 Type,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
UINTN Index;
UINT8 *LocalBuffer;
EFI_IFR_ONE_OF_OPTION OneOfOption;
ASSERT (Data != NULL && Data->Data != NULL);
if ((OptionCount != 0) && (OptionsList == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
for (Index = 0; Index < OptionCount; Index++) {
OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
OneOfOption.Header.Scope = 0;
OneOfOption.Option = OptionsList[Index].StringToken;
OneOfOption.Value = OptionsList[Index].Value;
OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
OneOfOption.Type = Type;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_ONF_OF_OPTION to cover the unaligned address access.
//
CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));
Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION);
}
return EFI_SUCCESS;
}
/**
Create EFI_IFR_ONE_OF_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param VarStoreId Storage ID
@param VarOffset Offset in Storage
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param OneOfFlags Flags for oneof opcode
@param OptionsList List of options
@param OptionCount Number of options in option list
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateOneOfOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 OneOfFlags,
IN IFR_OPTION *OptionsList,
IN UINTN OptionCount,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
UINTN Length;
EFI_IFR_ONE_OF OneOf;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidNumricFlags (OneOfFlags) ||
!IsValidQuestionFlags (QuestionFlags) ||
((OptionCount != 0) && (OptionsList == NULL))) {
return EFI_INVALID_PARAMETER;
}
Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
if (Data->Offset + Length > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;
OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);
OneOf.Header.Scope = 1;
OneOf.Question.Header.Prompt = Prompt;
OneOf.Question.Header.Help = Help;
OneOf.Question.QuestionId = QuestionId;
OneOf.Question.VarStoreId = VarStoreId;
OneOf.Question.VarStoreInfo.VarOffset = VarOffset;
OneOf.Question.Flags = QuestionFlags;
OneOf.Flags = OneOfFlags;
ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA));
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_ONF_OF to cover the unaligned address access.
//
CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));
Data->Offset += sizeof (EFI_IFR_ONE_OF);
CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data);
CreateEndOpCode (Data);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_ORDERED_LIST_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param VarStoreId Storage ID
@param VarOffset Offset in Storage
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param OrderedListFlags Flags for ordered list opcode
@param DataType Type for option value
@param MaxContainers Maximum count for options in this ordered list
@param OptionsList List of options
@param OptionCount Number of options in option list
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateOrderedListOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 OrderedListFlags,
IN UINT8 DataType,
IN UINT8 MaxContainers,
IN IFR_OPTION *OptionsList,
IN UINTN OptionCount,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
UINTN Length;
EFI_IFR_ORDERED_LIST OrderedList;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags) ||
((OptionCount != 0) && (OptionsList == NULL))) {
return EFI_INVALID_PARAMETER;
}
if ((OrderedListFlags != 0) &&
(OrderedListFlags != EFI_IFR_UNIQUE_SET) &&
(OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) {
return EFI_INVALID_PARAMETER;
}
Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END);
if (Data->Offset + Length > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);
OrderedList.Header.Scope = 1;
OrderedList.Question.Header.Prompt = Prompt;
OrderedList.Question.Header.Help = Help;
OrderedList.Question.QuestionId = QuestionId;
OrderedList.Question.VarStoreId = VarStoreId;
OrderedList.Question.VarStoreInfo.VarOffset = VarOffset;
OrderedList.Question.Flags = QuestionFlags;
OrderedList.MaxContainers = MaxContainers;
OrderedList.Flags = OrderedListFlags;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_ORDERED_LIST to cover the unaligned address access.
//
CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));
Data->Offset += sizeof (EFI_IFR_ORDERED_LIST);
CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data);
CreateEndOpCode (Data);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_CHECKBOX_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param VarStoreId Storage ID
@param VarOffset Offset in Storage
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param CheckBoxFlags Flags for checkbox opcode
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateCheckBoxOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 CheckBoxFlags,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_CHECKBOX CheckBox;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP;
CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX);
CheckBox.Header.Scope = 0;
CheckBox.Question.QuestionId = QuestionId;
CheckBox.Question.VarStoreId = VarStoreId;
CheckBox.Question.VarStoreInfo.VarOffset = VarOffset;
CheckBox.Question.Header.Prompt = Prompt;
CheckBox.Question.Header.Help = Help;
CheckBox.Question.Flags = QuestionFlags;
CheckBox.Flags = CheckBoxFlags;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_CHECKBOX to cover the unaligned address access.
//
CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));
Data->Offset += sizeof (EFI_IFR_CHECKBOX);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_NUMERIC_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param VarStoreId Storage ID
@param VarOffset Offset in Storage
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param NumericFlags Flags for numeric opcode
@param Minimum Numeric minimum value
@param Maximum Numeric maximum value
@param Step Numeric step for edit
@param Default Numeric default value
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateNumericOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 NumericFlags,
IN UINT64 Minimum,
IN UINT64 Maximum,
IN UINT64 Step,
IN UINT64 Default,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_STATUS Status;
EFI_IFR_NUMERIC Numeric;
MINMAXSTEP_DATA MinMaxStep;
EFI_IFR_TYPE_VALUE DefaultValue;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;
Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);
Numeric.Header.Scope = 1;
Numeric.Question.QuestionId = QuestionId;
Numeric.Question.VarStoreId = VarStoreId;
Numeric.Question.VarStoreInfo.VarOffset = VarOffset;
Numeric.Question.Header.Prompt = Prompt;
Numeric.Question.Header.Help = Help;
Numeric.Question.Flags = QuestionFlags;
Numeric.Flags = NumericFlags;
switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
case EFI_IFR_NUMERIC_SIZE_1:
MinMaxStep.u8.MinValue = (UINT8) Minimum;
MinMaxStep.u8.MaxValue = (UINT8) Maximum;
MinMaxStep.u8.Step = (UINT8) Step;
break;
case EFI_IFR_NUMERIC_SIZE_2:
MinMaxStep.u16.MinValue = (UINT16) Minimum;
MinMaxStep.u16.MaxValue = (UINT16) Maximum;
MinMaxStep.u16.Step = (UINT16) Step;
break;
case EFI_IFR_NUMERIC_SIZE_4:
MinMaxStep.u32.MinValue = (UINT32) Minimum;
MinMaxStep.u32.MaxValue = (UINT32) Maximum;
MinMaxStep.u32.Step = (UINT32) Step;
break;
case EFI_IFR_NUMERIC_SIZE_8:
MinMaxStep.u64.MinValue = Minimum;
MinMaxStep.u64.MaxValue = Maximum;
MinMaxStep.u64.Step = Step;
break;
}
CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA));
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_NUMERIC to cover the unaligned address access.
//
CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));
Data->Offset += sizeof (EFI_IFR_NUMERIC);
DefaultValue.u64 = Default;
Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data);
if (EFI_ERROR(Status)) {
return Status;
}
CreateEndOpCode (Data);
return EFI_SUCCESS;
}
/**
Create EFI_IFR_STRING_OP opcode.
If Data is NULL or Data->Data is NULL, then ASSERT.
@param QuestionId Question ID
@param VarStoreId Storage ID
@param VarOffset Offset in Storage
@param Prompt String ID for Prompt
@param Help String ID for Help
@param QuestionFlags Flags in Question Header
@param StringFlags Flags for string opcode
@param MinSize String minimum length
@param MaxSize String maximum length
@param Data Destination for the created opcode binary
@retval EFI_SUCCESS Opcode is created successfully.
@retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small.
@retval EFI_INVALID_PARAMETER If QuestionFlags is not valid.
**/
EFI_STATUS
EFIAPI
CreateStringOpCode (
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 StringFlags,
IN UINT8 MinSize,
IN UINT8 MaxSize,
IN OUT EFI_HII_UPDATE_DATA *Data
)
{
EFI_IFR_STRING String;
UINT8 *LocalBuffer;
ASSERT (Data != NULL && Data->Data != NULL);
if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & ~EFI_IFR_STRING_MULTI_LINE) != 0) {
return EFI_INVALID_PARAMETER;
}
if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) {
return EFI_BUFFER_TOO_SMALL;
}
String.Header.OpCode = EFI_IFR_STRING_OP;
String.Header.Length = sizeof (EFI_IFR_STRING);
String.Header.Scope = 0;
String.Question.Header.Prompt = Prompt;
String.Question.Header.Help = Help;
String.Question.QuestionId = QuestionId;
String.Question.VarStoreId = VarStoreId;
String.Question.VarStoreInfo.VarOffset = VarOffset;
String.Question.Flags = QuestionFlags;
String.MinSize = MinSize;
String.MaxSize = MaxSize;
String.Flags = StringFlags;
LocalBuffer = (UINT8 *) Data->Data + Data->Offset;
//
// CopyMem is used for EFI_IFR_STRING to cover the unaligned address access.
//
CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING));
Data->Offset += sizeof (EFI_IFR_STRING);
return EFI_SUCCESS;
}