]> git.proxmox.com Git - mirror_edk2.git/blob - EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Variable.c
d0c5c9bafb542b8af97848076923dc34669090ba
[mirror_edk2.git] / EdkNt32Pkg / 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 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
454 Temp = DevicePathToStr (TerminalDevicePath);
455 ConDevicePath = AppendDevicePathInstance (
456 ConDevicePath,
457 TerminalDevicePath
458 );
459 }
460 }
461
462 if (ConDevicePath) {
463 Status = gRT->SetVariable (
464 ConsoleName,
465 &gEfiGlobalVariableGuid,
466 VAR_FLAG,
467 GetDevicePathSize (ConDevicePath),
468 ConDevicePath
469 );
470 if (EFI_ERROR (Status)) {
471 return Status;
472 }
473 }
474
475 return EFI_SUCCESS;
476
477 }
478
479 EFI_STATUS
480 Var_UpdateConsoleInpOption (
481 VOID
482 )
483 {
484 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
485 }
486
487 EFI_STATUS
488 Var_UpdateConsoleOutOption (
489 VOID
490 )
491 {
492 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
493 }
494
495 EFI_STATUS
496 Var_UpdateErrorOutOption (
497 VOID
498 )
499 {
500 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
501 }
502
503 EFI_STATUS
504 Var_UpdateDriverOption (
505 IN BMM_CALLBACK_DATA *CallbackData,
506 IN EFI_HII_HANDLE HiiHandle,
507 IN UINT16 *DescriptionData,
508 IN UINT16 *OptionalData,
509 IN UINT8 ForceReconnect
510 )
511 {
512 UINT16 Index;
513 UINT16 *DriverOrderList;
514 UINT16 *NewDriverOrderList;
515 UINT16 DriverString[12];
516 UINTN DriverOrderListSize;
517 VOID *Buffer;
518 UINTN BufferSize;
519 UINT8 *Ptr;
520 BM_MENU_ENTRY *NewMenuEntry;
521 BM_LOAD_CONTEXT *NewLoadContext;
522 BOOLEAN OptionalDataExist;
523 EFI_STATUS Status;
524
525 OptionalDataExist = FALSE;
526
527 Index = BOpt_GetDriverOptionNumber ();
528 UnicodeSPrint (
529 DriverString,
530 sizeof (DriverString),
531 L"Driver%04x",
532 Index
533 );
534
535 if (*DescriptionData == 0x0000) {
536 StrCpy (DescriptionData, DriverString);
537 }
538
539 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);
540
541 if (*OptionalData != 0x0000) {
542 OptionalDataExist = TRUE;
543 BufferSize += StrSize (OptionalData);
544 }
545
546 Buffer = AllocateZeroPool (BufferSize);
547 if (NULL == Buffer) {
548 return EFI_OUT_OF_RESOURCES;
549 }
550
551 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
552 if (NULL == NewMenuEntry) {
553 return EFI_OUT_OF_RESOURCES;
554 }
555
556 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
557 NewLoadContext->Deleted = FALSE;
558 NewLoadContext->LoadOptionSize = BufferSize;
559 Ptr = (UINT8 *) Buffer;
560 NewLoadContext->LoadOption = Ptr;
561 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
562 NewLoadContext->Attributes = *((UINT32 *) Ptr);
563 NewLoadContext->IsActive = TRUE;
564 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
565
566 Ptr += sizeof (UINT32);
567 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
568 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
569
570 Ptr += sizeof (UINT16);
571 CopyMem (
572 Ptr,
573 DescriptionData,
574 StrSize (DescriptionData)
575 );
576
577 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
578 ASSERT (NewLoadContext->Description != NULL);
579 NewMenuEntry->DisplayString = NewLoadContext->Description;
580 CopyMem (
581 NewLoadContext->Description,
582 (VOID *) Ptr,
583 StrSize (DescriptionData)
584 );
585
586 Ptr += StrSize (DescriptionData);
587 CopyMem (
588 Ptr,
589 CallbackData->LoadContext->FilePathList,
590 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
591 );
592
593 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
594 ASSERT (NewLoadContext->FilePathList != NULL);
595
596 CopyMem (
597 NewLoadContext->FilePathList,
598 (VOID *) Ptr,
599 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
600 );
601
602 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
603 NewMenuEntry->OptionNumber = Index;
604 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
605 CallbackData,
606 DriverOptionStrDepository
607 );
608 CallbackData->Hii->NewString (
609 CallbackData->Hii,
610 NULL,
611 HiiHandle,
612 &NewMenuEntry->DisplayStringToken,
613 NewMenuEntry->DisplayString
614 );
615
616 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
617 CallbackData,
618 DriverOptionHelpStrDepository
619 );
620 CallbackData->Hii->NewString (
621 CallbackData->Hii,
622 NULL,
623 HiiHandle,
624 &NewMenuEntry->HelpStringToken,
625 NewMenuEntry->HelpString
626 );
627
628 if (OptionalDataExist) {
629 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
630
631 CopyMem (
632 Ptr,
633 OptionalData,
634 StrSize (OptionalData)
635 );
636 }
637
638 Status = gRT->SetVariable (
639 DriverString,
640 &gEfiGlobalVariableGuid,
641 VAR_FLAG,
642 BufferSize,
643 Buffer
644 );
645 DriverOrderList = BdsLibGetVariableAndSize (
646 L"DriverOrder",
647 &gEfiGlobalVariableGuid,
648 &DriverOrderListSize
649 );
650 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
651 ASSERT (NewDriverOrderList != NULL);
652 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
653 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
654 if (DriverOrderList != NULL) {
655 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
656 }
657
658 Status = gRT->SetVariable (
659 L"DriverOrder",
660 &gEfiGlobalVariableGuid,
661 VAR_FLAG,
662 DriverOrderListSize + sizeof (UINT16),
663 NewDriverOrderList
664 );
665 SafeFreePool (DriverOrderList);
666 DriverOrderList = NULL;
667 SafeFreePool (NewDriverOrderList);
668 NewDriverOrderList = NULL;
669 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
670 DriverOptionMenu.MenuNumber++;
671
672 *DescriptionData = 0x0000;
673 *OptionalData = 0x0000;
674 return EFI_SUCCESS;
675 }
676
677 EFI_STATUS
678 Var_UpdateBootOption (
679 IN BMM_CALLBACK_DATA *CallbackData,
680 IN FILE_EXPLORER_NV_DATA *NvRamMap
681 )
682 {
683 UINT16 *BootOrderList;
684 UINT16 *NewBootOrderList;
685 UINTN BootOrderListSize;
686 UINT16 BootString[10];
687 VOID *Buffer;
688 UINTN BufferSize;
689 UINT8 *Ptr;
690 UINT16 Index;
691 BM_MENU_ENTRY *NewMenuEntry;
692 BM_LOAD_CONTEXT *NewLoadContext;
693 BOOLEAN OptionalDataExist;
694 EFI_STATUS Status;
695
696 OptionalDataExist = FALSE;
697
698 Index = BOpt_GetBootOptionNumber ();
699 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
700
701 if (NvRamMap->DescriptionData[0] == 0x0000) {
702 StrCpy (NvRamMap->DescriptionData, BootString);
703 }
704
705 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);
706
707 if (NvRamMap->OptionalData[0] != 0x0000) {
708 OptionalDataExist = TRUE;
709 BufferSize += StrSize (NvRamMap->OptionalData);
710 }
711
712 Buffer = AllocateZeroPool (BufferSize);
713 if (NULL == Buffer) {
714 return EFI_OUT_OF_RESOURCES;
715 }
716
717 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
718 if (NULL == NewMenuEntry) {
719 return EFI_OUT_OF_RESOURCES;
720 }
721
722 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
723 NewLoadContext->Deleted = FALSE;
724 NewLoadContext->LoadOptionSize = BufferSize;
725 Ptr = (UINT8 *) Buffer;
726 NewLoadContext->LoadOption = Ptr;
727 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
728 NewLoadContext->Attributes = *((UINT32 *) Ptr);
729 NewLoadContext->IsActive = TRUE;
730 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
731
732 Ptr += sizeof (UINT32);
733 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
734 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
735 Ptr += sizeof (UINT16);
736
737 CopyMem (
738 Ptr,
739 NvRamMap->DescriptionData,
740 StrSize (NvRamMap->DescriptionData)
741 );
742
743 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));
744 ASSERT (NewLoadContext->Description != NULL);
745
746 NewMenuEntry->DisplayString = NewLoadContext->Description;
747 CopyMem (
748 NewLoadContext->Description,
749 (VOID *) Ptr,
750 StrSize (NvRamMap->DescriptionData)
751 );
752
753 Ptr += StrSize (NvRamMap->DescriptionData);
754 CopyMem (
755 Ptr,
756 CallbackData->LoadContext->FilePathList,
757 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
758 );
759
760 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
761 ASSERT (NewLoadContext->FilePathList != NULL);
762
763 CopyMem (
764 NewLoadContext->FilePathList,
765 (VOID *) Ptr,
766 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
767 );
768
769 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
770 NewMenuEntry->OptionNumber = Index;
771 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
772 CallbackData,
773 BootOptionStrDepository
774 );
775 CallbackData->Hii->NewString (
776 CallbackData->Hii,
777 NULL,
778 CallbackData->FeHiiHandle,
779 &NewMenuEntry->DisplayStringToken,
780 NewMenuEntry->DisplayString
781 );
782
783 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
784 CallbackData,
785 BootOptionHelpStrDepository
786 );
787
788 CallbackData->Hii->NewString (
789 CallbackData->Hii,
790 NULL,
791 CallbackData->FeHiiHandle,
792 &NewMenuEntry->HelpStringToken,
793 NewMenuEntry->HelpString
794 );
795
796 if (OptionalDataExist) {
797 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
798
799 CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
800 }
801
802 Status = gRT->SetVariable (
803 BootString,
804 &gEfiGlobalVariableGuid,
805 VAR_FLAG,
806 BufferSize,
807 Buffer
808 );
809
810 BootOrderList = BdsLibGetVariableAndSize (
811 L"BootOrder",
812 &gEfiGlobalVariableGuid,
813 &BootOrderListSize
814 );
815
816 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
817 ASSERT (NewBootOrderList != NULL);
818 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
819 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
820
821 if (BootOrderList != NULL) {
822 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
823 }
824
825 Status = gRT->SetVariable (
826 L"BootOrder",
827 &gEfiGlobalVariableGuid,
828 VAR_FLAG,
829 BootOrderListSize + sizeof (UINT16),
830 NewBootOrderList
831 );
832
833 SafeFreePool (BootOrderList);
834 BootOrderList = NULL;
835 SafeFreePool (NewBootOrderList);
836 NewBootOrderList = NULL;
837 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
838 BootOptionMenu.MenuNumber++;
839
840 NvRamMap->DescriptionData[0] = 0x0000;
841 NvRamMap->OptionalData[0] = 0x0000;
842 return EFI_SUCCESS;
843 }
844
845 EFI_STATUS
846 Var_UpdateBootNext (
847 IN BMM_CALLBACK_DATA *CallbackData
848 )
849 {
850 BM_MENU_ENTRY *NewMenuEntry;
851 BM_LOAD_CONTEXT *NewLoadContext;
852 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
853 UINT16 Index;
854 EFI_STATUS Status;
855
856 Status = EFI_SUCCESS;
857 CurrentFakeNVMap = CallbackData->BmmFakeNvData;
858 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
859 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
860 if (NULL == NewMenuEntry) {
861 return EFI_NOT_FOUND;
862 }
863
864 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
865 NewLoadContext->IsBootNext = FALSE;
866 }
867
868 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
869 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
870 return EFI_SUCCESS;
871 }
872
873 NewMenuEntry = BOpt_GetMenuEntry (
874 &BootOptionMenu,
875 CurrentFakeNVMap->BootNext
876 );
877 if (NULL == NewMenuEntry) {
878 return EFI_NOT_FOUND;
879 }
880
881 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
882 Status = gRT->SetVariable (
883 L"BootNext",
884 &gEfiGlobalVariableGuid,
885 VAR_FLAG,
886 sizeof (UINT16),
887 &NewMenuEntry->OptionNumber
888 );
889 NewLoadContext->IsBootNext = TRUE;
890 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
891 return Status;
892 }
893
894 EFI_STATUS
895 Var_UpdateBootOrder (
896 IN BMM_CALLBACK_DATA *CallbackData
897 )
898 {
899 EFI_STATUS Status;
900 UINT16 Index;
901 UINT16 *BootOrderList;
902 UINT16 *NewBootOrderList;
903 UINTN BootOrderListSize;
904 UINT8 *Map;
905
906 BootOrderList = NULL;
907 BootOrderListSize = 0;
908
909 //
910 // First check whether BootOrder is present in current configuration
911 //
912 BootOrderList = BdsLibGetVariableAndSize (
913 L"BootOrder",
914 &gEfiGlobalVariableGuid,
915 &BootOrderListSize
916 );
917
918 NewBootOrderList = AllocateZeroPool (BootOrderListSize);
919 if (!NewBootOrderList) {
920 return EFI_OUT_OF_RESOURCES;
921 }
922
923 Map = AllocateZeroPool (BootOrderListSize / sizeof (UINT16));
924 if (!Map) {
925 return EFI_OUT_OF_RESOURCES;
926 }
927 //
928 // If exists, delete it to hold new BootOrder
929 //
930 if (BootOrderList) {
931 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
932 }
933
934 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
935 NewBootOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;
936 }
937
938 Status = gRT->SetVariable (
939 L"BootOrder",
940 &gEfiGlobalVariableGuid,
941 VAR_FLAG,
942 BootOrderListSize,
943 NewBootOrderList
944 );
945 SafeFreePool (BootOrderList);
946 SafeFreePool (NewBootOrderList);
947 SafeFreePool (Map);
948 if (EFI_ERROR (Status)) {
949 return Status;
950 }
951
952 BOpt_FreeMenu (&BootOptionMenu);
953 BOpt_GetBootOptions (CallbackData);
954
955 return EFI_SUCCESS;
956
957 }
958
959 EFI_STATUS
960 Var_UpdateDriverOrder (
961 IN BMM_CALLBACK_DATA *CallbackData
962 )
963 {
964 EFI_STATUS Status;
965 UINT16 Index;
966 UINT16 *DriverOrderList;
967 UINT16 *NewDriverOrderList;
968 UINTN DriverOrderListSize;
969
970 DriverOrderList = NULL;
971 DriverOrderListSize = 0;
972
973 //
974 // First check whether DriverOrder is present in current configuration
975 //
976 DriverOrderList = BdsLibGetVariableAndSize (
977 L"DriverOrder",
978 &gEfiGlobalVariableGuid,
979 &DriverOrderListSize
980 );
981
982 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
983
984 if (!NewDriverOrderList) {
985 return EFI_OUT_OF_RESOURCES;
986 }
987 //
988 // If exists, delete it to hold new DriverOrder
989 //
990 if (DriverOrderList) {
991 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
992 }
993
994 for (Index = 0; Index < DriverOrderListSize; Index++) {
995 NewDriverOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;
996 }
997
998 Status = gRT->SetVariable (
999 L"DriverOrder",
1000 &gEfiGlobalVariableGuid,
1001 VAR_FLAG,
1002 DriverOrderListSize,
1003 NewDriverOrderList
1004 );
1005 if (EFI_ERROR (Status)) {
1006 return Status;
1007 }
1008
1009 SafeFreePool (DriverOrderList);
1010
1011 BOpt_FreeMenu (&DriverOptionMenu);
1012 BOpt_GetDriverOptions (CallbackData);
1013 return EFI_SUCCESS;
1014 }
1015
1016 EFI_STATUS
1017 Var_UpdateBBSOption (
1018 IN BMM_CALLBACK_DATA *CallbackData
1019 )
1020 {
1021 UINTN Index;
1022 UINTN Index2;
1023 VOID *BootOptionVar;
1024 CHAR16 VarName[100];
1025 UINTN OptionSize;
1026 UINT16 FilePathSize;
1027 UINT8 *Ptr;
1028 EFI_STATUS Status;
1029 CHAR16 DescString[100];
1030 UINTN NewOptionSize;
1031 UINT8 *NewOptionPtr;
1032 UINT8 *TempPtr;
1033 UINT32 *Attribute;
1034
1035 BM_MENU_OPTION *OptionMenu;
1036 BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
1037 UINT8 *LegacyDev;
1038 UINT8 *VarData;
1039 UINTN VarSize;
1040 BM_MENU_ENTRY *NewMenuEntry;
1041 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
1042 UINT8 *OriginalPtr;
1043 UINT8 *DisMap;
1044 UINTN Pos;
1045 UINTN Bit;
1046 UINT16 *NewOrder;
1047 UINT16 Tmp;
1048
1049 LegacyDeviceContext = NULL;
1050 DisMap = NULL;
1051 NewOrder = NULL;
1052
1053 if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1054 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
1055 LegacyDev = CallbackData->BmmFakeNvData->LegacyFD;
1056 CallbackData->BbsType = BBS_FLOPPY;
1057 } else {
1058 if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1059 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
1060 LegacyDev = CallbackData->BmmFakeNvData->LegacyHD;
1061 CallbackData->BbsType = BBS_HARDDISK;
1062 } else {
1063 if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
1064 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
1065 LegacyDev = CallbackData->BmmFakeNvData->LegacyCD;
1066 CallbackData->BbsType = BBS_CDROM;
1067 } else {
1068 if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
1069 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
1070 LegacyDev = CallbackData->BmmFakeNvData->LegacyNET;
1071 CallbackData->BbsType = BBS_EMBED_NETWORK;
1072 } else {
1073 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
1074 LegacyDev = CallbackData->BmmFakeNvData->LegacyBEV;
1075 CallbackData->BbsType = BBS_BEV_DEVICE;
1076 }
1077 }
1078 }
1079 }
1080
1081 DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
1082 Status = EFI_SUCCESS;
1083
1084 //
1085 // Find the first device's context
1086 // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
1087 // because we just use it to fill the desc string, and user can not see the string in UI
1088 //
1089 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1090 NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
1091 LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
1092 if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
1093 DEBUG ((EFI_D_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
1094 break;
1095 }
1096 }
1097 //
1098 // Update the Variable "LegacyDevOrder"
1099 //
1100 VarData = (UINT8 *) BdsLibGetVariableAndSize (
1101 VarLegacyDevOrder,
1102 &EfiLegacyDevOrderGuid,
1103 &VarSize
1104 );
1105
1106 if (NULL == VarData) {
1107 return EFI_NOT_FOUND;
1108 }
1109
1110 OriginalPtr = VarData;
1111 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1112
1113 while (VarData < VarData + VarSize) {
1114 if (DevOrder->BbsType == CallbackData->BbsType) {
1115 break;
1116 }
1117
1118 VarData += sizeof (BBS_TYPE);
1119 VarData += *(UINT16 *) VarData;
1120 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
1121 }
1122
1123 if (VarData >= VarData + VarSize) {
1124 SafeFreePool (OriginalPtr);
1125 return EFI_NOT_FOUND;
1126 }
1127
1128 NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));
1129 if (NULL == NewOrder) {
1130 SafeFreePool (VarData);
1131 return EFI_OUT_OF_RESOURCES;
1132 }
1133
1134 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1135 if (0xFF == LegacyDev[Index]) {
1136 break;
1137 }
1138
1139 NewOrder[Index] = LegacyDev[Index];
1140 }
1141 //
1142 // Only the enable/disable state of each boot device with same device type can be changed,
1143 // so we can count on the index information in DevOrder.
1144 // DisMap bit array is the only reliable source to check a device's en/dis state,
1145 // so we use DisMap to set en/dis state of each item in NewOrder array
1146 //
1147 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
1148 Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
1149 Tmp &= 0xFF;
1150 Pos = Tmp / 8;
1151 Bit = 7 - (Tmp % 8);
1152 if (DisMap[Pos] & (1 << Bit)) {
1153 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
1154 Index++;
1155 }
1156 }
1157
1158 CopyMem (
1159 (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
1160 NewOrder,
1161 DevOrder->Length - sizeof (UINT16)
1162 );
1163 SafeFreePool (NewOrder);
1164
1165 Status = gRT->SetVariable (
1166 VarLegacyDevOrder,
1167 &EfiLegacyDevOrderGuid,
1168 VAR_FLAG,
1169 VarSize,
1170 OriginalPtr
1171 );
1172
1173 SafeFreePool (OriginalPtr);
1174
1175 //
1176 // Update Optional Data of Boot####
1177 //
1178 BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
1179
1180 if (NULL != BootOptionVar) {
1181 CopyMem (
1182 DescString,
1183 LegacyDeviceContext->Description,
1184 StrSize (LegacyDeviceContext->Description)
1185 );
1186
1187 NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) + sizeof (BBS_TABLE) + sizeof (UINT16);
1188
1189 UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
1190
1191 Ptr = BootOptionVar;
1192
1193 Attribute = (UINT32 *) Ptr;
1194 *Attribute |= LOAD_OPTION_ACTIVE;
1195 if (0xFF == LegacyDev[0]) {
1196 //
1197 // Disable this legacy boot option
1198 //
1199 *Attribute &= ~LOAD_OPTION_ACTIVE;
1200 }
1201
1202 Ptr += sizeof (UINT32);
1203
1204 FilePathSize = *(UINT16 *) Ptr;
1205 Ptr += sizeof (UINT16);
1206
1207 NewOptionSize += FilePathSize;
1208
1209 NewOptionPtr = AllocateZeroPool (NewOptionSize);
1210 if (NULL == NewOptionPtr) {
1211 return EFI_OUT_OF_RESOURCES;
1212 }
1213
1214 TempPtr = NewOptionPtr;
1215
1216 //
1217 // Copy previous option data to new option except the description string
1218 //
1219 CopyMem (
1220 TempPtr,
1221 BootOptionVar,
1222 sizeof (UINT32) + sizeof (UINT16)
1223 );
1224
1225 TempPtr += (sizeof (UINT32) + sizeof (UINT16));
1226
1227 CopyMem (
1228 TempPtr,
1229 DescString,
1230 StrSize (DescString)
1231 );
1232
1233 TempPtr += StrSize (DescString);
1234
1235 //
1236 // Description = (CHAR16 *)Ptr;
1237 //
1238 Ptr += StrSize ((CHAR16 *) Ptr);
1239
1240 CopyMem (
1241 TempPtr,
1242 Ptr,
1243 FilePathSize
1244 );
1245
1246 TempPtr += FilePathSize;
1247
1248 //
1249 // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
1250 //
1251 Ptr += FilePathSize;
1252
1253 //
1254 // Now Ptr point to optional data, i.e. Bbs Table
1255 //
1256 CopyMem (
1257 TempPtr,
1258 LegacyDeviceContext->BbsTable,
1259 sizeof (BBS_TABLE)
1260 );
1261
1262 TempPtr += sizeof (BBS_TABLE);
1263 *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
1264
1265 Status = gRT->SetVariable (
1266 VarName,
1267 &gEfiGlobalVariableGuid,
1268 VAR_FLAG,
1269 NewOptionSize,
1270 NewOptionPtr
1271 );
1272
1273 SafeFreePool (NewOptionPtr);
1274 SafeFreePool (BootOptionVar);
1275 }
1276
1277 BOpt_GetBootOptions (CallbackData);
1278 return Status;
1279 }