问题遇到的现象和发生背景
最近学习UEFI Setup页面的页面编写,但是在Vfr窗体文件中加入 oneof 结构的时候进到setup下选择对应的选项就会导致整个setup卡死
问题相关代码,请勿粘贴截图
下面是String.Uni文件:
/=#
#langdef en-US "English"
#langdef fr-FR "Français"
#string STR_GUI_TEST_BANNER #language en-US "Gui Test"
#language fr-FR "Test de l’IG"
#string STR_GUI_TEST_HELP #language en-US "This selection will take you to the Gui Test"
#language fr-FR "Cette sélection vous conduira au Test Gui"
#string STR_TEST_OPTION_BANNER #language en-US "Gui Test Menu"
#language fr-FR "Menu de tests d’interface graphique"
#string STR_TEST_FOOTER #language en-US "This is help information in footer"
#language fr-FR "Ceci est help information in footer"
#string STR_TEST_EMPTY #language en-US " "
#language fr-FR " "
#string STR_TEST_LIST_TITLE #language en-US "Gui Test List"
#language fr-FR "Liste des tests d’interface graphique"
#string EXIT #language en-US "Press ESC to Exit"
#language fr-FR "Presse le ces de sortir"
#string STR_TEXT_ONE #language en-US "Text One"
#string STR_TEXT_HELP #language en-US "Text One Help"
#string STR_TEST_ONE_OF_PROMPT #language en-US "Test one-of Prompt"
#string STR_TEST_ONE_OF_HELP #language en-US "oneof help"
#string STR_ONE_OF_TEXT1 #language en-US "one-of Text #1"
#string STR_ONE_OF_TEXT2 #language en-US "one-of Text #2"
#string STR_ONE_OF_TEXT3 #language en-US "one-of Text #3"
#string STR_ENTER_PAGE2 #language en-US "Enter Page2"
#string STR_ENTER_PAGE_HELP #language en-US "Enter Page Help"
#string STR_ONE_OF_TITLE #language en-US "One Of"
下面是Vfr文件
#define FORMSET_GUID { 0x857bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }
// #define MY_GUITEST_FORM_ID 0x1000
#define MY_GUITEST_LIST_ID 0x1001
#define LABEL_GUITEST_OPTION 0x00
#define LABEL_ONEOF 0x01
#define LABEL_END 0xff
typedef struct {
UINT32 variableId;
} GUI_TEST_VAR_STRUCT;
formset
guid = FORMSET_GUID,
title = STRING_TOKEN(STR_GUI_TEST_BANNER), // Gui Test(Front Page)
help = STRING_TOKEN(STR_GUI_TEST_HELP), // Help Info(Fromt Page)
classguid = gEfiIfrFrontPageGuid,
// Define a Buffer Storage, efivarstore is to define a EFI variable storage
varstore GUI_TEST_VAR_STRUCT,
// attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
varid = 0x01,
name = myVarid,
guid = FORMSET_GUID;
form formid = 1,
title = STRING_TOKEN(STR_GUI_TEST_BANNER); // Gui Test (Option Title)
subtitle text = STRING_TOKEN(STR_TEST_EMPTY);
subtitle text = STRING_TOKEN(STR_TEST_OPTION_BANNER); // Gui Test Menu(Option Menu)
subtitle text = STRING_TOKEN(STR_TEST_EMPTY);
// label LABEL_GUITEST_OPTION;
// label LABEL_END;
text
help = STRING_TOKEN(STR_TEXT_ONE),
text = STRING_TOKEN(STR_TEXT_HELP);
goto 2,
prompt = STRING_TOKEN(STR_TEST_ONE_OF_PROMPT),
help = STRING_TOKEN(STR_TEST_ONE_OF_HELP);
goto 2,
prompt = STRING_TOKEN(STR_TEST_ONE_OF_PROMPT),
help = STRING_TOKEN(STR_TEST_ONE_OF_HELP);
goto 2,
prompt = STRING_TOKEN(STR_TEST_ONE_OF_PROMPT),
help = STRING_TOKEN(STR_TEST_ONE_OF_HELP);
label LABEL_ONEOF;
label LABEL_END;
oneof name = MyTestOneof,
varid = myVarid.variableId,
prompt = STRING_TOKEN(STR_TEST_ONE_OF_PROMPT),
help = STRING_TOKEN(STR_TEST_ONE_OF_HELP),
flags = RESET_REQUIRED,
option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value= 0x0, flags = 0;
option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value= 0x1, flags = 0;
option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value= 0x2, flags = DEFAULT;
endoneof;
subtitle text = STRING_TOKEN(STR_TEST_EMPTY);
subtitle text = STRING_TOKEN(STR_TEST_FOOTER); // help Info(Option footer)
endform;
form formid = 2,
title = STRING_TOKEN(STR_ONE_OF_TITLE);
endform;
endformset;
下面是模块.h文件
#ifndef _EFI_BOOT_MANAGER_H_
#define _EFI_BOOT_MANAGER_H_
#include <Base.h>
#include <Guid/MdeModuleHii.h>
#include <Guid/GlobalVariable.h>
#include <Protocol/HiiConfigAccess.h>
#include <Protocol/DevicePathToText.h>
#include <Protocol/FormBrowserEx2.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HiiLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiBootManagerLib.h>
//
// These are defined as the same with vfr file
//
#define GUI_TEST_FORMSET_GUID \
{ \
0x857bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \
}
#define GUI_TEST_FORM_ID 0x1000
#define LABEL_GUITEST_OPTION 0x00
#define LABEL_GUITEST_OPTION_END 0x01
extern UINT8 MyGuiTestVfrBin[];
#define GUI_TEST_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('G', 'T', 'C', 'B')
typedef struct {
VENDOR_DEVICE_PATH VendorDevicePath;
EFI_DEVICE_PATH_PROTOCOL End;
} HII_VENDOR_DEVICE_PATH;
typedef struct {
UINTN Signature;
//
// HII relative handles
//
EFI_HII_HANDLE HiiHandle;
EFI_HANDLE DriverHandle;
//
// Produced protocols
//
EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
} GUI_TEST_CALLBACK_DATA;
/**
* Customize oneof option in test
**/
VOID
UiCreateOneofMenu (
IN EFI_HII_HANDLE HiiHandle,
IN VOID *StartOpCodeHandle
);
#endif
下面是模块.C文件
/** @file
The gui test reference implementation
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "MyGuiTest.h"
GUI_TEST_CALLBACK_DATA gMyGuiTestPrivate = {
GUI_TEST_CALLBACK_DATA_SIGNATURE,
NULL,
NULL,
{
// BootManagerExtractConfig,
// BootManagerRouteConfig,
// BootManagerCallback
}
};
HII_VENDOR_DEVICE_PATH mGuiTestHiiVendorDevicePath = {
{
{
HARDWARE_DEVICE_PATH,
HW_VENDOR_DP,
{
(UINT8) (sizeof(VENDOR_DEVICE_PATH)),
(UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8)
}
},
{ 0x1eddbe15, 0x481d, 0x4d2b, { 0x82, 0x77, 0xb1, 0x91, 0xea, 0xf6, 0x65, 0x25 } }
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
(UINT8) (END_DEVICE_PATH_LENGTH),
(UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
}
}
};
EFI_GUID mGuiTestGuid = GUI_TEST_FORMSET_GUID;
#define ONEOF_QUESTION_ID 0x1006
#define LABEL_ONEOF 0X01
EFI_STATUS
EFIAPI
MyGuiTestUiLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
// oneof
EFI_IFR_GUID_LABEL *StartGuidLabel;
VOID *StartOpCodeHandle;
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (StartOpCodeHandle != NULL);
// oneof
StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartGuidLabel->Number = LABEL_ONEOF;
//
// Install Device Path Protocol and Config Access protocol to driver handle
//
gMyGuiTestPrivate.DriverHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&gMyGuiTestPrivate.DriverHandle,
&gEfiDevicePathProtocolGuid,
&mGuiTestHiiVendorDevicePath,
&gEfiHiiConfigAccessProtocolGuid,
&gMyGuiTestPrivate.ConfigAccess,
NULL
);
ASSERT_EFI_ERROR (Status);
//
// Publish our HII data
//
gMyGuiTestPrivate.HiiHandle = HiiAddPackages (
&mGuiTestGuid,
gMyGuiTestPrivate.DriverHandle,
MyGuiTestVfrBin,
MyGuiTestUiLibStrings,
NULL
);
ASSERT (gMyGuiTestPrivate.HiiHandle != NULL);
// BmInitialBootModeInfo ();
UiCreateOneofMenu(gMyGuiTestPrivate.HiiHandle, StartOpCodeHandle);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
MyGuiTestUiLibDestructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = gBS->UninstallMultipleProtocolInterfaces (
gMyGuiTestPrivate.DriverHandle,
&gEfiDevicePathProtocolGuid,
&mGuiTestHiiVendorDevicePath,
&gEfiHiiConfigAccessProtocolGuid,
&gMyGuiTestPrivate.ConfigAccess,
NULL
);
ASSERT_EFI_ERROR (Status);
HiiRemovePackages (gMyGuiTestPrivate.HiiHandle);
return EFI_SUCCESS;
}
VOID
UiCreateOneofMenu (
IN EFI_HII_HANDLE HiiHandle,
IN VOID *StartOpCodeHandle
)
{
VOID *OptionsOpCodeHandle;
// 1. allocate memory for Handle
OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT(OptionsOpCodeHandle != NULL);
// 2. Create oneof options opcpde
HiiCreateOneOfOptionOpCode (
OptionsOpCodeHandle,
STRING_TOKEN(STR_ONE_OF_TEXT1),
0,
EFI_IFR_NUMERIC_SIZE_1,
2
);
HiiCreateOneOfOptionOpCode (
OptionsOpCodeHandle,
STRING_TOKEN(STR_ONE_OF_TEXT2),
0,
EFI_IFR_NUMERIC_SIZE_1,
1
);
HiiCreateOneOfOptionOpCode (
OptionsOpCodeHandle,
STRING_TOKEN(STR_ONE_OF_TEXT3),
0,
EFI_IFR_NUMERIC_SIZE_1,
3
);
// 3. Create oneof opcode
HiiCreateOneOfOpCode (
StartOpCodeHandle,
ONEOF_QUESTION_ID,
0,
0,
STRING_TOKEN (STR_TEST_ONE_OF_PROMPT),
STRING_TOKEN (STR_TEST_ONE_OF_HELP),
0, // EFI_IFR_FLAG_CALLBACK,
EFI_IFR_NUMERIC_SIZE_4,
OptionsOpCodeHandle,
NULL
);
}
下面是模块.inf文件
[defines]
INF_VERSION = 0x00010005
BASE_NAME = MyGuiTestUiLib
MODULE_UNI_FILE = MyGuiTestUiLib.uni
FILE_GUID = CCB2DCE1-4FC8-41CB-88C5-D349E134C9FD
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION
CONSTRUCTOR = MyGuiTestUiLibConstructor
DESTRUCTOR = MyGuiTestUiLibDestructor
[Sources]
MyGuiTest.h
MyGuiTestVfr.Vfr
MyGuiTestStrings.uni
MyGuiTest.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiRuntimeServicesTableLib
ReportStatusCodeLib
MemoryAllocationLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
PrintLib
HiiLib
UefiBootManagerLib
[Guids]
gEfiIfrTianoGuid
gEfiIfrFrontPageGuid
[Protocols]
gEfiHiiConfigAccessProtocolGuid
gEfiDevicePathToTextProtocolGuid
gEdkiiFormBrowserEx2ProtocolGuid
[FeaturePcd]
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution
运行结果及报错内容
原本不加上面的oneof那一组的时候,该选项是可以直接进去并显示前面的text的,但是加了oneof之后,选择Gui Test选项回车,直接就卡死完全没反映了
每次卡死之后看到的日志信息如下:
我的解答思路和尝试过的方法
不知道是不是因为逻辑处理的问题,但是问过一些人,他们说这个完全就是界面编写的问题,只涉及到.Vfr文件,跟.c中的逻辑流程没什么太大的关系,我也尝试了去写oneof Opcode的逻辑处理,但是没有奇效。而且反复检查了上述代码没发现哪里有问题
我想要达到的结果
请大家帮忙看看,卡在这里好几天了,为什么会直接卡死