processoptions.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,634 行 · 第 1/5 页
C
1,634 行
/*++
Copyright (c) 2004 - 2005, 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.
Module Name:
ProcessOptions.c
Abstract:
Implementation for handling the User Interface option processing.
Revision History
--*/
#include "Ui.h"
#include "Setup.h"
EFI_STATUS
ExtractRequestedNvMap (
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN UINT16 VariableId,
OUT EFI_VARIABLE_DEFINITION **VariableDefinition
)
{
*VariableDefinition = FileFormTags->VariableDefinitions;
//
// Extract the data from the NV variable - consumer will free the buffer.
//
for (; *VariableDefinition != NULL; *VariableDefinition = (*VariableDefinition)->Next) {
//
// If there is a variable with this ID return with EFI_SUCCESS
//
if (!EfiCompareMem (&(*VariableDefinition)->VariableId, &VariableId, sizeof (UINT16))) {
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
ExtractNvValue (
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN UINT16 VariableId,
IN UINT16 VariableSize,
IN UINT16 OffsetValue,
OUT VOID **Buffer
)
{
EFI_STATUS Status;
EFI_VARIABLE_DEFINITION *VariableDefinition;
Status = ExtractRequestedNvMap (FileFormTags, VariableId, &VariableDefinition);
if (!EFI_ERROR (Status)) {
//
// Allocate sufficient space for the data and copy it into the outgoing buffer
//
*Buffer = EfiLibAllocateZeroPool (VariableSize);
ASSERT (*Buffer != NULL);
EfiCopyMem (*Buffer, &VariableDefinition->NvRamMap[OffsetValue], VariableSize);
return EFI_SUCCESS;
}
return Status;
}
VOID
AdjustNvMap (
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN UI_MENU_OPTION *MenuOption
)
{
CHAR8 *NvRamMap;
UINTN SizeRequired;
UINTN Index;
UINTN CachedStart;
EFI_VARIABLE_DEFINITION *VariableDefinition;
CachedStart = 0;
SizeRequired = MenuOption->ThisTag->StorageStart + MenuOption->ThisTag->StorageWidth;
ExtractRequestedNvMap (FileFormTags, MenuOption->Tags->VariableNumber, &VariableDefinition);
//
// We arrived here because the current NvRamMap is too small for the new op-code to store things and
// we need to adjust the buffer to support this.
//
NvRamMap = EfiLibAllocateZeroPool (SizeRequired + 1);
ASSERT (NvRamMap != NULL);
//
// Copy current NvRamMap to the new NvRamMap
//
EfiCopyMem (NvRamMap, VariableDefinition->NvRamMap, VariableDefinition->VariableFakeSize);
//
// Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap
//
for (Index = MenuOption->TagIndex;
(MenuOption->Tags[Index].Operand != EFI_IFR_END_FORM_OP) && (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP);
Index++
) {
switch (MenuOption->Tags[Index].Operand) {
case EFI_IFR_ORDERED_LIST_OP:
case EFI_IFR_ONE_OF_OP:
CachedStart = MenuOption->Tags[Index].StorageStart;
break;
case EFI_IFR_ONE_OF_OPTION_OP:
if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) {
EfiCopyMem (&NvRamMap[CachedStart], &MenuOption->Tags[Index].Value, 2);
}
break;
case EFI_IFR_CHECKBOX_OP:
EfiCopyMem (&NvRamMap[MenuOption->Tags[Index].StorageStart], &MenuOption->Tags[Index].Flags, 1);
break;
case EFI_IFR_NUMERIC_OP:
case EFI_IFR_DATE_OP:
case EFI_IFR_TIME_OP:
case EFI_IFR_STRING_OP:
case EFI_IFR_PASSWORD_OP:
EfiCopyMem (
&NvRamMap[MenuOption->Tags[Index].StorageStart],
&MenuOption->Tags[Index].Value,
MenuOption->Tags[Index].StorageWidth
);
break;
}
}
gBS->FreePool (VariableDefinition->NvRamMap);
VariableDefinition->NvRamMap = NvRamMap;
VariableDefinition->VariableFakeSize = (UINT16) SizeRequired;
}
EFI_STATUS
ProcessOptions (
IN UI_MENU_OPTION *MenuOption,
IN BOOLEAN Selected,
IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
IN EFI_IFR_DATA_ARRAY *PageData,
OUT CHAR16 **OptionString
)
{
EFI_STATUS Status;
CHAR16 *StringPtr;
UINTN Index;
UINTN CachedIndex;
EFI_FILE_FORM_TAGS *FileFormTags;
EFI_TAG *Tag;
CHAR16 FormattedNumber[6];
UINT16 Number;
UINT16 Value;
UINT16 *ValueArray;
UINT16 *NvRamMap;
CHAR8 *TmpNvRamMap;
UINTN Default;
UINTN StringCount;
CHAR16 Character[2];
UINTN Count;
EFI_TIME Time;
EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
STRING_REF PopUp;
CHAR16 NullCharacter;
EFI_INPUT_KEY Key;
EFI_VARIABLE_DEFINITION *VariableDefinition;
BOOLEAN OrderedList;
BOOLEAN Initialized;
UINT16 KeyValue;
BOOLEAN Skip;
FileFormTags = FileFormTagsHead;
for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
FileFormTags = FileFormTags->NextFile;
}
OrderedList = FALSE;
Initialized = FALSE;
ValueArray = NULL;
VariableDefinition = NULL;
Skip = FALSE;
EfiZeroMem (&Time, sizeof (EFI_TIME));
StringPtr = L"\0";
Tag = MenuOption->ThisTag;
ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
if (Tag->StorageStart > VariableDefinition->VariableSize) {
NvRamMap = (UINT16 *) &VariableDefinition->FakeNvRamMap[Tag->StorageStart];
} else {
NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
}
StringCount = 0;
Character[1] = 0;
Count = 0;
Default = 0;
NullCharacter = CHAR_NULL;
FormCallback = NULL;
if (MenuOption->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {
OrderedList = TRUE;
if (((UINT8 *) NvRamMap)[0] != 0x00) {
Initialized = TRUE;
}
}
EfiZeroMem (FormattedNumber, 12);
Status = gBS->HandleProtocol (
(VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
&gEfiFormCallbackProtocolGuid,
&FormCallback
);
if (*OptionString != NULL) {
gBS->FreePool (*OptionString);
*OptionString = NULL;
}
switch (Tag->Operand) {
case EFI_IFR_ORDERED_LIST_OP:
case EFI_IFR_ONE_OF_OP:
//
// If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
// created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
// the NvMap so that we can properly display the information
//
if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
AdjustNvMap (FileFormTags, MenuOption);
NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
}
CachedIndex = MenuOption->TagIndex;
//
// search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,
// each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks
// when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice
//
for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {
//
// We found an option - which assumedly has a string. We will eventually have to support
// wrapping of strings. For now, let's pretend they don't wrap and code that up.
//
// Count how many strings there are
//
if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
//
// If one of the options for the one-of has an interactive flag, back-define the oneof to have one too
//
if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_INTERACTIVE) {
MenuOption->Tags[CachedIndex].Flags = (UINT8) (MenuOption->Tags[CachedIndex].Flags | EFI_IFR_FLAG_INTERACTIVE);
}
StringCount++;
}
}
//
// We now know how many strings we will have, so we can allocate the
// space required for the array or strings.
//
*OptionString = EfiLibAllocateZeroPool (StringCount * (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
ASSERT (*OptionString);
//
// Add left delimeter to string
//
*OptionString[0] = LEFT_ONEOF_DELIMITER;
//
// Retrieve the current OneOf value
//
if (Selected) {
//
// Auto selection from list
//
Value = 0;
//
// Copy current setting to the seed Value
//
if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
ValueArray = EfiLibAllocateZeroPool (MenuOption->ThisTag->StorageWidth);
ASSERT (ValueArray != NULL);
EfiCopyMem (ValueArray, NvRamMap, MenuOption->ThisTag->StorageWidth);
} else {
EfiCopyMem (&Value, NvRamMap, MenuOption->ThisTag->StorageWidth);
EfiCopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
}
Number = Value;
if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
Status = GetSelectionInputPopUp (MenuOption, Tag, MenuOption->ThisTag->StorageWidth, ValueArray, &KeyValue);
} else {
Status = GetSelectionInputPopUp (MenuOption, Tag, 1, &Value, &KeyValue);
}
if (!EFI_ERROR (Status)) {
if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
EfiCopyMem (NvRamMap, ValueArray, MenuOption->ThisTag->StorageWidth);
gBS->FreePool (ValueArray);
} else {
//
// Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
//
EfiCopyMem (NvRamMap, &Value, Tag->StorageWidth);
MenuOption->ThisTag->Key = KeyValue;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?