HelloWorld4(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN VarSize = 0;
UINT16 *BootOrder = NULL;
UINTN BootOrderSize;
Status = gRT->GetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
NULL,
&BootOrderSize,
&BootOrder
);
Print(L"BootOrderSize :%x\n",BootOrderSize);
Print(L"BootOrder :%x\n",BootOrder);
return Status;
}
Boot 启动项中有个Boot Order的 Variable 打印一看 发现只存在几组 数据 0000 0001
真正的启动项呢?
Boot界面显示有多个启动项,这些启动项都是存在Nvram中 我们在Vaiabled中查找启动项
LOG 中Dump 了 Boot#### 以及Boot Order
Boot0006 : UEFI Shell
Boot0001 UEFI BootManagerMenuApp
Boot0002 UEFI Misc Device
Boot0003 UEFI Misc Non-Block Boot Device
Boot0004 UEFI BootManagerMenuAPP
Boot0005 UEFI AcpiViewApp
Boot 0000 是第一启动项 Enter Setup
Boot Menu是一个动态更新的,在Vfr中预留了Label Question id 0x1212
当点击goto 0x1212 会更新显示Menu Boot的启动项
\MdeModulePkg\Library\BootManagerUiLib\BootManagerVfr.Vfr
//
//Add this invisable text in order to indicate enter Boot Manager form.
//
suppressif TRUE;
text
help = STRING_TOKEN(STR_LAST_STRING ),
text = STRING_TOKEN(STR_LAST_STRING ),
flags = INTERACTIVE,
key = 0x1212;
endif;
//
// This is where we will dynamically add choices for the Boot Manager
//
label LABEL_BOOT_OPTION;
label LABEL_BOOT_OPTION_END;
动态更新Boot Menu 函数
VOID
UpdateBootManager (
VOID
)
{
UINTN Index;
EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
UINTN BootOptionCount;
EFI_STRING_ID Token;
CHAR16 *HelpString;
EFI_STRING_ID HelpToken;
UINT16 *TempStr;
EFI_HII_HANDLE HiiHandle;
UINTN TempSize;
VOID *StartOpCodeHandle;
VOID *EndOpCodeHandle;
EFI_IFR_GUID_LABEL *StartLabel;
EFI_IFR_GUID_LABEL *EndLabel;
UINT16 DeviceType;
BOOLEAN IsLegacyOption;
BOOLEAN NeedEndOp;
UINTN MaxLen;
DeviceType = (UINT16)-1;
//
// for better user experience
// 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option
// 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option
//
EfiBootManagerRefreshAllBootOption ();
//
// BdsDxe doesn't group the legacy boot options for the same device type
// It's UI's choice.
//
GroupMultipleLegacyBootOption4SameType ();
BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
HiiHandle = gBootManagerPrivate.HiiHandle;
//
// Allocate space for creation of UpdateData Buffer
//
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (StartOpCodeHandle != NULL);
EndOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (EndOpCodeHandle != NULL);
//
// Create Hii Extend Label OpCode as the start opcode
//
StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartLabel->Number = LABEL_BOOT_OPTION;
//
// Create Hii Extend Label OpCode as the end opcode
//
EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
EndLabel->Number = LABEL_BOOT_OPTION_END;
mKeyInput = 0;
NeedEndOp = FALSE;
for (Index = 0; Index < BootOptionCount; Index++) {
//
// At this stage we are creating a menu entry, thus the Keys are reproduceable
//
mKeyInput++;
//
// Don't display hidden boot options, but retain inactive ones.
//
if ((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) {
continue;
}
//
// Group the legacy boot option in the sub title created dynamically
//
IsLegacyOption = (BOOLEAN)(
(DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&
(DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)
);
if (!IsLegacyOption && NeedEndOp) {
NeedEndOp = FALSE;
HiiCreateEndOpCode (StartOpCodeHandle);
}
if (IsLegacyOption && (DeviceType != ((BBS_BBS_DEVICE_PATH *)BootOption[Index].FilePath)->DeviceType)) {
if (NeedEndOp) {
HiiCreateEndOpCode (StartOpCodeHandle);
}
DeviceType = ((BBS_BBS_DEVICE_PATH *)BootOption[Index].FilePath)->DeviceType;
Token = HiiSetString (
HiiHandle,
0,
mDeviceTypeStr[
MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1)
],
NULL
);
HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
NeedEndOp = TRUE;
}
ASSERT (BootOption[Index].Description != NULL);
Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL);
TempStr = BmDevicePathToStr (BootOption[Index].FilePath);
TempSize = StrSize (TempStr);
HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof (CHAR16);
ASSERT (HelpString != NULL);
StrCatS (HelpString, MaxLen, L"Device Path : ");
StrCatS (HelpString, MaxLen, TempStr);
HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
HiiCreateActionOpCode (
StartOpCodeHandle,
mKeyInput,
Token,
HelpToken,
EFI_IFR_FLAG_CALLBACK,
0
);
}
if (NeedEndOp) {
HiiCreateEndOpCode (StartOpCodeHandle);
}
HiiUpdateForm (
HiiHandle,
&mBootManagerGuid,
BOOT_MANAGER_FORM_ID,
StartOpCodeHandle,
EndOpCodeHandle
);
HiiFreeOpCodeHandle (StartOpCodeHandle);
HiiFreeOpCodeHandle (EndOpCodeHandle);
EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
}
增加一个Boot option
改变Boot option的Order
BootOrder Boot0006 -> Boot0007-> Boot0004-> Boot0002-> Boot0003-> Boot0005-> Boot0001-> Boot0000
启动信息存在Boot####中 通过Boot Order 确定启动的顺序
Boot Option的结构体
typedef struct {
//
// Data read from UEFI NV variables
//
UINTN OptionNumber; // #### numerical value, could be LoadOptionNumberUnassigned
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; // LoadOptionTypeBoot or LoadOptionTypeDriver
UINT32 Attributes; // Load Option Attributes
CHAR16 *Description; // Load Option Description
EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
UINT8 *OptionalData; // Load Option optional data to pass into image
UINT32 OptionalDataSize; // Load Option size of OptionalData
EFI_GUID VendorGuid;
//
// Used at runtime
//
EFI_STATUS Status; // Status returned from boot attempt gBS->StartImage ()
CHAR16 *ExitData; // Exit data returned from gBS->StartImage ()
UINTN ExitDataSize; // Size of ExitData
} EFI_BOOT_MANAGER_LOAD_OPTION;
// Size of ExitData
} EFI_BOOT_MANAGER_LOAD_OPTION;