2 Variable operation that will be used by bootmaint
4 Copyright (c) 2004 - 2018, 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
,
164 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
165 BootOrderListSize
* sizeof (UINT16
),
169 // Changing variable without increasing its size with current variable implementation shouldn't fail.
171 ASSERT_EFI_ERROR (Status
);
177 Delete Load Option that represent a Deleted state in BootOptionMenu.
178 After deleting this Driver option, call Var_ChangeDriverOrder to
179 make sure DriverOrder is in valid state.
181 @retval EFI_SUCCESS Load Option is successfully updated.
182 @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
183 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
188 Var_DelDriverOption (
192 BM_MENU_ENTRY
*NewMenuEntry
;
193 BM_LOAD_CONTEXT
*NewLoadContext
;
194 UINT16 DriverString
[12];
199 Status
= EFI_SUCCESS
;
201 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
202 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, (Index
- Index2
));
203 if (NULL
== NewMenuEntry
) {
204 return EFI_NOT_FOUND
;
207 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
208 if (!NewLoadContext
->Deleted
) {
214 sizeof (DriverString
),
216 NewMenuEntry
->OptionNumber
219 EfiLibDeleteVariable (DriverString
, &gEfiGlobalVariableGuid
);
222 RemoveEntryList (&NewMenuEntry
->Link
);
223 BOpt_DestroyMenuEntry (NewMenuEntry
);
227 DriverOptionMenu
.MenuNumber
-= Index2
;
229 Status
= Var_ChangeDriverOrder ();
234 After any operation on Driver####, there will be a discrepancy in
235 DriverOrder. Since some are missing but in DriverOrder, while some
236 are present but are not reflected by DriverOrder. Then a function
237 rebuild DriverOrder from scratch by content from DriverOptionMenu is
240 @retval EFI_SUCCESS The driver order is updated successfully.
241 @return Other status than EFI_SUCCESS if failed to 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
,
303 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
304 DriverOrderListSize
* sizeof (UINT16
),
308 // Changing variable without increasing its size with current variable implementation shouldn't fail.
310 ASSERT_EFI_ERROR (Status
);
318 This function delete and build multi-instance device path for
319 specified type of console device.
321 This function clear the EFI variable defined by ConsoleName and
322 gEfiGlobalVariableGuid. It then build the multi-instance device
323 path by appending the device path of the Console (In/Out/Err) instance
324 in ConsoleMenu. Then it scan all corresponding console device by
325 scanning Terminal (built from device supporting Serial I/O instances)
326 devices in TerminalMenu. At last, it save a EFI variable specifed
327 by ConsoleName and gEfiGlobalVariableGuid.
329 @param ConsoleName The name for the console device type. They are
330 usually "ConIn", "ConOut" and "ErrOut".
331 @param ConsoleMenu The console memu which is a list of console devices.
332 @param UpdatePageId The flag specifying which type of console device
335 @retval EFI_SUCCESS The function complete successfully.
336 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
340 Var_UpdateConsoleOption (
341 IN UINT16
*ConsoleName
,
342 IN BM_MENU_OPTION
*ConsoleMenu
,
343 IN UINT16 UpdatePageId
346 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
347 BM_MENU_ENTRY
*NewMenuEntry
;
348 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
349 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
351 VENDOR_DEVICE_PATH Vendor
;
352 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
355 ConDevicePath
= EfiLibGetVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
356 if (ConDevicePath
!= NULL
) {
357 EfiLibDeleteVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
358 FreePool (ConDevicePath
);
359 ConDevicePath
= NULL
;
363 // First add all console input device from console input menu
365 for (Index
= 0; Index
< ConsoleMenu
->MenuNumber
; Index
++) {
366 NewMenuEntry
= BOpt_GetMenuEntry (ConsoleMenu
, Index
);
368 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
369 if (NewConsoleContext
->IsActive
) {
370 ConDevicePath
= AppendDevicePathInstance (
372 NewConsoleContext
->DevicePath
377 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
378 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
380 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
381 if (((NewTerminalContext
->IsConIn
!= 0) && (UpdatePageId
== FORM_CON_IN_ID
)) ||
382 ((NewTerminalContext
->IsConOut
!= 0) && (UpdatePageId
== FORM_CON_OUT_ID
)) ||
383 ((NewTerminalContext
->IsStdErr
!= 0) && (UpdatePageId
== FORM_CON_ERR_ID
))
385 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
386 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
388 ASSERT (NewTerminalContext
->TerminalType
< (ARRAY_SIZE (TerminalTypeGuid
)));
391 &TerminalTypeGuid
[NewTerminalContext
->TerminalType
],
394 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
395 TerminalDevicePath
= AppendDevicePathNode (
396 NewTerminalContext
->DevicePath
,
397 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
399 ASSERT (TerminalDevicePath
!= NULL
);
400 ChangeTerminalDevicePath (&TerminalDevicePath
, TRUE
);
401 ConDevicePath
= AppendDevicePathInstance (
408 if (ConDevicePath
!= NULL
) {
409 Status
= gRT
->SetVariable (
411 &gEfiGlobalVariableGuid
,
412 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
413 GetDevicePathSize (ConDevicePath
),
416 if (EFI_ERROR (Status
)) {
426 This function delete and build multi-instance device path ConIn
429 @retval EFI_SUCCESS The function complete successfully.
430 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
433 Var_UpdateConsoleInpOption (
437 return Var_UpdateConsoleOption (L
"ConIn", &ConsoleInpMenu
, FORM_CON_IN_ID
);
441 This function delete and build multi-instance device path ConOut
444 @retval EFI_SUCCESS The function complete successfully.
445 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
448 Var_UpdateConsoleOutOption (
452 return Var_UpdateConsoleOption (L
"ConOut", &ConsoleOutMenu
, FORM_CON_OUT_ID
);
456 This function delete and build multi-instance device path ErrOut
459 @retval EFI_SUCCESS The function complete successfully.
460 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
463 Var_UpdateErrorOutOption (
467 return Var_UpdateConsoleOption (L
"ErrOut", &ConsoleErrMenu
, FORM_CON_ERR_ID
);
471 This function create a currently loaded Drive Option from
472 the BMM. It then appends this Driver Option to the end of
473 the "DriverOrder" list. It append this Driver Opotion to the end
476 @param CallbackData The BMM context data.
477 @param HiiHandle The HII handle associated with the BMM formset.
478 @param DescriptionData The description of this driver option.
479 @param OptionalData The optional load option.
480 @param ForceReconnect If to force reconnect.
482 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
483 @retval EFI_SUCCESS If function completes successfully.
487 Var_UpdateDriverOption (
488 IN BMM_CALLBACK_DATA
*CallbackData
,
489 IN EFI_HII_HANDLE HiiHandle
,
490 IN UINT16
*DescriptionData
,
491 IN UINT16
*OptionalData
,
492 IN UINT8 ForceReconnect
496 UINT16
*DriverOrderList
;
497 UINT16
*NewDriverOrderList
;
498 UINT16 DriverString
[12];
499 UINTN DriverOrderListSize
;
503 BM_MENU_ENTRY
*NewMenuEntry
;
504 BM_LOAD_CONTEXT
*NewLoadContext
;
505 BOOLEAN OptionalDataExist
;
508 OptionalDataExist
= FALSE
;
510 Index
= BOpt_GetDriverOptionNumber ();
513 sizeof (DriverString
),
518 if (*DescriptionData
== 0x0000) {
519 StrCpyS (DescriptionData
, DESCRIPTION_DATA_SIZE
, DriverString
);
522 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescriptionData
);
523 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
525 if (*OptionalData
!= 0x0000) {
526 OptionalDataExist
= TRUE
;
527 BufferSize
+= StrSize (OptionalData
);
530 Buffer
= AllocateZeroPool (BufferSize
);
531 if (NULL
== Buffer
) {
532 return EFI_OUT_OF_RESOURCES
;
535 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
536 if (NULL
== NewMenuEntry
) {
538 return EFI_OUT_OF_RESOURCES
;
541 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
542 NewLoadContext
->Deleted
= FALSE
;
543 NewLoadContext
->LoadOptionSize
= BufferSize
;
544 Ptr
= (UINT8
*) Buffer
;
545 NewLoadContext
->LoadOption
= Ptr
;
546 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
| (ForceReconnect
<< 1);
547 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
548 NewLoadContext
->IsActive
= TRUE
;
549 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
551 Ptr
+= sizeof (UINT32
);
552 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
553 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
555 Ptr
+= sizeof (UINT16
);
559 StrSize (DescriptionData
)
562 NewLoadContext
->Description
= AllocateZeroPool (StrSize (DescriptionData
));
563 ASSERT (NewLoadContext
->Description
!= NULL
);
564 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
566 NewLoadContext
->Description
,
568 StrSize (DescriptionData
)
571 Ptr
+= StrSize (DescriptionData
);
574 CallbackData
->LoadContext
->FilePathList
,
575 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
578 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
579 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
582 NewLoadContext
->FilePathList
,
584 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
587 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
588 NewMenuEntry
->OptionNumber
= Index
;
589 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
591 DriverOptionStrDepository
593 NewMenuEntry
->DisplayStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
595 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
597 DriverOptionHelpStrDepository
599 NewMenuEntry
->HelpStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
601 if (OptionalDataExist
) {
602 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
607 StrSize (OptionalData
)
611 Status
= gRT
->SetVariable (
613 &gEfiGlobalVariableGuid
,
614 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
618 if (!EFI_ERROR (Status
)) {
619 DriverOrderList
= BdsLibGetVariableAndSize (
621 &gEfiGlobalVariableGuid
,
624 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
+ sizeof (UINT16
));
625 ASSERT (NewDriverOrderList
!= NULL
);
626 if (DriverOrderList
!= NULL
) {
627 CopyMem (NewDriverOrderList
, DriverOrderList
, DriverOrderListSize
);
628 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
630 NewDriverOrderList
[DriverOrderListSize
/ sizeof (UINT16
)] = Index
;
632 Status
= gRT
->SetVariable (
634 &gEfiGlobalVariableGuid
,
635 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
636 DriverOrderListSize
+ sizeof (UINT16
),
639 if (DriverOrderList
!= NULL
) {
640 FreePool (DriverOrderList
);
642 DriverOrderList
= NULL
;
643 FreePool (NewDriverOrderList
);
644 if (!EFI_ERROR (Status
)) {
645 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
646 DriverOptionMenu
.MenuNumber
++;
649 // Update "change boot order" page used data, append the new add boot
650 // option at the end.
653 while (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] != 0) {
656 CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);
658 *DescriptionData
= 0x0000;
659 *OptionalData
= 0x0000;
666 This function create a currently loaded Boot Option from
667 the BMM. It then appends this Boot Option to the end of
668 the "BootOrder" list. It also append this Boot Opotion to the end
671 @param CallbackData The BMM context data.
672 @param NvRamMap The file explorer formset internal state.
674 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
675 @retval EFI_SUCCESS If function completes successfully.
679 Var_UpdateBootOption (
680 IN BMM_CALLBACK_DATA
*CallbackData
,
681 IN FILE_EXPLORER_NV_DATA
*NvRamMap
684 UINT16
*BootOrderList
;
685 UINT16
*NewBootOrderList
;
686 UINTN BootOrderListSize
;
687 UINT16 BootString
[10];
692 BM_MENU_ENTRY
*NewMenuEntry
;
693 BM_LOAD_CONTEXT
*NewLoadContext
;
694 BOOLEAN OptionalDataExist
;
697 OptionalDataExist
= FALSE
;
699 Index
= BOpt_GetBootOptionNumber () ;
700 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", Index
);
702 if (NvRamMap
->BootDescriptionData
[0] == 0x0000) {
704 NvRamMap
->BootDescriptionData
,
705 sizeof (NvRamMap
->BootDescriptionData
) / sizeof (NvRamMap
->BootDescriptionData
[0]),
710 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (NvRamMap
->BootDescriptionData
);
711 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
713 if (NvRamMap
->BootOptionalData
[0] != 0x0000) {
714 OptionalDataExist
= TRUE
;
715 BufferSize
+= StrSize (NvRamMap
->BootOptionalData
);
718 Buffer
= AllocateZeroPool (BufferSize
);
719 if (NULL
== Buffer
) {
720 return EFI_OUT_OF_RESOURCES
;
723 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
724 if (NULL
== NewMenuEntry
) {
725 return EFI_OUT_OF_RESOURCES
;
728 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
729 NewLoadContext
->Deleted
= FALSE
;
730 NewLoadContext
->LoadOptionSize
= BufferSize
;
731 Ptr
= (UINT8
*) Buffer
;
732 NewLoadContext
->LoadOption
= Ptr
;
733 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
734 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
735 NewLoadContext
->IsActive
= TRUE
;
736 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
738 Ptr
+= sizeof (UINT32
);
739 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
740 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
741 Ptr
+= sizeof (UINT16
);
745 NvRamMap
->BootDescriptionData
,
746 StrSize (NvRamMap
->BootDescriptionData
)
749 NewLoadContext
->Description
= AllocateZeroPool (StrSize (NvRamMap
->BootDescriptionData
));
750 ASSERT (NewLoadContext
->Description
!= NULL
);
752 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
754 NewLoadContext
->Description
,
756 StrSize (NvRamMap
->BootDescriptionData
)
759 Ptr
+= StrSize (NvRamMap
->BootDescriptionData
);
762 CallbackData
->LoadContext
->FilePathList
,
763 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
766 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
767 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
770 NewLoadContext
->FilePathList
,
772 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
775 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
776 NewMenuEntry
->OptionNumber
= Index
;
777 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
779 BootOptionStrDepository
781 NewMenuEntry
->DisplayStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
783 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
785 BootOptionHelpStrDepository
787 NewMenuEntry
->HelpStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
789 if (OptionalDataExist
) {
790 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
792 CopyMem (Ptr
, NvRamMap
->BootOptionalData
, StrSize (NvRamMap
->BootOptionalData
));
795 Status
= gRT
->SetVariable (
797 &gEfiGlobalVariableGuid
,
798 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
802 if (!EFI_ERROR (Status
)) {
804 BootOrderList
= BdsLibGetVariableAndSize (
806 &gEfiGlobalVariableGuid
,
809 ASSERT (BootOrderList
!= NULL
);
810 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
+ sizeof (UINT16
));
811 ASSERT (NewBootOrderList
!= NULL
);
812 CopyMem (NewBootOrderList
, BootOrderList
, BootOrderListSize
);
813 NewBootOrderList
[BootOrderListSize
/ sizeof (UINT16
)] = Index
;
815 if (BootOrderList
!= NULL
) {
816 FreePool (BootOrderList
);
819 Status
= gRT
->SetVariable (
821 &gEfiGlobalVariableGuid
,
822 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
823 BootOrderListSize
+ sizeof (UINT16
),
826 if (!EFI_ERROR (Status
)) {
828 FreePool (NewBootOrderList
);
829 NewBootOrderList
= NULL
;
830 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
831 BootOptionMenu
.MenuNumber
++;
834 // Update "change driver order" page used data, append the new add driver
835 // option at the end.
838 while (CallbackData
->BmmFakeNvData
.BootOptionOrder
[Index
] != 0) {
841 CallbackData
->BmmFakeNvData
.BootOptionOrder
[Index
] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);
843 NvRamMap
->BootDescriptionData
[0] = 0x0000;
844 NvRamMap
->BootOptionalData
[0] = 0x0000;
851 This function update the "BootNext" EFI Variable. If there is
852 no "BootNext" specified in BMM, this EFI Variable is deleted.
853 It also update the BMM context data specified the "BootNext"
856 @param CallbackData The BMM context data.
858 @retval EFI_SUCCESS The function complete successfully.
859 @return The EFI variable can be saved. See gRT->SetVariable
860 for detail return information.
865 IN BMM_CALLBACK_DATA
*CallbackData
868 BM_MENU_ENTRY
*NewMenuEntry
;
869 BM_LOAD_CONTEXT
*NewLoadContext
;
870 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
874 Status
= EFI_SUCCESS
;
875 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
876 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
877 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
878 ASSERT (NULL
!= NewMenuEntry
);
880 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
881 NewLoadContext
->IsBootNext
= FALSE
;
884 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
885 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
889 NewMenuEntry
= BOpt_GetMenuEntry (
891 CurrentFakeNVMap
->BootNext
893 ASSERT (NewMenuEntry
!= NULL
);
895 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
896 Status
= gRT
->SetVariable (
898 &gEfiGlobalVariableGuid
,
899 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
901 &NewMenuEntry
->OptionNumber
903 NewLoadContext
->IsBootNext
= TRUE
;
904 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
909 This function update the "BootOrder" EFI Variable based on
910 BMM Formset's NV map. It then refresh BootOptionMenu
911 with the new "BootOrder" list.
913 @param CallbackData The BMM context data.
915 @retval EFI_SUCCESS The function complete successfully.
916 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
917 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
921 Var_UpdateBootOrder (
922 IN BMM_CALLBACK_DATA
*CallbackData
928 UINT16
*BootOrderList
;
929 UINTN BootOrderListSize
;
932 BootOrderList
= NULL
;
933 BootOrderListSize
= 0;
936 // First check whether BootOrder is present in current configuration
938 BootOrderList
= BdsLibGetVariableAndSize (
940 &gEfiGlobalVariableGuid
,
943 if (BootOrderList
== NULL
) {
944 return EFI_OUT_OF_RESOURCES
;
947 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.BootOptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.BootOptionOrder
[0])));
949 for (OrderIndex
= 0; (OrderIndex
< BootOptionMenu
.MenuNumber
) && (CallbackData
->BmmFakeNvData
.BootOptionOrder
[OrderIndex
] != 0); OrderIndex
++) {
950 for (Index
= OrderIndex
; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
951 if ((BootOrderList
[Index
] == (UINT16
) (CallbackData
->BmmFakeNvData
.BootOptionOrder
[OrderIndex
] - 1)) && (OrderIndex
!= Index
)) {
952 OptionNumber
= BootOrderList
[Index
];
953 CopyMem (&BootOrderList
[OrderIndex
+ 1], &BootOrderList
[OrderIndex
], (Index
- OrderIndex
) * sizeof (UINT16
));
954 BootOrderList
[OrderIndex
] = OptionNumber
;
959 Status
= gRT
->SetVariable (
961 &gEfiGlobalVariableGuid
,
962 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
967 // Changing the content without increasing its size with current variable implementation shouldn't fail.
969 ASSERT_EFI_ERROR (Status
);
970 FreePool (BootOrderList
);
972 GroupMultipleLegacyBootOption4SameType ();
974 BOpt_FreeMenu (&BootOptionMenu
);
975 BOpt_GetBootOptions (CallbackData
);
982 This function update the "DriverOrder" EFI Variable based on
983 BMM Formset's NV map. It then refresh DriverOptionMenu
984 with the new "DriverOrder" list.
986 @param CallbackData The BMM context data.
988 @retval EFI_SUCCESS The function complete successfully.
989 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
990 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
994 Var_UpdateDriverOrder (
995 IN BMM_CALLBACK_DATA
*CallbackData
1000 UINT16
*DriverOrderList
;
1001 UINT16
*NewDriverOrderList
;
1002 UINTN DriverOrderListSize
;
1004 DriverOrderList
= NULL
;
1005 DriverOrderListSize
= 0;
1008 // First check whether DriverOrder is present in current configuration
1010 DriverOrderList
= BdsLibGetVariableAndSize (
1012 &gEfiGlobalVariableGuid
,
1013 &DriverOrderListSize
1016 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1018 if (NewDriverOrderList
== NULL
) {
1019 return EFI_OUT_OF_RESOURCES
;
1022 // If exists, delete it to hold new DriverOrder
1024 if (DriverOrderList
!= NULL
) {
1025 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1026 FreePool (DriverOrderList
);
1029 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.DriverOptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[0])));
1030 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1031 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.DriverOptionOrder
[Index
] - 1);
1034 Status
= gRT
->SetVariable (
1036 &gEfiGlobalVariableGuid
,
1037 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1038 DriverOrderListSize
,
1042 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1044 ASSERT_EFI_ERROR (Status
);
1046 BOpt_FreeMenu (&DriverOptionMenu
);
1047 BOpt_GetDriverOptions (CallbackData
);
1052 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable
1053 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1056 @param CallbackData The context data for BMM.
1057 @param FormId The form id.
1059 @return EFI_SUCCESS The function completed successfully.
1060 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.
1061 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1064 Var_UpdateBBSOption (
1065 IN BMM_CALLBACK_DATA
*CallbackData
,
1066 IN EFI_FORM_ID FormId
1071 VOID
*BootOptionVar
;
1072 CHAR16 VarName
[100];
1076 BM_MENU_OPTION
*OptionMenu
;
1080 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1087 UINT16
*EnBootOption
;
1088 UINTN EnBootOptionCount
;
1089 UINT16
*DisBootOption
;
1090 UINTN DisBootOptionCount
;
1096 case FORM_SET_FD_ORDER_ID
:
1097 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1098 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1099 CallbackData
->BbsType
= BBS_FLOPPY
;
1102 case FORM_SET_HD_ORDER_ID
:
1103 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1104 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1105 CallbackData
->BbsType
= BBS_HARDDISK
;
1108 case FORM_SET_CD_ORDER_ID
:
1109 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1110 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1111 CallbackData
->BbsType
= BBS_CDROM
;
1114 case FORM_SET_NET_ORDER_ID
:
1115 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1116 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1117 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1121 ASSERT (FORM_SET_BEV_ORDER_ID
== CallbackData
->BmmPreviousPageId
);
1122 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1123 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1124 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1128 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1129 Status
= EFI_SUCCESS
;
1133 // Update the Variable "LegacyDevOrder"
1135 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1136 VAR_LEGACY_DEV_ORDER
,
1137 &gEfiLegacyDevOrderVariableGuid
,
1141 if (VarData
== NULL
) {
1142 return EFI_NOT_FOUND
;
1145 OriginalPtr
= VarData
;
1146 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1148 while (VarData
< OriginalPtr
+ VarSize
) {
1149 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1153 VarData
+= sizeof (BBS_TYPE
) + DevOrder
->Length
;
1154 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1157 if (VarData
>= OriginalPtr
+ VarSize
) {
1158 FreePool (OriginalPtr
);
1159 return EFI_NOT_FOUND
;
1162 NewOrder
= AllocateZeroPool (DevOrder
->Length
- sizeof (DevOrder
->Length
));
1163 if (NewOrder
== NULL
) {
1164 FreePool (OriginalPtr
);
1165 return EFI_OUT_OF_RESOURCES
;
1168 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1169 if (0xFF == LegacyDev
[Index
]) {
1173 NewOrder
[Index
] = LegacyDev
[Index
];
1176 // Only the enable/disable state of each boot device with same device type can be changed,
1177 // so we can count on the index information in DevOrder.
1178 // DisMap bit array is the only reliable source to check a device's en/dis state,
1179 // so we use DisMap to set en/dis state of each item in NewOrder array
1181 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1182 Tmp
= (UINT16
) (DevOrder
->Data
[Index2
] & 0xFF);
1184 Bit
= 7 - (Tmp
% 8);
1185 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1186 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1194 DevOrder
->Length
- sizeof (DevOrder
->Length
)
1196 FreePool (NewOrder
);
1198 Status
= gRT
->SetVariable (
1199 VAR_LEGACY_DEV_ORDER
,
1200 &gEfiLegacyDevOrderVariableGuid
,
1201 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1208 // Update BootOrder and Boot####.Attribute
1210 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
1212 ASSERT (OptionMenu
->MenuNumber
== DevOrder
->Length
/ sizeof (UINT16
) - 1);
1214 OrderLegacyBootOption4SameType (
1216 DevOrder
->Length
/ sizeof (UINT16
) - 1,
1224 // 2. Deactivate the DisBootOption and activate the EnBootOption
1226 for (Index
= 0; Index
< DisBootOptionCount
; Index
++) {
1227 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", DisBootOption
[Index
]);
1228 BootOptionVar
= BdsLibGetVariableAndSize (
1230 &gEfiGlobalVariableGuid
,
1233 if (BootOptionVar
!= NULL
) {
1234 Attribute
= (UINT32
*) BootOptionVar
;
1235 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1237 Status
= gRT
->SetVariable (
1239 &gEfiGlobalVariableGuid
,
1240 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1245 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1247 ASSERT_EFI_ERROR (Status
);
1249 FreePool (BootOptionVar
);
1253 for (Index
= 0; Index
< EnBootOptionCount
; Index
++) {
1254 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", EnBootOption
[Index
]);
1255 BootOptionVar
= BdsLibGetVariableAndSize (
1257 &gEfiGlobalVariableGuid
,
1260 if (BootOptionVar
!= NULL
) {
1261 Attribute
= (UINT32
*) BootOptionVar
;
1262 *Attribute
|= LOAD_OPTION_ACTIVE
;
1264 Status
= gRT
->SetVariable (
1266 &gEfiGlobalVariableGuid
,
1267 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1272 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1274 ASSERT_EFI_ERROR (Status
);
1276 FreePool (BootOptionVar
);
1280 BOpt_GetBootOptions (CallbackData
);
1282 FreePool (OriginalPtr
);
1283 FreePool (EnBootOption
);
1284 FreePool (DisBootOption
);
1289 Update the Text Mode of Console.
1291 @param CallbackData The context data for BMM.
1293 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1294 @return Other value if the Text Mode of Console is not updated.
1299 IN BMM_CALLBACK_DATA
*CallbackData
1304 CONSOLE_OUT_MODE ModeInfo
;
1306 Mode
= CallbackData
->BmmFakeNvData
.ConsoleOutMode
;
1308 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, Mode
, &(ModeInfo
.Column
), &(ModeInfo
.Row
));
1309 if (!EFI_ERROR(Status
)) {
1310 Status
= PcdSet32S (PcdSetupConOutColumn
, (UINT32
) ModeInfo
.Column
);
1311 if (!EFI_ERROR (Status
)){
1312 Status
= PcdSet32S (PcdSetupConOutRow
, (UINT32
) ModeInfo
.Row
);