]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BootMaintenanceManagerUiLib/Variable.c
MdeModulePkg/Core/PiSmmCore: rebase to ARRAY_SIZE()
[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
201fbce6
DB
468 @retval other Contain some errors when excuting this function.See function\r
469 EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl\r
470 for detail return information.\r
4af04335
DB
471 @retval EFI_SUCCESS If function completes successfully.\r
472\r
473**/\r
474EFI_STATUS\r
475Var_UpdateDriverOption (\r
476 IN BMM_CALLBACK_DATA *CallbackData,\r
477 IN EFI_HII_HANDLE HiiHandle,\r
478 IN UINT16 *DescriptionData,\r
479 IN UINT16 *OptionalData,\r
480 IN UINT8 ForceReconnect\r
481 )\r
482{\r
483 UINT16 Index;\r
4af04335 484 UINT16 DriverString[12];\r
4af04335
DB
485 BM_MENU_ENTRY *NewMenuEntry;\r
486 BM_LOAD_CONTEXT *NewLoadContext;\r
487 BOOLEAN OptionalDataExist;\r
488 EFI_STATUS Status;\r
2ba36b2f
DB
489 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;\r
490 UINT8 *OptionalDesData;\r
491 UINT32 OptionalDataSize;\r
4af04335
DB
492\r
493 OptionalDataExist = FALSE;\r
2ba36b2f
DB
494 OptionalDesData = NULL;\r
495 OptionalDataSize = 0;\r
4af04335
DB
496\r
497 Index = BOpt_GetDriverOptionNumber ();\r
498 UnicodeSPrint (\r
499 DriverString,\r
500 sizeof (DriverString),\r
501 L"Driver%04x",\r
502 Index\r
503 );\r
504\r
505 if (*DescriptionData == 0x0000) {\r
506 StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);\r
507 }\r
508\r
4af04335
DB
509 if (*OptionalData != 0x0000) {\r
510 OptionalDataExist = TRUE;\r
2ba36b2f
DB
511 OptionalDesData = (UINT8 *)OptionalData;\r
512 OptionalDataSize = (UINT32)StrSize (OptionalData);\r
4af04335
DB
513 }\r
514\r
515 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
516 if (NULL == NewMenuEntry) {\r
4af04335
DB
517 return EFI_OUT_OF_RESOURCES;\r
518 }\r
519\r
2ba36b2f
DB
520 Status = EfiBootManagerInitializeLoadOption (\r
521 &LoadOption,\r
522 Index,\r
523 LoadOptionTypeDriver,\r
524 LOAD_OPTION_ACTIVE | (ForceReconnect << 1),\r
525 DescriptionData,\r
526 CallbackData->LoadContext->FilePathList,\r
527 OptionalDesData,\r
528 OptionalDataSize\r
529 );\r
201fbce6
DB
530 if (EFI_ERROR (Status)){\r
531 return Status;\r
532 }\r
533\r
534 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );\r
535 if (EFI_ERROR (Status)) {\r
536 EfiBootManagerFreeLoadOption(&LoadOption);\r
537 return Status;\r
2ba36b2f
DB
538 }\r
539\r
4af04335
DB
540 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
541 NewLoadContext->Deleted = FALSE;\r
2ba36b2f
DB
542 NewLoadContext->Attributes = LoadOption.Attributes;\r
543 NewLoadContext->FilePathListLength = (UINT16)GetDevicePathSize (LoadOption.FilePath);\r
4af04335
DB
544\r
545 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
546 ASSERT (NewLoadContext->Description != NULL);\r
547 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
548 CopyMem (\r
549 NewLoadContext->Description,\r
2ba36b2f 550 LoadOption.Description,\r
4af04335
DB
551 StrSize (DescriptionData)\r
552 );\r
553\r
4af04335
DB
554 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
555 ASSERT (NewLoadContext->FilePathList != NULL);\r
4af04335
DB
556 CopyMem (\r
557 NewLoadContext->FilePathList,\r
2ba36b2f 558 LoadOption.FilePath,\r
4af04335
DB
559 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
560 );\r
561\r
562 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);\r
563 NewMenuEntry->OptionNumber = Index;\r
564 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
565 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
566\r
567 if (OptionalDataExist) {\r
2ba36b2f 568 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);\r
48c18bd1 569 ASSERT (NewLoadContext->OptionalData != NULL);\r
4af04335 570 CopyMem (\r
2ba36b2f
DB
571 NewLoadContext->OptionalData,\r
572 LoadOption.OptionalData,\r
573 LoadOption.OptionalDataSize\r
4af04335
DB
574 );\r
575 }\r
576\r
4af04335
DB
577 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
578 DriverOptionMenu.MenuNumber++;\r
579\r
2ba36b2f
DB
580 EfiBootManagerFreeLoadOption(&LoadOption);\r
581\r
4af04335
DB
582 return EFI_SUCCESS;\r
583}\r
584\r
585/**\r
586 This function create a currently loaded Boot Option from \r
587 the BMM. It then appends this Boot Option to the end of \r
588 the "BootOrder" list. It also append this Boot Opotion to the end\r
589 of BootOptionMenu.\r
590\r
591 @param CallbackData The BMM context data.\r
592\r
201fbce6
DB
593 @retval other Contain some errors when excuting this function. See function\r
594 EfiBootManagerInitializeLoadOption/EfiBootManagerAddLoadOptionVariabl\r
595 for detail return information.\r
4af04335
DB
596 @retval EFI_SUCCESS If function completes successfully.\r
597\r
598**/\r
599EFI_STATUS\r
600Var_UpdateBootOption (\r
601 IN BMM_CALLBACK_DATA *CallbackData\r
602 )\r
603{\r
4af04335 604 UINT16 BootString[10];\r
4af04335
DB
605 UINT16 Index;\r
606 BM_MENU_ENTRY *NewMenuEntry;\r
607 BM_LOAD_CONTEXT *NewLoadContext;\r
608 BOOLEAN OptionalDataExist;\r
609 EFI_STATUS Status;\r
610 BMM_FAKE_NV_DATA *NvRamMap;\r
2ba36b2f
DB
611 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;\r
612 UINT8 *OptionalData;\r
613 UINT32 OptionalDataSize;\r
4af04335
DB
614\r
615 OptionalDataExist = FALSE;\r
616 NvRamMap = &CallbackData->BmmFakeNvData;\r
2ba36b2f
DB
617 OptionalData = NULL;\r
618 OptionalDataSize = 0;\r
4af04335
DB
619\r
620 Index = BOpt_GetBootOptionNumber () ;\r
621 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
622\r
623 if (NvRamMap->BootDescriptionData[0] == 0x0000) {\r
624 StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString);\r
625 }\r
626\r
4af04335
DB
627 if (NvRamMap->BootOptionalData[0] != 0x0000) {\r
628 OptionalDataExist = TRUE;\r
2ba36b2f
DB
629 OptionalData = (UINT8 *)NvRamMap->BootOptionalData;\r
630 OptionalDataSize = (UINT32)StrSize (NvRamMap->BootOptionalData);\r
4af04335
DB
631 }\r
632\r
633 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
634 if (NULL == NewMenuEntry) {\r
635 return EFI_OUT_OF_RESOURCES;\r
636 }\r
637\r
2ba36b2f
DB
638 Status = EfiBootManagerInitializeLoadOption (\r
639 &LoadOption,\r
640 Index,\r
641 LoadOptionTypeBoot,\r
642 LOAD_OPTION_ACTIVE,\r
643 NvRamMap->BootDescriptionData,\r
644 CallbackData->LoadContext->FilePathList,\r
645 OptionalData,\r
646 OptionalDataSize\r
647 );\r
201fbce6
DB
648 if (EFI_ERROR (Status)){\r
649 return Status;\r
650 }\r
651\r
652 Status = EfiBootManagerAddLoadOptionVariable (&LoadOption,(UINTN) -1 );\r
653 if (EFI_ERROR (Status)) {\r
654 EfiBootManagerFreeLoadOption(&LoadOption);\r
655 return Status;\r
2ba36b2f
DB
656 }\r
657\r
4af04335
DB
658 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
659 NewLoadContext->Deleted = FALSE;\r
2ba36b2f
DB
660 NewLoadContext->Attributes = LoadOption.Attributes;\r
661 NewLoadContext->FilePathListLength = (UINT16) GetDevicePathSize (LoadOption.FilePath);\r
4af04335
DB
662\r
663 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));\r
664 ASSERT (NewLoadContext->Description != NULL);\r
665\r
666 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
2ba36b2f 667\r
4af04335
DB
668 CopyMem (\r
669 NewLoadContext->Description,\r
2ba36b2f 670 LoadOption.Description,\r
4af04335
DB
671 StrSize (NvRamMap->BootDescriptionData)\r
672 );\r
673\r
4af04335
DB
674 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
675 ASSERT (NewLoadContext->FilePathList != NULL);\r
4af04335
DB
676 CopyMem (\r
677 NewLoadContext->FilePathList,\r
2ba36b2f 678 LoadOption.FilePath,\r
4af04335
DB
679 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
680 );\r
681\r
682 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);\r
683 NewMenuEntry->OptionNumber = Index;\r
684 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
685 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
686\r
687 if (OptionalDataExist) {\r
2ba36b2f 688 NewLoadContext->OptionalData = AllocateZeroPool (LoadOption.OptionalDataSize);\r
48c18bd1 689 ASSERT (NewLoadContext->OptionalData != NULL);\r
2ba36b2f
DB
690 CopyMem (\r
691 NewLoadContext->OptionalData,\r
692 LoadOption.OptionalData,\r
693 LoadOption.OptionalDataSize\r
694 );\r
4af04335
DB
695 }\r
696\r
4af04335
DB
697 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
698 BootOptionMenu.MenuNumber++;\r
699\r
2ba36b2f
DB
700 EfiBootManagerFreeLoadOption(&LoadOption);\r
701\r
4af04335
DB
702 return EFI_SUCCESS;\r
703}\r
704\r
705/**\r
706 This function update the "BootNext" EFI Variable. If there is \r
707 no "BootNext" specified in BMM, this EFI Variable is deleted.\r
708 It also update the BMM context data specified the "BootNext"\r
709 vaule.\r
710\r
711 @param CallbackData The BMM context data.\r
712\r
713 @retval EFI_SUCCESS The function complete successfully.\r
714 @return The EFI variable can be saved. See gRT->SetVariable \r
715 for detail return information.\r
716\r
717**/\r
718EFI_STATUS\r
719Var_UpdateBootNext (\r
720 IN BMM_CALLBACK_DATA *CallbackData\r
721 )\r
722{\r
723 BM_MENU_ENTRY *NewMenuEntry;\r
724 BM_LOAD_CONTEXT *NewLoadContext;\r
725 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
726 UINT16 Index;\r
727 EFI_STATUS Status;\r
728\r
729 Status = EFI_SUCCESS;\r
730 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
731 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
732 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
733 ASSERT (NULL != NewMenuEntry);\r
734\r
735 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
736 NewLoadContext->IsBootNext = FALSE;\r
737 }\r
738\r
f7986526 739 if (CurrentFakeNVMap->BootNext == NONE_BOOTNEXT_VALUE) {\r
4af04335
DB
740 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
741 return EFI_SUCCESS;\r
742 }\r
743\r
744 NewMenuEntry = BOpt_GetMenuEntry (\r
745 &BootOptionMenu,\r
746 CurrentFakeNVMap->BootNext\r
747 );\r
748 ASSERT (NewMenuEntry != NULL);\r
749\r
750 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
751 Status = gRT->SetVariable (\r
752 L"BootNext",\r
753 &gEfiGlobalVariableGuid,\r
754 VAR_FLAG,\r
755 sizeof (UINT16),\r
756 &NewMenuEntry->OptionNumber\r
757 );\r
758 NewLoadContext->IsBootNext = TRUE;\r
759 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
760 return Status;\r
761}\r
762\r
763/**\r
764 This function update the "BootOrder" EFI Variable based on\r
765 BMM Formset's NV map. It then refresh BootOptionMenu\r
766 with the new "BootOrder" list.\r
767\r
768 @param CallbackData The BMM context data.\r
769\r
770 @retval EFI_SUCCESS The function complete successfully.\r
771 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
772 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
773\r
774**/\r
775EFI_STATUS\r
776Var_UpdateBootOrder (\r
777 IN BMM_CALLBACK_DATA *CallbackData\r
778 )\r
779{\r
780 EFI_STATUS Status;\r
781 UINT16 Index;\r
782 UINT16 OrderIndex;\r
783 UINT16 *BootOrder;\r
784 UINTN BootOrderSize;\r
785 UINT16 OptionNumber;\r
786\r
787 //\r
788 // First check whether BootOrder is present in current configuration\r
789 //\r
790 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);\r
791 if (BootOrder == NULL) {\r
792 return EFI_OUT_OF_RESOURCES;\r
793 }\r
794\r
795 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));\r
796\r
797 //\r
798 // OptionOrder is subset of BootOrder\r
799 //\r
800 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {\r
801 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
802 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {\r
803 OptionNumber = BootOrder[Index];\r
804 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));\r
805 BootOrder[OrderIndex] = OptionNumber;\r
806 }\r
807 }\r
808 }\r
809\r
810 Status = gRT->SetVariable (\r
811 L"BootOrder",\r
812 &gEfiGlobalVariableGuid,\r
813 VAR_FLAG,\r
814 BootOrderSize,\r
815 BootOrder\r
816 );\r
817 FreePool (BootOrder);\r
818 \r
819 BOpt_FreeMenu (&BootOptionMenu);\r
820 BOpt_GetBootOptions (CallbackData);\r
821\r
822 return Status;\r
823\r
824}\r
825\r
826/**\r
827 This function update the "DriverOrder" EFI Variable based on\r
828 BMM Formset's NV map. It then refresh DriverOptionMenu\r
829 with the new "DriverOrder" list.\r
830\r
831 @param CallbackData The BMM context data.\r
832\r
833 @retval EFI_SUCCESS The function complete successfully.\r
834 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
835 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
836\r
837**/\r
838EFI_STATUS\r
839Var_UpdateDriverOrder (\r
840 IN BMM_CALLBACK_DATA *CallbackData\r
841 )\r
842{\r
843 EFI_STATUS Status;\r
844 UINT16 Index;\r
845 UINT16 *DriverOrderList;\r
846 UINT16 *NewDriverOrderList;\r
847 UINTN DriverOrderListSize;\r
848\r
849 DriverOrderList = NULL;\r
850 DriverOrderListSize = 0;\r
851\r
852 //\r
853 // First check whether DriverOrder is present in current configuration\r
854 //\r
855 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);\r
856 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
857\r
858 if (NewDriverOrderList == NULL) {\r
859 return EFI_OUT_OF_RESOURCES;\r
860 }\r
861 //\r
862 // If exists, delete it to hold new DriverOrder\r
863 //\r
864 if (DriverOrderList != NULL) {\r
865 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
866 FreePool (DriverOrderList);\r
867 }\r
868\r
869 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));\r
870 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
871 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);\r
872 }\r
873\r
874 Status = gRT->SetVariable (\r
875 L"DriverOrder",\r
876 &gEfiGlobalVariableGuid,\r
877 VAR_FLAG,\r
878 DriverOrderListSize,\r
879 NewDriverOrderList\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882 return Status;\r
883 }\r
884\r
885 BOpt_FreeMenu (&DriverOptionMenu);\r
886 BOpt_GetDriverOptions (CallbackData);\r
887 return EFI_SUCCESS;\r
888}\r
889\r
890/**\r
891 Update the Text Mode of Console.\r
892\r
893 @param CallbackData The context data for BMM.\r
894\r
895 @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
896 @return Other value if the Text Mode of Console is not updated.\r
897\r
898**/\r
899EFI_STATUS\r
900Var_UpdateConMode (\r
901 IN BMM_CALLBACK_DATA *CallbackData\r
902 )\r
903{\r
904 EFI_STATUS Status;\r
905 UINTN Mode;\r
906 CONSOLE_OUT_MODE ModeInfo;\r
907\r
908 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
909\r
910 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
911 if (!EFI_ERROR(Status)) {\r
912 Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);\r
913 if (!EFI_ERROR (Status)) {\r
914 Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row);\r
915 }\r
916 }\r
917\r
918 return Status;\r
919}\r