]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/BootMaintenanceManagerUiLib/Variable.c
MdeModulePkg: Add ASSERT to make sure pointer 'OptionalData' not be NULL
[mirror_edk2.git] / MdeModulePkg / Library / BootMaintenanceManagerUiLib / Variable.c
1 /** @file
2 Variable operation that will be used by bootmaint
3
4 Copyright (c) 2004 - 2016, 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
9
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.
12
13 **/
14
15 #include "BootMaintenanceManager.h"
16
17 /**
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.
21
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.
26
27 **/
28 EFI_STATUS
29 Var_DelBootOption (
30 VOID
31 )
32 {
33 BM_MENU_ENTRY *NewMenuEntry;
34 BM_LOAD_CONTEXT *NewLoadContext;
35 UINT16 BootString[10];
36 EFI_STATUS Status;
37 UINTN Index;
38 UINTN Index2;
39
40 Status = EFI_SUCCESS;
41 Index2 = 0;
42 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
43 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));
44 if (NULL == NewMenuEntry) {
45 return EFI_NOT_FOUND;
46 }
47
48 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
49 if (!NewLoadContext->Deleted) {
50 continue;
51 }
52
53 UnicodeSPrint (
54 BootString,
55 sizeof (BootString),
56 L"Boot%04x",
57 NewMenuEntry->OptionNumber
58 );
59
60 EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);
61 Index2++;
62 //
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
66 //
67 if (NewLoadContext->IsBootNext) {
68 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
69 }
70
71 RemoveEntryList (&NewMenuEntry->Link);
72 BOpt_DestroyMenuEntry (NewMenuEntry);
73 NewMenuEntry = NULL;
74 }
75
76 BootOptionMenu.MenuNumber -= Index2;
77
78 Status = Var_ChangeBootOrder ();
79 return Status;
80 }
81
82 /**
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.
87
88
89
90
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.
94
95 **/
96 EFI_STATUS
97 Var_ChangeBootOrder (
98 VOID
99 )
100 {
101
102 EFI_STATUS Status;
103 BM_MENU_ENTRY *NewMenuEntry;
104 UINT16 *BootOrderList;
105 UINT16 *BootOrderListPtr;
106 UINTN BootOrderListSize;
107 UINTN Index;
108
109 BootOrderList = NULL;
110 BootOrderListSize = 0;
111 //
112 // First check whether BootOrder is present in current configuration
113 //
114 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
115
116 //
117 // If exists, delete it to hold new BootOrder
118 //
119 if (BootOrderList != NULL) {
120 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
121 FreePool (BootOrderList);
122 BootOrderList = NULL;
123 }
124 //
125 // Maybe here should be some check method to ensure that
126 // no new added boot options will be added
127 // but the setup engine now will give only one callback
128 // that is to say, user are granted only one chance to
129 // decide whether the boot option will be added or not
130 // there should be no indictor to show whether this
131 // is a "new" boot option
132 //
133 BootOrderListSize = BootOptionMenu.MenuNumber;
134
135 if (BootOrderListSize > 0) {
136 BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));
137 ASSERT (BootOrderList != NULL);
138 BootOrderListPtr = BootOrderList;
139
140 //
141 // Get all current used Boot#### from BootOptionMenu.
142 // OptionNumber in each BM_LOAD_OPTION is really its
143 // #### value.
144 //
145 for (Index = 0; Index < BootOrderListSize; Index++) {
146 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
147 *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
148 BootOrderList++;
149 }
150
151 BootOrderList = BootOrderListPtr;
152
153 //
154 // After building the BootOrderList, write it back
155 //
156 Status = gRT->SetVariable (
157 L"BootOrder",
158 &gEfiGlobalVariableGuid,
159 VAR_FLAG,
160 BootOrderListSize * sizeof (UINT16),
161 BootOrderList
162 );
163 if (EFI_ERROR (Status)) {
164 return Status;
165 }
166 }
167 return EFI_SUCCESS;
168 }
169
170 /**
171 Delete Load Option that represent a Deleted state in BootOptionMenu.
172 After deleting this Driver option, call Var_ChangeDriverOrder to
173 make sure DriverOrder is in valid state.
174
175 @retval EFI_SUCCESS Load Option is successfully updated.
176 @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
177 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
178 Variable.
179
180 **/
181 EFI_STATUS
182 Var_DelDriverOption (
183 VOID
184 )
185 {
186 BM_MENU_ENTRY *NewMenuEntry;
187 BM_LOAD_CONTEXT *NewLoadContext;
188 UINT16 DriverString[12];
189 EFI_STATUS Status;
190 UINTN Index;
191 UINTN Index2;
192
193 Status = EFI_SUCCESS;
194 Index2 = 0;
195 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
196 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
197 if (NULL == NewMenuEntry) {
198 return EFI_NOT_FOUND;
199 }
200
201 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
202 if (!NewLoadContext->Deleted) {
203 continue;
204 }
205
206 UnicodeSPrint (
207 DriverString,
208 sizeof (DriverString),
209 L"Driver%04x",
210 NewMenuEntry->OptionNumber
211 );
212
213 EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
214 Index2++;
215
216 RemoveEntryList (&NewMenuEntry->Link);
217 BOpt_DestroyMenuEntry (NewMenuEntry);
218 NewMenuEntry = NULL;
219 }
220
221 DriverOptionMenu.MenuNumber -= Index2;
222
223 Status = Var_ChangeDriverOrder ();
224 return Status;
225 }
226
227 /**
228 After any operation on Driver####, there will be a discrepancy in
229 DriverOrder. Since some are missing but in DriverOrder, while some
230 are present but are not reflected by DriverOrder. Then a function
231 rebuild DriverOrder from scratch by content from DriverOptionMenu is
232 needed.
233
234 @retval EFI_SUCCESS The driver order is updated successfully.
235 @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
236
237 **/
238 EFI_STATUS
239 Var_ChangeDriverOrder (
240 VOID
241 )
242 {
243 EFI_STATUS Status;
244 BM_MENU_ENTRY *NewMenuEntry;
245 UINT16 *DriverOrderList;
246 UINT16 *DriverOrderListPtr;
247 UINTN DriverOrderListSize;
248 UINTN Index;
249
250 DriverOrderList = NULL;
251 DriverOrderListSize = 0;
252
253 //
254 // First check whether DriverOrder is present in current configuration
255 //
256 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
257 //
258 // If exists, delete it to hold new DriverOrder
259 //
260 if (DriverOrderList != NULL) {
261 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
262 FreePool (DriverOrderList);
263 DriverOrderList = NULL;
264 }
265
266 DriverOrderListSize = DriverOptionMenu.MenuNumber;
267
268 if (DriverOrderListSize > 0) {
269 DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
270 ASSERT (DriverOrderList != NULL);
271 DriverOrderListPtr = DriverOrderList;
272
273 //
274 // Get all current used Driver#### from DriverOptionMenu.
275 // OptionNumber in each BM_LOAD_OPTION is really its
276 // #### value.
277 //
278 for (Index = 0; Index < DriverOrderListSize; Index++) {
279 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
280 *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
281 DriverOrderList++;
282 }
283
284 DriverOrderList = DriverOrderListPtr;
285
286 //
287 // After building the DriverOrderList, write it back
288 //
289 Status = gRT->SetVariable (
290 L"DriverOrder",
291 &gEfiGlobalVariableGuid,
292 VAR_FLAG,
293 DriverOrderListSize * sizeof (UINT16),
294 DriverOrderList
295 );
296 if (EFI_ERROR (Status)) {
297 return Status;
298 }
299 }
300 return EFI_SUCCESS;
301 }
302
303 /**
304 Update the device path of "ConOut", "ConIn" and "ErrOut"
305 based on the new BaudRate, Data Bits, parity and Stop Bits
306 set.
307
308 **/
309 VOID
310 Var_UpdateAllConsoleOption (
311 VOID
312 )
313 {
314 EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
315 EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
316 EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
317 EFI_STATUS Status;
318
319 GetEfiGlobalVariable2 (L"ConOut", (VOID**)&OutDevicePath, NULL);
320 GetEfiGlobalVariable2 (L"ConIn", (VOID**)&InpDevicePath, NULL);
321 GetEfiGlobalVariable2 (L"ErrOut", (VOID**)&ErrDevicePath, NULL);
322 if (OutDevicePath != NULL) {
323 ChangeVariableDevicePath (OutDevicePath);
324 Status = gRT->SetVariable (
325 L"ConOut",
326 &gEfiGlobalVariableGuid,
327 VAR_FLAG,
328 GetDevicePathSize (OutDevicePath),
329 OutDevicePath
330 );
331 ASSERT (!EFI_ERROR (Status));
332 }
333
334 if (InpDevicePath != NULL) {
335 ChangeVariableDevicePath (InpDevicePath);
336 Status = gRT->SetVariable (
337 L"ConIn",
338 &gEfiGlobalVariableGuid,
339 VAR_FLAG,
340 GetDevicePathSize (InpDevicePath),
341 InpDevicePath
342 );
343 ASSERT (!EFI_ERROR (Status));
344 }
345
346 if (ErrDevicePath != NULL) {
347 ChangeVariableDevicePath (ErrDevicePath);
348 Status = gRT->SetVariable (
349 L"ErrOut",
350 &gEfiGlobalVariableGuid,
351 VAR_FLAG,
352 GetDevicePathSize (ErrDevicePath),
353 ErrDevicePath
354 );
355 ASSERT (!EFI_ERROR (Status));
356 }
357 }
358
359 /**
360 This function delete and build multi-instance device path for
361 specified type of console device.
362
363 This function clear the EFI variable defined by ConsoleName and
364 gEfiGlobalVariableGuid. It then build the multi-instance device
365 path by appending the device path of the Console (In/Out/Err) instance
366 in ConsoleMenu. Then it scan all corresponding console device by
367 scanning Terminal (built from device supporting Serial I/O instances)
368 devices in TerminalMenu. At last, it save a EFI variable specifed
369 by ConsoleName and gEfiGlobalVariableGuid.
370
371 @param ConsoleName The name for the console device type. They are
372 usually "ConIn", "ConOut" and "ErrOut".
373 @param ConsoleMenu The console memu which is a list of console devices.
374 @param UpdatePageId The flag specifying which type of console device
375 to be processed.
376
377 @retval EFI_SUCCESS The function complete successfully.
378 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
379
380 **/
381 EFI_STATUS
382 Var_UpdateConsoleOption (
383 IN UINT16 *ConsoleName,
384 IN BM_MENU_OPTION *ConsoleMenu,
385 IN UINT16 UpdatePageId
386 )
387 {
388 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
389 BM_MENU_ENTRY *NewMenuEntry;
390 BM_CONSOLE_CONTEXT *NewConsoleContext;
391 BM_TERMINAL_CONTEXT *NewTerminalContext;
392 EFI_STATUS Status;
393 VENDOR_DEVICE_PATH Vendor;
394 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
395 UINTN Index;
396
397 GetEfiGlobalVariable2 (ConsoleName, (VOID**)&ConDevicePath, NULL);
398 if (ConDevicePath != NULL) {
399 EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
400 FreePool (ConDevicePath);
401 ConDevicePath = NULL;
402 };
403
404 //
405 // First add all console input device from console input menu
406 //
407 for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
408 NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
409
410 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
411 if (NewConsoleContext->IsActive) {
412 ConDevicePath = AppendDevicePathInstance (
413 ConDevicePath,
414 NewConsoleContext->DevicePath
415 );
416 }
417 }
418
419 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
420 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
421
422 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
423 if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
424 ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
425 ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
426 ) {
427 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
428 Vendor.Header.SubType = MSG_VENDOR_DP;
429
430 ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])));
431 CopyMem (
432 &Vendor.Guid,
433 &TerminalTypeGuid[NewTerminalContext->TerminalType],
434 sizeof (EFI_GUID)
435 );
436 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
437 TerminalDevicePath = AppendDevicePathNode (
438 NewTerminalContext->DevicePath,
439 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
440 );
441 ASSERT (TerminalDevicePath != NULL);
442 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
443 ConDevicePath = AppendDevicePathInstance (
444 ConDevicePath,
445 TerminalDevicePath
446 );
447 }
448 }
449
450 if (ConDevicePath != NULL) {
451 Status = gRT->SetVariable (
452 ConsoleName,
453 &gEfiGlobalVariableGuid,
454 VAR_FLAG,
455 GetDevicePathSize (ConDevicePath),
456 ConDevicePath
457 );
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461 }
462
463 return EFI_SUCCESS;
464
465 }
466
467 /**
468 This function delete and build multi-instance device path ConIn
469 console device.
470
471 @retval EFI_SUCCESS The function complete successfully.
472 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
473 **/
474 EFI_STATUS
475 Var_UpdateConsoleInpOption (
476 VOID
477 )
478 {
479 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
480 }
481
482 /**
483 This function delete and build multi-instance device path ConOut
484 console device.
485
486 @retval EFI_SUCCESS The function complete successfully.
487 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
488 **/
489 EFI_STATUS
490 Var_UpdateConsoleOutOption (
491 VOID
492 )
493 {
494 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
495 }
496
497 /**
498 This function delete and build multi-instance device path ErrOut
499 console device.
500
501 @retval EFI_SUCCESS The function complete successfully.
502 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
503 **/
504 EFI_STATUS
505 Var_UpdateErrorOutOption (
506 VOID
507 )
508 {
509 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
510 }
511
512 /**
513 This function create a currently loaded Drive Option from
514 the BMM. It then appends this Driver Option to the end of
515 the "DriverOrder" list. It append this Driver Opotion to the end
516 of DriverOptionMenu.
517
518 @param CallbackData The BMM context data.
519 @param HiiHandle The HII handle associated with the BMM formset.
520 @param DescriptionData The description of this driver option.
521 @param OptionalData The optional load option.
522 @param ForceReconnect If to force reconnect.
523
524 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
525 @retval EFI_SUCCESS If function completes successfully.
526
527 **/
528 EFI_STATUS
529 Var_UpdateDriverOption (
530 IN BMM_CALLBACK_DATA *CallbackData,
531 IN EFI_HII_HANDLE HiiHandle,
532 IN UINT16 *DescriptionData,
533 IN UINT16 *OptionalData,
534 IN UINT8 ForceReconnect
535 )
536 {
537 UINT16 Index;
538 UINT16 DriverString[12];
539 BM_MENU_ENTRY *NewMenuEntry;
540 BM_LOAD_CONTEXT *NewLoadContext;
541 BOOLEAN OptionalDataExist;
542 EFI_STATUS Status;
543 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
544 UINT8 *OptionalDesData;
545 UINT32 OptionalDataSize;
546
547 OptionalDataExist = FALSE;
548 OptionalDesData = NULL;
549 OptionalDataSize = 0;
550
551 Index = BOpt_GetDriverOptionNumber ();
552 UnicodeSPrint (
553 DriverString,
554 sizeof (DriverString),
555 L"Driver%04x",
556 Index
557 );
558
559 if (*DescriptionData == 0x0000) {
560 StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);
561 }
562
563 if (*OptionalData != 0x0000) {
564 OptionalDataExist = TRUE;
565 OptionalDesData = (UINT8 *)OptionalData;
566 OptionalDataSize = (UINT32)StrSize (OptionalData);
567 }
568
569 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
570 if (NULL == NewMenuEntry) {
571 return EFI_OUT_OF_RESOURCES;
572 }
573
574 Status = EfiBootManagerInitializeLoadOption (
575 &LoadOption,
576 Index,
577 LoadOptionTypeDriver,
578 LOAD_OPTION_ACTIVE | (ForceReconnect << 1),
579 DescriptionData,
580 CallbackData->LoadContext->FilePathList,
581 OptionalDesData,
582 OptionalDataSize
583 );
584 if (!EFI_ERROR (Status)){
585 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );
586 }
587
588 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
589 NewLoadContext->Deleted = FALSE;
590 NewLoadContext->Attributes = LoadOption.Attributes;
591 NewLoadContext->FilePathListLength = (UINT16)GetDevicePathSize (LoadOption.FilePath);
592
593 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
594 ASSERT (NewLoadContext->Description != NULL);
595 NewMenuEntry->DisplayString = NewLoadContext->Description;
596 CopyMem (
597 NewLoadContext->Description,
598 LoadOption.Description,
599 StrSize (DescriptionData)
600 );
601
602 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
603 ASSERT (NewLoadContext->FilePathList != NULL);
604 CopyMem (
605 NewLoadContext->FilePathList,
606 LoadOption.FilePath,
607 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
608 );
609
610 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
611 NewMenuEntry->OptionNumber = Index;
612 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);
613 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);
614
615 if (OptionalDataExist) {
616 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);
617 ASSERT (NewLoadContext->OptionalData != NULL);
618 CopyMem (
619 NewLoadContext->OptionalData,
620 LoadOption.OptionalData,
621 LoadOption.OptionalDataSize
622 );
623 }
624
625 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
626 DriverOptionMenu.MenuNumber++;
627
628 EfiBootManagerFreeLoadOption(&LoadOption);
629
630 return EFI_SUCCESS;
631 }
632
633 /**
634 This function create a currently loaded Boot Option from
635 the BMM. It then appends this Boot Option to the end of
636 the "BootOrder" list. It also append this Boot Opotion to the end
637 of BootOptionMenu.
638
639 @param CallbackData The BMM context data.
640
641 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
642 @retval EFI_SUCCESS If function completes successfully.
643
644 **/
645 EFI_STATUS
646 Var_UpdateBootOption (
647 IN BMM_CALLBACK_DATA *CallbackData
648 )
649 {
650 UINT16 BootString[10];
651 UINT16 Index;
652 BM_MENU_ENTRY *NewMenuEntry;
653 BM_LOAD_CONTEXT *NewLoadContext;
654 BOOLEAN OptionalDataExist;
655 EFI_STATUS Status;
656 BMM_FAKE_NV_DATA *NvRamMap;
657 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
658 UINT8 *OptionalData;
659 UINT32 OptionalDataSize;
660
661 OptionalDataExist = FALSE;
662 NvRamMap = &CallbackData->BmmFakeNvData;
663 OptionalData = NULL;
664 OptionalDataSize = 0;
665
666 Index = BOpt_GetBootOptionNumber () ;
667 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
668
669 if (NvRamMap->BootDescriptionData[0] == 0x0000) {
670 StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString);
671 }
672
673 if (NvRamMap->BootOptionalData[0] != 0x0000) {
674 OptionalDataExist = TRUE;
675 OptionalData = (UINT8 *)NvRamMap->BootOptionalData;
676 OptionalDataSize = (UINT32)StrSize (NvRamMap->BootOptionalData);
677 }
678
679 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
680 if (NULL == NewMenuEntry) {
681 return EFI_OUT_OF_RESOURCES;
682 }
683
684 Status = EfiBootManagerInitializeLoadOption (
685 &LoadOption,
686 Index,
687 LoadOptionTypeBoot,
688 LOAD_OPTION_ACTIVE,
689 NvRamMap->BootDescriptionData,
690 CallbackData->LoadContext->FilePathList,
691 OptionalData,
692 OptionalDataSize
693 );
694 if (!EFI_ERROR (Status)){
695 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );
696 }
697
698 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
699 NewLoadContext->Deleted = FALSE;
700 NewLoadContext->Attributes = LoadOption.Attributes;
701 NewLoadContext->FilePathListLength = (UINT16) GetDevicePathSize (LoadOption.FilePath);
702
703 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));
704 ASSERT (NewLoadContext->Description != NULL);
705
706 NewMenuEntry->DisplayString = NewLoadContext->Description;
707
708 CopyMem (
709 NewLoadContext->Description,
710 LoadOption.Description,
711 StrSize (NvRamMap->BootDescriptionData)
712 );
713
714 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
715 ASSERT (NewLoadContext->FilePathList != NULL);
716 CopyMem (
717 NewLoadContext->FilePathList,
718 LoadOption.FilePath,
719 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
720 );
721
722 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
723 NewMenuEntry->OptionNumber = Index;
724 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
725 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
726
727 if (OptionalDataExist) {
728 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);
729 ASSERT (NewLoadContext->OptionalData != NULL);
730 CopyMem (
731 NewLoadContext->OptionalData,
732 LoadOption.OptionalData,
733 LoadOption.OptionalDataSize
734 );
735 }
736
737 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
738 BootOptionMenu.MenuNumber++;
739
740 EfiBootManagerFreeLoadOption(&LoadOption);
741
742 return EFI_SUCCESS;
743 }
744
745 /**
746 This function update the "BootNext" EFI Variable. If there is
747 no "BootNext" specified in BMM, this EFI Variable is deleted.
748 It also update the BMM context data specified the "BootNext"
749 vaule.
750
751 @param CallbackData The BMM context data.
752
753 @retval EFI_SUCCESS The function complete successfully.
754 @return The EFI variable can be saved. See gRT->SetVariable
755 for detail return information.
756
757 **/
758 EFI_STATUS
759 Var_UpdateBootNext (
760 IN BMM_CALLBACK_DATA *CallbackData
761 )
762 {
763 BM_MENU_ENTRY *NewMenuEntry;
764 BM_LOAD_CONTEXT *NewLoadContext;
765 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
766 UINT16 Index;
767 EFI_STATUS Status;
768
769 Status = EFI_SUCCESS;
770 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
771 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
772 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
773 ASSERT (NULL != NewMenuEntry);
774
775 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
776 NewLoadContext->IsBootNext = FALSE;
777 }
778
779 if (CurrentFakeNVMap->BootNext == NONE_BOOTNEXT_VALUE) {
780 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
781 return EFI_SUCCESS;
782 }
783
784 NewMenuEntry = BOpt_GetMenuEntry (
785 &BootOptionMenu,
786 CurrentFakeNVMap->BootNext
787 );
788 ASSERT (NewMenuEntry != NULL);
789
790 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
791 Status = gRT->SetVariable (
792 L"BootNext",
793 &gEfiGlobalVariableGuid,
794 VAR_FLAG,
795 sizeof (UINT16),
796 &NewMenuEntry->OptionNumber
797 );
798 NewLoadContext->IsBootNext = TRUE;
799 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
800 return Status;
801 }
802
803 /**
804 This function update the "BootOrder" EFI Variable based on
805 BMM Formset's NV map. It then refresh BootOptionMenu
806 with the new "BootOrder" list.
807
808 @param CallbackData The BMM context data.
809
810 @retval EFI_SUCCESS The function complete successfully.
811 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
812 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
813
814 **/
815 EFI_STATUS
816 Var_UpdateBootOrder (
817 IN BMM_CALLBACK_DATA *CallbackData
818 )
819 {
820 EFI_STATUS Status;
821 UINT16 Index;
822 UINT16 OrderIndex;
823 UINT16 *BootOrder;
824 UINTN BootOrderSize;
825 UINT16 OptionNumber;
826
827 //
828 // First check whether BootOrder is present in current configuration
829 //
830 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
831 if (BootOrder == NULL) {
832 return EFI_OUT_OF_RESOURCES;
833 }
834
835 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));
836
837 //
838 // OptionOrder is subset of BootOrder
839 //
840 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {
841 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {
842 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {
843 OptionNumber = BootOrder[Index];
844 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));
845 BootOrder[OrderIndex] = OptionNumber;
846 }
847 }
848 }
849
850 Status = gRT->SetVariable (
851 L"BootOrder",
852 &gEfiGlobalVariableGuid,
853 VAR_FLAG,
854 BootOrderSize,
855 BootOrder
856 );
857 FreePool (BootOrder);
858
859 BOpt_FreeMenu (&BootOptionMenu);
860 BOpt_GetBootOptions (CallbackData);
861
862 return Status;
863
864 }
865
866 /**
867 This function update the "DriverOrder" EFI Variable based on
868 BMM Formset's NV map. It then refresh DriverOptionMenu
869 with the new "DriverOrder" list.
870
871 @param CallbackData The BMM context data.
872
873 @retval EFI_SUCCESS The function complete successfully.
874 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
875 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
876
877 **/
878 EFI_STATUS
879 Var_UpdateDriverOrder (
880 IN BMM_CALLBACK_DATA *CallbackData
881 )
882 {
883 EFI_STATUS Status;
884 UINT16 Index;
885 UINT16 *DriverOrderList;
886 UINT16 *NewDriverOrderList;
887 UINTN DriverOrderListSize;
888
889 DriverOrderList = NULL;
890 DriverOrderListSize = 0;
891
892 //
893 // First check whether DriverOrder is present in current configuration
894 //
895 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
896 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
897
898 if (NewDriverOrderList == NULL) {
899 return EFI_OUT_OF_RESOURCES;
900 }
901 //
902 // If exists, delete it to hold new DriverOrder
903 //
904 if (DriverOrderList != NULL) {
905 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
906 FreePool (DriverOrderList);
907 }
908
909 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));
910 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
911 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);
912 }
913
914 Status = gRT->SetVariable (
915 L"DriverOrder",
916 &gEfiGlobalVariableGuid,
917 VAR_FLAG,
918 DriverOrderListSize,
919 NewDriverOrderList
920 );
921 if (EFI_ERROR (Status)) {
922 return Status;
923 }
924
925 BOpt_FreeMenu (&DriverOptionMenu);
926 BOpt_GetDriverOptions (CallbackData);
927 return EFI_SUCCESS;
928 }
929
930 /**
931 Update the Text Mode of Console.
932
933 @param CallbackData The context data for BMM.
934
935 @retval EFI_SUCCSS If the Text Mode of Console is updated.
936 @return Other value if the Text Mode of Console is not updated.
937
938 **/
939 EFI_STATUS
940 Var_UpdateConMode (
941 IN BMM_CALLBACK_DATA *CallbackData
942 )
943 {
944 EFI_STATUS Status;
945 UINTN Mode;
946 CONSOLE_OUT_MODE ModeInfo;
947
948 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
949
950 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
951 if (!EFI_ERROR(Status)) {
952 Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);
953 if (!EFI_ERROR (Status)) {
954 Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row);
955 }
956 }
957
958 return Status;
959 }