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