alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/ServiceBody/L05NovoButtonMenu/L05NovoButtonMenu.c

329 lines
9.7 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2012 - 2018, Insyde Software Corporation. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "L05NovoButtonMenu.h"
CHAR16 *mOptionStringList[] = {
NOVO_BUTTON_MENU_NORMAL_STARTUP_STRING,
NOVO_BUTTON_MENU_SETUP_STRING,
NOVO_BUTTON_MENU_BOOT_MANAGER_STRING,
NOVO_BUTTON_MENU_ONEKEY_RECOVERY_STRING,
NOVO_BUTTON_MENU_UEFI_DIAGNOSTICS_STRING,
};
UINTN mOptionStringListCount = sizeof (mOptionStringList) / sizeof (CHAR16 *);
UINTN mMaxColumn;
UINTN mMaxRow;
BOOLEAN mFindSystemRecovery = FALSE;
BOOLEAN mFindDiagnostics = FALSE;
UINTN
PrintAt (
IN UINTN Column,
IN UINTN Row,
IN CHAR16 *Fmt,
...
)
{
CHAR16 *Buffer;
UINTN StrLen;
VA_LIST Marker;
Buffer = AllocateZeroPool (0x10000);
ASSERT (Buffer);
if (Column != (UINTN) -1) {
gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
}
VA_START (Marker, Fmt);
StrLen = UnicodeVSPrint (Buffer, 0x10000 , Fmt, Marker);
VA_END (Marker);
if (gST->ConOut != NULL) {
gST->ConOut->OutputString (gST->ConOut, Buffer);
}
gBS->FreePool (Buffer);
return StrLen;
}
VOID
DrawNovoButtonMenuDialog (
IN UINTN DialogColumn,
IN UINTN DialogRow
)
{
UINTN Index;
UINTN Color;
UINTN LeftCol;
UINTN RightCol;
UINTN UpRow;
UINTN DownRow;
CHAR16 CleanLine[MAX_STRING_LENGTH];
LeftCol = (mMaxColumn - DialogColumn) / 2;
RightCol = LeftCol + DialogColumn + 1;
UpRow = (mMaxRow - DialogRow) / 2 ;
DownRow = UpRow + DialogRow + 1;
if (!mFindSystemRecovery) {
DownRow--;
}
if (!mFindDiagnostics) {
DownRow--;
}
Color = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLUE);
gST->ConOut->SetAttribute (gST->ConOut, Color);
for (Index = 0; Index <= DialogColumn; Index++) {
CleanLine[Index] = 0x20;
}
CleanLine[Index] = 0;
for (Index = UpRow; Index <= DownRow; Index++) {
PrintAt (LeftCol, Index, L"%s", CleanLine);
}
for (Index = LeftCol; Index < RightCol; Index++) {
PrintAt (Index, UpRow, L"%c", BOXDRAW_HORIZONTAL);
PrintAt (Index, UpRow + 2, L"%c", BOXDRAW_HORIZONTAL);
PrintAt (Index, DownRow, L"%c", BOXDRAW_HORIZONTAL);
}
for (Index = UpRow; Index < DownRow; Index++) {
PrintAt (LeftCol, Index, L"%c", BOXDRAW_VERTICAL);
PrintAt (RightCol, Index, L"%c", BOXDRAW_VERTICAL);
}
PrintAt (RightCol, DownRow, L"%c", BOXDRAW_UP_LEFT);
PrintAt (RightCol, UpRow, L"%c", BOXDRAW_DOWN_LEFT);
PrintAt (LeftCol, DownRow, L"%c", BOXDRAW_UP_RIGHT);
PrintAt (LeftCol, UpRow, L"%c", BOXDRAW_DOWN_RIGHT);
PrintAt (LeftCol, UpRow + 2, L"%c", BOXDRAW_VERTICAL_RIGHT);
PrintAt (RightCol, UpRow + 2, L"%c", BOXDRAW_VERTICAL_LEFT);
PrintAt (LeftCol + 1, UpRow + 1, L"%s", NOVO_BUTTON_MENU_TITLE_STRING);
Color = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK);
gST->ConOut->SetAttribute (gST->ConOut, Color);
PrintAt ((mMaxColumn - (StrSize (NOVO_BUTTON_MENU_HELP_STRING) / sizeof (CHAR16))) / 2, mMaxRow - 1, L"%s", NOVO_BUTTON_MENU_HELP_STRING);
}
VOID
DrawNovoButtonMenuOptionArea (
IN UINTN DialogColumn,
IN UINTN DialogRow,
IN UINTN MaxSelection,
IN UINT16 Selection
)
{
UINTN Index;
UINTN Index_Row;
UINTN NormalColor;
UINTN HighLightColor;
UINTN LeftCol;
UINTN UpRow;
Index_Row = 0;
LeftCol = (mMaxColumn - DialogColumn) / 2;
UpRow = (mMaxRow - DialogRow) / 2 ;
NormalColor = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLUE);
HighLightColor = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_CYAN);
for (Index = 0; Index < MaxSelection; Index++) {
if (Selection == Index) {
gST->ConOut->SetAttribute (gST->ConOut, HighLightColor);
} else {
gST->ConOut->SetAttribute (gST->ConOut, NormalColor);
}
if (((!mFindSystemRecovery) && (Index == NovoButtonMenuOneKey)) ||
((!mFindDiagnostics) && (Index == NovoButtonMenuDiagnostics))) {
//
// 1. [Lenovo China Minimum BIOS Spec 1.39]
// [3.3.3.3 Novo button power on Menu]
// 5 System Recovery item must be hidden if the recovery partition do not exist.
// 2. Skip inactive items.
//
continue;
}
PrintAt (LeftCol + 1, UpRow + 3 + Index_Row, L"%s", mOptionStringList[Index]);
Index_Row++;
}
}
EFI_STATUS
L05NovoButtonMenu (
IN OUT UINTN *L05NovoButtonMenuSelection
)
{
EFI_STATUS Status;
UINT16 Selection;
EFI_INPUT_KEY Key;
UINTN OldAttribute;
UINTN OldColumn;
UINTN OldRow;
UINTN DialogColumn;
UINTN DialogRow;
UINTN MaxSelection;
UINT16 Count;
UINT16 MaxSkip;
Status = EFI_UNSUPPORTED;
Selection = 0;
MaxSkip = 0;
//
// Init environment variable
//
gST->ConOut->QueryMode (
gST->ConOut,
gST->ConOut->Mode->Mode,
&mMaxColumn,
&mMaxRow
);
#ifdef L05_ONE_KEY_RECOVERY_ENABLE
mFindSystemRecovery = mFindSystemRecovery | IsOkrSystemRecovery ();
#endif
#ifdef L05_PUSH_BUTTON_RESET_ENABLE
mFindSystemRecovery = mFindSystemRecovery | IsPbrSystemRecovery ();
#endif
#ifdef L05_DIAGNOSTICS_SUPPORT
mFindDiagnostics = TRUE;
#endif
if (mFindSystemRecovery == FALSE) {
MaxSkip++;
}
if (mFindDiagnostics == FALSE) {
MaxSkip++;
}
//
// By L05 Dual mode BIOS spec v0.1a, show Novo menu when pressed Novo Menu.
//
MaxSelection = mOptionStringListCount;
DialogColumn = NOVO_BUTTON_MENU_STRING_MAX_LENGTH;
DialogRow = MaxSelection + 2;
DisableQuietBoot ();
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
gST->ConOut->ClearScreen (gST->ConOut);
OldAttribute = gST->ConOut->Mode->Attribute;
OldColumn = gST->ConOut->Mode->CursorColumn;
OldRow = gST->ConOut->Mode->CursorRow;
//
// Draw Menu dialog
//
DrawNovoButtonMenuDialog (DialogColumn, DialogRow);
//
// Process input
//
do {
DrawNovoButtonMenuOptionArea (DialogColumn, DialogRow, MaxSelection, Selection);
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (!EFI_ERROR (Status)) {
if (Key.ScanCode == SCAN_UP) {
if (Selection != 0) {
Selection--;
}
} else if (Key.ScanCode == SCAN_DOWN) {
if (Selection != MaxSelection - 1) {
Selection++;
}
} else if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
break;
}
Count = 0;
while (((!mFindSystemRecovery) && (Selection == NovoButtonMenuOneKey)) ||
((!mFindDiagnostics) && (Selection == NovoButtonMenuDiagnostics))) {
//
// 1. [Lenovo China Minimum BIOS Spec 1.39]
// [3.3.3.3 Novo button power on Menu]
// 5 System Recovery item must be hidden if the recovery partition do not exist.
// 2. Skip inactive items.
//
if (Key.ScanCode == SCAN_UP) {
if (Selection != 0) {
Selection--;
}
} else if (Key.ScanCode == SCAN_DOWN) {
if (Selection != MaxSelection - 1) {
Selection++;
}
}
//
// Special handling for consecutive hidden items
//
Count++;
if ((Count >= MaxSkip) && (Selection == (MaxSelection - 1))) {
if (Key.ScanCode == SCAN_UP) {
Selection = Selection + MaxSkip;
} else if (Key.ScanCode == SCAN_DOWN) {
Selection = Selection - MaxSkip;
}
break;
}
}
}
} while (TRUE);
gST->ConOut->SetAttribute (gST->ConOut, OldAttribute);
gST->ConOut->SetCursorPosition (gST->ConOut, OldColumn, OldRow);
Status = EFI_SUCCESS;
switch (Selection) {
case NovoButtonMenuNormalBoot:
case NovoButtonMenuSetup:
case NovoButtonMenuBootManager:
case NovoButtonMenuOneKey:
case NovoButtonMenuDiagnostics:
//
// Enter One Key Recovery would be handled by NovoRecovery function.
//
default:
*L05NovoButtonMenuSelection = Selection;
break;
}
gST->ConOut->ClearScreen (gST->ConOut);
return Status;
}