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