2 Variable operation that will be used by bootmaint
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Delete Boot Option that represent a Deleted state in BootOptionMenu.
13 After deleting this boot option, call Var_ChangeBootOrder to
14 make sure BootOrder is in valid state.
16 @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to
17 BM_LOAD_CONTEXT marked for deletion is deleted.
18 @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.
19 @return Others If failed to update the "BootOrder" variable after deletion.
27 BM_MENU_ENTRY
*NewMenuEntry
;
28 BM_LOAD_CONTEXT
*NewLoadContext
;
29 UINT16 BootString
[10];
36 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
37 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, (Index
- Index2
));
38 if (NULL
== NewMenuEntry
) {
42 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
43 if (!NewLoadContext
->Deleted
) {
51 NewMenuEntry
->OptionNumber
54 EfiLibDeleteVariable (BootString
, &gEfiGlobalVariableGuid
);
57 // If current Load Option is the same as BootNext,
58 // must delete BootNext in order to make sure
59 // there will be no panic on next boot
61 if (NewLoadContext
->IsBootNext
) {
62 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
65 RemoveEntryList (&NewMenuEntry
->Link
);
66 BOpt_DestroyMenuEntry (NewMenuEntry
);
70 BootOptionMenu
.MenuNumber
-= Index2
;
72 Status
= Var_ChangeBootOrder ();
77 After any operation on Boot####, there will be a discrepancy in BootOrder.
78 Since some are missing but in BootOrder, while some are present but are
79 not reflected by BootOrder. Then a function rebuild BootOrder from
80 scratch by content from BootOptionMenu is needed.
85 @retval EFI_SUCCESS The boot order is updated successfully.
86 @return EFI_STATUS other than EFI_SUCCESS if failed to
87 Set the "BootOrder" EFI Variable.
97 BM_MENU_ENTRY
*NewMenuEntry
;
98 UINT16
*BootOrderList
;
99 UINT16
*BootOrderListPtr
;
100 UINTN BootOrderListSize
;
103 BootOrderList
= NULL
;
104 BootOrderListSize
= 0;
107 // First check whether BootOrder is present in current configuration
109 BootOrderList
= BdsLibGetVariableAndSize (
111 &gEfiGlobalVariableGuid
,
116 // If exists, delete it to hold new BootOrder
118 if (BootOrderList
!= NULL
) {
119 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
120 FreePool (BootOrderList
);
121 BootOrderList
= NULL
;
124 // Maybe here should be some check method to ensure that
125 // no new added boot options will be added
126 // but the setup engine now will give only one callback
127 // that is to say, user are granted only one chance to
128 // decide whether the boot option will be added or not
129 // there should be no indictor to show whether this
130 // is a "new" boot option
132 BootOrderListSize
= BootOptionMenu
.MenuNumber
;
134 if (BootOrderListSize
> 0) {
135 BootOrderList
= AllocateZeroPool (BootOrderListSize
* sizeof (UINT16
));
136 ASSERT (BootOrderList
!= NULL
);
137 BootOrderListPtr
= BootOrderList
;
140 // Get all current used Boot#### from BootOptionMenu.
141 // OptionNumber in each BM_LOAD_OPTION is really its
144 for (Index
= 0; Index
< BootOrderListSize
; Index
++) {
145 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
146 *BootOrderList
= (UINT16
) NewMenuEntry
->OptionNumber
;
150 BootOrderList
= BootOrderListPtr
;
153 // After building the BootOrderList, write it back
155 Status
= gRT
->SetVariable (
157 &gEfiGlobalVariableGuid
,
158 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
159 BootOrderListSize
* sizeof (UINT16
),
163 // Changing variable without increasing its size with current variable implementation shouldn't fail.
165 ASSERT_EFI_ERROR (Status
);
171 Delete Load Option that represent a Deleted state in BootOptionMenu.
172 After deleting this Driver option, call Var_ChangeDriverOrder to
173 make sure DriverOrder is in valid state.
175 @retval EFI_SUCCESS Load Option is successfully updated.
176 @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
177 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
182 Var_DelDriverOption (
186 BM_MENU_ENTRY
*NewMenuEntry
;
187 BM_LOAD_CONTEXT
*NewLoadContext
;
188 UINT16 DriverString
[12];
193 Status
= EFI_SUCCESS
;
195 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
196 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, (Index
- Index2
));
197 if (NULL
== NewMenuEntry
) {
198 return EFI_NOT_FOUND
;
201 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
202 if (!NewLoadContext
->Deleted
) {
208 sizeof (DriverString
),
210 NewMenuEntry
->OptionNumber
213 EfiLibDeleteVariable (DriverString
, &gEfiGlobalVariableGuid
);
216 RemoveEntryList (&NewMenuEntry
->Link
);
217 BOpt_DestroyMenuEntry (NewMenuEntry
);
221 DriverOptionMenu
.MenuNumber
-= Index2
;
223 Status
= Var_ChangeDriverOrder ();
228 After any operation on Driver####, there will be a discrepancy in
229 DriverOrder. Since some are missing but in DriverOrder, while some
230 are present but are not reflected by DriverOrder. Then a function
231 rebuild DriverOrder from scratch by content from DriverOptionMenu is
234 @retval EFI_SUCCESS The driver order is updated successfully.
235 @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
239 Var_ChangeDriverOrder (
244 BM_MENU_ENTRY
*NewMenuEntry
;
245 UINT16
*DriverOrderList
;
246 UINT16
*DriverOrderListPtr
;
247 UINTN DriverOrderListSize
;
250 DriverOrderList
= NULL
;
251 DriverOrderListSize
= 0;
254 // First check whether DriverOrder is present in current configuration
256 DriverOrderList
= BdsLibGetVariableAndSize (
258 &gEfiGlobalVariableGuid
,
263 // If exists, delete it to hold new DriverOrder
265 if (DriverOrderList
!= NULL
) {
266 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
267 FreePool (DriverOrderList
);
268 DriverOrderList
= NULL
;
271 DriverOrderListSize
= DriverOptionMenu
.MenuNumber
;
273 if (DriverOrderListSize
> 0) {
274 DriverOrderList
= AllocateZeroPool (DriverOrderListSize
* sizeof (UINT16
));
275 ASSERT (DriverOrderList
!= NULL
);
276 DriverOrderListPtr
= DriverOrderList
;
279 // Get all current used Driver#### from DriverOptionMenu.
280 // OptionNumber in each BM_LOAD_OPTION is really its
283 for (Index
= 0; Index
< DriverOrderListSize
; Index
++) {
284 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index
);
285 *DriverOrderList
= (UINT16
) NewMenuEntry
->OptionNumber
;
289 DriverOrderList
= DriverOrderListPtr
;
292 // After building the DriverOrderList, write it back
294 Status
= gRT
->SetVariable (
296 &gEfiGlobalVariableGuid
,
297 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
298 DriverOrderListSize
* sizeof (UINT16
),
302 // Changing variable without increasing its size with current variable implementation shouldn't fail.
304 ASSERT_EFI_ERROR (Status
);
312 This function delete and build multi-instance device path for
313 specified type of console device.
315 This function clear the EFI variable defined by ConsoleName and
316 gEfiGlobalVariableGuid. It then build the multi-instance device
317 path by appending the device path of the Console (In/Out/Err) instance
318 in ConsoleMenu. Then it scan all corresponding console device by
319 scanning Terminal (built from device supporting Serial I/O instances)
320 devices in TerminalMenu. At last, it save a EFI variable specifed
321 by ConsoleName and gEfiGlobalVariableGuid.
323 @param ConsoleName The name for the console device type. They are
324 usually "ConIn", "ConOut" and "ErrOut".
325 @param ConsoleMenu The console memu which is a list of console devices.
326 @param UpdatePageId The flag specifying which type of console device
329 @retval EFI_SUCCESS The function complete successfully.
330 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
334 Var_UpdateConsoleOption (
335 IN UINT16
*ConsoleName
,
336 IN BM_MENU_OPTION
*ConsoleMenu
,
337 IN UINT16 UpdatePageId
340 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
341 BM_MENU_ENTRY
*NewMenuEntry
;
342 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
343 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
345 VENDOR_DEVICE_PATH Vendor
;
346 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
349 ConDevicePath
= EfiLibGetVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
350 if (ConDevicePath
!= NULL
) {
351 EfiLibDeleteVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
352 FreePool (ConDevicePath
);
353 ConDevicePath
= NULL
;
357 // First add all console input device from console input menu
359 for (Index
= 0; Index
< ConsoleMenu
->MenuNumber
; Index
++) {
360 NewMenuEntry
= BOpt_GetMenuEntry (ConsoleMenu
, Index
);
362 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
363 if (NewConsoleContext
->IsActive
) {
364 ConDevicePath
= AppendDevicePathInstance (
366 NewConsoleContext
->DevicePath
371 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
372 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
374 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
375 if (((NewTerminalContext
->IsConIn
!= 0) && (UpdatePageId
== FORM_CON_IN_ID
)) ||
376 ((NewTerminalContext
->IsConOut
!= 0) && (UpdatePageId
== FORM_CON_OUT_ID
)) ||
377 ((NewTerminalContext
->IsStdErr
!= 0) && (UpdatePageId
== FORM_CON_ERR_ID
))
379 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
380 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
382 ASSERT (NewTerminalContext
->TerminalType
< (ARRAY_SIZE (TerminalTypeGuid
)));
385 &TerminalTypeGuid
[NewTerminalContext
->TerminalType
],
388 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
389 TerminalDevicePath
= AppendDevicePathNode (
390 NewTerminalContext
->DevicePath
,
391 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
393 ASSERT (TerminalDevicePath
!= NULL
);
394 ChangeTerminalDevicePath (&TerminalDevicePath
, TRUE
);
395 ConDevicePath
= AppendDevicePathInstance (
402 if (ConDevicePath
!= NULL
) {
403 Status
= gRT
->SetVariable (
405 &gEfiGlobalVariableGuid
,
406 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
407 GetDevicePathSize (ConDevicePath
),
410 if (EFI_ERROR (Status
)) {
420 This function delete and build multi-instance device path ConIn
423 @retval EFI_SUCCESS The function complete successfully.
424 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
427 Var_UpdateConsoleInpOption (
431 return Var_UpdateConsoleOption (L
"ConIn", &ConsoleInpMenu
, FORM_CON_IN_ID
);
435 This function delete and build multi-instance device path ConOut
438 @retval EFI_SUCCESS The function complete successfully.
439 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
442 Var_UpdateConsoleOutOption (
446 return Var_UpdateConsoleOption (L
"ConOut", &ConsoleOutMenu
, FORM_CON_OUT_ID
);
450 This function delete and build multi-instance device path ErrOut
453 @retval EFI_SUCCESS The function complete successfully.
454 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
457 Var_UpdateErrorOutOption (
461 return Var_UpdateConsoleOption (L
"ErrOut", &ConsoleErrMenu
, FORM_CON_ERR_ID
);
465 This function create a currently loaded Drive Option from
466 the BMM. It then appends this Driver Option to the end of
467 the "DriverOrder" list. It append this Driver Opotion to the end
470 @param CallbackData The BMM context data.
471 @param HiiHandle The HII handle associated with the BMM formset.
472 @param DescriptionData The description of this driver option.
473 @param OptionalData The optional load option.
474 @param ForceReconnect If to force reconnect.
476 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
477 @retval EFI_SUCCESS If function completes successfully.
481 Var_UpdateDriverOption (
482 IN BMM_CALLBACK_DATA
*CallbackData
,
483 IN EFI_HII_HANDLE HiiHandle
,
484 IN UINT16
*DescriptionData
,
485 IN UINT16
*OptionalData
,
486 IN UINT8 ForceReconnect
490 UINT16
*DriverOrderList
;
491 UINT16
*NewDriverOrderList
;
492 UINT16 DriverString
[12];
493 UINTN DriverOrderListSize
;
497 BM_MENU_ENTRY
*NewMenuEntry
;
498 BM_LOAD_CONTEXT
*NewLoadContext
;
499 BOOLEAN OptionalDataExist
;
502 OptionalDataExist
= FALSE
;
504 Index
= BOpt_GetDriverOptionNumber ();
507 sizeof (DriverString
),
512 if (*DescriptionData
== 0x0000) {
513 StrCpyS (DescriptionData
, DESCRIPTION_DATA_SIZE
, DriverString
);
516 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescriptionData
);
517 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
519 if (*OptionalData
!= 0x0000) {
520 OptionalDataExist
= TRUE
;
521 BufferSize
+= StrSize (OptionalData
);
524 Buffer
= AllocateZeroPool (BufferSize
);
525 if (NULL
== Buffer
) {
526 return EFI_OUT_OF_RESOURCES
;
529 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
530 if (NULL
== NewMenuEntry
) {
532 return EFI_OUT_OF_RESOURCES
;
535 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
536 NewLoadContext
->Deleted
= FALSE
;
537 NewLoadContext
->LoadOptionSize
= BufferSize
;
538 Ptr
= (UINT8
*) Buffer
;
539 NewLoadContext
->LoadOption
= Ptr
;
540 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
| (ForceReconnect
<< 1);
541 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
542 NewLoadContext
->IsActive
= TRUE
;
543 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
545 Ptr
+= sizeof (UINT32
);
546 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
547 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
549 Ptr
+= sizeof (UINT16
);
553 StrSize (DescriptionData
)
556 NewLoadContext
->Description
= AllocateZeroPool (StrSize (DescriptionData
));
557 ASSERT (NewLoadContext
->Description
!= NULL
);
558 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
560 NewLoadContext
->Description
,
562 StrSize (DescriptionData
)
565 Ptr
+= StrSize (DescriptionData
);
568 CallbackData
->LoadContext
->FilePathList
,
569 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
572 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
573 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
576 NewLoadContext
->FilePathList
,
578 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
581 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
582 NewMenuEntry
->OptionNumber
= Index
;
583 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
585 DriverOptionStrDepository
587 NewMenuEntry
->DisplayStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
589 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
591 DriverOptionHelpStrDepository
593 NewMenuEntry
->HelpStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
595 if (OptionalDataExist
) {
596 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
601 StrSize (OptionalData
)
605 Status
= gRT
->SetVariable (
607 &gEfiGlobalVariableGuid
,
608 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
612 if (!EFI_ERROR (Status
)) {
613 DriverOrderList
= BdsLibGetVariableAndSize (
615 &gEfiGlobalVariableGuid
,
618 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
+ sizeof (UINT16
));
619 ASSERT (NewDriverOrderList
!= NULL
);
620 if (DriverOrderList
!= NULL
) {
621 CopyMem (NewDriverOrderList
, DriverOrderList
, DriverOrderListSize
);
622 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
624 NewDriverOrderList
[DriverOrderListSize
/ sizeof (UINT16
)] = Index
;
626 Status
= gRT
->SetVariable (
628 &gEfiGlobalVariableGuid
,
629 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
630 DriverOrderListSize
+ sizeof (UINT16
),
633 if (DriverOrderList
!= NULL
) {
634 FreePool (DriverOrderList
);
636 DriverOrderList
= NULL
;
637 FreePool (NewDriverOrderList
);
638 if (!EFI_ERROR (Status
)) {
639 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
640 DriverOptionMenu
.MenuNumber
++;
643 // Update "change boot order" page used data, append the new add boot
644 // option at the end.
647 while (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] != 0) {
650 CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);
652 *DescriptionData
= 0x0000;
653 *OptionalData
= 0x0000;
660 This function create a currently loaded Boot Option from
661 the BMM. It then appends this Boot Option to the end of
662 the "BootOrder" list. It also append this Boot Opotion to the end
665 @param CallbackData The BMM context data.
666 @param NvRamMap The file explorer formset internal state.
668 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
669 @retval EFI_SUCCESS If function completes successfully.
673 Var_UpdateBootOption (
674 IN BMM_CALLBACK_DATA
*CallbackData
,
675 IN FILE_EXPLORER_NV_DATA
*NvRamMap
678 UINT16
*BootOrderList
;
679 UINT16
*NewBootOrderList
;
680 UINTN BootOrderListSize
;
681 UINT16 BootString
[10];
686 BM_MENU_ENTRY
*NewMenuEntry
;
687 BM_LOAD_CONTEXT
*NewLoadContext
;
688 BOOLEAN OptionalDataExist
;
691 OptionalDataExist
= FALSE
;
693 Index
= BOpt_GetBootOptionNumber () ;
694 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", Index
);
696 if (NvRamMap
->BootDescriptionData
[0] == 0x0000) {
698 NvRamMap
->BootDescriptionData
,
699 sizeof (NvRamMap
->BootDescriptionData
) / sizeof (NvRamMap
->BootDescriptionData
[0]),
704 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (NvRamMap
->BootDescriptionData
);
705 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
707 if (NvRamMap
->BootOptionalData
[0] != 0x0000) {
708 OptionalDataExist
= TRUE
;
709 BufferSize
+= StrSize (NvRamMap
->BootOptionalData
);
712 Buffer
= AllocateZeroPool (BufferSize
);
713 if (NULL
== Buffer
) {
714 return EFI_OUT_OF_RESOURCES
;
717 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
718 if (NULL
== NewMenuEntry
) {
719 return EFI_OUT_OF_RESOURCES
;
722 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
723 NewLoadContext
->Deleted
= FALSE
;
724 NewLoadContext
->LoadOptionSize
= BufferSize
;
725 Ptr
= (UINT8
*) Buffer
;
726 NewLoadContext
->LoadOption
= Ptr
;
727 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
728 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
729 NewLoadContext
->IsActive
= TRUE
;
730 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
732 Ptr
+= sizeof (UINT32
);
733 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
734 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
735 Ptr
+= sizeof (UINT16
);
739 NvRamMap
->BootDescriptionData
,
740 StrSize (NvRamMap
->BootDescriptionData
)
743 NewLoadContext
->Description
= AllocateZeroPool (StrSize (NvRamMap
->BootDescriptionData
));
744 ASSERT (NewLoadContext
->Description
!= NULL
);
746 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
748 NewLoadContext
->Description
,
750 StrSize (NvRamMap
->BootDescriptionData
)
753 Ptr
+= StrSize (NvRamMap
->BootDescriptionData
);
756 CallbackData
->LoadContext
->FilePathList
,
757 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
760 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
761 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
764 NewLoadContext
->FilePathList
,
766 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
769 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
770 NewMenuEntry
->OptionNumber
= Index
;
771 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
773 BootOptionStrDepository
775 NewMenuEntry
->DisplayStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
777 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
779 BootOptionHelpStrDepository
781 NewMenuEntry
->HelpStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
783 if (OptionalDataExist
) {
784 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
786 CopyMem (Ptr
, NvRamMap
->BootOptionalData
, StrSize (NvRamMap
->BootOptionalData
));
789 Status
= gRT
->SetVariable (
791 &gEfiGlobalVariableGuid
,
792 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
796 if (!EFI_ERROR (Status
)) {
798 BootOrderList
= BdsLibGetVariableAndSize (
800 &gEfiGlobalVariableGuid
,
803 ASSERT (BootOrderList
!= NULL
);
804 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
+ sizeof (UINT16
));
805 ASSERT (NewBootOrderList
!= NULL
);
806 CopyMem (NewBootOrderList
, BootOrderList
, BootOrderListSize
);
807 NewBootOrderList
[BootOrderListSize
/ sizeof (UINT16
)] = Index
;
809 if (BootOrderList
!= NULL
) {
810 FreePool (BootOrderList
);
813 Status
= gRT
->SetVariable (
815 &gEfiGlobalVariableGuid
,
816 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
817 BootOrderListSize
+ sizeof (UINT16
),
820 if (!EFI_ERROR (Status
)) {
822 FreePool (NewBootOrderList
);
823 NewBootOrderList
= NULL
;
824 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
825 BootOptionMenu
.MenuNumber
++;
828 // Update "change driver order" page used data, append the new add driver
829 // option at the end.
832 while (CallbackData
->BmmFakeNvData
.BootOptionOrder
[Index
] != 0) {
835 CallbackData
->BmmFakeNvData
.BootOptionOrder
[Index
] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);
837 NvRamMap
->BootDescriptionData
[0] = 0x0000;
838 NvRamMap
->BootOptionalData
[0] = 0x0000;
845 This function update the "BootNext" EFI Variable. If there is
846 no "BootNext" specified in BMM, this EFI Variable is deleted.
847 It also update the BMM context data specified the "BootNext"
850 @param CallbackData The BMM context data.
852 @retval EFI_SUCCESS The function complete successfully.
853 @return The EFI variable can be saved. See gRT->SetVariable
854 for detail return information.
859 IN BMM_CALLBACK_DATA
*CallbackData
862 BM_MENU_ENTRY
*NewMenuEntry
;
863 BM_LOAD_CONTEXT
*NewLoadContext
;
864 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
868 Status
= EFI_SUCCESS
;
869 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
870 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
871 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
872 ASSERT (NULL
!= NewMenuEntry
);
874 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
875 NewLoadContext
->IsBootNext
= FALSE
;
878 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
879 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
883 NewMenuEntry
= BOpt_GetMenuEntry (
885 CurrentFakeNVMap
->BootNext
887 ASSERT (NewMenuEntry
!= NULL
);
889 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
890 Status
= gRT
->SetVariable (
892 &gEfiGlobalVariableGuid
,
893 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
895 &NewMenuEntry
->OptionNumber
897 NewLoadContext
->IsBootNext
= TRUE
;
898 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
903 This function update the "BootOrder" EFI Variable based on
904 BMM Formset's NV map. It then refresh BootOptionMenu
905 with the new "BootOrder" list.
907 @param CallbackData The BMM context data.
909 @retval EFI_SUCCESS The function complete successfully.
910 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
911 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
915 Var_UpdateBootOrder (
916 IN BMM_CALLBACK_DATA
*CallbackData
922 UINT16
*BootOrderList
;
923 UINTN BootOrderListSize
;
926 BootOrderList
= NULL
;
927 BootOrderListSize
= 0;
930 // First check whether BootOrder is present in current configuration
932 BootOrderList
= BdsLibGetVariableAndSize (
934 &gEfiGlobalVariableGuid
,
937 if (BootOrderList
== NULL
) {
938 return EFI_OUT_OF_RESOURCES
;
941 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.BootOptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.BootOptionOrder
[0])));
943 for (OrderIndex
= 0; (OrderIndex
< BootOptionMenu
.MenuNumber
) && (CallbackData
->BmmFakeNvData
.BootOptionOrder
[OrderIndex
] != 0); OrderIndex
++) {
944 for (Index
= OrderIndex
; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
945 if ((BootOrderList
[Index
] == (UINT16
) (CallbackData
->BmmFakeNvData
.BootOptionOrder
[OrderIndex
] - 1)) && (OrderIndex
!= Index
)) {
946 OptionNumber
= BootOrderList
[Index
];
947 CopyMem (&BootOrderList
[OrderIndex
+ 1], &BootOrderList
[OrderIndex
], (Index
- OrderIndex
) * sizeof (UINT16
));
948 BootOrderList
[OrderIndex
] = OptionNumber
;
953 Status
= gRT
->SetVariable (
955 &gEfiGlobalVariableGuid
,
956 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
961 // Changing the content without increasing its size with current variable implementation shouldn't fail.
963 ASSERT_EFI_ERROR (Status
);
964 FreePool (BootOrderList
);
966 GroupMultipleLegacyBootOption4SameType ();
968 BOpt_FreeMenu (&BootOptionMenu
);
969 BOpt_GetBootOptions (CallbackData
);
976 This function update the "DriverOrder" EFI Variable based on
977 BMM Formset's NV map. It then refresh DriverOptionMenu
978 with the new "DriverOrder" list.
980 @param CallbackData The BMM context data.
982 @retval EFI_SUCCESS The function complete successfully.
983 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
984 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
988 Var_UpdateDriverOrder (
989 IN BMM_CALLBACK_DATA
*CallbackData
994 UINT16
*DriverOrderList
;
995 UINT16
*NewDriverOrderList
;
996 UINTN DriverOrderListSize
;
998 DriverOrderList
= NULL
;
999 DriverOrderListSize
= 0;
1002 // First check whether DriverOrder is present in current configuration
1004 DriverOrderList
= BdsLibGetVariableAndSize (
1006 &gEfiGlobalVariableGuid
,
1007 &DriverOrderListSize
1010 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1012 if (NewDriverOrderList
== NULL
) {
1013 return EFI_OUT_OF_RESOURCES
;
1016 // If exists, delete it to hold new DriverOrder
1018 if (DriverOrderList
!= NULL
) {
1019 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1020 FreePool (DriverOrderList
);
1023 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.DriverOptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[0])));
1024 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1025 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] - 1);
1028 Status
= gRT
->SetVariable (
1030 &gEfiGlobalVariableGuid
,
1031 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1032 DriverOrderListSize
,
1036 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1038 ASSERT_EFI_ERROR (Status
);
1040 BOpt_FreeMenu (&DriverOptionMenu
);
1041 BOpt_GetDriverOptions (CallbackData
);
1046 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable
1047 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1050 @param CallbackData The context data for BMM.
1051 @param FormId The form id.
1053 @return EFI_SUCCESS The function completed successfully.
1054 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.
1055 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1058 Var_UpdateBBSOption (
1059 IN BMM_CALLBACK_DATA
*CallbackData
,
1060 IN EFI_FORM_ID FormId
1065 VOID
*BootOptionVar
;
1066 CHAR16 VarName
[100];
1070 BM_MENU_OPTION
*OptionMenu
;
1074 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1081 UINT16
*EnBootOption
;
1082 UINTN EnBootOptionCount
;
1083 UINT16
*DisBootOption
;
1084 UINTN DisBootOptionCount
;
1090 case FORM_SET_FD_ORDER_ID
:
1091 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1092 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1093 CallbackData
->BbsType
= BBS_FLOPPY
;
1096 case FORM_SET_HD_ORDER_ID
:
1097 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1098 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1099 CallbackData
->BbsType
= BBS_HARDDISK
;
1102 case FORM_SET_CD_ORDER_ID
:
1103 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1104 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1105 CallbackData
->BbsType
= BBS_CDROM
;
1108 case FORM_SET_NET_ORDER_ID
:
1109 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1110 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1111 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1115 ASSERT (FORM_SET_BEV_ORDER_ID
== CallbackData
->BmmPreviousPageId
);
1116 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1117 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1118 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1122 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1123 Status
= EFI_SUCCESS
;
1127 // Update the Variable "LegacyDevOrder"
1129 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1130 VAR_LEGACY_DEV_ORDER
,
1131 &gEfiLegacyDevOrderVariableGuid
,
1135 if (VarData
== NULL
) {
1136 return EFI_NOT_FOUND
;
1139 OriginalPtr
= VarData
;
1140 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1142 while (VarData
< OriginalPtr
+ VarSize
) {
1143 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1147 VarData
+= sizeof (BBS_TYPE
) + DevOrder
->Length
;
1148 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1151 if (VarData
>= OriginalPtr
+ VarSize
) {
1152 FreePool (OriginalPtr
);
1153 return EFI_NOT_FOUND
;
1156 NewOrder
= AllocateZeroPool (DevOrder
->Length
- sizeof (DevOrder
->Length
));
1157 if (NewOrder
== NULL
) {
1158 FreePool (OriginalPtr
);
1159 return EFI_OUT_OF_RESOURCES
;
1162 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1163 if (0xFF == LegacyDev
[Index
]) {
1167 NewOrder
[Index
] = LegacyDev
[Index
];
1170 // Only the enable/disable state of each boot device with same device type can be changed,
1171 // so we can count on the index information in DevOrder.
1172 // DisMap bit array is the only reliable source to check a device's en/dis state,
1173 // so we use DisMap to set en/dis state of each item in NewOrder array
1175 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1176 Tmp
= (UINT16
) (DevOrder
->Data
[Index2
] & 0xFF);
1178 Bit
= 7 - (Tmp
% 8);
1179 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1180 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1188 DevOrder
->Length
- sizeof (DevOrder
->Length
)
1190 FreePool (NewOrder
);
1192 Status
= gRT
->SetVariable (
1193 VAR_LEGACY_DEV_ORDER
,
1194 &gEfiLegacyDevOrderVariableGuid
,
1195 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1202 // Update BootOrder and Boot####.Attribute
1204 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
1206 ASSERT (OptionMenu
->MenuNumber
== DevOrder
->Length
/ sizeof (UINT16
) - 1);
1208 OrderLegacyBootOption4SameType (
1210 DevOrder
->Length
/ sizeof (UINT16
) - 1,
1218 // 2. Deactivate the DisBootOption and activate the EnBootOption
1220 for (Index
= 0; Index
< DisBootOptionCount
; Index
++) {
1221 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", DisBootOption
[Index
]);
1222 BootOptionVar
= BdsLibGetVariableAndSize (
1224 &gEfiGlobalVariableGuid
,
1227 if (BootOptionVar
!= NULL
) {
1228 Attribute
= (UINT32
*) BootOptionVar
;
1229 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1231 Status
= gRT
->SetVariable (
1233 &gEfiGlobalVariableGuid
,
1234 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1239 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1241 ASSERT_EFI_ERROR (Status
);
1243 FreePool (BootOptionVar
);
1247 for (Index
= 0; Index
< EnBootOptionCount
; Index
++) {
1248 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", EnBootOption
[Index
]);
1249 BootOptionVar
= BdsLibGetVariableAndSize (
1251 &gEfiGlobalVariableGuid
,
1254 if (BootOptionVar
!= NULL
) {
1255 Attribute
= (UINT32
*) BootOptionVar
;
1256 *Attribute
|= LOAD_OPTION_ACTIVE
;
1258 Status
= gRT
->SetVariable (
1260 &gEfiGlobalVariableGuid
,
1261 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1266 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1268 ASSERT_EFI_ERROR (Status
);
1270 FreePool (BootOptionVar
);
1274 BOpt_GetBootOptions (CallbackData
);
1276 FreePool (OriginalPtr
);
1277 FreePool (EnBootOption
);
1278 FreePool (DisBootOption
);
1283 Update the Text Mode of Console.
1285 @param CallbackData The context data for BMM.
1287 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1288 @return Other value if the Text Mode of Console is not updated.
1293 IN BMM_CALLBACK_DATA
*CallbackData
1298 CONSOLE_OUT_MODE ModeInfo
;
1300 Mode
= CallbackData
->BmmFakeNvData
.ConsoleOutMode
;
1302 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, Mode
, &(ModeInfo
.Column
), &(ModeInfo
.Row
));
1303 if (!EFI_ERROR(Status
)) {
1304 Status
= PcdSet32S (PcdSetupConOutColumn
, (UINT32
) ModeInfo
.Column
);
1305 if (!EFI_ERROR (Status
)){
1306 Status
= PcdSet32S (PcdSetupConOutRow
, (UINT32
) ModeInfo
.Row
);