2 Variable operation that will be used by bootmaint
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. 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 EFI_STATUS other than EFI_SUCCESS if failed to
241 Set the "DriverOrder" EFI Variable.
245 Var_ChangeDriverOrder (
250 BM_MENU_ENTRY
*NewMenuEntry
;
251 UINT16
*DriverOrderList
;
252 UINT16
*DriverOrderListPtr
;
253 UINTN DriverOrderListSize
;
256 DriverOrderList
= NULL
;
257 DriverOrderListSize
= 0;
260 // First check whether DriverOrder is present in current configuration
262 DriverOrderList
= BdsLibGetVariableAndSize (
264 &gEfiGlobalVariableGuid
,
269 // If exists, delete it to hold new DriverOrder
271 if (DriverOrderList
!= NULL
) {
272 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
273 FreePool (DriverOrderList
);
274 DriverOrderList
= NULL
;
277 DriverOrderListSize
= DriverOptionMenu
.MenuNumber
;
279 if (DriverOrderListSize
> 0) {
280 DriverOrderList
= AllocateZeroPool (DriverOrderListSize
* sizeof (UINT16
));
281 ASSERT (DriverOrderList
!= NULL
);
282 DriverOrderListPtr
= DriverOrderList
;
285 // Get all current used Driver#### from DriverOptionMenu.
286 // OptionNumber in each BM_LOAD_OPTION is really its
289 for (Index
= 0; Index
< DriverOrderListSize
; Index
++) {
290 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index
);
291 *DriverOrderList
= (UINT16
) NewMenuEntry
->OptionNumber
;
295 DriverOrderList
= DriverOrderListPtr
;
298 // After building the DriverOrderList, write it back
300 Status
= gRT
->SetVariable (
302 &gEfiGlobalVariableGuid
,
304 DriverOrderListSize
* sizeof (UINT16
),
307 if (EFI_ERROR (Status
)) {
315 Update the device path of "ConOut", "ConIn" and "ErrOut"
316 based on the new BaudRate, Data Bits, parity and Stop Bits
321 Var_UpdateAllConsoleOption (
325 EFI_DEVICE_PATH_PROTOCOL
*OutDevicePath
;
326 EFI_DEVICE_PATH_PROTOCOL
*InpDevicePath
;
327 EFI_DEVICE_PATH_PROTOCOL
*ErrDevicePath
;
330 OutDevicePath
= EfiLibGetVariable (L
"ConOut", &gEfiGlobalVariableGuid
);
331 InpDevicePath
= EfiLibGetVariable (L
"ConIn", &gEfiGlobalVariableGuid
);
332 ErrDevicePath
= EfiLibGetVariable (L
"ErrOut", &gEfiGlobalVariableGuid
);
333 if (OutDevicePath
!= NULL
) {
334 ChangeVariableDevicePath (OutDevicePath
);
335 Status
= gRT
->SetVariable (
337 &gEfiGlobalVariableGuid
,
339 GetDevicePathSize (OutDevicePath
),
342 ASSERT (!EFI_ERROR (Status
));
345 if (InpDevicePath
!= NULL
) {
346 ChangeVariableDevicePath (InpDevicePath
);
347 Status
= gRT
->SetVariable (
349 &gEfiGlobalVariableGuid
,
351 GetDevicePathSize (InpDevicePath
),
354 ASSERT (!EFI_ERROR (Status
));
357 if (ErrDevicePath
!= NULL
) {
358 ChangeVariableDevicePath (ErrDevicePath
);
359 Status
= gRT
->SetVariable (
361 &gEfiGlobalVariableGuid
,
363 GetDevicePathSize (ErrDevicePath
),
366 ASSERT (!EFI_ERROR (Status
));
371 This function delete and build multi-instance device path for
372 specified type of console device.
374 This function clear the EFI variable defined by ConsoleName and
375 gEfiGlobalVariableGuid. It then build the multi-instance device
376 path by appending the device path of the Console (In/Out/Err) instance
377 in ConsoleMenu. Then it scan all corresponding console device by
378 scanning Terminal (built from device supporting Serial I/O instances)
379 devices in TerminalMenu. At last, it save a EFI variable specifed
380 by ConsoleName and gEfiGlobalVariableGuid.
382 @param ConsoleName The name for the console device type. They are
383 usually "ConIn", "ConOut" and "ErrOut".
384 @param ConsoleMenu The console memu which is a list of console devices.
385 @param UpdatePageId The flag specifying which type of console device
388 @retval EFI_SUCCESS The function complete successfully.
389 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
393 Var_UpdateConsoleOption (
394 IN UINT16
*ConsoleName
,
395 IN BM_MENU_OPTION
*ConsoleMenu
,
396 IN UINT16 UpdatePageId
399 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
400 BM_MENU_ENTRY
*NewMenuEntry
;
401 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
402 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
404 VENDOR_DEVICE_PATH Vendor
;
405 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
408 ConDevicePath
= EfiLibGetVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
409 if (ConDevicePath
!= NULL
) {
410 EfiLibDeleteVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
411 FreePool (ConDevicePath
);
412 ConDevicePath
= NULL
;
416 // First add all console input device from console input menu
418 for (Index
= 0; Index
< ConsoleMenu
->MenuNumber
; Index
++) {
419 NewMenuEntry
= BOpt_GetMenuEntry (ConsoleMenu
, Index
);
421 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
422 if (NewConsoleContext
->IsActive
) {
423 ConDevicePath
= AppendDevicePathInstance (
425 NewConsoleContext
->DevicePath
430 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
431 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
433 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
434 if (((NewTerminalContext
->IsConIn
!= 0) && (UpdatePageId
== FORM_CON_IN_ID
)) ||
435 ((NewTerminalContext
->IsConOut
!= 0) && (UpdatePageId
== FORM_CON_OUT_ID
)) ||
436 ((NewTerminalContext
->IsStdErr
!= 0) && (UpdatePageId
== FORM_CON_ERR_ID
))
438 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
439 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
441 ASSERT (NewTerminalContext
->TerminalType
< (sizeof (TerminalTypeGuid
) / sizeof (TerminalTypeGuid
[0])));
444 &TerminalTypeGuid
[NewTerminalContext
->TerminalType
],
447 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
448 TerminalDevicePath
= AppendDevicePathNode (
449 NewTerminalContext
->DevicePath
,
450 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
452 ASSERT (TerminalDevicePath
!= NULL
);
453 ChangeTerminalDevicePath (TerminalDevicePath
, TRUE
);
454 ConDevicePath
= AppendDevicePathInstance (
461 if (ConDevicePath
!= NULL
) {
462 Status
= gRT
->SetVariable (
464 &gEfiGlobalVariableGuid
,
466 GetDevicePathSize (ConDevicePath
),
469 if (EFI_ERROR (Status
)) {
479 This function delete and build multi-instance device path ConIn
482 @retval EFI_SUCCESS The function complete successfully.
483 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
486 Var_UpdateConsoleInpOption (
490 return Var_UpdateConsoleOption (L
"ConIn", &ConsoleInpMenu
, FORM_CON_IN_ID
);
494 This function delete and build multi-instance device path ConOut
497 @retval EFI_SUCCESS The function complete successfully.
498 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
501 Var_UpdateConsoleOutOption (
505 return Var_UpdateConsoleOption (L
"ConOut", &ConsoleOutMenu
, FORM_CON_OUT_ID
);
509 This function delete and build multi-instance device path ErrOut
512 @retval EFI_SUCCESS The function complete successfully.
513 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
516 Var_UpdateErrorOutOption (
520 return Var_UpdateConsoleOption (L
"ErrOut", &ConsoleErrMenu
, FORM_CON_ERR_ID
);
524 This function create a currently loaded Drive Option from
525 the BMM. It then appends this Driver Option to the end of
526 the "DriverOrder" list. It append this Driver Opotion to the end
529 @param CallbackData The BMM context data.
530 @param HiiHandle The HII handle associated with the BMM formset.
531 @param DescriptionData The description of this driver option.
532 @param OptionalData The optional load option.
533 @param ForceReconnect If to force reconnect.
535 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
536 @retval EFI_SUCCESS If function completes successfully.
540 Var_UpdateDriverOption (
541 IN BMM_CALLBACK_DATA
*CallbackData
,
542 IN EFI_HII_HANDLE HiiHandle
,
543 IN UINT16
*DescriptionData
,
544 IN UINT16
*OptionalData
,
545 IN UINT8 ForceReconnect
549 UINT16
*DriverOrderList
;
550 UINT16
*NewDriverOrderList
;
551 UINT16 DriverString
[12];
552 UINTN DriverOrderListSize
;
556 BM_MENU_ENTRY
*NewMenuEntry
;
557 BM_LOAD_CONTEXT
*NewLoadContext
;
558 BOOLEAN OptionalDataExist
;
561 OptionalDataExist
= FALSE
;
563 Index
= BOpt_GetDriverOptionNumber ();
566 sizeof (DriverString
),
571 if (*DescriptionData
== 0x0000) {
572 StrCpy (DescriptionData
, DriverString
);
575 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescriptionData
);
576 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
578 if (*OptionalData
!= 0x0000) {
579 OptionalDataExist
= TRUE
;
580 BufferSize
+= StrSize (OptionalData
);
583 Buffer
= AllocateZeroPool (BufferSize
);
584 if (NULL
== Buffer
) {
585 return EFI_OUT_OF_RESOURCES
;
588 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
589 if (NULL
== NewMenuEntry
) {
591 return EFI_OUT_OF_RESOURCES
;
594 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
595 NewLoadContext
->Deleted
= FALSE
;
596 NewLoadContext
->LoadOptionSize
= BufferSize
;
597 Ptr
= (UINT8
*) Buffer
;
598 NewLoadContext
->LoadOption
= Ptr
;
599 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
| (ForceReconnect
<< 1);
600 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
601 NewLoadContext
->IsActive
= TRUE
;
602 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
604 Ptr
+= sizeof (UINT32
);
605 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
606 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
608 Ptr
+= sizeof (UINT16
);
612 StrSize (DescriptionData
)
615 NewLoadContext
->Description
= AllocateZeroPool (StrSize (DescriptionData
));
616 ASSERT (NewLoadContext
->Description
!= NULL
);
617 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
619 NewLoadContext
->Description
,
621 StrSize (DescriptionData
)
624 Ptr
+= StrSize (DescriptionData
);
627 CallbackData
->LoadContext
->FilePathList
,
628 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
631 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
632 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
635 NewLoadContext
->FilePathList
,
637 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
640 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
641 NewMenuEntry
->OptionNumber
= Index
;
642 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
644 DriverOptionStrDepository
646 HiiLibNewString (HiiHandle
, &NewMenuEntry
->DisplayStringToken
, NewMenuEntry
->DisplayString
);
648 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
650 DriverOptionHelpStrDepository
652 HiiLibNewString (HiiHandle
, &NewMenuEntry
->HelpStringToken
, NewMenuEntry
->HelpString
);
654 if (OptionalDataExist
) {
655 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
660 StrSize (OptionalData
)
664 Status
= gRT
->SetVariable (
666 &gEfiGlobalVariableGuid
,
671 ASSERT_EFI_ERROR (Status
);
672 DriverOrderList
= BdsLibGetVariableAndSize (
674 &gEfiGlobalVariableGuid
,
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 HiiLibNewString (CallbackData
->FeHiiHandle
, &NewMenuEntry
->DisplayStringToken
, NewMenuEntry
->DisplayString
);
820 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
822 BootOptionHelpStrDepository
824 HiiLibNewString (CallbackData
->FeHiiHandle
, &NewMenuEntry
->HelpStringToken
, NewMenuEntry
->HelpString
);
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
,
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 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
854 FreePool (BootOrderList
);
857 Status
= gRT
->SetVariable (
859 &gEfiGlobalVariableGuid
,
861 BootOrderListSize
+ sizeof (UINT16
),
864 ASSERT_EFI_ERROR (Status
);
866 FreePool (NewBootOrderList
);
867 NewBootOrderList
= NULL
;
868 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
869 BootOptionMenu
.MenuNumber
++;
871 NvRamMap
->DescriptionData
[0] = 0x0000;
872 NvRamMap
->OptionalData
[0] = 0x0000;
877 This function update the "BootNext" EFI Variable. If there is
878 no "BootNex" specified in BMM, this EFI Variable is deleted.
879 It also update the BMM context data specified the "BootNext"
882 @param CallbackData The BMM context data.
884 @retval EFI_SUCCESS The function complete successfully.
885 @return The EFI variable can be saved. See gRT->SetVariable
886 for detail return information.
891 IN BMM_CALLBACK_DATA
*CallbackData
894 BM_MENU_ENTRY
*NewMenuEntry
;
895 BM_LOAD_CONTEXT
*NewLoadContext
;
896 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
900 Status
= EFI_SUCCESS
;
901 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
902 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
903 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
904 ASSERT (NULL
!= NewMenuEntry
);
906 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
907 NewLoadContext
->IsBootNext
= FALSE
;
910 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
911 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
915 NewMenuEntry
= BOpt_GetMenuEntry (
917 CurrentFakeNVMap
->BootNext
919 ASSERT (NewMenuEntry
!= NULL
);
921 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
922 Status
= gRT
->SetVariable (
924 &gEfiGlobalVariableGuid
,
927 &NewMenuEntry
->OptionNumber
929 NewLoadContext
->IsBootNext
= TRUE
;
930 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
935 This function update the "BootOrder" EFI Variable based on
936 BMM Formset's NV map. It then refresh BootOptionMenu
937 with the new "BootOrder" list.
939 @param CallbackData The BMM context data.
941 @retval EFI_SUCCESS The function complete successfully.
942 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
943 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
947 Var_UpdateBootOrder (
948 IN BMM_CALLBACK_DATA
*CallbackData
953 UINT16
*BootOrderList
;
954 UINT16
*NewBootOrderList
;
955 UINTN BootOrderListSize
;
957 BootOrderList
= NULL
;
958 BootOrderListSize
= 0;
961 // First check whether BootOrder is present in current configuration
963 BootOrderList
= BdsLibGetVariableAndSize (
965 &gEfiGlobalVariableGuid
,
969 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
);
970 if (NewBootOrderList
== NULL
) {
971 return EFI_OUT_OF_RESOURCES
;
975 // If exists, delete it to hold new BootOrder
977 if (BootOrderList
!= NULL
) {
978 EfiLibDeleteVariable (L
"BootOrder", &gEfiGlobalVariableGuid
);
979 FreePool (BootOrderList
);
982 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
983 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
984 NewBootOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[Index
] - 1);
987 Status
= gRT
->SetVariable (
989 &gEfiGlobalVariableGuid
,
994 FreePool (NewBootOrderList
);
995 if (EFI_ERROR (Status
)) {
999 BOpt_FreeMenu (&BootOptionMenu
);
1000 BOpt_GetBootOptions (CallbackData
);
1007 This function update the "DriverOrder" EFI Variable based on
1008 BMM Formset's NV map. It then refresh DriverOptionMenu
1009 with the new "DriverOrder" list.
1011 @param CallbackData The BMM context data.
1013 @retval EFI_SUCCESS The function complete successfully.
1014 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
1015 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
1019 Var_UpdateDriverOrder (
1020 IN BMM_CALLBACK_DATA
*CallbackData
1025 UINT16
*DriverOrderList
;
1026 UINT16
*NewDriverOrderList
;
1027 UINTN DriverOrderListSize
;
1029 DriverOrderList
= NULL
;
1030 DriverOrderListSize
= 0;
1033 // First check whether DriverOrder is present in current configuration
1035 DriverOrderList
= BdsLibGetVariableAndSize (
1037 &gEfiGlobalVariableGuid
,
1038 &DriverOrderListSize
1041 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1043 if (NewDriverOrderList
== NULL
) {
1044 return EFI_OUT_OF_RESOURCES
;
1047 // If exists, delete it to hold new DriverOrder
1049 if (DriverOrderList
!= NULL
) {
1050 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1051 FreePool (DriverOrderList
);
1054 ASSERT (DriverOrderListSize
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
1055 for (Index
= 0; Index
< DriverOrderListSize
; Index
++) {
1056 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[Index
] - 1);
1059 Status
= gRT
->SetVariable (
1061 &gEfiGlobalVariableGuid
,
1063 DriverOrderListSize
,
1066 if (EFI_ERROR (Status
)) {
1070 BOpt_FreeMenu (&DriverOptionMenu
);
1071 BOpt_GetDriverOptions (CallbackData
);
1076 Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable
1077 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1080 @param CallbackData The context data for BMM.
1082 @return EFI_SUCCESS The function completed successfully.
1083 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.
1084 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1087 Var_UpdateBBSOption (
1088 IN BMM_CALLBACK_DATA
*CallbackData
1093 VOID
*BootOptionVar
;
1094 CHAR16 VarName
[100];
1098 CHAR16 DescString
[100];
1099 CHAR8 DescAsciiString
[100];
1100 UINTN NewOptionSize
;
1101 UINT8
*NewOptionPtr
;
1104 BM_MENU_OPTION
*OptionMenu
;
1105 BM_LEGACY_DEVICE_CONTEXT
*LegacyDeviceContext
;
1109 BM_MENU_ENTRY
*NewMenuEntry
;
1110 BM_LEGACY_DEV_ORDER_CONTEXT
*DevOrder
;
1118 LegacyDeviceContext
= NULL
;
1122 if (FORM_SET_FD_ORDER_ID
== CallbackData
->BmmPreviousPageId
) {
1123 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1124 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1125 CallbackData
->BbsType
= BBS_FLOPPY
;
1127 if (FORM_SET_HD_ORDER_ID
== CallbackData
->BmmPreviousPageId
) {
1128 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1129 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1130 CallbackData
->BbsType
= BBS_HARDDISK
;
1132 if (FORM_SET_CD_ORDER_ID
== CallbackData
->BmmPreviousPageId
) {
1133 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1134 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1135 CallbackData
->BbsType
= BBS_CDROM
;
1137 if (FORM_SET_NET_ORDER_ID
== CallbackData
->BmmPreviousPageId
) {
1138 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1139 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1140 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1142 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1143 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1144 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1150 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1151 Status
= EFI_SUCCESS
;
1154 // Find the first device's context
1155 // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
1156 // because we just use it to fill the desc string, and user can not see the string in UI
1158 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1159 NewMenuEntry
= BOpt_GetMenuEntry (OptionMenu
, Index
);
1160 LegacyDeviceContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1161 if (0xFF != LegacyDev
[0] && LegacyDev
[0] == LegacyDeviceContext
->Index
) {
1162 DEBUG ((DEBUG_ERROR
, "DescStr: %s\n", LegacyDeviceContext
->Description
));
1167 // Update the Variable "LegacyDevOrder"
1169 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1170 VAR_LEGACY_DEV_ORDER
,
1171 &EfiLegacyDevOrderGuid
,
1175 if (VarData
== NULL
) {
1176 return EFI_NOT_FOUND
;
1179 OriginalPtr
= VarData
;
1180 DevOrder
= (BM_LEGACY_DEV_ORDER_CONTEXT
*) VarData
;
1182 while (VarData
< VarData
+ VarSize
) {
1183 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1187 VarData
+= sizeof (BBS_TYPE
);
1188 VarData
+= *(UINT16
*) VarData
;
1189 DevOrder
= (BM_LEGACY_DEV_ORDER_CONTEXT
*) VarData
;
1192 if (VarData
>= VarData
+ VarSize
) {
1193 FreePool (OriginalPtr
);
1194 return EFI_NOT_FOUND
;
1197 NewOrder
= (UINT16
*) AllocateZeroPool (DevOrder
->Length
- sizeof (UINT16
));
1198 if (NewOrder
== NULL
) {
1200 return EFI_OUT_OF_RESOURCES
;
1203 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1204 if (0xFF == LegacyDev
[Index
]) {
1208 NewOrder
[Index
] = LegacyDev
[Index
];
1211 // Only the enable/disable state of each boot device with same device type can be changed,
1212 // so we can count on the index information in DevOrder.
1213 // DisMap bit array is the only reliable source to check a device's en/dis state,
1214 // so we use DisMap to set en/dis state of each item in NewOrder array
1216 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1217 Tmp
= *(UINT16
*) ((UINT8
*) DevOrder
+ sizeof (BBS_TYPE
) + sizeof (UINT16
) + Index2
* sizeof (UINT16
));
1220 Bit
= 7 - (Tmp
% 8);
1221 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1222 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1228 (UINT8
*) DevOrder
+ sizeof (BBS_TYPE
) + sizeof (UINT16
),
1230 DevOrder
->Length
- sizeof (UINT16
)
1232 FreePool (NewOrder
);
1234 Status
= gRT
->SetVariable (
1235 VAR_LEGACY_DEV_ORDER
,
1236 &EfiLegacyDevOrderGuid
,
1242 FreePool (OriginalPtr
);
1245 // Update Optional Data of Boot####
1247 BootOptionVar
= GetLegacyBootOptionVar (CallbackData
->BbsType
, &Index
, &OptionSize
);
1249 if (BootOptionVar
!= NULL
) {
1252 LegacyDeviceContext
->Description
,
1253 StrSize (LegacyDeviceContext
->Description
)
1256 UnicodeStrToAsciiStr((CONST CHAR16
*)&DescString
, (CHAR8
*)&DescAsciiString
);
1258 NewOptionSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescString
) +
1259 sizeof (BBS_BBS_DEVICE_PATH
);
1260 NewOptionSize
+= AsciiStrLen (DescAsciiString
) +
1261 END_DEVICE_PATH_LENGTH
+ sizeof (BBS_TABLE
) + sizeof (UINT16
);
1263 UnicodeSPrint (VarName
, 100, L
"Boot%04x", Index
);
1265 Ptr
= BootOptionVar
;
1267 Attribute
= (UINT32
*) Ptr
;
1268 *Attribute
|= LOAD_OPTION_ACTIVE
;
1269 if (LegacyDev
[0] == 0xFF) {
1271 // Disable this legacy boot option
1273 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1276 Ptr
+= sizeof (UINT32
);
1278 Ptr
+= sizeof (UINT16
);
1279 Ptr
+= StrSize ((CHAR16
*) Ptr
);
1281 NewOptionPtr
= AllocateZeroPool (NewOptionSize
);
1282 if (NewOptionPtr
== NULL
) {
1283 return EFI_OUT_OF_RESOURCES
;
1286 TempPtr
= NewOptionPtr
;
1297 TempPtr
+= sizeof (UINT32
);
1300 // BBS device path Length
1302 *((UINT16
*) TempPtr
) = (UINT16
) (sizeof (BBS_BBS_DEVICE_PATH
) +
1303 AsciiStrLen (DescAsciiString
) +
1304 END_DEVICE_PATH_LENGTH
);
1306 TempPtr
+= sizeof (UINT16
);
1309 // Description string
1314 StrSize (DescString
)
1317 TempPtr
+= StrSize (DescString
);
1325 sizeof (BBS_BBS_DEVICE_PATH
)
1329 ((BBS_BBS_DEVICE_PATH
*) TempPtr
)->String
,
1331 AsciiStrSize (DescAsciiString
)
1334 SetDevicePathNodeLength (
1335 (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
,
1336 sizeof (BBS_BBS_DEVICE_PATH
) + AsciiStrLen (DescAsciiString
)
1339 TempPtr
+= sizeof (BBS_BBS_DEVICE_PATH
) + AsciiStrLen (DescAsciiString
);
1347 END_DEVICE_PATH_LENGTH
1349 TempPtr
+= END_DEVICE_PATH_LENGTH
;
1352 // Now TempPtr point to optional data, i.e. Bbs Table
1356 LegacyDeviceContext
->BbsTable
,
1361 // Now TempPtr point to BBS index
1363 TempPtr
+= sizeof (BBS_TABLE
);
1364 *((UINT16
*) TempPtr
) = (UINT16
) LegacyDeviceContext
->Index
;
1366 Status
= gRT
->SetVariable (
1368 &gEfiGlobalVariableGuid
,
1374 FreePool (NewOptionPtr
);
1375 FreePool (BootOptionVar
);
1378 BOpt_GetBootOptions (CallbackData
);
1383 Update the Text Mode of Console.
1385 @param CallbackData The context data for BMM.
1387 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1388 @return Other value if the Text Mode of Console is not updated.
1393 IN BMM_CALLBACK_DATA
*CallbackData
1398 CONSOLE_OUT_MODE ModeInfo
;
1400 Mode
= CallbackData
->BmmFakeNvData
.ConsoleOutMode
;
1402 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, Mode
, &(ModeInfo
.Column
), &(ModeInfo
.Row
));
1403 if (EFI_ERROR(Status
)) {
1404 ModeInfo
.Column
= 80;
1408 Status
= gRT
->SetVariable (
1410 &gEfiGenericPlatformVariableGuid
,
1411 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1412 sizeof (CONSOLE_OUT_MODE
),