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