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 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
+ sizeof (UINT16
));
677 ASSERT (NewDriverOrderList
!= NULL
);
678 if (DriverOrderList
!= NULL
) {
679 CopyMem (NewDriverOrderList
, DriverOrderList
, DriverOrderListSize
);
680 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
682 NewDriverOrderList
[DriverOrderListSize
/ sizeof (UINT16
)] = Index
;
684 Status
= gRT
->SetVariable (
686 &gEfiGlobalVariableGuid
,
688 DriverOrderListSize
+ sizeof (UINT16
),
691 ASSERT_EFI_ERROR (Status
);
692 if (DriverOrderList
!= NULL
) {
693 FreePool (DriverOrderList
);
695 DriverOrderList
= NULL
;
696 FreePool (NewDriverOrderList
);
697 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
698 DriverOptionMenu
.MenuNumber
++;
700 *DescriptionData
= 0x0000;
701 *OptionalData
= 0x0000;
706 This function create a currently loaded Boot Option from
707 the BMM. It then appends this Boot Option to the end of
708 the "BootOrder" list. It also append this Boot Opotion to the end
711 @param CallbackData The BMM context data.
712 @param NvRamMap The file explorer formset internal state.
714 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
715 @retval EFI_SUCCESS If function completes successfully.
719 Var_UpdateBootOption (
720 IN BMM_CALLBACK_DATA
*CallbackData
,
721 IN FILE_EXPLORER_NV_DATA
*NvRamMap
724 UINT16
*BootOrderList
;
725 UINT16
*NewBootOrderList
;
726 UINTN BootOrderListSize
;
727 UINT16 BootString
[10];
732 BM_MENU_ENTRY
*NewMenuEntry
;
733 BM_LOAD_CONTEXT
*NewLoadContext
;
734 BOOLEAN OptionalDataExist
;
737 OptionalDataExist
= FALSE
;
739 Index
= BOpt_GetBootOptionNumber () ;
740 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", Index
);
742 if (NvRamMap
->DescriptionData
[0] == 0x0000) {
743 StrCpy (NvRamMap
->DescriptionData
, BootString
);
746 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (NvRamMap
->DescriptionData
);
747 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
749 if (NvRamMap
->OptionalData
[0] != 0x0000) {
750 OptionalDataExist
= TRUE
;
751 BufferSize
+= StrSize (NvRamMap
->OptionalData
);
754 Buffer
= AllocateZeroPool (BufferSize
);
755 if (NULL
== Buffer
) {
756 return EFI_OUT_OF_RESOURCES
;
759 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
760 if (NULL
== NewMenuEntry
) {
761 return EFI_OUT_OF_RESOURCES
;
764 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
765 NewLoadContext
->Deleted
= FALSE
;
766 NewLoadContext
->LoadOptionSize
= BufferSize
;
767 Ptr
= (UINT8
*) Buffer
;
768 NewLoadContext
->LoadOption
= Ptr
;
769 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
770 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
771 NewLoadContext
->IsActive
= TRUE
;
772 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
774 Ptr
+= sizeof (UINT32
);
775 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
776 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
777 Ptr
+= sizeof (UINT16
);
781 NvRamMap
->DescriptionData
,
782 StrSize (NvRamMap
->DescriptionData
)
785 NewLoadContext
->Description
= AllocateZeroPool (StrSize (NvRamMap
->DescriptionData
));
786 ASSERT (NewLoadContext
->Description
!= NULL
);
788 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
790 NewLoadContext
->Description
,
792 StrSize (NvRamMap
->DescriptionData
)
795 Ptr
+= StrSize (NvRamMap
->DescriptionData
);
798 CallbackData
->LoadContext
->FilePathList
,
799 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
802 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
803 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
806 NewLoadContext
->FilePathList
,
808 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
811 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
812 NewMenuEntry
->OptionNumber
= Index
;
813 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
815 BootOptionStrDepository
817 NewMenuEntry
->DisplayStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
819 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
821 BootOptionHelpStrDepository
823 NewMenuEntry
->HelpStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
825 if (OptionalDataExist
) {
826 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
828 CopyMem (Ptr
, NvRamMap
->OptionalData
, StrSize (NvRamMap
->OptionalData
));
831 Status
= gRT
->SetVariable (
833 &gEfiGlobalVariableGuid
,
838 ASSERT_EFI_ERROR (Status
);
840 BootOrderList
= BdsLibGetVariableAndSize (
842 &gEfiGlobalVariableGuid
,
845 ASSERT (BootOrderList
!= NULL
);
846 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
+ sizeof (UINT16
));
847 ASSERT (NewBootOrderList
!= NULL
);
848 CopyMem (NewBootOrderList
, BootOrderList
, BootOrderListSize
);
849 NewBootOrderList
[BootOrderListSize
/ sizeof (UINT16
)] = Index
;
851 if (BootOrderList
!= NULL
) {
852 FreePool (BootOrderList
);
855 Status
= gRT
->SetVariable (
857 &gEfiGlobalVariableGuid
,
859 BootOrderListSize
+ sizeof (UINT16
),
862 ASSERT_EFI_ERROR (Status
);
864 FreePool (NewBootOrderList
);
865 NewBootOrderList
= NULL
;
866 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
867 BootOptionMenu
.MenuNumber
++;
869 NvRamMap
->DescriptionData
[0] = 0x0000;
870 NvRamMap
->OptionalData
[0] = 0x0000;
875 This function update the "BootNext" EFI Variable. If there is
876 no "BootNext" specified in BMM, this EFI Variable is deleted.
877 It also update the BMM context data specified the "BootNext"
880 @param CallbackData The BMM context data.
882 @retval EFI_SUCCESS The function complete successfully.
883 @return The EFI variable can be saved. See gRT->SetVariable
884 for detail return information.
889 IN BMM_CALLBACK_DATA
*CallbackData
892 BM_MENU_ENTRY
*NewMenuEntry
;
893 BM_LOAD_CONTEXT
*NewLoadContext
;
894 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
898 Status
= EFI_SUCCESS
;
899 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
900 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
901 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
902 ASSERT (NULL
!= NewMenuEntry
);
904 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
905 NewLoadContext
->IsBootNext
= FALSE
;
908 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
909 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
913 NewMenuEntry
= BOpt_GetMenuEntry (
915 CurrentFakeNVMap
->BootNext
917 ASSERT (NewMenuEntry
!= NULL
);
919 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
920 Status
= gRT
->SetVariable (
922 &gEfiGlobalVariableGuid
,
925 &NewMenuEntry
->OptionNumber
927 NewLoadContext
->IsBootNext
= TRUE
;
928 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
933 This function update the "BootOrder" EFI Variable based on
934 BMM Formset's NV map. It then refresh BootOptionMenu
935 with the new "BootOrder" list.
937 @param CallbackData The BMM context data.
939 @retval EFI_SUCCESS The function complete successfully.
940 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
941 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
945 Var_UpdateBootOrder (
946 IN BMM_CALLBACK_DATA
*CallbackData
952 UINT16
*BootOrderList
;
953 UINTN BootOrderListSize
;
956 BootOrderList
= NULL
;
957 BootOrderListSize
= 0;
960 // First check whether BootOrder is present in current configuration
962 BootOrderList
= BdsLibGetVariableAndSize (
964 &gEfiGlobalVariableGuid
,
967 if (BootOrderList
== NULL
) {
968 return EFI_OUT_OF_RESOURCES
;
971 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
973 for (OrderIndex
= 0; (OrderIndex
< BootOptionMenu
.MenuNumber
) && (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] != 0); OrderIndex
++) {
974 for (Index
= OrderIndex
; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
975 if ((BootOrderList
[Index
] == (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] - 1)) && (OrderIndex
!= Index
)) {
976 OptionNumber
= BootOrderList
[Index
];
977 CopyMem (&BootOrderList
[OrderIndex
+ 1], &BootOrderList
[OrderIndex
], (Index
- OrderIndex
) * sizeof (UINT16
));
978 BootOrderList
[OrderIndex
] = OptionNumber
;
983 GroupMultipleLegacyBootOption4SameType (
985 BootOrderListSize
/ sizeof (UINT16
)
988 Status
= gRT
->SetVariable (
990 &gEfiGlobalVariableGuid
,
995 FreePool (BootOrderList
);
997 BOpt_FreeMenu (&BootOptionMenu
);
998 BOpt_GetBootOptions (CallbackData
);
1005 This function update the "DriverOrder" EFI Variable based on
1006 BMM Formset's NV map. It then refresh DriverOptionMenu
1007 with the new "DriverOrder" list.
1009 @param CallbackData The BMM context data.
1011 @retval EFI_SUCCESS The function complete successfully.
1012 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
1013 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
1017 Var_UpdateDriverOrder (
1018 IN BMM_CALLBACK_DATA
*CallbackData
1023 UINT16
*DriverOrderList
;
1024 UINT16
*NewDriverOrderList
;
1025 UINTN DriverOrderListSize
;
1027 DriverOrderList
= NULL
;
1028 DriverOrderListSize
= 0;
1031 // First check whether DriverOrder is present in current configuration
1033 DriverOrderList
= BdsLibGetVariableAndSize (
1035 &gEfiGlobalVariableGuid
,
1036 &DriverOrderListSize
1039 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1041 if (NewDriverOrderList
== NULL
) {
1042 return EFI_OUT_OF_RESOURCES
;
1045 // If exists, delete it to hold new DriverOrder
1047 if (DriverOrderList
!= NULL
) {
1048 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1049 FreePool (DriverOrderList
);
1052 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
1053 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1054 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[Index
] - 1);
1057 Status
= gRT
->SetVariable (
1059 &gEfiGlobalVariableGuid
,
1061 DriverOrderListSize
,
1064 if (EFI_ERROR (Status
)) {
1068 BOpt_FreeMenu (&DriverOptionMenu
);
1069 BOpt_GetDriverOptions (CallbackData
);
1074 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable
1075 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1078 @param CallbackData The context data for BMM.
1080 @return EFI_SUCCESS The function completed successfully.
1081 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.
1082 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1085 Var_UpdateBBSOption (
1086 IN BMM_CALLBACK_DATA
*CallbackData
1091 VOID
*BootOptionVar
;
1092 CHAR16 VarName
[100];
1096 BM_MENU_OPTION
*OptionMenu
;
1100 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1107 UINT16
*EnBootOption
;
1108 UINTN EnBootOptionCount
;
1109 UINT16
*DisBootOption
;
1110 UINTN DisBootOptionCount
;
1116 switch (CallbackData
->BmmPreviousPageId
) {
1117 case FORM_SET_FD_ORDER_ID
:
1118 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1119 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1120 CallbackData
->BbsType
= BBS_FLOPPY
;
1123 case FORM_SET_HD_ORDER_ID
:
1124 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1125 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1126 CallbackData
->BbsType
= BBS_HARDDISK
;
1129 case FORM_SET_CD_ORDER_ID
:
1130 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1131 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1132 CallbackData
->BbsType
= BBS_CDROM
;
1135 case FORM_SET_NET_ORDER_ID
:
1136 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1137 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1138 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1142 ASSERT (FORM_SET_BEV_ORDER_ID
== CallbackData
->BmmPreviousPageId
);
1143 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1144 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1145 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1149 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1150 Status
= EFI_SUCCESS
;
1154 // Update the Variable "LegacyDevOrder"
1156 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1157 VAR_LEGACY_DEV_ORDER
,
1158 &gEfiLegacyDevOrderVariableGuid
,
1162 if (VarData
== NULL
) {
1163 return EFI_NOT_FOUND
;
1166 OriginalPtr
= VarData
;
1167 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1169 while (VarData
< OriginalPtr
+ VarSize
) {
1170 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1174 VarData
+= sizeof (BBS_TYPE
) + DevOrder
->Length
;
1175 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1178 if (VarData
>= OriginalPtr
+ VarSize
) {
1179 FreePool (OriginalPtr
);
1180 return EFI_NOT_FOUND
;
1183 NewOrder
= AllocateZeroPool (DevOrder
->Length
- sizeof (DevOrder
->Length
));
1184 if (NewOrder
== NULL
) {
1185 FreePool (OriginalPtr
);
1186 return EFI_OUT_OF_RESOURCES
;
1189 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1190 if (0xFF == LegacyDev
[Index
]) {
1194 NewOrder
[Index
] = LegacyDev
[Index
];
1197 // Only the enable/disable state of each boot device with same device type can be changed,
1198 // so we can count on the index information in DevOrder.
1199 // DisMap bit array is the only reliable source to check a device's en/dis state,
1200 // so we use DisMap to set en/dis state of each item in NewOrder array
1202 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1203 Tmp
= (UINT16
) (DevOrder
->Data
[Index2
] & 0xFF);
1205 Bit
= 7 - (Tmp
% 8);
1206 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1207 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1215 DevOrder
->Length
- sizeof (DevOrder
->Length
)
1217 FreePool (NewOrder
);
1219 Status
= gRT
->SetVariable (
1220 VAR_LEGACY_DEV_ORDER
,
1221 &gEfiLegacyDevOrderVariableGuid
,
1229 // Update BootOrder and Boot####.Attribute
1231 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
1233 ASSERT (OptionMenu
->MenuNumber
== DevOrder
->Length
/ sizeof (UINT16
) - 1);
1234 BootOrder
= BdsLibGetVariableAndSize (
1236 &gEfiGlobalVariableGuid
,
1239 ASSERT (BootOrder
!= NULL
);
1241 DisBootOption
= AllocatePool (VarSize
);
1242 ASSERT (DisBootOption
!= NULL
);
1243 EnBootOption
= AllocatePool (VarSize
);
1244 ASSERT (EnBootOption
!= NULL
);
1246 OrderLegacyBootOption4SameType (
1248 VarSize
/ sizeof (UINT16
),
1250 DevOrder
->Length
/ sizeof (UINT16
) - 1,
1257 Status
= gRT
->SetVariable (
1259 &gEfiGlobalVariableGuid
,
1264 ASSERT_EFI_ERROR (Status
);
1266 FreePool (BootOrder
);
1269 // 2. Deactivate the DisBootOption and activate the EnBootOption
1271 for (Index
= 0; Index
< DisBootOptionCount
; Index
++) {
1272 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", DisBootOption
[Index
]);
1273 BootOptionVar
= BdsLibGetVariableAndSize (
1275 &gEfiGlobalVariableGuid
,
1278 if (BootOptionVar
!= NULL
) {
1279 Attribute
= (UINT32
*) BootOptionVar
;
1280 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1282 Status
= gRT
->SetVariable (
1284 &gEfiGlobalVariableGuid
,
1290 FreePool (BootOptionVar
);
1294 for (Index
= 0; Index
< EnBootOptionCount
; Index
++) {
1295 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", EnBootOption
[Index
]);
1296 BootOptionVar
= BdsLibGetVariableAndSize (
1298 &gEfiGlobalVariableGuid
,
1301 if (BootOptionVar
!= NULL
) {
1302 Attribute
= (UINT32
*) BootOptionVar
;
1303 *Attribute
|= LOAD_OPTION_ACTIVE
;
1305 Status
= gRT
->SetVariable (
1307 &gEfiGlobalVariableGuid
,
1313 FreePool (BootOptionVar
);
1317 BOpt_GetBootOptions (CallbackData
);
1319 FreePool (OriginalPtr
);
1320 FreePool (EnBootOption
);
1321 FreePool (DisBootOption
);
1326 Update the Text Mode of Console.
1328 @param CallbackData The context data for BMM.
1330 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1331 @return Other value if the Text Mode of Console is not updated.
1336 IN BMM_CALLBACK_DATA
*CallbackData
1341 CONSOLE_OUT_MODE ModeInfo
;
1343 Mode
= CallbackData
->BmmFakeNvData
.ConsoleOutMode
;
1345 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, Mode
, &(ModeInfo
.Column
), &(ModeInfo
.Row
));
1346 if (!EFI_ERROR(Status
)) {
1347 PcdSet32 (PcdSetupConOutColumn
, (UINT32
) ModeInfo
.Column
);
1348 PcdSet32 (PcdSetupConOutRow
, (UINT32
) ModeInfo
.Row
);