2 Variable operation that will be used by bootmaint
4 Copyright (c) 2004 - 2014, 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
);
316 Update the device path of "ConOut", "ConIn" and "ErrOut"
317 based on the new BaudRate, Data Bits, parity and Stop Bits
322 Var_UpdateAllConsoleOption (
326 EFI_DEVICE_PATH_PROTOCOL
*OutDevicePath
;
327 EFI_DEVICE_PATH_PROTOCOL
*InpDevicePath
;
328 EFI_DEVICE_PATH_PROTOCOL
*ErrDevicePath
;
331 OutDevicePath
= EfiLibGetVariable (L
"ConOut", &gEfiGlobalVariableGuid
);
332 InpDevicePath
= EfiLibGetVariable (L
"ConIn", &gEfiGlobalVariableGuid
);
333 ErrDevicePath
= EfiLibGetVariable (L
"ErrOut", &gEfiGlobalVariableGuid
);
334 if (OutDevicePath
!= NULL
) {
335 ChangeVariableDevicePath (OutDevicePath
);
336 Status
= gRT
->SetVariable (
338 &gEfiGlobalVariableGuid
,
339 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
340 GetDevicePathSize (OutDevicePath
),
344 // Changing variable without increasing its size with current variable implementation shouldn't fail.
346 ASSERT_EFI_ERROR (Status
);
349 if (InpDevicePath
!= NULL
) {
350 ChangeVariableDevicePath (InpDevicePath
);
351 Status
= gRT
->SetVariable (
353 &gEfiGlobalVariableGuid
,
354 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
355 GetDevicePathSize (InpDevicePath
),
359 // Changing variable without increasing its size with current variable implementation shouldn't fail.
361 ASSERT_EFI_ERROR (Status
);
364 if (ErrDevicePath
!= NULL
) {
365 ChangeVariableDevicePath (ErrDevicePath
);
366 Status
= gRT
->SetVariable (
368 &gEfiGlobalVariableGuid
,
369 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
370 GetDevicePathSize (ErrDevicePath
),
374 // Changing variable without increasing its size with current variable implementation shouldn't fail.
376 ASSERT_EFI_ERROR (Status
);
381 This function delete and build multi-instance device path for
382 specified type of console device.
384 This function clear the EFI variable defined by ConsoleName and
385 gEfiGlobalVariableGuid. It then build the multi-instance device
386 path by appending the device path of the Console (In/Out/Err) instance
387 in ConsoleMenu. Then it scan all corresponding console device by
388 scanning Terminal (built from device supporting Serial I/O instances)
389 devices in TerminalMenu. At last, it save a EFI variable specifed
390 by ConsoleName and gEfiGlobalVariableGuid.
392 @param ConsoleName The name for the console device type. They are
393 usually "ConIn", "ConOut" and "ErrOut".
394 @param ConsoleMenu The console memu which is a list of console devices.
395 @param UpdatePageId The flag specifying which type of console device
398 @retval EFI_SUCCESS The function complete successfully.
399 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
403 Var_UpdateConsoleOption (
404 IN UINT16
*ConsoleName
,
405 IN BM_MENU_OPTION
*ConsoleMenu
,
406 IN UINT16 UpdatePageId
409 EFI_DEVICE_PATH_PROTOCOL
*ConDevicePath
;
410 BM_MENU_ENTRY
*NewMenuEntry
;
411 BM_CONSOLE_CONTEXT
*NewConsoleContext
;
412 BM_TERMINAL_CONTEXT
*NewTerminalContext
;
414 VENDOR_DEVICE_PATH Vendor
;
415 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
418 ConDevicePath
= EfiLibGetVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
419 if (ConDevicePath
!= NULL
) {
420 EfiLibDeleteVariable (ConsoleName
, &gEfiGlobalVariableGuid
);
421 FreePool (ConDevicePath
);
422 ConDevicePath
= NULL
;
426 // First add all console input device from console input menu
428 for (Index
= 0; Index
< ConsoleMenu
->MenuNumber
; Index
++) {
429 NewMenuEntry
= BOpt_GetMenuEntry (ConsoleMenu
, Index
);
431 NewConsoleContext
= (BM_CONSOLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
432 if (NewConsoleContext
->IsActive
) {
433 ConDevicePath
= AppendDevicePathInstance (
435 NewConsoleContext
->DevicePath
440 for (Index
= 0; Index
< TerminalMenu
.MenuNumber
; Index
++) {
441 NewMenuEntry
= BOpt_GetMenuEntry (&TerminalMenu
, Index
);
443 NewTerminalContext
= (BM_TERMINAL_CONTEXT
*) NewMenuEntry
->VariableContext
;
444 if (((NewTerminalContext
->IsConIn
!= 0) && (UpdatePageId
== FORM_CON_IN_ID
)) ||
445 ((NewTerminalContext
->IsConOut
!= 0) && (UpdatePageId
== FORM_CON_OUT_ID
)) ||
446 ((NewTerminalContext
->IsStdErr
!= 0) && (UpdatePageId
== FORM_CON_ERR_ID
))
448 Vendor
.Header
.Type
= MESSAGING_DEVICE_PATH
;
449 Vendor
.Header
.SubType
= MSG_VENDOR_DP
;
451 ASSERT (NewTerminalContext
->TerminalType
< (sizeof (TerminalTypeGuid
) / sizeof (TerminalTypeGuid
[0])));
454 &TerminalTypeGuid
[NewTerminalContext
->TerminalType
],
457 SetDevicePathNodeLength (&Vendor
.Header
, sizeof (VENDOR_DEVICE_PATH
));
458 TerminalDevicePath
= AppendDevicePathNode (
459 NewTerminalContext
->DevicePath
,
460 (EFI_DEVICE_PATH_PROTOCOL
*) &Vendor
462 ASSERT (TerminalDevicePath
!= NULL
);
463 ChangeTerminalDevicePath (&TerminalDevicePath
, TRUE
);
464 ConDevicePath
= AppendDevicePathInstance (
471 if (ConDevicePath
!= NULL
) {
472 Status
= gRT
->SetVariable (
474 &gEfiGlobalVariableGuid
,
475 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
476 GetDevicePathSize (ConDevicePath
),
479 if (EFI_ERROR (Status
)) {
489 This function delete and build multi-instance device path ConIn
492 @retval EFI_SUCCESS The function complete successfully.
493 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
496 Var_UpdateConsoleInpOption (
500 return Var_UpdateConsoleOption (L
"ConIn", &ConsoleInpMenu
, FORM_CON_IN_ID
);
504 This function delete and build multi-instance device path ConOut
507 @retval EFI_SUCCESS The function complete successfully.
508 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
511 Var_UpdateConsoleOutOption (
515 return Var_UpdateConsoleOption (L
"ConOut", &ConsoleOutMenu
, FORM_CON_OUT_ID
);
519 This function delete and build multi-instance device path ErrOut
522 @retval EFI_SUCCESS The function complete successfully.
523 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
526 Var_UpdateErrorOutOption (
530 return Var_UpdateConsoleOption (L
"ErrOut", &ConsoleErrMenu
, FORM_CON_ERR_ID
);
534 This function create a currently loaded Drive Option from
535 the BMM. It then appends this Driver Option to the end of
536 the "DriverOrder" list. It append this Driver Opotion to the end
539 @param CallbackData The BMM context data.
540 @param HiiHandle The HII handle associated with the BMM formset.
541 @param DescriptionData The description of this driver option.
542 @param OptionalData The optional load option.
543 @param ForceReconnect If to force reconnect.
545 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
546 @retval EFI_SUCCESS If function completes successfully.
550 Var_UpdateDriverOption (
551 IN BMM_CALLBACK_DATA
*CallbackData
,
552 IN EFI_HII_HANDLE HiiHandle
,
553 IN UINT16
*DescriptionData
,
554 IN UINT16
*OptionalData
,
555 IN UINT8 ForceReconnect
559 UINT16
*DriverOrderList
;
560 UINT16
*NewDriverOrderList
;
561 UINT16 DriverString
[12];
562 UINTN DriverOrderListSize
;
566 BM_MENU_ENTRY
*NewMenuEntry
;
567 BM_LOAD_CONTEXT
*NewLoadContext
;
568 BOOLEAN OptionalDataExist
;
571 OptionalDataExist
= FALSE
;
573 Index
= BOpt_GetDriverOptionNumber ();
576 sizeof (DriverString
),
581 if (*DescriptionData
== 0x0000) {
582 StrCpy (DescriptionData
, DriverString
);
585 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (DescriptionData
);
586 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
588 if (*OptionalData
!= 0x0000) {
589 OptionalDataExist
= TRUE
;
590 BufferSize
+= StrSize (OptionalData
);
593 Buffer
= AllocateZeroPool (BufferSize
);
594 if (NULL
== Buffer
) {
595 return EFI_OUT_OF_RESOURCES
;
598 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
599 if (NULL
== NewMenuEntry
) {
601 return EFI_OUT_OF_RESOURCES
;
604 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
605 NewLoadContext
->Deleted
= FALSE
;
606 NewLoadContext
->LoadOptionSize
= BufferSize
;
607 Ptr
= (UINT8
*) Buffer
;
608 NewLoadContext
->LoadOption
= Ptr
;
609 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
| (ForceReconnect
<< 1);
610 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
611 NewLoadContext
->IsActive
= TRUE
;
612 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
614 Ptr
+= sizeof (UINT32
);
615 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
616 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
618 Ptr
+= sizeof (UINT16
);
622 StrSize (DescriptionData
)
625 NewLoadContext
->Description
= AllocateZeroPool (StrSize (DescriptionData
));
626 ASSERT (NewLoadContext
->Description
!= NULL
);
627 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
629 NewLoadContext
->Description
,
631 StrSize (DescriptionData
)
634 Ptr
+= StrSize (DescriptionData
);
637 CallbackData
->LoadContext
->FilePathList
,
638 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
641 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
642 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
645 NewLoadContext
->FilePathList
,
647 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
650 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
651 NewMenuEntry
->OptionNumber
= Index
;
652 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
654 DriverOptionStrDepository
656 NewMenuEntry
->DisplayStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
658 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
660 DriverOptionHelpStrDepository
662 NewMenuEntry
->HelpStringToken
= HiiSetString (HiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
664 if (OptionalDataExist
) {
665 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
670 StrSize (OptionalData
)
674 Status
= gRT
->SetVariable (
676 &gEfiGlobalVariableGuid
,
677 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
681 if (!EFI_ERROR (Status
)) {
682 DriverOrderList
= BdsLibGetVariableAndSize (
684 &gEfiGlobalVariableGuid
,
687 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
+ sizeof (UINT16
));
688 ASSERT (NewDriverOrderList
!= NULL
);
689 if (DriverOrderList
!= NULL
) {
690 CopyMem (NewDriverOrderList
, DriverOrderList
, DriverOrderListSize
);
691 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
693 NewDriverOrderList
[DriverOrderListSize
/ sizeof (UINT16
)] = Index
;
695 Status
= gRT
->SetVariable (
697 &gEfiGlobalVariableGuid
,
698 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
699 DriverOrderListSize
+ sizeof (UINT16
),
702 if (DriverOrderList
!= NULL
) {
703 FreePool (DriverOrderList
);
705 DriverOrderList
= NULL
;
706 FreePool (NewDriverOrderList
);
707 if (!EFI_ERROR (Status
)) {
708 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
709 DriverOptionMenu
.MenuNumber
++;
711 *DescriptionData
= 0x0000;
712 *OptionalData
= 0x0000;
719 This function create a currently loaded Boot Option from
720 the BMM. It then appends this Boot Option to the end of
721 the "BootOrder" list. It also append this Boot Opotion to the end
724 @param CallbackData The BMM context data.
725 @param NvRamMap The file explorer formset internal state.
727 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
728 @retval EFI_SUCCESS If function completes successfully.
732 Var_UpdateBootOption (
733 IN BMM_CALLBACK_DATA
*CallbackData
,
734 IN FILE_EXPLORER_NV_DATA
*NvRamMap
737 UINT16
*BootOrderList
;
738 UINT16
*NewBootOrderList
;
739 UINTN BootOrderListSize
;
740 UINT16 BootString
[10];
745 BM_MENU_ENTRY
*NewMenuEntry
;
746 BM_LOAD_CONTEXT
*NewLoadContext
;
747 BOOLEAN OptionalDataExist
;
750 OptionalDataExist
= FALSE
;
752 Index
= BOpt_GetBootOptionNumber () ;
753 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", Index
);
755 if (NvRamMap
->DescriptionData
[0] == 0x0000) {
756 StrCpy (NvRamMap
->DescriptionData
, BootString
);
759 BufferSize
= sizeof (UINT32
) + sizeof (UINT16
) + StrSize (NvRamMap
->DescriptionData
);
760 BufferSize
+= GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
762 if (NvRamMap
->OptionalData
[0] != 0x0000) {
763 OptionalDataExist
= TRUE
;
764 BufferSize
+= StrSize (NvRamMap
->OptionalData
);
767 Buffer
= AllocateZeroPool (BufferSize
);
768 if (NULL
== Buffer
) {
769 return EFI_OUT_OF_RESOURCES
;
772 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
773 if (NULL
== NewMenuEntry
) {
774 return EFI_OUT_OF_RESOURCES
;
777 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
778 NewLoadContext
->Deleted
= FALSE
;
779 NewLoadContext
->LoadOptionSize
= BufferSize
;
780 Ptr
= (UINT8
*) Buffer
;
781 NewLoadContext
->LoadOption
= Ptr
;
782 *((UINT32
*) Ptr
) = LOAD_OPTION_ACTIVE
;
783 NewLoadContext
->Attributes
= *((UINT32
*) Ptr
);
784 NewLoadContext
->IsActive
= TRUE
;
785 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
787 Ptr
+= sizeof (UINT32
);
788 *((UINT16
*) Ptr
) = (UINT16
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
789 NewLoadContext
->FilePathListLength
= *((UINT16
*) Ptr
);
790 Ptr
+= sizeof (UINT16
);
794 NvRamMap
->DescriptionData
,
795 StrSize (NvRamMap
->DescriptionData
)
798 NewLoadContext
->Description
= AllocateZeroPool (StrSize (NvRamMap
->DescriptionData
));
799 ASSERT (NewLoadContext
->Description
!= NULL
);
801 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
803 NewLoadContext
->Description
,
805 StrSize (NvRamMap
->DescriptionData
)
808 Ptr
+= StrSize (NvRamMap
->DescriptionData
);
811 CallbackData
->LoadContext
->FilePathList
,
812 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
815 NewLoadContext
->FilePathList
= AllocateZeroPool (GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
));
816 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
819 NewLoadContext
->FilePathList
,
821 GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
)
824 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
825 NewMenuEntry
->OptionNumber
= Index
;
826 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
828 BootOptionStrDepository
830 NewMenuEntry
->DisplayStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->DisplayString
, NULL
);
832 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
834 BootOptionHelpStrDepository
836 NewMenuEntry
->HelpStringToken
= HiiSetString (CallbackData
->FeHiiHandle
, 0, NewMenuEntry
->HelpString
, NULL
);
838 if (OptionalDataExist
) {
839 Ptr
+= (UINT8
) GetDevicePathSize (CallbackData
->LoadContext
->FilePathList
);
841 CopyMem (Ptr
, NvRamMap
->OptionalData
, StrSize (NvRamMap
->OptionalData
));
844 Status
= gRT
->SetVariable (
846 &gEfiGlobalVariableGuid
,
847 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
851 if (!EFI_ERROR (Status
)) {
853 BootOrderList
= BdsLibGetVariableAndSize (
855 &gEfiGlobalVariableGuid
,
858 ASSERT (BootOrderList
!= NULL
);
859 NewBootOrderList
= AllocateZeroPool (BootOrderListSize
+ sizeof (UINT16
));
860 ASSERT (NewBootOrderList
!= NULL
);
861 CopyMem (NewBootOrderList
, BootOrderList
, BootOrderListSize
);
862 NewBootOrderList
[BootOrderListSize
/ sizeof (UINT16
)] = Index
;
864 if (BootOrderList
!= NULL
) {
865 FreePool (BootOrderList
);
868 Status
= gRT
->SetVariable (
870 &gEfiGlobalVariableGuid
,
871 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
872 BootOrderListSize
+ sizeof (UINT16
),
875 if (!EFI_ERROR (Status
)) {
877 FreePool (NewBootOrderList
);
878 NewBootOrderList
= NULL
;
879 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
880 BootOptionMenu
.MenuNumber
++;
882 NvRamMap
->DescriptionData
[0] = 0x0000;
883 NvRamMap
->OptionalData
[0] = 0x0000;
890 This function update the "BootNext" EFI Variable. If there is
891 no "BootNext" specified in BMM, this EFI Variable is deleted.
892 It also update the BMM context data specified the "BootNext"
895 @param CallbackData The BMM context data.
897 @retval EFI_SUCCESS The function complete successfully.
898 @return The EFI variable can be saved. See gRT->SetVariable
899 for detail return information.
904 IN BMM_CALLBACK_DATA
*CallbackData
907 BM_MENU_ENTRY
*NewMenuEntry
;
908 BM_LOAD_CONTEXT
*NewLoadContext
;
909 BMM_FAKE_NV_DATA
*CurrentFakeNVMap
;
913 Status
= EFI_SUCCESS
;
914 CurrentFakeNVMap
= &CallbackData
->BmmFakeNvData
;
915 for (Index
= 0; Index
< BootOptionMenu
.MenuNumber
; Index
++) {
916 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
917 ASSERT (NULL
!= NewMenuEntry
);
919 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
920 NewLoadContext
->IsBootNext
= FALSE
;
923 if (CurrentFakeNVMap
->BootNext
== BootOptionMenu
.MenuNumber
) {
924 EfiLibDeleteVariable (L
"BootNext", &gEfiGlobalVariableGuid
);
928 NewMenuEntry
= BOpt_GetMenuEntry (
930 CurrentFakeNVMap
->BootNext
932 ASSERT (NewMenuEntry
!= NULL
);
934 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
935 Status
= gRT
->SetVariable (
937 &gEfiGlobalVariableGuid
,
938 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
940 &NewMenuEntry
->OptionNumber
942 NewLoadContext
->IsBootNext
= TRUE
;
943 CallbackData
->BmmOldFakeNVData
.BootNext
= CurrentFakeNVMap
->BootNext
;
948 This function update the "BootOrder" EFI Variable based on
949 BMM Formset's NV map. It then refresh BootOptionMenu
950 with the new "BootOrder" list.
952 @param CallbackData The BMM context data.
954 @retval EFI_SUCCESS The function complete successfully.
955 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
956 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
960 Var_UpdateBootOrder (
961 IN BMM_CALLBACK_DATA
*CallbackData
967 UINT16
*BootOrderList
;
968 UINTN BootOrderListSize
;
971 BootOrderList
= NULL
;
972 BootOrderListSize
= 0;
975 // First check whether BootOrder is present in current configuration
977 BootOrderList
= BdsLibGetVariableAndSize (
979 &gEfiGlobalVariableGuid
,
982 if (BootOrderList
== NULL
) {
983 return EFI_OUT_OF_RESOURCES
;
986 ASSERT (BootOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
988 for (OrderIndex
= 0; (OrderIndex
< BootOptionMenu
.MenuNumber
) && (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] != 0); OrderIndex
++) {
989 for (Index
= OrderIndex
; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
990 if ((BootOrderList
[Index
] == (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[OrderIndex
] - 1)) && (OrderIndex
!= Index
)) {
991 OptionNumber
= BootOrderList
[Index
];
992 CopyMem (&BootOrderList
[OrderIndex
+ 1], &BootOrderList
[OrderIndex
], (Index
- OrderIndex
) * sizeof (UINT16
));
993 BootOrderList
[OrderIndex
] = OptionNumber
;
998 Status
= gRT
->SetVariable (
1000 &gEfiGlobalVariableGuid
,
1001 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1006 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1008 ASSERT_EFI_ERROR (Status
);
1009 FreePool (BootOrderList
);
1011 GroupMultipleLegacyBootOption4SameType ();
1013 BOpt_FreeMenu (&BootOptionMenu
);
1014 BOpt_GetBootOptions (CallbackData
);
1021 This function update the "DriverOrder" EFI Variable based on
1022 BMM Formset's NV map. It then refresh DriverOptionMenu
1023 with the new "DriverOrder" list.
1025 @param CallbackData The BMM context data.
1027 @retval EFI_SUCCESS The function complete successfully.
1028 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
1029 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
1033 Var_UpdateDriverOrder (
1034 IN BMM_CALLBACK_DATA
*CallbackData
1039 UINT16
*DriverOrderList
;
1040 UINT16
*NewDriverOrderList
;
1041 UINTN DriverOrderListSize
;
1043 DriverOrderList
= NULL
;
1044 DriverOrderListSize
= 0;
1047 // First check whether DriverOrder is present in current configuration
1049 DriverOrderList
= BdsLibGetVariableAndSize (
1051 &gEfiGlobalVariableGuid
,
1052 &DriverOrderListSize
1055 NewDriverOrderList
= AllocateZeroPool (DriverOrderListSize
);
1057 if (NewDriverOrderList
== NULL
) {
1058 return EFI_OUT_OF_RESOURCES
;
1061 // If exists, delete it to hold new DriverOrder
1063 if (DriverOrderList
!= NULL
) {
1064 EfiLibDeleteVariable (L
"DriverOrder", &gEfiGlobalVariableGuid
);
1065 FreePool (DriverOrderList
);
1068 ASSERT (DriverOptionMenu
.MenuNumber
<= (sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
) / sizeof (CallbackData
->BmmFakeNvData
.OptionOrder
[0])));
1069 for (Index
= 0; Index
< DriverOptionMenu
.MenuNumber
; Index
++) {
1070 NewDriverOrderList
[Index
] = (UINT16
) (CallbackData
->BmmFakeNvData
.OptionOrder
[Index
] - 1);
1073 Status
= gRT
->SetVariable (
1075 &gEfiGlobalVariableGuid
,
1076 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1077 DriverOrderListSize
,
1081 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1083 ASSERT_EFI_ERROR (Status
);
1085 BOpt_FreeMenu (&DriverOptionMenu
);
1086 BOpt_GetDriverOptions (CallbackData
);
1091 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable
1092 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1095 @param CallbackData The context data for BMM.
1097 @return EFI_SUCCESS The function completed successfully.
1098 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.
1099 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource
1102 Var_UpdateBBSOption (
1103 IN BMM_CALLBACK_DATA
*CallbackData
1108 VOID
*BootOptionVar
;
1109 CHAR16 VarName
[100];
1113 BM_MENU_OPTION
*OptionMenu
;
1117 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1124 UINT16
*EnBootOption
;
1125 UINTN EnBootOptionCount
;
1126 UINT16
*DisBootOption
;
1127 UINTN DisBootOptionCount
;
1132 switch (CallbackData
->BmmPreviousPageId
) {
1133 case FORM_SET_FD_ORDER_ID
:
1134 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1135 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1136 CallbackData
->BbsType
= BBS_FLOPPY
;
1139 case FORM_SET_HD_ORDER_ID
:
1140 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1141 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1142 CallbackData
->BbsType
= BBS_HARDDISK
;
1145 case FORM_SET_CD_ORDER_ID
:
1146 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1147 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1148 CallbackData
->BbsType
= BBS_CDROM
;
1151 case FORM_SET_NET_ORDER_ID
:
1152 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1153 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1154 CallbackData
->BbsType
= BBS_EMBED_NETWORK
;
1158 ASSERT (FORM_SET_BEV_ORDER_ID
== CallbackData
->BmmPreviousPageId
);
1159 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1160 LegacyDev
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1161 CallbackData
->BbsType
= BBS_BEV_DEVICE
;
1165 DisMap
= CallbackData
->BmmOldFakeNVData
.DisableMap
;
1166 Status
= EFI_SUCCESS
;
1170 // Update the Variable "LegacyDevOrder"
1172 VarData
= (UINT8
*) BdsLibGetVariableAndSize (
1173 VAR_LEGACY_DEV_ORDER
,
1174 &gEfiLegacyDevOrderVariableGuid
,
1178 if (VarData
== NULL
) {
1179 return EFI_NOT_FOUND
;
1182 OriginalPtr
= VarData
;
1183 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1185 while (VarData
< OriginalPtr
+ VarSize
) {
1186 if (DevOrder
->BbsType
== CallbackData
->BbsType
) {
1190 VarData
+= sizeof (BBS_TYPE
) + DevOrder
->Length
;
1191 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) VarData
;
1194 if (VarData
>= OriginalPtr
+ VarSize
) {
1195 FreePool (OriginalPtr
);
1196 return EFI_NOT_FOUND
;
1199 NewOrder
= AllocateZeroPool (DevOrder
->Length
- sizeof (DevOrder
->Length
));
1200 if (NewOrder
== NULL
) {
1201 FreePool (OriginalPtr
);
1202 return EFI_OUT_OF_RESOURCES
;
1205 for (Index
= 0; Index
< OptionMenu
->MenuNumber
; Index
++) {
1206 if (0xFF == LegacyDev
[Index
]) {
1210 NewOrder
[Index
] = LegacyDev
[Index
];
1213 // Only the enable/disable state of each boot device with same device type can be changed,
1214 // so we can count on the index information in DevOrder.
1215 // DisMap bit array is the only reliable source to check a device's en/dis state,
1216 // so we use DisMap to set en/dis state of each item in NewOrder array
1218 for (Index2
= 0; Index2
< OptionMenu
->MenuNumber
; Index2
++) {
1219 Tmp
= (UINT16
) (DevOrder
->Data
[Index2
] & 0xFF);
1221 Bit
= 7 - (Tmp
% 8);
1222 if ((DisMap
[Pos
] & (1 << Bit
)) != 0) {
1223 NewOrder
[Index
] = (UINT16
) (0xFF00 | Tmp
);
1231 DevOrder
->Length
- sizeof (DevOrder
->Length
)
1233 FreePool (NewOrder
);
1235 Status
= gRT
->SetVariable (
1236 VAR_LEGACY_DEV_ORDER
,
1237 &gEfiLegacyDevOrderVariableGuid
,
1238 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1245 // Update BootOrder and Boot####.Attribute
1247 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
1249 ASSERT (OptionMenu
->MenuNumber
== DevOrder
->Length
/ sizeof (UINT16
) - 1);
1251 OrderLegacyBootOption4SameType (
1253 DevOrder
->Length
/ sizeof (UINT16
) - 1,
1261 // 2. Deactivate the DisBootOption and activate the EnBootOption
1263 for (Index
= 0; Index
< DisBootOptionCount
; Index
++) {
1264 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", DisBootOption
[Index
]);
1265 BootOptionVar
= BdsLibGetVariableAndSize (
1267 &gEfiGlobalVariableGuid
,
1270 if (BootOptionVar
!= NULL
) {
1271 Attribute
= (UINT32
*) BootOptionVar
;
1272 *Attribute
&= ~LOAD_OPTION_ACTIVE
;
1274 Status
= gRT
->SetVariable (
1276 &gEfiGlobalVariableGuid
,
1277 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1282 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1284 ASSERT_EFI_ERROR (Status
);
1286 FreePool (BootOptionVar
);
1290 for (Index
= 0; Index
< EnBootOptionCount
; Index
++) {
1291 UnicodeSPrint (VarName
, sizeof (VarName
), L
"Boot%04x", EnBootOption
[Index
]);
1292 BootOptionVar
= BdsLibGetVariableAndSize (
1294 &gEfiGlobalVariableGuid
,
1297 if (BootOptionVar
!= NULL
) {
1298 Attribute
= (UINT32
*) BootOptionVar
;
1299 *Attribute
|= LOAD_OPTION_ACTIVE
;
1301 Status
= gRT
->SetVariable (
1303 &gEfiGlobalVariableGuid
,
1304 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1309 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1311 ASSERT_EFI_ERROR (Status
);
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
);