2 Variable operation that will be used by bootmaint
4 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BootMaint.h"
18 Delete Boot Option that represent a Deleted state in BootOptionMenu.
19 After deleting this boot option, call Var_ChangeBootOrder to
20 make sure BootOrder is in valid state.
22 @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to
23 BM_LOAD_CONTEXT marked for deletion is deleted.
24 @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.
25 @return Others If failed to update the "BootOrder" variable after deletion.
33 BM_MENU_ENTRY
*NewMenuEntry
;
34 BM_LOAD_CONTEXT
*NewLoadContext
;
35 UINT16 BootString
[10];
42 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
43 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, (Index
- Index2
));
44 if (NULL
== NewMenuEntry
) {
48 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
49 if (!NewLoadContext
->Deleted
) {
57 NewMenuEntry
->OptionNumber
60 EfiLibDeleteVariable (BootString
, &gEfiGlobalVariableGuid
);
63 // If current Load Option is the same as BootNext,
64 // must delete BootNext in order to make sure
65 // there will be no panic on next boot
67 if (NewLoadContext
->IsBootNext
) {
68 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
71 RemoveEntryList (&NewMenuEntry
->Link
);
72 BOpt_DestroyMenuEntry (NewMenuEntry
);
76 BootOptionMenu
.MenuNumber
-= Index2
;
78 Status
= Var_ChangeBootOrder ();
83 After any operation on Boot####, there will be a discrepancy in BootOrder.
84 Since some are missing but in BootOrder, while some are present but are
85 not reflected by BootOrder. Then a function rebuild BootOrder from
86 scratch by content from BootOptionMenu is needed.
91 @retval EFI_SUCCESS The boot order is updated successfully.
92 @return EFI_STATUS other than EFI_SUCCESS if failed to
93 Set the "BootOrder" EFI Variable.
103 BM_MENU_ENTRY
*NewMenuEntry
;
104 UINT16
*BootOrderList
;
105 UINT16
*BootOrderListPtr
;
106 UINTN BootOrderListSize
;
109 BootOrderList
= NULL
;
110 BootOrderListSize
= 0;
113 // First check whether BootOrder is present in current configuration
115 BootOrderList
= BdsLibGetVariableAndSize (
117 &gEfiGlobalVariableGuid
,
122 // If exists, delete it to hold new BootOrder
124 if (BootOrderList
!= NULL
) {
125 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
126 FreePool (BootOrderList
);
127 BootOrderList
= NULL
;
130 // Maybe here should be some check method to ensure that
131 // no new added boot options will be added
132 // but the setup engine now will give only one callback
133 // that is to say, user are granted only one chance to
134 // decide whether the boot option will be added or not
135 // there should be no indictor to show whether this
136 // is a "new" boot option
138 BootOrderListSize
= BootOptionMenu
.MenuNumber
;
140 if (BootOrderListSize
> 0) {
141 BootOrderList
= AllocateZeroPool (BootOrderListSize
* sizeof (UINT16
));
142 ASSERT (BootOrderList
!= NULL
);
143 BootOrderListPtr
= BootOrderList
;
146 // Get all current used Boot#### from BootOptionMenu.
147 // OptionNumber in each BM_LOAD_OPTION is really its
150 for (Index
= 0; Index
< BootOrderListSize
; Index
++) {
151 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
152 *BootOrderList
= (UINT16
) NewMenuEntry
->OptionNumber
;
156 BootOrderList
= BootOrderListPtr
;
159 // After building the BootOrderList, write it back
161 Status
= gRT
->SetVariable (
163 &gEfiGlobalVariableGuid
,
165 BootOrderListSize
* sizeof (UINT16
),
168 if (EFI_ERROR (Status
)) {
176 Delete Load Option that represent a Deleted state in BootOptionMenu.
177 After deleting this Driver option, call Var_ChangeDriverOrder to
178 make sure DriverOrder is in valid state.
180 @retval EFI_SUCCESS Load Option is successfully updated.
181 @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
182 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
187 Var_DelDriverOption (
191 BM_MENU_ENTRY
*NewMenuEntry
;
192 BM_LOAD_CONTEXT
*NewLoadContext
;
193 UINT16 DriverString
[12];
198 Status
= EFI_SUCCESS
;
200 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
201 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, (Index
- Index2
));
202 if (NULL
== NewMenuEntry
) {
203 return EFI_NOT_FOUND
;
206 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
207 if (!NewLoadContext
->Deleted
) {
213 sizeof (DriverString
),
215 NewMenuEntry
->OptionNumber
218 EfiLibDeleteVariable (DriverString
, &gEfiGlobalVariableGuid
);
221 RemoveEntryList (&NewMenuEntry
->Link
);
222 BOpt_DestroyMenuEntry (NewMenuEntry
);
226 DriverOptionMenu
.MenuNumber
-= Index2
;
228 Status
= Var_ChangeDriverOrder ();
233 After any operation on Driver####, there will be a discrepancy in
234 DriverOrder. Since some are missing but in DriverOrder, while some
235 are present but are not reflected by DriverOrder. Then a function
236 rebuild DriverOrder from scratch by content from DriverOptionMenu is
239 @retval EFI_SUCCESS The driver order is updated successfully.
240 @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
244 Var_ChangeDriverOrder (
249 BM_MENU_ENTRY
*NewMenuEntry
;
250 UINT16
*DriverOrderList
;
251 UINT16
*DriverOrderListPtr
;
252 UINTN DriverOrderListSize
;
255 DriverOrderList
= NULL
;
256 DriverOrderListSize
= 0;
259 // First check whether DriverOrder is present in current configuration
261 DriverOrderList
= BdsLibGetVariableAndSize (
263 &gEfiGlobalVariableGuid
,
268 // If exists, delete it to hold new DriverOrder
270 if (DriverOrderList
!= NULL
) {
271 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
272 FreePool (DriverOrderList
);
273 DriverOrderList
= NULL
;
276 DriverOrderListSize
= DriverOptionMenu
.MenuNumber
;
278 if (DriverOrderListSize
> 0) {
279 DriverOrderList
= AllocateZeroPool (DriverOrderListSize
* sizeof (UINT16
));
280 ASSERT (DriverOrderList
!= NULL
);
281 DriverOrderListPtr
= DriverOrderList
;
284 // Get all current used Driver#### from DriverOptionMenu.
285 // OptionNumber in each BM_LOAD_OPTION is really its
288 for (Index
= 0; Index
< DriverOrderListSize
; Index
++) {
289 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index
);
290 *DriverOrderList
= (UINT16
) NewMenuEntry
->OptionNumber
;
294 DriverOrderList
= DriverOrderListPtr
;
297 // After building the DriverOrderList, write it back
299 Status
= gRT
->SetVariable (
301 &gEfiGlobalVariableGuid
,
303 DriverOrderListSize
* sizeof (UINT16
),
306 if (EFI_ERROR (Status
)) {
314 Update the device path of "ConOut", "ConIn" and "ErrOut"
315 based on the new BaudRate, Data Bits, parity and Stop Bits
320 Var_UpdateAllConsoleOption (
324 EFI_DEVICE_PATH_PROTOCOL
*OutDevicePath
;
325 EFI_DEVICE_PATH_PROTOCOL
*InpDevicePath
;
326 EFI_DEVICE_PATH_PROTOCOL
*ErrDevicePath
;
329 OutDevicePath
= EfiLibGetVariable (L
"ConOut", &gEfiGlobalVariableGuid
);
330 InpDevicePath
= EfiLibGetVariable (L
"ConIn", &gEfiGlobalVariableGuid
);
331 ErrDevicePath
= EfiLibGetVariable (L
"ErrOut", &gEfiGlobalVariableGuid
);
332 if (OutDevicePath
!= NULL
) {
333 ChangeVariableDevicePath (OutDevicePath
);
334 Status
= gRT
->SetVariable (
336 &gEfiGlobalVariableGuid
,
338 GetDevicePathSize (OutDevicePath
),
341 ASSERT (!EFI_ERROR (Status
));
344 if (InpDevicePath
!= NULL
) {
345 ChangeVariableDevicePath (InpDevicePath
);
346 Status
= gRT
->SetVariable (
348 &gEfiGlobalVariableGuid
,
350 GetDevicePathSize (InpDevicePath
),
353 ASSERT (!EFI_ERROR (Status
));
356 if (ErrDevicePath
!= NULL
) {
357 ChangeVariableDevicePath (ErrDevicePath
);
358 Status
= gRT
->SetVariable (
360 &gEfiGlobalVariableGuid
,
362 GetDevicePathSize (ErrDevicePath
),
365 ASSERT (!EFI_ERROR (Status
));
370 This function delete and build multi-instance device path for
371 specified type of console device.
373 This function clear the EFI variable defined by ConsoleName and
374 gEfiGlobalVariableGuid. It then build the multi-instance device
375 path by appending the device path of the Console (In/Out/Err) instance
376 in ConsoleMenu. Then it scan all corresponding console device by
377 scanning Terminal (built from device supporting Serial I/O instances)
378 devices in TerminalMenu. At last, it save a EFI variable specifed
379 by ConsoleName and gEfiGlobalVariableGuid.
381 @param ConsoleName The name for the console device type. They are
382 usually "ConIn", "ConOut" and "ErrOut".
383 @param ConsoleMenu The console memu which is a list of console devices.
384 @param UpdatePageId The flag specifying which type of console device
387 @retval EFI_SUCCESS The function complete successfully.
388 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
392 Var_UpdateConsoleOption (
393 IN UINT16
*ConsoleName
,
394 IN BM_MENU_OPTION
*ConsoleMenu
,
395 IN UINT16 UpdatePageId
398 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
399 BM_MENU_ENTRY
*NewMenuEntry
;
400 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
401 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
403 VENDOR_DEVICE_PATH Vendor
;
404 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
407 ConDevicePath
= EfiLibGetVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
408 if (ConDevicePath
!= NULL
) {
409 EfiLibDeleteVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
410 FreePool (ConDevicePath
);
411 ConDevicePath
= NULL
;
415 // First add all console input device from console input menu
417 for (Index
= 0; Index
< ConsoleMenu
->MenuNumber
; Index
++) {
418 NewMenuEntry
= BOpt_GetMenuEntry (ConsoleMenu
, Index
);
420 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
421 if (NewConsoleContext
->IsActive
) {
422 ConDevicePath
= AppendDevicePathInstance (
424 NewConsoleContext
->DevicePath
429 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
430 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
432 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
433 if (((NewTerminalContext
->IsConIn
!= 0) && (UpdatePageId
== FORM_CON_IN_ID
)) ||
434 ((NewTerminalContext
->IsConOut
!= 0) && (UpdatePageId
== FORM_CON_OUT_ID
)) ||
435 ((NewTerminalContext
->IsStdErr
!= 0) && (UpdatePageId
== FORM_CON_ERR_ID
))
437 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
438 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
440 ASSERT (NewTerminalContext
->TerminalType
< (sizeof (TerminalTypeGuid
) / sizeof (TerminalTypeGuid
[0])));
443 &TerminalTypeGuid
[NewTerminalContext
->TerminalType
],
446 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
447 TerminalDevicePath
= AppendDevicePathNode (
448 NewTerminalContext
->DevicePath
,
449 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
451 ASSERT (TerminalDevicePath
!= NULL
);
452 ChangeTerminalDevicePath (&TerminalDevicePath
, TRUE
);
453 ConDevicePath
= AppendDevicePathInstance (
460 if (ConDevicePath
!= NULL
) {
461 Status
= gRT
->SetVariable (
463 &gEfiGlobalVariableGuid
,
465 GetDevicePathSize (ConDevicePath
),
468 if (EFI_ERROR (Status
)) {
478 This function delete and build multi-instance device path ConIn
481 @retval EFI_SUCCESS The function complete successfully.
482 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
485 Var_UpdateConsoleInpOption (
489 return Var_UpdateConsoleOption (L
"ConIn", &ConsoleInpMenu
, FORM_CON_IN_ID
);
493 This function delete and build multi-instance device path ConOut
496 @retval EFI_SUCCESS The function complete successfully.
497 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
500 Var_UpdateConsoleOutOption (
504 return Var_UpdateConsoleOption (L
"ConOut", &ConsoleOutMenu
, FORM_CON_OUT_ID
);
508 This function delete and build multi-instance device path ErrOut
511 @retval EFI_SUCCESS The function complete successfully.
512 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
515 Var_UpdateErrorOutOption (
519 return Var_UpdateConsoleOption (L
"ErrOut", &ConsoleErrMenu
, FORM_CON_ERR_ID
);
523 This function create a currently loaded Drive Option from
524 the BMM. It then appends this Driver Option to the end of
525 the "DriverOrder" list. It append this Driver Opotion to the end
528 @param CallbackData The BMM context data.
529 @param HiiHandle The HII handle associated with the BMM formset.
530 @param DescriptionData The description of this driver option.
531 @param OptionalData The optional load option.
532 @param ForceReconnect If to force reconnect.
534 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
535 @retval EFI_SUCCESS If function completes successfully.
539 Var_UpdateDriverOption (
540 IN BMM_CALLBACK_DATA
*CallbackData
,
541 IN EFI_HII_HANDLE HiiHandle
,
542 IN UINT16
*DescriptionData
,
543 IN UINT16
*OptionalData
,
544 IN UINT8 ForceReconnect
548 UINT16
*DriverOrderList
;
549 UINT16
*NewDriverOrderList
;
550 UINT16 DriverString
[12];
551 UINTN DriverOrderListSize
;
555 BM_MENU_ENTRY
*NewMenuEntry
;
556 BM_LOAD_CONTEXT
*NewLoadContext
;
557 BOOLEAN OptionalDataExist
;
560 OptionalDataExist
= FALSE
;
562 Index
= BOpt_GetDriverOptionNumber ();
565 sizeof (DriverString
),
570 if (*DescriptionData
== 0x0000) {
571 StrCpy (DescriptionData
, DriverString
);
574 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescriptionData
);
575 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
577 if (*OptionalData
!= 0x0000) {
578 OptionalDataExist
= TRUE
;
579 BufferSize
+= StrSize (OptionalData
);
582 Buffer
= AllocateZeroPool (BufferSize
);
583 if (NULL
== Buffer
) {
584 return EFI_OUT_OF_RESOURCES
;
587 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
588 if (NULL
== NewMenuEntry
) {
590 return EFI_OUT_OF_RESOURCES
;
593 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
594 NewLoadContext
->Deleted
= FALSE
;
595 NewLoadContext
->LoadOptionSize
= BufferSize
;
596 Ptr
= (UINT8
*) Buffer
;
597 NewLoadContext
->LoadOption
= Ptr
;
598 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
| (ForceReconnect
<< 1);
599 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
600 NewLoadContext
->IsActive
= TRUE
;
601 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
603 Ptr
+= sizeof (UINT32
);
604 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
605 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
607 Ptr
+= sizeof (UINT16
);
611 StrSize (DescriptionData
)
614 NewLoadContext
->Description
= AllocateZeroPool (StrSize (DescriptionData
));
615 ASSERT (NewLoadContext
->Description
!= NULL
);
616 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
618 NewLoadContext
->Description
,
620 StrSize (DescriptionData
)
623 Ptr
+= StrSize (DescriptionData
);
626 CallbackData
->LoadContext
->FilePathList
,
627 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
630 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
631 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
634 NewLoadContext
->FilePathList
,
636 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
639 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
640 NewMenuEntry
->OptionNumber
= Index
;
641 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
643 DriverOptionStrDepository
645 NewMenuEntry
->DisplayStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
647 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
649 DriverOptionHelpStrDepository
651 NewMenuEntry
->HelpStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
653 if (OptionalDataExist
) {
654 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
659 StrSize (OptionalData
)
663 Status
= gRT
->SetVariable (
665 &gEfiGlobalVariableGuid
,
670 ASSERT_EFI_ERROR (Status
);
671 DriverOrderList
= BdsLibGetVariableAndSize (
673 &gEfiGlobalVariableGuid
,
676 ASSERT (DriverOrderList
!= NULL
);
677 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
+ sizeof (UINT16
));
678 ASSERT (NewDriverOrderList
!= NULL
);
679 CopyMem (NewDriverOrderList
, DriverOrderList
, DriverOrderListSize
);
680 NewDriverOrderList
[DriverOrderListSize
/ sizeof (UINT16
)] = Index
;
681 if (DriverOrderList
!= NULL
) {
682 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
685 Status
= gRT
->SetVariable (
687 &gEfiGlobalVariableGuid
,
689 DriverOrderListSize
+ sizeof (UINT16
),
692 ASSERT_EFI_ERROR (Status
);
693 if (DriverOrderList
!= NULL
) {
694 FreePool (DriverOrderList
);
696 DriverOrderList
= NULL
;
697 FreePool (NewDriverOrderList
);
698 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
699 DriverOptionMenu
.MenuNumber
++;
701 *DescriptionData
= 0x0000;
702 *OptionalData
= 0x0000;
707 This function create a currently loaded Boot Option from
708 the BMM. It then appends this Boot Option to the end of
709 the "BootOrder" list. It also append this Boot Opotion to the end
712 @param CallbackData The BMM context data.
713 @param NvRamMap The file explorer formset internal state.
715 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
716 @retval EFI_SUCCESS If function completes successfully.
720 Var_UpdateBootOption (
721 IN BMM_CALLBACK_DATA
*CallbackData
,
722 IN FILE_EXPLORER_NV_DATA
*NvRamMap
725 UINT16
*BootOrderList
;
726 UINT16
*NewBootOrderList
;
727 UINTN BootOrderListSize
;
728 UINT16 BootString
[10];
733 BM_MENU_ENTRY
*NewMenuEntry
;
734 BM_LOAD_CONTEXT
*NewLoadContext
;
735 BOOLEAN OptionalDataExist
;
738 OptionalDataExist
= FALSE
;
740 Index
= BOpt_GetBootOptionNumber () ;
741 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", Index
);
743 if (NvRamMap
->DescriptionData
[0] == 0x0000) {
744 StrCpy (NvRamMap
->DescriptionData
, BootString
);
747 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (NvRamMap
->DescriptionData
);
748 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
750 if (NvRamMap
->OptionalData
[0] != 0x0000) {
751 OptionalDataExist
= TRUE
;
752 BufferSize
+= StrSize (NvRamMap
->OptionalData
);
755 Buffer
= AllocateZeroPool (BufferSize
);
756 if (NULL
== Buffer
) {
757 return EFI_OUT_OF_RESOURCES
;
760 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
761 if (NULL
== NewMenuEntry
) {
762 return EFI_OUT_OF_RESOURCES
;
765 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
766 NewLoadContext
->Deleted
= FALSE
;
767 NewLoadContext
->LoadOptionSize
= BufferSize
;
768 Ptr
= (UINT8
*) Buffer
;
769 NewLoadContext
->LoadOption
= Ptr
;
770 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
771 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
772 NewLoadContext
->IsActive
= TRUE
;
773 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
775 Ptr
+= sizeof (UINT32
);
776 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
777 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
778 Ptr
+= sizeof (UINT16
);
782 NvRamMap
->DescriptionData
,
783 StrSize (NvRamMap
->DescriptionData
)
786 NewLoadContext
->Description
= AllocateZeroPool (StrSize (NvRamMap
->DescriptionData
));
787 ASSERT (NewLoadContext
->Description
!= NULL
);
789 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
791 NewLoadContext
->Description
,
793 StrSize (NvRamMap
->DescriptionData
)
796 Ptr
+= StrSize (NvRamMap
->DescriptionData
);
799 CallbackData
->LoadContext
->FilePathList
,
800 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
803 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
804 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
807 NewLoadContext
->FilePathList
,
809 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
812 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
813 NewMenuEntry
->OptionNumber
= Index
;
814 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
816 BootOptionStrDepository
818 NewMenuEntry
->DisplayStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
820 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
822 BootOptionHelpStrDepository
824 NewMenuEntry
->HelpStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
826 if (OptionalDataExist
) {
827 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
829 CopyMem (Ptr
, NvRamMap
->OptionalData
, StrSize (NvRamMap
->OptionalData
));
832 Status
= gRT
->SetVariable (
834 &gEfiGlobalVariableGuid
,
839 ASSERT_EFI_ERROR (Status
);
841 BootOrderList
= BdsLibGetVariableAndSize (
843 &gEfiGlobalVariableGuid
,
846 ASSERT (BootOrderList
!= NULL
);
847 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
+ sizeof (UINT16
));
848 ASSERT (NewBootOrderList
!= NULL
);
849 CopyMem (NewBootOrderList
, BootOrderList
, BootOrderListSize
);
850 NewBootOrderList
[BootOrderListSize
/ sizeof (UINT16
)] = Index
;
852 if (BootOrderList
!= NULL
) {
853 FreePool (BootOrderList
);
856 Status
= gRT
->SetVariable (
858 &gEfiGlobalVariableGuid
,
860 BootOrderListSize
+ sizeof (UINT16
),
863 ASSERT_EFI_ERROR (Status
);
865 FreePool (NewBootOrderList
);
866 NewBootOrderList
= NULL
;
867 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
868 BootOptionMenu
.MenuNumber
++;
870 NvRamMap
->DescriptionData
[0] = 0x0000;
871 NvRamMap
->OptionalData
[0] = 0x0000;
876 This function update the "BootNext" EFI Variable. If there is
877 no "BootNext" specified in BMM, this EFI Variable is deleted.
878 It also update the BMM context data specified the "BootNext"
881 @param CallbackData The BMM context data.
883 @retval EFI_SUCCESS The function complete successfully.
884 @return The EFI variable can be saved. See gRT->SetVariable
885 for detail return information.
890 IN BMM_CALLBACK_DATA
*CallbackData
893 BM_MENU_ENTRY
*NewMenuEntry
;
894 BM_LOAD_CONTEXT
*NewLoadContext
;
895 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
899 Status
= EFI_SUCCESS
;
900 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
901 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
902 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
903 ASSERT (NULL
!= NewMenuEntry
);
905 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
906 NewLoadContext
->IsBootNext
= FALSE
;
909 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
910 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
914 NewMenuEntry
= BOpt_GetMenuEntry (
916 CurrentFakeNVMap
->BootNext
918 ASSERT (NewMenuEntry
!= NULL
);
920 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
921 Status
= gRT
->SetVariable (
923 &gEfiGlobalVariableGuid
,
926 &NewMenuEntry
->OptionNumber
928 NewLoadContext
->IsBootNext
= TRUE
;
929 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
934 This function update the "BootOrder" EFI Variable based on
935 BMM Formset's NV map. It then refresh BootOptionMenu
936 with the new "BootOrder" list.
938 @param CallbackData The BMM context data.
940 @retval EFI_SUCCESS The function complete successfully.
941 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
942 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
946 Var_UpdateBootOrder (
947 IN BMM_CALLBACK_DATA
*CallbackData
953 UINT16
*BootOrderList
;
954 UINTN BootOrderListSize
;
957 BootOrderList
= NULL
;
958 BootOrderListSize
= 0;
961 // First check whether BootOrder is present in current configuration
963 BootOrderList
= BdsLibGetVariableAndSize (
965 &gEfiGlobalVariableGuid
,
968 if (BootOrderList
== NULL
) {
969 return EFI_OUT_OF_RESOURCES
;
972 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
974 for (OrderIndex
= 0; (OrderIndex
< BootOptionMenu
.MenuNumber
) && (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] != 0); OrderIndex
++) {
975 for (Index
= OrderIndex
; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
976 if ((BootOrderList
[Index
] == (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] - 1)) && (OrderIndex
!= Index
)) {
977 OptionNumber
= BootOrderList
[Index
];
978 CopyMem (&BootOrderList
[OrderIndex
+ 1], &BootOrderList
[OrderIndex
], (Index
- OrderIndex
) * sizeof (UINT16
));
979 BootOrderList
[OrderIndex
] = OptionNumber
;
984 GroupMultipleLegacyBootOption4SameType (
986 BootOrderListSize
/ sizeof (UINT16
)
989 Status
= gRT
->SetVariable (
991 &gEfiGlobalVariableGuid
,
996 FreePool (BootOrderList
);
998 BOpt_FreeMenu (&BootOptionMenu
);
999 BOpt_GetBootOptions (CallbackData
);
1006 This function update the "DriverOrder" EFI Variable based on
1007 BMM Formset's NV map. It then refresh DriverOptionMenu
1008 with the new "DriverOrder" list.
1010 @param CallbackData The BMM context data.
1012 @retval EFI_SUCCESS The function complete successfully.
1013 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
1014 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
1018 Var_UpdateDriverOrder (
1019 IN BMM_CALLBACK_DATA
*CallbackData
1024 UINT16
*DriverOrderList
;
1025 UINT16
*NewDriverOrderList
;
1026 UINTN DriverOrderListSize
;
1028 DriverOrderList
= NULL
;
1029 DriverOrderListSize
= 0;
1032 // First check whether DriverOrder is present in current configuration
1034 DriverOrderList
= BdsLibGetVariableAndSize (
1036 &gEfiGlobalVariableGuid
,
1037 &DriverOrderListSize
1040 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1042 if (NewDriverOrderList
== NULL
) {
1043 return EFI_OUT_OF_RESOURCES
;
1046 // If exists, delete it to hold new DriverOrder
1048 if (DriverOrderList
!= NULL
) {
1049 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1050 FreePool (DriverOrderList
);
1053 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
1054 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1055 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[Index
] - 1);
1058 Status
= gRT
->SetVariable (
1060 &gEfiGlobalVariableGuid
,
1062 DriverOrderListSize
,
1065 if (EFI_ERROR (Status
)) {
1069 BOpt_FreeMenu (&DriverOptionMenu
);
1070 BOpt_GetDriverOptions (CallbackData
);
1075 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable
1076 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1079 @param CallbackData The context data for BMM.
1081 @return EFI_SUCCESS The function completed successfully.
1082 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.
1083 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1086 Var_UpdateBBSOption (
1087 IN BMM_CALLBACK_DATA
*CallbackData
1092 VOID
*BootOptionVar
;
1093 CHAR16 VarName
[100];
1097 BM_MENU_OPTION
*OptionMenu
;
1101 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1108 UINT16
*EnBootOption
;
1109 UINTN EnBootOptionCount
;
1110 UINT16
*DisBootOption
;
1111 UINTN DisBootOptionCount
;
1117 switch (CallbackData
->BmmPreviousPageId
) {
1118 case FORM_SET_FD_ORDER_ID
:
1119 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1120 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1121 CallbackData
->BbsType
= BBS_FLOPPY
;
1124 case FORM_SET_HD_ORDER_ID
:
1125 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1126 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1127 CallbackData
->BbsType
= BBS_HARDDISK
;
1130 case FORM_SET_CD_ORDER_ID
:
1131 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1132 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1133 CallbackData
->BbsType
= BBS_CDROM
;
1136 case FORM_SET_NET_ORDER_ID
:
1137 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1138 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1139 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1143 ASSERT (FORM_SET_BEV_ORDER_ID
== CallbackData
->BmmPreviousPageId
);
1144 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1145 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1146 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1150 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1151 Status
= EFI_SUCCESS
;
1155 // Update the Variable "LegacyDevOrder"
1157 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1158 VAR_LEGACY_DEV_ORDER
,
1159 &gEfiLegacyDevOrderVariableGuid
,
1163 if (VarData
== NULL
) {
1164 return EFI_NOT_FOUND
;
1167 OriginalPtr
= VarData
;
1168 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1170 while (VarData
< OriginalPtr
+ VarSize
) {
1171 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1175 VarData
+= sizeof (BBS_TYPE
) + DevOrder
->Length
;
1176 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1179 if (VarData
>= OriginalPtr
+ VarSize
) {
1180 FreePool (OriginalPtr
);
1181 return EFI_NOT_FOUND
;
1184 NewOrder
= AllocateZeroPool (DevOrder
->Length
- sizeof (DevOrder
->Length
));
1185 if (NewOrder
== NULL
) {
1186 FreePool (OriginalPtr
);
1187 return EFI_OUT_OF_RESOURCES
;
1190 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1191 if (0xFF == LegacyDev
[Index
]) {
1195 NewOrder
[Index
] = LegacyDev
[Index
];
1198 // Only the enable/disable state of each boot device with same device type can be changed,
1199 // so we can count on the index information in DevOrder.
1200 // DisMap bit array is the only reliable source to check a device's en/dis state,
1201 // so we use DisMap to set en/dis state of each item in NewOrder array
1203 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1204 Tmp
= (UINT16
) (DevOrder
->Data
[Index2
] & 0xFF);
1206 Bit
= 7 - (Tmp
% 8);
1207 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1208 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1216 DevOrder
->Length
- sizeof (DevOrder
->Length
)
1218 FreePool (NewOrder
);
1220 Status
= gRT
->SetVariable (
1221 VAR_LEGACY_DEV_ORDER
,
1222 &gEfiLegacyDevOrderVariableGuid
,
1230 // Update BootOrder and Boot####.Attribute
1232 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
1234 ASSERT (OptionMenu
->MenuNumber
== DevOrder
->Length
/ sizeof (UINT16
) - 1);
1235 BootOrder
= BdsLibGetVariableAndSize (
1237 &gEfiGlobalVariableGuid
,
1240 ASSERT (BootOrder
!= NULL
);
1242 DisBootOption
= AllocatePool (VarSize
);
1243 ASSERT (DisBootOption
!= NULL
);
1244 EnBootOption
= AllocatePool (VarSize
);
1245 ASSERT (EnBootOption
!= NULL
);
1247 OrderLegacyBootOption4SameType (
1249 VarSize
/ sizeof (UINT16
),
1251 DevOrder
->Length
/ sizeof (UINT16
) - 1,
1258 Status
= gRT
->SetVariable (
1260 &gEfiGlobalVariableGuid
,
1265 ASSERT_EFI_ERROR (Status
);
1267 FreePool (BootOrder
);
1270 // 2. Deactivate the DisBootOption and activate the EnBootOption
1272 for (Index
= 0; Index
< DisBootOptionCount
; Index
++) {
1273 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", DisBootOption
[Index
]);
1274 BootOptionVar
= BdsLibGetVariableAndSize (
1276 &gEfiGlobalVariableGuid
,
1279 if (BootOptionVar
!= NULL
) {
1280 Attribute
= (UINT32
*) BootOptionVar
;
1281 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1283 Status
= gRT
->SetVariable (
1285 &gEfiGlobalVariableGuid
,
1291 FreePool (BootOptionVar
);
1295 for (Index
= 0; Index
< EnBootOptionCount
; Index
++) {
1296 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", EnBootOption
[Index
]);
1297 BootOptionVar
= BdsLibGetVariableAndSize (
1299 &gEfiGlobalVariableGuid
,
1302 if (BootOptionVar
!= NULL
) {
1303 Attribute
= (UINT32
*) BootOptionVar
;
1304 *Attribute
|= LOAD_OPTION_ACTIVE
;
1306 Status
= gRT
->SetVariable (
1308 &gEfiGlobalVariableGuid
,
1314 FreePool (BootOptionVar
);
1318 BOpt_GetBootOptions (CallbackData
);
1320 FreePool (OriginalPtr
);
1321 FreePool (EnBootOption
);
1322 FreePool (DisBootOption
);
1327 Update the Text Mode of Console.
1329 @param CallbackData The context data for BMM.
1331 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1332 @return Other value if the Text Mode of Console is not updated.
1337 IN BMM_CALLBACK_DATA
*CallbackData
1342 CONSOLE_OUT_MODE ModeInfo
;
1344 Mode
= CallbackData
->BmmFakeNvData
.ConsoleOutMode
;
1346 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, Mode
, &(ModeInfo
.Column
), &(ModeInfo
.Row
));
1347 if (!EFI_ERROR(Status
)) {
1348 PcdSet32 (PcdConOutColumn
, (UINT32
) ModeInfo
.Column
);
1349 PcdSet32 (PcdConOutRow
, (UINT32
) ModeInfo
.Row
);