]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
Clean up BootMaint module in BdsDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BootMaint / Variable.c
1 /** @file
2 Variable operation that will be used by bootmaint
3
4 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
5 All rights reserved. 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
23 @param VOID EDES_TODO: Add parameter description
24
25 @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to
26 BM_LOAD_CONTEXT marked for deletion is deleted
27 @return Others If failed to update the "BootOrder" variable after deletion.
28
29 **/
30 EFI_STATUS
31 Var_DelBootOption (
32 VOID
33 )
34 {
35 BM_MENU_ENTRY *NewMenuEntry;
36 BM_LOAD_CONTEXT *NewLoadContext;
37 UINT16 BootString[10];
38 EFI_STATUS Status;
39 UINTN Index;
40 UINTN Index2;
41
42 Status = EFI_SUCCESS;
43 Index2 = 0;
44 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
45 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));
46 if (NULL == NewMenuEntry) {
47 return EFI_NOT_FOUND;
48 }
49
50 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
51 if (!NewLoadContext->Deleted) {
52 continue;
53 }
54
55 UnicodeSPrint (
56 BootString,
57 sizeof (BootString),
58 L"Boot%04x",
59 NewMenuEntry->OptionNumber
60 );
61
62 EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);
63 Index2++;
64 //
65 // If current Load Option is the same as BootNext,
66 // must delete BootNext in order to make sure
67 // there will be no panic on next boot
68 //
69 if (NewLoadContext->IsBootNext) {
70 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
71 }
72
73 RemoveEntryList (&NewMenuEntry->Link);
74 BOpt_DestroyMenuEntry (NewMenuEntry);
75 NewMenuEntry = NULL;
76 }
77
78 BootOptionMenu.MenuNumber -= Index2;
79
80 Status = Var_ChangeBootOrder ();
81 return Status;
82 }
83
84 /**
85 After any operation on Boot####, there will be a discrepancy in BootOrder.
86 Since some are missing but in BootOrder, while some are present but are
87 not reflected by BootOrder. Then a function rebuild BootOrder from
88 scratch by content from BootOptionMenu is needed.
89
90
91 @param VOID
92
93 @retval EFI_SUCCESS The boot order is updated successfully.
94 @return EFI_STATUS other than EFI_SUCCESS if failed to
95 Set the "BootOrder" EFI Variable.
96
97 **/
98 EFI_STATUS
99 Var_ChangeBootOrder (
100 VOID
101 )
102 {
103
104 EFI_STATUS Status;
105 BM_MENU_ENTRY *NewMenuEntry;
106 UINT16 *BootOrderList;
107 UINT16 *BootOrderListPtr;
108 UINTN BootOrderListSize;
109 UINTN Index;
110
111 BootOrderList = NULL;
112 BootOrderListSize = 0;
113
114 //
115 // First check whether BootOrder is present in current configuration
116 //
117 BootOrderList = BdsLibGetVariableAndSize (
118 L"BootOrder",
119 &gEfiGlobalVariableGuid,
120 &BootOrderListSize
121 );
122
123 //
124 // If exists, delete it to hold new BootOrder
125 //
126 if (BootOrderList != NULL) {
127 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
128 SafeFreePool (BootOrderList);
129 BootOrderList = NULL;
130 }
131 //
132 // Maybe here should be some check method to ensure that
133 // no new added boot options will be added
134 // but the setup engine now will give only one callback
135 // that is to say, user are granted only one chance to
136 // decide whether the boot option will be added or not
137 // there should be no indictor to show whether this
138 // is a "new" boot option
139 //
140 BootOrderListSize = BootOptionMenu.MenuNumber;
141
142 if (BootOrderListSize > 0) {
143 BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));
144 ASSERT (BootOrderList != NULL);
145 BootOrderListPtr = BootOrderList;
146
147 //
148 // Get all current used Boot#### from BootOptionMenu.
149 // OptionNumber in each BM_LOAD_OPTION is really its
150 // #### value.
151 //
152 for (Index = 0; Index < BootOrderListSize; Index++) {
153 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
154 *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
155 BootOrderList++;
156 }
157
158 BootOrderList = BootOrderListPtr;
159
160 //
161 // After building the BootOrderList, write it back
162 //
163 Status = gRT->SetVariable (
164 L"BootOrder",
165 &gEfiGlobalVariableGuid,
166 VAR_FLAG,
167 BootOrderListSize * sizeof (UINT16),
168 BootOrderList
169 );
170 if (EFI_ERROR (Status)) {
171 return Status;
172 }
173 }
174 return EFI_SUCCESS;
175 }
176
177 /**
178 Delete Load Option that represent a Deleted state in BootOptionMenu.
179 After deleting this Driver option, call Var_ChangeDriverOrder to
180 make sure DriverOrder is in valid state.
181
182
183 @param VOID
184
185 @retval EFI_SUCCESS Load Option is successfully updated.
186 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
187 Variable.
188
189 **/
190 EFI_STATUS
191 Var_DelDriverOption (
192 VOID
193 )
194 {
195 BM_MENU_ENTRY *NewMenuEntry;
196 BM_LOAD_CONTEXT *NewLoadContext;
197 UINT16 DriverString[12];
198 EFI_STATUS Status;
199 UINTN Index;
200 UINTN Index2;
201
202 Status = EFI_SUCCESS;
203 Index2 = 0;
204 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
205 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
206 if (NULL == NewMenuEntry) {
207 return EFI_NOT_FOUND;
208 }
209
210 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
211 if (!NewLoadContext->Deleted) {
212 continue;
213 }
214
215 UnicodeSPrint (
216 DriverString,
217 sizeof (DriverString),
218 L"Driver%04x",
219 NewMenuEntry->OptionNumber
220 );
221
222 EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
223 Index2++;
224
225 RemoveEntryList (&NewMenuEntry->Link);
226 BOpt_DestroyMenuEntry (NewMenuEntry);
227 NewMenuEntry = NULL;
228 }
229
230 DriverOptionMenu.MenuNumber -= Index2;
231
232 Status = Var_ChangeDriverOrder ();
233 return Status;
234 }
235
236 /**
237 After any operation on Driver####, there will be a discrepancy in
238 DriverOrder. Since some are missing but in DriverOrder, while some
239 are present but are not reflected by DriverOrder. Then a function
240 rebuild DriverOrder from scratch by content from DriverOptionMenu is
241 needed.
242
243
244 @param VOID
245
246 @retval EFI_SUCCESS The driver order is updated successfully.
247 @return EFI_STATUS other than EFI_SUCCESS if failed to
248 Set the "DriverOrder" EFI Variable.
249
250 **/
251 EFI_STATUS
252 Var_ChangeDriverOrder (
253 VOID
254 )
255 {
256 EFI_STATUS Status;
257 BM_MENU_ENTRY *NewMenuEntry;
258 UINT16 *DriverOrderList;
259 UINT16 *DriverOrderListPtr;
260 UINTN DriverOrderListSize;
261 UINTN Index;
262
263 DriverOrderList = NULL;
264 DriverOrderListSize = 0;
265
266 //
267 // First check whether DriverOrder is present in current configuration
268 //
269 DriverOrderList = BdsLibGetVariableAndSize (
270 L"DriverOrder",
271 &gEfiGlobalVariableGuid,
272 &DriverOrderListSize
273 );
274
275 //
276 // If exists, delete it to hold new DriverOrder
277 //
278 if (DriverOrderList != NULL) {
279 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
280 SafeFreePool (DriverOrderList);
281 DriverOrderList = NULL;
282 }
283
284 DriverOrderListSize = DriverOptionMenu.MenuNumber;
285
286 if (DriverOrderListSize > 0) {
287 DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
288 ASSERT (DriverOrderList != NULL);
289 DriverOrderListPtr = DriverOrderList;
290
291 //
292 // Get all current used Driver#### from DriverOptionMenu.
293 // OptionNumber in each BM_LOAD_OPTION is really its
294 // #### value.
295 //
296 for (Index = 0; Index < DriverOrderListSize; Index++) {
297 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
298 *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
299 DriverOrderList++;
300 }
301
302 DriverOrderList = DriverOrderListPtr;
303
304 //
305 // After building the DriverOrderList, write it back
306 //
307 Status = gRT->SetVariable (
308 L"DriverOrder",
309 &gEfiGlobalVariableGuid,
310 VAR_FLAG,
311 DriverOrderListSize * sizeof (UINT16),
312 DriverOrderList
313 );
314 if (EFI_ERROR (Status)) {
315 return Status;
316 }
317 }
318 return EFI_SUCCESS;
319 }
320
321 /**
322 Update the device path of "ConOut", "ConIn" and "ErrOut"
323 based on the new BaudRate, Data Bits, parity and Stop Bits
324 set.
325
326 @param VOID
327
328 @return VOID
329
330 **/
331 VOID
332 Var_UpdateAllConsoleOption (
333 VOID
334 )
335 {
336 EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
337 EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
338 EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
339 EFI_STATUS Status;
340
341 OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
342 InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
343 ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
344 if (OutDevicePath != NULL) {
345 ChangeVariableDevicePath (OutDevicePath);
346 Status = gRT->SetVariable (
347 L"ConOut",
348 &gEfiGlobalVariableGuid,
349 VAR_FLAG,
350 GetDevicePathSize (OutDevicePath),
351 OutDevicePath
352 );
353 ASSERT (!EFI_ERROR (Status));
354 }
355
356 if (InpDevicePath != NULL) {
357 ChangeVariableDevicePath (InpDevicePath);
358 Status = gRT->SetVariable (
359 L"ConIn",
360 &gEfiGlobalVariableGuid,
361 VAR_FLAG,
362 GetDevicePathSize (InpDevicePath),
363 InpDevicePath
364 );
365 ASSERT (!EFI_ERROR (Status));
366 }
367
368 if (ErrDevicePath != NULL) {
369 ChangeVariableDevicePath (ErrDevicePath);
370 Status = gRT->SetVariable (
371 L"ErrOut",
372 &gEfiGlobalVariableGuid,
373 VAR_FLAG,
374 GetDevicePathSize (ErrDevicePath),
375 ErrDevicePath
376 );
377 ASSERT (!EFI_ERROR (Status));
378 }
379 }
380
381 /**
382 This function delete and build multi-instance device path for
383 specified type of console device.
384
385 This function clear the EFI variable defined by ConsoleName and
386 gEfiGlobalVariableGuid. It then build the multi-instance device
387 path by appending the device path of the Console (In/Out/Err) instance
388 in ConsoleMenu. Then it scan all corresponding console device by
389 scanning Terminal (built from device supporting Serial I/O instances)
390 devices in TerminalMenu. At last, it save a EFI variable specifed
391 by ConsoleName and gEfiGlobalVariableGuid.
392
393 @param ConsoleName The name for the console device type. They are
394 usually "ConIn", "ConOut" and "ErrOut".
395 @param ConsoleMenu The console memu which is a list of console devices.
396 @param UpdatePageId The flag specifying which type of console device
397 to be processed.
398
399 @retval EFI_SUCCESS The function complete successfully.
400 @return The EFI variable can be saved. See gRT->SetVariable
401 for detail return information.
402
403 **/
404 EFI_STATUS
405 Var_UpdateConsoleOption (
406 IN UINT16 *ConsoleName,
407 IN BM_MENU_OPTION *ConsoleMenu,
408 IN UINT16 UpdatePageId
409 )
410 {
411 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
412 BM_MENU_ENTRY *NewMenuEntry;
413 BM_CONSOLE_CONTEXT *NewConsoleContext;
414 BM_TERMINAL_CONTEXT *NewTerminalContext;
415 EFI_STATUS Status;
416 VENDOR_DEVICE_PATH Vendor;
417 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
418 UINTN Index;
419
420 ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);
421 if (ConDevicePath != NULL) {
422 EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
423 SafeFreePool (ConDevicePath);
424 ConDevicePath = NULL;
425 };
426
427 //
428 // First add all console input device from console input menu
429 //
430 for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
431 NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
432
433 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
434 if (NewConsoleContext->IsActive) {
435 ConDevicePath = AppendDevicePathInstance (
436 ConDevicePath,
437 NewConsoleContext->DevicePath
438 );
439 }
440 }
441
442 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
443 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
444
445 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
446 if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
447 ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
448 ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
449 ) {
450 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
451 Vendor.Header.SubType = MSG_VENDOR_DP;
452 CopyMem (
453 &Vendor.Guid,
454 &TerminalTypeGuid[NewTerminalContext->TerminalType],
455 sizeof (EFI_GUID)
456 );
457 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
458 TerminalDevicePath = AppendDevicePathNode (
459 NewTerminalContext->DevicePath,
460 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
461 );
462 ASSERT (TerminalDevicePath != NULL);
463 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
464 ConDevicePath = AppendDevicePathInstance (
465 ConDevicePath,
466 TerminalDevicePath
467 );
468 }
469 }
470
471 if (ConDevicePath != NULL) {
472 Status = gRT->SetVariable (
473 ConsoleName,
474 &gEfiGlobalVariableGuid,
475 VAR_FLAG,
476 GetDevicePathSize (ConDevicePath),
477 ConDevicePath
478 );
479 if (EFI_ERROR (Status)) {
480 return Status;
481 }
482 }
483
484 return EFI_SUCCESS;
485
486 }
487
488 /**
489 This function delete and build multi-instance device path ConIn
490 console device.
491
492
493 @param VOID
494
495 @retval EFI_SUCCESS The function complete successfully.
496 @return The EFI variable can be saved. See gRT->SetVariable
497 for detail return information.
498 **/
499 EFI_STATUS
500 Var_UpdateConsoleInpOption (
501 VOID
502 )
503 {
504 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
505 }
506
507 /**
508 This function delete and build multi-instance device path ConOut
509 console device.
510
511
512 @param VOID
513
514 @retval EFI_SUCCESS The function complete successfully.
515 @return The EFI variable can be saved. See gRT->SetVariable
516 for detail return information.
517 **/
518 EFI_STATUS
519 Var_UpdateConsoleOutOption (
520 VOID
521 )
522 {
523 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
524 }
525
526 /**
527 This function delete and build multi-instance device path ErrOut
528 console device.
529
530
531 @param VOID
532
533 @retval EFI_SUCCESS The function complete successfully.
534 @return The EFI variable can be saved. See gRT->SetVariable
535 for detail return information.
536 **/
537 EFI_STATUS
538 Var_UpdateErrorOutOption (
539 VOID
540 )
541 {
542 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
543 }
544
545 /**
546 This function create a currently loaded Drive Option from
547 the BMM. It then appends this Driver Option to the end of
548 the "DriverOrder" list. It append this Driver Opotion to the end
549 of DriverOptionMenu.
550
551 @param CallbackData The BMM context data.
552 @param HiiHandle The HII handle associated with the BMM formset.
553 @param DescriptionData The description of this driver option.
554 @param OptionalData The optional load option.
555 @param ForceReconnect EDES_TODO: Add parameter description
556
557 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
558 @retval EFI_SUCCESS If function completes successfully.
559
560 **/
561 EFI_STATUS
562 Var_UpdateDriverOption (
563 IN BMM_CALLBACK_DATA *CallbackData,
564 IN EFI_HII_HANDLE HiiHandle,
565 IN UINT16 *DescriptionData,
566 IN UINT16 *OptionalData,
567 IN UINT8 ForceReconnect
568 )
569 {
570 UINT16 Index;
571 UINT16 *DriverOrderList;
572 UINT16 *NewDriverOrderList;
573 UINT16 DriverString[12];
574 UINTN DriverOrderListSize;
575 VOID *Buffer;
576 UINTN BufferSize;
577 UINT8 *Ptr;
578 BM_MENU_ENTRY *NewMenuEntry;
579 BM_LOAD_CONTEXT *NewLoadContext;
580 BOOLEAN OptionalDataExist;
581 EFI_STATUS Status;
582
583 OptionalDataExist = FALSE;
584
585 Index = BOpt_GetDriverOptionNumber ();
586 UnicodeSPrint (
587 DriverString,
588 sizeof (DriverString),
589 L"Driver%04x",
590 Index
591 );
592
593 if (*DescriptionData == 0x0000) {
594 StrCpy (DescriptionData, DriverString);
595 }
596
597 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);
598 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
599
600 if (*OptionalData != 0x0000) {
601 OptionalDataExist = TRUE;
602 BufferSize += StrSize (OptionalData);
603 }
604
605 Buffer = AllocateZeroPool (BufferSize);
606 if (NULL == Buffer) {
607 return EFI_OUT_OF_RESOURCES;
608 }
609
610 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
611 if (NULL == NewMenuEntry) {
612 return EFI_OUT_OF_RESOURCES;
613 }
614
615 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
616 NewLoadContext->Deleted = FALSE;
617 NewLoadContext->LoadOptionSize = BufferSize;
618 Ptr = (UINT8 *) Buffer;
619 NewLoadContext->LoadOption = Ptr;
620 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
621 NewLoadContext->Attributes = *((UINT32 *) Ptr);
622 NewLoadContext->IsActive = TRUE;
623 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
624
625 Ptr += sizeof (UINT32);
626 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
627 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
628
629 Ptr += sizeof (UINT16);
630 CopyMem (
631 Ptr,
632 DescriptionData,
633 StrSize (DescriptionData)
634 );
635
636 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
637 ASSERT (NewLoadContext->Description != NULL);
638 NewMenuEntry->DisplayString = NewLoadContext->Description;
639 CopyMem (
640 NewLoadContext->Description,
641 (VOID *) Ptr,
642 StrSize (DescriptionData)
643 );
644
645 Ptr += StrSize (DescriptionData);
646 CopyMem (
647 Ptr,
648 CallbackData->LoadContext->FilePathList,
649 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
650 );
651
652 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
653 ASSERT (NewLoadContext->FilePathList != NULL);
654
655 CopyMem (
656 NewLoadContext->FilePathList,
657 (VOID *) Ptr,
658 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
659 );
660
661 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
662 NewMenuEntry->OptionNumber = Index;
663 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
664 CallbackData,
665 DriverOptionStrDepository
666 );
667 HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
668
669 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
670 CallbackData,
671 DriverOptionHelpStrDepository
672 );
673 HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
674
675 if (OptionalDataExist) {
676 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
677
678 CopyMem (
679 Ptr,
680 OptionalData,
681 StrSize (OptionalData)
682 );
683 }
684
685 Status = gRT->SetVariable (
686 DriverString,
687 &gEfiGlobalVariableGuid,
688 VAR_FLAG,
689 BufferSize,
690 Buffer
691 );
692 ASSERT_EFI_ERROR (Status);
693 DriverOrderList = BdsLibGetVariableAndSize (
694 L"DriverOrder",
695 &gEfiGlobalVariableGuid,
696 &DriverOrderListSize
697 );
698 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
699 ASSERT (NewDriverOrderList != NULL);
700 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
701 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
702 if (DriverOrderList != NULL) {
703 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
704 }
705
706 Status = gRT->SetVariable (
707 L"DriverOrder",
708 &gEfiGlobalVariableGuid,
709 VAR_FLAG,
710 DriverOrderListSize + sizeof (UINT16),
711 NewDriverOrderList
712 );
713 ASSERT_EFI_ERROR (Status);
714 SafeFreePool (DriverOrderList);
715 DriverOrderList = NULL;
716 SafeFreePool (NewDriverOrderList);
717 NewDriverOrderList = NULL;
718 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
719 DriverOptionMenu.MenuNumber++;
720
721 *DescriptionData = 0x0000;
722 *OptionalData = 0x0000;
723 return EFI_SUCCESS;
724 }
725
726 /**
727 This function create a currently loaded Boot Option from
728 the BMM. It then appends this Boot Option to the end of
729 the "BootOrder" list. It also append this Boot Opotion to the end
730 of BootOptionMenu.
731
732 @param CallbackData The BMM context data.
733 @param NvRamMap The file explorer formset internal state.
734
735 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
736 @retval EFI_SUCCESS If function completes successfully.
737
738 **/
739
740 EFI_STATUS
741 Var_UpdateBootOption (
742 IN BMM_CALLBACK_DATA *CallbackData,
743 IN FILE_EXPLORER_NV_DATA *NvRamMap
744 )
745 {
746 UINT16 *BootOrderList;
747 UINT16 *NewBootOrderList;
748 UINTN BootOrderListSize;
749 UINT16 BootString[10];
750 VOID *Buffer;
751 UINTN BufferSize;
752 UINT8 *Ptr;
753 UINT16 Index;
754 BM_MENU_ENTRY *NewMenuEntry;
755 BM_LOAD_CONTEXT *NewLoadContext;
756 BOOLEAN OptionalDataExist;
757 EFI_STATUS Status;
758
759 OptionalDataExist = FALSE;
760
761 Index = BOpt_GetBootOptionNumber () ;
762 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
763
764 if (NvRamMap->DescriptionData[0] == 0x0000) {
765 StrCpy (NvRamMap->DescriptionData, BootString);
766 }
767
768 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);
769 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
770
771 if (NvRamMap->OptionalData[0] != 0x0000) {
772 OptionalDataExist = TRUE;
773 BufferSize += StrSize (NvRamMap->OptionalData);
774 }
775
776 Buffer = AllocateZeroPool (BufferSize);
777 if (NULL == Buffer) {
778 return EFI_OUT_OF_RESOURCES;
779 }
780
781 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
782 if (NULL == NewMenuEntry) {
783 return EFI_OUT_OF_RESOURCES;
784 }
785
786 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
787 NewLoadContext->Deleted = FALSE;
788 NewLoadContext->LoadOptionSize = BufferSize;
789 Ptr = (UINT8 *) Buffer;
790 NewLoadContext->LoadOption = Ptr;
791 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
792 NewLoadContext->Attributes = *((UINT32 *) Ptr);
793 NewLoadContext->IsActive = TRUE;
794 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
795
796 Ptr += sizeof (UINT32);
797 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
798 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
799 Ptr += sizeof (UINT16);
800
801 CopyMem (
802 Ptr,
803 NvRamMap->DescriptionData,
804 StrSize (NvRamMap->DescriptionData)
805 );
806
807 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));
808 ASSERT (NewLoadContext->Description != NULL);
809
810 NewMenuEntry->DisplayString = NewLoadContext->Description;
811 CopyMem (
812 NewLoadContext->Description,
813 (VOID *) Ptr,
814 StrSize (NvRamMap->DescriptionData)
815 );
816
817 Ptr += StrSize (NvRamMap->DescriptionData);
818 CopyMem (
819 Ptr,
820 CallbackData->LoadContext->FilePathList,
821 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
822 );
823
824 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
825 ASSERT (NewLoadContext->FilePathList != NULL);
826
827 CopyMem (
828 NewLoadContext->FilePathList,
829 (VOID *) Ptr,
830 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
831 );
832
833 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
834 NewMenuEntry->OptionNumber = Index;
835 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
836 CallbackData,
837 BootOptionStrDepository
838 );
839 HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
840
841 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
842 CallbackData,
843 BootOptionHelpStrDepository
844 );
845 HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
846
847 if (OptionalDataExist) {
848 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
849
850 CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
851 }
852
853 Status = gRT->SetVariable (
854 BootString,
855 &gEfiGlobalVariableGuid,
856 VAR_FLAG,
857 BufferSize,
858 Buffer
859 );
860 ASSERT_EFI_ERROR (Status);
861
862 BootOrderList = BdsLibGetVariableAndSize (
863 L"BootOrder",
864 &gEfiGlobalVariableGuid,
865 &BootOrderListSize
866 );
867
868 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
869 ASSERT (NewBootOrderList != NULL);
870 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
871 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
872
873 if (BootOrderList != NULL) {
874 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
875 }
876
877 Status = gRT->SetVariable (
878 L"BootOrder",
879 &gEfiGlobalVariableGuid,
880 VAR_FLAG,
881 BootOrderListSize + sizeof (UINT16),
882 NewBootOrderList
883 );
884 ASSERT_EFI_ERROR (Status);
885
886 SafeFreePool (BootOrderList);
887 BootOrderList = NULL;
888 SafeFreePool (NewBootOrderList);
889 NewBootOrderList = NULL;
890 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
891 BootOptionMenu.MenuNumber++;
892
893 NvRamMap->DescriptionData[0] = 0x0000;
894 NvRamMap->OptionalData[0] = 0x0000;
895 return EFI_SUCCESS;
896 }
897
898 /**
899 This function update the "BootNext" EFI Variable. If there is
900 no "BootNex" specified in BMM, this EFI Variable is deleted.
901 It also update the BMM context data specified the "BootNext"
902 vaule.
903
904 @param CallbackData The BMM context data.
905
906 @retval EFI_SUCCESS The function complete successfully.
907 @return The EFI variable can be saved. See gRT->SetVariable
908 for detail return information.
909
910 **/
911 EFI_STATUS
912 Var_UpdateBootNext (
913 IN BMM_CALLBACK_DATA *CallbackData
914 )
915 {
916 BM_MENU_ENTRY *NewMenuEntry;
917 BM_LOAD_CONTEXT *NewLoadContext;
918 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
919 UINT16 Index;
920 EFI_STATUS Status;
921
922 Status = EFI_SUCCESS;
923 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
924 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
925 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
926 ASSERT (NULL != NewMenuEntry);
927
928 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
929 NewLoadContext->IsBootNext = FALSE;
930 }
931
932 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
933 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
934 return EFI_SUCCESS;
935 }
936
937 NewMenuEntry = BOpt_GetMenuEntry (
938 &BootOptionMenu,
939 CurrentFakeNVMap->BootNext
940 );
941 ASSERT (NewMenuEntry != NULL);
942
943 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
944 Status = gRT->SetVariable (
945 L"BootNext",
946 &gEfiGlobalVariableGuid,
947 VAR_FLAG,
948 sizeof (UINT16),
949 &NewMenuEntry->OptionNumber
950 );
951 NewLoadContext->IsBootNext = TRUE;
952 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
953 return Status;
954 }
955
956 /**
957 This function update the "BootOrder" EFI Variable based on
958 BMM Formset's NV map. It then refresh BootOptionMenu
959 with the new "BootOrder" list.
960
961 @param CallbackData The BMM context data.
962
963 @retval EFI_SUCCESS The function complete successfully.
964 @retval EFI_SUCCESS Not enough memory to complete the function.
965 @return The EFI variable can be saved. See gRT->SetVariable
966 for detail return information.
967
968 **/
969 EFI_STATUS
970 Var_UpdateBootOrder (
971 IN BMM_CALLBACK_DATA *CallbackData
972 )
973 {
974 EFI_STATUS Status;
975 UINT16 Index;
976 UINT16 *BootOrderList;
977 UINT16 *NewBootOrderList;
978 UINTN BootOrderListSize;
979
980 BootOrderList = NULL;
981 BootOrderListSize = 0;
982
983 //
984 // First check whether BootOrder is present in current configuration
985 //
986 BootOrderList = BdsLibGetVariableAndSize (
987 L"BootOrder",
988 &gEfiGlobalVariableGuid,
989 &BootOrderListSize
990 );
991
992 NewBootOrderList = AllocateZeroPool (BootOrderListSize);
993 if (NewBootOrderList == NULL) {
994 return EFI_OUT_OF_RESOURCES;
995 }
996
997 //
998 // If exists, delete it to hold new BootOrder
999 //
1000 if (BootOrderList != NULL) {
1001 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
1002 }
1003
1004 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
1005 NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
1006 }
1007
1008 Status = gRT->SetVariable (
1009 L"BootOrder",
1010 &gEfiGlobalVariableGuid,
1011 VAR_FLAG,
1012 BootOrderListSize,
1013 NewBootOrderList
1014 );
1015 SafeFreePool (BootOrderList);
1016 SafeFreePool (NewBootOrderList);
1017 if (EFI_ERROR (Status)) {
1018 return Status;
1019 }
1020
1021 BOpt_FreeMenu (&BootOptionMenu);
1022 BOpt_GetBootOptions (CallbackData);
1023
1024 return EFI_SUCCESS;
1025
1026 }
1027
1028 /**
1029 This function update the "DriverOrder" EFI Variable based on
1030 BMM Formset's NV map. It then refresh DriverOptionMenu
1031 with the new "DriverOrder" list.
1032
1033 @param CallbackData The BMM context data.
1034
1035 @retval EFI_SUCCESS The function complete successfully.
1036 @retval EFI_SUCCESS Not enough memory to complete the function.
1037 @return The EFI variable can be saved. See gRT->SetVariable
1038 for detail return information.
1039
1040 **/
1041 EFI_STATUS
1042 Var_UpdateDriverOrder (
1043 IN BMM_CALLBACK_DATA *CallbackData
1044 )
1045 {
1046 EFI_STATUS Status;
1047 UINT16 Index;
1048 UINT16 *DriverOrderList;
1049 UINT16 *NewDriverOrderList;
1050 UINTN DriverOrderListSize;
1051
1052 DriverOrderList = NULL;
1053 DriverOrderListSize = 0;
1054
1055 //
1056 // First check whether DriverOrder is present in current configuration
1057 //
1058 DriverOrderList = BdsLibGetVariableAndSize (
1059 L"DriverOrder",
1060 &gEfiGlobalVariableGuid,
1061 &DriverOrderListSize
1062 );
1063
1064 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
1065
1066 if (NewDriverOrderList == NULL) {
1067 return EFI_OUT_OF_RESOURCES;
1068 }
1069 //
1070 // If exists, delete it to hold new DriverOrder
1071 //
1072 if (DriverOrderList != NULL) {
1073 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
1074 }
1075
1076 for (Index = 0; Index < DriverOrderListSize; Index++) {
1077 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
1078 }
1079
1080 Status = gRT->SetVariable (
1081 L"DriverOrder",
1082 &gEfiGlobalVariableGuid,
1083 VAR_FLAG,
1084 DriverOrderListSize,
1085 NewDriverOrderList
1086 );
1087 if (EFI_ERROR (Status)) {
1088 return Status;
1089 }
1090
1091 SafeFreePool (DriverOrderList);
1092
1093 BOpt_FreeMenu (&DriverOptionMenu);
1094 BOpt_GetDriverOptions (CallbackData);
1095 return EFI_SUCCESS;
1096 }
1097
1098 /**
1099 Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable
1100 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1101 is also updated.
1102
1103 @param CallbackData The context data for BMM.
1104
1105 @return EFI_SUCCESS The function completed successfully.
1106 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.
1107
1108 **/
1109 EFI_STATUS
1110 Var_UpdateBBSOption (
1111 IN BMM_CALLBACK_DATA *CallbackData
1112 )
1113 {
1114 UINTN Index;
1115 UINTN Index2;
1116 VOID *BootOptionVar;
1117 CHAR16 VarName[100];
1118 UINTN OptionSize;
1119 UINT8 *Ptr;
1120 EFI_STATUS Status;
1121 CHAR16 DescString[100];
1122 CHAR8 DescAsciiString[100];
1123 UINTN NewOptionSize;
1124 UINT8 *NewOptionPtr;
1125 UINT8 *TempPtr;
1126 UINT32 *Attribute;
1127 BM_MENU_OPTION *OptionMenu;
1128 BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
1129 UINT8 *LegacyDev;
1130 UINT8 *VarData;
1131 UINTN VarSize;
1132 BM_MENU_ENTRY *NewMenuEntry;
1133 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
1134 UINT8 *OriginalPtr;
1135 UINT8 *DisMap;
1136 UINTN Pos;
1137 UINTN Bit;
1138 UINT16 *NewOrder;
1139 UINT16 Tmp;
1140
1141 LegacyDeviceContext = NULL;
1142 DisMap = NULL;
1143 NewOrder = NULL;
1144
1145 if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1146 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
1147 LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;
1148 CallbackData->BbsType = BBS_FLOPPY;
1149 } else {
1150 if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1151 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
1152 LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;
1153 CallbackData->BbsType = BBS_HARDDISK;
1154 } else {
1155 if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1156 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
1157 LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;
1158 CallbackData->BbsType = BBS_CDROM;
1159 } else {
1160 if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
1161 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
1162 LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;
1163 CallbackData->BbsType = BBS_EMBED_NETWORK;
1164 } else {
1165 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
1166 LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;
1167 CallbackData->BbsType = BBS_BEV_DEVICE;
1168 }
1169 }
1170 }
1171 }
1172
1173 DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
1174 Status = EFI_SUCCESS;
1175
1176 //
1177 // Find the first device's context
1178 // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
1179 // because we just use it to fill the desc string, and user can not see the string in UI
1180 //
1181 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1182 NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
1183 LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
1184 if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
1185 DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
1186 break;
1187 }
1188 }
1189 //
1190 // Update the Variable "LegacyDevOrder"
1191 //
1192 VarData = (UINT8 *) BdsLibGetVariableAndSize (
1193 VAR_LEGACY_DEV_ORDER,
1194 &EfiLegacyDevOrderGuid,
1195 &VarSize
1196 );
1197
1198 if (NULL == VarData) {
1199 return EFI_NOT_FOUND;
1200 }
1201
1202 OriginalPtr = VarData;
1203 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1204
1205 while (VarData < VarData + VarSize) {
1206 if (DevOrder->BbsType == CallbackData->BbsType) {
1207 break;
1208 }
1209
1210 VarData += sizeof (BBS_TYPE);
1211 VarData += *(UINT16 *) VarData;
1212 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1213 }
1214
1215 if (VarData >= VarData + VarSize) {
1216 SafeFreePool (OriginalPtr);
1217 return EFI_NOT_FOUND;
1218 }
1219
1220 NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));
1221 if (NULL == NewOrder) {
1222 SafeFreePool (VarData);
1223 return EFI_OUT_OF_RESOURCES;
1224 }
1225
1226 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1227 if (0xFF == LegacyDev[Index]) {
1228 break;
1229 }
1230
1231 NewOrder[Index] = LegacyDev[Index];
1232 }
1233 //
1234 // Only the enable/disable state of each boot device with same device type can be changed,
1235 // so we can count on the index information in DevOrder.
1236 // DisMap bit array is the only reliable source to check a device's en/dis state,
1237 // so we use DisMap to set en/dis state of each item in NewOrder array
1238 //
1239 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
1240 Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
1241 Tmp &= 0xFF;
1242 Pos = Tmp / 8;
1243 Bit = 7 - (Tmp % 8);
1244 if ((DisMap[Pos] & (1 << Bit)) != 0) {
1245 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
1246 Index++;
1247 }
1248 }
1249
1250 CopyMem (
1251 (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
1252 NewOrder,
1253 DevOrder->Length - sizeof (UINT16)
1254 );
1255 SafeFreePool (NewOrder);
1256
1257 Status = gRT->SetVariable (
1258 VAR_LEGACY_DEV_ORDER,
1259 &EfiLegacyDevOrderGuid,
1260 VAR_FLAG,
1261 VarSize,
1262 OriginalPtr
1263 );
1264
1265 SafeFreePool (OriginalPtr);
1266
1267 //
1268 // Update Optional Data of Boot####
1269 //
1270 BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
1271
1272 if (NULL != BootOptionVar) {
1273 CopyMem (
1274 DescString,
1275 LegacyDeviceContext->Description,
1276 StrSize (LegacyDeviceContext->Description)
1277 );
1278
1279 UnicodeToAscii (DescString, StrSize (DescString), DescAsciiString);
1280
1281 NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +
1282 sizeof (BBS_BBS_DEVICE_PATH);
1283 NewOptionSize += AsciiStrLen (DescAsciiString) +
1284 EFI_END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);
1285
1286 UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
1287
1288 Ptr = BootOptionVar;
1289
1290 Attribute = (UINT32 *) Ptr;
1291 *Attribute |= LOAD_OPTION_ACTIVE;
1292 if (0xFF == LegacyDev[0]) {
1293 //
1294 // Disable this legacy boot option
1295 //
1296 *Attribute &= ~LOAD_OPTION_ACTIVE;
1297 }
1298
1299 Ptr += sizeof (UINT32);
1300
1301 Ptr += sizeof (UINT16);
1302 Ptr += StrSize ((CHAR16 *) Ptr);
1303
1304 NewOptionPtr = AllocateZeroPool (NewOptionSize);
1305 if (NULL == NewOptionPtr) {
1306 return EFI_OUT_OF_RESOURCES;
1307 }
1308
1309 TempPtr = NewOptionPtr;
1310
1311 //
1312 // Attribute
1313 //
1314 CopyMem (
1315 TempPtr,
1316 BootOptionVar,
1317 sizeof (UINT32)
1318 );
1319
1320 TempPtr += sizeof (UINT32);
1321
1322 //
1323 // BBS device path Length
1324 //
1325 *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +
1326 AsciiStrLen (DescAsciiString) +
1327 EFI_END_DEVICE_PATH_LENGTH);
1328
1329 TempPtr += sizeof (UINT16);
1330
1331 //
1332 // Description string
1333 //
1334 CopyMem (
1335 TempPtr,
1336 DescString,
1337 StrSize (DescString)
1338 );
1339
1340 TempPtr += StrSize (DescString);
1341
1342 //
1343 // BBS device path
1344 //
1345 CopyMem (
1346 TempPtr,
1347 Ptr,
1348 sizeof (BBS_BBS_DEVICE_PATH)
1349 );
1350
1351 CopyMem (
1352 ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,
1353 DescAsciiString,
1354 AsciiStrSize (DescAsciiString)
1355 );
1356
1357 SetDevicePathNodeLength (
1358 (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,
1359 sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)
1360 );
1361
1362 TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);
1363
1364 //
1365 // End node
1366 //
1367 CopyMem (
1368 TempPtr,
1369 EndDevicePath,
1370 EFI_END_DEVICE_PATH_LENGTH
1371 );
1372 TempPtr += EFI_END_DEVICE_PATH_LENGTH;
1373
1374 //
1375 // Now TempPtr point to optional data, i.e. Bbs Table
1376 //
1377 CopyMem (
1378 TempPtr,
1379 LegacyDeviceContext->BbsTable,
1380 sizeof (BBS_TABLE)
1381 );
1382
1383 //
1384 // Now TempPtr point to BBS index
1385 //
1386 TempPtr += sizeof (BBS_TABLE);
1387 *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
1388
1389 Status = gRT->SetVariable (
1390 VarName,
1391 &gEfiGlobalVariableGuid,
1392 VAR_FLAG,
1393 NewOptionSize,
1394 NewOptionPtr
1395 );
1396
1397 SafeFreePool (NewOptionPtr);
1398 SafeFreePool (BootOptionVar);
1399 }
1400
1401 BOpt_GetBootOptions (CallbackData);
1402 return Status;
1403 }
1404
1405 /**
1406 Update the Text Mode of Console.
1407
1408 @param CallbackData The context data for BMM.
1409
1410 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1411 @return Other value if the Text Mode of Console is not updated.
1412
1413 **/
1414 EFI_STATUS
1415 Var_UpdateConMode (
1416 IN BMM_CALLBACK_DATA *CallbackData
1417 )
1418 {
1419 EFI_STATUS Status;
1420 UINTN Mode;
1421 CONSOLE_OUT_MODE ModeInfo;
1422
1423 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
1424
1425 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
1426 if (EFI_ERROR(Status)) {
1427 ModeInfo.Column = 80;
1428 ModeInfo.Row = 25;
1429 }
1430
1431 Status = gRT->SetVariable (
1432 VarConOutMode,
1433 &gEfiGenericPlatformVariableGuid,
1434 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1435 sizeof (CONSOLE_OUT_MODE),
1436 &ModeInfo
1437 );
1438
1439 return Status;
1440 }