这篇文章主要记录一些setup界面的实例,这些实例都是EDK上的,我们可以看到如下图:
上面三个为banner,下面的都是通过LABLE动态加载的,代码如下:
我们可以看到 UiListThirdPartyDrivers (HiiHandle, &gEfiIfrFrontPageGuid, NULL, StartOpCodeHandle);这个函数,就是发现第三方的HII驱动然后给它放到FrontPage也就是主页当中,怎么发现,就是通过VFR中的classguid是不是gEfiIfrFrontPageGuid,这是重要依据,自己创建一个第三方驱动AnthonyPage,其中VFR:
, C文件中保留重要的函数就行,仿照其他第三方驱动,这些驱动以Library形式在DSC文件中被包入,这样就新增了一个页面,在DeviceManager页面,还有一种驱动,这种是独立的驱动
在Devices List下有六个子项,这六个子项就是六个独立的驱动,以Browser Testcase Engine为例子,查看vfr:
可以看到重点是EFI_HII_PLATFORM_SETUP_FORMSET_GUID,这个classguid和device manager这个页面是绑定的,在仿照这种驱动的时候,这个classguid必须是EFI_HII_PLATFORM_SETUP_FORMSET_GUID。
打开Browser Testcase Engine页面,一个一个分析:
第一个:My subtitle text:
title就是My First Setup Page,下面的就是My subtitle text和它的help,一个vfr只有一个formset,其他的就是formid,formid和LABLE同级。
第二个My CPU Speed is :
第一个text就是左边的文字,第二个就是它的值,这种形式可以看到,它是可以选中但是不能改动的,因为没有key,不能执行action
Exit now!
text
help = STRING_TOKEN(STR_EXIT_TEXT),
text = STRING_TOKEN(STR_EXIT_TEXT),
flags = INTERACTIVE, // VfrCompiler will generate opcode EFI_IFR_ACTION for Text marked as INTERACTIVE
key = 0x1237;
INTERACTIVE,意味人机交互,也就是可以动作的,通过这个key去进行操作,这种形式选中后按Enter就是执行操作,先理解三个函数,ExtractConfig,导出配置,RouteConfig,存储配置,CallBack,操作Hii数据。执行操作在callback中:
case EFI_BROWSER_ACTION_CHANGED:
switch (QuestionId) {
case 0x1237:
//
// User press "Exit now", request Browser to exit
//
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
break;
case 0x1238:
//
// User press "Save now", request Browser to save the uncommitted data.
//
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
break;
直接跳过到My one-of prompt #1,前面几个类似,不介绍了:
//
// Define oneof (EFI_IFR_ONE_OF)
//
oneof name = MyOneOf, // Define reference name for Question
varid = MyIfrNVData.SuppressGrayOutSomething, // Use "DataStructure.Member" to reference Buffer Storage
prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
help = STRING_TOKEN(STR_ONE_OF_HELP),
//
// Define an option (EFI_IFR_ONE_OF_OPTION)
//
option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0;
option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0;
//
// DEFAULT indicate this option will be marked with EFI_IFR_OPTION_DEFAULT
//
option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT;
endoneof;
看代码,one-of也就是其中之一,这里有三个选项,分别是0:让checkbox隐藏,1:让checkbox不可选,2:让checkbox可选,我们尝试更改为Suppress the Checkbox,可以看到:
下方的checkbox没有了,反而出现了一个Pick 1。这里主要说明不可选和隐藏的使用,
grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
suppressif questionref(MyOneOf) == 0x0;
checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
help = STRING_TOKEN(STR_CHECK_BOX_HELP),
//
// CHECKBOX_DEFAULT indicate this checkbox is marked with EFI_IFR_CHECKBOX_DEFAULT
// CHECKBOX_DEFAULT_MFG indicate EFI_IFR_CHECKBOX_DEFAULT_MFG.
//
flags = CHECKBOX_DEFAULT | CHECKBOX_DEFAULT_MFG,
default = TRUE,
endcheckbox;
endif;
endif;
第一句就是可选与不可选,ideqval只是判断,这句话可以这样理解,grayout if true,如果是true就不可选,什么条件,也就是SuppressGrayOutSomething 的值为0x1;如果不加判断,直接不可选,那么可以这么写 grayoutif TRUE;,别 grayoutif ideqval TRUE,不然会报错。隐藏也是一样,MyOneof只是引用,给该变量取个别名一样,使用是一样的,只是需要加一个questionref。
标准的checkbox如上,简化的如下,需要先初始化变量:
checkbox varid = MyIfrNVData.SerialPortStatus,
prompt = STRING_TOKEN(STR_SERIAL_PORT_STATUS),
help = STRING_TOKEN(STR_CHECK_BOX_HELP),
endcheckbox;
上图选项更改成LargeBootList,Boot Order会多显示USB选项,这个就是在最后一个USB选项加了个隐藏选项,也就是说隐藏和不可选也可以放在一个选项的内部。
然后再看一下Boot Order,它能显示多个选项,是因为使用了orderedlist,这里可以看到suppressif嵌入在中间:
orderedlist
varid = MyIfrNVData.BootOrder,
prompt = STRING_TOKEN(STR_BOOT_OPTIONS),
help = STRING_TOKEN(STR_NULL_STRING),
flags = RESET_REQUIRED,
option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = 0;
option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = 0;
option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = 0;
suppressif ideqval MyIfrNVData.BootOrderLarge == 0;
option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = 0;
endif;
endlist;
待写----