]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/UiApp/BootMaint/Variable.c
NetworkPkg: Fix DHCP TransmitReceive EFI_NO_MAPPING return in DnsDxe
[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
528 **/
529 EFI_STATUS
530 Var_UpdateDriverOption (
531 IN BMM_CALLBACK_DATA *CallbackData,
532 IN EFI_HII_HANDLE HiiHandle,
533 IN UINT16 *DescriptionData,
534 IN UINT16 *OptionalData,
535 IN UINT8 ForceReconnect
536 )
537 {
538 UINT16 Index;
539 UINT16 *DriverOrderList;
540 UINT16 *NewDriverOrderList;
541 UINT16 DriverString[12];
542 UINTN DriverOrderListSize;
543 VOID *Buffer;
544 UINTN BufferSize;
545 UINT8 *Ptr;
546 BM_MENU_ENTRY *NewMenuEntry;
547 BM_LOAD_CONTEXT *NewLoadContext;
548 BOOLEAN OptionalDataExist;
549 EFI_STATUS Status;
550
551 OptionalDataExist = FALSE;
552
553 Index = BOpt_GetDriverOptionNumber ();
554 UnicodeSPrint (
555 DriverString,
556 sizeof (DriverString),
557 L"Driver%04x",
558 Index
559 );
560
561 if (*DescriptionData == 0x0000) {
562 StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);
563 }
564
565 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);
566 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
567
568 if (*OptionalData != 0x0000) {
569 OptionalDataExist = TRUE;
570 BufferSize += StrSize (OptionalData);
571 }
572
573 Buffer = AllocateZeroPool (BufferSize);
574 if (NULL == Buffer) {
575 return EFI_OUT_OF_RESOURCES;
576 }
577
578 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
579 if (NULL == NewMenuEntry) {
580 FreePool (Buffer);
581 return EFI_OUT_OF_RESOURCES;
582 }
583
584 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
585 NewLoadContext->Deleted = FALSE;
586 NewLoadContext->LoadOptionSize = BufferSize;
587 Ptr = (UINT8 *) Buffer;
588 NewLoadContext->LoadOption = Ptr;
589 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
590 NewLoadContext->Attributes = *((UINT32 *) Ptr);
591 NewLoadContext->IsActive = TRUE;
592 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
593
594 Ptr += sizeof (UINT32);
595 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
596 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
597
598 Ptr += sizeof (UINT16);
599 CopyMem (
600 Ptr,
601 DescriptionData,
602 StrSize (DescriptionData)
603 );
604
605 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
606 ASSERT (NewLoadContext->Description != NULL);
607 NewMenuEntry->DisplayString = NewLoadContext->Description;
608 CopyMem (
609 NewLoadContext->Description,
610 (VOID *) Ptr,
611 StrSize (DescriptionData)
612 );
613
614 Ptr += StrSize (DescriptionData);
615 CopyMem (
616 Ptr,
617 CallbackData->LoadContext->FilePathList,
618 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
619 );
620
621 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
622 ASSERT (NewLoadContext->FilePathList != NULL);
623
624 CopyMem (
625 NewLoadContext->FilePathList,
626 (VOID *) Ptr,
627 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
628 );
629
630 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
631 NewMenuEntry->OptionNumber = Index;
632 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
633 CallbackData,
634 DriverOptionStrDepository
635 );
636 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);
637
638 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
639 CallbackData,
640 DriverOptionHelpStrDepository
641 );
642 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);
643
644 if (OptionalDataExist) {
645 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
646
647 CopyMem (
648 Ptr,
649 OptionalData,
650 StrSize (OptionalData)
651 );
652 }
653
654 Status = gRT->SetVariable (
655 DriverString,
656 &gEfiGlobalVariableGuid,
657 VAR_FLAG,
658 BufferSize,
659 Buffer
660 );
661 ASSERT_EFI_ERROR (Status);
662 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
663 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
664 ASSERT (NewDriverOrderList != NULL);
665 if (DriverOrderList != NULL){
666 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
667 }
668 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
669 if (DriverOrderList != NULL) {
670 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
671 }
672
673 Status = gRT->SetVariable (
674 L"DriverOrder",
675 &gEfiGlobalVariableGuid,
676 VAR_FLAG,
677 DriverOrderListSize + sizeof (UINT16),
678 NewDriverOrderList
679 );
680 ASSERT_EFI_ERROR (Status);
681 if (DriverOrderList != NULL) {
682 FreePool (DriverOrderList);
683 }
684 DriverOrderList = NULL;
685 FreePool (NewDriverOrderList);
686 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
687 DriverOptionMenu.MenuNumber++;
688
689 *DescriptionData = 0x0000;
690 *OptionalData = 0x0000;
691 return EFI_SUCCESS;
692 }
693
694 /**
695 This function create a currently loaded Boot Option from
696 the BMM. It then appends this Boot Option to the end of
697 the "BootOrder" list. It also append this Boot Opotion to the end
698 of BootOptionMenu.
699
700 @param CallbackData The BMM context data.
701 @param NvRamMap The file explorer formset internal state.
702
703 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
704 @retval EFI_SUCCESS If function completes successfully.
705
706 **/
707 EFI_STATUS
708 Var_UpdateBootOption (
709 IN BMM_CALLBACK_DATA *CallbackData,
710 IN FILE_EXPLORER_NV_DATA *NvRamMap
711 )
712 {
713 UINT16 *BootOrderList;
714 UINT16 *NewBootOrderList;
715 UINTN BootOrderListSize;
716 UINT16 BootString[10];
717 VOID *Buffer;
718 UINTN BufferSize;
719 UINT8 *Ptr;
720 UINT16 Index;
721 BM_MENU_ENTRY *NewMenuEntry;
722 BM_LOAD_CONTEXT *NewLoadContext;
723 BOOLEAN OptionalDataExist;
724 EFI_STATUS Status;
725
726 OptionalDataExist = FALSE;
727
728 Index = BOpt_GetBootOptionNumber () ;
729 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
730
731 if (NvRamMap->DescriptionData[0] == 0x0000) {
732 StrCpyS (NvRamMap->DescriptionData, sizeof (NvRamMap->DescriptionData) / sizeof (NvRamMap->DescriptionData[0]), BootString);
733 }
734
735 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);
736 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
737
738 if (NvRamMap->OptionalData[0] != 0x0000) {
739 OptionalDataExist = TRUE;
740 BufferSize += StrSize (NvRamMap->OptionalData);
741 }
742
743 Buffer = AllocateZeroPool (BufferSize);
744 if (NULL == Buffer) {
745 return EFI_OUT_OF_RESOURCES;
746 }
747
748 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
749 if (NULL == NewMenuEntry) {
750 return EFI_OUT_OF_RESOURCES;
751 }
752
753 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
754 NewLoadContext->Deleted = FALSE;
755 NewLoadContext->LoadOptionSize = BufferSize;
756 Ptr = (UINT8 *) Buffer;
757 NewLoadContext->LoadOption = Ptr;
758 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
759 NewLoadContext->Attributes = *((UINT32 *) Ptr);
760 NewLoadContext->IsActive = TRUE;
761 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
762
763 Ptr += sizeof (UINT32);
764 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
765 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
766 Ptr += sizeof (UINT16);
767
768 CopyMem (
769 Ptr,
770 NvRamMap->DescriptionData,
771 StrSize (NvRamMap->DescriptionData)
772 );
773
774 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));
775 ASSERT (NewLoadContext->Description != NULL);
776
777 NewMenuEntry->DisplayString = NewLoadContext->Description;
778 CopyMem (
779 NewLoadContext->Description,
780 (VOID *) Ptr,
781 StrSize (NvRamMap->DescriptionData)
782 );
783
784 Ptr += StrSize (NvRamMap->DescriptionData);
785 CopyMem (
786 Ptr,
787 CallbackData->LoadContext->FilePathList,
788 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
789 );
790
791 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
792 ASSERT (NewLoadContext->FilePathList != NULL);
793
794 CopyMem (
795 NewLoadContext->FilePathList,
796 (VOID *) Ptr,
797 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
798 );
799
800 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
801 NewMenuEntry->OptionNumber = Index;
802 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
803 CallbackData,
804 BootOptionStrDepository
805 );
806 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
807
808 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
809 CallbackData,
810 BootOptionHelpStrDepository
811 );
812 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL);
813
814 if (OptionalDataExist) {
815 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
816
817 CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
818 }
819
820 Status = gRT->SetVariable (
821 BootString,
822 &gEfiGlobalVariableGuid,
823 VAR_FLAG,
824 BufferSize,
825 Buffer
826 );
827 ASSERT_EFI_ERROR (Status);
828
829 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
830 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
831 ASSERT (NewBootOrderList != NULL);
832 if (BootOrderList != NULL){
833 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
834 }
835 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
836
837 if (BootOrderList != NULL) {
838 FreePool (BootOrderList);
839 }
840
841 Status = gRT->SetVariable (
842 L"BootOrder",
843 &gEfiGlobalVariableGuid,
844 VAR_FLAG,
845 BootOrderListSize + sizeof (UINT16),
846 NewBootOrderList
847 );
848 ASSERT_EFI_ERROR (Status);
849
850 FreePool (NewBootOrderList);
851 NewBootOrderList = NULL;
852 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
853 BootOptionMenu.MenuNumber++;
854
855 NvRamMap->DescriptionData[0] = 0x0000;
856 NvRamMap->OptionalData[0] = 0x0000;
857 return EFI_SUCCESS;
858 }
859
860 /**
861 This function update the "BootNext" EFI Variable. If there is
862 no "BootNext" specified in BMM, this EFI Variable is deleted.
863 It also update the BMM context data specified the "BootNext"
864 vaule.
865
866 @param CallbackData The BMM context data.
867
868 @retval EFI_SUCCESS The function complete successfully.
869 @return The EFI variable can be saved. See gRT->SetVariable
870 for detail return information.
871
872 **/
873 EFI_STATUS
874 Var_UpdateBootNext (
875 IN BMM_CALLBACK_DATA *CallbackData
876 )
877 {
878 BM_MENU_ENTRY *NewMenuEntry;
879 BM_LOAD_CONTEXT *NewLoadContext;
880 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
881 UINT16 Index;
882 EFI_STATUS Status;
883
884 Status = EFI_SUCCESS;
885 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
886 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
887 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
888 ASSERT (NULL != NewMenuEntry);
889
890 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
891 NewLoadContext->IsBootNext = FALSE;
892 }
893
894 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
895 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
896 return EFI_SUCCESS;
897 }
898
899 NewMenuEntry = BOpt_GetMenuEntry (
900 &BootOptionMenu,
901 CurrentFakeNVMap->BootNext
902 );
903 ASSERT (NewMenuEntry != NULL);
904
905 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
906 Status = gRT->SetVariable (
907 L"BootNext",
908 &gEfiGlobalVariableGuid,
909 VAR_FLAG,
910 sizeof (UINT16),
911 &NewMenuEntry->OptionNumber
912 );
913 NewLoadContext->IsBootNext = TRUE;
914 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
915 return Status;
916 }
917
918 /**
919 This function update the "BootOrder" EFI Variable based on
920 BMM Formset's NV map. It then refresh BootOptionMenu
921 with the new "BootOrder" list.
922
923 @param CallbackData The BMM context data.
924
925 @retval EFI_SUCCESS The function complete successfully.
926 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
927 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
928
929 **/
930 EFI_STATUS
931 Var_UpdateBootOrder (
932 IN BMM_CALLBACK_DATA *CallbackData
933 )
934 {
935 EFI_STATUS Status;
936 UINT16 Index;
937 UINT16 OrderIndex;
938 UINT16 *BootOrder;
939 UINTN BootOrderSize;
940 UINT16 OptionNumber;
941
942 //
943 // First check whether BootOrder is present in current configuration
944 //
945 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
946 if (BootOrder == NULL) {
947 return EFI_OUT_OF_RESOURCES;
948 }
949
950 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));
951
952 //
953 // OptionOrder is subset of BootOrder
954 //
955 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {
956 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {
957 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {
958 OptionNumber = BootOrder[Index];
959 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));
960 BootOrder[OrderIndex] = OptionNumber;
961 }
962 }
963 }
964
965 Status = gRT->SetVariable (
966 L"BootOrder",
967 &gEfiGlobalVariableGuid,
968 VAR_FLAG,
969 BootOrderSize,
970 BootOrder
971 );
972 FreePool (BootOrder);
973
974 BOpt_FreeMenu (&BootOptionMenu);
975 BOpt_GetBootOptions (CallbackData);
976
977 return Status;
978
979 }
980
981 /**
982 This function update the "DriverOrder" EFI Variable based on
983 BMM Formset's NV map. It then refresh DriverOptionMenu
984 with the new "DriverOrder" list.
985
986 @param CallbackData The BMM context data.
987
988 @retval EFI_SUCCESS The function complete successfully.
989 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
990 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
991
992 **/
993 EFI_STATUS
994 Var_UpdateDriverOrder (
995 IN BMM_CALLBACK_DATA *CallbackData
996 )
997 {
998 EFI_STATUS Status;
999 UINT16 Index;
1000 UINT16 *DriverOrderList;
1001 UINT16 *NewDriverOrderList;
1002 UINTN DriverOrderListSize;
1003
1004 DriverOrderList = NULL;
1005 DriverOrderListSize = 0;
1006
1007 //
1008 // First check whether DriverOrder is present in current configuration
1009 //
1010 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
1011 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
1012
1013 if (NewDriverOrderList == NULL) {
1014 return EFI_OUT_OF_RESOURCES;
1015 }
1016 //
1017 // If exists, delete it to hold new DriverOrder
1018 //
1019 if (DriverOrderList != NULL) {
1020 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
1021 FreePool (DriverOrderList);
1022 }
1023
1024 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));
1025 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
1026 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);
1027 }
1028
1029 Status = gRT->SetVariable (
1030 L"DriverOrder",
1031 &gEfiGlobalVariableGuid,
1032 VAR_FLAG,
1033 DriverOrderListSize,
1034 NewDriverOrderList
1035 );
1036 if (EFI_ERROR (Status)) {
1037 return Status;
1038 }
1039
1040 BOpt_FreeMenu (&DriverOptionMenu);
1041 BOpt_GetDriverOptions (CallbackData);
1042 return EFI_SUCCESS;
1043 }
1044
1045 /**
1046 Update the Text Mode of Console.
1047
1048 @param CallbackData The context data for BMM.
1049
1050 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1051 @return Other value if the Text Mode of Console is not updated.
1052
1053 **/
1054 EFI_STATUS
1055 Var_UpdateConMode (
1056 IN BMM_CALLBACK_DATA *CallbackData
1057 )
1058 {
1059 EFI_STATUS Status;
1060 UINTN Mode;
1061 CONSOLE_OUT_MODE ModeInfo;
1062
1063 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
1064
1065 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
1066 if (!EFI_ERROR(Status)) {
1067 PcdSet32 (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);
1068 PcdSet32 (PcdSetupConOutRow, (UINT32) ModeInfo.Row);
1069 }
1070
1071 return EFI_SUCCESS;
1072 }