/** Allocate a block of memory that will contain performance data to OS. **/ VOID BdsAllocateMemoryForPerformanceData ( VOID ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; AcpiLowMemoryBase = 0x0FFFFFFFFULL; // // Allocate a block of memory that will contain performance data to OS. // Status = gBS->AllocatePages ( AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH), &AcpiLowMemoryBase ); if (!EFI_ERROR (Status)) { // // Save the pointer to variable for use in S3 resume. // Status = BdsDxeSetVariableAndReportStatusCodeOnError ( L"PerfDataMemAddr", &gPerformanceProtocolGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (EFI_PHYSICAL_ADDRESS), &AcpiLowMemoryBase ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase)); } // // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code. // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); if (!EFI_ERROR (Status)) { Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid); ASSERT_EFI_ERROR (Status); } } }
/** Initialize Lang or PlatformLang variable, if Lang or PlatformLang variable is not found, or it has been set to an unsupported value(not one of platform supported language codes), set the default language code to it. @param LangName Language name, L"Lang" or L"PlatformLang". @param SupportedLang Platform supported language codes. @param DefaultLang Default language code. @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646, TRUE for L"Lang" LangName or FALSE for L"PlatformLang" LangName. **/ VOID InitializeLangVariable ( IN CHAR16 *LangName, IN CHAR8 *SupportedLang, IN CHAR8 *DefaultLang, IN BOOLEAN Iso639Language ) { CHAR8 *Lang; // // Find current Lang or PlatformLang from EFI Variable. // GetEfiGlobalVariable2 (LangName, (VOID **) &Lang, NULL); // // If Lang or PlatformLang variable is not found, // or it has been set to an unsupported value(not one of the supported language codes), // set the default language code to it. // if ((Lang == NULL) || !IsLangInSupportedLangCodes (SupportedLang, Lang, Iso639Language)) { // // The default language code should be one of the supported language codes. // ASSERT (IsLangInSupportedLangCodes (SupportedLang, DefaultLang, Iso639Language)); BdsDxeSetVariableAndReportStatusCodeOnError ( LangName, &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, AsciiStrSize (DefaultLang), DefaultLang ); } if (Lang != NULL) { FreePool (Lang); } }
/** 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; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } gCallbackKey = QuestionId; 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) { BdsDxeSetVariableAndReportStatusCodeOnError ( L"PlatformLang", &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, AsciiStrSize (Lang), Lang ); } else { ASSERT (FALSE); } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; FreePool (Lang); break; 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 // break; case FRONT_PAGE_KEY_DEVICE_MANAGER: // // Device Manager // break; case FRONT_PAGE_KEY_BOOT_MAINTAIN: // // Boot Maintenance Manager // break; default: gCallbackKey = 0; break; } } 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_SET_FD_ORDER_ID: case FORM_SET_HD_ORDER_ID: case FORM_SET_CD_ORDER_ID: case FORM_SET_NET_ORDER_ID: case FORM_SET_BEV_ORDER_ID: Var_UpdateBBSOption (Private); break; case FORM_BOOT_DEL_ID: for (Index = 0; ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->OptionDel) / sizeof (CurrentFakeNVMap->OptionDel[0])))); Index ++) { NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = CurrentFakeNVMap->OptionDel[Index]; } Var_DelBootOption (); break; case FORM_DRV_DEL_ID: for (Index = 0; ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->OptionDel) / sizeof (CurrentFakeNVMap->OptionDel[0])))); Index++) { NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = CurrentFakeNVMap->OptionDel[Index]; } 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: BdsDxeSetVariableAndReportStatusCodeOnError ( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), &(CurrentFakeNVMap->BootTimeOut) ); 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; NewTerminalContext->FlowControl = CurrentFakeNVMap->COMFlowControl; 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; }
/** Formalize Bds global variables. 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable. 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps 3. Delete OsIndications variable if it is not NV/BS/RT UINT64 Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable. **/ VOID BdsFormalizeEfiGlobalVariable ( VOID ) { EFI_STATUS Status; UINT64 OsIndicationSupport; UINT64 OsIndication; UINTN DataSize; UINT32 Attributes; // // Validate Console variable. // BdsFormalizeConsoleVariable (L"ConIn"); BdsFormalizeConsoleVariable (L"ConOut"); BdsFormalizeConsoleVariable (L"ErrOut"); // // OS indicater support variable // OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \ | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; BdsDxeSetVariableAndReportStatusCodeOnError ( L"OsIndicationsSupported", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(UINT64), &OsIndicationSupport ); // // If OsIndications is invalid, remove it. // Invalid case // 1. Data size != UINT64 // 2. OsIndication value inconsistence // 3. OsIndication attribute inconsistence // OsIndication = 0; Attributes = 0; DataSize = sizeof(UINT64); Status = gRT->GetVariable ( L"OsIndications", &gEfiGlobalVariableGuid, &Attributes, &DataSize, &OsIndication ); if (!EFI_ERROR(Status)) { if (DataSize != sizeof(UINT64) || (OsIndication & ~OsIndicationSupport) != 0 || Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){ DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n")); Status = gRT->SetVariable ( L"OsIndications", &gEfiGlobalVariableGuid, 0, 0, NULL ); // // Deleting variable with current variable implementation shouldn't fail. // ASSERT_EFI_ERROR (Status); } } }
/** Service routine for BdsInstance->Entry(). Devices are connected, the consoles are initialized, and the boot options are tried. @param This Protocol Instance structure. **/ VOID EFIAPI BdsEntry ( IN EFI_BDS_ARCH_PROTOCOL *This ) { LIST_ENTRY DriverOptionList; LIST_ENTRY BootOptionList; UINTN BootNextSize; CHAR16 *FirmwareVendor; EFI_STATUS Status; UINT16 BootTimeOut; UINTN Index; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; // // Insert the performance probe // PERF_END (NULL, "DXE", NULL, 0); PERF_START (NULL, "BDS", NULL, 0); // // Initialize the global system boot option and driver option // InitializeListHead (&DriverOptionList); InitializeListHead (&BootOptionList); // // Initialize hotkey service // InitializeHotkeyService (); // // Fill in FirmwareVendor and FirmwareRevision from PCDs // FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor); gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); ASSERT (gST->FirmwareVendor != NULL); gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); // // Fixup Tasble CRC after we updated Firmware Vendor and Revision // gST->Hdr.CRC32 = 0; gBS->CalculateCrc32 ((VOID *)gST, sizeof(EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); // // Validate Variable. // BdsFormalizeEfiGlobalVariable(); // // Mark the read-only variables if the Variable Lock protocol exists // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status)); if (!EFI_ERROR (Status)) { for (Index = 0; Index < ARRAY_SIZE (mReadOnlyVariables); Index++) { Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid); ASSERT_EFI_ERROR (Status); } } // // Report Status Code to indicate connecting drivers will happen // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS) ); InitializeHwErrRecSupport(); // // Initialize L"Timeout" EFI global variable. // BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); if (BootTimeOut != 0xFFFF) { // // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification // define same behavior between no value or 0xFFFF value for L"Timeout". // BdsDxeSetVariableAndReportStatusCodeOnError ( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), &BootTimeOut ); } // // bugbug: platform specific code // Initialize the platform specific string and language // InitializeStringSupport (); InitializeLanguage (TRUE); InitializeFrontPage (TRUE); // // Do the platform init, can be customized by OEM/IBV // PERF_START (NULL, "PlatformBds", "BDS", 0); PlatformBdsInit (); // // Set up the device list based on EFI 1.1 variables // process Driver#### and Load the driver's in the // driver option list // BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); if (!IsListEmpty (&DriverOptionList)) { BdsLibLoadDrivers (&DriverOptionList); } // // Check if we have the boot next option // mBootNext = BdsLibGetVariableAndSize ( L"BootNext", &gEfiGlobalVariableGuid, &BootNextSize ); // // Setup some platform policy here // PlatformBdsPolicyBehavior (&DriverOptionList, &BootOptionList, BdsProcessCapsules, BdsMemoryTest); PERF_END (NULL, "PlatformBds", "BDS", 0); // // BDS select the boot device to load OS // BdsBootDeviceSelect (); // // Only assert here since this is the right behavior, we should never // return back to DxeCore. // ASSERT (FALSE); return ; }