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