/** 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)); AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize); } return EFI_SUCCESS; }
/** Try to boot the boot option triggered by hotkey. @retval EFI_SUCCESS There is HotkeyBootOption & it is processed @retval EFI_NOT_FOUND There is no HotkeyBootOption **/ EFI_STATUS HotkeyBoot ( VOID ) { EFI_STATUS Status; UINTN ExitDataSize; CHAR16 *ExitData; if (mHotkeyBootOption == NULL) { return EFI_NOT_FOUND; } BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath); // // Clear the screen before launch this BootOption // gST->ConOut->Reset (gST->ConOut, FALSE); Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData); if (EFI_ERROR (Status)) { // // Call platform action to indicate the boot fail // mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize); } else { // // Call platform action to indicate the boot success // mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (mHotkeyBootOption); } FreePool (mHotkeyBootOption->Description); FreePool (mHotkeyBootOption->DevicePath); FreePool (mHotkeyBootOption->LoadOptions); FreePool (mHotkeyBootOption); mHotkeyBootOption = NULL; return EFI_SUCCESS; }
/** 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 ) { EFI_STRING TmpString; TmpString = HiiGetPackageString (ProducerGuid, Token, NULL); if (TmpString == NULL) { *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); } else { *String = TmpString; } return EFI_SUCCESS; }
/** Perform the memory test base on the memory test intensive level, and update the memory resource. @param Level The memory test intensive level. @retval EFI_STATUS Success test all the system memory and update the memory resource **/ EFI_STATUS EFIAPI BdsMemoryTest ( IN EXTENDMEM_COVERAGE_LEVEL Level ) { EFI_STATUS Status; EFI_STATUS KeyStatus; EFI_STATUS InitStatus; EFI_STATUS ReturnStatus; BOOLEAN RequireSoftECCInit; EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; UINT64 TestedMemorySize; UINT64 TotalMemorySize; UINTN TestPercent; UINT64 PreviousValue; BOOLEAN ErrorOut; BOOLEAN TestAbort; EFI_INPUT_KEY Key; CHAR16 StrPercent[80]; CHAR16 *StrTotalMemory; CHAR16 *Pos; CHAR16 *TmpStr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; BOOLEAN IsFirstBoot; UINT32 TempData; UINTN StrTotalMemorySize; ReturnStatus = EFI_SUCCESS; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); StrTotalMemorySize = 128; Pos = AllocateZeroPool (StrTotalMemorySize); if (Pos == NULL) { return ReturnStatus; } StrTotalMemory = Pos; TestedMemorySize = 0; TotalMemorySize = 0; PreviousValue = 0; ErrorOut = FALSE; TestAbort = FALSE; SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); RequireSoftECCInit = FALSE; Status = gBS->LocateProtocol ( &gEfiGenericMemTestProtocolGuid, NULL, (VOID **) &GenMemoryTest ); if (EFI_ERROR (Status)) { FreePool (Pos); return EFI_SUCCESS; } InitStatus = GenMemoryTest->MemoryTestInit ( GenMemoryTest, Level, &RequireSoftECCInit ); if (InitStatus == EFI_NO_MEDIA) { // // The PEI codes also have the relevant memory test code to check the memory, // it can select to test some range of the memory or all of them. If PEI code // checks all the memory, this BDS memory test will has no not-test memory to // do the test, and then the status of EFI_NO_MEDIA will be returned by // "MemoryTestInit". So it does not need to test memory again, just return. // FreePool (Pos); return EFI_SUCCESS; } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } } else { DEBUG ((EFI_D_INFO, "Enter memory test.\n")); } do { Status = GenMemoryTest->PerformMemoryTest ( GenMemoryTest, &TestedMemorySize, &TotalMemorySize, &ErrorOut, TestAbort ); if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } ASSERT (0); } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); TestPercent = (UINTN) DivU64x32 ( DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), TempData ); if (TestPercent != PreviousValue) { UnicodeValueToString (StrPercent, 0, TestPercent, 0); TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); if (TmpStr != NULL) { // // TmpStr size is 64, StrPercent is reserved to 16. // StrCatS (StrPercent, sizeof (StrPercent) / sizeof (CHAR16), TmpStr); PrintXY (10, 10, NULL, NULL, StrPercent); FreePool (TmpStr); } TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, TestPercent, (UINTN) PreviousValue ); FreePool (TmpStr); } } PreviousValue = TestPercent; } else { DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); } if (!PcdGetBool (PcdConInConnectOnDemand)) { KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { if (!RequireSoftECCInit) { if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, 100, (UINTN) PreviousValue ); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, L"100"); } Status = GenMemoryTest->Finished (GenMemoryTest); goto Done; } TestAbort = TRUE; } } } while (Status != EFI_NOT_FOUND); Status = GenMemoryTest->Finished (GenMemoryTest); Done: if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); if (StrTotalMemory[0] == L',') { StrTotalMemory++; StrTotalMemorySize -= sizeof (CHAR16); } TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); if (TmpStr != NULL) { StrCatS (StrTotalMemory, StrTotalMemorySize / sizeof (CHAR16), TmpStr); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, StrTotalMemory); PlatformBdsShowProgress ( Foreground, Background, StrTotalMemory, Color, 100, (UINTN) PreviousValue ); } else { DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); } FreePool (Pos); // // Use a DynamicHii type pcd to save the boot status, which is used to // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. // IsFirstBoot = PcdGetBool(PcdBootState); if (IsFirstBoot) { PcdSetBool(PcdBootState, FALSE); } return ReturnStatus; }
/** This function invokes Boot Manager. If all devices have not a chance to be connected, the connect all will be triggered. It then enumerate all boot options. If a boot option from the Boot Manager page is selected, Boot Manager will boot from this boot option. **/ VOID CallBootManager ( VOID ) { EFI_STATUS Status; BDS_COMMON_OPTION *Option; LIST_ENTRY *Link; CHAR16 *ExitData; UINTN ExitDataSize; EFI_STRING_ID Token; EFI_INPUT_KEY Key; CHAR16 *HelpString; UINTN HelpSize; EFI_STRING_ID HelpToken; UINT16 *TempStr; EFI_HII_HANDLE HiiHandle; EFI_BROWSER_ACTION_REQUEST ActionRequest; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINT16 DeviceType; BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; DeviceType = (UINT16) -1; gOption = NULL; InitializeListHead (&mBootOptionsList); // // Connect all prior to entering the platform setup menu. // if (!gConnectAllHappened) { BdsLibConnectAllDriversToAllControllers (); gConnectAllHappened = TRUE; } BdsLibEnumerateAllBootOption (&mBootOptionsList); // // Group the legacy boot options for the same device type // GroupMultipleLegacyBootOption4SameType (); InitializeListHead (&mBootOptionsList); BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder"); 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; mKeyInput = 0; NeedEndOp = FALSE; for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); // // At this stage we are creating a menu entry, thus the Keys are reproduceable // mKeyInput++; // // Don't display the hidden/inactive boot option // if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) { continue; } // // Group the legacy boot option in the sub title created dynamically // IsLegacyOption = (BOOLEAN) ( (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) ); if (!IsLegacyOption && NeedEndOp) { NeedEndOp = FALSE; HiiCreateEndOpCode (StartOpCodeHandle); } if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) { if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType; Token = HiiSetString ( HiiHandle, 0, mDeviceTypeStr[ MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1) ], NULL ); HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); NeedEndOp = TRUE; } ASSERT (Option->Description != NULL); Token = HiiSetString (HiiHandle, 0, Option->Description, NULL); TempStr = DevicePathToStr (Option->DevicePath); HelpSize = StrSize (TempStr) + StrSize (L"Device Path : "); HelpString = AllocateZeroPool (HelpSize); ASSERT (HelpString != NULL); StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : "); StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, mKeyInput, Token, HelpToken, EFI_IFR_FLAG_CALLBACK, 0 ); } if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } HiiUpdateForm ( HiiHandle, &gBootManagerFormSetGuid, BOOT_MANAGER_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &HiiHandle, 1, &gBootManagerFormSetGuid, 0, NULL, &ActionRequest ); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } if (gOption == NULL) { return ; } // // Will leave browser, check any reset required change is applied? if yes, reset system // SetupResetReminder (); // // Restore to original mode before launching boot option. // BdsSetConsoleMode (FALSE); // // parse the selected option // Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); if (!EFI_ERROR (Status)) { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (gOption); } else { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); gST->ConOut->OutputString ( gST->ConOut, GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) ); gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); } }
/** Function show progress bar to wait for user input. @param TimeoutDefault The fault time out value before the system continue to boot. @retval EFI_SUCCESS User pressed some key except "Enter" @retval EFI_TIME_OUT Timeout expired or user press "Enter" **/ EFI_STATUS ShowProgress ( IN UINT16 TimeoutDefault ) { CHAR16 *TmpStr; UINT16 TimeoutRemain; EFI_STATUS Status; EFI_INPUT_KEY Key; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; if (TimeoutDefault != 0) { DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n")); SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION)); if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { // // Clear the progress status bar first // if (TmpStr != NULL) { PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0); } } TimeoutRemain = TimeoutDefault; while (TimeoutRemain != 0) { DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain)); Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); if (Status != EFI_TIMEOUT) { break; } TimeoutRemain--; if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { // // Show progress // if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault), 0 ); } } } if (TmpStr != NULL) { gBS->FreePool (TmpStr); } // // Timeout expired // if (TimeoutRemain == 0) { return EFI_TIMEOUT; } } // // User pressed some key // if (!PcdGetBool (PcdConInConnectOnDemand)) { Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (EFI_ERROR (Status)) { return Status; } if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { // // User pressed enter, equivalent to select "continue" // return EFI_TIMEOUT; } } return EFI_SUCCESS; }
/** This function attempts to boot for the boot order specified by platform policy. **/ VOID BdsBootDeviceSelect ( VOID ) { EFI_STATUS Status; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN ExitDataSize; CHAR16 *ExitData; UINT16 Timeout; LIST_ENTRY BootLists; CHAR16 Buffer[20]; BOOLEAN BootNextExist; LIST_ENTRY *LinkBootNext; EFI_EVENT ConnectConInEvent; // // Got the latest boot option // BootNextExist = FALSE; LinkBootNext = NULL; ConnectConInEvent = NULL; InitializeListHead (&BootLists); // // First check the boot next option // ZeroMem (Buffer, sizeof (Buffer)); // // Create Event to signal ConIn connection request // if (PcdGetBool (PcdConInConnectOnDemand)) { Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, BdsEmptyCallbackFunction, NULL, &gConnectConInEventGuid, &ConnectConInEvent ); if (EFI_ERROR(Status)) { ConnectConInEvent = NULL; } } if (mBootNext != NULL) { // // Indicate we have the boot next variable, so this time // boot will always have this boot option // BootNextExist = TRUE; // // Clear the this variable so it's only exist in this time boot // Status = gRT->SetVariable ( L"BootNext", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 0, NULL ); // // Deleting variable with current variable implementation shouldn't fail. // ASSERT_EFI_ERROR (Status); // // Add the boot next boot option // UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); BootOption = BdsLibVariableToOption (&BootLists, Buffer); // // If fail to get boot option from variable, just return and do nothing. // if (BootOption == NULL) { return; } BootOption->BootCurrent = *mBootNext; } // // Parse the boot order to get boot option // BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); // // When we didn't have chance to build boot option variables in the first // full configuration boot (e.g.: Reset in the first page or in Device Manager), // we have no boot options in the following mini configuration boot. // Give the last chance to enumerate the boot options. // if (IsListEmpty (&BootLists)) { BdsLibEnumerateAllBootOption (&BootLists); } Link = BootLists.ForwardLink; // // Parameter check, make sure the loop will be valid // if (Link == NULL) { return ; } // // Here we make the boot in a loop, every boot success will // return to the front page // for (;;) { // // Check the boot option list first // if (Link == &BootLists) { // // When LazyConIn enabled, signal connect ConIn event before enter UI // if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { gBS->SignalEvent (ConnectConInEvent); } // // There are two ways to enter here: // 1. There is no active boot option, give user chance to // add new boot option // 2. All the active boot option processed, and there is no // one is success to boot, then we back here to allow user // add new active boot option // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); InitializeListHead (&BootLists); BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); Link = BootLists.ForwardLink; continue; } // // Get the boot option from the link list // BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); // // According to EFI Specification, if a load option is not marked // as LOAD_OPTION_ACTIVE, the boot manager will not automatically // load the option. // if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, because it has no boot option // Link = Link->ForwardLink; continue; } // // Make sure the boot option device path connected, // but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { // // Notes: the internal shell can not been connected with device path // so we do not check the status here // BdsLibConnectDevicePath (BootOption->DevicePath); } // // Restore to original mode before launching boot option. // BdsSetConsoleMode (FALSE); // // All the driver options should have been processed since // now boot will be performed. // Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); if (Status != EFI_SUCCESS) { // // Call platform action to indicate the boot fail // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); // // Check the next boot option // Link = Link->ForwardLink; } else { // // Call platform action to indicate the boot success // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (BootOption); // // Boot success, then stop process the boot order, and // present the boot manager menu, front page // // // When LazyConIn enabled, signal connect ConIn Event before enter UI // if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) { gBS->SignalEvent (ConnectConInEvent); } Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); // // Rescan the boot option list, avoid potential risk of the boot // option change in front page // if (BootNextExist) { LinkBootNext = BootLists.ForwardLink; } InitializeListHead (&BootLists); if (LinkBootNext != NULL) { // // Reserve the boot next option // InsertTailList (&BootLists, LinkBootNext); } BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); Link = BootLists.ForwardLink; } } }
/** This is the common notification function for HotKeys, it will be registered with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle. @param KeyData A pointer to a buffer that is filled in with the keystroke information for the key that was pressed. @retval EFI_SUCCESS KeyData is successfully processed. @return EFI_NOT_FOUND Fail to find boot option variable. **/ EFI_STATUS EFIAPI HotkeyCallback ( IN EFI_KEY_DATA *KeyData ) { BOOLEAN HotkeyCatched; LIST_ENTRY BootLists; LIST_ENTRY *Link; BDS_HOTKEY_OPTION *Hotkey; UINT16 Buffer[10]; BDS_COMMON_OPTION *BootOption; UINTN ExitDataSize; CHAR16 *ExitData; EFI_STATUS Status; EFI_KEY_DATA *HotkeyData; if (mHotkeyCallbackPending) { // // When responsing to a Hotkey, ignore sequential hotkey stroke until // the current Boot#### load option returned // return EFI_SUCCESS; } Status = EFI_SUCCESS; Link = GetFirstNode (&mHotkeyList); while (!IsNull (&mHotkeyList, Link)) { HotkeyCatched = FALSE; Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link); // // Is this Key Stroke we are waiting for? // ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0]))); HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey]; if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) && (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) && (((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) { // // Receive an expecting key stroke // if (Hotkey->CodeCount > 1) { // // For hotkey of key combination, transit to next waiting state // Hotkey->WaitingKey++; if (Hotkey->WaitingKey == Hotkey->CodeCount) { // // Received the whole key stroke sequence // HotkeyCatched = TRUE; } } else { // // For hotkey of single key stroke // HotkeyCatched = TRUE; } } else { // // Receive an unexpected key stroke, reset to initial waiting state // Hotkey->WaitingKey = 0; } if (HotkeyCatched) { // // Reset to initial waiting state // Hotkey->WaitingKey = 0; // // Launch its BootOption // InitializeListHead (&BootLists); UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber); BootOption = BdsLibVariableToOption (&BootLists, Buffer); if (BootOption == NULL) { return EFI_NOT_FOUND; } BootOption->BootCurrent = Hotkey->BootOptionNumber; BdsLibConnectDevicePath (BootOption->DevicePath); // // Clear the screen before launch this BootOption // gST->ConOut->Reset (gST->ConOut, FALSE); mHotkeyCallbackPending = TRUE; Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); mHotkeyCallbackPending = FALSE; if (EFI_ERROR (Status)) { // // Call platform action to indicate the boot fail // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); } else { // // Call platform action to indicate the boot success // BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (BootOption); } } Link = GetNextNode (&mHotkeyList, Link); } return Status; }
/** Add a new user profile into the user profile database. **/ VOID CallAddUser ( VOID ) { EFI_STATUS Status; EFI_INPUT_KEY Key; EFI_USER_PROFILE_HANDLE User; UINTN UserNameLen; CHAR16 UserName[USER_NAME_LENGTH]; CHAR16 *QuestionStr; CHAR16 *PromptStr; QuestionStr = NULL; PromptStr = NULL; // // Get user name to add. // UserNameLen = sizeof (UserName); Status = GetUserNameInput (&UserNameLen, UserName); if (EFI_ERROR (Status)) { if (Status != EFI_ABORTED) { QuestionStr = GetStringById (STRING_TOKEN (STR_GET_USERNAME_FAILED)); PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); goto Done; } return ; } // // Create a new user profile. // User = NULL; Status = mUserManager->Create (mUserManager, &User); if (EFI_ERROR (Status)) { QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_FAILED)); PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); } else { // // Add default user information. // Status = SetUserName (User, UserNameLen, UserName); if (EFI_ERROR (Status)) { QuestionStr = GetStringById (STRING_TOKEN (STR_USER_ALREADY_EXISTED)); PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); goto Done; } SetCreateDate (User); SetIdentityPolicy (User); SetAccessPolicy (User); QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_SUCCESS)); PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); } Done: CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, QuestionStr, L"", PromptStr, NULL ); FreePool (QuestionStr); FreePool (PromptStr); }
/** 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; }
/** This function processes changes in user profile 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 Others Fail to handle the action. **/ EFI_STATUS EFIAPI UserProfileManagerCallback ( 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 ) { EFI_STATUS Status; EFI_INPUT_KEY Key; UINT32 CurrentAccessRight; CHAR16 *QuestionStr; CHAR16 *PromptStr; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; EFI_USER_PROFILE_HANDLE CurrentUser; Status = EFI_SUCCESS; switch (Action) { case EFI_BROWSER_ACTION_FORM_OPEN: { // // Update user manage Form when user manage Form is opened. // This will be done only in FORM_OPEN CallBack of question with QUESTIONID_USER_MANAGE from user manage Form. // if (QuestionId != QUESTIONID_USER_MANAGE) { return EFI_SUCCESS; } // // Get current user // CurrentUser = NULL; mUserManager->Current (mUserManager, &CurrentUser); if (CurrentUser == NULL) { DEBUG ((DEBUG_ERROR, "Error: current user does not exist!\n")); return EFI_NOT_READY; } // // Get current user's right information. // Status = GetAccessRight (&CurrentAccessRight); if (EFI_ERROR (Status)) { CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; } // // Init credential provider information. // Status = InitProviderInfo (); if (EFI_ERROR (Status)) { return Status; } // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label 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_USER_MANAGE_FUNC; 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; // // Add user profile option. // if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) || (CurrentAccessRight == EFI_USER_INFO_ACCESS_ENROLL_OTHERS) ) { HiiCreateActionOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes KEY_ADD_USER, // Question ID STRING_TOKEN (STR_ADD_USER_TITLE), // Prompt text STRING_TOKEN (STR_ADD_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); } // // Add modify user profile option. // HiiCreateGotoOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes FORMID_MODIFY_USER, // Target Form ID STRING_TOKEN (STR_MODIFY_USER_TITLE), // Prompt text STRING_TOKEN (STR_MODIFY_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag KEY_MODIFY_USER // Question ID ); // // Add delete user profile option // if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) { HiiCreateGotoOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes FORMID_DEL_USER, // Target Form ID STRING_TOKEN (STR_DELETE_USER_TITLE), // Prompt text STRING_TOKEN (STR_DELETE_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag KEY_DEL_USER // Question ID ); } HiiUpdateForm ( mCallbackInfo->HiiHandle, // HII handle &gUserProfileManagerGuid, // Formset GUID FORMID_USER_MANAGE, // Form ID StartOpCodeHandle, // Label for where to insert opcodes EndOpCodeHandle // Replace data ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); return EFI_SUCCESS; } break; case EFI_BROWSER_ACTION_FORM_CLOSE: Status = EFI_SUCCESS; break; case EFI_BROWSER_ACTION_CHANGED: { // // Handle the request from form. // if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } // // Judge first 2 bits. // switch (QuestionId & KEY_FIRST_FORM_MASK) { // // Add user profile operation. // case KEY_ADD_USER: CallAddUser (); break; // // Delete user profile operation. // case KEY_DEL_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Delete specified user profile. // case KEY_SELECT_USER: DeleteUser ((UINT8) QuestionId); // // Update select user form after delete a user. // SelectUserToDelete (); break; default: break; } break; // // Modify user profile operation. // case KEY_MODIFY_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter user profile information form. // case KEY_SELECT_USER: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_INFO_MASK) { // // Modify user name. // case KEY_MODIFY_NAME: ModifyUserName (); // // Update username in parent form. // SelectUserToModify (); break; // // Modify identity policy. // case KEY_MODIFY_IP: // // Judge next 3 bits // switch (QuestionId & KEY_MODIFY_IP_MASK) { // // Change credential provider option. // case KEY_MODIFY_PROV: mProviderChoice = Value->u8; break; // // Change logical connector. // case KEY_MODIFY_CONN: mConncetLogical = Value->u8; break; // // Save option. // case KEY_ADD_IP_OP: AddIdentityPolicyItem (); break; // // Return to user profile information form. // case KEY_IP_RETURN_UIF: SaveIdentityPolicy (); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; default: break; } break; // // Modify access policy. // case KEY_MODIFY_AP: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_AP_MASK) { // // Change access right choice. // case KEY_MODIFY_RIGHT: mAccessInfo.AccessRight = Value->u8; break; // // Change setup choice. // case KEY_MODIFY_SETUP: mAccessInfo.AccessSetup= Value->u8; break; // // Change boot order choice. // case KEY_MODIFY_BOOT: mAccessInfo.AccessBootOrder = Value->u32; break; // // Return to user profile information form. // case KEY_AP_RETURN_UIF: SaveAccessPolicy (); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; default: break; } break; default: break; } break; // // Access policy device path modified. // case KEY_MODIFY_AP_DP: // // Judge next 2 bits. // switch (QuestionId & KEY_MODIFY_DP_MASK) { // // Load permit device path modified. // case KEY_LOAD_PERMIT_MODIFY: QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_FORBID_LIST)); PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, QuestionStr, L"", PromptStr, NULL ); FreePool (QuestionStr); FreePool (PromptStr); if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { break; } AddToForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); DisplayLoadPermit (); break; // // Load forbid device path modified. // case KEY_LOAD_FORBID_MODIFY: QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_PERMIT_LIST)); PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, QuestionStr, L"", PromptStr, NULL ); FreePool (QuestionStr); FreePool (PromptStr); if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { break; } DeleteFromForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); DisplayLoadForbid (); break; // // Connect permit device path modified. // case KEY_CONNECT_PERMIT_MODIFY: break; // // Connect forbid device path modified. // case KEY_CONNECT_FORBID_MODIFY: break; default: break; } break; default: break; } break; default: break; } } break; case EFI_BROWSER_ACTION_CHANGING: { // // Handle the request from form. // if (Value == NULL) { return EFI_INVALID_PARAMETER; } // // Judge first 2 bits. // switch (QuestionId & KEY_FIRST_FORM_MASK) { // // Delete user profile operation. // case KEY_DEL_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter delete user profile form. // case KEY_ENTER_NEXT_FORM: SelectUserToDelete (); break; default: break; } break; // // Modify user profile operation. // case KEY_MODIFY_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter modify user profile form. // case KEY_ENTER_NEXT_FORM: SelectUserToModify (); break; // // Enter user profile information form. // case KEY_SELECT_USER: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_INFO_MASK) { // // Display user information form. // case KEY_ENTER_NEXT_FORM: ModifyUserInfo ((UINT8) QuestionId); break; // // Modify identity policy. // case KEY_MODIFY_IP: // // Judge next 3 bits // switch (QuestionId & KEY_MODIFY_IP_MASK) { // // Display identity policy modify form. // case KEY_ENTER_NEXT_FORM: ModifyIdentityPolicy (); break; default: break; } break; // // Modify access policy. // case KEY_MODIFY_AP: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_AP_MASK) { // // Display access policy modify form. // case KEY_ENTER_NEXT_FORM: ModidyAccessPolicy (); break; // // Load device path form. // case KEY_MODIFY_LOAD: // // Judge next 2 bits. // switch (QuestionId & KEY_DISPLAY_DP_MASK) { // // Permit load device path. // case KEY_PERMIT_MODIFY: DisplayLoadPermit (); break; // // Forbid load device path. // case KEY_FORBID_MODIFY: DisplayLoadForbid (); break; default: break; } break; // // Connect device path form. // case KEY_MODIFY_CONNECT: // // Judge next 2 bits. // switch (QuestionId & KEY_DISPLAY_DP_MASK) { // // Permit connect device path. // case KEY_PERMIT_MODIFY: DisplayConnectPermit (); break; // // Forbid connect device path. // case KEY_FORBID_MODIFY: DisplayConnectForbid (); break; default: break; } break; default: break; } break; default: break; } break; default: break; } break; default: break; } } break; default: // // All other action return unsupported. // Status = EFI_UNSUPPORTED; break; } return Status; }