EDKII Boot Order Boot Option 介绍


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;

UiListThirdPartyDrivers是edk2中的一个用户界面控件,用于显示第三方驱动程序列表。要使用它,你需要遵循以下步骤: 1. 在你的edk2工程中创建一个新的表单文件(.fdf)或在现有的表单文件中添加一个新的表单页。 2. 在表单页中添加UiListThirdPartyDrivers控件。你可以使用以下代码片段添加该控件: ``` <Form> <Guid>YOUR_FORM_GUID_HERE</Guid> <Title>Your Form Title</Title> <SuppressIfDisabled>false</SuppressIfDisabled> <FormData> <Guid>YOUR_FORM_DATA_GUID_HERE</Guid> <Data> ... </Data> </FormData> <SubTitle>Your Form Subtitle</SubTitle> <Ui> <List> <QuestionType>ONE_OF</QuestionType> <QuestionId>YOUR_QUESTION_ID_HERE</QuestionId> <LabelText>Your List Label</LabelText> <HelpText>Your List Help Text</HelpText> <Options> <Option> <Text>Your Option Text</Text> <Value>0</Value> <SuppressIf>FALSE</SuppressIf> </Option> ... </Options> <Default>0</Default> <MaxContainers>0</MaxContainers> <NoSubmitIf>FALSE</NoSubmitIf> <Attributes> <Attribute> <Id>UEFI_LIST_THIRD_PARTY_DRIVERS</Id> <Value>TRUE</Value> </Attribute> </Attributes> </List> </Ui> </Form> ``` 3. 在你的edk2应用程序中处理表单提交事件,并从提交表单数据中获取用户选择的第三方驱动程序列表。你可以使用以下代码片段来处理表单提交事件: ``` EFI_STATUS EFIAPI YourFormSubmitHandler ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress ) { ... EFI_STRING Value; // Get user selection from the submitted form data Value = HiiGetConfigString ( &This->ConfigAccess, Configuration, L"YOUR_QUESTION_ID_HERE" ); ... } ``` 希望这可以帮助你开始使用UiListThirdPartyDrivers控件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小菜鸟-BIOS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值