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