From 143f0b1de83257f1bd238f016bba955879d448c2 Mon Sep 17 00:00:00 2001 From: Eric Dong Date: Thu, 30 Jul 2015 03:41:35 +0000 Subject: [PATCH] UiApp code split from IntelFrameworkModulePkg/Universal/BdsDxe driver. This is the UI part of the old BdsDxe driver, also remove the legacy boot option related code. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong Reviewed-by: Ruiyu Ni git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18111 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Application/UiApp/BootMaint/Bm.vfr | 352 ++++ .../Application/UiApp/BootMaint/BmLib.c | 369 ++++ .../Application/UiApp/BootMaint/Bmstring.uni | Bin 0 -> 41508 bytes .../Application/UiApp/BootMaint/BootMaint.c | 1407 +++++++++++++++ .../Application/UiApp/BootMaint/BootMaint.h | 1478 +++++++++++++++ .../Application/UiApp/BootMaint/BootOption.c | 1527 ++++++++++++++++ .../UiApp/BootMaint/ConsoleOption.c | 995 ++++++++++ .../Application/UiApp/BootMaint/Data.c | 274 +++ .../Application/UiApp/BootMaint/FE.vfr | 123 ++ .../UiApp/BootMaint/FileExplorer.c | 327 ++++ .../Application/UiApp/BootMaint/FormGuid.h | 204 +++ .../Application/UiApp/BootMaint/UpdatePage.c | 1194 ++++++++++++ .../Application/UiApp/BootMaint/Variable.c | 1068 +++++++++++ .../Application/UiApp/BootMngr/BootManager.c | 385 ++++ .../Application/UiApp/BootMngr/BootManager.h | 112 ++ .../UiApp/BootMngr/BootManagerStrings.uni | Bin 0 -> 3518 bytes .../UiApp/BootMngr/BootManagerVfr.Vfr | 50 + .../UiApp/DeviceMngr/DeviceManager.c | 796 ++++++++ .../UiApp/DeviceMngr/DeviceManager.h | 155 ++ .../UiApp/DeviceMngr/DeviceManagerStrings.uni | Bin 0 -> 7086 bytes .../UiApp/DeviceMngr/DeviceManagerVfr.Vfr | 102 ++ .../UiApp/DeviceMngr/DriverHealthVfr.Vfr | 45 + MdeModulePkg/Application/UiApp/FormsetGuid.h | 51 + MdeModulePkg/Application/UiApp/FrontPage.c | 1601 +++++++++++++++++ MdeModulePkg/Application/UiApp/FrontPage.h | 278 +++ .../Application/UiApp/FrontPageStrings.uni | Bin 0 -> 11190 bytes .../Application/UiApp/FrontPageVfr.Vfr | 149 ++ MdeModulePkg/Application/UiApp/Language.c | 309 ++++ MdeModulePkg/Application/UiApp/Language.h | 48 + MdeModulePkg/Application/UiApp/String.c | 67 + MdeModulePkg/Application/UiApp/String.h | 76 + MdeModulePkg/Application/UiApp/Strings.uni | Bin 0 -> 4702 bytes MdeModulePkg/Application/UiApp/Ui.h | 179 ++ MdeModulePkg/Application/UiApp/UiApp.inf | 143 ++ .../Include/Guid/HiiBootMaintenanceFormset.h | 29 + MdeModulePkg/MdeModulePkg.dec | 3 + MdeModulePkg/MdeModulePkg.dsc | 1 + 37 files changed, 13897 insertions(+) create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/Bm.vfr create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/BmLib.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/Bmstring.uni create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/BootMaint.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/BootMaint.h create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/BootOption.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/ConsoleOption.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/Data.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/FE.vfr create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/FileExplorer.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/FormGuid.h create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/UpdatePage.c create mode 100644 MdeModulePkg/Application/UiApp/BootMaint/Variable.c create mode 100644 MdeModulePkg/Application/UiApp/BootMngr/BootManager.c create mode 100644 MdeModulePkg/Application/UiApp/BootMngr/BootManager.h create mode 100644 MdeModulePkg/Application/UiApp/BootMngr/BootManagerStrings.uni create mode 100644 MdeModulePkg/Application/UiApp/BootMngr/BootManagerVfr.Vfr create mode 100644 MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.c create mode 100644 MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.h create mode 100644 MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerStrings.uni create mode 100644 MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerVfr.Vfr create mode 100644 MdeModulePkg/Application/UiApp/DeviceMngr/DriverHealthVfr.Vfr create mode 100644 MdeModulePkg/Application/UiApp/FormsetGuid.h create mode 100644 MdeModulePkg/Application/UiApp/FrontPage.c create mode 100644 MdeModulePkg/Application/UiApp/FrontPage.h create mode 100644 MdeModulePkg/Application/UiApp/FrontPageStrings.uni create mode 100644 MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr create mode 100644 MdeModulePkg/Application/UiApp/Language.c create mode 100644 MdeModulePkg/Application/UiApp/Language.h create mode 100644 MdeModulePkg/Application/UiApp/String.c create mode 100644 MdeModulePkg/Application/UiApp/String.h create mode 100644 MdeModulePkg/Application/UiApp/Strings.uni create mode 100644 MdeModulePkg/Application/UiApp/Ui.h create mode 100644 MdeModulePkg/Application/UiApp/UiApp.inf create mode 100644 MdeModulePkg/Include/Guid/HiiBootMaintenanceFormset.h diff --git a/MdeModulePkg/Application/UiApp/BootMaint/Bm.vfr b/MdeModulePkg/Application/UiApp/BootMaint/Bm.vfr new file mode 100644 index 0000000000..7247bbe997 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/Bm.vfr @@ -0,0 +1,352 @@ +///** @file +// +// Boot Maintenance Utility Formset +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#include "FormGuid.h" + +formset + guid = BOOT_MAINT_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = BOOT_MAINT_FORMSET_GUID, + + varstore BMM_FAKE_NV_DATA, + varid = VARSTORE_ID_BOOT_MAINT, + name = BmmData, + guid = BOOT_MAINT_FORMSET_GUID; + + form formid = FORM_MAIN_ID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE); + + goto FORM_BOOT_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_DRIVER_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP), + flags = INTERACTIVE, + key = FORM_DRIVER_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_CON_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP), + flags = INTERACTIVE, + key = FORM_CON_MAIN_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto + formsetguid = FILE_EXPLORE_FORMSET_GUID, + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_BOOT_FROM_FILE), + help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP), + flags = INTERACTIVE, + key = KEY_VALUE_BOOT_FROM_FILE; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + +// label FORM_MAIN_ID; + + goto FORM_BOOT_NEXT_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_NEXT_ID; + + goto FORM_TIME_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP), + flags = INTERACTIVE, + key = FORM_TIME_OUT_ID; + + label LABEL_BMM_PLATFORM_INFORMATION; + // + // This is where we will dynamically add a Action type op-code to show + // the platform information. + // + + // + // This is where we will dynamically add a Action type op-code to show + // the advanced menu. + // + + // + // This is where we will dynamically add a Action type op-code to show + // the intel test menu. + // + label LABEL_END; + endform; + + form formid = FORM_BOOT_SETUP_ID, + title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto + formsetguid = FILE_EXPLORE_FORMSET_GUID, + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_ADD_ID; + + goto FORM_BOOT_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_DEL_ID; + + goto FORM_BOOT_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), + flags = INTERACTIVE, + key = FORM_BOOT_CHG_ID; + endform; + + form formid = FORM_DRIVER_SETUP_ID, + title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), + flags = INTERACTIVE, + key = FORM_DRV_ADD_ID; + + goto FORM_DRV_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_DRV_DEL_ID; + + goto FORM_DRV_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE, + key = FORM_DRV_CHG_ID; + endform; + + form formid = FORM_BOOT_DEL_ID, + title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE); + + label FORM_BOOT_DEL_ID; + label LABEL_END; + endform; + + form formid = FORM_BOOT_CHG_ID, + title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE); + + label FORM_BOOT_CHG_ID; + label LABEL_END; + + endform; + + form formid = FORM_BOOT_NEXT_ID, + title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE); + + label FORM_BOOT_NEXT_ID; + label LABEL_END; + endform; + + form formid = FORM_TIME_OUT_ID, + title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE); + + label FORM_TIME_OUT_ID; + label LABEL_END; + endform; + + form formid = FORM_MEMORY_CHECK_ID, + title = STRING_TOKEN(STR_FORM_MEMORY_CHECK_TITLE); + + label FORM_MEMORY_CHECK_ID; + label LABEL_END; + endform; + + form formid = FORM_UEFI_OPTIMIZED_BOOT_ID, + title = STRING_TOKEN(STR_FORM_UEFI_OPTIMIZED_BOOT_TITLE); + + label FORM_UEFI_OPTIMIZED_BOOT_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto + formsetguid = FILE_EXPLORE_FORMSET_GUID, + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + flags = INTERACTIVE, + key = FORM_DRV_ADD_FILE_ID; + + endform; + + form formid = FORM_DRV_DEL_ID, + title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); + + label FORM_DRV_DEL_ID; + label LABEL_END; + + endform; + + form formid = FORM_DRV_CHG_ID, + title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); + + label FORM_DRV_CHG_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_MAIN_ID, + title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN); + //flags = INTERACTIVE, + //key = FORM_MAIN_ID; + + goto FORM_CON_IN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_IN_HELP), + flags = INTERACTIVE, + key = FORM_CON_IN_ID; + + goto FORM_CON_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), + flags = INTERACTIVE, + key = FORM_CON_OUT_ID; + + goto FORM_CON_ERR_ID, + prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), + help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), + flags = INTERACTIVE, + key = FORM_CON_ERR_ID; + + goto FORM_CON_MODE_ID, + prompt = STRING_TOKEN(STR_FORM_MODE_TITLE), + help = STRING_TOKEN(STR_FORM_MODE_HELP), + flags = INTERACTIVE, + key = FORM_CON_MODE_ID; + + goto FORM_CON_COM_ID, + prompt = STRING_TOKEN(STR_FORM_COM_TITLE), + help = STRING_TOKEN(STR_FORM_COM_HELP), + flags = INTERACTIVE, + key = FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_MODE_ID, + title = STRING_TOKEN(STR_FORM_MODE_TITLE); + + label FORM_CON_MODE_ID; + label LABEL_END; + endform; + + form formid = FORM_CON_COM_ID, + title = STRING_TOKEN(STR_FORM_COM_TITLE); + + label FORM_CON_COM_ID; + label LABEL_END; + endform; + + form formid = FORM_CON_COM_SETUP_ID, + title = STRING_TOKEN(STR_CON_COM_SETUP); + + label FORM_CON_COM_SETUP_ID; + label LABEL_END; + endform; + + form formid = FORM_FILE_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_SEEK_ID; + label LABEL_END; + endform; + + form formid = FORM_FILE_NEW_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_NEW_SEEK_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_HANDLE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); + + label FORM_DRV_ADD_HANDLE_ID; + label LABEL_END; + endform; + + form formid = FORM_DRV_ADD_HANDLE_DESC_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRV_ADD_HANDLE_DESC_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_IN_ID, + title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); + + label FORM_CON_IN_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_OUT_ID, + title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); + + label FORM_CON_OUT_ID; + label LABEL_END; + + endform; + + form formid = FORM_CON_ERR_ID, + title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); + + label FORM_CON_ERR_ID; + label LABEL_END; + + endform; + +endformset; diff --git a/MdeModulePkg/Application/UiApp/BootMaint/BmLib.c b/MdeModulePkg/Application/UiApp/BootMaint/BmLib.c new file mode 100644 index 0000000000..2b98076512 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/BmLib.c @@ -0,0 +1,369 @@ +/** @file + Utility routines used by boot maintenance modules. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +/** + + Find the first instance of this Protocol + in the system and return it's interface. + + + @param ProtocolGuid Provides the protocol to search for + @param Interface On return, a pointer to the first interface + that matches ProtocolGuid + + @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found + @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid + +**/ +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + (VOID **) Interface + ); + return Status; +} + +/** + + Function opens and returns a file handle to the root directory of a volume. + + @param DeviceHandle A handle for a device + + @return A valid file handle or NULL is returned + +**/ +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE File; + + File = NULL; + + // + // File the file system interface to the device + // + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + + // + // Open the root directory of the volume + // + if (!EFI_ERROR (Status)) { + Status = Volume->OpenVolume ( + Volume, + &File + ); + } + // + // Done + // + return EFI_ERROR (Status) ? NULL : File; +} + +/** + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + + + @param Status Current status + @param Buffer Current allocated buffer, or NULL + @param BufferSize Current buffer size needed + + @retval TRUE if the buffer was reallocated and the caller + should try the API again. + @retval FALSE The caller should not call this function again. + +**/ +BOOLEAN +EfiGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if ((*Buffer == NULL) && (BufferSize != 0)) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + + +/** + Function deletes the variable specified by VarName and VarGuid. + + @param VarName A Null-terminated Unicode string that is + the name of the vendor's variable. + + @param VarGuid A unique identifier for the vendor. + + @retval EFI_SUCCESS The variable was found and removed + @retval EFI_UNSUPPORTED The variable store was inaccessible + @retval EFI_NOT_FOUND The variable was not found + +**/ +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ) +{ + return gRT->SetVariable ( + VarName, + VarGuid, + 0, + 0, + NULL + ); +} + +/** + + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + + + @param FHand The file handle. + + @return A pointer to a buffer with file information. + @retval NULL is returned if failed to get Vaolume Label Info. + +**/ +EFI_FILE_SYSTEM_VOLUME_LABEL * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; + UINTN BufferSize; + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileSystemVolumeLabelInfoIdGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + Duplicate a string. + + @param Src The source. + + @return A new string which is duplicated copy of the source. + @retval NULL If there is not enough memory. + +**/ +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ) +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize (Src); + Dest = AllocateZeroPool (Size); + ASSERT (Dest != NULL); + if (Dest != NULL) { + CopyMem (Dest, Src, Size); + } + + return Dest; +} + +/** + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + + @param FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned + +**/ +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + Function is used to determine the number of device path instances + that exist in a device path. + + + @param DevicePath A pointer to a device path data structure. + + @return This function counts and returns the number of device path instances + in DevicePath. + +**/ +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN Count; + UINTN Size; + + Count = 0; + while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) { + Count += 1; + } + + return Count; +} + +/** + Adjusts the size of a previously allocated buffer. + + + @param OldPool - A pointer to the buffer whose size is being adjusted. + @param OldSize - The size of the current buffer. + @param NewSize - The size of the new buffer. + + @return The newly allocated buffer. + @retval NULL Allocation failed. + +**/ +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize != 0) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool != NULL) { + if (NewPool != NULL) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + FreePool (OldPool); + } + + return NewPool; +} + +/** + Get a string from the Data Hub record based on + a device path. + + @param DevPath The device Path. + + @return A string located from the Data Hub records based on + the device path. + @retval NULL If failed to get the String from Data Hub. + +**/ +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + return NULL; +} diff --git a/MdeModulePkg/Application/UiApp/BootMaint/Bmstring.uni b/MdeModulePkg/Application/UiApp/BootMaint/Bmstring.uni new file mode 100644 index 0000000000000000000000000000000000000000..f93c041a743bb1d1e592407f8a47d978c96ff087 GIT binary patch literal 41508 zcmeHQ+io1W5$)G3u>Ua7z9hlQUiq@N7fBFZMzRpeQZ$mi$%`QC;x$&Xj2YRx&JX7= zlAOa*nPg9Mx|%auwt-+U)0gRPRvi|LMOLx;zyG;k@$*M~2Gw7yi|TE4S)Es3S6{jF z1Dp-_c|59asxhv6SG~c}8LsAC@9@3B_ZoW>oWH={7~3^$ukp{I+O1C9bvL-<9roW< zr`Q`*NAA8$cmJpAUQ}LK_Bx*PzWU_KepCJAp80z`;}3YogX+6#rFvX_i~VgpnPpsJ zpZAP$7k^J&Ii&9%{#nKUyn>v_(@6Cg_f7B}S0C|vhAaOB4i2inL{uH3^tX=7_qg&J z_w(sjxSw2|VS9rs$lD3%JH-`Opn?B=atIK&D;$$bmVW|DCQ%6|IM4fu3Q;1aq{o-Q z`-wfze8iXac2d2@FVB5&bnxk(7Aft@(XDinHc}kd-8E{@-?xSu-@x%sL`zsRzc@Tj z@jK1&ThK#fiHKmv(k3`2=dVGjN)2meP!U^laDjiMhDi6XxM~1eL%L#Y1kq2p>hb|32 zko|M@&F7JuM$l(i5-8(cK20Upd4Az!Y*>u*xcn6Vo35SgqRw~G3RvUEu6-Or4$`Pt z_;2q+*|)M!rOb?r;gm;bJDzJmb`MyxH4U*nf~H7e+YQe>Xl(6&v|V?R-u7#o=&83X zk6RNxx%jZR*a1>8jZO5_+uJUBKlaiWuvZ4qaG#u(J9ie&Yy2nn9Q)1k*yYpOj_U?= z`F8aZI8vw2mOTru8)%zvon=Y8tf{W!x|;W>iKe>jwbL{YPSY~jMAK~f^AdL!;nzp` z>q2Wgu3qo0!Y0~C>O9Jc1=m%yYK|eA^-U?e!a`LJR@1Vl?Wqe^Ls);?z-$%T?)|OJ z??;jxldvrxpx?d1K1X6Y2HS+zisyEKfqV#%XKtTs(t6v+K#J7(<7X+ z94)wxfEs-a-co<@8ON8-7W#nWQb=~8E)TnTWHO$EnU+8C$y>Nk zoI_@he-6*;&)7f2*pVLBQaV6emX*SJFr1cU3x=@_Xe`0aEpF-ur{sEsPd_6pkr}1X zT^#Kx+|v^4XXxWG6pw7Uhlut`X6Kbv3ug6Mqa4gQ>&DoQfs1-!3=KW!;>qT$9M4?3 z_?vB?gbeixXIeO0HG+0w{0yHJ z-aEmwct0aWd_6NhLGK*8I1_p!CU`1o9XL%jh9`_xi^k4K)YA>_lV~ZH8a~sPdasz4 z+YNa1^!&eGM3S^#QaZ-_@{iCTa!!SI-9Gv*T6x>mKXI1+7(WUL#~y9EW(gLe&eZ5U z%oSwmU#PRtKXVs4Ts318jiGO_8;y&@G3+s$XbgRYOQ?&`Q>{Iv4PAP+Ip(7k$mpH2 zXfK|VdYvdLZIaAcvJosc`o2Zt8Q1eW=r~J1+D&d$8W+25lAFcJwiQQ}WJOMSY@#lf z>d^9#9+3Zg&!SS`V+i`EJr>DBU6M7*&THv)XlKS-St766@Mo+W~ZX4%tm*L?HF6404*5T<&iP& z?{DWUINQ&8HHoI@=$0~jihivxa@vL3uGpq!mr`uOb{Of_y2R2?>(LcYn$!llDuwX; zG`Hg{qv>Nhp zJI2rN6yxVWn^l$!nw9Vb%Do_71aJA6dj_VeXJj7R{yE%)KTB&1^*DdsA^dYl% z6JH09MT&Kvfos5IPPCNukV9n(OOCvDvG&rB87zAiEcMByP>Rc+&HsZt^$vLVdCHcgO#?mvz?A*=?u_cGVA3UtG)A}aSc zm?wV^^h=Mr)NbuYryb9B$+zK2DN)SW7hM54wX`|1{QzBkfGwkPDAgNo{{*96W|5h= zbJUHT)eX-Pf3AOK9Gj21ImA;KSwkN@<68R>9Vil0n)~*;udlvhqzbc5G_@{Ef1)di z{QPizr8@I9F*-`}oor%{-lkF-Z9aOtrkYqX!#Y=}SOY2{YV_YsAZENF{iE;U&}8Mc+wzNHQM-k?t_{47-2v6_zM zpGM4rl}E_0n)={cN;o6${|n>0O6j5bX-?t1gV`I}C$V4S*v;s?gyv%Qjpxt`@yCKQ zvtBYbgSj^NtC7rM^buDz@O&v;yVID1BO{Mv{Pf6zBV)33UM9q_KbA*V3cF&s3j8>O z&a7pMoZnh7+(9pQf<7>gdSwPA#uUoBm{Kxmr>!e);#*@r)nm+Va1CVWvz!Mv=7tix zf-9p-#$~3^OHr7@a0FSPe9=gBL$&w{7S zi%xq3LX94J6H7^F9-VD?YNWxeHMSnvdGL(=LVZTGjnXzu)#JT*OhXTM8sxD&YhC8)be_HqOZCuMkhIMc zdMs1Ex^mffW;cWYbXZW*dcV81hX8 zN6x0?8xn|U8o@l-Qy(U?wu%?CeA|`UO;Of{*@i=E6;ik6tnksoF;gEeW1Gdx+ZW7I zl(k{T*&42JW;>lFVe(&2TMhl)eL-uQrZ$`yoyW`vcPCpKE6_jLN>SE^*|ZKjc0Pw@ zIkU*tihH{e-*WU_vH8Dg8gg(*uN1K0@VI&cpG!#;>J;Q)kX|id!QdgH%pMiRpiV&! z1`m^3*Mh-H^~}BVt7L14DagU#(OeijE8G&|@^kp7*R}a$k%1?LB_J+8hyU*r+}rHh zM=sj5TnmWH&*A^cT>L*QEdO!&Is8AJi~k3Odx5z89R8op$v^FYa`G?Mn3kWzKjXvm z_1{Y2_8*s@$A8KiwCMkp!umfhKac;EC1~NltQ{Pdp2vI20<`e{uxQHojYR+_O!k*XQoT((`yvS$$2V*XQI{5Ucm7;0V~4p2vI2;_6Ucli&VAW=e5b5D3*RMMx-Ywp@9FvHdFQ*z)wY(L!*j}-v5n`xFDBty zat_Za3&zItlVUt;$vHfyEEgNkPmA%aCAaY`zL8mNIJ7VMs@}C-^gxuToo#f+ZcG6M^)G27gVA|(7OBY(&{~p?2IsU`ab9hhdK|Ak^ zAD8zttYXfKYeX;cR)ta$A&AVPDF>&tzO>+Uh?Qm6#SjTgZ{uBKn`X5NuO}?L?<3Y* zqRB^y$tWciO;p&iNVk%1SiD5U#jzW0>v-GWzlgo2`l#DW(=^y|NVft{eG?6Jn<=E> z7!fEthzlDPlZ{!_*s-x#6?Sa+p1DnU0ZO$O!6c?4g$38tNIa>Rg7!TN7F@kD!IvvW zMp#`t!5-i5Qwo*Y^rZ0dx&3@jQhl328Yc@r&DlO_6>@cQ`MfyY=u6?}*9&hVu8;AQ z%v>(nQ0BwWugu+q9nX9?%vxSH?@2pNIXI62A|j4}Gqk zwr;qkHKNF$1-FsQKd0G>Cy>t9(0%fLL$4c|;VFD8#)iu;!uLWj&j@q$bITFRF238S zS02+MUUPf8HkR2BZrn(+7_o#fw^* zZ-ik+sp)J3xp;A2NLDNRoJ@VfElpon{Me%PEg{o=SuTEjD%Um9-s%%>({y#kE7W|8 z!z+AhpYWQdt1Dj8GfX38@3)%thCa0qtFpV%*A+i`Z_6w62?ux^dL75y_Sui#xe2)@ z%2JqZK;tuG#TxodTIHdoso9XWVWq@tH!YY+E(m?oWjT*wGaV^Bbe=)-pm3&=Qp2^t z)7dM%Bw6s#c?QXO@*bl)j!#OCPTD9+VWjyZ_AqzCwS<~EX5V3TIMu?^dWtslGM;ka z?peb9%zC(t?FD|hhF1JcyRfIP+^nGHFaE7Ge0?UnD~0!~`_-k z%U?)eqP!_u-)YVa1?RX{-yDPr G?f(E=j@j`5 literal 0 HcmV?d00001 diff --git a/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.c b/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.c new file mode 100644 index 0000000000..aec6b85c22 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.c @@ -0,0 +1,1407 @@ +/** @file + The functions for Boot Maintainence Main menu. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {165A028F-0BB2-4b5f-8747-77592E3F6499} + // + { 0x165a028f, 0xbb2, 0x4b5f, { 0x87, 0x47, 0x77, 0x59, 0x2e, 0x3f, 0x64, 0x99 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {91DB4238-B0C8-472e-BBCF-F3A6541010F4} + // + { 0x91db4238, 0xb0c8, 0x472e, { 0xbb, 0xcf, 0xf3, 0xa6, 0x54, 0x10, 0x10, 0xf4 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID; +EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID; + +CHAR16 mBootMaintStorageName[] = L"BmmData"; +CHAR16 mFileExplorerStorageName[] = L"FeData"; +BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL; +BOOLEAN mAllMenuInit = FALSE; +BOOLEAN mEnterFileExplorer = FALSE; + +/** + Init all memu. + + @param CallbackData The BMM context data. + +**/ +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Free up all Menu Option list. + +**/ +VOID +FreeAllMenu ( + VOID + ); + +/** + Create string tokens for a menu from its help strings and display strings + + @param CallbackData The BMM context data. + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + + @retval EFI_SUCCESS String tokens created successfully + @retval others contain some errors +**/ +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + + NewMenuEntry->DisplayStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->DisplayString, + NULL + ); + + if (NULL == NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + NewMenuEntry->HelpStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->HelpString, + NULL + ); + } + } + + return EFI_SUCCESS; +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +BootMaintExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + BMM_CALLBACK_DATA *Private; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + BOOLEAN AllocatedRequest; + UINTN Size; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mBootMaintGuid, mBootMaintStorageName)) { + return EFI_NOT_FOUND; + } + + ConfigRequestHdr = NULL; + ConfigRequest = NULL; + AllocatedRequest = FALSE; + Size = 0; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + // + // Convert buffer data to by helper function BlockToConfig() + // + BufferSize = sizeof (BMM_FAKE_NV_DATA); + ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + // + // Request has no request element, construct full request string. + // Allocate and fill a buffer large enough to hold the template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator + // + ConfigRequestHdr = HiiConstructConfigHdr (&mBootMaintGuid, mBootMaintStorageName, Private->BmmDriverHandle); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + ASSERT (ConfigRequest != NULL); + AllocatedRequest = TRUE; + UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); + FreePool (ConfigRequestHdr); + } + + Status = gHiiConfigRouting->BlockToConfig ( + gHiiConfigRouting, + ConfigRequest, + (UINT8 *) &Private->BmmFakeNvData, + BufferSize, + Results, + Progress + ); + // + // Free the allocated config request string. + // + if (AllocatedRequest) { + FreePool (ConfigRequest); + ConfigRequest = NULL; + } + // + // Set Progress string to the original request string. + // + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr (Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen (Request); + } + + return Status; +} + +/** + This function applies changes in a driver's configuration. + Input is a Configuration, which has the routing data for this + driver followed by name / value configuration pairs. The driver + must apply those pairs to its configurable storage. If the + driver's configuration is stored in a linear block of data + and the driver's name / value pairs are in + format, it may use the ConfigToBlock helper function (above) to + simplify the job. Currently not implemented. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginn ing of the string if the failure + is in the first name / value pair) or + the terminating NULL if all was + successful. + + @retval EFI_SUCCESS The results have been distributed or are + awaiting distribution. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + @retval EFI_NOT_FOUND Target for the specified routing data + was not found. +**/ +EFI_STATUS +EFIAPI +BootMaintRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + BMM_FAKE_NV_DATA *NewBmmData; + BMM_FAKE_NV_DATA *OldBmmData; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + BMM_CALLBACK_DATA *Private; + + if (Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Configuration; + + if (Configuration == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check routing data in . + // Note: there is no name for Name/Value storage, only GUID will be checked + // + if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **)&ConfigRouting + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + // + // Get Buffer Storage data from EFI variable + // + BufferSize = sizeof (BMM_FAKE_NV_DATA); + OldBmmData = &Private->BmmOldFakeNVData; + NewBmmData = &Private->BmmFakeNvData; + // + // Convert to buffer data by helper function ConfigToBlock() + // + Status = ConfigRouting->ConfigToBlock ( + ConfigRouting, + Configuration, + (UINT8 *) NewBmmData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + // + // Compare new and old BMM configuration data and only do action for modified item to + // avoid setting unnecessary non-volatile variable + // + + // + // Check data which located in BMM main page and save the settings if need + // + if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { + Status = Var_UpdateBootNext (Private); + } + + // + // Check data which located in Boot Options Menu and save the settings if need + // + if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { + for (Index = 0; + ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); + Index ++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; + NewBmmData->BootOptionDel[Index] = FALSE; + } + + Var_DelBootOption (); + } + + if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { + Status = Var_UpdateBootOrder (Private); + } + + // + // Check data which located in Driver Options Menu and save the settings if need + // + if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { + for (Index = 0; + ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; + NewBmmData->DriverOptionDel[Index] = FALSE; + } + Var_DelDriverOption (); + } + + if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { + Status = Var_UpdateDriverOrder (Private); + } + + // + // After user do the save action, need to update OldBmmData. + // + CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); + + return EFI_SUCCESS; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. +**/ +EFI_STATUS +EFIAPI +BootMaintCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + BMM_CALLBACK_DATA *Private; + BM_MENU_ENTRY *NewMenuEntry; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + EFI_STATUS Status; + UINTN OldValue; + UINTN NewValue; + UINTN Number; + UINTN Index; + + // + //Chech whether exit from FileExplorer and reenter BM,if yes,reclaim string depositories + // + if (Action == EFI_BROWSER_ACTION_FORM_OPEN){ + if(mEnterFileExplorer ){ + ReclaimStringDepository(); + mEnterFileExplorer = FALSE; + } + } + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + OldValue = 0; + NewValue = 0; + Number = 0; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + + // + // Retrive uncommitted data from Form Browser + // + CurrentFakeNVMap = &Private->BmmFakeNvData; + HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); + + if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + UpdatePageId (Private, QuestionId); + + if (QuestionId < FILE_OPTION_OFFSET) { + if (QuestionId < CONFIG_OPTION_OFFSET) { + switch (QuestionId) { + case FORM_BOOT_ADD_ID: + // Leave Bm and enter FileExplorer. + Private->FeCurrentState = FileExplorerStateAddBootOption; + Private->FeDisplayContext = FileExplorerDisplayUnknown; + ReclaimStringDepository (); + UpdateFileExplorer(Private, 0); + mEnterFileExplorer = TRUE; + break; + + case FORM_DRV_ADD_FILE_ID: + // Leave Bm and enter FileExplorer. + Private->FeCurrentState = FileExplorerStateAddDriverOptionState; + Private->FeDisplayContext = FileExplorerDisplayUnknown; + ReclaimStringDepository (); + UpdateFileExplorer(Private, 0); + mEnterFileExplorer = TRUE; + break; + + case FORM_DRV_ADD_HANDLE_ID: + CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); + UpdateDrvAddHandlePage (Private); + break; + + case FORM_BOOT_DEL_ID: + CleanUpPage (FORM_BOOT_DEL_ID, Private); + UpdateBootDelPage (Private); + break; + + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + UpdatePageBody (QuestionId, Private); + break; + + case FORM_DRV_DEL_ID: + CleanUpPage (FORM_DRV_DEL_ID, Private); + UpdateDrvDelPage (Private); + break; + + case FORM_BOOT_NEXT_ID: + CleanUpPage (FORM_BOOT_NEXT_ID, Private); + UpdateBootNextPage (Private); + break; + + case FORM_TIME_OUT_ID: + CleanUpPage (FORM_TIME_OUT_ID, Private); + UpdateTimeOutPage (Private); + break; + + case FORM_CON_IN_ID: + case FORM_CON_OUT_ID: + case FORM_CON_ERR_ID: + UpdatePageBody (QuestionId, Private); + break; + + case FORM_CON_MODE_ID: + CleanUpPage (FORM_CON_MODE_ID, Private); + UpdateConModePage (Private); + break; + + case FORM_CON_COM_ID: + CleanUpPage (FORM_CON_COM_ID, Private); + UpdateConCOMPage (Private); + break; + + default: + break; + } + } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { + Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); + Private->CurrentTerminal = Index; + + CleanUpPage (FORM_CON_COM_SETUP_ID, Private); + UpdateTerminalPage (Private); + + } else if (QuestionId >= HANDLE_OPTION_OFFSET) { + Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); + + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); + ASSERT (NewMenuEntry != NULL); + Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + + CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); + + Private->MenuEntry = NewMenuEntry; + Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; + + UpdateDriverAddHandleDescPage (Private); + } + } + if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){ + // Leave Bm and enter FileExplorer. + Private->FeCurrentState = FileExplorerStateBootFromFile; + Private->FeDisplayContext = FileExplorerDisplayUnknown; + ReclaimStringDepository (); + UpdateFileExplorer(Private, 0); + mEnterFileExplorer = TRUE; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (QuestionId) { + case KEY_VALUE_SAVE_AND_EXIT: + case KEY_VALUE_NO_SAVE_AND_EXIT: + if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) { + Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId); + if (EFI_ERROR (Status)) { + return Status; + } + } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) { + DiscardChangeHandler (Private, CurrentFakeNVMap); + } + + // + // Tell browser not to ask for confirmation of changes, + // since we have already applied or discarded. + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; + + break; + + default: + break; + } + } + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); + + return EFI_SUCCESS; +} + +/** + Function handling request to apply changes for BMM pages. + + @param Private Pointer to callback data buffer. + @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM + @param FormId ID of the form which has sent the request to apply change. + + @retval EFI_SUCCESS Change successfully applied. + @retval Other Error occurs while trying to apply changes. + +**/ +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN EFI_FORM_ID FormId + ) +{ + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_LOAD_CONTEXT *NewLoadContext; + BM_MENU_ENTRY *NewMenuEntry; + EFI_STATUS Status; + UINT16 Index; + + Status = EFI_SUCCESS; + + switch (FormId) { + case FORM_BOOT_DEL_ID: + for (Index = 0; + ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])))); + Index ++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index]; + CurrentFakeNVMap->BootOptionDel[Index] = FALSE; + } + + Var_DelBootOption (); + break; + + case FORM_DRV_DEL_ID: + for (Index = 0; + ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index]; + CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; + } + + Var_DelDriverOption (); + break; + + case FORM_BOOT_CHG_ID: + Status = Var_UpdateBootOrder (Private); + break; + + case FORM_DRV_CHG_ID: + Status = Var_UpdateDriverOrder (Private); + break; + + case FORM_TIME_OUT_ID: + Status = gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &(CurrentFakeNVMap->BootTimeOut) + ); + ASSERT_EFI_ERROR(Status); + + Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut; + break; + + case FORM_BOOT_NEXT_ID: + Status = Var_UpdateBootNext (Private); + break; + + case FORM_CON_MODE_ID: + Status = Var_UpdateConMode (Private); + break; + + case FORM_CON_COM_SETUP_ID: + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal); + + ASSERT (NewMenuEntry != NULL); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate; + ASSERT (CurrentFakeNVMap->COMBaudRate < (sizeof (BaudRateList) / sizeof (BaudRateList[0]))); + NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value; + NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate; + ASSERT (CurrentFakeNVMap->COMDataRate < (sizeof (DataBitsList) / sizeof (DataBitsList[0]))); + NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value; + NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits; + ASSERT (CurrentFakeNVMap->COMStopBits < (sizeof (StopBitsList) / sizeof (StopBitsList[0]))); + NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value; + NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity; + ASSERT (CurrentFakeNVMap->COMParity < (sizeof (ParityList) / sizeof (ParityList[0]))); + NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value; + NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType; + + ChangeTerminalDevicePath ( + NewTerminalContext->DevicePath, + FALSE + ); + + Var_UpdateConsoleInpOption (); + Var_UpdateConsoleOutOption (); + Var_UpdateErrorOutOption (); + break; + + case FORM_CON_IN_ID: + for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER); + NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber]; + } + + Var_UpdateConsoleInpOption (); + break; + + case FORM_CON_OUT_ID: + for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER); + NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber]; + } + + Var_UpdateConsoleOutOption (); + break; + + case FORM_CON_ERR_ID: + for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index < MAX_MENU_NUMBER); + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER); + NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber]; + } + + Var_UpdateErrorOutOption (); + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + Status = Var_UpdateDriverOption ( + Private, + Private->BmmHiiHandle, + CurrentFakeNVMap->DriverAddHandleDesc, + CurrentFakeNVMap->DriverAddHandleOptionalData, + CurrentFakeNVMap->DriverAddForceReconnect + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu); + break; + + default: + break; + } + +Error: + return Status; +} + +/** + Discard all changes done to the BMM pages such as Boot Order change, + Driver order change. + + @param Private The BMM context data. + @param CurrentFakeNVMap The current Fack NV Map. + +**/ +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ) +{ + UINT16 Index; + + switch (Private->BmmPreviousPageId) { + case FORM_BOOT_CHG_ID: + CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); + break; + + case FORM_DRV_CHG_ID: + CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); + break; + + case FORM_BOOT_DEL_ID: + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->BootOptionDel[Index] = FALSE; + } + break; + + case FORM_DRV_DEL_ID: + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; + } + break; + + case FORM_BOOT_NEXT_ID: + CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; + break; + + case FORM_TIME_OUT_ID: + CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + case FORM_DRV_ADD_FILE_ID: + case FORM_DRV_ADD_HANDLE_ID: + CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; + CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; + break; + + default: + break; + } +} + + +/** + Create dynamic code for BMM. + + @param BmmCallbackInfo The BMM context data. + +**/ +VOID +InitializeDrivers( + IN BMM_CALLBACK_DATA *BmmCallbackInfo + ) +{ + EFI_HII_HANDLE HiiHandle; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + UINTN Index; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID FormSetHelp; + EFI_STRING String; + EFI_STRING_ID Token; + EFI_STRING_ID TokenHelp; + EFI_HII_HANDLE *HiiHandles; + UINTN SkipCount; + EFI_GUID FormSetGuid; + CHAR16 *DevicePathStr; + EFI_STRING_ID DevicePathId; + + HiiHandle = BmmCallbackInfo->BmmHiiHandle; + // + // 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_BMM_PLATFORM_INFORMATION; + + // + // 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_END; + + // + // Get all the Hii handles + // + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + // + // Search for formset of each class type + // + SkipCount = 0; + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiIfrBootMaintenanceGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) { + SkipCount = 0; + continue; + } + String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + Token = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + DevicePathStr = ExtractDevicePathFromHiiHandle(HiiHandles[Index]); + DevicePathId = 0; + if (DevicePathStr != NULL){ + DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL); + FreePool (DevicePathStr); + } + + HiiCreateGotoExOpCode ( + StartOpCodeHandle, + 0, + Token, + TokenHelp, + 0, + (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_OFFSET), + 0, + &FormSetGuid, + DevicePathId + ); + // + //One packagelist may has more than one form package, + //Index-- means keep current HiiHandle and still extract from the packagelist, + //SkipCount++ means skip the formset which was found before in the same form package. + // + SkipCount++; + Index--; + } + + HiiUpdateForm ( + HiiHandle, + &mBootMaintGuid, + FORM_MAIN_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + FreePool (HiiHandles); +} + + +/** + Create dynamic code for BMM. + + @param BmmCallbackInfo The BMM context data. + +**/ +VOID +InitializeBmmConfig( + IN BMM_CALLBACK_DATA *BmmCallbackInfo + ) +{ + UpdateBootDelPage (BmmCallbackInfo); + UpdateDrvDelPage (BmmCallbackInfo); + + if (TerminalMenu.MenuNumber > 0) { + BmmCallbackInfo->CurrentTerminal = 0; + UpdateTerminalPage (BmmCallbackInfo); + } + + InitializeDrivers (BmmCallbackInfo); +} + +/** + Initialize the Boot Maintenance Utitliy. + +**/ +VOID +InitializeBM ( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + + BmmCallbackInfo = mBmmCallbackInfo; + BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; + BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; + BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; + BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; + + InitAllMenu (BmmCallbackInfo); + + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); + + InitializeBmmConfig(BmmCallbackInfo); +} + +/** + Initialized all Menu Option List. + + @param CallbackData The BMM context data. + +**/ +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + InitializeListHead (&BootOptionMenu.Head); + InitializeListHead (&DriverOptionMenu.Head); + BOpt_GetBootOptions (CallbackData); + BOpt_GetDriverOptions (CallbackData); + InitializeListHead (&FsOptionMenu.Head); + BOpt_FindDrivers (); + InitializeListHead (&DirectoryMenu.Head); + InitializeListHead (&ConsoleInpMenu.Head); + InitializeListHead (&ConsoleOutMenu.Head); + InitializeListHead (&ConsoleErrMenu.Head); + InitializeListHead (&TerminalMenu.Head); + LocateSerialIo (); + GetAllConsoles (); + mAllMenuInit = TRUE; +} + +/** + Free up all Menu Option list. + +**/ +VOID +FreeAllMenu ( + VOID + ) +{ + if (!mAllMenuInit){ + return; + } + BOpt_FreeMenu (&DirectoryMenu); + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FreeMenu (&BootOptionMenu); + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_FreeMenu (&DriverMenu); + FreeAllConsoles (); + mAllMenuInit = FALSE; +} + +/** + Initialize all the string depositories. + +**/ +VOID +InitializeStringDepository ( + VOID + ) +{ + STRING_DEPOSITORY *StringDepository; + StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); + FileOptionStrDepository = StringDepository++; + ConsoleOptionStrDepository = StringDepository++; + BootOptionStrDepository = StringDepository++; + BootOptionHelpStrDepository = StringDepository++; + DriverOptionStrDepository = StringDepository++; + DriverOptionHelpStrDepository = StringDepository++; + TerminalStrDepository = StringDepository; +} + +/** + Fetch a usable string node from the string depository and return the string token. + + @param CallbackData The BMM context data. + @param StringDepository The string repository. + + @retval EFI_STRING_ID String token. + +**/ +EFI_STRING_ID +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) +{ + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + + CurrentListNode = StringDepository->CurrentNode; + + if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { + // + // Fetch one reclaimed node from the list. + // + NextListNode = StringDepository->CurrentNode->Next; + } else { + // + // If there is no usable node in the list, update the list. + // + NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); + ASSERT (NextListNode != NULL); + NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL); + ASSERT (NextListNode->StringToken != 0); + + StringDepository->TotalNodeNumber++; + + if (NULL == CurrentListNode) { + StringDepository->ListHead = NextListNode; + } else { + CurrentListNode->Next = NextListNode; + } + } + + StringDepository->CurrentNode = NextListNode; + + return StringDepository->CurrentNode->StringToken; +} + +/** + Reclaim string depositories by moving the current node pointer to list head.. + +**/ +VOID +ReclaimStringDepository ( + VOID + ) +{ + UINTN DepositoryIndex; + STRING_DEPOSITORY *StringDepository; + + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + StringDepository->CurrentNode = StringDepository->ListHead; + StringDepository++; + } +} + +/** + Release resource for all the string depositories. + +**/ +VOID +CleanUpStringDepository ( + VOID + ) +{ + UINTN NodeIndex; + UINTN DepositoryIndex; + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + STRING_DEPOSITORY *StringDepository; + + // + // Release string list nodes. + // + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + CurrentListNode = StringDepository->ListHead; + for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { + NextListNode = CurrentListNode->Next; + FreePool (CurrentListNode); + CurrentListNode = NextListNode; + } + + StringDepository++; + } + // + // Release string depository. + // + FreePool (FileOptionStrDepository); +} + +/** + Install BootMaint and FileExplorer HiiPackages. + +**/ +VOID +InitBootMaintenance( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + EFI_STATUS Status; + UINT8 *Ptr; + + Status = EFI_SUCCESS; + + if (!gConnectAllHappened){ + EfiBootManagerConnectAll(); + gConnectAllHappened = TRUE; + } + + EfiBootManagerRefreshAllBootOption (); + + // + // Create CallbackData structures for Driver Callback + // + BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); + ASSERT (BmmCallbackInfo != NULL); + + // + // Create LoadOption in BmmCallbackInfo for Driver Callback + // + Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); + ASSERT (Ptr != NULL); + + // + // Initialize Bmm callback data. + // + BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; + Ptr += sizeof (BM_LOAD_CONTEXT); + + BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; + Ptr += sizeof (BM_FILE_CONTEXT); + + BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; + Ptr += sizeof (BM_HANDLE_CONTEXT); + + BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; + + BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; + BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig; + BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig; + BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback; + BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; + BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; + BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig; + BmmCallbackInfo->FeConfigAccess.RouteConfig = FakeRouteConfig; + BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback; + BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; + BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BmmCallbackInfo->BmmDriverHandle, + &gEfiDevicePathProtocolGuid, + &mBmmHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->BmmConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BmmCallbackInfo->FeDriverHandle, + &gEfiDevicePathProtocolGuid, + &mFeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->FeConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Post our Boot Maint VFR binary to the HII database. + // + BmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( + &mBootMaintGuid, + BmmCallbackInfo->BmmDriverHandle, + BmBin, + UiAppStrings, + NULL + ); + ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL); + + // + // Post our File Explorer VFR binary to the HII database. + // + BmmCallbackInfo->FeHiiHandle = HiiAddPackages ( + &mFileExplorerGuid, + BmmCallbackInfo->FeDriverHandle, + FEBin, + UiAppStrings, + NULL + ); + ASSERT (BmmCallbackInfo->FeHiiHandle != NULL); + + // + // Init OpCode Handle and Allocate space for creation of Buffer + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (mStartOpCodeHandle != NULL); + + mEndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (mEndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + + // + // Create Hii Extend Label OpCode as the end opcode + // + mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + mEndLabel->Number = LABEL_END; + + mBmmCallbackInfo = BmmCallbackInfo; + + InitializeStringDepository (); + +} + +/** + Remove the installed BootMaint and FileExplorer HiiPackages. + +**/ + +VOID +FreeBMPackage( + VOID + ) +{ + BMM_CALLBACK_DATA *BmmCallbackInfo; + + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + if (mEndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mEndOpCodeHandle); + } + + FreeAllMenu (); + CleanUpStringDepository (); + + BmmCallbackInfo = mBmmCallbackInfo; + + // + // Remove our IFR data from HII database + // + HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle); + HiiRemovePackages (BmmCallbackInfo->FeHiiHandle); + + gBS->UninstallMultipleProtocolInterfaces ( + BmmCallbackInfo->FeDriverHandle, + &gEfiDevicePathProtocolGuid, + &mFeHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->FeConfigAccess, + NULL + ); + + gBS->UninstallMultipleProtocolInterfaces ( + BmmCallbackInfo->BmmDriverHandle, + &gEfiDevicePathProtocolGuid, + &mBmmHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &BmmCallbackInfo->BmmConfigAccess, + NULL + ); + + FreePool (BmmCallbackInfo->LoadContext); + FreePool (BmmCallbackInfo); +} + diff --git a/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.h b/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.h new file mode 100644 index 0000000000..49cbd3e89b --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/BootMaint.h @@ -0,0 +1,1478 @@ +/** @file + Header file for boot maintenance module. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BOOT_MAINT_H_ +#define _BOOT_MAINT_H_ + +#include "Ui.h" +#include "FormGuid.h" +#include "FrontPage.h" + +// +// Constants which are variable names used to access variables +// + +#define VAR_CON_OUT_MODE L"ConOutMode" + + +// +// String Contant +// +#define STR_FLOPPY L"Floppy Drive #%02x" +#define STR_HARDDISK L"HardDisk Drive #%02x" +#define STR_CDROM L"ATAPI CDROM Drive #%02x" +#define STR_NET L"NET Drive #%02x" +#define STR_BEV L"BEV Drive #%02x" +#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" +#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" +#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" +#define STR_NET_HELP L"NET Drive #%02x" +#define STR_BEV_HELP L"BEV Drive #%02x" + +// +// Variable created with this flag will be "Efi:...." +// +#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE + +extern EFI_GUID mBootMaintGuid; +extern EFI_GUID mFileExplorerGuid; +extern CHAR16 mFileExplorerStorageName[]; +extern CHAR16 mBootMaintStorageName[]; +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 BmBin[]; +extern UINT8 FEBin[]; + +// +// Below are the number of options in Baudrate, Databits, +// Parity and Stopbits selection for serial ports. +// +#define BM_COM_ATTR_BUADRATE 19 +#define BM_COM_ATTR_DATABITS 4 +#define BM_COM_ATTR_PARITY 5 +#define BM_COM_ATTR_STOPBITS 3 + +// +// Callback function helper +// +#define BMM_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('C', 'b', 'c', 'k') +#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) + +#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE) + +// +// Enumeration type definition +// +typedef UINT8 BBS_TYPE; + +typedef enum _TYPE_OF_TERMINAL { + TerminalTypePcAnsi = 0, + TerminalTypeVt100, + TerminalTypeVt100Plus, + TerminalTypeVtUtf8 +} TYPE_OF_TERMINAL; + +typedef enum _FILE_EXPLORER_STATE { + FileExplorerStateInActive = 0, + FileExplorerStateBootFromFile, + FileExplorerStateAddBootOption, + FileExplorerStateAddDriverOptionState, + FileExplorerStateUnknown +} FILE_EXPLORER_STATE; + +typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT { + FileExplorerDisplayFileSystem, + FileExplorerDisplayDirectory, + FileExplorerDisplayUnknown +} FILE_EXPLORER_DISPLAY_CONTEXT; + +// +// All of the signatures that will be used in list structure +// +#define BM_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') +#define BM_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd') +#define BM_CONSOLE_OPTION_SIGNATURE SIGNATURE_32 ('c', 'n', 's', 'l') +#define BM_FILE_OPTION_SIGNATURE SIGNATURE_32 ('f', 'i', 'l', 'e') +#define BM_HANDLE_OPTION_SIGNATURE SIGNATURE_32 ('h', 'n', 'd', 'l') +#define BM_TERMINAL_OPTION_SIGNATURE SIGNATURE_32 ('t', 'r', 'm', 'l') +#define BM_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') + +#define BM_LOAD_CONTEXT_SELECT 0x0 +#define BM_CONSOLE_CONTEXT_SELECT 0x1 +#define BM_FILE_CONTEXT_SELECT 0x2 +#define BM_HANDLE_CONTEXT_SELECT 0x3 +#define BM_TERMINAL_CONTEXT_SELECT 0x5 + +#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6 +#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7 +#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8 + +// +// Buffer size for update data +// +#define UPDATE_DATA_SIZE 0x100000 + +// +// Namespace of callback keys used in display and file system navigation +// +#define MAX_BBS_OFFSET 0xE000 +#define NET_OPTION_OFFSET 0xD800 +#define BEV_OPTION_OFFSET 0xD000 +#define FD_OPTION_OFFSET 0xC000 +#define HD_OPTION_OFFSET 0xB000 +#define CD_OPTION_OFFSET 0xA000 +#define FILE_OPTION_OFFSET 0x8000 +#define FILE_OPTION_MASK 0x7FFF +#define HANDLE_OPTION_OFFSET 0x7000 +#define CONSOLE_OPTION_OFFSET 0x6000 +#define TERMINAL_OPTION_OFFSET 0x5000 +#define CONFIG_OPTION_OFFSET 0x1200 +#define KEY_VALUE_OFFSET 0x1100 +#define FORM_ID_OFFSET 0x1000 + +// +// VarOffset that will be used to create question +// all these values are computed from the structure +// defined below +// +#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field))) + +// +// Question Id of Zero is invalid, so add an offset to it +// +#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET) + +#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut) +#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext) +#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate) +#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate) +#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits) +#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity) +#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) +#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate) +#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate) +#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits) +#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity) +#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive) +#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect) +#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1) +#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2) +#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1) +#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2) +#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1) +#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2) +#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode) +#define CON_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleCheck) +#define BOOT_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (BootOptionOrder) +#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionOrder) +#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel) +#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel) +#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate) +#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate) +#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits) +#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity) +#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType) + +#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut) +#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext) +#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate) +#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate) +#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits) +#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity) +#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate) +#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate) +#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits) +#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity) +#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive) +#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect) +#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1) +#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2) +#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1) +#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2) +#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1) +#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2) +#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode) +#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck) +#define BOOT_OPTION_ORDER_QUESTION_ID QUESTION_ID (BootOptionOrder) +#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionOrder) +#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel) +#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel) +#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate) +#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate) +#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits) +#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity) +#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType) + +#define STRING_DEPOSITORY_NUMBER 8 + +/// +/// Serial Ports attributes, first one is the value for +/// return from callback function, stringtoken is used to +/// display the value properly +/// +typedef struct { + UINTN Value; + UINT16 StringToken; +} COM_ATTR; + +typedef struct { + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; + + UINT8 BaudRateIndex; + UINT8 DataBitsIndex; + UINT8 ParityIndex; + UINT8 StopBitsIndex; + + UINT8 IsConIn; + UINT8 IsConOut; + UINT8 IsStdErr; + UINT8 TerminalType; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_TERMINAL_CONTEXT; + +typedef struct { + BOOLEAN IsBootNext; + BOOLEAN LoadOptionModified; + BOOLEAN Deleted; + + BOOLEAN IsLegacy; + BOOLEAN IsActive; + BOOLEAN ForceReconnect; + UINTN OptionalDataSize; + + UINTN LoadOptionSize; + UINT8 *LoadOption; + + UINT32 Attributes; + UINT16 FilePathListLength; + UINT16 *Description; + EFI_DEVICE_PATH_PROTOCOL *FilePathList; + UINT8 *OptionalData; + + UINT16 BbsIndex; +} BM_LOAD_CONTEXT; + +typedef struct { + + BOOLEAN IsActive; + + BOOLEAN IsTerminal; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_CONSOLE_CONTEXT; + +typedef struct { + UINTN Column; + UINTN Row; +} CONSOLE_OUT_MODE; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} BM_FILE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_HANDLE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} BM_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID HelpStringToken; + UINTN ContextSelection; + VOID *VariableContext; +} BM_MENU_ENTRY; + +typedef struct { + // + // Shared callback data. + // + UINTN Signature; + + BM_MENU_ENTRY *MenuEntry; + BM_HANDLE_CONTEXT *HandleContext; + BM_FILE_CONTEXT *FileContext; + BM_LOAD_CONTEXT *LoadContext; + BM_TERMINAL_CONTEXT *TerminalContext; + UINTN CurrentTerminal; + BBS_TYPE BbsType; + + // + // BMM main formset callback data. + // + EFI_HII_HANDLE BmmHiiHandle; + EFI_HANDLE BmmDriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess; + EFI_FORM_ID BmmCurrentPageId; + EFI_FORM_ID BmmPreviousPageId; + BOOLEAN BmmAskSaveOrNot; + BMM_FAKE_NV_DATA BmmFakeNvData; + BMM_FAKE_NV_DATA BmmOldFakeNVData; + + // + // File explorer formset callback data. + // + EFI_HII_HANDLE FeHiiHandle; + EFI_HANDLE FeDriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess; + FILE_EXPLORER_STATE FeCurrentState; + FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; + FILE_EXPLORER_NV_DATA FeFakeNvData; +} BMM_CALLBACK_DATA; + +typedef struct _STRING_LIST_NODE STRING_LIST_NODE; + +struct _STRING_LIST_NODE { + EFI_STRING_ID StringToken; + STRING_LIST_NODE *Next; +}; + +typedef struct _STRING_DEPOSITORY { + UINTN TotalNodeNumber; + STRING_LIST_NODE *CurrentNode; + STRING_LIST_NODE *ListHead; +} STRING_DEPOSITORY; + +// +// #pragma pack() +// +// For initializing File System menu +// + +/** + This function build the FsOptionMenu list which records all + available file system in the system. They includes all instances + of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM + and all type of legacy boot device. + + @param CallbackData BMM context data + + @retval EFI_SUCCESS Success find the file system + @retval EFI_OUT_OF_RESOURCES Can not create menu entry + +**/ +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + + @param CallbackData The BMM context data. + @param MenuEntry The Menu Entry. + + @retval EFI_SUCCESS Get files from current dir successfully. + @return Other value if can't get files from current dir. + +**/ +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ); + +/** + + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + + @retval EFI_SUCCESS The function complets successfully. + @return Other value if failed to build the DriverMenu. + +**/ +EFI_STATUS +BOpt_FindDrivers ( + VOID + ); + +/** + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION. + + @param CallbackData The BMM context data. + + @return The number of the Var Boot####. + +**/ +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + + Build up all DriverOptionMenu + + @param CallbackData The BMM context data. + + @return EFI_SUCESS The functin completes successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. + + +**/ +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Free resources allocated in Allocate Rountine. + + @param FreeMenu Menu to be freed + +**/ +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ); + + +/** + + Append file name to existing file name. + + @param Str1 The existing file name + @param Str2 The file name to be appended + + @return Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +**/ +CHAR16* +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ); + +/** + + Check whether current FileName point to a valid + Efi Image File. + + @param FileName File need to be checked. + + @retval TRUE Is Efi Image + @retval FALSE Not a valid Efi Image + +**/ +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ); + +/** + + Check whether current FileName point to a valid Efi Application + + @param Dir Pointer to current Directory + @param FileName Pointer to current File name. + + @retval TRUE Is a valid Efi Application + @retval FALSE not a valid Efi Application + +**/ +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ); + +/** + + Get the Option Number that has not been allocated for use. + + @param Type The type of Option. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetOptionNumber ( + CHAR16 *Type + ); + +/** + + Get the Option Number for Boot#### that does not used. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ); + +/** + +Get the Option Number for Driver#### that does not used. + +@return The unused Option Number. + +**/ +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ); + +/** + Create a menu entry give a Menu type. + + @param MenuType The Menu type to be created. + + + @retval NULL If failed to create the menu. + @return The menu. + +**/ +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ); + +/** + Free up all resource allocated for a BM_MENU_ENTRY. + + @param MenuEntry A pointer to BM_MENU_ENTRY. + +**/ +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ); + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ); + +/** + Get option number according to Boot#### and BootOrder variable. + The value is saved as #### + 1. + + @param CallbackData The BMM context data. +**/ +VOID +GetBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Get driver option order from globalc DriverOptionMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +GetDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Locate all serial io devices for console +// +/** + Build a list containing all serial devices. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_UNSUPPORTED No serial ports present. + +**/ +EFI_STATUS +LocateSerialIo ( + VOID + ); + +// +// Initializing Console menu +// +/** + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. + +**/ +EFI_STATUS +GetAllConsoles( + VOID + ); + +// +// Get current mode information +// +/** + Get mode number according to column and row + + @param CallbackData The BMM context data. +**/ +VOID +GetConsoleOutMode ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Cleaning up console menu +// +/** + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. +**/ +EFI_STATUS +FreeAllConsoles ( + VOID + ); + +/** + Update the device path that describing a terminal device + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + + @param DevicePath The devicepath protocol instance wanted to be updated. + +**/ +VOID +ChangeVariableDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Update the multi-instance device path of Terminal Device based on + the global TerminalMenu. If ChangeTernimal is TRUE, the terminal + device path in the Terminal Device in TerminalMenu is also updated. + + @param DevicePath The multi-instance device path. + @param ChangeTerminal TRUE, then device path in the Terminal Device + in TerminalMenu is also updated; FALSE, no update. + + @return EFI_SUCCESS The function completes successfully. + +**/ +EFI_STATUS +ChangeTerminalDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN ChangeTerminal + ); + +// +// Variable operation by menu selection +// +/** + This function create a currently loaded Boot Option from + the BMM. It then appends this Boot Option to the end of + the "BootOrder" list. It also append this Boot Opotion to the end + of BootOptionMenu. + + @param CallbackData The BMM context data. + @param NvRamMap The file explorer formset internal state. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ); + +/** + Delete Boot Option that represent a Deleted state in BootOptionMenu. + After deleting this boot option, call Var_ChangeBootOrder to + make sure BootOrder is in valid state. + + @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to + BM_LOAD_CONTEXT marked for deletion is deleted + @return Others If failed to update the "BootOrder" variable after deletion. + +**/ +EFI_STATUS +Var_DelBootOption ( + VOID + ); + +/** + After any operation on Boot####, there will be a discrepancy in BootOrder. + Since some are missing but in BootOrder, while some are present but are + not reflected by BootOrder. Then a function rebuild BootOrder from + scratch by content from BootOptionMenu is needed. + + @retval EFI_SUCCESS The boot order is updated successfully. + @return other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeBootOrder ( + VOID + ); + +/** + This function create a currently loaded Drive Option from + the BMM. It then appends this Driver Option to the end of + the "DriverOrder" list. It append this Driver Opotion to the end + of DriverOptionMenu. + + @param CallbackData The BMM context data. + @param HiiHandle The HII handle associated with the BMM formset. + @param DescriptionData The description of this driver option. + @param OptionalData The optional load option. + @param ForceReconnect If to force reconnect. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ); + +/** + Delete Load Option that represent a Deleted state in BootOptionMenu. + After deleting this Driver option, call Var_ChangeDriverOrder to + make sure DriverOrder is in valid state. + + @retval EFI_SUCCESS Load Option is successfully updated. + @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI + Variable. + +**/ +EFI_STATUS +Var_DelDriverOption ( + VOID + ); + +/** + After any operation on Driver####, there will be a discrepancy in + DriverOrder. Since some are missing but in DriverOrder, while some + are present but are not reflected by DriverOrder. Then a function + rebuild DriverOrder from scratch by content from DriverOptionMenu is + needed. + + @retval EFI_SUCCESS The driver order is updated successfully. + @return other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeDriverOrder ( + VOID + ); + +/** + This function delete and build multi-instance device path ConIn + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleInpOption ( + VOID + ); + +/** + This function delete and build multi-instance device path ConOut console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleOutOption ( + VOID + ); + +/** + This function delete and build multi-instance device path ErrOut console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateErrorOutOption ( + VOID + ); + +/** + This function delete and build Out of Band console device. + + @param MenuIndex Menu index which user select in the terminal menu list. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateOutOfBandOption ( + IN UINT16 MenuIndex + ); + +/** + Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits, + parity and stop Bits set. + +**/ +VOID +Var_UpdateAllConsoleOption ( + VOID + ); + +/** + This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM, + this EFI Variable is deleted. + It also update the BMM context data specified the "BootNext" value. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh + BootOptionMenu with the new "BootOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + This function update the "DriverOrder" EFI Variable based on + BMM Formset's NV map. It then refresh DriverOptionMenu + with the new "DriverOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Update the Text Mode of Console. + + @param CallbackData The context data for BMM. + + @retval EFI_SUCCSS If the Text Mode of Console is updated. + @return Other value if the Text Mode of Console is not updated. + +**/ +EFI_STATUS +Var_UpdateConMode ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Following are page create and refresh functions +// +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshUpdateData ( + VOID + ); + +/** + Clean up the dynamic opcode at label and form specified by + both LabelId. + + @param LabelId It is both the Form ID and Label ID for + opcode deletion. + @param CallbackData The BMM context data. + +**/ +VOID +CleanUpPage ( + IN UINT16 LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of boot option from global BootOptionMenu. It + allow user to delete the boot option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of driver option from global DriverMenu. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a lit of driver option from global DriverOptionMenu. It + allow user to delete the driver option. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Prepare the page to allow user to add description for a Driver Option. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Dispatch the correct update page function to call based on the UpdatePageId. + + @param UpdatePageId The form ID. + @param CallbackData The BMM context data. +**/ +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page to allow user to set the "BootNext" vaule. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page to allow user to set the "TimeOut" vaule. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, + Parity, Stop Bits, Terminal Type. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Refresh the text mode page + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConModePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Create a list of Goto Opcode for all terminal devices logged + by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +/** + Function opens and returns a file handle to the root directory of a volume. + + @param DeviceHandle A handle for a device + @return A valid file handle or NULL is returned +**/ +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +/** + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + + @param FHand The file handle. + + @return A pointer to a buffer with file information. + NULL is returned if failed to get Vaolume Label Info. +**/ +EFI_FILE_SYSTEM_VOLUME_LABEL * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +/** + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + + @param FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned + +**/ +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +/** + Find the first instance of this Protocol in the system and return it's interface. + + @param ProtocolGuid Provides the protocol to search for + @param Interface On return, a pointer to the first interface + that matches ProtocolGuid + + @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found + @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid + +**/ +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ); + +/** + Adjusts the size of a previously allocated buffer. + + @param OldPool A pointer to the buffer whose size is being adjusted. + @param OldSize The size of the current buffer. + @param NewSize The size of the new buffer. + + @return The newly allocated buffer. if NULL, allocation failed. + +**/ +VOID* +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ); + +/** + Function deletes the variable specified by VarName and VarGuid. + + + @param VarName A Null-terminated Unicode string that is + the name of the vendor's variable. + + @param VarGuid A unique identifier for the vendor. + + @retval EFI_SUCCESS The variable was found and removed + @retval EFI_UNSUPPORTED The variable store was inaccessible + @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available + @retval EFI_NOT_FOUND The variable was not found + +**/ +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ); + +/** + Duplicate a string. + + @param Src The source. + + @return A new string which is duplicated copy of the source. + @retval NULL If there is not enough memory. + +**/ +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ); + +/** + Function is used to determine the number of device path instances + that exist in a device path. + + + @param DevicePath A pointer to a device path data structure. + + @return This function counts and returns the number of device path instances + in DevicePath. + +**/ +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Create string tokens for a menu from its help strings and display strings + + + @param CallbackData The BMM context data. + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + + @retval EFI_SUCCESS string tokens created successfully + @retval others contain some errors + +**/ +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ); + +/** + Get a string from the Data Hub record based on + a device path. + + @param DevPath The device Path. + + @return A string located from the Data Hub records based on + the device path. + @retval NULL If failed to get the String from Data Hub. + +**/ +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +/** + Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type + specified by DeviceType. + + @param DeviceType The legacy device type. It can be floppy, network, harddisk, cdrom, + etc. + @param OptionIndex Returns the index number (#### in Boot####). + @param OptionSize Return the size of the Boot### variable. + +**/ +VOID * +GetLegacyBootOptionVar ( + IN UINTN DeviceType, + OUT UINTN *OptionIndex, + OUT UINTN *OptionSize + ); + +/** + Initialize the Boot Maintenance Utitliy. + +**/ +VOID +InitializeBM ( + VOID + ); + + +/** + Intialize all the string depositories. + +**/ +VOID +InitializeStringDepository ( + VOID + ); + +/** + Fetch a usable string node from the string depository and return the string token. + + + @param CallbackData The BMM context data. + @param StringDepository Pointer of the string depository. + + @retval EFI_STRING_ID String token. + +**/ +EFI_STRING_ID +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ); + +/** + Reclaim string depositories by moving the current node pointer to list head.. +**/ +VOID +ReclaimStringDepository ( + VOID + ); + +/** + Release resource for all the string depositories. + +**/ +VOID +CleanUpStringDepository ( + VOID + ); + +/** + Function handling request to apply changes for BMM pages. + + @param Private Pointer to callback data buffer. + @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM + @param FormId ID of the form which has sent the request to apply change. + + @retval EFI_SUCCESS Change successfully applied. + @retval Other Error occurs while trying to apply changes. + +**/ +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN EFI_FORM_ID FormId + ); + +/** + Discard all changes done to the BMM pages such as Boot Order change, + Driver order change. + + @param Private The BMM context data. + @param CurrentFakeNVMap The current Fack NV Map. + +**/ +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ); + +/** + Dispatch the display to the next page based on NewPageId. + + @param Private The BMM context data. + @param NewPageId The original page ID. + +**/ +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ); + +/** + Boot a file selected by user at File Expoloer of BMM. + + @param FileContext The file context data, which contains the device path + of the file to be boot from. + + @retval EFI_SUCCESS The function completed successfull. + @return Other value if the boot from the file fails. + +**/ +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ); + +/** + Update the file explower page with the refershed file system. + + + @param CallbackData BMM context data + @param KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ); + +/** + This function processes the results of changes in configuration. + When user select a interactive opcode, this callback will be triggered. + Based on the Question(QuestionId) that triggers the callback, the corresponding + actions is performed. It handles: + + 1) the addition of boot option. + 2) the addition of driver option. + 3) exit from file browser + 4) update of file content if a dir is selected. + 5) boot the file if a file is selected in "boot from file" + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + Remove the installed BootMaint and FileExplorer HiiPackages. + +**/ +VOID +FreeBMPackage( + VOID + ); + +/** + Install BootMaint and FileExplorer HiiPackages. + +**/ +VOID +InitBootMaintenance( + VOID + ); + +// +// Global variable in this program (defined in data.c) +// +extern BM_MENU_OPTION BootOptionMenu; +extern BM_MENU_OPTION DriverOptionMenu; +extern BM_MENU_OPTION FsOptionMenu; +extern BM_MENU_OPTION ConsoleInpMenu; +extern BM_MENU_OPTION ConsoleOutMenu; +extern BM_MENU_OPTION ConsoleErrMenu; +extern BM_MENU_OPTION DirectoryMenu; +extern BM_MENU_OPTION DriverMenu; +extern BM_MENU_OPTION TerminalMenu; +extern UINT16 TerminalType[]; +extern COM_ATTR BaudRateList[19]; +extern COM_ATTR DataBitsList[4]; +extern COM_ATTR ParityList[5]; +extern COM_ATTR StopBitsList[3]; +extern EFI_GUID TerminalTypeGuid[4]; +extern STRING_DEPOSITORY *FileOptionStrDepository; +extern STRING_DEPOSITORY *ConsoleOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionHelpStrDepository; +extern STRING_DEPOSITORY *DriverOptionStrDepository; +extern STRING_DEPOSITORY *DriverOptionHelpStrDepository; +extern STRING_DEPOSITORY *TerminalStrDepository; +extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[]; + +// +// Shared IFR form update data +// +extern VOID *mStartOpCodeHandle; +extern VOID *mEndOpCodeHandle; +extern EFI_IFR_GUID_LABEL *mStartLabel; +extern EFI_IFR_GUID_LABEL *mEndLabel; + +#endif diff --git a/MdeModulePkg/Application/UiApp/BootMaint/BootOption.c b/MdeModulePkg/Application/UiApp/BootMaint/BootOption.c new file mode 100644 index 0000000000..a5bd796194 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/BootOption.c @@ -0,0 +1,1527 @@ +/** @file + Provide boot option support for Application "BootMaint" + + Include file system navigation, system handle selection + + Boot option manipulation + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +/// +/// Define the maximum characters that will be accepted. +/// +#define MAX_CHAR 480 + +/** + Create a menu entry by given menu type. + + @param MenuType The Menu type to be created. + + @retval NULL If failed to create the menu. + @return the new menu entry. + +**/ +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ) +{ + BM_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + // + // Get context size according to menu type + // + switch (MenuType) { + case BM_LOAD_CONTEXT_SELECT: + ContextSize = sizeof (BM_LOAD_CONTEXT); + break; + + case BM_FILE_CONTEXT_SELECT: + ContextSize = sizeof (BM_FILE_CONTEXT); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_CONSOLE_CONTEXT); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + ContextSize = sizeof (BM_TERMINAL_CONTEXT); + break; + + case BM_HANDLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_HANDLE_CONTEXT); + break; + + default: + ContextSize = 0; + break; + } + + if (ContextSize == 0) { + return NULL; + } + + // + // Create new menu entry + // + MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); + if (MenuEntry == NULL) { + return NULL; + } + + MenuEntry->VariableContext = AllocateZeroPool (ContextSize); + if (MenuEntry->VariableContext == NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; + MenuEntry->ContextSelection = MenuType; + return MenuEntry; +} + +/** + Free up all resource allocated for a BM_MENU_ENTRY. + + @param MenuEntry A pointer to BM_MENU_ENTRY. + +**/ +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ) +{ + BM_LOAD_CONTEXT *LoadContext; + BM_FILE_CONTEXT *FileContext; + BM_CONSOLE_CONTEXT *ConsoleContext; + BM_TERMINAL_CONTEXT *TerminalContext; + BM_HANDLE_CONTEXT *HandleContext; + + // + // Select by the type in Menu entry for current context type + // + switch (MenuEntry->ContextSelection) { + case BM_LOAD_CONTEXT_SELECT: + LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; + FreePool (LoadContext->FilePathList); + FreePool (LoadContext->LoadOption); + if (LoadContext->OptionalData != NULL) { + FreePool (LoadContext->OptionalData); + } + FreePool (LoadContext); + break; + + case BM_FILE_CONTEXT_SELECT: + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + if (!FileContext->IsRoot) { + FreePool (FileContext->DevicePath); + } else { + if (FileContext->FHandle != NULL) { + FileContext->FHandle->Close (FileContext->FHandle); + } + } + + if (FileContext->FileName != NULL) { + FreePool (FileContext->FileName); + } + if (FileContext->Info != NULL) { + FreePool (FileContext->Info); + } + FreePool (FileContext); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; + FreePool (ConsoleContext->DevicePath); + FreePool (ConsoleContext); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; + FreePool (TerminalContext->DevicePath); + FreePool (TerminalContext); + break; + + case BM_HANDLE_CONTEXT_SELECT: + HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; + FreePool (HandleContext); + break; + + default: + break; + } + + FreePool (MenuEntry->DisplayString); + if (MenuEntry->HelpString != NULL) { + FreePool (MenuEntry->HelpString); + } + + FreePool (MenuEntry); +} + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + ASSERT (MenuNumber < MenuOption->MenuNumber); + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +/** + This function build the FsOptionMenu list which records all + available file system in the system. They includes all instances + of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM + and all type of legacy boot device. + + @param CallbackData BMM context data + + @retval EFI_SUCCESS Success find the file system + @retval EFI_OUT_OF_RESOURCES Can not create menu entry + +**/ +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN NoBlkIoHandles; + UINTN NoSimpleFsHandles; + UINTN NoLoadFileHandles; + EFI_HANDLE *BlkIoHandle; + EFI_HANDLE *SimpleFsHandle; + EFI_HANDLE *LoadFileHandle; + UINT16 *VolumeLabel; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *MenuEntry; + BM_FILE_CONTEXT *FileContext; + UINT16 *TempStr; + UINTN OptionNumber; + VOID *Buffer; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 DeviceType; + BBS_BBS_DEVICE_PATH BbsDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN RemovableMedia; + + + NoSimpleFsHandles = 0; + NoLoadFileHandles = 0; + OptionNumber = 0; + InitializeListHead (&FsOptionMenu.Head); + + // + // Locate Handles that support BlockIo protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoBlkIoHandles, + &BlkIoHandle + ); + if (!EFI_ERROR (Status)) { + + for (Index = 0; Index < NoBlkIoHandles; Index++) { + Status = gBS->HandleProtocol ( + BlkIoHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + + if (EFI_ERROR (Status)) { + continue; + } + + // + // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media + // + if (BlkIo->Media->RemovableMedia) { + Buffer = AllocateZeroPool (BlkIo->Media->BlockSize); + if (NULL == Buffer) { + FreePool (BlkIoHandle); + return EFI_OUT_OF_RESOURCES; + } + + BlkIo->ReadBlocks ( + BlkIo, + BlkIo->Media->MediaId, + 0, + BlkIo->Media->BlockSize, + Buffer + ); + FreePool (Buffer); + } + } + FreePool (BlkIoHandle); + } + + // + // Locate Handles that support Simple File System protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoSimpleFsHandles, + &SimpleFsHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find all the instances of the File System prototocol + // + for (Index = 0; Index < NoSimpleFsHandles; Index++) { + Status = gBS->HandleProtocol ( + SimpleFsHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + // + // If no block IO exists assume it's NOT a removable media + // + RemovableMedia = FALSE; + } else { + // + // If block IO exists check to see if it's remobable media + // + RemovableMedia = BlkIo->Media->RemovableMedia; + } + + // + // Allocate pool for this load option + // + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + FreePool (SimpleFsHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->Handle = SimpleFsHandle[Index]; + MenuEntry->OptionNumber = Index; + FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); + if (FileContext->FHandle == NULL) { + BOpt_DestroyMenuEntry (MenuEntry); + continue; + } + + MenuEntry->HelpString = UiDevicePathToStr (DevicePathFromHandle (FileContext->Handle)); + FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); + FileContext->FileName = EfiStrDuplicate (L"\\"); + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + FileContext->IsDir = TRUE; + FileContext->IsRoot = TRUE; + FileContext->IsRemovableMedia = RemovableMedia; + FileContext->IsLoadFile = FALSE; + + // + // Get current file system's Volume Label + // + if (FileContext->Info == NULL) { + VolumeLabel = L"NO FILE SYSTEM INFO"; + } else { + if (FileContext->Info->VolumeLabel == NULL) { + VolumeLabel = L"NULL VOLUME LABEL"; + } else { + VolumeLabel = FileContext->Info->VolumeLabel; + if (*VolumeLabel == 0x0000) { + VolumeLabel = L"NO VOLUME LABEL"; + } + } + } + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"%s, [%s]", + VolumeLabel, + TempStr + ); + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoSimpleFsHandles != 0) { + FreePool (SimpleFsHandle); + } + // + // Searching for handles that support Load File protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NoLoadFileHandles, + &LoadFileHandle + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoLoadFileHandles; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + FreePool (LoadFileHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->Handle = LoadFileHandle[Index]; + FileContext->IsRoot = TRUE; + + FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle); + FileContext->FileName = UiDevicePathToStr (FileContext->DevicePath); + + MenuEntry->HelpString = UiDevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Load File [%s]", + TempStr + ); + + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoLoadFileHandles != 0) { + FreePool (LoadFileHandle); + } + + // + // Add Legacy Boot Option Support Here + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **) &LegacyBios + ); + if (!EFI_ERROR (Status)) { + + for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->IsBootLegacy = TRUE; + DeviceType = (UINT16) Index; + BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevicePathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength ( + &BbsDevicePathNode.Header, + sizeof (BBS_BBS_DEVICE_PATH) + ); + BbsDevicePathNode.DeviceType = DeviceType; + BbsDevicePathNode.StatusFlag = 0; + BbsDevicePathNode.String[0] = 0; + DevicePath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode + ); + + FileContext->DevicePath = DevicePath; + MenuEntry->HelpString = UiDevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Boot Legacy [%s]", + TempStr + ); + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + // + // Remember how many file system options are here + // + FsOptionMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +/** + Free resources allocated in Allocate Rountine. + + @param FreeMenu Menu to be freed +**/ +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ) +{ + BM_MENU_ENTRY *MenuEntry; + while (!IsListEmpty (&FreeMenu->Head)) { + MenuEntry = CR ( + FreeMenu->Head.ForwardLink, + BM_MENU_ENTRY, + Link, + BM_MENU_ENTRY_SIGNATURE + ); + RemoveEntryList (&MenuEntry->Link); + BOpt_DestroyMenuEntry (MenuEntry); + } + FreeMenu->MenuNumber = 0; +} + +/** + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + + @param CallbackData The BMM context data. + @param MenuEntry The Menu Entry. + + @retval EFI_SUCCESS Get files from current dir successfully. + @return Other value if can't get files from current dir. + +**/ +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +{ + EFI_FILE_HANDLE NewDir; + EFI_FILE_HANDLE Dir; + EFI_FILE_INFO *DirInfo; + UINTN BufferSize; + UINTN DirBufferSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *FileContext; + BM_FILE_CONTEXT *NewFileContext; + UINTN Pass; + EFI_STATUS Status; + UINTN OptionNumber; + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + Dir = FileContext->FHandle; + OptionNumber = 0; + // + // Open current directory to get files from it + // + Status = Dir->Open ( + Dir, + &NewDir, + FileContext->FileName, + EFI_FILE_READ_ONLY, + 0 + ); + if (!FileContext->IsRoot) { + Dir->Close (Dir); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + DirInfo = EfiLibFileInfo (NewDir); + if (DirInfo == NULL) { + return EFI_NOT_FOUND; + } + + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + return EFI_INVALID_PARAMETER; + } + + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + + DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; + DirInfo = AllocateZeroPool (DirBufferSize); + if (DirInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get all files in current directory + // Pass 1 to get Directories + // Pass 2 to get files that are EFI images + // + for (Pass = 1; Pass <= 2; Pass++) { + NewDir->SetPosition (NewDir, 0); + for (;;) { + BufferSize = DirBufferSize; + Status = NewDir->Read (NewDir, &BufferSize, DirInfo); + if (EFI_ERROR (Status) || BufferSize == 0) { + break; + } + + if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) || + ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1) + ) { + // + // Pass 1 is for Directories + // Pass 2 is for file names + // + continue; + } + + if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) { + // + // Slip file unless it is a directory entry or a .EFI file + // + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + NewFileContext->Handle = FileContext->Handle; + NewFileContext->FileName = BOpt_AppendFileName ( + FileContext->FileName, + DirInfo->FileName + ); + NewFileContext->FHandle = NewDir; + NewFileContext->DevicePath = FileDevicePath ( + NewFileContext->Handle, + NewFileContext->FileName + ); + NewMenuEntry->HelpString = NULL; + + MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + FileOptionStrDepository + ); + + NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); + + if (NewFileContext->IsDir) { + BufferSize = StrLen (DirInfo->FileName) * 2 + 6; + NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); + + UnicodeSPrint ( + NewMenuEntry->DisplayString, + BufferSize, + L"<%s>", + DirInfo->FileName + ); + + } else { + NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); + } + + NewFileContext->IsRoot = FALSE; + NewFileContext->IsLoadFile = FALSE; + NewFileContext->IsRemovableMedia = FALSE; + + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); + } + } + + DirectoryMenu.MenuNumber = OptionNumber; + FreePool (DirInfo); + return EFI_SUCCESS; +} + +/** + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION. + + @param CallbackData The BMM context data. + + @return EFI_NOT_FOUND Fail to find "BootOrder" variable. + @return EFI_SUCESS Success build boot option menu. + +**/ +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINT16 BootString[10]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN BootOptionSize; + BOOLEAN BootNextFlag; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 *BootNext; + UINTN BootNextSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN MenuCount; + UINT8 *Ptr; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + + MenuCount = 0; + BootOrderListSize = 0; + BootNextSize = 0; + BootOrderList = NULL; + BootNext = NULL; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&BootOptionMenu); + InitializeListHead (&BootOptionMenu.Head); + + // + // Get the BootOrder from the Var + // + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); + if (BootOrderList == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get the BootNext from the Var + // + GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize); + if (BootNext != NULL) { + if (BootNextSize != sizeof (UINT16)) { + FreePool (BootNext); + BootNext = NULL; + } + } + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + // + // Don't display the hidden/inactive boot option + // + if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { + continue; + } + + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); + // + // Get all loadoptions from the VAR + // + GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize); + if (LoadOptionFromVar == NULL) { + continue; + } + + LoadOption = AllocateZeroPool (BootOptionSize); + if (LoadOption == NULL) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize); + FreePool (LoadOptionFromVar); + + if (BootNext != NULL) { + BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); + } else { + BootNextFlag = FALSE; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + ASSERT (NULL != NewMenuEntry); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + BootOptionSize; + + NewMenuEntry->OptionNumber = BootOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsBootNext = BootNextFlag; + + // + // Is a Legacy Device? + // + Ptr = (UINT8 *) LoadOption; + + // + // Attribute = *(UINT32 *)Ptr; + // + Ptr += sizeof (UINT32); + + // + // FilePathSize = *(UINT16 *)Ptr; + // + Ptr += sizeof (UINT16); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + NewLoadContext->IsLegacy = TRUE; + } else { + NewLoadContext->IsLegacy = FALSE; + } + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = BootOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize((UINT16*)LoadOptionPtr); + + NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr)); + ASSERT (NewLoadContext->Description != NULL); + StrCpy (NewLoadContext->Description, (UINT16*)LoadOptionPtr); + + ASSERT (NewLoadContext->Description != NULL); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = BootOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + MenuCount++; + } + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + if (BootNext != NULL) { + FreePool (BootNext); + } + if (BootOrderList != NULL) { + FreePool (BootOrderList); + } + BootOptionMenu.MenuNumber = MenuCount; + return EFI_SUCCESS; +} + +/** + + Append file name to existing file name. + + @param Str1 The existing file name + @param Str2 The file name to be appended + + @return Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +**/ +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +{ + UINTN Size1; + UINTN Size2; + CHAR16 *Str; + CHAR16 *TmpStr; + CHAR16 *Ptr; + CHAR16 *LastSlash; + + Size1 = StrSize (Str1); + Size2 = StrSize (Str2); + Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (Str != NULL); + + TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (TmpStr != NULL); + + StrCat (Str, Str1); + if (!((*Str == '\\') && (*(Str + 1) == 0))) { + StrCat (Str, L"\\"); + } + + StrCat (Str, Str2); + + Ptr = Str; + LastSlash = Str; + while (*Ptr != 0) { + if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') { + // + // Convert "\Name\..\" to "\" + // DO NOT convert the .. if it is at the end of the string. This will + // break the .. behavior in changing directories. + // + + // + // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpy (TmpStr, Ptr + 3); + StrCpy (LastSlash, TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { + // + // Convert a "\.\" to a "\" + // + + // + // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpy (TmpStr, Ptr + 2); + StrCpy (Ptr, TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\') { + LastSlash = Ptr; + } + + Ptr++; + } + + FreePool (TmpStr); + + return Str; +} + +/** + + Check whether current FileName point to a valid + Efi Image File. + + @param FileName File need to be checked. + + @retval TRUE Is Efi Image + @retval FALSE Not a valid Efi Image + +**/ +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ) +{ + // + // Search for ".efi" extension + // + while (*FileName != L'\0') { + if (FileName[0] == '.') { + if (FileName[1] == 'e' || FileName[1] == 'E') { + if (FileName[2] == 'f' || FileName[2] == 'F') { + if (FileName[3] == 'i' || FileName[3] == 'I') { + return TRUE; + } else if (FileName[3] == 0x0000) { + return FALSE; + } + } else if (FileName[2] == 0x0000) { + return FALSE; + } + } else if (FileName[1] == 0x0000) { + return FALSE; + } + } + + FileName += 1; + } + + return FALSE; +} + +/** + + Check whether current FileName point to a valid Efi Application + + @param Dir Pointer to current Directory + @param FileName Pointer to current File name. + + @retval TRUE Is a valid Efi Application + @retval FALSE not a valid Efi Application + +**/ +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ) +{ + UINTN BufferSize; + EFI_IMAGE_DOS_HEADER DosHdr; + UINT16 Subsystem; + EFI_FILE_HANDLE File; + EFI_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; + + Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); + File->Read (File, &BufferSize, &DosHdr); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + File->Close (File); + return FALSE; + } + + File->SetPosition (File, DosHdr.e_lfanew); + BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + File->Read (File, &BufferSize, &PeHdr); + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + File->Close (File); + return FALSE; + } + // + // Determine PE type and read subsytem + // + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem; + } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; + } else { + return FALSE; + } + + if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + File->Close (File); + return TRUE; + } else { + File->Close (File); + return FALSE; + } +} + +/** + + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + + @retval EFI_SUCCESS The function complets successfully. + @return Other value if failed to build the DriverMenu. + +**/ +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +{ + UINTN NoDevicePathHandles; + EFI_HANDLE *DevicePathHandle; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + BM_HANDLE_CONTEXT *NewHandleContext; + EFI_HANDLE CurHandle; + UINTN OptionNumber; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + + SimpleFs = NULL; + LoadFile = NULL; + + InitializeListHead (&DriverMenu.Head); + + // + // At first, get all handles that support Device Path + // protocol which is the basic requirement for + // Driver#### + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &NoDevicePathHandles, + &DevicePathHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OptionNumber = 0; + for (Index = 0; Index < NoDevicePathHandles; Index++) { + CurHandle = DevicePathHandle[Index]; + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &SimpleFs + ); + if (Status == EFI_SUCCESS) { + continue; + } + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiLoadFileProtocolGuid, + (VOID **) &LoadFile + ); + if (Status == EFI_SUCCESS) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + FreePool (DevicePathHandle); + return EFI_OUT_OF_RESOURCES; + } + + NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + NewHandleContext->Handle = CurHandle; + NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); + NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath); + NewMenuEntry->HelpString = NULL; + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); + + } + + if (DevicePathHandle != NULL) { + FreePool (DevicePathHandle); + } + + DriverMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +/** + + Get the Option Number that has not been allocated for use. + + @param Type The type of Option. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetOptionNumber ( + CHAR16 *Type + ) +{ + UINT16 *OrderList; + UINTN OrderListSize; + UINTN Index; + CHAR16 StrTemp[20]; + UINT16 *OptionBuffer; + UINT16 OptionNumber; + UINTN OptionSize; + + OrderListSize = 0; + OrderList = NULL; + OptionNumber = 0; + Index = 0; + + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type); + + GetEfiGlobalVariable2 (StrTemp, (VOID **) &OrderList, &OrderListSize); + for (OptionNumber = 0; ; OptionNumber++) { + if (OrderList != NULL) { + for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) { + if (OptionNumber == OrderList[Index]) { + break; + } + } + } + + if (Index < OrderListSize / sizeof (UINT16)) { + // + // The OptionNumber occurs in the OrderList, continue to use next one + // + continue; + } + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber); + DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp)); + GetEfiGlobalVariable2 (StrTemp, (VOID **) &OptionBuffer, &OptionSize); + if (NULL == OptionBuffer) { + // + // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it + // + break; + } + } + + return OptionNumber; +} + +/** + + Get the Option Number for Boot#### that does not used. + + @return The available Option Number. + +**/ +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ) +{ + return BOpt_GetOptionNumber (L"Boot"); +} + +/** + + Get the Option Number for Driver#### that does not used. + + @return The unused Option Number. + +**/ +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ) +{ + return BOpt_GetOptionNumber (L"Driver"); +} + +/** + + Build up all DriverOptionMenu + + @param CallbackData The BMM context data. + + @retval EFI_SUCESS The functin completes successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation. + @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable. + +**/ +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINT16 DriverString[12]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN DriverOptionSize; + + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + DriverOptionSize = 0; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&DriverOptionMenu); + InitializeListHead (&DriverOptionMenu.Head); + // + // Get the DriverOrder from the Var + // + GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); + if (DriverOrderList == NULL) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + DriverOrderList[Index] + ); + // + // Get all loadoptions from the VAR + // + GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize); + if (LoadOptionFromVar == NULL) { + continue; + } + + LoadOption = AllocateZeroPool (DriverOptionSize); + if (LoadOption == NULL) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize); + FreePool (LoadOptionFromVar); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + DriverOptionSize; + NewMenuEntry->OptionNumber = DriverOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsLegacy = FALSE; + + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = DriverOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = DriverOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + + } + + if (DriverOrderList != NULL) { + FreePool (DriverOrderList); + } + DriverOptionMenu.MenuNumber = Index; + return EFI_SUCCESS; + +} + +/** + Get option number according to Boot#### and BootOrder variable. + The value is saved as #### + 1. + + @param CallbackData The BMM context data. +**/ +VOID +GetBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BMM_FAKE_NV_DATA *BmmConfig; + UINT16 Index; + UINT16 OptionOrderIndex; + UINTN DeviceType; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + ASSERT (CallbackData != NULL); + + DeviceType = (UINTN) -1; + BmmConfig = &CallbackData->BmmFakeNvData; + ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder)); + + for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) && + (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsLegacy) { + if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { + DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; + } else { + // + // Only show one legacy boot option for the same device type + // assuming the boot options are grouped by the device type + // + continue; + } + } + BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); + } +} + +/** + Get driver option order from globalc DriverOptionMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +GetDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BMM_FAKE_NV_DATA *BmmConfig; + UINT16 Index; + UINT16 OptionOrderIndex; + UINTN DeviceType; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + + ASSERT (CallbackData != NULL); + + DeviceType = (UINTN) -1; + BmmConfig = &CallbackData->BmmFakeNvData; + ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder)); + + for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) && + (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0])))); + Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsLegacy) { + if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) { + DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType; + } else { + // + // Only show one legacy boot option for the same device type + // assuming the boot options are grouped by the device type + // + continue; + } + } + BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1); + } +} + + diff --git a/MdeModulePkg/Application/UiApp/BootMaint/ConsoleOption.c b/MdeModulePkg/Application/UiApp/BootMaint/ConsoleOption.c new file mode 100644 index 0000000000..5407207dc8 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/ConsoleOption.c @@ -0,0 +1,995 @@ +/** @file + handles console redirection from boot manager + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + + +/** + Function compares a device path data structure to that of all the nodes of a + second device path instance. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @retval TRUE If the Single device path is contained within Multi device path. + @retval FALSE The Single device path is not match within Multi device path. + +**/ +BOOLEAN +MatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + + if (Multi == NULL || Single == NULL) { + return FALSE; + } + + DevicePath = Multi; + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + + // + // Search for the match of 'Single' in 'Multi' + // + while (DevicePathInst != NULL) { + // + // If the single device path is found in multiple device paths, + // return success + // + if (CompareMem (Single, DevicePathInst, Size) == 0) { + FreePool (DevicePathInst); + return TRUE; + } + + FreePool (DevicePathInst); + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + } + + return FALSE; +} + +/** + Check whether the device path node is ISA Serial Node. + + @param Acpi Device path node to be checked + + @retval TRUE It's ISA Serial Node. + @retval FALSE It's NOT ISA Serial Node. + +**/ +BOOLEAN +IsIsaSerialNode ( + IN ACPI_HID_DEVICE_PATH *Acpi + ) +{ + return (BOOLEAN) ( + (DevicePathType (Acpi) == ACPI_DEVICE_PATH) && + (DevicePathSubType (Acpi) == ACPI_DP) && + (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501)) + ); +} + +/** + Update Com Ports attributes from DevicePath + + @param DevicePath DevicePath that contains Com ports + + @retval EFI_SUCCESS The update is successful. + +**/ +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Update the multi-instance device path of Terminal Device based on + the global TerminalMenu. If ChangeTernimal is TRUE, the terminal + device path in the Terminal Device in TerminalMenu is also updated. + + @param DevicePath The multi-instance device path. + @param ChangeTerminal TRUE, then device path in the Terminal Device + in TerminalMenu is also updated; FALSE, no update. + + @return EFI_SUCCESS The function completes successfully. + +**/ +EFI_STATUS +ChangeTerminalDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN ChangeTerminal + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *Node1; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN Com; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + // + // Change the device path in the ComPort + // + if (ChangeTerminal) { + Node1 = NewTerminalContext->DevicePath; + Node1 = NextDevicePathNode (Node1); + while (!IsDevicePathEnd (Node1)) { + if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) { + Uart1 = (UART_DEVICE_PATH *) Node1; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + break; + } + // + // end if + // + Node1 = NextDevicePathNode (Node1); + } + // + // end while + // + break; + } + } + + Node = NextDevicePathNode (Node); + } + + return EFI_SUCCESS; + +} + +/** + Update the device path that describing a terminal device + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + + @param DevicePath terminal device's path + +**/ +VOID +ChangeVariableDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UINTN Com; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + Com + ); + ASSERT (NewMenuEntry != NULL); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + } + + Node = NextDevicePathNode (Node); + } +} + +/** + Retrieve ACPI UID of UART from device path + + @param Handle The handle for the UART device. + @param AcpiUid The ACPI UID on output. + + @retval TRUE Find valid UID from device path + @retval FALSE Can't find + +**/ +BOOLEAN +RetrieveUartUid ( + IN EFI_HANDLE Handle, + IN OUT UINT32 *AcpiUid + ) +{ + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Acpi = NULL; + for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) { + break; + } + // + // Acpi points to the node before the Uart node + // + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + if (AcpiUid != NULL) { + CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32)); + } + return TRUE; + } else { + return FALSE; + } +} + +/** + Sort Uart handles array with Acpi->UID from low to high. + + @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer + @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count +**/ +VOID +SortedUartHandle ( + IN EFI_HANDLE *Handles, + IN UINTN NoHandles + ) +{ + UINTN Index1; + UINTN Index2; + UINTN Position; + UINT32 AcpiUid1; + UINT32 AcpiUid2; + UINT32 TempAcpiUid; + EFI_HANDLE TempHandle; + + for (Index1 = 0; Index1 < NoHandles-1; Index1++) { + if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) { + continue; + } + TempHandle = Handles[Index1]; + Position = Index1; + TempAcpiUid = AcpiUid1; + + for (Index2 = Index1+1; Index2 < NoHandles; Index2++) { + if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) { + continue; + } + if (AcpiUid2 < TempAcpiUid) { + TempAcpiUid = AcpiUid2; + TempHandle = Handles[Index2]; + Position = Index2; + } + } + Handles[Position] = Handles[Index1]; + Handles[Index1] = TempHandle; + } +} + +/** + Test whether DevicePath is a valid Terminal + + + @param DevicePath DevicePath to be checked + @param Termi If DevicePath is valid Terminal, terminal type is returned. + @param Com If DevicePath is valid Terminal, Com Port type is returned. + + @retval TRUE If DevicePath point to a Terminal. + @retval FALSE If DevicePath does not point to a Terminal. + +**/ +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ); + +/** + Build a list containing all serial devices. + + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_UNSUPPORTED No serial ports present. + +**/ +EFI_STATUS +LocateSerialIo ( + VOID + ) +{ + UINTN Index; + UINTN Index2; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + VENDOR_DEVICE_PATH Vendor; + + // + // Get all handles that have SerialIo protocol installed + // + InitializeListHead (&TerminalMenu.Head); + TerminalMenu.MenuNumber = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSerialIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + // + // No serial ports present + // + return EFI_UNSUPPORTED; + } + + // + // Sort Uart handles array with Acpi->UID from low to high + // then Terminal menu can be built from low Acpi->UID to high Acpi->UID + // + SortedUartHandle (Handles, NoHandles); + + for (Index = 0; Index < NoHandles; Index++) { + // + // Check to see whether the handle has DevicePath Protocol installed + // + gBS->HandleProtocol ( + Handles[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + + Acpi = NULL; + for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + break; + } + // + // Acpi points to the node before Uart node + // + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); + if (NewMenuEntry == NULL) { + FreePool (Handles); + return EFI_OUT_OF_RESOURCES; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); + NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath); + // + // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! + // coz' the misc data for each platform is not correct, actually it's the device path stored in + // datahub which is not completed, so a searching for end of device path will enter a + // dead-loop. + // + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = UiDevicePathToStr (DevicePath); + } + + NewMenuEntry->HelpString = NULL; + + gBS->HandleProtocol ( + Handles[Index], + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo + ); + + CopyMem ( + &NewTerminalContext->BaudRate, + &SerialIo->Mode->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &SerialIo->Mode->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &SerialIo->Mode->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &SerialIo->Mode->StopBits, + sizeof (UINT8) + ); + InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); + TerminalMenu.MenuNumber++; + } + } + if (Handles != NULL) { + FreePool (Handles); + } + + // + // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var + // + OutDevicePath = GetEfiGlobalVariable (L"ConOut"); + InpDevicePath = GetEfiGlobalVariable (L"ConIn"); + ErrDevicePath = GetEfiGlobalVariable (L"ErrOut"); + if (OutDevicePath != NULL) { + UpdateComAttributeFromVariable (OutDevicePath); + } + + if (InpDevicePath != NULL) { + UpdateComAttributeFromVariable (InpDevicePath); + } + + if (ErrDevicePath != NULL) { + UpdateComAttributeFromVariable (ErrDevicePath); + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->TerminalType = 0; + NewTerminalContext->IsConIn = FALSE; + NewTerminalContext->IsConOut = FALSE; + NewTerminalContext->IsStdErr = FALSE; + + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + for (Index2 = 0; Index2 < 4; Index2++) { + CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + NewDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + if (NewMenuEntry->HelpString != NULL) { + FreePool (NewMenuEntry->HelpString); + } + // + // NewMenuEntry->HelpString = UiDevicePathToStr (NewDevicePath); + // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; + // + NewMenuEntry->HelpString = NULL; + + if (MatchDevicePaths (OutDevicePath, NewDevicePath)) { + NewTerminalContext->IsConOut = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (MatchDevicePaths (InpDevicePath, NewDevicePath)) { + NewTerminalContext->IsConIn = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (MatchDevicePaths (ErrDevicePath, NewDevicePath)) { + NewTerminalContext->IsStdErr = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + } + } + + return EFI_SUCCESS; +} + +/** + Update Com Ports attributes from DevicePath + + @param DevicePath DevicePath that contains Com ports + + @retval EFI_SUCCESS The update is successful. + @retval EFI_NOT_FOUND Can not find specific menu entry +**/ +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *SerialNode; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN TerminalNumber; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINTN Index; + + Node = DevicePath; + Node = NextDevicePathNode (Node); + TerminalNumber = 0; + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + while (!IsDevicePathEnd (Node)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (IsIsaSerialNode (Acpi)) { + CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem ( + &NewTerminalContext->BaudRate, + &Uart->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &Uart->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &Uart->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &Uart->StopBits, + sizeof (UINT8) + ); + + SerialNode = NewTerminalContext->DevicePath; + SerialNode = NextDevicePathNode (SerialNode); + while (!IsDevicePathEnd (SerialNode)) { + if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { + // + // Update following device paths according to + // previous acquired uart attributes + // + Uart1 = (UART_DEVICE_PATH *) SerialNode; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + + break; + } + + SerialNode = NextDevicePathNode (SerialNode); + } + // + // end while + // + } + + Node = NextDevicePathNode (Node); + } + // + // end while + // + } + + return EFI_SUCCESS; +} + +/** + Build up Console Menu based on types passed in. The type can + be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT + and BM_CONSOLE_ERR_CONTEXT_SELECT. + + @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT + and BM_CONSOLE_ERR_CONTEXT_SELECT. + + @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. + @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", + "ConInDev" or "ConErrDev" doesn't exists. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. + @retval EFI_SUCCESS Function completes successfully. + +**/ +EFI_STATUS +GetConsoleMenu ( + IN UINTN ConsoleMenuType + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; + EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + UINTN AllCount; + UINTN Index; + UINTN Index2; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + TYPE_OF_TERMINAL Terminal; + UINTN Com; + BM_MENU_OPTION *ConsoleMenu; + + DevicePath = NULL; + AllDevicePath = NULL; + AllCount = 0; + switch (ConsoleMenuType) { + case BM_CONSOLE_IN_CONTEXT_SELECT: + ConsoleMenu = &ConsoleInpMenu; + DevicePath = GetEfiGlobalVariable (L"ConIn"); + AllDevicePath = GetEfiGlobalVariable (L"ConInDev"); + break; + + case BM_CONSOLE_OUT_CONTEXT_SELECT: + ConsoleMenu = &ConsoleOutMenu; + DevicePath = GetEfiGlobalVariable (L"ConOut"); + AllDevicePath = GetEfiGlobalVariable (L"ConOutDev"); + break; + + case BM_CONSOLE_ERR_CONTEXT_SELECT: + ConsoleMenu = &ConsoleErrMenu; + DevicePath = GetEfiGlobalVariable (L"ErrOut"); + AllDevicePath = GetEfiGlobalVariable (L"ErrOutDev"); + break; + + default: + return EFI_UNSUPPORTED; + } + + if (NULL == AllDevicePath) { + return EFI_NOT_FOUND; + } + + InitializeListHead (&ConsoleMenu->Head); + + AllCount = EfiDevicePathInstanceCount (AllDevicePath); + ConsoleMenu->MenuNumber = 0; + // + // Following is menu building up for Console Devices selected. + // + MultiDevicePath = AllDevicePath; + Index2 = 0; + for (Index = 0; Index < AllCount; Index++) { + DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewMenuEntry->OptionNumber = Index2; + + NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); + ASSERT (NewConsoleContext->DevicePath != NULL); + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = UiDevicePathToStr (NewConsoleContext->DevicePath); + } + + NewConsoleContext->IsTerminal = IsTerminalDevicePath ( + NewConsoleContext->DevicePath, + &Terminal, + &Com + ); + + NewConsoleContext->IsActive = MatchDevicePaths ( + DevicePath, + NewConsoleContext->DevicePath + ); + + if (NewConsoleContext->IsTerminal) { + BOpt_DestroyMenuEntry (NewMenuEntry); + } else { + Index2++; + ConsoleMenu->MenuNumber++; + InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); + } + } + + return EFI_SUCCESS; +} + +/** + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. + +**/ +EFI_STATUS +GetAllConsoles ( + VOID + ) +{ + GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT); + return EFI_SUCCESS; +} + +/** + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + + @retval EFI_SUCCESS The function always complete successfully. +**/ +EFI_STATUS +FreeAllConsoles ( + VOID + ) +{ + BOpt_FreeMenu (&ConsoleOutMenu); + BOpt_FreeMenu (&ConsoleInpMenu); + BOpt_FreeMenu (&ConsoleErrMenu); + BOpt_FreeMenu (&TerminalMenu); + return EFI_SUCCESS; +} + +/** + Test whether DevicePath is a valid Terminal + + + @param DevicePath DevicePath to be checked + @param Termi If DevicePath is valid Terminal, terminal type is returned. + @param Com If DevicePath is valid Terminal, Com Port type is returned. + + @retval TRUE If DevicePath point to a Terminal. + @retval FALSE If DevicePath does not point to a Terminal. + +**/ +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ) +{ + BOOLEAN IsTerminal; + EFI_DEVICE_PATH_PROTOCOL *Node; + VENDOR_DEVICE_PATH *Vendor; + UART_DEVICE_PATH *Uart; + ACPI_HID_DEVICE_PATH *Acpi; + + IsTerminal = FALSE; + + Uart = NULL; + Vendor = NULL; + Acpi = NULL; + for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { + // + // Vendor points to the node before the End node + // + Vendor = (VENDOR_DEVICE_PATH *) Node; + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + } + + if (Uart == NULL) { + // + // Acpi points to the node before the UART node + // + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + } + } + + if (Vendor == NULL || + DevicePathType (Vendor) != MESSAGING_DEVICE_PATH || + DevicePathSubType (Vendor) != MSG_VENDOR_DP || + Uart == NULL) { + return FALSE; + } + + // + // There are four kinds of Terminal types + // check to see whether this devicepath + // is one of that type + // + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[0])) { + *Termi = TerminalTypePcAnsi; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[1])) { + *Termi = TerminalTypeVt100; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[2])) { + *Termi = TerminalTypeVt100Plus; + IsTerminal = TRUE; + } else { + if (CompareGuid (&Vendor->Guid, &TerminalTypeGuid[3])) { + *Termi = TerminalTypeVtUtf8; + IsTerminal = TRUE; + } else { + IsTerminal = FALSE; + } + } + } + } + + if (!IsTerminal) { + return FALSE; + } + + if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { + CopyMem (Com, &Acpi->UID, sizeof (UINT32)); + } else { + return FALSE; + } + + return TRUE; +} + +/** + Get mode number according to column and row + + @param CallbackData The BMM context data. +**/ +VOID +GetConsoleOutMode ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Col; + UINTN Row; + UINTN CurrentCol; + UINTN CurrentRow; + UINTN Mode; + UINTN MaxMode; + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + + ConOut = gST->ConOut; + MaxMode = (UINTN) (ConOut->Mode->MaxMode); + + CurrentCol = PcdGet32 (PcdSetupConOutColumn); + CurrentRow = PcdGet32 (PcdSetupConOutRow); + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (!EFI_ERROR(Status)) { + if (CurrentCol == Col && CurrentRow == Row) { + CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode; + break; + } + } + } +} diff --git a/MdeModulePkg/Application/UiApp/BootMaint/Data.c b/MdeModulePkg/Application/UiApp/BootMaint/Data.c new file mode 100644 index 0000000000..9c7256f9ed --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/Data.c @@ -0,0 +1,274 @@ +/** @file + Define some data used for Boot Maint + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +VOID *mStartOpCodeHandle = NULL; +VOID *mEndOpCodeHandle = NULL; +EFI_IFR_GUID_LABEL *mStartLabel = NULL; +EFI_IFR_GUID_LABEL *mEndLabel = NULL; + +STRING_DEPOSITORY *FileOptionStrDepository; +STRING_DEPOSITORY *ConsoleOptionStrDepository; +STRING_DEPOSITORY *BootOptionStrDepository; +STRING_DEPOSITORY *BootOptionHelpStrDepository; +STRING_DEPOSITORY *DriverOptionStrDepository; +STRING_DEPOSITORY *DriverOptionHelpStrDepository; +STRING_DEPOSITORY *TerminalStrDepository; + +/// +/// Terminal type string token storage +/// +UINT16 TerminalType[] = { + STRING_TOKEN(STR_COM_TYPE_0), + STRING_TOKEN(STR_COM_TYPE_1), + STRING_TOKEN(STR_COM_TYPE_2), + STRING_TOKEN(STR_COM_TYPE_3), +}; + +/// +/// File system selection menu +/// +BM_MENU_OPTION FsOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Console Input Device Selection Menu +/// +BM_MENU_OPTION ConsoleInpMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Console Output Device Selection Menu +/// +BM_MENU_OPTION ConsoleOutMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Error Output Device Selection Menu +/// +BM_MENU_OPTION ConsoleErrMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Boot Option from variable Menu +/// +BM_MENU_OPTION BootOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Driver Option from variable menu +/// +BM_MENU_OPTION DriverOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Files and sub-directories in current directory menu +/// +BM_MENU_OPTION DirectoryMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Handles in current system selection menu +/// +BM_MENU_OPTION DriverMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +BM_MENU_OPTION TerminalMenu = { + BM_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Value and string token correspondency for BaudRate +/// +COM_ATTR BaudRateList[19] = { + { + 115200, + STRING_TOKEN(STR_COM_BAUD_RATE_0) + }, + { + 57600, + STRING_TOKEN(STR_COM_BAUD_RATE_1) + }, + { + 38400, + STRING_TOKEN(STR_COM_BAUD_RATE_2) + }, + { + 19200, + STRING_TOKEN(STR_COM_BAUD_RATE_3) + }, + { + 9600, + STRING_TOKEN(STR_COM_BAUD_RATE_4) + }, + { + 7200, + STRING_TOKEN(STR_COM_BAUD_RATE_5) + }, + { + 4800, + STRING_TOKEN(STR_COM_BAUD_RATE_6) + }, + { + 3600, + STRING_TOKEN(STR_COM_BAUD_RATE_7) + }, + { + 2400, + STRING_TOKEN(STR_COM_BAUD_RATE_8) + }, + { + 2000, + STRING_TOKEN(STR_COM_BAUD_RATE_9) + }, + { + 1800, + STRING_TOKEN(STR_COM_BAUD_RATE_10) + }, + { + 1200, + STRING_TOKEN(STR_COM_BAUD_RATE_11) + }, + { + 600, + STRING_TOKEN(STR_COM_BAUD_RATE_12) + }, + { + 300, + STRING_TOKEN(STR_COM_BAUD_RATE_13) + }, + { + 150, + STRING_TOKEN(STR_COM_BAUD_RATE_14) + }, + { + 134, + STRING_TOKEN(STR_COM_BAUD_RATE_15) + }, + { + 110, + STRING_TOKEN(STR_COM_BAUD_RATE_16) + }, + { + 75, + STRING_TOKEN(STR_COM_BAUD_RATE_17) + }, + { + 50, + STRING_TOKEN(STR_COM_BAUD_RATE_18) + } +}; + +/// +/// Value and string token correspondency for DataBits +/// +COM_ATTR DataBitsList[4] = { + { + 5, + STRING_TOKEN(STR_COM_DATA_BITS_0) + }, + { + 6, + STRING_TOKEN(STR_COM_DATA_BITS_1) + }, + { + 7, + STRING_TOKEN(STR_COM_DATA_BITS_2) + }, + { + 8, + STRING_TOKEN(STR_COM_DATA_BITS_3) + } +}; + +/// +/// Value and string token correspondency for Parity +/// +COM_ATTR ParityList[5] = { + { + NoParity, + STRING_TOKEN(STR_COM_PAR_0) + }, + { + EvenParity, + STRING_TOKEN(STR_COM_PAR_1) + }, + { + OddParity, + STRING_TOKEN(STR_COM_PAR_2) + }, + { + MarkParity, + STRING_TOKEN(STR_COM_PAR_3) + }, + { + SpaceParity, + STRING_TOKEN(STR_COM_PAR_4) + } +}; + +/// +/// Value and string token correspondency for Baudreate +/// +COM_ATTR StopBitsList[3] = { + { + OneStopBit, + STRING_TOKEN(STR_COM_STOP_BITS_0) + }, + { + OneFiveStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_1) + }, + { + TwoStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_2) + } +}; + +/// +/// Guid for messaging path, used in Serial port setting. +/// +EFI_GUID TerminalTypeGuid[4] = { + DEVICE_PATH_MESSAGING_PC_ANSI, + DEVICE_PATH_MESSAGING_VT_100, + DEVICE_PATH_MESSAGING_VT_100_PLUS, + DEVICE_PATH_MESSAGING_VT_UTF8 +}; diff --git a/MdeModulePkg/Application/UiApp/BootMaint/FE.vfr b/MdeModulePkg/Application/UiApp/BootMaint/FE.vfr new file mode 100644 index 0000000000..5eca6343bf --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/FE.vfr @@ -0,0 +1,123 @@ +///** @file +// +// File Explorer Formset +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#include "FormGuid.h" + +formset + guid = FILE_EXPLORE_FORMSET_GUID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = FILE_EXPLORE_FORMSET_GUID, + + varstore FILE_EXPLORER_NV_DATA, + varid = VARSTORE_ID_BOOT_MAINT, + name = FeData, + guid = FILE_EXPLORE_FORMSET_GUID; + + form formid = FORM_FILE_EXPLORER_ID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + form formid = FORM_BOOT_ADD_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); + + label FORM_BOOT_ADD_DESCRIPTION_ID; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FeData.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FeData.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_BOOT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT; + + endform; + + form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FeData.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FeData.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + checkbox varid = FeData.ForceReconnect, + prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + flags = CHECKBOX_DEFAULT, + key = 0, + endcheckbox; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset??? + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER; + + endform; + +endformset; \ No newline at end of file diff --git a/MdeModulePkg/Application/UiApp/BootMaint/FileExplorer.c b/MdeModulePkg/Application/UiApp/BootMaint/FileExplorer.c new file mode 100644 index 0000000000..f6fc19278a --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/FileExplorer.c @@ -0,0 +1,327 @@ +/** @file + File explorer related functions. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +/** + Update the File Explore page. + + @param CallbackData The BMM context data. + @param MenuOption Pointer to menu options to display. + +**/ +VOID +UpdateFileExplorePage ( + IN BMM_CALLBACK_DATA *CallbackData, + BM_MENU_OPTION *MenuOption + ) +{ + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + + NewMenuEntry = NULL; + NewFileContext = NULL; + FormId = 0; + + RefreshUpdateData (); + mStartLabel->Number = FORM_FILE_EXPLORER_ID; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsBootLegacy) { + continue; + } + + if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) { + // + // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. + // + HiiCreateActionOpCode ( + mStartOpCodeHandle, + (UINT16) (FILE_OPTION_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } else { + // + // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. + // + if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FormId, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (FILE_OPTION_OFFSET + Index) + ); + } + } + + HiiUpdateForm ( + CallbackData->FeHiiHandle, + &mFileExplorerGuid, + FORM_FILE_EXPLORER_ID, + mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Update the file explower page with the refershed file system. + + + @param CallbackData BMM context data + @param KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ) +{ + UINT16 FileOptionMask; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + BOOLEAN ExitFileExplorer; + EFI_STATUS Status; + + NewMenuEntry = NULL; + NewFileContext = NULL; + ExitFileExplorer = FALSE; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); + + if (FileExplorerDisplayUnknown == CallbackData->FeDisplayContext) { + // + // First in, display file system. + // + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FindFileSystem (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); + + UpdateFileExplorePage (CallbackData, &FsOptionMenu); + + CallbackData->FeDisplayContext = FileExplorerDisplayFileSystem; + } else { + if (FileExplorerDisplayFileSystem == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); + } else if (FileExplorerDisplayDirectory == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsDir ) { + CallbackData->FeDisplayContext = FileExplorerDisplayDirectory; + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_FreeMenu (&DirectoryMenu); + Status = BOpt_FindFiles (CallbackData, NewMenuEntry); + if (EFI_ERROR (Status)) { + ExitFileExplorer = TRUE; + goto exit; + } + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); + BOpt_DestroyMenuEntry (NewMenuEntry); + + UpdateFileExplorePage (CallbackData, &DirectoryMenu); + + } else { + switch (CallbackData->FeCurrentState) { + case FileExplorerStateBootFromFile: + // + // Here boot from file + // + BootThisFile (NewFileContext); + ExitFileExplorer = TRUE; + break; + + case FileExplorerStateAddBootOption: + case FileExplorerStateAddDriverOptionState: + if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + CallbackData->MenuEntry = NewMenuEntry; + CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; + + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (); + mStartLabel->Number = FormId; + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + 0, + 0 + ); + + HiiUpdateForm ( + CallbackData->FeHiiHandle, + &mFileExplorerGuid, + FormId, + mStartOpCodeHandle, // Label FormId + mEndOpCodeHandle // LABEL_END + ); + break; + + default: + break; + } + } + } + exit: + return ExitFileExplorer; +} + +/** + This function processes the results of changes in configuration. + When user select a interactive opcode, this callback will be triggered. + Based on the Question(QuestionId) that triggers the callback, the corresponding + actions is performed. It handles: + + 1) the addition of boot option. + 2) the addition of driver option. + 3) exit from file browser + 4) update of file content if a dir is selected. + 5) boot the file if a file is selected in "boot from file" + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. +**/ +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + BMM_CALLBACK_DATA *Private; + FILE_EXPLORER_NV_DATA *NvRamMap; + EFI_STATUS Status; + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + Private = FE_CALLBACK_DATA_FROM_THIS (This); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + + // + // Retrieve uncommitted data from Form Browser + // + NvRamMap = &Private->FeFakeNvData; + HiiGetBrowserData (&mFileExplorerGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { + // + // Apply changes and exit formset + // + if (FileExplorerStateAddBootOption == Private->FeCurrentState) { + Status = Var_UpdateBootOption (Private, NvRamMap); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetBootOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); + } else if (FileExplorerStateAddDriverOptionState == Private->FeCurrentState) { + Status = Var_UpdateDriverOption ( + Private, + Private->FeHiiHandle, + NvRamMap->DescriptionData, + NvRamMap->OptionalData, + NvRamMap->ForceReconnect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); + } + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { + // + // Discard changes and exit formset + // + NvRamMap->OptionalData[0] = 0x0000; + NvRamMap->DescriptionData[0] = 0x0000; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } else if (QuestionId < FILE_OPTION_OFFSET) { + // + // Exit File Explorer formset + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (QuestionId >= FILE_OPTION_OFFSET) { + UpdateFileExplorer (Private, QuestionId); + } + } + + return Status; +} diff --git a/MdeModulePkg/Application/UiApp/BootMaint/FormGuid.h b/MdeModulePkg/Application/UiApp/BootMaint/FormGuid.h new file mode 100644 index 0000000000..4b1efb7109 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/FormGuid.h @@ -0,0 +1,204 @@ +/** @file + Formset guids, form id and VarStore data structure for Boot Maintenance Manager. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#ifndef _FORM_GUID_H_ +#define _FORM_GUID_H_ + +#define BOOT_MAINT_FORMSET_GUID \ + { \ + 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \ + } + +#define FILE_EXPLORE_FORMSET_GUID \ + { \ + 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \ + } + +#define FORM_MAIN_ID 0x1001 +#define FORM_BOOT_ADD_ID 0x1002 +#define FORM_BOOT_DEL_ID 0x1003 +#define FORM_BOOT_CHG_ID 0x1004 +#define FORM_DRV_ADD_ID 0x1005 +#define FORM_DRV_DEL_ID 0x1006 +#define FORM_DRV_CHG_ID 0x1007 +#define FORM_CON_MAIN_ID 0x1008 +#define FORM_CON_IN_ID 0x1009 +#define FORM_CON_OUT_ID 0x100A +#define FORM_CON_ERR_ID 0x100B +#define FORM_FILE_SEEK_ID 0x100C +#define FORM_FILE_NEW_SEEK_ID 0x100D +#define FORM_DRV_ADD_FILE_ID 0x100E +#define FORM_DRV_ADD_HANDLE_ID 0x100F +#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010 +#define FORM_BOOT_NEXT_ID 0x1011 +#define FORM_TIME_OUT_ID 0x1012 +#define FORM_BOOT_SETUP_ID 0x1014 +#define FORM_DRIVER_SETUP_ID 0x1015 +#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016 +#define FORM_CON_COM_ID 0x1017 +#define FORM_CON_COM_SETUP_ID 0x1018 +#define FORM_FILE_EXPLORER_ID 0x101E +#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F +#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020 +#define FORM_CON_MODE_ID 0x1021 +#define FORM_MEMORY_CHECK_ID 0x1022 +#define FORM_UEFI_OPTIMIZED_BOOT_ID 0x1023 + +#define MAXIMUM_FORM_ID 0x10FF + +#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101 +#define KEY_VALUE_COM_SET_DATA_BITS 0x1102 +#define KEY_VALUE_COM_SET_STOP_BITS 0x1103 +#define KEY_VALUE_COM_SET_PARITY 0x1104 +#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105 +#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106 +#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107 +#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108 +#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109 +#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A +#define KEY_VALUE_SAVE_AND_EXIT 0x110B +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C +#define KEY_VALUE_BOOT_FROM_FILE 0x110D + +#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF + +// +// Varstore ID defined for Buffer Storage +// +#define VARSTORE_ID_BOOT_MAINT 0x1000 +#define VARSTORE_ID_FILE_EXPLORER 0x1001 + +// +// End Label +// +#define LABEL_BMM_PLATFORM_INFORMATION 0xfffe +#define LABEL_END 0xffff +#define MAX_MENU_NUMBER 100 + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Three questions displayed at the main page + // for Timeout, BootNext, Variables respectively + // + UINT16 BootTimeOut; + UINT16 BootNext; + + // + // This is the COM1 Attributes value storage + // + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + + // + // This is the COM2 Attributes value storage + // + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + + // + // Driver Option Add Handle page storage + // + UINT16 DriverAddHandleDesc[MAX_MENU_NUMBER]; + UINT16 DriverAddHandleOptionalData[MAX_MENU_NUMBER]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + + // + // Console Input/Output/Errorout using COM port check storage + // + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + + // + // At most 100 input/output/errorout device for console storage + // + UINT8 ConsoleCheck[MAX_MENU_NUMBER]; + + // + // Boot or Driver Option Order storage + // The value is the OptionNumber+1 because the order list value cannot be 0 + // Use UINT32 to hold the potential value 0xFFFF+1=0x10000 + // + UINT32 BootOptionOrder[MAX_MENU_NUMBER]; + UINT32 DriverOptionOrder[MAX_MENU_NUMBER]; + // + // Boot or Driver Option Delete storage + // + BOOLEAN BootOptionDel[MAX_MENU_NUMBER]; + BOOLEAN DriverOptionDel[MAX_MENU_NUMBER]; + + // + // This is the Terminal Attributes value storage + // + UINT8 COMBaudRate; + UINT8 COMDataRate; + UINT8 COMStopBits; + UINT8 COMParity; + UINT8 COMTerminalType; + + // + // We use DisableMap array to record the enable/disable state of each boot device + // It should be taken as a bit array, from left to right there are totally 256 bits + // the most left one stands for BBS table item 0, and the most right one stands for item 256 + // If the bit is 1, it means the boot device has been disabled. + // + UINT8 DisableMap[32]; + + // + // Console Output Text Mode + // + UINT16 ConsoleOutMode; + + // + // UINT16 PadArea[10]; + // +} BMM_FAKE_NV_DATA; + +// +// Key used by File Explorer forms +// +#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000 +#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001 +#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002 +#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003 + +/// +/// This is the data structure used by File Explorer formset +/// +typedef struct { + UINT16 DescriptionData[75]; + UINT16 OptionalData[127]; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; + +#endif + diff --git a/MdeModulePkg/Application/UiApp/BootMaint/UpdatePage.c b/MdeModulePkg/Application/UiApp/BootMaint/UpdatePage.c new file mode 100644 index 0000000000..ea96d132e5 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/UpdatePage.c @@ -0,0 +1,1194 @@ +/** @file +Dynamically update the pages. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshUpdateData ( + VOID + ) +{ + // + // Free current updated date + // + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + // + // Create new OpCode Handle + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + + // + // Create Hii Extend Label OpCode as the start opcode + // + mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + +} + +/** + Add a "Go back to main page" tag in front of the form when there are no + "Apply changes" and "Discard changes" tags in the end of the form. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageStart ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (); + mStartLabel->Number = CallbackData->BmmCurrentPageId; + + if (!(CallbackData->BmmAskSaveOrNot)) { + // + // Add a "Go back to main page" tag in front of the form when there are no + // "Apply changes" and "Discard changes" tags in the end of the form. + // + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_MAIN_ID, + STRING_TOKEN (STR_FORM_GOTO_MAIN), + STRING_TOKEN (STR_FORM_GOTO_MAIN), + 0, + FORM_MAIN_ID + ); + } + +} + +/** + Create the "Apply changes" and "Discard changes" tags. And + ensure user can return to the main page. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageEnd ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + // + // Create the "Apply changes" and "Discard changes" tags. + // + if (CallbackData->BmmAskSaveOrNot) { + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 0 + ); + + HiiCreateActionOpCode ( + mStartOpCodeHandle, + KEY_VALUE_SAVE_AND_EXIT, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } + + // + // Ensure user can return to the main page. + // + HiiCreateActionOpCode ( + mStartOpCodeHandle, + KEY_VALUE_NO_SAVE_AND_EXIT, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + + HiiUpdateForm ( + CallbackData->BmmHiiHandle, + &mBootMaintGuid, + CallbackData->BmmCurrentPageId, + mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Clean up the dynamic opcode at label and form specified by both LabelId. + + @param LabelId It is both the Form ID and Label ID for opcode deletion. + @param CallbackData The BMM context data. + +**/ +VOID +CleanUpPage ( + IN UINT16 LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (); + + // + // Remove all op-codes from dynamic page + // + mStartLabel->Number = LabelId; + HiiUpdateForm ( + CallbackData->BmmHiiHandle, + &mBootMaintGuid, + LabelId, + mStartOpCodeHandle, // Label LabelId + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Boot a file selected by user at File Expoloer of BMM. + + @param FileContext The file context data, which contains the device path + of the file to be boot from. + + @retval EFI_SUCCESS The function completed successfull. + @return Other value if the boot from the file fails. + +**/ +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ) +{ + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + EfiBootManagerInitializeLoadOption ( + &BootOption, + 0, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE, + FileContext->FileName, + FileContext->DevicePath, + NULL, + 0 + ); + // + // Since current no boot from removable media directly is allowed */ + // + gST->ConOut->ClearScreen (gST->ConOut); + + BdsSetConsoleMode (FALSE); + EfiBootManagerBoot (&BootOption); + BdsSetConsoleMode (TRUE); + + EfiBootManagerFreeLoadOption (&BootOption); + + return BootOption.Status; + +} + +/** + Create a list of Goto Opcode for all terminal devices logged + by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID. + + @param CallbackData The BMM context data. +**/ +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + + UpdatePageStart (CallbackData); + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_CON_COM_SETUP_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (TERMINAL_OPTION_OFFSET + Index) + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + + IsShellNodeDevicePath checks for the Shell device path. + If it's the shell device path then return TRUE otherwise + return FALSE. + + @param DevicePath The DevicePath to check + + @retval TRUE DevicePath is Shell + @retval FALSE DevicePath is not Shell + +**/ +BOOLEAN +IsShellNodeDevicePath( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + + EFI_DEVICE_PATH_PROTOCOL *Node; + + for (Node = FilePath; !IsDevicePathEnd(Node); Node = NextDevicePathNode(Node)) + { + if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_PIWG_FW_FILE_DP)) { + if (!CompareMem(PcdGetPtr(PcdShellFile), &(((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node)->FvFileName), sizeof(EFI_GUID))) + return TRUE; + } + } + return FALSE; +} + +/** + Create a list of boot option from global BootOptionMenu. It + allow user to delete the boot option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + + //CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0]))); + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsLegacy) { + continue; + } + + // + // Check to see if the current boot option devicepath is the ShellDevice + // path. If it is keep only UEFI Shell in the delete boot option list + // or else continue + // + //if ((NULL != NewLoadContext->FilePathList) && (TRUE == IsShellNodeDevicePath(NewLoadContext->FilePathList))) { + // NewLoadContext->Deleted = FALSE; + // CallbackData->BmmFakeNvData.OptionDel[Index] = FALSE; + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + 0, + 0, + NULL + ); + //} else { + // continue; + //} + } + UpdatePageEnd (CallbackData); +} + +/** + Create a lit of driver option from global DriverMenu. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData); + + for (Index = 0; Index < DriverMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); + + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FORM_DRV_ADD_HANDLE_DESC_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (HANDLE_OPTION_OFFSET + Index) + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create a lit of driver option from global DriverOptionMenu. It + allow user to delete the driver option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu); + + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE; + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + 0, + 0, + NULL + ); + } + + UpdatePageEnd (CallbackData); +} + +/** + Prepare the page to allow user to add description for + a Driver Option. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + + CallbackData->BmmFakeNvData.DriverAddActive = 0x01; + CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00; + CallbackData->BmmAskSaveOrNot = TRUE; + NewMenuEntry = CallbackData->MenuEntry; + + UpdatePageStart (CallbackData); + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + 0, + 0 + ); + + HiiCreateStringOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRV_ADD_HANDLE_DESC_VAR_OFFSET, + STRING_TOKEN (STR_LOAD_OPTION_DESC), + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 6, + 75, + NULL + ); + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRV_ADD_RECON_VAR_OFFSET, + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + 0, + 0, + NULL + ); + + HiiCreateStringOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + DRIVER_ADD_OPTION_VAR_OFFSET, + STRING_TOKEN (STR_OPTIONAL_DATA), + STRING_TOKEN (STR_NULL_STRING), + 0, + 0, + 6, + 75, + NULL + ); + + UpdatePageEnd (CallbackData); +} + +/** + Update console page. + + @param UpdatePageId The form ID to be updated. + @param ConsoleMenu The console menu list. + @param CallbackData The BMM context data. + +**/ +VOID +UpdateConsolePage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *ConsoleMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINT16 Index; + UINT16 Index2; + UINT8 CheckFlags; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \ + (Index < (sizeof (CallbackData->BmmFakeNvData.ConsoleCheck) / sizeof (UINT8)))) ; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + CheckFlags = 0; + if (NewConsoleContext->IsActive) { + CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT; + CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE; + } + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (CON_DEVICE_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + 0, + CheckFlags, + NULL + ); + } + + for (Index2 = 0; ((Index2 < TerminalMenu.MenuNumber) && \ + (Index2 < (sizeof (CallbackData->BmmFakeNvData.ConsoleCheck) / sizeof (UINT8)))); Index2++) { + CheckFlags = 0; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + ASSERT (Index < MAX_MENU_NUMBER); + if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || + ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || + ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) + ) { + CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT; + CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE; + } + + HiiCreateCheckBoxOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index), + VARSTORE_ID_BOOT_MAINT, + (UINT16) (CON_DEVICE_VAR_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + 0, + CheckFlags, + NULL + ); + + Index++; + } + + UpdatePageEnd (CallbackData); +} + +/** + Update the page's NV Map if user has changed the order + a list. This list can be Boot Order or Driver Order. + + @param UpdatePageId The form ID to be updated. + @param OptionMenu The new list. + @param CallbackData The BMM context data. + +**/ +VOID +UpdateOrderPage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *OptionMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT16 OptionIndex; + VOID *OptionsOpCodeHandle; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN BootOptionFound; + UINT32 *OptionOrder; + EFI_QUESTION_ID QuestionId; + UINT16 VarOffset; + + + UpdatePageStart (CallbackData); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + OptionOrder = NULL; + QuestionId = 0; + VarOffset = 0; + switch (UpdatePageId) { + + case FORM_BOOT_CHG_ID: + GetBootOrder (CallbackData); + OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder; + QuestionId = BOOT_OPTION_ORDER_QUESTION_ID; + VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET; + break; + + case FORM_DRV_CHG_ID: + GetDriverOrder (CallbackData); + OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder; + QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID; + VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET; + break; + } + ASSERT (OptionOrder != NULL); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + NewMenuEntry = NULL; + for (OptionIndex = 0; (OptionOrder[OptionIndex] != 0 && OptionIndex < MAX_MENU_NUMBER); OptionIndex++) { + BootOptionFound = FALSE; + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) { + BootOptionFound = TRUE; + break; + } + } + if (BootOptionFound) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_32, + OptionOrder[OptionIndex] + ); + } + } + + if (OptionMenu->MenuNumber > 0) { + HiiCreateOrderedListOpCode ( + mStartOpCodeHandle, // Container for dynamic created opcodes + QuestionId, // Question ID + VARSTORE_ID_BOOT_MAINT, // VarStore ID + VarOffset, // Offset in Buffer Storage + STRING_TOKEN (STR_CHANGE_ORDER), // Question prompt text + STRING_TOKEN (STR_CHANGE_ORDER), // Question help text + 0, // Question flag + 0, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET + EFI_IFR_TYPE_NUM_SIZE_32, // Data type of Question value + 100, // Maximum container + OptionsOpCodeHandle, // Option Opcode list + NULL // Default Opcode is NULL + ); + } + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + UpdatePageEnd (CallbackData); + +} + +/** + Create the dynamic page to allow user to set + the "BootNext" value. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINTN NumberOfOptions; + UINT16 Index; + VOID *OptionsOpCodeHandle; + + NumberOfOptions = BootOptionMenu.MenuNumber; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + if (NumberOfOptions > 0) { + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewLoadContext->IsBootNext) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + CallbackData->BmmFakeNvData.BootNext = Index; + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } + } + + if (CallbackData->BmmFakeNvData.BootNext == Index) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NONE), + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NONE), + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + BOOT_NEXT_VAR_OFFSET, + STRING_TOKEN (STR_BOOT_NEXT), + STRING_TOKEN (STR_BOOT_NEXT_HELP), + 0, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + } + + UpdatePageEnd (CallbackData); +} + +/** + Create the dynamic page to allow user to set the "TimeOut" value. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 BootTimeOut; + VOID *DefaultOpCodeHandle; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + HiiCreateDefaultOpCode (DefaultOpCodeHandle, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_NUM_SIZE_16, BootTimeOut); + + HiiCreateNumericOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + BOOT_TIME_OUT_VAR_OFFSET, + STRING_TOKEN (STR_NUM_AUTO_BOOT), + STRING_TOKEN (STR_HLP_AUTO_BOOT), + 0, + EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC, + 0, + 65535, + 0, + DefaultOpCodeHandle + ); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + + CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut; + + UpdatePageEnd (CallbackData); +} + + +/** + Refresh the text mode page. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateConModePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Mode; + UINTN Index; + UINTN Col; + UINTN Row; + CHAR16 ModeString[50]; + CHAR16 *PStr; + UINTN MaxMode; + UINTN ValidMode; + EFI_STRING_ID *ModeToken; + EFI_STATUS Status; + VOID *OptionsOpCodeHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + + ConOut = gST->ConOut; + Index = 0; + ValidMode = 0; + MaxMode = (UINTN) (ConOut->Mode->MaxMode); + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + // + // Check valid mode + // + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (EFI_ERROR (Status)) { + continue; + } + ValidMode++; + } + + if (ValidMode == 0) { + return; + } + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode); + ASSERT(ModeToken != NULL); + + // + // Determin which mode should be the first entry in menu + // + GetConsoleOutMode (CallbackData); + + // + // Build text mode options + // + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Build mode string Column x Row + // + UnicodeValueToString (ModeString, 0, Col, 0); + PStr = &ModeString[0]; + StrnCat (PStr, L" x ", StrLen(L" x ") + 1); + PStr = PStr + StrLen (PStr); + UnicodeValueToString (PStr , 0, Row, 0); + + ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL); + + if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ModeToken[Index], + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_TYPE_NUM_SIZE_16, + (UINT16) Mode + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ModeToken[Index], + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + (UINT16) Mode + ); + } + Index++; + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) CON_MODE_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + CON_MODE_VAR_OFFSET, + STRING_TOKEN (STR_CON_MODE_SETUP), + STRING_TOKEN (STR_CON_MODE_SETUP), + EFI_IFR_FLAG_RESET_REQUIRED, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + FreePool (ModeToken); + + UpdatePageEnd (CallbackData); +} + +/** + Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits, + Parity, Stop Bits, Terminal Type. + + @param CallbackData The BMM context data. + +**/ +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 Index; + UINT8 CheckFlags; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + VOID *OptionsOpCodeHandle; + + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData); + + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + CallbackData->CurrentTerminal + ); + + if (NewMenuEntry == NULL) { + return ; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) { + CheckFlags = 0; + if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + NewTerminalContext->BaudRateIndex = Index; + CallbackData->BmmFakeNvData.COMBaudRate = NewTerminalContext->BaudRateIndex; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + BaudRateList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + COM_BAUD_RATE_VAR_OFFSET, + STRING_TOKEN (STR_COM_BAUD_RATE), + STRING_TOKEN (STR_COM_BAUD_RATE), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) { + CheckFlags = 0; + + if (NewTerminalContext->DataBits == DataBitsList[Index].Value) { + NewTerminalContext->DataBitsIndex = Index; + CallbackData->BmmFakeNvData.COMDataRate = NewTerminalContext->DataBitsIndex; + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + DataBitsList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + COM_DATA_RATE_VAR_OFFSET, + STRING_TOKEN (STR_COM_DATA_BITS), + STRING_TOKEN (STR_COM_DATA_BITS), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) { + CheckFlags = 0; + if (NewTerminalContext->Parity == ParityList[Index].Value) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + NewTerminalContext->ParityIndex = (UINT8) Index; + CallbackData->BmmFakeNvData.COMParity = NewTerminalContext->ParityIndex; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ParityList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + COM_PARITY_VAR_OFFSET, + STRING_TOKEN (STR_COM_PARITY), + STRING_TOKEN (STR_COM_PARITY), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) { + CheckFlags = 0; + if (NewTerminalContext->StopBits == StopBitsList[Index].Value) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + NewTerminalContext->StopBitsIndex = (UINT8) Index; + CallbackData->BmmFakeNvData.COMStopBits = NewTerminalContext->StopBitsIndex; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + StopBitsList[Index].StringToken, + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + COM_STOP_BITS_VAR_OFFSET, + STRING_TOKEN (STR_COM_STOP_BITS), + STRING_TOKEN (STR_COM_STOP_BITS), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + for (Index = 0; Index < 4; Index++) { + CheckFlags = 0; + if (NewTerminalContext->TerminalType == Index) { + CheckFlags |= EFI_IFR_OPTION_DEFAULT; + CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + (EFI_STRING_ID) TerminalType[Index], + CheckFlags, + EFI_IFR_TYPE_NUM_SIZE_8, + Index + ); + } + + HiiCreateOneOfOpCode ( + mStartOpCodeHandle, + (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID, + VARSTORE_ID_BOOT_MAINT, + COM_TERMINAL_VAR_OFFSET, + STRING_TOKEN (STR_COM_TERMI_TYPE), + STRING_TOKEN (STR_COM_TERMI_TYPE), + 0, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + UpdatePageEnd (CallbackData); +} + +/** + Dispatch the correct update page function to call based on + the UpdatePageId. + + @param UpdatePageId The form ID. + @param CallbackData The BMM context data. + +**/ +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + CleanUpPage (UpdatePageId, CallbackData); + switch (UpdatePageId) { + case FORM_CON_IN_ID: + UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData); + break; + + case FORM_CON_OUT_ID: + UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData); + break; + + case FORM_CON_ERR_ID: + UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData); + break; + + case FORM_BOOT_CHG_ID: + UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData); + break; + + case FORM_DRV_CHG_ID: + UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData); + break; + + default: + break; + } +} + +/** + Dispatch the display to the next page based on NewPageId. + + @param Private The BMM context data. + @param NewPageId The original page ID. + +**/ +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ) +{ + if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) { + // + // If we select a handle to add driver option, advance to the add handle description page. + // + NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID; + } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) { + // + // Return to main page after "Save Changes" or "Discard Changes". + // + NewPageId = FORM_MAIN_ID; + } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) { + NewPageId = FORM_CON_COM_SETUP_ID; + } + + if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) { + Private->BmmPreviousPageId = Private->BmmCurrentPageId; + Private->BmmCurrentPageId = NewPageId; + } +} diff --git a/MdeModulePkg/Application/UiApp/BootMaint/Variable.c b/MdeModulePkg/Application/UiApp/BootMaint/Variable.c new file mode 100644 index 0000000000..cbcd276278 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMaint/Variable.c @@ -0,0 +1,1068 @@ +/** @file + Variable operation that will be used by bootmaint + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootMaint.h" + +/** + Delete Boot Option that represent a Deleted state in BootOptionMenu. + After deleting this boot option, call Var_ChangeBootOrder to + make sure BootOrder is in valid state. + + @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to + BM_LOAD_CONTEXT marked for deletion is deleted. + @retval EFI_NOT_FOUND If can not find the boot option want to be deleted. + @return Others If failed to update the "BootOrder" variable after deletion. + +**/ +EFI_STATUS +Var_DelBootOption ( + VOID + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 BootString[10]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid); + Index2++; + // + // If current Load Option is the same as BootNext, + // must delete BootNext in order to make sure + // there will be no panic on next boot + // + if (NewLoadContext->IsBootNext) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + } + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + BootOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeBootOrder (); + return Status; +} + +/** + After any operation on Boot####, there will be a discrepancy in BootOrder. + Since some are missing but in BootOrder, while some are present but are + not reflected by BootOrder. Then a function rebuild BootOrder from + scratch by content from BootOptionMenu is needed. + + + + + @retval EFI_SUCCESS The boot order is updated successfully. + @return EFI_STATUS other than EFI_SUCCESS if failed to + Set the "BootOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeBootOrder ( + VOID + ) +{ + + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *BootOrderList; + UINT16 *BootOrderListPtr; + UINTN BootOrderListSize; + UINTN Index; + + BootOrderList = NULL; + BootOrderListSize = 0; + + // + // First check whether BootOrder is present in current configuration + // + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); + + // + // If exists, delete it to hold new BootOrder + // + if (BootOrderList != NULL) { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + FreePool (BootOrderList); + BootOrderList = NULL; + } + // + // Maybe here should be some check method to ensure that + // no new added boot options will be added + // but the setup engine now will give only one callback + // that is to say, user are granted only one chance to + // decide whether the boot option will be added or not + // there should be no indictor to show whether this + // is a "new" boot option + // + BootOrderListSize = BootOptionMenu.MenuNumber; + + if (BootOrderListSize > 0) { + BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16)); + ASSERT (BootOrderList != NULL); + BootOrderListPtr = BootOrderList; + + // + // Get all current used Boot#### from BootOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < BootOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + *BootOrderList = (UINT16) NewMenuEntry->OptionNumber; + BootOrderList++; + } + + BootOrderList = BootOrderListPtr; + + // + // After building the BootOrderList, write it back + // + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderListSize * sizeof (UINT16), + BootOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return EFI_SUCCESS; +} + +/** + Delete Load Option that represent a Deleted state in BootOptionMenu. + After deleting this Driver option, call Var_ChangeDriverOrder to + make sure DriverOrder is in valid state. + + @retval EFI_SUCCESS Load Option is successfully updated. + @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted. + @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI + Variable. + +**/ +EFI_STATUS +Var_DelDriverOption ( + VOID + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 DriverString[12]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid); + Index2++; + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + DriverOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeDriverOrder (); + return Status; +} + +/** + After any operation on Driver####, there will be a discrepancy in + DriverOrder. Since some are missing but in DriverOrder, while some + are present but are not reflected by DriverOrder. Then a function + rebuild DriverOrder from scratch by content from DriverOptionMenu is + needed. + + @retval EFI_SUCCESS The driver order is updated successfully. + @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable. + +**/ +EFI_STATUS +Var_ChangeDriverOrder ( + VOID + ) +{ + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *DriverOrderList; + UINT16 *DriverOrderListPtr; + UINTN DriverOrderListSize; + UINTN Index; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + FreePool (DriverOrderList); + DriverOrderList = NULL; + } + + DriverOrderListSize = DriverOptionMenu.MenuNumber; + + if (DriverOrderListSize > 0) { + DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16)); + ASSERT (DriverOrderList != NULL); + DriverOrderListPtr = DriverOrderList; + + // + // Get all current used Driver#### from DriverOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < DriverOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber; + DriverOrderList++; + } + + DriverOrderList = DriverOrderListPtr; + + // + // After building the DriverOrderList, write it back + // + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize * sizeof (UINT16), + DriverOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return EFI_SUCCESS; +} + +/** + Update the device path of "ConOut", "ConIn" and "ErrOut" + based on the new BaudRate, Data Bits, parity and Stop Bits + set. + +**/ +VOID +Var_UpdateAllConsoleOption ( + VOID + ) +{ + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + EFI_STATUS Status; + + OutDevicePath = GetEfiGlobalVariable (L"ConOut"); + InpDevicePath = GetEfiGlobalVariable (L"ConIn"); + ErrDevicePath = GetEfiGlobalVariable (L"ErrOut"); + if (OutDevicePath != NULL) { + ChangeVariableDevicePath (OutDevicePath); + Status = gRT->SetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (OutDevicePath), + OutDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } + + if (InpDevicePath != NULL) { + ChangeVariableDevicePath (InpDevicePath); + Status = gRT->SetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (InpDevicePath), + InpDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } + + if (ErrDevicePath != NULL) { + ChangeVariableDevicePath (ErrDevicePath); + Status = gRT->SetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (ErrDevicePath), + ErrDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } +} + +/** + This function delete and build multi-instance device path for + specified type of console device. + + This function clear the EFI variable defined by ConsoleName and + gEfiGlobalVariableGuid. It then build the multi-instance device + path by appending the device path of the Console (In/Out/Err) instance + in ConsoleMenu. Then it scan all corresponding console device by + scanning Terminal (built from device supporting Serial I/O instances) + devices in TerminalMenu. At last, it save a EFI variable specifed + by ConsoleName and gEfiGlobalVariableGuid. + + @param ConsoleName The name for the console device type. They are + usually "ConIn", "ConOut" and "ErrOut". + @param ConsoleMenu The console memu which is a list of console devices. + @param UpdatePageId The flag specifying which type of console device + to be processed. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateConsoleOption ( + IN UINT16 *ConsoleName, + IN BM_MENU_OPTION *ConsoleMenu, + IN UINT16 UpdatePageId + ) +{ + EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_STATUS Status; + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; + UINTN Index; + + ConDevicePath = GetEfiGlobalVariable (ConsoleName); + if (ConDevicePath != NULL) { + EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); + FreePool (ConDevicePath); + ConDevicePath = NULL; + }; + + // + // First add all console input device from console input menu + // + for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + if (NewConsoleContext->IsActive) { + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + NewConsoleContext->DevicePath + ); + } + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || + ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || + ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) + ) { + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0]))); + CopyMem ( + &Vendor.Guid, + &TerminalTypeGuid[NewTerminalContext->TerminalType], + sizeof (EFI_GUID) + ); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + TerminalDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + ASSERT (TerminalDevicePath != NULL); + ChangeTerminalDevicePath (TerminalDevicePath, TRUE); + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + TerminalDevicePath + ); + } + } + + if (ConDevicePath != NULL) { + Status = gRT->SetVariable ( + ConsoleName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (ConDevicePath), + ConDevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + +/** + This function delete and build multi-instance device path ConIn + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleInpOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID); +} + +/** + This function delete and build multi-instance device path ConOut + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateConsoleOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID); +} + +/** + This function delete and build multi-instance device path ErrOut + console device. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. +**/ +EFI_STATUS +Var_UpdateErrorOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID); +} + +/** + This function create a currently loaded Drive Option from + the BMM. It then appends this Driver Option to the end of + the "DriverOrder" list. It append this Driver Opotion to the end + of DriverOptionMenu. + + @param CallbackData The BMM context data. + @param HiiHandle The HII handle associated with the BMM formset. + @param DescriptionData The description of this driver option. + @param OptionalData The optional load option. + @param ForceReconnect If to force reconnect. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ) +{ + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINT16 DriverString[12]; + UINTN DriverOrderListSize; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetDriverOptionNumber (); + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + Index + ); + + if (*DescriptionData == 0x0000) { + StrCpy (DescriptionData, DriverString); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData); + BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (*OptionalData != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (OptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + FreePool (Buffer); + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1); + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + + Ptr += sizeof (UINT16); + CopyMem ( + Ptr, + DescriptionData, + StrSize (DescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (DescriptionData) + ); + + Ptr += StrSize (DescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem ( + Ptr, + OptionalData, + StrSize (OptionalData) + ); + } + + Status = gRT->SetVariable ( + DriverString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + ASSERT_EFI_ERROR (Status); + GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16)); + ASSERT (NewDriverOrderList != NULL); + CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize); + NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index; + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + } + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize + sizeof (UINT16), + NewDriverOrderList + ); + ASSERT_EFI_ERROR (Status); + if (DriverOrderList != NULL) { + FreePool (DriverOrderList); + } + DriverOrderList = NULL; + FreePool (NewDriverOrderList); + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + DriverOptionMenu.MenuNumber++; + + *DescriptionData = 0x0000; + *OptionalData = 0x0000; + return EFI_SUCCESS; +} + +/** + This function create a currently loaded Boot Option from + the BMM. It then appends this Boot Option to the end of + the "BootOrder" list. It also append this Boot Opotion to the end + of BootOptionMenu. + + @param CallbackData The BMM context data. + @param NvRamMap The file explorer formset internal state. + + @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. + @retval EFI_SUCCESS If function completes successfully. + +**/ +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ) +{ + UINT16 *BootOrderList; + UINT16 *NewBootOrderList; + UINTN BootOrderListSize; + UINT16 BootString[10]; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetBootOptionNumber () ; + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); + + if (NvRamMap->DescriptionData[0] == 0x0000) { + StrCpy (NvRamMap->DescriptionData, BootString); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData); + BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (NvRamMap->OptionalData[0] != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (NvRamMap->OptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + NvRamMap->DescriptionData, + StrSize (NvRamMap->DescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (NvRamMap->DescriptionData) + ); + + Ptr += StrSize (NvRamMap->DescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData)); + } + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + ASSERT_EFI_ERROR (Status); + + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize); + NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); + ASSERT (NewBootOrderList != NULL); + CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); + NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; + + if (BootOrderList != NULL) { + FreePool (BootOrderList); + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderListSize + sizeof (UINT16), + NewBootOrderList + ); + ASSERT_EFI_ERROR (Status); + + FreePool (NewBootOrderList); + NewBootOrderList = NULL; + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + BootOptionMenu.MenuNumber++; + + NvRamMap->DescriptionData[0] = 0x0000; + NvRamMap->OptionalData[0] = 0x0000; + return EFI_SUCCESS; +} + +/** + This function update the "BootNext" EFI Variable. If there is + no "BootNext" specified in BMM, this EFI Variable is deleted. + It also update the BMM context data specified the "BootNext" + vaule. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @return The EFI variable can be saved. See gRT->SetVariable + for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + UINT16 Index; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + CurrentFakeNVMap = &CallbackData->BmmFakeNvData; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + ASSERT (NULL != NewMenuEntry); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->IsBootNext = FALSE; + } + + if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + return EFI_SUCCESS; + } + + NewMenuEntry = BOpt_GetMenuEntry ( + &BootOptionMenu, + CurrentFakeNVMap->BootNext + ); + ASSERT (NewMenuEntry != NULL); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + Status = gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + VAR_FLAG, + sizeof (UINT16), + &NewMenuEntry->OptionNumber + ); + NewLoadContext->IsBootNext = TRUE; + CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext; + return Status; +} + +/** + This function update the "BootOrder" EFI Variable based on + BMM Formset's NV map. It then refresh BootOptionMenu + with the new "BootOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 OrderIndex; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINT16 OptionNumber; + + // + // First check whether BootOrder is present in current configuration + // + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); + if (BootOrder == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0]))); + + // + // OptionOrder is subset of BootOrder + // + for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) { + for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) { + if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) { + OptionNumber = BootOrder[Index]; + CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16)); + BootOrder[OrderIndex] = OptionNumber; + } + } + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + FreePool (BootOrder); + + BOpt_FreeMenu (&BootOptionMenu); + BOpt_GetBootOptions (CallbackData); + + return Status; + +} + +/** + This function update the "DriverOrder" EFI Variable based on + BMM Formset's NV map. It then refresh DriverOptionMenu + with the new "DriverOrder" list. + + @param CallbackData The BMM context data. + + @retval EFI_SUCCESS The function complete successfully. + @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. + @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. + +**/ +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINTN DriverOrderListSize; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); + + if (NewDriverOrderList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + FreePool (DriverOrderList); + } + + ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0]))); + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1); + } + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize, + NewDriverOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_GetDriverOptions (CallbackData); + return EFI_SUCCESS; +} + +/** + Update the Text Mode of Console. + + @param CallbackData The context data for BMM. + + @retval EFI_SUCCSS If the Text Mode of Console is updated. + @return Other value if the Text Mode of Console is not updated. + +**/ +EFI_STATUS +Var_UpdateConMode ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINTN Mode; + CONSOLE_OUT_MODE ModeInfo; + + Mode = CallbackData->BmmFakeNvData.ConsoleOutMode; + + Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row)); + if (!EFI_ERROR(Status)) { + PcdSet32 (PcdSetupConOutColumn, (UINT32) ModeInfo.Column); + PcdSet32 (PcdSetupConOutRow, (UINT32) ModeInfo.Row); + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Application/UiApp/BootMngr/BootManager.c b/MdeModulePkg/Application/UiApp/BootMngr/BootManager.c new file mode 100644 index 0000000000..3612c581da --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMngr/BootManager.c @@ -0,0 +1,385 @@ +/** @file + The platform boot manager reference implementation + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BootManager.h" + +EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID; +CHAR16 *mDeviceTypeStr[] = { + L"Legacy BEV", + L"Legacy Floppy", + L"Legacy Hard Drive", + L"Legacy CD ROM", + L"Legacy PCMCIA", + L"Legacy USB", + L"Legacy Embedded Network", + L"Legacy Unknown Device" +}; + + +HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {1DDDBE15-481D-4d2b-8277-B191EAF66525} + // + { 0x1dddbe15, 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) + } + } +}; + +BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = { + BOOT_MANAGER_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + BootManagerCallback + } +}; + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +BootManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + UINT16 KeyCount; + EFI_INPUT_KEY Key; + EFI_BOOT_MANAGER_LOAD_OPTION Option; + + if (Action != EFI_BROWSER_ACTION_CHANGED) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the key count + // + KeyCount = 0; + Option.Attributes = 0; + BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + for (Index = 0; Index < BootOptionCount; Index++) { + KeyCount++; + + EfiBootManagerInitializeLoadOption ( + &Option, + BootOption[Index].OptionNumber, + BootOption[Index].OptionType, + BootOption[Index].Attributes, + BootOption[Index].Description, + BootOption[Index].FilePath, + BootOption[Index].OptionalData, + BootOption[Index].OptionalDataSize + ); + + // + // Is this device the one chosen? + // + if (KeyCount == QuestionId) { + // + // Clear the screen before. + // + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->ClearScreen (gST->ConOut); + // + // Check any reset required change is applied? if yes, reset system + // + SetupResetReminder(); + // + // Parse the selected option. + // + BdsSetConsoleMode(FALSE); + EfiBootManagerBoot (&Option); + BdsSetConsoleMode(TRUE); + + if (EFI_ERROR (Option.Status)) { + gST->ConOut->OutputString ( + gST->ConOut, + GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) + ); + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + } + break; + } + } + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + return EFI_SUCCESS; +} + +/** + Register HII packages to HII database. + +**/ +VOID +InitializeBootManager ( + VOID + ) +{ + EFI_STATUS Status; + + if (!gConnectAllHappened){ + EfiBootManagerConnectAll(); + gConnectAllHappened = TRUE; + } + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + gBootManagerPrivate.DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &gBootManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mBootManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gBootManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + gBootManagerPrivate.HiiHandle = HiiAddPackages ( + &mBootManagerGuid, + gBootManagerPrivate.DriverHandle, + BootManagerVfrBin, + UiAppStrings, + NULL + ); + ASSERT(gBootManagerPrivate.HiiHandle != NULL); +} + + +/** + Enumerate possible boot options. + +**/ +VOID +EnumerateBootOptions ( + 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; + UINT16 KeyInput; + + 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 (); + + 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; + + KeyInput = 0; + NeedEndOp = FALSE; + for (Index = 0; Index < BootOptionCount; Index++) { + // + // At this stage we are creating a menu entry, thus the Keys are reproduceable + // + KeyInput++; + + // + // Don't display the hidden/inactive boot option + // + if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 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, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) + ], + NULL + ); + HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); + NeedEndOp = TRUE; + } + + ASSERT (BootOption[Index].Description != NULL); + + Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL); + + TempStr = UiDevicePathToStr (BootOption[Index].FilePath); + TempSize = StrSize (TempStr); + HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : ")); + ASSERT (HelpString != NULL); + StrCat (HelpString, L"Device Path : "); + StrCat (HelpString, TempStr); + + HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); + + HiiCreateActionOpCode ( + StartOpCodeHandle, + KeyInput, + 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); +} + + +/** + Remove the installed packages from the HII Database. + +**/ +VOID +FreeBootManager ( + VOID + ) +{ + EFI_STATUS Status; + Status = gBS->UninstallMultipleProtocolInterfaces ( + gBootManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mBootManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gBootManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + HiiRemovePackages (gBootManagerPrivate.HiiHandle); +} diff --git a/MdeModulePkg/Application/UiApp/BootMngr/BootManager.h b/MdeModulePkg/Application/UiApp/BootMngr/BootManager.h new file mode 100644 index 0000000000..34a07da975 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMngr/BootManager.h @@ -0,0 +1,112 @@ +/** @file + The platform boot manager reference implement + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_BOOT_MANAGER_H_ +#define _EFI_BOOT_MANAGER_H_ + +#include "Ui.h" +#include "FrontPage.h" + +// +// These are defined as the same with vfr file +// +#define BOOT_MANAGER_FORMSET_GUID \ + { \ + 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \ + } + +#define BOOT_MANAGER_FORM_ID 0x1000 + +#define LABEL_BOOT_OPTION 0x00 +#define LABEL_BOOT_OPTION_END 0x01 + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 BootManagerVfrBin[]; + +#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('B', 'M', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} BOOT_MANAGER_CALLBACK_DATA; + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +BootManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + Register HII packages to HII database. + +**/ +VOID +InitializeBootManager ( + VOID + ); + +/** + Enumerate possible boot options. + +**/ +VOID +EnumerateBootOptions ( + VOID + ); + +/** + Remove the installed packages from the HII Database. + +**/ +VOID +FreeBootManager ( + VOID + ); + +#endif diff --git a/MdeModulePkg/Application/UiApp/BootMngr/BootManagerStrings.uni b/MdeModulePkg/Application/UiApp/BootMngr/BootManagerStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..b784212af99c389852befc9655cdf9c6e9b1a816 GIT binary patch literal 3518 zcmc(h+fEZv6o%KeiSIC$3)DbS6K_lOkpLGnsu{hkyTj?X~ycKYOO{IbUG!tZzdbSM>tpvI{(Nwb! zlm}L!UxwWPepNRZEfa5Nv`UWiGpkaU7#B0%LcAYk;=6>zsk2<8rMOm^qn2G+%~2O! zU%j0a!gC~Kx8{5Xc8=VM!&YUyj9po&IsYg0gkEFv+CWw^^6RCJkd^;0)Ss9UcAd!5 z+>2jF$v!Xa#MaBOQ76Xa^YD%=pxm_Q@Ox(8+Sa1C#eOKN2kulTPV{MCcUhbK5cr`qpf6TT~^QfyT5tNmO3#aOQK zG;nd8T!Ge5Br?bDG*lcWFQ;=}ajU(aqg(B59f>StNsiV*b{A)g?qg!03Ewq7oq^T7 zWg%PU?2KJfPKdH{!G1p3rypg(g8g#+uSne@E6FjXGMd=-+AT)fuJ3cv1Sx-?D8^&k ziZY*T<-^;IEXtBHbO#Cfzt3WXE@^p+=KofeACe4bdj7?? zKg0g!8re27X`Ty2g>sMbknZJZmvk2tf$_UZzls?ls z%en{G`yLXXaU^;K>v>ouorPfe>?%_#e(qiQ!0ugY^-{+Cba>UiB0GyXjl z zQ>3?0I{Wz7o?`uqlh@;x)wd~T4`6Wu4!sZq5N*@aJK3K{jeT<{^$JukKC{c~2vaM$ h>wY=rHrD;zbfsQeRo-D)Y$wMa!u+Nf^nUdY`3F(P=rRBR literal 0 HcmV?d00001 diff --git a/MdeModulePkg/Application/UiApp/BootMngr/BootManagerVfr.Vfr b/MdeModulePkg/Application/UiApp/BootMngr/BootManagerVfr.Vfr new file mode 100644 index 0000000000..06a156d492 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/BootMngr/BootManagerVfr.Vfr @@ -0,0 +1,50 @@ +///** @file +// +// Browser formset. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } + +#define BOOT_MANAGER_FORM_ID 0x1000 + +#define LABEL_BOOT_OPTION 0x00 +#define LABEL_BOOT_OPTION_END 0x01 + +#define BOOT_MANAGER_CLASS 0x00 +#define BOOT_MANAGER_SUBCLASS 0x00 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_BM_BANNER), + help = STRING_TOKEN(STR_LAST_STRING), + classguid = FORMSET_GUID, + + form formid = BOOT_MANAGER_FORM_ID, + title = STRING_TOKEN(STR_BM_BANNER); + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER); + subtitle text = STRING_TOKEN(STR_LAST_STRING); + + // + // This is where we will dynamically add choices for the Boot Manager + // + label LABEL_BOOT_OPTION; + label LABEL_BOOT_OPTION_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_HELP_FOOTER); + + endform; + +endformset; diff --git a/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.c b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.c new file mode 100644 index 0000000000..8e3a9f1370 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.c @@ -0,0 +1,796 @@ +/** @file + The platform device manager reference implementation + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "DeviceManager.h" + +DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = { + DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + DeviceManagerCallback + } +}; + +#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10 + +EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID; + +// +// Which Mac Address string is select +// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form. +// +EFI_STRING mSelectedMacAddrString; + +// +// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID +// +MAC_ADDRESS_NODE_LIST mMacDeviceList; + +DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = { + { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS }, + { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS }, + { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS }, + { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS }, + { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS }, + { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS } +}; + +HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {102579A0-3686-466e-ACD8-80C087044F4A} + // + { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + This function is invoked if user selected a interactive opcode from Device Manager's + Formset. If user set VBIOS, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DeviceManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + UINTN CurIndex; + + if (Action != EFI_BROWSER_ACTION_CHANGING) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { + // + // If user select the mac address, need to record mac address string to support next form show. + // + for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex ++) { + if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) { + mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL); + } + } + CreateDeviceManagerForm(NETWORK_DEVICE_FORM_ID); + } else if(QuestionId == QUESTION_NETWORK_DEVICE_ID){ + CreateDeviceManagerForm(NETWORK_DEVICE_LIST_FORM_ID); + } + + return EFI_SUCCESS; +} + +/** + Get the mac address string from the device path. + if the device path has the vlan, get the vanid also. + + @param MacAddressNode Device path begin with mac address + @param PBuffer Output string buffer contain mac address. + +**/ +BOOLEAN +GetMacAddressString( + IN MAC_ADDR_DEVICE_PATH *MacAddressNode, + OUT CHAR16 **PBuffer + ) +{ + UINTN HwAddressSize; + UINTN Index; + UINT8 *HwAddress; + EFI_DEVICE_PATH_PROTOCOL *Node; + UINT16 VlanId; + CHAR16 *String; + UINTN BufferLen; + + VlanId = 0; + String = NULL; + ASSERT(MacAddressNode != NULL); + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) { + HwAddressSize = 6; + } + + // + // The output format is MAC:XX:XX:XX:...\XXXX + // The size is the Number size + ":" size + Vlan size(\XXXX) + End + // + BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16); + String = AllocateZeroPool (BufferLen); + if (String == NULL) { + return FALSE; + } + + *PBuffer = String; + StrCpy(String, L"MAC:"); + String += 4; + + // + // Convert the MAC address into a unicode string. + // + HwAddress = &MacAddressNode->MacAddress.Addr[0]; + for (Index = 0; Index < HwAddressSize; Index++) { + String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2); + if (Index < HwAddressSize - 1) { + *String++ = L':'; + } + } + + // + // If VLAN is configured, it will need extra 5 characters like "\0005". + // Plus one unicode character for the null-terminator. + // + Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode; + while (!IsDevicePathEnd (Node)) { + if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) { + VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId; + } + Node = NextDevicePathNode (Node); + } + + if (VlanId != 0) { + *String++ = L'\\'; + String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4); + } + + // + // Null terminate the Unicode string + // + *String = L'\0'; + + return TRUE; +} + +/** + Save question id and prompt id to the mac device list. + If the same mac address has saved yet, no need to add more. + + @param MacAddrString Mac address string. + + @retval EFI_SUCCESS Add the item is successful. + @return Other values if failed to Add the item. +**/ +BOOLEAN +AddIdToMacDeviceList ( + IN EFI_STRING MacAddrString + ) +{ + MENU_INFO_ITEM *TempDeviceList; + UINTN Index; + EFI_STRING StoredString; + EFI_STRING_ID PromptId; + EFI_HII_HANDLE HiiHandle; + + HiiHandle = gDeviceManagerPrivate.HiiHandle; + TempDeviceList = NULL; + + for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) { + StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL); + if (StoredString == NULL) { + return FALSE; + } + + // + // Already has save the same mac address to the list. + // + if (StrCmp (MacAddrString, StoredString) == 0) { + return FALSE; + } + } + + PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL); + // + // If not in the list, save it. + // + if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) { + mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId; + mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); + } else { + mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN; + if (mMacDeviceList.CurListLen != 0) { + TempDeviceList = (MENU_INFO_ITEM *)AllocateCopyPool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, (VOID *)mMacDeviceList.NodeList); + } else { + TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen); + } + + if (TempDeviceList == NULL) { + return FALSE; + } + TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; + TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); + + if (mMacDeviceList.CurListLen > 0) { + FreePool(mMacDeviceList.NodeList); + } + + mMacDeviceList.NodeList = TempDeviceList; + } + mMacDeviceList.CurListLen ++; + + return TRUE; +} + +/** + Check the devcie path, try to find whether it has mac address path. + + In this function, first need to check whether this path has mac address path. + second, when the mac address device path has find, also need to deicide whether + need to add this mac address relate info to the menu. + + @param *Node Input device which need to be check. + @param NextShowFormId FormId Which need to be show. + @param *NeedAddItem Whether need to add the menu in the network device list. + + @retval TRUE Has mac address device path. + @retval FALSE NOT Has mac address device path. + +**/ +BOOLEAN +IsMacAddressDevicePath ( + IN VOID *Node, + IN EFI_FORM_ID NextShowFormId, + OUT BOOLEAN *NeedAddItem + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *Buffer; + BOOLEAN ReturnVal; + + ASSERT (Node != NULL); + *NeedAddItem = FALSE; + ReturnVal = FALSE; + Buffer = NULL; + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; + + // + // find the partition device path node + // + while (!IsDevicePathEnd (DevicePath)) { + if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) { + ReturnVal = TRUE; + + if (DEVICE_MANAGER_FORM_ID == NextShowFormId) { + *NeedAddItem = TRUE; + break; + } + + if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) { + break; + } + + if (NETWORK_DEVICE_FORM_ID == NextShowFormId) { + if (StrCmp (Buffer, mSelectedMacAddrString) == 0) { + *NeedAddItem = TRUE; + } + break; + } + + if (NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) { + // + // Same handle may has two network child handle, so the questionid + // has the offset of SAME_HANDLE_KEY_OFFSET. + // + if (AddIdToMacDeviceList (Buffer)) { + *NeedAddItem = TRUE; + } + break; + } + } + DevicePath = NextDevicePathNode (DevicePath); + } + + if (Buffer != NULL) { + FreePool (Buffer); + } + + return ReturnVal; +} + +/** + Check to see if the device path is for the network device. + + @param Handle The HII handle which include the mac address device path. + @param NextShowFormId The FormId of the form which will be show next time. + @param ItemCount The new add Mac address item count. + + @retval TRUE Need to add new item in the menu. + @return FALSE Do not need to add the menu about the network. + +**/ +BOOLEAN +IsNeedAddNetworkMenu ( + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID NextShowFormId, + OUT UINTN *ItemCount + ) +{ + EFI_STATUS Status; + UINTN EntryCount; + UINTN Index; + EFI_HII_HANDLE HiiDeviceManagerHandle; + EFI_HANDLE DriverHandle; + EFI_HANDLE ControllerHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + BOOLEAN IsNeedAdd; + + HiiDeviceManagerHandle = gDeviceManagerPrivate.HiiHandle; + IsNeedAdd = FALSE; + OpenInfoBuffer = NULL; + if ((Handle == NULL) || (ItemCount == NULL)) { + return FALSE; + } + *ItemCount = 0; + + Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); + if (EFI_ERROR (Status)) { + return FALSE; + } + // + // Get the device path by the got Driver handle . + // + Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); + if (EFI_ERROR (Status)) { + return FALSE; + } + TmpDevicePath = DevicePath; + + // + // Check whether this device path include mac address device path. + // If this path has mac address path, get the value whether need + // add this info to the menu and return. + // Else check more about the child handle devcie path. + // + if (IsMacAddressDevicePath(TmpDevicePath, NextShowFormId,&IsNeedAdd)) { + if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) && IsNeedAdd) { + (*ItemCount) = 1; + } + return IsNeedAdd; + } + + // + // Search whether this path is the controller path, not he child handle path. + // And the child handle has the network devcie connected. + // + TmpDevicePath = DevicePath; + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!IsDevicePathEnd (TmpDevicePath)) { + return FALSE; + } + + // + // Retrieve the list of agents that are consuming the specific protocol + // on ControllerHandle. + // The buffer point by OpenInfoBuffer need be free at this function. + // + Status = gBS->OpenProtocolInformation ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Inspect if ChildHandle is one of the agents. + // + Status = EFI_UNSUPPORTED; + for (Index = 0; Index < EntryCount; Index++) { + // + // Query all the children created by the controller handle's driver + // + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ChildDevicePath, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Check whether this device path include mac address device path. + // + if (!IsMacAddressDevicePath(ChildDevicePath, NextShowFormId,&IsNeedAdd)) { + // + // If this path not has mac address path, check the other. + // + continue; + } else { + // + // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more. + // + if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId)) { + if (IsNeedAdd) { + (*ItemCount) += 1; + } + continue; + } else { + // + // If need to update other form, return whether need to add to the menu. + // + goto Done; + } + } + } + } + +Done: + if (OpenInfoBuffer != NULL) { + FreePool (OpenInfoBuffer); + } + return IsNeedAdd; +} + +/** + This function registers HII packages to HII database. + +**/ +VOID +InitializeDeviceManager ( + VOID +) +{ + EFI_STATUS Status; + + if (!gConnectAllHappened){ + EfiBootManagerConnectAll(); + gConnectAllHappened = TRUE; + } + + gDeviceManagerPrivate.DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &gDeviceManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDeviceManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gDeviceManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data. + // + gDeviceManagerPrivate.HiiHandle = HiiAddPackages ( + &mDeviceManagerGuid, + gDeviceManagerPrivate.DriverHandle, + DeviceManagerVfrBin, + UiAppStrings, + NULL + ); + ASSERT (gDeviceManagerPrivate.HiiHandle != NULL); +} + +/** + Remove the installed packages from the HII Database. + +**/ +VOID +FreeDeviceManager( + VOID +) +{ + EFI_STATUS Status; + + Status = gBS->UninstallMultipleProtocolInterfaces ( + gDeviceManagerPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDeviceManagerHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gDeviceManagerPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + HiiRemovePackages (gDeviceManagerPrivate.HiiHandle); +} + +/** + Dynamic create Hii information for Device Manager. + + @param NextShowFormId The FormId which need to be show. + +**/ +VOID +CreateDeviceManagerForm( + IN EFI_FORM_ID NextShowFormId +) +{ + UINTN Index; + EFI_STRING String; + EFI_STRING_ID Token; + EFI_STRING_ID TokenHelp; + EFI_HII_HANDLE *HiiHandles; + EFI_HII_HANDLE HiiHandle; + UINTN SkipCount; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID FormSetHelp; + EFI_GUID FormSetGuid; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + BOOLEAN AddNetworkMenu; + UINTN AddItemCount; + UINTN NewStringLen; + EFI_STRING NewStringTitle; + CHAR16 *DevicePathStr; + EFI_STRING_ID DevicePathId; + + HiiHandle = gDeviceManagerPrivate.HiiHandle; + AddNetworkMenu = FALSE; + AddItemCount = 0; + + // + // If need show the Network device list form, clear the old save list first. + // + if ((NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) { + mMacDeviceList.CurListLen = 0; + } + + // + // Update the network device form titile. + // + if (NextShowFormId == NETWORK_DEVICE_FORM_ID) { + String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NULL); + NewStringLen = StrLen(mSelectedMacAddrString) * 2; + NewStringLen += (StrLen(String) + 2) * 2; + NewStringTitle = AllocatePool (NewStringLen); + UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString); + HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); + FreePool (String); + FreePool (NewStringTitle); + } + + // + // 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; + // + // According to the next show Form id(mNextShowFormId) to decide which form need to update. + // + StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + NextShowFormId); + + // + // 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_END; + + // + // Get all the Hii handles + // + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + // + // Search for formset of each class type + // + SkipCount = 0; + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + // + // The QuestionId in the form which will call the driver form has this asssumption. + // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET; + // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET. + // + ASSERT(Index < MAX_KEY_SECTION_LEN); + if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) { + SkipCount = 0; + continue; + } + + String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + Token = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL); + if (String == NULL) { + String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); + ASSERT (String != NULL); + } + TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); + FreePool (String); + + // + // Network device process + // + if (IsNeedAddNetworkMenu (HiiHandles[Index], NextShowFormId,&AddItemCount)) { + if (NextShowFormId == DEVICE_MANAGER_FORM_ID) { + // + // Only show one menu item "Network Config" in the device manger form. + // + if (!AddNetworkMenu) { + AddNetworkMenu = TRUE; + HiiCreateGotoOpCode ( + StartOpCodeHandle, + NETWORK_DEVICE_LIST_FORM_ID, + STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE), + STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP), + EFI_IFR_FLAG_CALLBACK, + (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID + ); + } + } else if (NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) { + // + // In network device list form, same mac address device only show one menu. + // + while (AddItemCount > 0) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, + NETWORK_DEVICE_FORM_ID, + mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId, + STRING_TOKEN (STR_NETWORK_DEVICE_HELP), + EFI_IFR_FLAG_CALLBACK, + mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId + ); + AddItemCount -= 1; + } + } else if (NextShowFormId == NETWORK_DEVICE_FORM_ID) { + // + // In network device form, only the selected mac address device need to be show. + // + DevicePathStr = ExtractDevicePathFromHiiHandle(HiiHandles[Index]); + DevicePathId = 0; + if (DevicePathStr != NULL){ + DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL); + FreePool(DevicePathStr); + } + HiiCreateGotoExOpCode ( + StartOpCodeHandle, + 0, + Token, + TokenHelp, + 0, + (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET), + 0, + &FormSetGuid, + DevicePathId + ); + } + } else { + // + // + // Not network device process, only need to show at device manger form. + // + if (NextShowFormId == DEVICE_MANAGER_FORM_ID) { + DevicePathStr = ExtractDevicePathFromHiiHandle(HiiHandles[Index]); + DevicePathId = 0; + if (DevicePathStr != NULL){ + DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL); + FreePool(DevicePathStr); + } + HiiCreateGotoExOpCode ( + StartOpCodeHandle, + 0, + Token, + TokenHelp, + 0, + (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET), + 0, + &FormSetGuid, + DevicePathId + ); + } + } + // + //One packagelist may has more than one form package, + //Index-- means keep current HiiHandle and still extract from the packagelist, + //SkipCount++ means skip the formset which was found before in the same form package. + // + SkipCount++; + Index--; + } + + HiiUpdateForm ( + HiiHandle, + &mDeviceManagerGuid, + NextShowFormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + FreePool (HiiHandles); +} + diff --git a/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.h b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.h new file mode 100644 index 0000000000..7fb68a3c28 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManager.h @@ -0,0 +1,155 @@ +/** @file + The platform device manager reference implement + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DEVICE_MANAGER_H_ +#define _DEVICE_MANAGER_H_ + +#include "Ui.h" +#include "FrontPage.h" +#include + +// +// These are defined as the same with vfr file +// +#define DEVICE_MANAGER_FORMSET_GUID \ + { \ + 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \ + } + +#define LABEL_DEVICES_LIST 0x1100 +#define LABEL_NETWORK_DEVICE_LIST_ID 0x1101 +#define LABEL_NETWORK_DEVICE_ID 0x1102 +#define LABEL_END 0xffff +#define LABEL_FORM_ID_OFFSET 0x0100 + +#define LABEL_VBIOS 0x0040 + +#define DEVICE_MANAGER_FORM_ID 0x1000 +#define NETWORK_DEVICE_LIST_FORM_ID 0x1001 +#define NETWORK_DEVICE_FORM_ID 0x1002 +#define DEVICE_KEY_OFFSET 0x4000 +#define NETWORK_DEVICE_LIST_KEY_OFFSET 0x2000 +#define DEVICE_MANAGER_KEY_VBIOS 0x3000 +#define MAX_KEY_SECTION_LEN 0x1000 + +#define QUESTION_NETWORK_DEVICE_ID 0x3FFF +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 DeviceManagerVfrBin[]; + +#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B') + + +typedef struct { + UINTN Signature; + + /// + /// Device Manager HII relative handles + /// + EFI_HII_HANDLE HiiHandle; + + EFI_HANDLE DriverHandle; + + /// + /// Device Manager Produced protocols + /// + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + /// + /// Configuration data + /// + UINT8 VideoBios; +} DEVICE_MANAGER_CALLBACK_DATA; + +typedef struct { + EFI_STRING_ID PromptId; + EFI_QUESTION_ID QuestionId; +}MENU_INFO_ITEM; + +typedef struct { + UINTN CurListLen; + UINTN MaxListLen; + MENU_INFO_ITEM *NodeList; +} MAC_ADDRESS_NODE_LIST; + +#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + DEVICE_MANAGER_CALLBACK_DATA, \ + ConfigAccess, \ + DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \ + ) +typedef struct { + EFI_STRING_ID StringId; + UINT16 Class; +} DEVICE_MANAGER_MENU_ITEM; + +/** + This function is invoked if user selected a interactive opcode from Device Manager's + Formset. If user set VBIOS, the new value is saved to EFI variable. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DeviceManagerCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + This function registers HII packages to HII database. + +**/ +VOID +InitializeDeviceManager ( + VOID + ); + +/** + Remove the installed packages from the HII Database. + +**/ +VOID +FreeDeviceManager( + VOID +); + +/** + Dynamic create Hii information for Device Manager. + + @param NextShowFormId The FormId which need to be show. + +**/ +VOID +CreateDeviceManagerForm( + IN EFI_FORM_ID NextShowFormId +); + +#endif diff --git a/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerStrings.uni b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..4ce01f6789c7858d38197a85e9993575128a152a GIT binary patch literal 7086 zcmeI1-)`en5XR>kiFdHl8$jC>khnpB*ltsZc9T?Xx?QfKv}wE5woR3|E&Ig01@Qak z)Uln~jt!JX0!6Wp&!3rZzB8UPKIf0$w@kk;_(k@ko!Nz5+NphNpLl&lZMLlE1B-1& zziT_^X+m#}y5=AApHiAre@1D>J+}Ash-`=J9qlLn)Uz@D#z;7&S39R8tM3(3ZtSD$ zJ4aHCq|cD?Irp#aOZ&>cu@{uPNQ;qmNm*lNjM8{-mx?9H~=_wX*G6RY1OmGUD5a;J>%8aGswwdJ} zp5NrKWYOL`A17QTIdAa=TBT8p1kR*w&a*5(25I6cnw7}Jtt>dBCCrd;|4Oe2tXW)n zZXzrj!*7JlFn;>Lf-uE7cI7)UGxDwbwY=&S7Usym1(m$AO?k$=ZY|BgoSI{LPHc0j zrHz#L{Ik4d%R~FwI-uLbn+En1*O%7gxeL2`BXl29+r{4wDRrFlL+f+zP%mbJgmgZ- z_;-gM2QGO)Nq((si@W4XYK!}}KkMm54&f0!BzNFCBRitszGLfC-$kyZ3|#*{PeQLc zX&us6eWW+^+NH1b|HAz>EyAuhvh$!N*wL|f3puIuE^O@KW74@(5(N~Qwj6(8_Iuk{ zJZ&%^^6GPcE958oX55z2DdN8&{1DBZXmu zr)&fab2xGv#6Z_Z*d?|ODT%EiHp&l*ekqn)G$|hDEszaWu`@!KEWUj}Sft~x*A=15 z^3)Vv8F%vcw=gB&K7cj(gm|q+UW6_?`^)I&$Wuhq{Dt|fmfy6s2u~GTkMWfABR*ck zOqQut_=@m6=0|*dfSIh9CH}rjL$mfGJdgRQ!c)eNd`HX-8ZlIaXPKY3_>0!u>Dn-~ z3Q-wHefSv??G@SUdr}>a`tTFmy|16^<4JW;m2stYY|q!nCU0CFu9T_X5UrKltj8O- z3Q-wH$^k}X83WHBc51$PbvWwbNg%vzPbmiQI%x=FXYa!0o;cl>C zZe93Vg{X|9j%SBMGRu+Y0?L#7WYN`YP92V(Ywb_6&$9gS9TpB7SsRg!COL3<{pQ^c31_GNDHG5yw&w_=QCJXU*I@EemaNjy* z|3>*#vIBR$l#eQZPxl^^-74i2$_i4Y~o6Sdc#LMq7l<`>|M^YA_Dx&1?N^qW5rlH=t_XpFc{h zMyIo$bcedbx9HsWzqRYA7^q$I?7qGBV$!&(OjEgQF5kbd589k S#g0xSbo!A!u}U;2v-T%uF1&jH literal 0 HcmV?d00001 diff --git a/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerVfr.Vfr b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerVfr.Vfr new file mode 100644 index 0000000000..bc457ce3eb --- /dev/null +++ b/MdeModulePkg/Application/UiApp/DeviceMngr/DeviceManagerVfr.Vfr @@ -0,0 +1,102 @@ +///** @file +// +// Device Manager formset. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 } + +#define EFI_DISK_DEVICE_CLASS 0x0001 +#define EFI_VIDEO_DEVICE_CLASS 0x0002 +#define EFI_NETWORK_DEVICE_CLASS 0x0004 +#define EFI_INPUT_DEVICE_CLASS 0x0008 +#define EFI_ON_BOARD_DEVICE_CLASS 0x0010 +#define EFI_OTHER_DEVICE_CLASS 0x0020 +#define LABEL_VBIOS 0x0040 +#define LABEL_DEVICES_LIST 0x1100 +#define LABEL_NETWORK_DEVICE_LIST_ID 0x1101 +#define LABEL_NETWORK_DEVICE_ID 0x1102 +#define LABEL_END 0xffff + +#define DEVICE_MANAGER_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0003 + +#define DEVICE_MANAGER_FORM_ID 0x1000 +#define NETWORK_DEVICE_LIST_FORM_ID 0x1001 +#define NETWORK_DEVICE_FORM_ID 0x1002 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_EDKII_MENU_TITLE), + help = STRING_TOKEN(STR_EMPTY_STRING), + classguid = FORMSET_GUID, + + form formid = DEVICE_MANAGER_FORM_ID, + title = STRING_TOKEN(STR_EDKII_MENU_TITLE); + + subtitle text = STRING_TOKEN(STR_DEVICES_LIST); + // + // This is where devices get added to the device manager hierarchy + // + label EFI_DISK_DEVICE_CLASS; +// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size + + label EFI_VIDEO_DEVICE_CLASS; +// label LABEL_END; + + label EFI_NETWORK_DEVICE_CLASS; +// label LABEL_END; + + label EFI_INPUT_DEVICE_CLASS; +// label LABEL_END; + + label EFI_ON_BOARD_DEVICE_CLASS; +// label LABEL_END; + +// label EFI_OTHER_DEVICE_CLASS; + + label LABEL_DEVICES_LIST; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + label LABEL_VBIOS; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + + endform; + + form formid = NETWORK_DEVICE_LIST_FORM_ID, + title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_LIST_TITLE); + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_LIST_STRING); + + label LABEL_NETWORK_DEVICE_LIST_ID; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = NETWORK_DEVICE_FORM_ID, + title = STRING_TOKEN(STR_FORM_NETWORK_DEVICE_TITLE); + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE_STRING); + + label LABEL_NETWORK_DEVICE_ID; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; +endformset; + diff --git a/MdeModulePkg/Application/UiApp/DeviceMngr/DriverHealthVfr.Vfr b/MdeModulePkg/Application/UiApp/DeviceMngr/DriverHealthVfr.Vfr new file mode 100644 index 0000000000..e2f8ff5b8e --- /dev/null +++ b/MdeModulePkg/Application/UiApp/DeviceMngr/DriverHealthVfr.Vfr @@ -0,0 +1,45 @@ +///** @file +// +// Driver Health formset. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#define DRIVER_HEALTH_FORMSET_GUID { 0xf76e0a70, 0xb5ed, 0x4c38, 0xac, 0x9a, 0xe5, 0xf5, 0x4b, 0xf1, 0x6e, 0x34 } + +#define LABEL_DRIVER_HEALTH 0x2000 +#define LABEL_DRIVER_HEALTH_END 0x2001 +#define LABEL_DRIVER_HEALTH_REAPIR_ALL 0x3000 +#define LABEL_DRIVER_HEALTH_REAPIR_ALL_END 0x3001 + +#define DRIVER_HEALTH_FORM_ID 0x1003 + +formset + guid = DRIVER_HEALTH_FORMSET_GUID, + title = STRING_TOKEN(STR_DH_BANNER), + help = STRING_TOKEN(STR_EMPTY_STRING), + classguid = DRIVER_HEALTH_FORMSET_GUID, + + form formid = DRIVER_HEALTH_FORM_ID, + title = STRING_TOKEN(STR_DH_BANNER); + + label LABEL_DRIVER_HEALTH; + label LABEL_DRIVER_HEALTH_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + label LABEL_DRIVER_HEALTH_REAPIR_ALL; + label LABEL_DRIVER_HEALTH_REAPIR_ALL_END; + + subtitle text = STRING_TOKEN(STR_LAST_STRING); + subtitle text = STRING_TOKEN(STR_HELP_FOOTER); + subtitle text = STRING_TOKEN(STR_LAST_STRING); + endform; +endformset; diff --git a/MdeModulePkg/Application/UiApp/FormsetGuid.h b/MdeModulePkg/Application/UiApp/FormsetGuid.h new file mode 100644 index 0000000000..a0170357cf --- /dev/null +++ b/MdeModulePkg/Application/UiApp/FormsetGuid.h @@ -0,0 +1,51 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +//**/ +#ifndef _FORMSET_GUID_H_ +#define _FORMSET_GUID_H_ + +#include "BootMaint/FormGuid.h" + +#define FRONT_PAGE_FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } + +// Used by Boot manager form +#define BOOT_MANAGER_FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } + +#define BOOT_MANAGER_FORM_ID 0x1000 + + +// Used by Device manager form. +#define DEVICE_MANAGER_FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 } + +#define DEVICE_MANAGER_FORM_ID 0x2000 +#define NETWORK_DEVICE_LIST_FORM_ID 0x2001 +#define NETWORK_DEVICE_FORM_ID 0x2002 + +#define DEVICE_KEY_OFFSET 0x2000 +#define NETWORK_DEVICE_LIST_KEY_OFFSET 0x2100 +#define MAX_KEY_SECTION_LEN 0x0100 + +#define QUESTION_NETWORK_DEVICE_ID 0x2FFF + +#define LABEL_DEVICES_LIST 0x2100 +#define LABEL_NETWORK_DEVICE_LIST_ID 0x2101 +#define LABEL_NETWORK_DEVICE_ID 0x2102 +#define LABEL_END 0xffff +#define LABEL_FORM_ID_OFFSET 0x0100 +#define LABEL_VBIOS 0x0040 + + +#endif diff --git a/MdeModulePkg/Application/UiApp/FrontPage.c b/MdeModulePkg/Application/UiApp/FrontPage.c new file mode 100644 index 0000000000..4e80d7c6da --- /dev/null +++ b/MdeModulePkg/Application/UiApp/FrontPage.c @@ -0,0 +1,1601 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "FrontPage.h" +#include "Language.h" +#define MAX_STRING_LEN 200 + +EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID; + +BOOLEAN gConnectAllHappened = FALSE; +BOOLEAN mFeaturerSwitch = TRUE; +BOOLEAN mResetRequired = FALSE; +BOOLEAN mEnterBmm = FALSE; + +EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; +CHAR8 *mLanguageString; +BOOLEAN mModeInitialized = FALSE; +// +// Boot video resolution and text mode. +// +UINT32 mBootHorizontalResolution = 0; +UINT32 mBootVerticalResolution = 0; +UINT32 mBootTextModeColumn = 0; +UINT32 mBootTextModeRow = 0; +// +// BIOS setup video resolution and text mode. +// +UINT32 mSetupTextModeColumn = 0; +UINT32 mSetupTextModeRow = 0; +UINT32 mSetupHorizontalResolution = 0; +UINT32 mSetupVerticalResolution = 0; + +FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = { + FRONT_PAGE_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + NULL, + { + FakeExtractConfig, + FakeRouteConfig, + FrontPageCallback + } +}; + +HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {8E6D99EE-7531-48f8-8745-7F6144468FF2} + // + { 0x8e6d99ee, 0x7531, 0x48f8, { 0x87, 0x45, 0x7f, 0x61, 0x44, 0x46, 0x8f, 0xf2 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Update the banner information for the Front Page based on Smbios information. + +**/ +VOID +UpdateFrontPageStrings ( + VOID + ); + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Configuration; + if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName) + && !HiiIsConfigHdrMatch (Configuration, &mFileExplorerGuid, mFileExplorerStorageName)) { + return EFI_NOT_FOUND; + } + + *Progress = Configuration + StrLen (Configuration); + return EFI_SUCCESS; +} + +/** + Create oneof options for language. + +**/ +VOID +InitializeLanguage ( + VOID + ) +{ + EFI_STATUS Status; + CHAR8 *LangCode; + CHAR8 *Lang; + CHAR8 *CurrentLang; + UINTN OptionCount; + CHAR16 *StringBuffer; + EFI_HII_HANDLE HiiHandle; + VOID *OptionsOpCodeHandle; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_HII_STRING_PROTOCOL *HiiString; + UINTN StringSize; + + Lang = NULL; + StringBuffer = NULL; + + // + // Init OpCode Handle and Allocate space for creation of UpdateData Buffer + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != 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_SELECT_LANGUAGE; + + // + // 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_END; + // + // Collect the languages from what our current Language support is based on our VFR + // + HiiHandle = gFrontPagePrivate.HiiHandle; + + CurrentLang = GetEfiGlobalVariable (L"PlatformLang"); + + if (mLanguageString == NULL) { + // + // Get Support language list from variable. + // + mLanguageString = GetEfiGlobalVariable (L"PlatformLangCodes"); + if (mLanguageString == NULL) { + mLanguageString = AllocateCopyPool ( + AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), + (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) + ); + ASSERT (mLanguageString != NULL); + } + } + + if (gFrontPagePrivate.LanguageToken == NULL) { + // + // Count the language list number. + // + LangCode = mLanguageString; + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + OptionCount = 0; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + OptionCount ++; + } + + // + // Allocate extra 1 as the end tag. + // + gFrontPagePrivate.LanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); + ASSERT (gFrontPagePrivate.LanguageToken != NULL); + + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); + ASSERT_EFI_ERROR (Status); + + LangCode = mLanguageString; + OptionCount = 0; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + StringSize = 0; + Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + StringBuffer = AllocateZeroPool (StringSize); + ASSERT (StringBuffer != NULL); + Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); + ASSERT_EFI_ERROR (Status); + } + + if (EFI_ERROR (Status)) { + StringBuffer = AllocatePool (AsciiStrSize (Lang) * sizeof (CHAR16)); + ASSERT (StringBuffer != NULL); + AsciiStrToUnicodeStr (Lang, StringBuffer); + } + + ASSERT (StringBuffer != NULL); + gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); + FreePool (StringBuffer); + + OptionCount++; + } + } + + ASSERT (gFrontPagePrivate.LanguageToken != NULL); + LangCode = mLanguageString; + OptionCount = 0; + if (Lang == NULL) { + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + } + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + gFrontPagePrivate.LanguageToken[OptionCount], + EFI_IFR_OPTION_DEFAULT, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) OptionCount + ); + } else { + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + gFrontPagePrivate.LanguageToken[OptionCount], + 0, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) OptionCount + ); + } + + OptionCount++; + } + + if (CurrentLang != NULL) { + FreePool (CurrentLang); + } + FreePool (Lang); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, + FRONT_PAGE_KEY_LANGUAGE, + 0, + 0, + STRING_TOKEN (STR_LANGUAGE_SELECT), + STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), + EFI_IFR_FLAG_CALLBACK, + EFI_IFR_NUMERIC_SIZE_1, + OptionsOpCodeHandle, + NULL + ); + + Status = HiiUpdateForm ( + HiiHandle, + &mFrontPageGuid, + FRONT_PAGE_FORM_ID, + StartOpCodeHandle, // LABEL_SELECT_LANGUAGE + EndOpCodeHandle // LABEL_END + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FrontPageCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + CHAR8 *LangCode; + CHAR8 *Lang; + UINTN Index; + EFI_STATUS Status; + + // + //Chech whether exit from BMM and reenter frontpage,if yes,reclaim string depositories + // + if (Action == EFI_BROWSER_ACTION_FORM_OPEN){ + if (mEnterBmm){ + ReclaimStringDepository(); + mEnterBmm = FALSE; + } + } + + if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { + // + // Do nothing for other UEFI Action. Only do call back when data is changed. + // + return EFI_UNSUPPORTED; + } + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (QuestionId) { + case FRONT_PAGE_KEY_CONTINUE: + // + // This is the continue - clear the screen and return an error to get out of FrontPage loop + // + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; + + case FRONT_PAGE_KEY_LANGUAGE: + // + // Allocate working buffer for RFC 4646 language in supported LanguageString. + // + Lang = AllocatePool (AsciiStrSize (mLanguageString)); + ASSERT (Lang != NULL); + + Index = 0; + LangCode = mLanguageString; + while (*LangCode != 0) { + GetNextLanguage (&LangCode, Lang); + + if (Index == Value->u8) { + break; + } + + Index++; + } + + if (Index == Value->u8) { + Status = gRT->SetVariable ( + L"PlatformLang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (Lang), + Lang + ); + ASSERT_EFI_ERROR(Status); + } else { + ASSERT (FALSE); + } + FreePool (Lang); + // + //Current language of platform is changed,recreate oneof options for language. + // + InitializeLanguage(); + break; + + + case FRONT_PAGE_KEY_RESET: + // + // Reset + // + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; + + default: + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + switch (QuestionId) { + case FRONT_PAGE_KEY_BOOT_MANAGER: + // + // Boot Manager + // + EnumerateBootOptions (); + break; + + case FRONT_PAGE_KEY_DEVICE_MANAGER: + // + // Device Manager + // + CreateDeviceManagerForm(DEVICE_MANAGER_FORM_ID); + break; + + case FRONT_PAGE_KEY_BOOT_MAINTAIN: + // + // Boot Maintenance Manager + // + InitializeBM (); + mEnterBmm = TRUE; + break; + + default: + break; + } + } + + return EFI_SUCCESS; +} + +/** + Initialize HII information for the FrontPage + + + @retval EFI_SUCCESS The operation is successful. + @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. + +**/ +EFI_STATUS +InitializeFrontPage ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Locate Hii relative protocols + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // + gFrontPagePrivate.DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &gFrontPagePrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mFrontPageHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gFrontPagePrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + gFrontPagePrivate.HiiHandle = HiiAddPackages ( + &mFrontPageGuid, + gFrontPagePrivate.DriverHandle, + FrontPageVfrBin, + UiAppStrings, + NULL + ); + ASSERT (gFrontPagePrivate.HiiHandle != NULL); + + // + //Updata Front Page strings + // + UpdateFrontPageStrings (); + + // + // Initialize laguage options + // + InitializeLanguage (); + + return Status; +} + +/** + Call the browser and display the front page + + @return Status code that will be returned by + EFI_FORM_BROWSER2_PROTOCOL.SendForm (). + +**/ +EFI_STATUS +CallFrontPage ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + + // + // Begin waiting for USER INPUT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) + ); + + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = gFormBrowser2->SendForm ( + gFormBrowser2, + &gFrontPagePrivate.HiiHandle, + 1, + &mFrontPageGuid, + 0, + NULL, + &ActionRequest + ); + // + // Check whether user change any option setting which needs a reset to be effective + // + if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { + EnableResetRequired (); + } + + return Status; +} + +VOID +FreeFrontPage( + VOID + ) +{ + EFI_STATUS Status; + Status = gBS->UninstallMultipleProtocolInterfaces ( + gFrontPagePrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mFrontPageHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &gFrontPagePrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + HiiRemovePackages (gFrontPagePrivate.HiiHandle); + if (gFrontPagePrivate.LanguageToken != NULL) { + FreePool (gFrontPagePrivate.LanguageToken); + gFrontPagePrivate.LanguageToken = NULL; + } +} + +/** + Convert Processor Frequency Data to a string. + + @param ProcessorFrequency The frequency data to process + @param Base10Exponent The exponent based on 10 + @param String The string that is created + +**/ +VOID +ConvertProcessorToString ( + IN UINT16 ProcessorFrequency, + IN UINT16 Base10Exponent, + OUT CHAR16 **String + ) +{ + CHAR16 *StringBuffer; + UINTN Index; + UINT32 FreqMhz; + + if (Base10Exponent >= 6) { + FreqMhz = ProcessorFrequency; + for (Index = 0; Index < (UINTN) (Base10Exponent - 6); Index++) { + FreqMhz *= 10; + } + } else { + FreqMhz = 0; + } + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3); + StrCat (StringBuffer, L"."); + UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2); + StrCat (StringBuffer, L" GHz"); + *String = (CHAR16 *) StringBuffer; + return ; +} + + +/** + Convert Memory Size to a string. + + @param MemorySize The size of the memory to process + @param String The string that is created + +**/ +VOID +ConvertMemorySizeToString ( + IN UINT32 MemorySize, + OUT CHAR16 **String + ) +{ + CHAR16 *StringBuffer; + + StringBuffer = AllocateZeroPool (0x24); + ASSERT (StringBuffer != NULL); + UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 10); + StrCat (StringBuffer, L" MB RAM"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +/** + + Acquire the string associated with the Index from smbios structure and return it. + The caller is responsible for free the string buffer. + + @param OptionalStrStart The start position to search the string + @param Index The index of the string to extract + @param String The string that is extracted + + @retval EFI_SUCCESS The function returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetOptionalStringByIndex ( + IN CHAR8 *OptionalStrStart, + IN UINT8 Index, + OUT CHAR16 **String + ) +{ + UINTN StrSize; + + if (Index == 0) { + *String = AllocateZeroPool (sizeof (CHAR16)); + return EFI_SUCCESS; + } + + StrSize = 0; + do { + Index--; + OptionalStrStart += StrSize; + StrSize = AsciiStrSize (OptionalStrStart); + } while (OptionalStrStart[StrSize] != 0 && Index != 0); + + if ((Index != 0) || (StrSize == 1)) { + // + // Meet the end of strings set but Index is non-zero, or + // Find an empty string + // + *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); + } else { + *String = AllocatePool (StrSize * sizeof (CHAR16)); + AsciiStrToUnicodeStr (OptionalStrStart, *String); + } + + return EFI_SUCCESS; +} + + +/** + Update the banner information for the Front Page based on Smbios information. +**/ +VOID +UpdateFrontPageStrings ( + VOID + ) +{ + UINT8 StrIndex; + CHAR16 *NewString; + CHAR16 *FirmwareVersionString; + BOOLEAN Find[5]; + EFI_STATUS Status; + EFI_STRING_ID TokenToUpdate; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *Smbios; + SMBIOS_TABLE_TYPE0 *Type0Record; + SMBIOS_TABLE_TYPE1 *Type1Record; + SMBIOS_TABLE_TYPE4 *Type4Record; + SMBIOS_TABLE_TYPE19 *Type19Record; + EFI_SMBIOS_TABLE_HEADER *Record; + + ZeroMem (Find, sizeof (Find)); + + // + // Update Front Page strings + // + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **) &Smbios + ); + if (EFI_ERROR (Status)) { + return ; + } + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + do { + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + if (EFI_ERROR(Status)) { + break; + } + + if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { + Type0Record = (SMBIOS_TABLE_TYPE0 *) Record; + StrIndex = Type0Record->BiosVersion; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION); + FirmwareVersionString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString); + if (*FirmwareVersionString != 0x0000 ) { + FreePool (NewString); + NewString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + } else { + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + } + Find[0] = TRUE; + } + + if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) { + Type1Record = (SMBIOS_TABLE_TYPE1 *) Record; + StrIndex = Type1Record->ProductName; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[1] = TRUE; + } + + if ((Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) && !Find[2]) { + Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; + // + // The information in the record should be only valid when the CPU Socket is populated. + // + if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) { + StrIndex = Type4Record->ProcessorVersion; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[2] = TRUE; + } + } + + if ((Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) && !Find[3]) { + Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; + // + // The information in the record should be only valid when the CPU Socket is populated. + // + if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) { + ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[3] = TRUE; + } + } + + if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) { + Type19Record = (SMBIOS_TABLE_TYPE19 *) Record; + ConvertMemorySizeToString ( + (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)), + &NewString + ); + TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE); + HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); + FreePool (NewString); + Find[4] = TRUE; + } + } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); + return ; +} + +/** + This function will change video resolution and text mode + according to defined setup mode or defined boot mode + + @param IsSetupMode Indicate mode is changed to setup mode or boot mode. + + @retval EFI_SUCCESS Mode is changed successfully. + @retval Others Mode failed to be changed. + +**/ +EFI_STATUS +EFIAPI +BdsSetConsoleMode ( + BOOLEAN IsSetupMode + ) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINT32 MaxGopMode; + UINT32 MaxTextMode; + UINT32 ModeNumber; + UINT32 NewHorizontalResolution; + UINT32 NewVerticalResolution; + UINT32 NewColumns; + UINT32 NewRows; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + UINTN Index; + UINTN CurrentColumn; + UINTN CurrentRow; + + MaxGopMode = 0; + MaxTextMode = 0; + + // + // Get current video resolution and text mode + // + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput + ); + if (EFI_ERROR (Status)) { + GraphicsOutput = NULL; + } + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID**)&SimpleTextOut + ); + if (EFI_ERROR (Status)) { + SimpleTextOut = NULL; + } + + if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) { + return EFI_UNSUPPORTED; + } + + if (IsSetupMode) { + // + // The requried resolution and text mode is setup mode. + // + NewHorizontalResolution = mSetupHorizontalResolution; + NewVerticalResolution = mSetupVerticalResolution; + NewColumns = mSetupTextModeColumn; + NewRows = mSetupTextModeRow; + } else { + // + // The required resolution and text mode is boot mode. + // + NewHorizontalResolution = mBootHorizontalResolution; + NewVerticalResolution = mBootVerticalResolution; + NewColumns = mBootTextModeColumn; + NewRows = mBootTextModeRow; + } + + if (GraphicsOutput != NULL) { + MaxGopMode = GraphicsOutput->Mode->MaxMode; + } + + if (SimpleTextOut != NULL) { + MaxTextMode = SimpleTextOut->Mode->MaxMode; + } + + // + // 1. If current video resolution is same with required video resolution, + // video resolution need not be changed. + // 1.1. If current text mode is same with required text mode, text mode need not be changed. + // 1.2. If current text mode is different from required text mode, text mode need be changed. + // 2. If current video resolution is different from required video resolution, we need restart whole console drivers. + // + for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) { + Status = GraphicsOutput->QueryMode ( + GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution == NewHorizontalResolution) && + (Info->VerticalResolution == NewVerticalResolution)) { + if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) && + (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) { + // + // Current resolution is same with required resolution, check if text mode need be set + // + Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow); + ASSERT_EFI_ERROR (Status); + if (CurrentColumn == NewColumns && CurrentRow == NewRows) { + // + // If current text mode is same with required text mode. Do nothing + // + FreePool (Info); + return EFI_SUCCESS; + } else { + // + // If current text mode is different from requried text mode. Set new video mode + // + for (Index = 0; Index < MaxTextMode; Index++) { + Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow); + if (!EFI_ERROR(Status)) { + if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) { + // + // Required text mode is supported, set it. + // + Status = SimpleTextOut->SetMode (SimpleTextOut, Index); + ASSERT_EFI_ERROR (Status); + // + // Update text mode PCD. + // + PcdSet32 (PcdConOutColumn, mSetupTextModeColumn); + PcdSet32 (PcdConOutRow, mSetupTextModeRow); + FreePool (Info); + return EFI_SUCCESS; + } + } + } + if (Index == MaxTextMode) { + // + // If requried text mode is not supported, return error. + // + FreePool (Info); + return EFI_UNSUPPORTED; + } + } + } else { + // + // If current video resolution is not same with the new one, set new video resolution. + // In this case, the driver which produces simple text out need be restarted. + // + Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + } + FreePool (Info); + } + } + + if (ModeNumber == MaxGopMode) { + // + // If the resolution is not supported, return error. + // + return EFI_UNSUPPORTED; + } + + // + // Set PCD to Inform GraphicsConsole to change video resolution. + // Set PCD to Inform Consplitter to change text mode. + // + PcdSet32 (PcdVideoHorizontalResolution, NewHorizontalResolution); + PcdSet32 (PcdVideoVerticalResolution, NewVerticalResolution); + PcdSet32 (PcdConOutColumn, NewColumns); + PcdSet32 (PcdConOutRow, NewRows); + + + // + // Video mode is changed, so restart graphics console driver and higher level driver. + // Reconnect graphics console driver and higher level driver. + // Locate all the handles with GOP protocol and reconnect it. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + } + + return EFI_SUCCESS; +} + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the image goes into a library that calls this + function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeUserInterface ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HII_HANDLE HiiHandle; + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN BootTextColumn; + UINTN BootTextRow; + + if (!mModeInitialized) { + // + // After the console is ready, get current video resolution + // and text mode before launching setup at first time. + // + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput + ); + if (EFI_ERROR (Status)) { + GraphicsOutput = NULL; + } + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID**)&SimpleTextOut + ); + if (EFI_ERROR (Status)) { + SimpleTextOut = NULL; + } + + if (GraphicsOutput != NULL) { + // + // Get current video resolution and text mode. + // + mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; + mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; + } + + if (SimpleTextOut != NULL) { + Status = SimpleTextOut->QueryMode ( + SimpleTextOut, + SimpleTextOut->Mode->Mode, + &BootTextColumn, + &BootTextRow + ); + mBootTextModeColumn = (UINT32)BootTextColumn; + mBootTextModeRow = (UINT32)BootTextRow; + } + + // + // Get user defined text mode for setup. + // + mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); + mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); + mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); + mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); + + mModeInitialized = TRUE; + } + + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + gST->ConOut->ClearScreen (gST->ConOut); + + // + // Install customized fonts needed by Front Page + // + + HiiHandle = ExportFonts (); + ASSERT (HiiHandle != NULL); + + InitializeStringSupport (); + + BdsSetConsoleMode (TRUE); + UiEntry (FALSE); + BdsSetConsoleMode (FALSE); + + UninitializeStringSupport (); + HiiRemovePackages (HiiHandle); + + return EFI_SUCCESS; +} + +/** + This function is the main entry of the UI entry. + The function will present the main menu of the system UI. + + @param ConnectAllHappened Caller passes the value to UI to avoid unnecessary connect-all. + +**/ +VOID +EFIAPI +UiEntry ( + IN BOOLEAN ConnectAllHappened + ) +{ + EFI_STATUS Status; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + + // + // Indicate if the connect all has been performed before. + // + if (ConnectAllHappened) { + gConnectAllHappened = TRUE; + } + + // + // The boot option enumeration time is acceptable in Ui driver + // + EfiBootManagerRefreshAllBootOption (); + + // + // Boot Logo is corrupted, report it using Boot Logo protocol. + // + Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + if (!EFI_ERROR (Status) && (BootLogo != NULL)) { + BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); + } + + InitializeFrontPage (); + InitializeDeviceManager (); + InitializeBootManager (); + InitBootMaintenance(); + + CallFrontPage (); + + FreeBMPackage (); + FreeBootManager (); + FreeDeviceManager (); + FreeFrontPage (); + + if (mLanguageString != NULL) { + FreePool (mLanguageString); + mLanguageString = NULL; + } + + // + //Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); +} + +/** + Extract device path for given HII handle and class guid. + + @param Handle The HII handle. + + @retval NULL Fail to get the device path string. + @return PathString Get the device path string. + +**/ +CHAR16 * +ExtractDevicePathFromHiiHandle ( + IN EFI_HII_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_HANDLE DriverHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *PathToText; + CHAR16 *NewString; + + ASSERT (Handle != NULL); + + if (Handle == NULL) { + return NULL; + } + + Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Get the device path by the got Driver handle . + // + Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); + if (EFI_ERROR (Status)) { + return NULL; + } + + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &PathToText + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Get device path string. + // + NewString = PathToText->ConvertDevicePathToText(DevicePath, FALSE, FALSE); + + return NewString; +} + +/** + Extract the displayed formset for given HII handle and class guid. + + @param Handle The HII handle. + @param SetupClassGuid The class guid specifies which form set will be displayed. + @param SkipCount Skip some formsets which has processed before. + @param FormSetTitle Formset title string. + @param FormSetHelp Formset help string. + @param FormSetGuid Formset Guid. + + @retval TRUE The formset for given HII handle will be displayed. + @return FALSE The formset for given HII handle will not be displayed. + +**/ +BOOLEAN +ExtractDisplayedHiiFormFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *SetupClassGuid, + IN UINTN SkipCount, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp, + OUT EFI_GUID *FormSetGuid + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT8 *Package; + UINT8 *OpCodeData; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + EFI_GUID *ClassGuid; + UINT8 ClassGuidNum; + BOOLEAN FoundAndSkip; + + ASSERT (Handle != NULL); + ASSERT (SetupClassGuid != NULL && FormSetTitle != NULL && FormSetHelp != NULL && FormSetGuid != NULL); + + *FormSetTitle = 0; + *FormSetHelp = 0; + ClassGuidNum = 0; + ClassGuid = NULL; + FoundAndSkip = FALSE; + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); + // + // Handle is a invalid handle. Check if Handle is corrupted. + // + ASSERT (Status != EFI_NOT_FOUND); + // + // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. + // + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + HiiPackageList = AllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + Offset += PackageHeader.Length; + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search FormSet Opcode in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { + // + // Find FormSet OpCode + // + ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); + ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET)); + while (ClassGuidNum-- > 0) { + if (CompareGuid (SetupClassGuid, ClassGuid)) { + // + // Check whether need to skip the formset. + // + if (SkipCount != 0) { + SkipCount--; + FoundAndSkip = TRUE; + break; + } + CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); + FreePool (HiiPackageList); + return TRUE; + } + ClassGuid ++; + } + if (FoundAndSkip) { + break; + } + } else if (CompareGuid (SetupClassGuid, &gEfiHiiPlatformSetupFormsetGuid)) { + // + // Check whether need to skip the formset. + // + if (SkipCount != 0) { + SkipCount--; + break; + } + CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); + FreePool (HiiPackageList); + return TRUE; + } + } + } + } + } + + FreePool (HiiPackageList); + + return FALSE; +} + +// +// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature. +// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if +// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection. +// + + +/** + Enable the setup browser reset reminder feature. + This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it. + +**/ +VOID +EFIAPI +EnableResetReminderFeature ( + VOID + ) +{ + mFeaturerSwitch = TRUE; +} + + +/** + Disable the setup browser reset reminder feature. + This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it. + +**/ +VOID +EFIAPI +DisableResetReminderFeature ( + VOID + ) +{ + mFeaturerSwitch = FALSE; +} + + +/** + Record the info that a reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +EnableResetRequired ( + VOID + ) +{ + mResetRequired = TRUE; +} + + +/** + Record the info that no reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +DisableResetRequired ( + VOID + ) +{ + mResetRequired = FALSE; +} + + +/** + Check whether platform policy enable the reset reminder feature. The default is enabled. + +**/ +BOOLEAN +EFIAPI +IsResetReminderFeatureEnable ( + VOID + ) +{ + return mFeaturerSwitch; +} + + +/** + Check if user changed any option setting which needs a system reset to be effective. + +**/ +BOOLEAN +EFIAPI +IsResetRequired ( + VOID + ) +{ + return mResetRequired; +} + + +/** + Check whether a reset is needed, and finish the reset reminder feature. + If a reset is needed, Popup a menu to notice user, and finish the feature + according to the user selection. + +**/ +VOID +EFIAPI +SetupResetReminder ( + VOID + ) +{ + EFI_INPUT_KEY Key; + CHAR16 *StringBuffer1; + CHAR16 *StringBuffer2; + + + // + //check any reset required change is applied? if yes, reset system + // + if (IsResetReminderFeatureEnable ()) { + if (IsResetRequired ()) { + + StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); + ASSERT (StringBuffer1 != NULL); + StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); + ASSERT (StringBuffer2 != NULL); + StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now."); + StrCpy (StringBuffer2, L"Press ENTER to reset"); + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool (StringBuffer1); + FreePool (StringBuffer2); + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } +} + + +/** + This function converts an input device structure to a Unicode string. + + @param DevPath A pointer to the device path structure. + + @return A new allocated Unicode string that represents the device path. + +**/ +CHAR16 * +UiDevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_STATUS Status; + CHAR16 *ToText; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + + if (DevPath == NULL) { + return NULL; + } + + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText + ); + ASSERT_EFI_ERROR (Status); + ToText = DevPathToText->ConvertDevicePathToText ( + DevPath, + FALSE, + TRUE + ); + ASSERT (ToText != NULL); + return ToText; +} diff --git a/MdeModulePkg/Application/UiApp/FrontPage.h b/MdeModulePkg/Application/UiApp/FrontPage.h new file mode 100644 index 0000000000..08d16929cf --- /dev/null +++ b/MdeModulePkg/Application/UiApp/FrontPage.h @@ -0,0 +1,278 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _FRONT_PAGE_H_ +#define _FRONT_PAGE_H_ + +#include "DeviceMngr/DeviceManager.h" +#include "BootMaint/BootMaint.h" +#include "BootMngr/BootManager.h" +#include "String.h" + +#include +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 FrontPageVfrBin[]; + +extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2; + +extern BOOLEAN gConnectAllHappened; + +#define SMBIOS_TYPE4_CPU_SOCKET_POPULATED BIT6 + +/// +/// The size of a 3 character ISO639 language code. +/// +#define ISO_639_2_ENTRY_SIZE 3 + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001 + +// +// These are defined as the same with vfr file +// +#define FRONT_PAGE_FORM_ID 0x1000 +#define INVALID_FORM_ID 0x0FFF + +#define FRONT_PAGE_KEY_SECTION 0x1000 +#define FRONT_PAGE_KEY_OFFSET 0x4000 +#define FRONT_PAGE_KEY_CONTINUE 0x1000 +#define FRONT_PAGE_KEY_LANGUAGE 0x1234 +#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064 +#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567 +#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876 +#define FRONT_PAGE_KEY_RESET 0X7654 + +#define LABEL_SELECT_LANGUAGE 0x1000 +#define LABEL_PLATFORM_INFORMATION 0x1001 +#define LABEL_END 0xffff + +#define FRONT_PAGE_FORMSET_GUID \ + { \ + 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \ + } + +#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('F', 'P', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + EFI_STRING_ID *LanguageToken; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} FRONT_PAGE_CALLBACK_DATA; + + +#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + FRONT_PAGE_CALLBACK_DATA, \ + ConfigAccess, \ + FRONT_PAGE_CALLBACK_DATA_SIGNATURE \ + ) + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request - A null-terminated Unicode string in format. + @param Progress - On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results - A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration - A null-terminated Unicode string in format. + @param Progress - A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function processes the results of changes in configuration. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action - Specifies the type of action taken by the browser. + @param QuestionId - A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type - The type of value for the question. + @param Value - A pointer to the data being sent to the original exporting driver. + @param ActionRequest - On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. + +**/ +EFI_STATUS +EFIAPI +FrontPageCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + Initialize HII information for the FrontPage + + @retval EFI_SUCCESS The operation is successful. + @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. + +**/ +EFI_STATUS +InitializeFrontPage ( + VOID + ); + +/** + Acquire the string associated with the ProducerGuid and return it. + + + @param ProducerGuid - The Guid to search the HII database for + @param Token - The token value of the string to extract + @param String - The string that is extracted + + @retval EFI_SUCCESS The function returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetProducerString ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID Token, + OUT CHAR16 **String + ); + +/** + This function is the main entry of the UI entry. + The function will present the main menu of the system UI. + + @param ConnectAllHappened Caller passes the value to UI to avoid unnecessary connect-all. + +**/ +VOID +EFIAPI +UiEntry ( + IN BOOLEAN ConnectAllHappened + ); + +/** + Extract the displayed formset for given HII handle and class guid. + + @param Handle The HII handle. + @param SetupClassGuid The class guid specifies which form set will be displayed. + @param SkipCount Skip some formsets which has processed before. + @param FormSetTitle Formset title string. + @param FormSetHelp Formset help string. + @param FormSetGuid Formset Guid. + + @retval TRUE The formset for given HII handle will be displayed. + @return FALSE The formset for given HII handle will not be displayed. + +**/ +BOOLEAN +ExtractDisplayedHiiFormFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *SetupClassGuid, + IN UINTN SkipCount, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp, + OUT EFI_GUID *FormSetGuid + ); + +/** + Extract device path for given HII handle and class guid. + + @param Handle The HII handle. + + @retval NULL Fail to get the device path string. + @return PathString Get the device path string. + +**/ +CHAR16 * +ExtractDevicePathFromHiiHandle ( + IN EFI_HII_HANDLE Handle + ); + +/** + This function will change video resolution and text mode + according to defined setup mode or defined boot mode + + @param IsSetupMode Indicate mode is changed to setup mode or boot mode. + + @retval EFI_SUCCESS Mode is changed successfully. + @retval Others Mode failed to be changed. + +**/ +EFI_STATUS +EFIAPI +BdsSetConsoleMode ( + BOOLEAN IsSetupMode + ); + +#endif // _FRONT_PAGE_H_ + diff --git a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..421db11cc4507ecbcb4a37ee9307b3cdd27de4d8 GIT binary patch literal 11190 zcmds->uwuG6vyW?67OK8LZzrpo3s>)0FjGREaEt_U3&Rq*>Nt0Bo4Nl5+170#5bCk z0RF!@p6sr7?W}EzqiALC?#%4WIsbE?-GBam=s3R6QE)%F1J`lKZr^?CKJo1ZwZ^Zx zuepKiY22wh)LmPndFoWZfqq?G_0@i$tDes58qs&VnzgBZYdyK@KT+Sl+Lsfn#8=$V zJZJ90uXyN=G`8SAcYE%h&a3W`jwiZ$FuYrFkKKJ;mqf)tGau`k8G4$7e`qiom({bT zen!BJ%?;%}JqJ}icdq}oX!}-NRNeOp8tbB^<2gOk$gZAeb~tNl?Y7PXjoA11d!o0i zzBAufO^7xI#~~0?&g#E$8|nyQXXDpSHK24rY&N z0h696fzLoEv_WxFeqG5bdTw1(-_-qff|fY7?>ruR`e)`O#~rQ8iXdW`v07jEaNZK7 zaj6s>*uueqdQ3vl{kujLL~ER`BsK+c)|9RkG^ah^9ijkDg9N&0(m)dV#_KscW(e~{ z&*QzUwR)24!x0Je)zT96ZE0O{{bkK^q+cAD_;ua==!&9lSK3r@&-K6N%DOKJ-GcDt zTvuyJ`u0LsMUVLlx1)1W?I2?_MDi#}zl$1C^D|d;gypmv{+_%02?}3o z1oKw>ng#b#UQJ#DO7*I34|u8rE#Sk`~7^H1u5b}X_uT*de( zx>r~8M6;KK#;$aXH8;oj1U%J4Pro7iox5{&cSrI-s}H?ZpeG#2^?`U}oh8joKXU6! zR!jcb?B@<7{ReK#^Sz`q_I>L9(m&5mdXg1wZC1oznyq2c*za^SOqwa1Dv-HzWnboN zOtTuEAEZ@x4Pm_|EiCE^8P3^P zk~q{hw(Ggy#L}VOPZsRVN;ZoC6e(PKb9>US0BU`nPc1CmEI7o$<@gn_dPdBj@LAD zOT8_P?6}`F;!-VS`Q+SbZl{YqC>R0EYCMCJZaH|D`@btZjZQyoZjN6U-yN+q2`^eZU(;p_U+X_G(u zB+Kqgk1C#gUp|Z71@mu@-81z*)Beh$(Ega*%p;q}Gs&jr(YHOGf_ysOh#iWab{|0e zjee_=$P-EAsryR4=9y$k6>k6RcWU|`jK1Qb zQI?<2ZO?~Q?d%U-4)24l#d)_jki>iAuLJ+%WK2D0yBa&H>8N~dFNPW~*ux_HyH&N<-<0_6MKw!RV-l?0ppvU zXFNeuqZq+hi+UDMi0KxqEo#U4C(CR~+vqv+S*Ohv>@VPODSN!UMh~`qw)tFE5%z@G z;bTW=V@}J!`vuhJV2?VoA1r}Z-T?d}G|7|5^n#_J58%w0FhkfK4cJF-X~Kv-&D8VOh@M5dNCvhz zN#Pqhq6R+?RmZB%l4wwS!6~`?v91~2yu!tLB19s2M~E;cvb1bV3{@>_7#icWV_k8k zBD-NHjVjJ;s;V_69eK2astR8hs%^8P;N>UHK7C&nJ?VIp^gM>#rnf5d=~jizhSxYd zGG4Oin>7ltNB^tWp$p-QPc=&lmT~iNpB!DzJr|)S1eNwM%2>omODIGQIJLMnjm&t{ zlSkk4$SjF9c^y%deV9{k;WtJ1voXA@m>vCbgcatKL4(=lQSLmy$My>WN*d0Vs@Gu%5Zou`rp;ik>3xM3mG3VEUFgM zH6Y%o;677)BVQ%wAUEc#qeaPS+uLT~!K$wiU0YYtHLISZ25I{^2iIwyz+%92ja zzvtS~y8_BUo{`&>~2v=Ur*C`&trQ&_8v43 zMxd7mrzL%TF&^nzda_m>^$n~#j@R(L4z`+4AM)~Am8N5J1L?;ixK6G=E&r1vO&02- zHW95KRoUqp+Pt<|%JRaInvT+Om|DKi4pBopL>289z8-nolcni-Fl7gG@)w^^<(K&O db4B~*d|OtMN1{UDjWkcEzxG^=c77~Q{sp=n_?7?w literal 0 HcmV?d00001 diff --git a/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr new file mode 100644 index 0000000000..4ede961745 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr @@ -0,0 +1,149 @@ +///** @file +// +// Browser formset. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//**/ + +#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } +#include "FormsetGuid.h" + +#define FRONT_PAGE_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0002 + +#define FRONT_PAGE_FORM_ID 0x1000 + +#define FRONT_PAGE_ITEM_ONE 0x0001 +#define FRONT_PAGE_ITEM_TWO 0x0002 +#define FRONT_PAGE_ITEM_THREE 0x0003 +#define FRONT_PAGE_ITEM_FOUR 0x0004 +#define FRONT_PAGE_ITEM_FIVE 0x0005 + +#define FRONT_PAGE_KEY_CONTINUE 0x1000 +#define FRONT_PAGE_KEY_LANGUAGE 0x1234 +#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064 +#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567 +#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876 + +#define LABEL_SELECT_LANGUAGE 0x1000 +#define LABEL_TIMEOUT 0x2000 +#define LABEL_END 0xffff + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = FORMSET_GUID, + + form formid = FRONT_PAGE_FORM_ID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), + line 1, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), + line 2, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), + line 2, + align right; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), + line 3, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), + line 3, + align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT), +// line 0, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT), +// line 0, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT), +// line 1, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT), +// line 1, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT), +// line 2, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT), +// line 3, +// align left; + + + text + help = STRING_TOKEN(STR_CONTINUE_HELP), + text = STRING_TOKEN(STR_CONTINUE_PROMPT), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_CONTINUE; + + label LABEL_SELECT_LANGUAGE; + // + // This is where we will dynamically add a OneOf type op-code to select + // Languages from the currently available choices + // + label LABEL_END; + + goto + formsetguid = DEVICE_MANAGER_FORMSET_GUID, + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_EDKII_MENU), + help = STRING_TOKEN(STR_EDKII_MENU_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_DEVICE_MANAGER; + + + goto + formsetguid = BOOT_MANAGER_FORMSET_GUID , + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_BOOT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MANAGER_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_BOOT_MANAGER; + + + goto + formsetguid = BOOT_MAINT_FORMSET_GUID, + formid = 0, + question = 0, + prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP), + flags = INTERACTIVE, + key = FRONT_PAGE_KEY_BOOT_MAINTAIN; + + endform; + +endformset; diff --git a/MdeModulePkg/Application/UiApp/Language.c b/MdeModulePkg/Application/UiApp/Language.c new file mode 100644 index 0000000000..bd19f6462e --- /dev/null +++ b/MdeModulePkg/Application/UiApp/Language.c @@ -0,0 +1,309 @@ +/** @file + Language settings + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Language.h" +#include "FrontPage.h" + +EFI_GUID mFontPackageGuid = { + 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc} +}; + +#define NARROW_GLYPH_NUMBER 8 +#define WIDE_GLYPH_NUMBER 75 + +typedef struct { + /// + /// This 4-bytes total array length is required by HiiAddPackages() + /// + UINT32 Length; + + // + // This is the Font package definition + // + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; + EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; +} FONT_PACK_BIN; + +FONT_PACK_BIN mFontBin = { + sizeof (FONT_PACK_BIN), + { + sizeof (FONT_PACK_BIN) - sizeof (UINT32), + EFI_HII_PACKAGE_SIMPLE_FONTS, + }, + NARROW_GLYPH_NUMBER, + 0, + { // Narrow Glyphs + { + 0x05d0, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x4E, + 0x6E, + 0x62, + 0x32, + 0x32, + 0x3C, + 0x68, + 0x4C, + 0x4C, + 0x46, + 0x76, + 0x72, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d1, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x7E, + 0x7E, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d2, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x1C, + 0x3E, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d3, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7E, + 0x7E, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d4, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7C, + 0x7E, + 0x06, + 0x06, + 0x06, + 0x06, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d5, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x3C, + 0x3C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d6, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x1E, + 0x1E, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x0000, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + } + } + } +}; + +/** + Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. + +**/ +EFI_HII_HANDLE +ExportFonts ( + VOID + ) +{ + return HiiAddPackages ( + &mFontPackageGuid, + gImageHandle, + &mFontBin, + NULL + ); +} + +/** + Get next language from language code list (with separator ';'). + + If LangCode is NULL, then ASSERT. + If Lang is NULL, then ASSERT. + + @param LangCode On input: point to first language in the list. On + output: point to next language in the list, or + NULL if no more language in the list. + @param Lang The first language in the list. + +**/ +VOID +EFIAPI +GetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ) +{ + UINTN Index; + CHAR8 *StringPtr; + + ASSERT (LangCode != NULL); + ASSERT (*LangCode != NULL); + ASSERT (Lang != NULL); + + Index = 0; + StringPtr = *LangCode; + while (StringPtr[Index] != 0 && StringPtr[Index] != ';') { + Index++; + } + + CopyMem (Lang, StringPtr, Index); + Lang[Index] = 0; + + if (StringPtr[Index] == ';') { + Index++; + } + *LangCode = StringPtr + Index; +} \ No newline at end of file diff --git a/MdeModulePkg/Application/UiApp/Language.h b/MdeModulePkg/Application/UiApp/Language.h new file mode 100644 index 0000000000..c294e6c392 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/Language.h @@ -0,0 +1,48 @@ +/** @file + Language setting + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LANGUAGE_H_ +#define _LANGUAGE_H_ + +#include "String.h" + +/** + Get next language from language code list (with separator ';'). + + If LangCode is NULL, then ASSERT. + If Lang is NULL, then ASSERT. + + @param LangCode On input: point to first language in the list. On + output: point to next language in the list, or + NULL if no more language in the list. + @param Lang The first language in the list. + +**/ +VOID +EFIAPI +GetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ); + +/** + Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. + +**/ +EFI_HII_HANDLE +ExportFonts ( + VOID + ); + +#endif // _LANGUAGE_H_ diff --git a/MdeModulePkg/Application/UiApp/String.c b/MdeModulePkg/Application/UiApp/String.c new file mode 100644 index 0000000000..ad3ba57771 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/String.c @@ -0,0 +1,67 @@ +/** @file + String support + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ui.h" +#include "Language.h" +#include "FrontPage.h" + +EFI_HII_HANDLE gStringPackHandle; + +EFI_GUID mUiStringPackGuid = { + 0x136a3048, 0x752a, 0x4bf6, { 0xa7, 0x57, 0x9, 0x36, 0x11, 0x95, 0x38, 0xed } +}; + +/** + Initialize HII global accessor for string support. + +**/ +VOID +InitializeStringSupport ( + VOID + ) +{ + gStringPackHandle = HiiAddPackages ( + &mUiStringPackGuid, + gImageHandle, + UiAppStrings, + NULL + ); + ASSERT (gStringPackHandle != NULL); +} + +VOID +UninitializeStringSupport ( + VOID + ) +{ + HiiRemovePackages (gStringPackHandle); +} + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (gStringPackHandle, Id, NULL); +} diff --git a/MdeModulePkg/Application/UiApp/String.h b/MdeModulePkg/Application/UiApp/String.h new file mode 100644 index 0000000000..1a0636698a --- /dev/null +++ b/MdeModulePkg/Application/UiApp/String.h @@ -0,0 +1,76 @@ +/** @file + String support + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _STRING_H_ +#define _STRING_H_ + +extern EFI_HII_HANDLE gStringPackHandle; + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// + +extern UINT8 BdsDxeStrings[]; + +// +// String Definition Guid for BDS Platform +// +#define EFI_BDS_PLATFORM_GUID \ + { \ + 0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \ + } + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ); + +/** + Initialize HII global accessor for string support. + +**/ +VOID +InitializeStringSupport ( + VOID + ); + +VOID +UninitializeStringSupport ( + VOID + ); + +/** + Call the browser and display the front page + + @return Status code that will be returned by + EFI_FORM_BROWSER2_PROTOCOL.SendForm (). + +**/ +EFI_STATUS +CallFrontPage ( + VOID + ); + +#endif // _STRING_H_ diff --git a/MdeModulePkg/Application/UiApp/Strings.uni b/MdeModulePkg/Application/UiApp/Strings.uni new file mode 100644 index 0000000000000000000000000000000000000000..7b101aa6e47b95e5a1a23ba3b4cc2f2e2c912f12 GIT binary patch literal 4702 zcmc(jYi}Dx6o$`dB>uxH`9O;r2axzu0mAVmSR`?jI244C<=C-n$%#|jY3VPn@+W}j zos-GVuGYbnO4iCdvvWD~p7&g4#()2{Z+gDu$?QiP+tg-uWuMz;p*^EDt?T>TR<>Z= zjZOF(FbjJOKlLlDmCyA6HsndfX>2RvG7N^OR;RM!FR znm?m=NKH%%PricYi*dEQ*Vteuyd2| zqXL!`?YqFokhdfkHJ-AnRum)7nO0l!EzK`Mnp!0@aVrhR^tgqD`%gw?U`=rqxyjIM zfOllb^!f7#7KCY4U{}7g!Xht&XUnUcVa-?szH6+tz^?lx3oL251pUbNN4O2EQtMw07{f3u>*v`GuWOwrCeKE+Mx^2mfv{;yg(1 zQj=fny+bLvlDb2A5We;GqJZ!fBP6#Q*39e`~ z1IASP|F2i!OPO+fvV&*dH^h_jlIJ94KF>inK{L-@jy>XC$LA3`9>Qb;-|FMdU7jAb zdIgKQo>h1^;qwT56SNqHd~!f8n1fut{c@|!3YYS*&@HKz8Es&H?HukoDcW_sdNxuP zIp+G3FMjN&}u<83q z9urlyP3#%1CLDg+@bi&kUYW2;?#H)PAu4AYXHvMdn=3Nv>>Cl!zcX~szR(Ces5p9> zrz$+D%1otRm9Zz?gHJIzE#O+mn7ENQUEod1 zxyl5`wE3Aqc|v>s2`xIM#HR{ZnXx9^jPWL&^yKH4*wQnt@`ZMdA?n_dx&Y^vC1Rs8HiszGfRxX|} zl&u@#?A0W5Z>njPE@i7Yns_sar=3k#*lb)CjxwjZ{rKHM>_j|jd72rWFLkQz6V*DQ zK7B@rc&iYVnQ3tk(M_p|jaK}$Uu`S6=(ckVQ|TEfdP!Pt<}vZi>)d3>*UeIQRh``PJ)?M@sIimPw&q(i l`-1Eu-91_Ao^Q`&(jn%yRJ&A%e*l2LfA|0Z literal 0 HcmV?d00001 diff --git a/MdeModulePkg/Application/UiApp/Ui.h b/MdeModulePkg/Application/UiApp/Ui.h new file mode 100644 index 0000000000..6075b642ff --- /dev/null +++ b/MdeModulePkg/Application/UiApp/Ui.h @@ -0,0 +1,179 @@ +/** @file + FrontPage routines to handle the callbacks and browser calls + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _BDS_MODULE_H_ +#define _BDS_MODULE_H_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#pragma pack(1) + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#pragma pack() + + +// +//The interface functions related to the Setup Browser Reset Reminder feature +// +/** + Enable the setup browser reset reminder feature. + This routine is used in a platform tip. If the platform policy needs the feature, use the routine to enable it. + +**/ +VOID +EFIAPI +EnableResetReminderFeature ( + VOID + ); + +/** + Disable the setup browser reset reminder feature. + This routine is used in a platform tip. If the platform policy does not want the feature, use the routine to disable it. + +**/ +VOID +EFIAPI +DisableResetReminderFeature ( + VOID + ); + +/** + Record the info that a reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +EnableResetRequired ( + VOID + ); + + +/** + Record the info that no reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +DisableResetRequired ( + VOID + ); + +/** + Check whether platform policy enables the reset reminder feature. The default is enabled. + +**/ +BOOLEAN +EFIAPI +IsResetReminderFeatureEnable ( + VOID + ); + +/** + Check if the user changed any option setting that needs a system reset to be effective. + +**/ +BOOLEAN +EFIAPI +IsResetRequired ( + VOID + ); + +/** + Check whether a reset is needed, and finish the reset reminder feature. + If a reset is needed, pop up a menu to notice user, and finish the feature + according to the user selection. + +**/ +VOID +EFIAPI +SetupResetReminder ( + VOID + ); + +/** + This function converts an input device structure to a Unicode string. + + @param DevPath A pointer to the device path structure. + + @return A new allocated Unicode string that represents the device path. + +**/ +CHAR16 * +UiDevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); +#endif diff --git a/MdeModulePkg/Application/UiApp/UiApp.inf b/MdeModulePkg/Application/UiApp/UiApp.inf new file mode 100644 index 0000000000..ba2b7b1edc --- /dev/null +++ b/MdeModulePkg/Application/UiApp/UiApp.inf @@ -0,0 +1,143 @@ +## @file +# UiApp module is driver for BDS phase. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UiApp + FILE_GUID = 462CAA21-7614-4503-836E-8AB6F4662331 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeUserInterface + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + FrontPage.h + Ui.h + BootMngr/BootManager.h + BootMaint/BootMaint.h + BootMaint/FormGuid.h + + DeviceMngr/DeviceManager.h + DeviceMngr/DeviceManagerVfr.Vfr + DeviceMngr/DeviceManagerStrings.uni + DeviceMngr/DeviceManager.c + BootMngr/BootManagerVfr.Vfr + BootMngr/BootManagerStrings.uni + BootMngr/BootManager.c + BootMaint/FE.vfr + BootMaint/FileExplorer.c + BootMaint/BootMaint.c + BootMaint/UpdatePage.c + BootMaint/Variable.c + BootMaint/Data.c + BootMaint/ConsoleOption.c + BootMaint/BootOption.c + BootMaint/BmLib.c + BootMaint/Bm.vfr + BootMaint/Bmstring.uni + FrontPageVfr.Vfr + FrontPageStrings.uni + Strings.uni + FrontPage.c + String.c + String.h + Language.c + Language.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + HobLib + UefiRuntimeServicesTableLib + ReportStatusCodeLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + HiiLib + UefiApplicationEntryPoint + PcdLib + UefiHiiServicesLib + UefiBootManagerLib + +[Guids] + gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootNext" (The number of next boot option) + ## SOMETIMES_PRODUCES ## Variable:L"BootXX" (Boot option variable) + ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" (Platform supported languange in Rfc4646 format) + ## SOMETIMES_PRODUCES ## Variable:L"Lang" (Platform supported languange in Iso639 format) + ## SOMETIMES_PRODUCES ## Variable:L"KeyXX" (Hotkey option variable) + ## PRODUCES ## Variable:L"HwErrRecSupport" (The level of platform supported hardware Error Record Persistence) + ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" (The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP + ## SOMETIMES_PRODUCES (not PcdUefiVariableDefaultLangDeprecate)## Variable:L"LangCodes" (Value of PcdUefiVariableDefaultLangCodes) + ## PRODUCES ## Variable:L"PlatformLangCodes" (Value of PcdUefiVariableDefaultPlatformLangCodes) + ## PRODUCES ## Variable:L"Timeout" (The time out value in second of showing progress bar) + ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" (The boot option array) + ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" (The driver order list) + ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device) + ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device) + ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device) + gEfiFileSystemVolumeLabelInfoIdGuid ## CONSUMES ## GUID (Indicate the information type is volume) + gEfiFileInfoGuid ## CONSUMES ## GUID (Indicate the information type is file) + gEfiHiiPlatformSetupFormsetGuid ## CONSUMES ## GUID (Indicate the formset class guid to be displayed) + gEfiIfrTianoGuid ## CONSUMES ## GUID (Extended IFR Guid Opcode) + gEfiHiiDriverHealthFormsetGuid ## CONSUMES ## GUID (Indicate the Driver Health formset class guid to be displayed) + gEfiIfrBootMaintenanceGuid ## CONSUMES ## GUID + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## PROTOCOL CONSUMES + gEfiLoadFileProtocolGuid ## PROTOCOL CONSUMES + gEfiSmbiosProtocolGuid ## PROTOCOL CONSUMES + gEfiGenericMemTestProtocolGuid ## PROTOCOL CONSUMES + gEfiLegacyBiosProtocolGuid ## PROTOCOL CONSUMES + gEfiUgaDrawProtocolGuid |PcdUgaConsumeSupport ## PROTOCOL SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## PROTOCOL CONSUMES + gEfiGraphicsOutputProtocolGuid ## PROTOCOL SOMETIMES_CONSUMES + gEfiSimpleTextInputExProtocolGuid ## PROTOCOL CONSUMES + gEfiHiiConfigAccessProtocolGuid ## PROTOCOL CONSUMES + gEfiFormBrowser2ProtocolGuid ## PROTOCOL CONSUMES + gEfiSerialIoProtocolGuid ## PROTOCOL CONSUMES + gEfiDevicePathProtocolGuid ## PROTOCOL CONSUMES + gEfiPciIoProtocolGuid ## PROTOCOL CONSUMES + gEfiDevicePathToTextProtocolGuid ## PROTOCOL CONSUMES + gEfiBootLogoProtocolGuid ## PROTOCOL CONSUMES + +[FeaturePcd] + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString diff --git a/MdeModulePkg/Include/Guid/HiiBootMaintenanceFormset.h b/MdeModulePkg/Include/Guid/HiiBootMaintenanceFormset.h new file mode 100644 index 0000000000..96c39f977d --- /dev/null +++ b/MdeModulePkg/Include/Guid/HiiBootMaintenanceFormset.h @@ -0,0 +1,29 @@ +// +/** @file + Guid definition for Boot Maintainence Formset. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __HII_BOOT_MAINTENANCE_FORMSET_H__ +#define __HII_BOOT_MAINTENANCE_FORMSET_H__ + +/// +/// Guid define to group the item show on the Boot Menaintenance Manager Menu. +/// +#define EFI_IFR_BOOT_MAINTENANCE_GUID \ + { 0xb2dedc91, 0xd59f, 0x48d2, { 0x89, 0x8a, 0x12, 0x49, 0xc, 0x74, 0xa4, 0xe0 } } + + +extern EFI_GUID gEfiIfrBootMaintenanceGuid; + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 613c331f8e..25e3e1d019 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -309,6 +309,9 @@ ## Include/Guid/TtyTerm.h gEfiTtyTermGuid = { 0x7d916d80, 0x5bb1, 0x458c, {0xa4, 0x8f, 0xe2, 0x5f, 0xdd, 0x51, 0xef, 0x94 }} + ## Include/Guid/HiiBootMaintenanceFormset.h + gEfiIfrBootMaintenanceGuid = { 0xb2dedc91, 0xd59f, 0x48d2, { 0x89, 0x8a, 0x12, 0x49, 0xc, 0x74, 0xa4, 0xe0 }} + [Ppis] ## Include/Ppi/AtaController.h gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }} diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index be67e9d17b..20edc08fec 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -280,6 +280,7 @@ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf + MdeModulePkg/Application/UiApp/UiApp.inf MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf MdeModulePkg/Universal/CapsulePei/CapsulePei.inf -- 2.39.2