基础驱动综述
UEFI用户交互界面的框架如下所示:
其中上边是输入设备,比如键盘、鼠标等;右边是输出设备,比如显示器;左边是UEFI变量,用来存放交互界面会涉及到的变量。这三个部分都属于UEFI基础,不属于这里介绍的对象。
剩余的部分就是用户交互界面的基本模块,对应到代码中有如下的几个:
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
除此之外,其它的模块(就是上图绿色部分Driver)也会提供用户交互界面需要的元素,这通常是为了完成该模块需要的操作。
在上面的三个模块中,HiiDatabaseDxe.inf这个模块用来初始化并安装操作界面元素的Protocol以及配置相关的Protocol,这些界面元素包括Fonts,Strings,Forms、Images等,就是上图中下边部分的内容。SetupBrowserDxe.inf这个模块依赖于HiiDatabaseDxe.inf,它提供了上图中间部分的实现,实际上是整个用户交互界面的引擎,用来实现各类必要的操作(实际上也不是它来实现,它只是调用了在绿色部分Driver中的操作)。DisplayEngineDxe.inf是配合SetupBrowserDxe.inf一起使用的,它依赖于SetupBrowserDxe.inf。
HiiDatabaseDxe.inf
本模块初始化了HII_DATABASE_PRIVATE_DATA(对应变量mPrivate):
InitializeListHead (&mPrivate.DatabaseList);
InitializeListHead (&mPrivate.DatabaseNotifyList);
InitializeListHead (&mPrivate.HiiHandleList);
InitializeListHead (&mPrivate.FontInfoList);
然后安装了一堆Protocol:
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiHiiFontProtocolGuid,
&mPrivate.HiiFont,
&gEfiHiiStringProtocolGuid,
&mPrivate.HiiString,
&gEfiHiiDatabaseProtocolGuid,
&mPrivate.HiiDatabase,
&gEfiHiiConfigRoutingProtocolGuid,
&mPrivate.ConfigRouting,
&gEfiConfigKeywordHandlerProtocolGuid,
&mPrivate.ConfigKeywordHandler,
NULL
);
还有一部分是可选的:
if (FeaturePcdGet (PcdSupportHiiImageProtocol)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiHiiImageProtocolGuid, &mPrivate.HiiImage,
&gEfiHiiImageExProtocolGuid, &mPrivate.HiiImageEx,
NULL
);
}
关于各个安装的Protocol,后续会介绍。
SetupBrowserDxe.inf
该模块依赖于在HiiDatabaseDxe.inf中安装的某些Protocol:
//
// Locate required Hii relative protocols
//
Status = gBS->LocateProtocol (
&gEfiHiiDatabaseProtocolGuid,
NULL,
(VOID **) &mHiiDatabase
);
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
&gEfiHiiConfigRoutingProtocolGuid,
NULL,
(VOID **) &mHiiConfigRouting
);
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
&gEfiDevicePathFromTextProtocolGuid,
NULL,
(VOID **) &mPathFromText
);
然后安装Protocol:
//
// Install FormBrowser2 protocol
//
mPrivateData.Handle = NULL;
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
&gEfiFormBrowser2ProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.FormBrowser2
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
&gEdkiiFormBrowserEx2ProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.FormBrowserEx2
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
&gEdkiiFormBrowserExProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.FormBrowserEx
);
ASSERT_EFI_ERROR (Status);
然后初始化SETUP_DRIVER_PRIVATE_DATA(对应变量mPrivateData):
InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);
InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);
还有初始化EDKII_FORM_DISPLAY_ENGINE_PROTOCOL(对应mFormDisplay,这个Protocol实际上会在DisplayEngineDxe.inf整个模块中安装):
Status = gBS->LocateProtocol (
&gEdkiiFormDisplayEngineProtocolGuid,
NULL,
(VOID **) &mFormDisplay
);
if (EFI_ERROR (Status)) {
EfiCreateProtocolNotifyEvent (
&gEdkiiFormDisplayEngineProtocolGuid,
TPL_CALLBACK,
FormDisplayCallback,
NULL,
&Registration
);
}
以及FORM_DISPLAY_ENGINE_FORM(对应gDisplayFormData):
InitializeDisplayFormData ();
/**
Initialize the Display form structure data.
**/
VOID
InitializeDisplayFormData (
VOID
)
{
EFI_STATUS Status;
gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;
gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;
gDisplayFormData.ImageId = 0;
gDisplayFormData.AnimationId = 0;
InitializeListHead (&gDisplayFormData.StatementListHead);
InitializeListHead (&gDisplayFormData.StatementListOSF);
InitializeListHead (&gDisplayFormData.HotKeyListHead);
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_CALLBACK,
EfiEventEmptyFunction,
NULL,
&mValueChangedEvent
);
ASSERT_EFI_ERROR (Status);
}
DisplayEngineDxe.inf
首先是安装一个Strings:
gHiiHandle = HiiAddPackages (
&gDisplayEngineGuid,
ImageHandle,
DisplayEngineStrings,
NULL
);
ASSERT (gHiiHandle != NULL);
然后是安装Protocol:
//
// Install Form Display protocol
//
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
&gEdkiiFormDisplayEngineProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.FromDisplayProt
);
ASSERT_EFI_ERROR (Status);
之后初始化一堆字符串:
InitializeDisplayStrings();
/**
Initialize the HII String Token to the correct values.
**/
VOID
InitializeDisplayStrings (
VOID
)
{
gReconnectConfirmChanges = GetToken (STRING_TOKEN (RECONNECT_CONFIRM_CHANGES), gHiiHandle);
mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);
gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
gNoSubmitIfFailed = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle);
gReconnectFail = GetToken (STRING_TOKEN (RECONNECT_FAILED), gHiiHandle);
gReconnectRequired = GetToken (STRING_TOKEN (RECONNECT_REQUIRED), gHiiHandle);
gChangesOpt = GetToken (STRING_TOKEN (RECONNECT_CHANGES_OPTIONS), gHiiHandle);
gSaveProcess = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle);
gSaveNoSubmitProcess = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle);
gDiscardChange = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle);
gJumpToFormSet = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle);
gCheckError = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle);
gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);
gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);
gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);
gBrowserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);
gConfirmDefaultMsg = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE), gHiiHandle);
gConfirmDiscardMsg = GetToken (STRING_TOKEN (CONFIRM_DISCARD_MESSAGE), gHiiHandle);
gConfirmSubmitMsg = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE), gHiiHandle);
gConfirmResetMsg = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE), gHiiHandle);
gConfirmExitMsg = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE), gHiiHandle);
gConfirmDefaultMsg2nd = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE_2ND), gHiiHandle);
gConfirmSubmitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE_2ND), gHiiHandle);
gConfirmResetMsg2nd = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE_2ND), gHiiHandle);
gConfirmExitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE_2ND), gHiiHandle);
gConfirmOpt = GetToken (STRING_TOKEN (CONFIRM_OPTION), gHiiHandle);
gConfirmOptYes = GetToken (STRING_TOKEN (CONFIRM_OPTION_YES), gHiiHandle);
gConfirmOptNo = GetToken (STRING_TOKEN (CONFIRM_OPTION_NO), gHiiHandle);
gConfirmMsgConnect = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle);
gConfirmMsgEnd = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle);
gPasswordUnsupported = GetToken (STRING_TOKEN (PASSWORD_NOT_SUPPORTED ), gHiiHandle);
}
之后初始化几个变量:
ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));
ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));
最后注册几个快捷键:
//
// Use BrowserEx2 protocol to register HotKey.
//
Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
if (!EFI_ERROR (Status)) {
//
// Register the default HotKey F9 and F10 again.
//
HotKey.UnicodeChar = CHAR_NULL;
HotKey.ScanCode = SCAN_F10;
NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
ASSERT (NewString != NULL);
FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
HotKey.ScanCode = SCAN_F9;
NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
ASSERT (NewString != NULL);
FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
}
以上是基本介绍,后续会进一步深入。