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