3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Misc BDS library function
22 #define MAX_STRING_LEN 200
23 static BOOLEAN mFeaturerSwitch = TRUE;
24 static BOOLEAN mResetRequired = FALSE;
25 extern UINT16 gPlatformBootTimeOutDefault;
35 Return the default value for system Timeout variable.
52 // Return Timeout variable or 0xffff if no valid
53 // Timeout variable exists.
55 Size = sizeof (UINT16);
56 Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
57 if (!EFI_ERROR (Status)) {
61 // To make the current EFI Automatic-Test activity possible, just add
62 // following code to make AutoBoot enabled when this variable is not
64 // This code should be removed later.
66 Timeout = gPlatformBootTimeOutDefault;
69 // Notes: Platform should set default variable if non exists on all error cases!!!
71 Status = gRT->SetVariable (
73 &gEfiGlobalVariableGuid,
74 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
83 IN LIST_ENTRY *BdsDriverLists
89 The function will go through the driver optoin link list, load and start
90 every driver the driver optoin device path point to.
94 BdsDriverLists - The header of the current driver option link list
104 BDS_COMMON_OPTION *Option;
105 EFI_HANDLE ImageHandle;
106 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
109 BOOLEAN ReconnectAll;
111 ReconnectAll = FALSE;
114 // Process the driver option
116 for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {
117 Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
119 // If a load option is not marked as LOAD_OPTION_ACTIVE,
120 // the boot manager will not automatically load the option.
122 if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {
126 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
127 // then all of the EFI drivers in the system will be disconnected and
128 // reconnected after the last driver load option is processed.
130 if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {
134 // Make sure the driver path is connected.
136 BdsLibConnectDevicePath (Option->DevicePath);
139 // Load and start the image that Driver#### describes
141 Status = gBS->LoadImage (
150 if (!EFI_ERROR (Status)) {
151 gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid,
152 (VOID **)&ImageInfo);
155 // Verify whether this image is a driver, if not,
156 // exit it and continue to parse next load option
158 if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
159 gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
163 if (Option->LoadOptionsSize != 0) {
164 ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;
165 ImageInfo->LoadOptions = Option->LoadOptions;
168 // Before calling the image, enable the Watchdog Timer for
169 // the 5 Minute period
171 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
173 Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
174 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Driver Return Status = %r\n", Status));
177 // Clear the Watchdog Timer after the image returns
179 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
183 // Process the LOAD_OPTION_FORCE_RECONNECT driver option
186 BdsLibDisconnectAllEfi ();
193 BdsLibRegisterNewOption (
194 IN LIST_ENTRY *BdsOptionList,
195 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
197 IN CHAR16 *VariableName
203 This function will register the new boot#### or driver#### option base on
204 the VariableName. The new registered boot#### or driver#### will be linked
205 to BdsOptionList and also update to the VariableName. After the boot#### or
206 driver#### updated, the BootOrder or DriverOrder will also be updated.
210 BdsOptionList - The header of the boot#### or driver#### link list
212 DevicePath - The device path which the boot####
213 or driver#### option present
215 String - The description of the boot#### or driver####
217 VariableName - Indicate if the boot#### or driver#### option
221 EFI_SUCCESS - The boot#### or driver#### have been success registered
223 EFI_STATUS - Return the status of gRT->SetVariable ().
229 UINT16 MaxOptionNumber;
230 UINT16 RegisterOptionNumber;
231 UINT16 *TempOptionPtr;
232 UINTN TempOptionSize;
233 UINT16 *OptionOrderPtr;
237 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
239 CHAR16 OptionName[10];
240 BOOLEAN UpdateBootDevicePath;
245 OptionDevicePath = NULL;
248 OptionOrderPtr = NULL;
249 UpdateBootDevicePath = FALSE;
250 ZeroMem (OptionName, sizeof (OptionName));
253 TempOptionPtr = BdsLibGetVariableAndSize (
255 &gEfiGlobalVariableGuid,
259 // Compare with current option variable
261 for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {
263 // Got the max option#### number
265 if (MaxOptionNumber < TempOptionPtr[Index]) {
266 MaxOptionNumber = TempOptionPtr[Index];
269 if (*VariableName == 'B') {
270 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);
272 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);
275 OptionPtr = BdsLibGetVariableAndSize (
277 &gEfiGlobalVariableGuid,
281 TempPtr += sizeof (UINT32) + sizeof (UINT16);
282 Description = (CHAR16 *) TempPtr;
283 TempPtr += StrSize ((CHAR16 *) TempPtr);
284 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
287 // Notes: the description may will change base on the GetStringToken
289 if (CompareMem (Description, String, StrSize (Description)) == 0) {
290 if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {
292 // Got the option, so just return
294 gBS->FreePool (OptionPtr);
295 gBS->FreePool (TempOptionPtr);
299 // Boot device path changed, need update.
301 UpdateBootDevicePath = TRUE;
306 gBS->FreePool (OptionPtr);
309 OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath);
310 OptionPtr = AllocateZeroPool (OptionSize);
312 *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;
313 TempPtr += sizeof (UINT32);
314 *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);
315 TempPtr += sizeof (UINT16);
316 CopyMem (TempPtr, String, StrSize (String));
317 TempPtr += StrSize (String);
318 CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));
320 if (UpdateBootDevicePath) {
322 // The number in option#### to be updated
324 RegisterOptionNumber = TempOptionPtr[Index];
327 // The new option#### number
329 RegisterOptionNumber = MaxOptionNumber + 1;
332 if (*VariableName == 'B') {
333 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);
335 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);
338 Status = gRT->SetVariable (
340 &gEfiGlobalVariableGuid,
341 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
345 if (EFI_ERROR (Status) || UpdateBootDevicePath) {
346 gBS->FreePool (OptionPtr);
347 gBS->FreePool (TempOptionPtr);
351 gBS->FreePool (OptionPtr);
354 // Update the option order variable
356 OptionOrderPtr = AllocateZeroPool ((Index + 1) * sizeof (UINT16));
357 CopyMem (OptionOrderPtr, TempOptionPtr, Index * sizeof (UINT16));
358 OptionOrderPtr[Index] = RegisterOptionNumber;
359 Status = gRT->SetVariable (
361 &gEfiGlobalVariableGuid,
362 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
363 (Index + 1) * sizeof (UINT16),
366 if (EFI_ERROR (Status)) {
367 gBS->FreePool (TempOptionPtr);
368 gBS->FreePool (OptionOrderPtr);
372 gBS->FreePool (TempOptionPtr);
373 gBS->FreePool (OptionOrderPtr);
379 BdsLibVariableToOption (
380 IN OUT LIST_ENTRY *BdsCommonOptionList,
381 IN CHAR16 *VariableName
387 Build the boot#### or driver#### option from the VariableName, the
388 build boot#### or driver#### will also be linked to BdsCommonOptionList
392 BdsCommonOptionList - The header of the boot#### or driver#### option link list
394 VariableName - EFI Variable name indicate if it is boot#### or driver####
398 BDS_COMMON_OPTION - Get the option just been created
400 NULL - Failed to get the new option
409 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
410 BDS_COMMON_OPTION *Option;
412 UINT32 LoadOptionsSize;
416 // Read the variable. We will never free this data.
418 Variable = BdsLibGetVariableAndSize (
420 &gEfiGlobalVariableGuid,
423 if (Variable == NULL) {
427 // Notes: careful defined the variable of Boot#### or
428 // Driver####, consider use some macro to abstract the code
431 // Get the option attribute
434 Attribute = *(UINT32 *) Variable;
435 TempPtr += sizeof (UINT32);
438 // Get the option's device path size
440 FilePathSize = *(UINT16 *) TempPtr;
441 TempPtr += sizeof (UINT16);
444 // Get the option's description string
446 Description = (CHAR16 *) TempPtr;
449 // Get the option's description string size
451 TempPtr += StrSize ((CHAR16 *) TempPtr);
454 // Get the option's device path
456 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
457 TempPtr += FilePathSize;
459 LoadOptions = TempPtr;
460 LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
463 // The Console variables may have multiple device paths, so make
464 // an Entry for each one.
466 Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));
467 if (Option == NULL) {
471 Option->Signature = BDS_LOAD_OPTION_SIGNATURE;
472 Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));
473 CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
474 Option->Attribute = Attribute;
475 Option->Description = AllocateZeroPool (StrSize (Description));
476 CopyMem (Option->Description, Description, StrSize (Description));
477 Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);
478 CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);
479 Option->LoadOptionsSize = LoadOptionsSize;
482 // Insert active entry to BdsDeviceList
484 if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {
485 InsertTailList (BdsCommonOptionList, &Option->Link);
486 gBS->FreePool (Variable);
490 gBS->FreePool (Variable);
491 gBS->FreePool (Option);
497 BdsLibBuildOptionFromVar (
498 IN LIST_ENTRY *BdsCommonOptionList,
499 IN CHAR16 *VariableName
505 Process BootOrder, or DriverOrder variables, by calling
506 BdsLibVariableToOption () for each UINT16 in the variables.
510 BdsCommonOptionList - The header of the option list base on variable
513 VariableName - EFI Variable name indicate the BootOrder or DriverOrder
517 EFI_SUCCESS - Success create the boot option or driver option list
519 EFI_OUT_OF_RESOURCES - Failed to get the boot option or driver option list
524 UINTN OptionOrderSize;
526 BDS_COMMON_OPTION *Option;
527 CHAR16 OptionName[20];
530 // Zero Buffer in order to get all BOOT#### variables
532 ZeroMem (OptionName, sizeof (OptionName));
535 // Read the BootOrder, or DriverOrder variable.
537 OptionOrder = BdsLibGetVariableAndSize (
539 &gEfiGlobalVariableGuid,
542 if (OptionOrder == NULL) {
543 return EFI_OUT_OF_RESOURCES;
546 for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
547 if (*VariableName == 'B') {
548 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);
550 UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);
552 Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);
553 Option->BootCurrent = OptionOrder[Index];
557 gBS->FreePool (OptionOrder);
564 OUT EFI_BOOT_MODE *BootMode
570 Get boot mode by looking up configuration table and parsing HOB list
574 BootMode - Boot mode from PEI handoff HOB.
578 EFI_SUCCESS - Successfully get boot mode
580 EFI_NOT_FOUND - Can not find the current system boot mode
584 EFI_HOB_HANDOFF_INFO_TABLE *HobList;
586 HobList = GetHobList ();
587 ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF);
588 *BootMode = HobList->BootMode;
594 BdsLibGetVariableAndSize (
596 IN EFI_GUID *VendorGuid,
597 OUT UINTN *VariableSize
603 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
604 buffer, and the size of the buffer. If failure return NULL.
608 Name - String part of EFI variable name
610 VendorGuid - GUID part of EFI variable name
612 VariableSize - Returns the size of the EFI variable that was read
616 Dynamically allocated memory that contains a copy of the EFI variable.
617 Caller is responsible freeing the buffer.
619 NULL - Variable was not read
630 // Pass in a zero size buffer to find the required buffer size.
633 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
634 if (Status == EFI_BUFFER_TOO_SMALL) {
636 // Allocate the buffer to return
638 Buffer = AllocateZeroPool (BufferSize);
639 if (Buffer == NULL) {
643 // Read variable into the allocated buffer.
645 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
646 if (EFI_ERROR (Status)) {
651 *VariableSize = BufferSize;
656 BdsLibMatchDevicePaths (
657 IN EFI_DEVICE_PATH_PROTOCOL *Multi,
658 IN EFI_DEVICE_PATH_PROTOCOL *Single
664 Function compares a device path data structure to that of all the nodes of a
665 second device path instance.
669 Multi - A pointer to a multi-instance device path data structure.
671 Single - A pointer to a single-instance device path data structure.
675 TRUE - If the Single is contained within Multi
677 FALSE - The Single is not match within Multi
682 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
683 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
686 if (!Multi || !Single) {
691 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
692 Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);
695 // Search for the match of 'Single' in 'Multi'
697 while (DevicePathInst != NULL) {
699 // If the single device path is found in multiple device paths,
706 if (CompareMem (Single, DevicePathInst, Size) == 0) {
710 gBS->FreePool (DevicePathInst);
711 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
712 Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);
719 BdsLibOutputStrings (
720 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut,
727 This function prints a series of strings.
731 ConOut - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL
733 ... - A variable argument list containing series of strings,
734 the last string must be NULL.
738 EFI_SUCCESS - Success print out the string using ConOut.
740 EFI_STATUS - Return the status of the ConOut->OutputString ().
748 Status = EFI_SUCCESS;
749 VA_START (args, ConOut);
751 while (!EFI_ERROR (Status)) {
753 // If String is NULL, then it's the end of the list
755 String = VA_ARG (args, CHAR16 *);
760 Status = ConOut->OutputString (ConOut, String);
762 if (EFI_ERROR (Status)) {
771 // Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.
772 // Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if
773 // user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.
777 EnableResetReminderFeature (
784 Enable the setup browser reset reminder feature.
785 This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.
797 mFeaturerSwitch = TRUE;
801 DisableResetReminderFeature (
808 Disable the setup browser reset reminder feature.
809 This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.
821 mFeaturerSwitch = FALSE;
825 EnableResetRequired (
832 Record the info that a reset is required.
833 A module boolean variable is used to record whether a reset is required.
845 mResetRequired = TRUE;
849 DisableResetRequired (
856 Record the info that no reset is required.
857 A module boolean variable is used to record whether a reset is required.
869 mResetRequired = FALSE;
873 IsResetReminderFeatureEnable (
880 Check whether platform policy enable the reset reminder feature. The default is enabled.
892 return mFeaturerSwitch;
903 Check if user changed any option setting which needs a system reset to be effective.
915 return mResetRequired;
926 Check whether a reset is needed, and finish the reset reminder feature.
927 If a reset is needed, Popup a menu to notice user, and finish the feature
928 according to the user selection.
941 EFI_FORM_BROWSER_PROTOCOL *Browser;
943 CHAR16 *StringBuffer1;
944 CHAR16 *StringBuffer2;
948 //check any reset required change is applied? if yes, reset system
950 if (IsResetReminderFeatureEnable ()) {
951 if (IsResetRequired ()) {
953 Status = gBS->LocateProtocol (
954 &gEfiFormBrowserProtocolGuid,
959 StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
960 ASSERT (StringBuffer1 != NULL);
961 StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
962 ASSERT (StringBuffer2 != NULL);
963 StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");
964 StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)");
966 // Popup a menu to notice user
969 Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);
970 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
972 gBS->FreePool (StringBuffer1);
973 gBS->FreePool (StringBuffer2);
975 // If the user hits the YES Response key, reset
977 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
978 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
980 gST->ConOut->ClearScreen (gST->ConOut);