]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
Refine function comments 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 FreePool (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 FreePool (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 not be saved. See gRT->SetVariable for detail return information.
388
389 **/
390 EFI_STATUS
391 Var_UpdateConsoleOption (
392 IN UINT16 *ConsoleName,
393 IN BM_MENU_OPTION *ConsoleMenu,
394 IN UINT16 UpdatePageId
395 )
396 {
397 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
398 BM_MENU_ENTRY *NewMenuEntry;
399 BM_CONSOLE_CONTEXT *NewConsoleContext;
400 BM_TERMINAL_CONTEXT *NewTerminalContext;
401 EFI_STATUS Status;
402 VENDOR_DEVICE_PATH Vendor;
403 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
404 UINTN Index;
405
406 ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);
407 if (ConDevicePath != NULL) {
408 EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
409 FreePool (ConDevicePath);
410 ConDevicePath = NULL;
411 };
412
413 //
414 // First add all console input device from console input menu
415 //
416 for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
417 NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
418
419 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
420 if (NewConsoleContext->IsActive) {
421 ConDevicePath = AppendDevicePathInstance (
422 ConDevicePath,
423 NewConsoleContext->DevicePath
424 );
425 }
426 }
427
428 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
429 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
430
431 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
432 if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
433 ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
434 ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
435 ) {
436 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
437 Vendor.Header.SubType = MSG_VENDOR_DP;
438 CopyMem (
439 &Vendor.Guid,
440 &TerminalTypeGuid[NewTerminalContext->TerminalType],
441 sizeof (EFI_GUID)
442 );
443 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
444 TerminalDevicePath = AppendDevicePathNode (
445 NewTerminalContext->DevicePath,
446 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
447 );
448 ASSERT (TerminalDevicePath != NULL);
449 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
450 ConDevicePath = AppendDevicePathInstance (
451 ConDevicePath,
452 TerminalDevicePath
453 );
454 }
455 }
456
457 if (ConDevicePath != NULL) {
458 Status = gRT->SetVariable (
459 ConsoleName,
460 &gEfiGlobalVariableGuid,
461 VAR_FLAG,
462 GetDevicePathSize (ConDevicePath),
463 ConDevicePath
464 );
465 if (EFI_ERROR (Status)) {
466 return Status;
467 }
468 }
469
470 return EFI_SUCCESS;
471
472 }
473
474 /**
475 This function delete and build multi-instance device path ConIn
476 console device.
477
478 @retval EFI_SUCCESS The function complete successfully.
479 @return The EFI variable can be saved. See gRT->SetVariable
480 for detail return information.
481 **/
482 EFI_STATUS
483 Var_UpdateConsoleInpOption (
484 VOID
485 )
486 {
487 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
488 }
489
490 /**
491 This function delete and build multi-instance device path ConOut
492 console device.
493
494 @retval EFI_SUCCESS The function complete successfully.
495 @return The EFI variable can be saved. See gRT->SetVariable
496 for detail return information.
497 **/
498 EFI_STATUS
499 Var_UpdateConsoleOutOption (
500 VOID
501 )
502 {
503 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
504 }
505
506 /**
507 This function delete and build multi-instance device path ErrOut
508 console device.
509
510 @retval EFI_SUCCESS The function complete successfully.
511 @return The EFI variable can be saved. See gRT->SetVariable
512 for detail return information.
513 **/
514 EFI_STATUS
515 Var_UpdateErrorOutOption (
516 VOID
517 )
518 {
519 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
520 }
521
522 /**
523 This function create a currently loaded Drive Option from
524 the BMM. It then appends this Driver Option to the end of
525 the "DriverOrder" list. It append this Driver Opotion to the end
526 of DriverOptionMenu.
527
528 @param CallbackData The BMM context data.
529 @param HiiHandle The HII handle associated with the BMM formset.
530 @param DescriptionData The description of this driver option.
531 @param OptionalData The optional load option.
532 @param ForceReconnect If to force reconnect.
533
534 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.
535 @retval EFI_SUCCESS If function completes successfully.
536
537 **/
538 EFI_STATUS
539 Var_UpdateDriverOption (
540 IN BMM_CALLBACK_DATA *CallbackData,
541 IN EFI_HII_HANDLE HiiHandle,
542 IN UINT16 *DescriptionData,
543 IN UINT16 *OptionalData,
544 IN UINT8 ForceReconnect
545 )
546 {
547 UINT16 Index;
548 UINT16 *DriverOrderList;
549 UINT16 *NewDriverOrderList;
550 UINT16 DriverString[12];
551 UINTN DriverOrderListSize;
552 VOID *Buffer;
553 UINTN BufferSize;
554 UINT8 *Ptr;
555 BM_MENU_ENTRY *NewMenuEntry;
556 BM_LOAD_CONTEXT *NewLoadContext;
557 BOOLEAN OptionalDataExist;
558 EFI_STATUS Status;
559
560 OptionalDataExist = FALSE;
561
562 Index = BOpt_GetDriverOptionNumber ();
563 UnicodeSPrint (
564 DriverString,
565 sizeof (DriverString),
566 L"Driver%04x",
567 Index
568 );
569
570 if (*DescriptionData == 0x0000) {
571 StrCpy (DescriptionData, DriverString);
572 }
573
574 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);
575 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
576
577 if (*OptionalData != 0x0000) {
578 OptionalDataExist = TRUE;
579 BufferSize += StrSize (OptionalData);
580 }
581
582 Buffer = AllocateZeroPool (BufferSize);
583 if (NULL == Buffer) {
584 return EFI_OUT_OF_RESOURCES;
585 }
586
587 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
588 if (NULL == NewMenuEntry) {
589 return EFI_OUT_OF_RESOURCES;
590 }
591
592 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
593 NewLoadContext->Deleted = FALSE;
594 NewLoadContext->LoadOptionSize = BufferSize;
595 Ptr = (UINT8 *) Buffer;
596 NewLoadContext->LoadOption = Ptr;
597 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
598 NewLoadContext->Attributes = *((UINT32 *) Ptr);
599 NewLoadContext->IsActive = TRUE;
600 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
601
602 Ptr += sizeof (UINT32);
603 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
604 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
605
606 Ptr += sizeof (UINT16);
607 CopyMem (
608 Ptr,
609 DescriptionData,
610 StrSize (DescriptionData)
611 );
612
613 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
614 ASSERT (NewLoadContext->Description != NULL);
615 NewMenuEntry->DisplayString = NewLoadContext->Description;
616 CopyMem (
617 NewLoadContext->Description,
618 (VOID *) Ptr,
619 StrSize (DescriptionData)
620 );
621
622 Ptr += StrSize (DescriptionData);
623 CopyMem (
624 Ptr,
625 CallbackData->LoadContext->FilePathList,
626 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
627 );
628
629 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
630 ASSERT (NewLoadContext->FilePathList != NULL);
631
632 CopyMem (
633 NewLoadContext->FilePathList,
634 (VOID *) Ptr,
635 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
636 );
637
638 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
639 NewMenuEntry->OptionNumber = Index;
640 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
641 CallbackData,
642 DriverOptionStrDepository
643 );
644 HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
645
646 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
647 CallbackData,
648 DriverOptionHelpStrDepository
649 );
650 HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
651
652 if (OptionalDataExist) {
653 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
654
655 CopyMem (
656 Ptr,
657 OptionalData,
658 StrSize (OptionalData)
659 );
660 }
661
662 Status = gRT->SetVariable (
663 DriverString,
664 &gEfiGlobalVariableGuid,
665 VAR_FLAG,
666 BufferSize,
667 Buffer
668 );
669 ASSERT_EFI_ERROR (Status);
670 DriverOrderList = BdsLibGetVariableAndSize (
671 L"DriverOrder",
672 &gEfiGlobalVariableGuid,
673 &DriverOrderListSize
674 );
675 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
676 ASSERT (NewDriverOrderList != NULL);
677 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
678 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
679 if (DriverOrderList != NULL) {
680 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
681 }
682
683 Status = gRT->SetVariable (
684 L"DriverOrder",
685 &gEfiGlobalVariableGuid,
686 VAR_FLAG,
687 DriverOrderListSize + sizeof (UINT16),
688 NewDriverOrderList
689 );
690 ASSERT_EFI_ERROR (Status);
691 if (DriverOrderList != NULL) {
692 FreePool (DriverOrderList);
693 }
694 DriverOrderList = NULL;
695 FreePool (NewDriverOrderList);
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 FreePool (BootOrderList);
853 }
854
855 Status = gRT->SetVariable (
856 L"BootOrder",
857 &gEfiGlobalVariableGuid,
858 VAR_FLAG,
859 BootOrderListSize + sizeof (UINT16),
860 NewBootOrderList
861 );
862 ASSERT_EFI_ERROR (Status);
863
864 FreePool (NewBootOrderList);
865 NewBootOrderList = NULL;
866 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
867 BootOptionMenu.MenuNumber++;
868
869 NvRamMap->DescriptionData[0] = 0x0000;
870 NvRamMap->OptionalData[0] = 0x0000;
871 return EFI_SUCCESS;
872 }
873
874 /**
875 This function update the "BootNext" EFI Variable. If there is
876 no "BootNex" specified in BMM, this EFI Variable is deleted.
877 It also update the BMM context data specified the "BootNext"
878 vaule.
879
880 @param CallbackData The BMM context data.
881
882 @retval EFI_SUCCESS The function complete successfully.
883 @return The EFI variable can be saved. See gRT->SetVariable
884 for detail return information.
885
886 **/
887 EFI_STATUS
888 Var_UpdateBootNext (
889 IN BMM_CALLBACK_DATA *CallbackData
890 )
891 {
892 BM_MENU_ENTRY *NewMenuEntry;
893 BM_LOAD_CONTEXT *NewLoadContext;
894 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
895 UINT16 Index;
896 EFI_STATUS Status;
897
898 Status = EFI_SUCCESS;
899 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
900 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
901 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
902 ASSERT (NULL != NewMenuEntry);
903
904 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
905 NewLoadContext->IsBootNext = FALSE;
906 }
907
908 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
909 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
910 return EFI_SUCCESS;
911 }
912
913 NewMenuEntry = BOpt_GetMenuEntry (
914 &BootOptionMenu,
915 CurrentFakeNVMap->BootNext
916 );
917 ASSERT (NewMenuEntry != NULL);
918
919 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
920 Status = gRT->SetVariable (
921 L"BootNext",
922 &gEfiGlobalVariableGuid,
923 VAR_FLAG,
924 sizeof (UINT16),
925 &NewMenuEntry->OptionNumber
926 );
927 NewLoadContext->IsBootNext = TRUE;
928 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
929 return Status;
930 }
931
932 /**
933 This function update the "BootOrder" EFI Variable based on
934 BMM Formset's NV map. It then refresh BootOptionMenu
935 with the new "BootOrder" list.
936
937 @param CallbackData The BMM context data.
938
939 @retval EFI_SUCCESS The function complete successfully.
940 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
941 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
942
943 **/
944 EFI_STATUS
945 Var_UpdateBootOrder (
946 IN BMM_CALLBACK_DATA *CallbackData
947 )
948 {
949 EFI_STATUS Status;
950 UINT16 Index;
951 UINT16 *BootOrderList;
952 UINT16 *NewBootOrderList;
953 UINTN BootOrderListSize;
954
955 BootOrderList = NULL;
956 BootOrderListSize = 0;
957
958 //
959 // First check whether BootOrder is present in current configuration
960 //
961 BootOrderList = BdsLibGetVariableAndSize (
962 L"BootOrder",
963 &gEfiGlobalVariableGuid,
964 &BootOrderListSize
965 );
966
967 NewBootOrderList = AllocateZeroPool (BootOrderListSize);
968 if (NewBootOrderList == NULL) {
969 return EFI_OUT_OF_RESOURCES;
970 }
971
972 //
973 // If exists, delete it to hold new BootOrder
974 //
975 if (BootOrderList != NULL) {
976 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
977 FreePool (BootOrderList);
978 }
979
980 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
981 NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
982 }
983
984 Status = gRT->SetVariable (
985 L"BootOrder",
986 &gEfiGlobalVariableGuid,
987 VAR_FLAG,
988 BootOrderListSize,
989 NewBootOrderList
990 );
991 FreePool (NewBootOrderList);
992 if (EFI_ERROR (Status)) {
993 return Status;
994 }
995
996 BOpt_FreeMenu (&BootOptionMenu);
997 BOpt_GetBootOptions (CallbackData);
998
999 return EFI_SUCCESS;
1000
1001 }
1002
1003 /**
1004 This function update the "DriverOrder" EFI Variable based on
1005 BMM Formset's NV map. It then refresh DriverOptionMenu
1006 with the new "DriverOrder" list.
1007
1008 @param CallbackData The BMM context data.
1009
1010 @retval EFI_SUCCESS The function complete successfully.
1011 @retval EFI_SUCCESS Not enough memory to complete the function.
1012 @return The EFI variable can be saved. See gRT->SetVariable
1013 for detail return information.
1014
1015 **/
1016 EFI_STATUS
1017 Var_UpdateDriverOrder (
1018 IN BMM_CALLBACK_DATA *CallbackData
1019 )
1020 {
1021 EFI_STATUS Status;
1022 UINT16 Index;
1023 UINT16 *DriverOrderList;
1024 UINT16 *NewDriverOrderList;
1025 UINTN DriverOrderListSize;
1026
1027 DriverOrderList = NULL;
1028 DriverOrderListSize = 0;
1029
1030 //
1031 // First check whether DriverOrder is present in current configuration
1032 //
1033 DriverOrderList = BdsLibGetVariableAndSize (
1034 L"DriverOrder",
1035 &gEfiGlobalVariableGuid,
1036 &DriverOrderListSize
1037 );
1038
1039 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
1040
1041 if (NewDriverOrderList == NULL) {
1042 return EFI_OUT_OF_RESOURCES;
1043 }
1044 //
1045 // If exists, delete it to hold new DriverOrder
1046 //
1047 if (DriverOrderList != NULL) {
1048 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
1049 FreePool (DriverOrderList);
1050 }
1051
1052 for (Index = 0; Index < DriverOrderListSize; Index++) {
1053 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
1054 }
1055
1056 Status = gRT->SetVariable (
1057 L"DriverOrder",
1058 &gEfiGlobalVariableGuid,
1059 VAR_FLAG,
1060 DriverOrderListSize,
1061 NewDriverOrderList
1062 );
1063 if (EFI_ERROR (Status)) {
1064 return Status;
1065 }
1066
1067 BOpt_FreeMenu (&DriverOptionMenu);
1068 BOpt_GetDriverOptions (CallbackData);
1069 return EFI_SUCCESS;
1070 }
1071
1072 /**
1073 Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable
1074 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
1075 is also updated.
1076
1077 @param CallbackData The context data for BMM.
1078
1079 @return EFI_SUCCESS The function completed successfully.
1080 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.
1081
1082 **/
1083 EFI_STATUS
1084 Var_UpdateBBSOption (
1085 IN BMM_CALLBACK_DATA *CallbackData
1086 )
1087 {
1088 UINTN Index;
1089 UINTN Index2;
1090 VOID *BootOptionVar;
1091 CHAR16 VarName[100];
1092 UINTN OptionSize;
1093 UINT8 *Ptr;
1094 EFI_STATUS Status;
1095 CHAR16 DescString[100];
1096 CHAR8 DescAsciiString[100];
1097 UINTN NewOptionSize;
1098 UINT8 *NewOptionPtr;
1099 UINT8 *TempPtr;
1100 UINT32 *Attribute;
1101 BM_MENU_OPTION *OptionMenu;
1102 BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
1103 UINT8 *LegacyDev;
1104 UINT8 *VarData;
1105 UINTN VarSize;
1106 BM_MENU_ENTRY *NewMenuEntry;
1107 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
1108 UINT8 *OriginalPtr;
1109 UINT8 *DisMap;
1110 UINTN Pos;
1111 UINTN Bit;
1112 UINT16 *NewOrder;
1113 UINT16 Tmp;
1114
1115 LegacyDeviceContext = NULL;
1116 DisMap = NULL;
1117 NewOrder = NULL;
1118
1119 if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1120 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
1121 LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;
1122 CallbackData->BbsType = BBS_FLOPPY;
1123 } else {
1124 if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1125 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
1126 LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;
1127 CallbackData->BbsType = BBS_HARDDISK;
1128 } else {
1129 if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1130 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
1131 LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;
1132 CallbackData->BbsType = BBS_CDROM;
1133 } else {
1134 if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
1135 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
1136 LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;
1137 CallbackData->BbsType = BBS_EMBED_NETWORK;
1138 } else {
1139 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
1140 LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;
1141 CallbackData->BbsType = BBS_BEV_DEVICE;
1142 }
1143 }
1144 }
1145 }
1146
1147 DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
1148 Status = EFI_SUCCESS;
1149
1150 //
1151 // Find the first device's context
1152 // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
1153 // because we just use it to fill the desc string, and user can not see the string in UI
1154 //
1155 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1156 NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
1157 LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
1158 if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
1159 DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
1160 break;
1161 }
1162 }
1163 //
1164 // Update the Variable "LegacyDevOrder"
1165 //
1166 VarData = (UINT8 *) BdsLibGetVariableAndSize (
1167 VAR_LEGACY_DEV_ORDER,
1168 &EfiLegacyDevOrderGuid,
1169 &VarSize
1170 );
1171
1172 if (NULL == VarData) {
1173 return EFI_NOT_FOUND;
1174 }
1175
1176 OriginalPtr = VarData;
1177 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1178
1179 while (VarData < VarData + VarSize) {
1180 if (DevOrder->BbsType == CallbackData->BbsType) {
1181 break;
1182 }
1183
1184 VarData += sizeof (BBS_TYPE);
1185 VarData += *(UINT16 *) VarData;
1186 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1187 }
1188
1189 if (VarData >= VarData + VarSize) {
1190 FreePool (OriginalPtr);
1191 return EFI_NOT_FOUND;
1192 }
1193
1194 NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));
1195 if (NULL == NewOrder) {
1196 FreePool (VarData);
1197 return EFI_OUT_OF_RESOURCES;
1198 }
1199
1200 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1201 if (0xFF == LegacyDev[Index]) {
1202 break;
1203 }
1204
1205 NewOrder[Index] = LegacyDev[Index];
1206 }
1207 //
1208 // Only the enable/disable state of each boot device with same device type can be changed,
1209 // so we can count on the index information in DevOrder.
1210 // DisMap bit array is the only reliable source to check a device's en/dis state,
1211 // so we use DisMap to set en/dis state of each item in NewOrder array
1212 //
1213 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
1214 Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
1215 Tmp &= 0xFF;
1216 Pos = Tmp / 8;
1217 Bit = 7 - (Tmp % 8);
1218 if ((DisMap[Pos] & (1 << Bit)) != 0) {
1219 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
1220 Index++;
1221 }
1222 }
1223
1224 CopyMem (
1225 (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
1226 NewOrder,
1227 DevOrder->Length - sizeof (UINT16)
1228 );
1229 FreePool (NewOrder);
1230
1231 Status = gRT->SetVariable (
1232 VAR_LEGACY_DEV_ORDER,
1233 &EfiLegacyDevOrderGuid,
1234 VAR_FLAG,
1235 VarSize,
1236 OriginalPtr
1237 );
1238
1239 FreePool (OriginalPtr);
1240
1241 //
1242 // Update Optional Data of Boot####
1243 //
1244 BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
1245
1246 if (NULL != BootOptionVar) {
1247 CopyMem (
1248 DescString,
1249 LegacyDeviceContext->Description,
1250 StrSize (LegacyDeviceContext->Description)
1251 );
1252
1253 UnicodeStrToAsciiStr((CONST CHAR16*)&DescString, (CHAR8 *)&DescAsciiString);
1254
1255 NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +
1256 sizeof (BBS_BBS_DEVICE_PATH);
1257 NewOptionSize += AsciiStrLen (DescAsciiString) +
1258 END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);
1259
1260 UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
1261
1262 Ptr = BootOptionVar;
1263
1264 Attribute = (UINT32 *) Ptr;
1265 *Attribute |= LOAD_OPTION_ACTIVE;
1266 if (0xFF == LegacyDev[0]) {
1267 //
1268 // Disable this legacy boot option
1269 //
1270 *Attribute &= ~LOAD_OPTION_ACTIVE;
1271 }
1272
1273 Ptr += sizeof (UINT32);
1274
1275 Ptr += sizeof (UINT16);
1276 Ptr += StrSize ((CHAR16 *) Ptr);
1277
1278 NewOptionPtr = AllocateZeroPool (NewOptionSize);
1279 if (NULL == NewOptionPtr) {
1280 return EFI_OUT_OF_RESOURCES;
1281 }
1282
1283 TempPtr = NewOptionPtr;
1284
1285 //
1286 // Attribute
1287 //
1288 CopyMem (
1289 TempPtr,
1290 BootOptionVar,
1291 sizeof (UINT32)
1292 );
1293
1294 TempPtr += sizeof (UINT32);
1295
1296 //
1297 // BBS device path Length
1298 //
1299 *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +
1300 AsciiStrLen (DescAsciiString) +
1301 END_DEVICE_PATH_LENGTH);
1302
1303 TempPtr += sizeof (UINT16);
1304
1305 //
1306 // Description string
1307 //
1308 CopyMem (
1309 TempPtr,
1310 DescString,
1311 StrSize (DescString)
1312 );
1313
1314 TempPtr += StrSize (DescString);
1315
1316 //
1317 // BBS device path
1318 //
1319 CopyMem (
1320 TempPtr,
1321 Ptr,
1322 sizeof (BBS_BBS_DEVICE_PATH)
1323 );
1324
1325 CopyMem (
1326 ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,
1327 DescAsciiString,
1328 AsciiStrSize (DescAsciiString)
1329 );
1330
1331 SetDevicePathNodeLength (
1332 (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,
1333 sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)
1334 );
1335
1336 TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);
1337
1338 //
1339 // End node
1340 //
1341 CopyMem (
1342 TempPtr,
1343 EndDevicePath,
1344 END_DEVICE_PATH_LENGTH
1345 );
1346 TempPtr += END_DEVICE_PATH_LENGTH;
1347
1348 //
1349 // Now TempPtr point to optional data, i.e. Bbs Table
1350 //
1351 CopyMem (
1352 TempPtr,
1353 LegacyDeviceContext->BbsTable,
1354 sizeof (BBS_TABLE)
1355 );
1356
1357 //
1358 // Now TempPtr point to BBS index
1359 //
1360 TempPtr += sizeof (BBS_TABLE);
1361 *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
1362
1363 Status = gRT->SetVariable (
1364 VarName,
1365 &gEfiGlobalVariableGuid,
1366 VAR_FLAG,
1367 NewOptionSize,
1368 NewOptionPtr
1369 );
1370
1371 FreePool (NewOptionPtr);
1372 FreePool (BootOptionVar);
1373 }
1374
1375 BOpt_GetBootOptions (CallbackData);
1376 return Status;
1377 }
1378
1379 /**
1380 Update the Text Mode of Console.
1381
1382 @param CallbackData The context data for BMM.
1383
1384 @retval EFI_SUCCSS If the Text Mode of Console is updated.
1385 @return Other value if the Text Mode of Console is not updated.
1386
1387 **/
1388 EFI_STATUS
1389 Var_UpdateConMode (
1390 IN BMM_CALLBACK_DATA *CallbackData
1391 )
1392 {
1393 EFI_STATUS Status;
1394 UINTN Mode;
1395 CONSOLE_OUT_MODE ModeInfo;
1396
1397 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
1398
1399 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
1400 if (EFI_ERROR(Status)) {
1401 ModeInfo.Column = 80;
1402 ModeInfo.Row = 25;
1403 }
1404
1405 Status = gRT->SetVariable (
1406 VAR_CON_OUT_MODE,
1407 &gEfiGenericPlatformVariableGuid,
1408 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1409 sizeof (CONSOLE_OUT_MODE),
1410 &ModeInfo
1411 );
1412
1413 return Status;
1414 }