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