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 extern UINT16 gPlatformBootTimeOutDefault
;
32 Return the default value for system Timeout variable.
49 // Return Timeout variable or 0xffff if no valid
50 // Timeout variable exists.
52 Size
= sizeof (UINT16
);
53 Status
= gRT
->GetVariable (L
"Timeout", &gEfiGlobalVariableGuid
, NULL
, &Size
, &Timeout
);
54 if (!EFI_ERROR (Status
)) {
58 // To make the current EFI Automatic-Test activity possible, just add
59 // following code to make AutoBoot enabled when this variable is not
61 // This code should be removed later.
63 Timeout
= gPlatformBootTimeOutDefault
;
66 // Notes: Platform should set default variable if non exists on all error cases!!!
68 Status
= gRT
->SetVariable (
70 &gEfiGlobalVariableGuid
,
71 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
80 IN LIST_ENTRY
*BdsDriverLists
86 The function will go through the driver optoin link list, load and start
87 every driver the driver optoin device path point to.
91 BdsDriverLists - The header of the current driver option link list
101 BDS_COMMON_OPTION
*Option
;
102 EFI_HANDLE ImageHandle
;
103 EFI_LOADED_IMAGE_PROTOCOL
*ImageInfo
;
106 BOOLEAN ReconnectAll
;
108 ReconnectAll
= FALSE
;
111 // Process the driver option
113 for (Link
= BdsDriverLists
->ForwardLink
; Link
!= BdsDriverLists
; Link
= Link
->ForwardLink
) {
114 Option
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
116 // If a load option is not marked as LOAD_OPTION_ACTIVE,
117 // the boot manager will not automatically load the option.
119 if (!IS_LOAD_OPTION_TYPE (Option
->Attribute
, LOAD_OPTION_ACTIVE
)) {
123 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
124 // then all of the EFI drivers in the system will be disconnected and
125 // reconnected after the last driver load option is processed.
127 if (IS_LOAD_OPTION_TYPE (Option
->Attribute
, LOAD_OPTION_FORCE_RECONNECT
)) {
131 // Make sure the driver path is connected.
133 BdsLibConnectDevicePath (Option
->DevicePath
);
136 // Load and start the image that Driver#### describes
138 Status
= gBS
->LoadImage (
147 if (!EFI_ERROR (Status
)) {
148 gBS
->HandleProtocol (ImageHandle
, &gEfiLoadedImageProtocolGuid
, &ImageInfo
);
151 // Verify whether this image is a driver, if not,
152 // exit it and continue to parse next load option
154 if (ImageInfo
->ImageCodeType
!= EfiBootServicesCode
&& ImageInfo
->ImageCodeType
!= EfiRuntimeServicesCode
) {
155 gBS
->Exit (ImageHandle
, EFI_INVALID_PARAMETER
, 0, NULL
);
159 if (Option
->LoadOptionsSize
!= 0) {
160 ImageInfo
->LoadOptionsSize
= Option
->LoadOptionsSize
;
161 ImageInfo
->LoadOptions
= Option
->LoadOptions
;
164 // Before calling the image, enable the Watchdog Timer for
165 // the 5 Minute period
167 gBS
->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL
);
169 Status
= gBS
->StartImage (ImageHandle
, &ExitDataSize
, &ExitData
);
170 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Driver Return Status = %r\n", Status
));
173 // Clear the Watchdog Timer after the image returns
175 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
179 // Process the LOAD_OPTION_FORCE_RECONNECT driver option
182 BdsLibDisconnectAllEfi ();
189 BdsLibRegisterNewOption (
190 IN LIST_ENTRY
*BdsOptionList
,
191 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
193 IN CHAR16
*VariableName
199 This function will register the new boot#### or driver#### option base on
200 the VariableName. The new registered boot#### or driver#### will be linked
201 to BdsOptionList and also update to the VariableName. After the boot#### or
202 driver#### updated, the BootOrder or DriverOrder will also be updated.
206 BdsOptionList - The header of the boot#### or driver#### link list
208 DevicePath - The device path which the boot####
209 or driver#### option present
211 String - The description of the boot#### or driver####
213 VariableName - Indicate if the boot#### or driver#### option
217 EFI_SUCCESS - The boot#### or driver#### have been success registered
219 EFI_STATUS - Return the status of gRT->SetVariable ().
225 UINT16 MaxOptionNumber
;
226 UINT16 RegisterOptionNumber
;
227 UINT16
*TempOptionPtr
;
228 UINTN TempOptionSize
;
229 UINT16
*OptionOrderPtr
;
233 EFI_DEVICE_PATH_PROTOCOL
*OptionDevicePath
;
235 CHAR16 OptionName
[10];
236 BOOLEAN UpdateBootDevicePath
;
241 OptionDevicePath
= NULL
;
244 OptionOrderPtr
= NULL
;
245 UpdateBootDevicePath
= FALSE
;
246 ZeroMem (OptionName
, sizeof (OptionName
));
249 TempOptionPtr
= BdsLibGetVariableAndSize (
251 &gEfiGlobalVariableGuid
,
255 // Compare with current option variable
257 for (Index
= 0; Index
< TempOptionSize
/ sizeof (UINT16
); Index
++) {
259 // Got the max option#### number
261 if (MaxOptionNumber
< TempOptionPtr
[Index
]) {
262 MaxOptionNumber
= TempOptionPtr
[Index
];
265 if (*VariableName
== 'B') {
266 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Boot%04x", TempOptionPtr
[Index
]);
268 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Driver%04x", TempOptionPtr
[Index
]);
271 OptionPtr
= BdsLibGetVariableAndSize (
273 &gEfiGlobalVariableGuid
,
277 TempPtr
+= sizeof (UINT32
) + sizeof (UINT16
);
278 Description
= (CHAR16
*) TempPtr
;
279 TempPtr
+= StrSize ((CHAR16
*) TempPtr
);
280 OptionDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
;
283 // Notes: the description may will change base on the GetStringToken
285 if (CompareMem (Description
, String
, StrSize (Description
)) == 0) {
286 if (CompareMem (OptionDevicePath
, DevicePath
, GetDevicePathSize (OptionDevicePath
)) == 0) {
288 // Got the option, so just return
290 gBS
->FreePool (OptionPtr
);
291 gBS
->FreePool (TempOptionPtr
);
295 // Boot device path changed, need update.
297 UpdateBootDevicePath
= TRUE
;
302 gBS
->FreePool (OptionPtr
);
305 OptionSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (String
) + GetDevicePathSize (DevicePath
);
306 OptionPtr
= AllocateZeroPool (OptionSize
);
308 *(UINT32
*) TempPtr
= LOAD_OPTION_ACTIVE
;
309 TempPtr
+= sizeof (UINT32
);
310 *(UINT16
*) TempPtr
= (UINT16
) GetDevicePathSize (DevicePath
);
311 TempPtr
+= sizeof (UINT16
);
312 CopyMem (TempPtr
, String
, StrSize (String
));
313 TempPtr
+= StrSize (String
);
314 CopyMem (TempPtr
, DevicePath
, GetDevicePathSize (DevicePath
));
316 if (UpdateBootDevicePath
) {
318 // The number in option#### to be updated
320 RegisterOptionNumber
= TempOptionPtr
[Index
];
323 // The new option#### number
325 RegisterOptionNumber
= MaxOptionNumber
+ 1;
328 if (*VariableName
== 'B') {
329 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Boot%04x", RegisterOptionNumber
);
331 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Driver%04x", RegisterOptionNumber
);
334 Status
= gRT
->SetVariable (
336 &gEfiGlobalVariableGuid
,
337 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
341 if (EFI_ERROR (Status
) || UpdateBootDevicePath
) {
342 gBS
->FreePool (OptionPtr
);
343 gBS
->FreePool (TempOptionPtr
);
347 gBS
->FreePool (OptionPtr
);
350 // Update the option order variable
352 OptionOrderPtr
= AllocateZeroPool ((Index
+ 1) * sizeof (UINT16
));
353 CopyMem (OptionOrderPtr
, TempOptionPtr
, Index
* sizeof (UINT16
));
354 OptionOrderPtr
[Index
] = RegisterOptionNumber
;
355 Status
= gRT
->SetVariable (
357 &gEfiGlobalVariableGuid
,
358 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
359 (Index
+ 1) * sizeof (UINT16
),
362 if (EFI_ERROR (Status
)) {
363 gBS
->FreePool (TempOptionPtr
);
364 gBS
->FreePool (OptionOrderPtr
);
368 gBS
->FreePool (TempOptionPtr
);
369 gBS
->FreePool (OptionOrderPtr
);
375 BdsLibVariableToOption (
376 IN OUT LIST_ENTRY
*BdsCommonOptionList
,
377 IN CHAR16
*VariableName
383 Build the boot#### or driver#### option from the VariableName, the
384 build boot#### or driver#### will also be linked to BdsCommonOptionList
388 BdsCommonOptionList - The header of the boot#### or driver#### option link list
390 VariableName - EFI Variable name indicate if it is boot#### or driver####
394 BDS_COMMON_OPTION - Get the option just been created
396 NULL - Failed to get the new option
405 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
406 BDS_COMMON_OPTION
*Option
;
408 UINT32 LoadOptionsSize
;
412 // Read the variable. We will never free this data.
414 Variable
= BdsLibGetVariableAndSize (
416 &gEfiGlobalVariableGuid
,
419 if (Variable
== NULL
) {
423 // Notes: careful defined the variable of Boot#### or
424 // Driver####, consider use some macro to abstract the code
427 // Get the option attribute
430 Attribute
= *(UINT32
*) Variable
;
431 TempPtr
+= sizeof (UINT32
);
434 // Get the option's device path size
436 FilePathSize
= *(UINT16
*) TempPtr
;
437 TempPtr
+= sizeof (UINT16
);
440 // Get the option's description string
442 Description
= (CHAR16
*) TempPtr
;
445 // Get the option's description string size
447 TempPtr
+= StrSize ((CHAR16
*) TempPtr
);
450 // Get the option's device path
452 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
;
453 TempPtr
+= FilePathSize
;
455 LoadOptions
= TempPtr
;
456 LoadOptionsSize
= (UINT32
) (VariableSize
- (UINTN
) (TempPtr
- Variable
));
459 // The Console variables may have multiple device paths, so make
460 // an Entry for each one.
462 Option
= AllocateZeroPool (sizeof (BDS_COMMON_OPTION
));
463 if (Option
== NULL
) {
467 Option
->Signature
= BDS_LOAD_OPTION_SIGNATURE
;
468 Option
->DevicePath
= AllocateZeroPool (GetDevicePathSize (DevicePath
));
469 CopyMem (Option
->DevicePath
, DevicePath
, GetDevicePathSize (DevicePath
));
470 Option
->Attribute
= Attribute
;
471 Option
->Description
= AllocateZeroPool (StrSize (Description
));
472 CopyMem (Option
->Description
, Description
, StrSize (Description
));
473 Option
->LoadOptions
= AllocateZeroPool (LoadOptionsSize
);
474 CopyMem (Option
->LoadOptions
, LoadOptions
, LoadOptionsSize
);
475 Option
->LoadOptionsSize
= LoadOptionsSize
;
478 // Insert active entry to BdsDeviceList
480 if ((Option
->Attribute
& LOAD_OPTION_ACTIVE
) == LOAD_OPTION_ACTIVE
) {
481 InsertTailList (BdsCommonOptionList
, &Option
->Link
);
482 gBS
->FreePool (Variable
);
486 gBS
->FreePool (Variable
);
487 gBS
->FreePool (Option
);
493 BdsLibBuildOptionFromVar (
494 IN LIST_ENTRY
*BdsCommonOptionList
,
495 IN CHAR16
*VariableName
501 Process BootOrder, or DriverOrder variables, by calling
502 BdsLibVariableToOption () for each UINT16 in the variables.
506 BdsCommonOptionList - The header of the option list base on variable
509 VariableName - EFI Variable name indicate the BootOrder or DriverOrder
513 EFI_SUCCESS - Success create the boot option or driver option list
515 EFI_OUT_OF_RESOURCES - Failed to get the boot option or driver option list
520 UINTN OptionOrderSize
;
522 BDS_COMMON_OPTION
*Option
;
523 CHAR16 OptionName
[20];
526 // Zero Buffer in order to get all BOOT#### variables
528 ZeroMem (OptionName
, sizeof (OptionName
));
531 // Read the BootOrder, or DriverOrder variable.
533 OptionOrder
= BdsLibGetVariableAndSize (
535 &gEfiGlobalVariableGuid
,
538 if (OptionOrder
== NULL
) {
539 return EFI_OUT_OF_RESOURCES
;
542 for (Index
= 0; Index
< OptionOrderSize
/ sizeof (UINT16
); Index
++) {
543 if (*VariableName
== 'B') {
544 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Boot%04x", OptionOrder
[Index
]);
546 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"Driver%04x", OptionOrder
[Index
]);
548 Option
= BdsLibVariableToOption (BdsCommonOptionList
, OptionName
);
549 Option
->BootCurrent
= OptionOrder
[Index
];
553 gBS
->FreePool (OptionOrder
);
560 OUT EFI_BOOT_MODE
*BootMode
566 Get boot mode by looking up configuration table and parsing HOB list
570 BootMode - Boot mode from PEI handoff HOB.
574 EFI_SUCCESS - Successfully get boot mode
576 EFI_NOT_FOUND - Can not find the current system boot mode
580 EFI_HOB_HANDOFF_INFO_TABLE
*HobList
;
582 HobList
= GetHobList ();
583 ASSERT (HobList
->Header
.HobType
== EFI_HOB_TYPE_HANDOFF
);
584 *BootMode
= HobList
->BootMode
;
590 BdsLibGetVariableAndSize (
592 IN EFI_GUID
*VendorGuid
,
593 OUT UINTN
*VariableSize
599 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
600 buffer, and the size of the buffer. If failure return NULL.
604 Name - String part of EFI variable name
606 VendorGuid - GUID part of EFI variable name
608 VariableSize - Returns the size of the EFI variable that was read
612 Dynamically allocated memory that contains a copy of the EFI variable.
613 Caller is responsible freeing the buffer.
615 NULL - Variable was not read
626 // Pass in a zero size buffer to find the required buffer size.
629 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
630 if (Status
== EFI_BUFFER_TOO_SMALL
) {
632 // Allocate the buffer to return
634 Buffer
= AllocateZeroPool (BufferSize
);
635 if (Buffer
== NULL
) {
639 // Read variable into the allocated buffer.
641 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
642 if (EFI_ERROR (Status
)) {
647 *VariableSize
= BufferSize
;
652 BdsLibMatchDevicePaths (
653 IN EFI_DEVICE_PATH_PROTOCOL
*Multi
,
654 IN EFI_DEVICE_PATH_PROTOCOL
*Single
660 Function compares a device path data structure to that of all the nodes of a
661 second device path instance.
665 Multi - A pointer to a multi-instance device path data structure.
667 Single - A pointer to a single-instance device path data structure.
671 TRUE - If the Single is contained within Multi
673 FALSE - The Single is not match within Multi
678 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
679 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
682 if (!Multi
|| !Single
) {
687 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
688 Size
-= sizeof (EFI_DEVICE_PATH_PROTOCOL
);
691 // Search for the match of 'Single' in 'Multi'
693 while (DevicePathInst
!= NULL
) {
695 // If the single device path is found in multiple device paths,
702 if (CompareMem (Single
, DevicePathInst
, Size
) == 0) {
706 gBS
->FreePool (DevicePathInst
);
707 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
708 Size
-= sizeof (EFI_DEVICE_PATH_PROTOCOL
);
715 BdsLibOutputStrings (
716 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*ConOut
,
723 This function prints a series of strings.
727 ConOut - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL
729 ... - A variable argument list containing series of strings,
730 the last string must be NULL.
734 EFI_SUCCESS - Success print out the string using ConOut.
736 EFI_STATUS - Return the status of the ConOut->OutputString ().
744 Status
= EFI_SUCCESS
;
745 VA_START (args
, ConOut
);
747 while (!EFI_ERROR (Status
)) {
749 // If String is NULL, then it's the end of the list
751 String
= VA_ARG (args
, CHAR16
*);
756 Status
= ConOut
->OutputString (ConOut
, String
);
758 if (EFI_ERROR (Status
)) {