Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 49 additions & 15 deletions SetupDataPkg/ConfApp/BootOptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@

#include "ConfApp.h"

#define STATIC_BOOT_OPTIONS 2
#define STATIC_BOOT_OPTIONS 2
#define MAX_BOOT_OPTION_INPUT_DIGITS 5

CONST ConfAppKeyOptions StaticBootOptions[STATIC_BOOT_OPTIONS] = {
{
.KeyName = NULL,
.KeyNameTextAttr = EFI_TEXT_ATTR (EFI_YELLOW, EFI_BLACK),
.Description = L"\n\tSelect Index to boot to the corresponding option.\n",
.Description = L"\n\tType index number and press Enter to boot to the corresponding option.\n",
.DescriptionTextAttr = EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK),
.UnicodeChar = CHAR_NULL,
.ScanCode = SCAN_NULL,
Expand All @@ -47,9 +48,11 @@ BootOptState_t mBootOptState = BootOptInit;
EFI_BOOT_MANAGER_LOAD_OPTION *mBootOptions = NULL;
UINTN mBootOptionCount = 0;
UINT16 mOpCandidate;
ConfAppKeyOptions *mKeyOptions = NULL;
UINTN mOptionCount = 0;
CHAR16 *mKeyNames = NULL;
ConfAppKeyOptions *mKeyOptions = NULL;
UINTN mOptionCount = 0;
CHAR16 *mKeyNames = NULL;
CHAR16 mInputBuffer[MAX_BOOT_OPTION_INPUT_DIGITS + 1] = { CHAR_NULL };
UINTN mInputLen = 0;

/**
Helper internal function to reset all local variable in this file.
Expand All @@ -65,6 +68,9 @@ ResetGlobals (
mBootOptionCount = 0;
mOpCandidate = 0;

mInputBuffer[0] = CHAR_NULL;
mInputLen = 0;

mOptionCount = 0;
if (mKeyOptions != NULL) {
FreePool (mKeyOptions);
Expand Down Expand Up @@ -105,9 +111,9 @@ PrintBootOptions (
mKeyOptions[OptionIndex].KeyNameTextAttr = EFI_TEXT_ATTR (EFI_YELLOW, EFI_BLACK);
mKeyOptions[OptionIndex].Description = mBootOptions[OptionIndex].Description;
mKeyOptions[OptionIndex].DescriptionTextAttr = EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK);
mKeyOptions[OptionIndex].UnicodeChar = (CHAR16)(OptionIndex + '1');
mKeyOptions[OptionIndex].UnicodeChar = CHAR_NULL;
mKeyOptions[OptionIndex].ScanCode = SCAN_NULL;
mKeyOptions[OptionIndex].EndState = BootOptBootNow;
mKeyOptions[OptionIndex].EndState = MAX_UINT32;
}

CopyMem (&mKeyOptions[OptionIndex], StaticBootOptions, sizeof (ConfAppKeyOptions) * STATIC_BOOT_OPTIONS);
Expand Down Expand Up @@ -162,14 +168,42 @@ BootOptionMgr (
DEBUG ((DEBUG_ERROR, "%a Error occurred waiting for key stroke - %r\n", __func__, Status));
ASSERT (FALSE);
} else {
Status = CheckSupportedOptions (&KeyData, mKeyOptions, mOptionCount, (UINT32 *)&mBootOptState);
if (Status == EFI_NOT_FOUND) {
Status = EFI_SUCCESS;
} else if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Error processing incoming keystroke - %r\n", __func__, Status));
ASSERT (FALSE);
} else {
mOpCandidate = KeyData.Key.UnicodeChar - '1';
if ((KeyData.Key.ScanCode == SCAN_ESC) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
mInputLen = 0;
mInputBuffer[0] = CHAR_NULL;
mBootOptState = BootOptExit;
} else if (KeyData.Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
if (mInputLen > 0) {
UINTN Selection;
UINTN DigitIndex;

Selection = 0;
for (DigitIndex = 0; DigitIndex < mInputLen; DigitIndex++) {
Selection = Selection * 10 + (mInputBuffer[DigitIndex] - '0');
}

mInputLen = 0;
mInputBuffer[0] = CHAR_NULL;
if ((Selection >= 1) && (Selection <= mBootOptionCount)) {
mOpCandidate = (UINT16)(Selection - 1);
mBootOptState = BootOptBootNow;
}
}
} else if (KeyData.Key.UnicodeChar == CHAR_BACKSPACE) {
if (mInputLen > 0) {
mInputLen--;
mInputBuffer[mInputLen] = CHAR_NULL;
Print (L"%c %c", CHAR_BACKSPACE, CHAR_BACKSPACE);
}
} else if ((KeyData.Key.UnicodeChar >= '0') && (KeyData.Key.UnicodeChar <= '9')) {
// Ignore a leading zero
if (!((mInputLen == 0) && (KeyData.Key.UnicodeChar == '0'))) {
if (mInputLen < MAX_BOOT_OPTION_INPUT_DIGITS) {
mInputBuffer[mInputLen++] = KeyData.Key.UnicodeChar;
mInputBuffer[mInputLen] = CHAR_NULL;
Print (L"%c", KeyData.Key.UnicodeChar);
}
}
}
}

Expand Down
109 changes: 109 additions & 0 deletions SetupDataPkg/ConfApp/UnitTest/ConfAppBootOptionUnitTest.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,14 @@ ConfAppBootOptSelectOne (
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptWait);

KeyData1.Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptBootNow);
Expand Down Expand Up @@ -555,6 +563,14 @@ ConfAppBootOptSelectMore (
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptWait);

KeyData1.Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptBootNow);
Expand All @@ -572,6 +588,98 @@ ConfAppBootOptSelectMore (
return UNIT_TEST_PASSED;
}

/**
Unit test for BootOptions page when selecting boot option 10 (two-digit input).

@param[in] Context [Optional] An optional parameter that enables:
1) test-case reuse with varied parameters and
2) test-case re-entry for Target tests that need a
reboot. This parameter is a VOID* and it is the
responsibility of the test author to ensure that the
contents are well understood by all test cases that may
consume it.

@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
ConfAppBootOptSelect10 (
IN UNIT_TEST_CONTEXT Context
)
{
EFI_STATUS Status;
EFI_KEY_DATA KeyData1;
UINTN Index;

EFI_BOOT_MANAGER_LOAD_OPTION BootOptions[10];

for (Index = 0; Index < 10; Index++) {
BootOptions[Index].Description = L"TestOption";
BootOptions[Index].Attributes = 0;
}

BootOptions[9].Description = L"Test10";
BootOptions[9].Attributes = 0xDEADBEEF;

will_return (MockClearScreen, EFI_SUCCESS);
will_return_always (MockSetAttribute, EFI_SUCCESS);

expect_any (MockSetCursorPosition, Column);
expect_any (MockSetCursorPosition, Row);
will_return (MockSetCursorPosition, EFI_SUCCESS);

will_return (EfiBootManagerGetLoadOptions, 10);
will_return (EfiBootManagerGetLoadOptions, BootOptions);

// Initial run
Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptWait);

mSimpleTextInEx = &MockSimpleInput;

// Press '1'
KeyData1.Key.UnicodeChar = '1';
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptWait);

// Press '0'
KeyData1.Key.UnicodeChar = '0';
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptWait);

// Press Enter to confirm
KeyData1.Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
KeyData1.Key.ScanCode = SCAN_NULL;
will_return (MockReadKey, &KeyData1);

Status = BootOptionMgr ();
UT_ASSERT_NOT_EFI_ERROR (Status);
UT_ASSERT_EQUAL (mBootOptState, BootOptBootNow);

expect_memory (EfiBootManagerBoot, BootOption, &BootOptions[9], sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
will_return (EfiBootManagerBoot, EFI_SUCCESS);

gResetCalled = FALSE;
expect_value (ResetSystemWithSubtype, ResetType, EfiResetCold);
expect_value (ResetSystemWithSubtype, ResetSubtype, &gConfAppResetGuid);

BootOptionMgr ();
UT_ASSERT_TRUE (gResetCalled);

return UNIT_TEST_PASSED;
}

/**
Initialize the unit test framework, suite, and unit tests for the
ConfApp and run the ConfApp unit test.
Expand Down Expand Up @@ -622,6 +730,7 @@ UnitTestingEntry (
AddTestCase (MiscTests, "Boot Options page select others should do nothing", "SelectOther", ConfAppBootOptSelectOther, NULL, BootOptionsCleanup, NULL);
AddTestCase (MiscTests, "Boot Options page should boot to single option", "BootOptionSingle", ConfAppBootOptSelectOne, NULL, BootOptionsCleanup, NULL);
AddTestCase (MiscTests, "Boot Options page should boot to multiple options", "BootOptionMultiple", ConfAppBootOptSelectMore, NULL, BootOptionsCleanup, NULL);
AddTestCase (MiscTests, "Boot Options page should boot to option 10 with two-digit input", "BootOption10", ConfAppBootOptSelect10, NULL, BootOptionsCleanup, NULL);

//
// Execute the tests.
Expand Down
Loading