1 /** @file
2 Variable operation that will be used by bootmaint
3
4 Copyright (c) 2004 - 2016, 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 "BootMaintenanceManager.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
Var_DelBootOption(VOID)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
Var_ChangeBootOrder(VOID)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 // First check whether BootOrder is present in current configuration
113 //
114 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
115
116 //
117 // If exists, delete it to hold new BootOrder
118 //
119 if (BootOrderList != NULL) {
120 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
121 FreePool (BootOrderList);
122 BootOrderList = NULL;
123 }
124 //
125 // Maybe here should be some check method to ensure that
126 // no new added boot options will be added
127 // but the setup engine now will give only one callback
128 // that is to say, user are granted only one chance to
129 // decide whether the boot option will be added or not
130 // there should be no indictor to show whether this
131 // is a "new" boot option
132 //
133 BootOrderListSize = BootOptionMenu.MenuNumber;
134
135 if (BootOrderListSize > 0) {
136 BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));
137 ASSERT (BootOrderList != NULL);
138 BootOrderListPtr = BootOrderList;
139
140 //
141 // Get all current used Boot#### from BootOptionMenu.
142 // OptionNumber in each BM_LOAD_OPTION is really its
143 // #### value.
144 //
145 for (Index = 0; Index < BootOrderListSize; Index++) {
146 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
147 *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
148 BootOrderList++;
149 }
150
151 BootOrderList = BootOrderListPtr;
152
153 //
154 // After building the BootOrderList, write it back
155 //
156 Status = gRT->SetVariable (
157 L"BootOrder",
158 &gEfiGlobalVariableGuid,
159 VAR_FLAG,
160 BootOrderListSize * sizeof (UINT16),
161 BootOrderList
162 );
163 if (EFI_ERROR (Status)) {
164 return Status;
165 }
166 }
167 return EFI_SUCCESS;
168 }
169
170 /**
171 Delete Load Option that represent a Deleted state in BootOptionMenu.
172 After deleting this Driver option, call Var_ChangeDriverOrder to
173 make sure DriverOrder is in valid state.
174
175 @retval EFI_SUCCESS Load Option is successfully updated.
176 @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.
177 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI
178 Variable.
179
180 **/
181 EFI_STATUS
Var_DelDriverOption(VOID)182 Var_DelDriverOption (
183 VOID
184 )
185 {
186 BM_MENU_ENTRY *NewMenuEntry;
187 BM_LOAD_CONTEXT *NewLoadContext;
188 UINT16 DriverString[12];
189 EFI_STATUS Status;
190 UINTN Index;
191 UINTN Index2;
192
193 Status = EFI_SUCCESS;
194 Index2 = 0;
195 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
196 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
197 if (NULL == NewMenuEntry) {
198 return EFI_NOT_FOUND;
199 }
200
201 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
202 if (!NewLoadContext->Deleted) {
203 continue;
204 }
205
206 UnicodeSPrint (
207 DriverString,
208 sizeof (DriverString),
209 L"Driver%04x",
210 NewMenuEntry->OptionNumber
211 );
212
213 EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
214 Index2++;
215
216 RemoveEntryList (&NewMenuEntry->Link);
217 BOpt_DestroyMenuEntry (NewMenuEntry);
218 NewMenuEntry = NULL;
219 }
220
221 DriverOptionMenu.MenuNumber -= Index2;
222
223 Status = Var_ChangeDriverOrder ();
224 return Status;
225 }
226
227 /**
228 After any operation on Driver####, there will be a discrepancy in
229 DriverOrder. Since some are missing but in DriverOrder, while some
230 are present but are not reflected by DriverOrder. Then a function
231 rebuild DriverOrder from scratch by content from DriverOptionMenu is
232 needed.
233
234 @retval EFI_SUCCESS The driver order is updated successfully.
235 @return Other status than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.
236
237 **/
238 EFI_STATUS
Var_ChangeDriverOrder(VOID)239 Var_ChangeDriverOrder (
240 VOID
241 )
242 {
243 EFI_STATUS Status;
244 BM_MENU_ENTRY *NewMenuEntry;
245 UINT16 *DriverOrderList;
246 UINT16 *DriverOrderListPtr;
247 UINTN DriverOrderListSize;
248 UINTN Index;
249
250 DriverOrderList = NULL;
251 DriverOrderListSize = 0;
252
253 //
254 // First check whether DriverOrder is present in current configuration
255 //
256 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
257 //
258 // If exists, delete it to hold new DriverOrder
259 //
260 if (DriverOrderList != NULL) {
261 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
262 FreePool (DriverOrderList);
263 DriverOrderList = NULL;
264 }
265
266 DriverOrderListSize = DriverOptionMenu.MenuNumber;
267
268 if (DriverOrderListSize > 0) {
269 DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
270 ASSERT (DriverOrderList != NULL);
271 DriverOrderListPtr = DriverOrderList;
272
273 //
274 // Get all current used Driver#### from DriverOptionMenu.
275 // OptionNumber in each BM_LOAD_OPTION is really its
276 // #### value.
277 //
278 for (Index = 0; Index < DriverOrderListSize; Index++) {
279 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
280 *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
281 DriverOrderList++;
282 }
283
284 DriverOrderList = DriverOrderListPtr;
285
286 //
287 // After building the DriverOrderList, write it back
288 //
289 Status = gRT->SetVariable (
290 L"DriverOrder",
291 &gEfiGlobalVariableGuid,
292 VAR_FLAG,
293 DriverOrderListSize * sizeof (UINT16),
294 DriverOrderList
295 );
296 if (EFI_ERROR (Status)) {
297 return Status;
298 }
299 }
300 return EFI_SUCCESS;
301 }
302
303 /**
304 This function delete and build multi-instance device path for
305 specified type of console device.
306
307 This function clear the EFI variable defined by ConsoleName and
308 gEfiGlobalVariableGuid. It then build the multi-instance device
309 path by appending the device path of the Console (In/Out/Err) instance
310 in ConsoleMenu. Then it scan all corresponding console device by
311 scanning Terminal (built from device supporting Serial I/O instances)
312 devices in TerminalMenu. At last, it save a EFI variable specifed
313 by ConsoleName and gEfiGlobalVariableGuid.
314
315 @param ConsoleName The name for the console device type. They are
316 usually "ConIn", "ConOut" and "ErrOut".
317 @param ConsoleMenu The console memu which is a list of console devices.
318 @param UpdatePageId The flag specifying which type of console device
319 to be processed.
320
321 @retval EFI_SUCCESS The function complete successfully.
322 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
323
324 **/
325 EFI_STATUS
Var_UpdateConsoleOption(IN UINT16 * ConsoleName,IN BM_MENU_OPTION * ConsoleMenu,IN UINT16 UpdatePageId)326 Var_UpdateConsoleOption (
327 IN UINT16 *ConsoleName,
328 IN BM_MENU_OPTION *ConsoleMenu,
329 IN UINT16 UpdatePageId
330 )
331 {
332 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
333 BM_MENU_ENTRY *NewMenuEntry;
334 BM_CONSOLE_CONTEXT *NewConsoleContext;
335 BM_TERMINAL_CONTEXT *NewTerminalContext;
336 EFI_STATUS Status;
337 VENDOR_DEVICE_PATH Vendor;
338 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
339 UINTN Index;
340
341 GetEfiGlobalVariable2 (ConsoleName, (VOID**)&ConDevicePath, NULL);
342 if (ConDevicePath != NULL) {
343 EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
344 FreePool (ConDevicePath);
345 ConDevicePath = NULL;
346 };
347
348 //
349 // First add all console input device from console input menu
350 //
351 for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
352 NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
353
354 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
355 if (NewConsoleContext->IsActive) {
356 ConDevicePath = AppendDevicePathInstance (
357 ConDevicePath,
358 NewConsoleContext->DevicePath
359 );
360 }
361 }
362
363 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
364 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
365
366 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
367 if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
368 ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
369 ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
370 ) {
371 Vendor.Header.Type = MESSAGING_DEVICE_PATH;
372 Vendor.Header.SubType = MSG_VENDOR_DP;
373
374 ASSERT (NewTerminalContext->TerminalType < (ARRAY_SIZE (TerminalTypeGuid)));
375 CopyMem (
376 &Vendor.Guid,
377 &TerminalTypeGuid[NewTerminalContext->TerminalType],
378 sizeof (EFI_GUID)
379 );
380 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
381 TerminalDevicePath = AppendDevicePathNode (
382 NewTerminalContext->DevicePath,
383 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
384 );
385 ASSERT (TerminalDevicePath != NULL);
386 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
387 ConDevicePath = AppendDevicePathInstance (
388 ConDevicePath,
389 TerminalDevicePath
390 );
391 }
392 }
393
394 if (ConDevicePath != NULL) {
395 Status = gRT->SetVariable (
396 ConsoleName,
397 &gEfiGlobalVariableGuid,
398 VAR_FLAG,
399 GetDevicePathSize (ConDevicePath),
400 ConDevicePath
401 );
402 if (EFI_ERROR (Status)) {
403 return Status;
404 }
405 }
406
407 return EFI_SUCCESS;
408
409 }
410
411 /**
412 This function delete and build multi-instance device path ConIn
413 console device.
414
415 @retval EFI_SUCCESS The function complete successfully.
416 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
417 **/
418 EFI_STATUS
Var_UpdateConsoleInpOption(VOID)419 Var_UpdateConsoleInpOption (
420 VOID
421 )
422 {
423 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
424 }
425
426 /**
427 This function delete and build multi-instance device path ConOut
428 console device.
429
430 @retval EFI_SUCCESS The function complete successfully.
431 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
432 **/
433 EFI_STATUS
Var_UpdateConsoleOutOption(VOID)434 Var_UpdateConsoleOutOption (
435 VOID
436 )
437 {
438 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
439 }
440
441 /**
442 This function delete and build multi-instance device path ErrOut
443 console device.
444
445 @retval EFI_SUCCESS The function complete successfully.
446 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
447 **/
448 EFI_STATUS
Var_UpdateErrorOutOption(VOID)449 Var_UpdateErrorOutOption (
450 VOID
451 )
452 {
453 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
454 }
455
456 /**
457 This function create a currently loaded Drive Option from
458 the BMM. It then appends this Driver Option to the end of
459 the "DriverOrder" list. It append this Driver Opotion to the end
460 of DriverOptionMenu.
461
462 @param CallbackData The BMM context data.
463 @param HiiHandle The HII handle associated with the BMM formset.
464 @param DescriptionData The description of this driver option.
465 @param OptionalData The optional load option.
466 @param ForceReconnect If to force reconnect.
467
468 @retval other Contain some errors when excuting this function.See function
469 EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl
470 for detail return information.
471 @retval EFI_SUCCESS If function completes successfully.
472
473 **/
474 EFI_STATUS
Var_UpdateDriverOption(IN BMM_CALLBACK_DATA * CallbackData,IN EFI_HII_HANDLE HiiHandle,IN UINT16 * DescriptionData,IN UINT16 * OptionalData,IN UINT8 ForceReconnect)475 Var_UpdateDriverOption (
476 IN BMM_CALLBACK_DATA *CallbackData,
477 IN EFI_HII_HANDLE HiiHandle,
478 IN UINT16 *DescriptionData,
479 IN UINT16 *OptionalData,
480 IN UINT8 ForceReconnect
481 )
482 {
483 UINT16 Index;
484 UINT16 DriverString[12];
485 BM_MENU_ENTRY *NewMenuEntry;
486 BM_LOAD_CONTEXT *NewLoadContext;
487 BOOLEAN OptionalDataExist;
488 EFI_STATUS Status;
489 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
490 UINT8 *OptionalDesData;
491 UINT32 OptionalDataSize;
492
493 OptionalDataExist = FALSE;
494 OptionalDesData = NULL;
495 OptionalDataSize = 0;
496
497 Index = BOpt_GetDriverOptionNumber ();
498 UnicodeSPrint (
499 DriverString,
500 sizeof (DriverString),
501 L"Driver%04x",
502 Index
503 );
504
505 if (*DescriptionData == 0x0000) {
506 StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);
507 }
508
509 if (*OptionalData != 0x0000) {
510 OptionalDataExist = TRUE;
511 OptionalDesData = (UINT8 *)OptionalData;
512 OptionalDataSize = (UINT32)StrSize (OptionalData);
513 }
514
515 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
516 if (NULL == NewMenuEntry) {
517 return EFI_OUT_OF_RESOURCES;
518 }
519
520 Status = EfiBootManagerInitializeLoadOption (
521 &LoadOption,
522 Index,
523 LoadOptionTypeDriver,
524 LOAD_OPTION_ACTIVE | (ForceReconnect << 1),
525 DescriptionData,
526 CallbackData->LoadContext->FilePathList,
527 OptionalDesData,
528 OptionalDataSize
529 );
530 if (EFI_ERROR (Status)){
531 return Status;
532 }
533
534 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );
535 if (EFI_ERROR (Status)) {
536 EfiBootManagerFreeLoadOption(&LoadOption);
537 return Status;
538 }
539
540 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
541 NewLoadContext->Deleted = FALSE;
542 NewLoadContext->Attributes = LoadOption.Attributes;
543 NewLoadContext->FilePathListLength = (UINT16)GetDevicePathSize (LoadOption.FilePath);
544
545 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
546 ASSERT (NewLoadContext->Description != NULL);
547 NewMenuEntry->DisplayString = NewLoadContext->Description;
548 CopyMem (
549 NewLoadContext->Description,
550 LoadOption.Description,
551 StrSize (DescriptionData)
552 );
553
554 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
555 ASSERT (NewLoadContext->FilePathList != NULL);
556 CopyMem (
557 NewLoadContext->FilePathList,
558 LoadOption.FilePath,
559 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
560 );
561
562 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
563 NewMenuEntry->OptionNumber = Index;
564 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);
565 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);
566
567 if (OptionalDataExist) {
568 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);
569 ASSERT (NewLoadContext->OptionalData != NULL);
570 CopyMem (
571 NewLoadContext->OptionalData,
572 LoadOption.OptionalData,
573 LoadOption.OptionalDataSize
574 );
575 }
576
577 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
578 DriverOptionMenu.MenuNumber++;
579
580 EfiBootManagerFreeLoadOption(&LoadOption);
581
582 return EFI_SUCCESS;
583 }
584
585 /**
586 This function create a currently loaded Boot Option from
587 the BMM. It then appends this Boot Option to the end of
588 the "BootOrder" list. It also append this Boot Opotion to the end
589 of BootOptionMenu.
590
591 @param CallbackData The BMM context data.
592
593 @retval other Contain some errors when excuting this function. See function
594 EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl
595 for detail return information.
596 @retval EFI_SUCCESS If function completes successfully.
597
598 **/
599 EFI_STATUS
Var_UpdateBootOption(IN BMM_CALLBACK_DATA * CallbackData)600 Var_UpdateBootOption (
601 IN BMM_CALLBACK_DATA *CallbackData
602 )
603 {
604 UINT16 BootString[10];
605 UINT16 Index;
606 BM_MENU_ENTRY *NewMenuEntry;
607 BM_LOAD_CONTEXT *NewLoadContext;
608 BOOLEAN OptionalDataExist;
609 EFI_STATUS Status;
610 BMM_FAKE_NV_DATA *NvRamMap;
611 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
612 UINT8 *OptionalData;
613 UINT32 OptionalDataSize;
614
615 OptionalDataExist = FALSE;
616 NvRamMap = &CallbackData->BmmFakeNvData;
617 OptionalData = NULL;
618 OptionalDataSize = 0;
619
620 Index = BOpt_GetBootOptionNumber () ;
621 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
622
623 if (NvRamMap->BootDescriptionData[0] == 0x0000) {
624 StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString);
625 }
626
627 if (NvRamMap->BootOptionalData[0] != 0x0000) {
628 OptionalDataExist = TRUE;
629 OptionalData = (UINT8 *)NvRamMap->BootOptionalData;
630 OptionalDataSize = (UINT32)StrSize (NvRamMap->BootOptionalData);
631 }
632
633 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
634 if (NULL == NewMenuEntry) {
635 return EFI_OUT_OF_RESOURCES;
636 }
637
638 Status = EfiBootManagerInitializeLoadOption (
639 &LoadOption,
640 Index,
641 LoadOptionTypeBoot,
642 LOAD_OPTION_ACTIVE,
643 NvRamMap->BootDescriptionData,
644 CallbackData->LoadContext->FilePathList,
645 OptionalData,
646 OptionalDataSize
647 );
648 if (EFI_ERROR (Status)){
649 return Status;
650 }
651
652 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );
653 if (EFI_ERROR (Status)) {
654 EfiBootManagerFreeLoadOption(&LoadOption);
655 return Status;
656 }
657
658 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
659 NewLoadContext->Deleted = FALSE;
660 NewLoadContext->Attributes = LoadOption.Attributes;
661 NewLoadContext->FilePathListLength = (UINT16) GetDevicePathSize (LoadOption.FilePath);
662
663 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));
664 ASSERT (NewLoadContext->Description != NULL);
665
666 NewMenuEntry->DisplayString = NewLoadContext->Description;
667
668 CopyMem (
669 NewLoadContext->Description,
670 LoadOption.Description,
671 StrSize (NvRamMap->BootDescriptionData)
672 );
673
674 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
675 ASSERT (NewLoadContext->FilePathList != NULL);
676 CopyMem (
677 NewLoadContext->FilePathList,
678 LoadOption.FilePath,
679 GetDevicePathSize (CallbackData->LoadContext->FilePathList)
680 );
681
682 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
683 NewMenuEntry->OptionNumber = Index;
684 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
685 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
686
687 if (OptionalDataExist) {
688 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);
689 ASSERT (NewLoadContext->OptionalData != NULL);
690 CopyMem (
691 NewLoadContext->OptionalData,
692 LoadOption.OptionalData,
693 LoadOption.OptionalDataSize
694 );
695 }
696
697 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
698 BootOptionMenu.MenuNumber++;
699
700 EfiBootManagerFreeLoadOption(&LoadOption);
701
702 return EFI_SUCCESS;
703 }
704
705 /**
706 This function update the "BootNext" EFI Variable. If there is
707 no "BootNext" specified in BMM, this EFI Variable is deleted.
708 It also update the BMM context data specified the "BootNext"
709 vaule.
710
711 @param CallbackData The BMM context data.
712
713 @retval EFI_SUCCESS The function complete successfully.
714 @return The EFI variable can be saved. See gRT->SetVariable
715 for detail return information.
716
717 **/
718 EFI_STATUS
Var_UpdateBootNext(IN BMM_CALLBACK_DATA * CallbackData)719 Var_UpdateBootNext (
720 IN BMM_CALLBACK_DATA *CallbackData
721 )
722 {
723 BM_MENU_ENTRY *NewMenuEntry;
724 BM_LOAD_CONTEXT *NewLoadContext;
725 BMM_FAKE_NV_DATA *CurrentFakeNVMap;
726 UINT16 Index;
727 EFI_STATUS Status;
728
729 Status = EFI_SUCCESS;
730 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
731 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
732 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
733 ASSERT (NULL != NewMenuEntry);
734
735 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
736 NewLoadContext->IsBootNext = FALSE;
737 }
738
739 if (CurrentFakeNVMap->BootNext == NONE_BOOTNEXT_VALUE) {
740 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
741 return EFI_SUCCESS;
742 }
743
744 NewMenuEntry = BOpt_GetMenuEntry (
745 &BootOptionMenu,
746 CurrentFakeNVMap->BootNext
747 );
748 ASSERT (NewMenuEntry != NULL);
749
750 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
751 Status = gRT->SetVariable (
752 L"BootNext",
753 &gEfiGlobalVariableGuid,
754 VAR_FLAG,
755 sizeof (UINT16),
756 &NewMenuEntry->OptionNumber
757 );
758 NewLoadContext->IsBootNext = TRUE;
759 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
760 return Status;
761 }
762
763 /**
764 This function update the "BootOrder" EFI Variable based on
765 BMM Formset's NV map. It then refresh BootOptionMenu
766 with the new "BootOrder" list.
767
768 @param CallbackData The BMM context data.
769
770 @retval EFI_SUCCESS The function complete successfully.
771 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
772 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
773
774 **/
775 EFI_STATUS
Var_UpdateBootOrder(IN BMM_CALLBACK_DATA * CallbackData)776 Var_UpdateBootOrder (
777 IN BMM_CALLBACK_DATA *CallbackData
778 )
779 {
780 EFI_STATUS Status;
781 UINT16 Index;
782 UINT16 OrderIndex;
783 UINT16 *BootOrder;
784 UINTN BootOrderSize;
785 UINT16 OptionNumber;
786
787 //
788 // First check whether BootOrder is present in current configuration
789 //
790 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
791 if (BootOrder == NULL) {
792 return EFI_OUT_OF_RESOURCES;
793 }
794
795 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));
796
797 //
798 // OptionOrder is subset of BootOrder
799 //
800 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {
801 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {
802 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {
803 OptionNumber = BootOrder[Index];
804 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));
805 BootOrder[OrderIndex] = OptionNumber;
806 }
807 }
808 }
809
810 Status = gRT->SetVariable (
811 L"BootOrder",
812 &gEfiGlobalVariableGuid,
813 VAR_FLAG,
814 BootOrderSize,
815 BootOrder
816 );
817 FreePool (BootOrder);
818
819 BOpt_FreeMenu (&BootOptionMenu);
820 BOpt_GetBootOptions (CallbackData);
821
822 return Status;
823
824 }
825
826 /**
827 This function update the "DriverOrder" EFI Variable based on
828 BMM Formset's NV map. It then refresh DriverOptionMenu
829 with the new "DriverOrder" list.
830
831 @param CallbackData The BMM context data.
832
833 @retval EFI_SUCCESS The function complete successfully.
834 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.
835 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.
836
837 **/
838 EFI_STATUS
Var_UpdateDriverOrder(IN BMM_CALLBACK_DATA * CallbackData)839 Var_UpdateDriverOrder (
840 IN BMM_CALLBACK_DATA *CallbackData
841 )
842 {
843 EFI_STATUS Status;
844 UINT16 Index;
845 UINT16 *DriverOrderList;
846 UINT16 *NewDriverOrderList;
847 UINTN DriverOrderListSize;
848
849 DriverOrderList = NULL;
850 DriverOrderListSize = 0;
851
852 //
853 // First check whether DriverOrder is present in current configuration
854 //
855 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
856 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
857
858 if (NewDriverOrderList == NULL) {
859 return EFI_OUT_OF_RESOURCES;
860 }
861 //
862 // If exists, delete it to hold new DriverOrder
863 //
864 if (DriverOrderList != NULL) {
865 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
866 FreePool (DriverOrderList);
867 }
868
869 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));
870 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
871 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);
872 }
873
874 Status = gRT->SetVariable (
875 L"DriverOrder",
876 &gEfiGlobalVariableGuid,
877 VAR_FLAG,
878 DriverOrderListSize,
879 NewDriverOrderList
880 );
881 if (EFI_ERROR (Status)) {
882 return Status;
883 }
884
885 BOpt_FreeMenu (&DriverOptionMenu);
886 BOpt_GetDriverOptions (CallbackData);
887 return EFI_SUCCESS;
888 }
889
890 /**
891 Update the Text Mode of Console.
892
893 @param CallbackData The context data for BMM.
894
895 @retval EFI_SUCCSS If the Text Mode of Console is updated.
896 @return Other value if the Text Mode of Console is not updated.
897
898 **/
899 EFI_STATUS
Var_UpdateConMode(IN BMM_CALLBACK_DATA * CallbackData)900 Var_UpdateConMode (
901 IN BMM_CALLBACK_DATA *CallbackData
902 )
903 {
904 EFI_STATUS Status;
905 UINTN Mode;
906 CONSOLE_OUT_MODE ModeInfo;
907
908 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
909
910 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
911 if (!EFI_ERROR(Status)) {
912 Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);
913 if (!EFI_ERROR (Status)) {
914 Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row);
915 }
916 }
917
918 return Status;
919 }
920