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