2 Load option library functions which relate with creating and processing load options.
4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "InternalBm.h"
18 GLOBAL_REMOVE_IF_UNREFERENCED
19 CHAR16
*mBmLoadOptionName
[] = {
25 GLOBAL_REMOVE_IF_UNREFERENCED
26 CHAR16
*mBmLoadOptionOrderName
[] = {
27 EFI_DRIVER_ORDER_VARIABLE_NAME
,
28 EFI_SYS_PREP_ORDER_VARIABLE_NAME
,
29 EFI_BOOT_ORDER_VARIABLE_NAME
33 Call Visitor function for each variable in variable storage.
35 @param Visitor Visitor function.
36 @param Context The context passed to Visitor function.
40 BM_VARIABLE_VISITOR Visitor
,
50 NameSize
= sizeof (CHAR16
);
51 Name
= AllocateZeroPool (NameSize
);
52 ASSERT (Name
!= NULL
);
54 NewNameSize
= NameSize
;
55 Status
= gRT
->GetNextVariableName (&NewNameSize
, Name
, &Guid
);
56 if (Status
== EFI_BUFFER_TOO_SMALL
) {
57 Name
= ReallocatePool (NameSize
, NewNameSize
, Name
);
58 ASSERT (Name
!= NULL
);
59 Status
= gRT
->GetNextVariableName (&NewNameSize
, Name
, &Guid
);
60 NameSize
= NewNameSize
;
63 if (Status
== EFI_NOT_FOUND
) {
66 ASSERT_EFI_ERROR (Status
);
68 Visitor (Name
, &Guid
, Context
);
75 Get the Option Number that wasn't used.
77 @param LoadOptionType The load option type.
78 @param FreeOptionNumber Return the minimal free option number.
80 @retval EFI_SUCCESS The option number is found and will be returned.
81 @retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
82 @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
86 BmGetFreeOptionNumber (
87 IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
,
88 OUT UINT16
*FreeOptionNumber
95 UINTN OptionOrderSize
;
98 ASSERT (FreeOptionNumber
!= NULL
);
99 ASSERT (LoadOptionType
== LoadOptionTypeDriver
||
100 LoadOptionType
== LoadOptionTypeBoot
||
101 LoadOptionType
== LoadOptionTypeSysPrep
);
103 GetEfiGlobalVariable2 (mBmLoadOptionOrderName
[LoadOptionType
], (VOID
**) &OptionOrder
, &OptionOrderSize
);
104 ASSERT ((OptionOrder
!= NULL
&& OptionOrderSize
!= 0) || (OptionOrder
== NULL
&& OptionOrderSize
== 0));
107 if (LoadOptionType
== LoadOptionTypeBoot
) {
108 GetEfiGlobalVariable2 (L
"BootNext", (VOID
**) &BootNext
, NULL
);
111 for (OptionNumber
= 0;
112 OptionNumber
< OptionOrderSize
/ sizeof (UINT16
)
113 + ((BootNext
!= NULL
) ? 1 : 0);
117 // Search in OptionOrder whether the OptionNumber exists
119 for (Index
= 0; Index
< OptionOrderSize
/ sizeof (UINT16
); Index
++) {
120 if (OptionNumber
== OptionOrder
[Index
]) {
126 // We didn't find it in the ****Order array and it doesn't equal to BootNext
127 // Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
129 if ((Index
== OptionOrderSize
/ sizeof (UINT16
)) &&
130 ((BootNext
== NULL
) || (OptionNumber
!= *BootNext
))
135 if (OptionOrder
!= NULL
) {
136 FreePool (OptionOrder
);
139 if (BootNext
!= NULL
) {
144 // When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
145 // OptionNumber equals to 0x10000 which is not valid.
147 ASSERT (OptionNumber
<= 0x10000);
148 if (OptionNumber
== 0x10000) {
149 return EFI_OUT_OF_RESOURCES
;
151 *FreeOptionNumber
= (UINT16
) OptionNumber
;
157 Create the Boot####, Driver####, SysPrep####, variable from the load option.
159 @param LoadOption Pointer to the load option.
161 @retval EFI_SUCCESS The variable was created.
162 @retval Others Error status returned by RT->SetVariable.
166 EfiBootManagerLoadOptionToVariable (
167 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Option
173 CHAR16 OptionName
[BM_OPTION_NAME_LEN
];
176 UINT32 VariableAttributes
;
178 if ((Option
->OptionNumber
== LoadOptionNumberUnassigned
) ||
179 (Option
->FilePath
== NULL
) ||
180 ((UINT32
) Option
->OptionType
>= LoadOptionTypeMax
)
182 return EFI_INVALID_PARAMETER
;
186 // Convert NULL description to empty description
189 Description
= Option
->Description
;
190 if (Description
== NULL
) {
191 Description
= &NullChar
;
196 UINT16 FilePathListLength;
197 CHAR16 Description[];
198 EFI_DEVICE_PATH_PROTOCOL FilePathList[];
199 UINT8 OptionalData[];
200 TODO: FilePathList[] IS:
201 A packed array of UEFI device paths. The first element of the
202 array is a device path that describes the device and location of the
203 Image for this load option. The FilePathList[0] is specific
204 to the device type. Other device paths may optionally exist in the
205 FilePathList, but their usage is OSV specific. Each element
206 in the array is variable length, and ends at the device path end
209 VariableSize
= sizeof (Option
->Attributes
)
211 + StrSize (Description
)
212 + GetDevicePathSize (Option
->FilePath
)
213 + Option
->OptionalDataSize
;
215 Variable
= AllocatePool (VariableSize
);
216 ASSERT (Variable
!= NULL
);
219 WriteUnaligned32 ((UINT32
*) Ptr
, Option
->Attributes
);
220 Ptr
+= sizeof (Option
->Attributes
);
222 WriteUnaligned16 ((UINT16
*) Ptr
, (UINT16
) GetDevicePathSize (Option
->FilePath
));
223 Ptr
+= sizeof (UINT16
);
225 CopyMem (Ptr
, Description
, StrSize (Description
));
226 Ptr
+= StrSize (Description
);
228 CopyMem (Ptr
, Option
->FilePath
, GetDevicePathSize (Option
->FilePath
));
229 Ptr
+= GetDevicePathSize (Option
->FilePath
);
231 CopyMem (Ptr
, Option
->OptionalData
, Option
->OptionalDataSize
);
233 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"%s%04x", mBmLoadOptionName
[Option
->OptionType
], Option
->OptionNumber
);
235 VariableAttributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
237 return gRT
->SetVariable (
239 &gEfiGlobalVariableGuid
,
247 Update order variable .
249 @param OptionOrderName Order variable name which need to be updated.
250 @param OptionNumber Option number for the new option.
251 @param Position Position of the new load option to put in the ****Order variable.
253 @retval EFI_SUCCESS The boot#### or driver#### have been successfully registered.
254 @retval EFI_ALREADY_STARTED The option number of Option is being used already.
255 @retval EFI_STATUS Return the status of gRT->SetVariable ().
259 BmAddOptionNumberToOrderVariable (
260 IN CHAR16
*OptionOrderName
,
261 IN UINT16 OptionNumber
,
268 UINT16
*NewOptionOrder
;
269 UINTN OptionOrderSize
;
271 // Update the option order variable
273 GetEfiGlobalVariable2 (OptionOrderName
, (VOID
**) &OptionOrder
, &OptionOrderSize
);
274 ASSERT ((OptionOrder
!= NULL
&& OptionOrderSize
!= 0) || (OptionOrder
== NULL
&& OptionOrderSize
== 0));
276 Status
= EFI_SUCCESS
;
277 for (Index
= 0; Index
< OptionOrderSize
/ sizeof (UINT16
); Index
++) {
278 if (OptionOrder
[Index
] == OptionNumber
) {
279 Status
= EFI_ALREADY_STARTED
;
284 if (!EFI_ERROR (Status
)) {
285 Position
= MIN (Position
, OptionOrderSize
/ sizeof (UINT16
));
287 NewOptionOrder
= AllocatePool (OptionOrderSize
+ sizeof (UINT16
));
288 ASSERT (NewOptionOrder
!= NULL
);
289 if (OptionOrderSize
!= 0) {
290 CopyMem (NewOptionOrder
, OptionOrder
, Position
* sizeof (UINT16
));
291 CopyMem (&NewOptionOrder
[Position
+ 1], &OptionOrder
[Position
], OptionOrderSize
- Position
* sizeof (UINT16
));
293 NewOptionOrder
[Position
] = OptionNumber
;
295 Status
= gRT
->SetVariable (
297 &gEfiGlobalVariableGuid
,
298 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
299 OptionOrderSize
+ sizeof (UINT16
),
302 FreePool (NewOptionOrder
);
305 if (OptionOrder
!= NULL
) {
306 FreePool (OptionOrder
);
313 This function will register the new Boot####, Driver#### or SysPrep#### option.
314 After the *#### is updated, the *Order will also be updated.
316 @param Option Pointer to load option to add.
317 @param Position Position of the new load option to put in the ****Order variable.
319 @retval EFI_SUCCESS The *#### have been successfully registered.
320 @retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
321 @retval EFI_ALREADY_STARTED The option number of Option is being used already.
322 Note: this API only adds new load option, no replacement support.
323 @retval EFI_OUT_OF_RESOURCES There is no free option number that can be used when the
324 option number specified in the Option is LoadOptionNumberUnassigned.
325 @retval EFI_STATUS Return the status of gRT->SetVariable ().
330 EfiBootManagerAddLoadOptionVariable (
331 IN EFI_BOOT_MANAGER_LOAD_OPTION
*Option
,
338 if (Option
== NULL
) {
339 return EFI_INVALID_PARAMETER
;
342 if (Option
->OptionType
!= LoadOptionTypeDriver
&&
343 Option
->OptionType
!= LoadOptionTypeSysPrep
&&
344 Option
->OptionType
!= LoadOptionTypeBoot
346 return EFI_INVALID_PARAMETER
;
350 // Get the free option number if the option number is unassigned
352 if (Option
->OptionNumber
== LoadOptionNumberUnassigned
) {
353 Status
= BmGetFreeOptionNumber (Option
->OptionType
, &OptionNumber
);
354 if (EFI_ERROR (Status
)) {
357 Option
->OptionNumber
= OptionNumber
;
360 if (Option
->OptionNumber
>= LoadOptionNumberMax
) {
361 return EFI_INVALID_PARAMETER
;
364 Status
= BmAddOptionNumberToOrderVariable (mBmLoadOptionOrderName
[Option
->OptionType
], (UINT16
) Option
->OptionNumber
, Position
);
365 if (!EFI_ERROR (Status
)) {
367 // Save the Boot#### or Driver#### variable
369 Status
= EfiBootManagerLoadOptionToVariable (Option
);
370 if (EFI_ERROR (Status
)) {
372 // Remove the #### from *Order variable when the Driver####/SysPrep####/Boot#### cannot be saved.
374 EfiBootManagerDeleteLoadOptionVariable (Option
->OptionNumber
, Option
->OptionType
);
382 Sort the load option. The DriverOrder or BootOrder will be re-created to
383 reflect the new order.
385 @param OptionType Load option type
386 @param CompareFunction The comparator
390 EfiBootManagerSortLoadOptionVariable (
391 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
,
392 SORT_COMPARE CompareFunction
396 EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOption
;
397 UINTN LoadOptionCount
;
401 LoadOption
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, OptionType
);
404 // Insertion sort algorithm
409 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
),
414 // Create new ****Order variable
416 OptionOrder
= AllocatePool (LoadOptionCount
* sizeof (UINT16
));
417 ASSERT (OptionOrder
!= NULL
);
418 for (Index
= 0; Index
< LoadOptionCount
; Index
++) {
419 OptionOrder
[Index
] = (UINT16
) LoadOption
[Index
].OptionNumber
;
422 Status
= gRT
->SetVariable (
423 mBmLoadOptionOrderName
[OptionType
],
424 &gEfiGlobalVariableGuid
,
425 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
426 LoadOptionCount
* sizeof (UINT16
),
430 // Changing the *Order content without increasing its size with current variable implementation shouldn't fail.
432 ASSERT_EFI_ERROR (Status
);
434 FreePool (OptionOrder
);
435 EfiBootManagerFreeLoadOptions (LoadOption
, LoadOptionCount
);
439 Initialize a load option.
441 @param Option Pointer to the load option to be initialized.
442 @param OptionNumber Option number of the load option.
443 @param OptionType Type of the load option.
444 @param Attributes Attributes of the load option.
445 @param Description Description of the load option.
446 @param FilePath Device path of the load option.
447 @param OptionalData Optional data of the load option.
448 @param OptionalDataSize Size of the optional data of the load option.
450 @retval EFI_SUCCESS The load option was initialized successfully.
451 @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
455 EfiBootManagerInitializeLoadOption (
456 IN OUT EFI_BOOT_MANAGER_LOAD_OPTION
*Option
,
457 IN UINTN OptionNumber
,
458 IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
,
459 IN UINT32 Attributes
,
460 IN CHAR16
*Description
,
461 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
462 IN UINT8
*OptionalData
, OPTIONAL
463 IN UINT32 OptionalDataSize
466 if ((Option
== NULL
) || (Description
== NULL
) || (FilePath
== NULL
)) {
467 return EFI_INVALID_PARAMETER
;
470 if (((OptionalData
!= NULL
) && (OptionalDataSize
== 0)) ||
471 ((OptionalData
== NULL
) && (OptionalDataSize
!= 0))) {
472 return EFI_INVALID_PARAMETER
;
475 if ((UINT32
) OptionType
>= LoadOptionTypeMax
) {
476 return EFI_INVALID_PARAMETER
;
479 ZeroMem (Option
, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
));
480 Option
->OptionNumber
= OptionNumber
;
481 Option
->OptionType
= OptionType
;
482 Option
->Attributes
= Attributes
;
483 Option
->Description
= AllocateCopyPool (StrSize (Description
), Description
);
484 Option
->FilePath
= DuplicateDevicePath (FilePath
);
485 if (OptionalData
!= NULL
) {
486 Option
->OptionalData
= AllocateCopyPool (OptionalDataSize
, OptionalData
);
487 Option
->OptionalDataSize
= OptionalDataSize
;
495 Return the index of the load option in the load option array.
497 The function consider two load options are equal when the
498 OptionType, Attributes, Description, FilePath and OptionalData are equal.
500 @param Key Pointer to the load option to be found.
501 @param Array Pointer to the array of load options to be found.
502 @param Count Number of entries in the Array.
504 @retval -1 Key wasn't found in the Array.
505 @retval 0 ~ Count-1 The index of the Key in the Array.
509 EfiBootManagerFindLoadOption (
510 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Key
,
511 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Array
,
517 for (Index
= 0; Index
< Count
; Index
++) {
518 if ((Key
->OptionType
== Array
[Index
].OptionType
) &&
519 (Key
->Attributes
== Array
[Index
].Attributes
) &&
520 (StrCmp (Key
->Description
, Array
[Index
].Description
) == 0) &&
521 (CompareMem (Key
->FilePath
, Array
[Index
].FilePath
, GetDevicePathSize (Key
->FilePath
)) == 0) &&
522 (Key
->OptionalDataSize
== Array
[Index
].OptionalDataSize
) &&
523 (CompareMem (Key
->OptionalData
, Array
[Index
].OptionalData
, Key
->OptionalDataSize
) == 0)) {
532 Delete the load option.
534 @param OptionNumber Indicate the option number of load option
535 @param OptionType Indicate the type of load option
537 @retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
538 @retval EFI_NOT_FOUND The load option cannot be found
539 @retval EFI_SUCCESS The load option was deleted
540 @retval others Status of RT->SetVariable()
544 EfiBootManagerDeleteLoadOptionVariable (
545 IN UINTN OptionNumber
,
546 IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
550 UINTN OptionOrderSize
;
554 if (((UINT32
) OptionType
>= LoadOptionTypeMax
) || (OptionNumber
>= LoadOptionNumberMax
)) {
555 return EFI_INVALID_PARAMETER
;
558 Status
= EFI_NOT_FOUND
;
560 if (OptionType
== LoadOptionTypeDriver
|| OptionType
== LoadOptionTypeSysPrep
|| OptionType
== LoadOptionTypeBoot
) {
562 // If the associated *Order exists, just remove the reference in *Order.
564 GetEfiGlobalVariable2 (mBmLoadOptionOrderName
[OptionType
], (VOID
**) &OptionOrder
, &OptionOrderSize
);
565 ASSERT ((OptionOrder
!= NULL
&& OptionOrderSize
!= 0) || (OptionOrder
== NULL
&& OptionOrderSize
== 0));
567 for (Index
= 0; Index
< OptionOrderSize
/ sizeof (UINT16
); Index
++) {
568 if (OptionOrder
[Index
] == OptionNumber
) {
569 OptionOrderSize
-= sizeof (UINT16
);
570 CopyMem (&OptionOrder
[Index
], &OptionOrder
[Index
+ 1], OptionOrderSize
- Index
* sizeof (UINT16
));
571 Status
= gRT
->SetVariable (
572 mBmLoadOptionOrderName
[OptionType
],
573 &gEfiGlobalVariableGuid
,
574 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
581 if (OptionOrder
!= NULL
) {
582 FreePool (OptionOrder
);
590 Returns the size of a device path in bytes.
592 This function returns the size, in bytes, of the device path data structure
593 specified by DevicePath including the end of device path node. If DevicePath
594 is NULL, then 0 is returned. If the length of the device path is bigger than
595 MaxSize, also return 0 to indicate this is an invalidate device path.
597 @param DevicePath A pointer to a device path data structure.
598 @param MaxSize Max valid device path size. If big than this size,
601 @retval 0 An invalid device path.
602 @retval Others The size of a device path in bytes.
606 BmGetDevicePathSizeEx (
607 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
614 if (DevicePath
== NULL
) {
619 // Search for the end of the device path structure
622 while (!IsDevicePathEnd (DevicePath
)) {
623 NodeSize
= DevicePathNodeLength (DevicePath
);
628 if (Size
> MaxSize
) {
631 DevicePath
= NextDevicePathNode (DevicePath
);
633 Size
+= DevicePathNodeLength (DevicePath
);
634 if (Size
> MaxSize
) {
642 Returns the length of a Null-terminated Unicode string. If the length is
643 bigger than MaxStringLen, return length 0 to indicate that this is an
646 This function returns the number of Unicode characters in the Null-terminated
647 Unicode string specified by String.
649 If String is NULL, then ASSERT().
650 If String is not aligned on a 16-bit boundary, then ASSERT().
652 @param String A pointer to a Null-terminated Unicode string.
653 @param MaxStringLen Max string len in this string.
655 @retval 0 An invalid string.
656 @retval Others The length of String.
661 IN CONST CHAR16
*String
,
662 IN UINTN MaxStringLen
667 ASSERT (String
!= NULL
&& MaxStringLen
!= 0);
668 ASSERT (((UINTN
) String
& BIT0
) == 0);
670 for (Length
= 0; *String
!= L
'\0' && MaxStringLen
!= Length
; String
++, Length
+=2);
672 if (*String
!= L
'\0' && MaxStringLen
== Length
) {
680 Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)
682 @param Variable The variable data.
683 @param VariableSize The variable size.
685 @retval TRUE The variable data is correct.
686 @retval FALSE The variable data is corrupted.
696 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
697 UINTN DescriptionSize
;
699 if (VariableSize
<= sizeof (UINT16
) + sizeof (UINT32
)) {
704 // Skip the option attribute
706 Variable
+= sizeof (UINT32
);
709 // Get the option's device path size
711 FilePathSize
= ReadUnaligned16 ((UINT16
*) Variable
);
712 Variable
+= sizeof (UINT16
);
715 // Get the option's description string size
717 DescriptionSize
= BmStrSizeEx ((CHAR16
*) Variable
, VariableSize
- sizeof (UINT16
) - sizeof (UINT32
));
718 Variable
+= DescriptionSize
;
721 // Get the option's device path
723 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Variable
;
726 // Validation boot option variable.
728 if ((FilePathSize
== 0) || (DescriptionSize
== 0)) {
732 if (sizeof (UINT32
) + sizeof (UINT16
) + DescriptionSize
+ FilePathSize
> VariableSize
) {
736 return (BOOLEAN
) (BmGetDevicePathSizeEx (DevicePath
, FilePathSize
) != 0);
740 Check whether the VariableName is a valid load option variable name
741 and return the load option type and option number.
743 @param VariableName The name of the load option variable.
744 @param OptionType Return the load option type.
745 @param OptionNumber Return the load option number.
747 @retval TRUE The variable name is valid; The load option type and
748 load option number is returned.
749 @retval FALSE The variable name is NOT valid.
752 BmIsValidLoadOptionVariableName (
753 IN CHAR16
*VariableName
,
754 OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE
*OptionType
,
755 OUT UINT16
*OptionNumber
758 UINTN VariableNameLen
;
762 VariableNameLen
= StrLen (VariableName
);
764 if (VariableNameLen
<= 4) {
768 for (Index
= 0; Index
< sizeof (mBmLoadOptionName
) / sizeof (mBmLoadOptionName
[0]); Index
++) {
769 if ((VariableNameLen
- 4 == StrLen (mBmLoadOptionName
[Index
])) &&
770 (StrnCmp (VariableName
, mBmLoadOptionName
[Index
], VariableNameLen
- 4) == 0)
776 if (Index
== sizeof (mBmLoadOptionName
) / sizeof (mBmLoadOptionName
[0])) {
780 *OptionType
= (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE
) Index
;
782 for (Index
= VariableNameLen
- 4; Index
< VariableNameLen
; Index
++) {
783 Uint
= BmCharToUint (VariableName
[Index
]);
787 *OptionNumber
= (UINT16
) Uint
+ *OptionNumber
* 0x10;
791 return (BOOLEAN
) (Index
== VariableNameLen
);
795 Build the Boot#### or Driver#### option from the VariableName.
797 @param VariableName Variable name of the load option
798 @param VendorGuid Variable GUID of the load option
799 @param Option Return the load option.
801 @retval EFI_SUCCESS Get the option just been created
802 @retval EFI_NOT_FOUND Failed to get the new option
807 EfiBootManagerVariableToLoadOptionEx (
808 IN CHAR16
*VariableName
,
809 IN EFI_GUID
*VendorGuid
,
810 IN OUT EFI_BOOT_MANAGER_LOAD_OPTION
*Option
819 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
821 UINT32 OptionalDataSize
;
823 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
;
826 if ((VariableName
== NULL
) || (Option
== NULL
)) {
827 return EFI_INVALID_PARAMETER
;
830 if (!BmIsValidLoadOptionVariableName (VariableName
, &OptionType
, &OptionNumber
)) {
831 return EFI_INVALID_PARAMETER
;
837 GetVariable2 (VariableName
, VendorGuid
, (VOID
**) &Variable
, &VariableSize
);
838 if (Variable
== NULL
) {
839 return EFI_NOT_FOUND
;
843 // Validate *#### variable data.
845 if (!BmValidateOption(Variable
, VariableSize
)) {
847 return EFI_INVALID_PARAMETER
;
851 // Get the option attribute
853 VariablePtr
= Variable
;
854 Attribute
= ReadUnaligned32 ((UINT32
*) VariablePtr
);
855 VariablePtr
+= sizeof (UINT32
);
858 // Get the option's device path size
860 FilePathSize
= ReadUnaligned16 ((UINT16
*) VariablePtr
);
861 VariablePtr
+= sizeof (UINT16
);
864 // Get the option's description string
866 Description
= (CHAR16
*) VariablePtr
;
869 // Get the option's description string size
871 VariablePtr
+= StrSize ((CHAR16
*) VariablePtr
);
874 // Get the option's device path
876 FilePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariablePtr
;
877 VariablePtr
+= FilePathSize
;
879 OptionalDataSize
= (UINT32
) (VariableSize
- (UINTN
) (VariablePtr
- Variable
));
880 if (OptionalDataSize
== 0) {
883 OptionalData
= VariablePtr
;
886 Status
= EfiBootManagerInitializeLoadOption (
896 ASSERT_EFI_ERROR (Status
);
898 CopyGuid (&Option
->VendorGuid
, VendorGuid
);
905 Build the Boot#### or Driver#### option from the VariableName.
907 @param VariableName EFI Variable name indicate if it is Boot#### or Driver####
908 @param Option Return the Boot#### or Driver#### option.
910 @retval EFI_SUCCESS Get the option just been created
911 @retval EFI_NOT_FOUND Failed to get the new option
915 EfiBootManagerVariableToLoadOption (
916 IN CHAR16
*VariableName
,
917 IN OUT EFI_BOOT_MANAGER_LOAD_OPTION
*Option
920 return EfiBootManagerVariableToLoadOptionEx (VariableName
, &gEfiGlobalVariableGuid
, Option
);
924 Returns an array of load options based on the EFI variable
925 L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
926 #### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
928 @param LoadOptionCount Returns number of entries in the array.
929 @param LoadOptionType The type of the load option.
931 @retval NULL No load options exist.
932 @retval !NULL Array of load option entries.
935 EFI_BOOT_MANAGER_LOAD_OPTION
*
937 EfiBootManagerGetLoadOptions (
938 OUT UINTN
*OptionCount
,
939 IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
944 UINTN OptionOrderSize
;
947 EFI_BOOT_MANAGER_LOAD_OPTION
*Options
;
948 CHAR16 OptionName
[BM_OPTION_NAME_LEN
];
953 if (LoadOptionType
== LoadOptionTypeDriver
|| LoadOptionType
== LoadOptionTypeSysPrep
|| LoadOptionType
== LoadOptionTypeBoot
) {
955 // Read the BootOrder, or DriverOrder variable.
957 GetEfiGlobalVariable2 (mBmLoadOptionOrderName
[LoadOptionType
], (VOID
**) &OptionOrder
, &OptionOrderSize
);
958 if (OptionOrder
== NULL
) {
962 *OptionCount
= OptionOrderSize
/ sizeof (UINT16
);
964 Options
= AllocatePool (*OptionCount
* sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
));
965 ASSERT (Options
!= NULL
);
968 for (Index
= 0; Index
< *OptionCount
; Index
++) {
969 OptionNumber
= OptionOrder
[Index
];
970 UnicodeSPrint (OptionName
, sizeof (OptionName
), L
"%s%04x", mBmLoadOptionName
[LoadOptionType
], OptionNumber
);
972 Status
= EfiBootManagerVariableToLoadOption (OptionName
, &Options
[OptionIndex
]);
973 if (EFI_ERROR (Status
)) {
974 DEBUG ((EFI_D_INFO
, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName
));
975 EfiBootManagerDeleteLoadOptionVariable (OptionNumber
, LoadOptionType
);
977 ASSERT (Options
[OptionIndex
].OptionNumber
== OptionNumber
);
982 if (OptionOrder
!= NULL
) {
983 FreePool (OptionOrder
);
986 if (OptionIndex
< *OptionCount
) {
987 Options
= ReallocatePool (*OptionCount
* sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
), OptionIndex
* sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
), Options
);
988 ASSERT (Options
!= NULL
);
989 *OptionCount
= OptionIndex
;
1000 Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
1002 @param LoadOption Pointer to boot option to Free.
1004 @return EFI_SUCCESS BootOption was freed
1005 @return EFI_NOT_FOUND BootOption == NULL
1010 EfiBootManagerFreeLoadOption (
1011 IN EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOption
1014 if (LoadOption
== NULL
) {
1015 return EFI_NOT_FOUND
;
1018 if (LoadOption
->Description
!= NULL
) {
1019 FreePool (LoadOption
->Description
);
1021 if (LoadOption
->FilePath
!= NULL
) {
1022 FreePool (LoadOption
->FilePath
);
1024 if (LoadOption
->OptionalData
!= NULL
) {
1025 FreePool (LoadOption
->OptionalData
);
1032 Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by
1033 EfiBootManagerGetLoadOptions().
1035 @param Option Pointer to boot option array to free.
1036 @param OptionCount Number of array entries in BootOption
1038 @return EFI_SUCCESS BootOption was freed
1039 @return EFI_NOT_FOUND BootOption == NULL
1044 EfiBootManagerFreeLoadOptions (
1045 IN EFI_BOOT_MANAGER_LOAD_OPTION
*Option
,
1046 IN UINTN OptionCount
1051 if (Option
== NULL
) {
1052 return EFI_NOT_FOUND
;
1055 for (Index
= 0;Index
< OptionCount
; Index
++) {
1056 EfiBootManagerFreeLoadOption (&Option
[Index
]);
1065 Return whether the PE header of the load option is valid or not.
1067 @param[in] Type The load option type.
1068 @param[in] FileBuffer The PE file buffer of the load option.
1069 @param[in] FileSize The size of the load option file.
1071 @retval TRUE The PE header of the load option is valid.
1072 @retval FALSE The PE header of the load option is not valid.
1075 BmIsLoadOptionPeHeaderValid (
1076 IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type
,
1077 IN VOID
*FileBuffer
,
1081 EFI_IMAGE_DOS_HEADER
*DosHeader
;
1082 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHeader
;
1083 EFI_IMAGE_OPTIONAL_HEADER32
*OptionalHeader
;
1086 if (FileBuffer
== NULL
|| FileSize
== 0) {
1093 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
1094 if (FileSize
>= sizeof (EFI_IMAGE_DOS_HEADER
) &&
1095 FileSize
> DosHeader
->e_lfanew
&& DosHeader
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
1098 // Read and check PE signature
1100 PeHeader
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINT8
*) FileBuffer
+ DosHeader
->e_lfanew
);
1101 if (FileSize
>= DosHeader
->e_lfanew
+ sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
) &&
1102 PeHeader
->Pe32
.Signature
== EFI_IMAGE_NT_SIGNATURE
1105 // Check PE32 or PE32+ magic, and machine type
1107 OptionalHeader
= (EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHeader
->Pe32
.OptionalHeader
;
1108 if ((OptionalHeader
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
||
1109 OptionalHeader
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) &&
1110 EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHeader
->Pe32
.FileHeader
.Machine
)
1113 // Check the Subsystem:
1114 // Driver#### must be of type BootServiceDriver or RuntimeDriver
1115 // SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
1117 Subsystem
= OptionalHeader
->Subsystem
;
1118 if ((Type
== LoadOptionTypeDriver
&& Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
1119 (Type
== LoadOptionTypeDriver
&& Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) ||
1120 (Type
== LoadOptionTypeSysPrep
&& Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) ||
1121 (Type
== LoadOptionTypeBoot
&& Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
)
1133 Process (load and execute) the load option.
1135 @param LoadOption Pointer to the load option.
1137 @retval EFI_INVALID_PARAMETER The load option type is invalid,
1138 or the load option file path doesn't point to a valid file.
1139 @retval EFI_UNSUPPORTED The load option type is of LoadOptionTypeBoot.
1140 @retval EFI_SUCCESS The load option is inactive, or successfully loaded and executed.
1144 EfiBootManagerProcessLoadOption (
1145 IN EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOption
1149 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
1150 EFI_HANDLE ImageHandle
;
1151 EFI_LOADED_IMAGE_PROTOCOL
*ImageInfo
;
1155 if ((UINT32
) LoadOption
->OptionType
>= LoadOptionTypeMax
) {
1156 return EFI_INVALID_PARAMETER
;
1159 if (LoadOption
->OptionType
== LoadOptionTypeBoot
) {
1160 return EFI_UNSUPPORTED
;
1164 // If a load option is not marked as LOAD_OPTION_ACTIVE,
1165 // the boot manager will not automatically load the option.
1167 if ((LoadOption
->Attributes
& LOAD_OPTION_ACTIVE
) == 0) {
1171 Status
= EFI_INVALID_PARAMETER
;
1174 // Load and start the load option.
1177 DEBUG_INFO
| DEBUG_LOAD
, "Process Load Option (%s%04x) ...\n",
1178 mBmLoadOptionName
[LoadOption
->OptionType
], LoadOption
->OptionNumber
1181 FileBuffer
= BmGetLoadOptionBuffer (LoadOption
->FilePath
, &FilePath
, &FileSize
);
1183 if (FileBuffer
!= NULL
&& CompareMem (LoadOption
->FilePath
, FilePath
, GetDevicePathSize (FilePath
)) != 0) {
1184 DEBUG ((EFI_D_INFO
, "[Bds] DevicePath expand: "));
1185 BmPrintDp (LoadOption
->FilePath
);
1186 DEBUG ((EFI_D_INFO
, " -> "));
1187 BmPrintDp (FilePath
);
1188 DEBUG ((EFI_D_INFO
, "\n"));
1191 if (BmIsLoadOptionPeHeaderValid (LoadOption
->OptionType
, FileBuffer
, FileSize
)) {
1192 Status
= gBS
->LoadImage (
1201 if (FilePath
!= NULL
) {
1202 FreePool (FilePath
);
1204 if (FileBuffer
!= NULL
) {
1205 FreePool (FileBuffer
);
1208 if (!EFI_ERROR (Status
)) {
1209 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**) &ImageInfo
);
1210 ASSERT_EFI_ERROR (Status
);
1212 ImageInfo
->LoadOptionsSize
= LoadOption
->OptionalDataSize
;
1213 ImageInfo
->LoadOptions
= LoadOption
->OptionalData
;
1215 // Before calling the image, enable the Watchdog Timer for the 5-minute period
1217 gBS
->SetWatchdogTimer (5 * 60, 0, 0, NULL
);
1219 LoadOption
->Status
= gBS
->StartImage (ImageHandle
, &LoadOption
->ExitDataSize
, &LoadOption
->ExitData
);
1221 DEBUG_INFO
| DEBUG_LOAD
, "Load Option (%s%04x) Return Status = %r\n",
1222 mBmLoadOptionName
[LoadOption
->OptionType
], LoadOption
->OptionNumber
, LoadOption
->Status
1226 // Clear the Watchdog Timer after the image returns
1228 gBS
->SetWatchdogTimer (0, 0, 0, NULL
);