]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/UiApp/BootMaint/Variable.c
MdeModulePkg:Create Boot Maintenance Manager Library
[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
cf34f86b
ED
320 GetEfiGlobalVariable2 (L"ConOut", (VOID**)&OutDevicePath, NULL);\r
321 GetEfiGlobalVariable2 (L"ConIn", (VOID**)&InpDevicePath, NULL);\r
322 GetEfiGlobalVariable2 (L"ErrOut", (VOID**)&ErrDevicePath, NULL);\r
143f0b1d
ED
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
cf34f86b 398 GetEfiGlobalVariable2 (ConsoleName, (VOID**)&ConDevicePath, NULL);\r
143f0b1d
ED
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
527\r
528**/\r
529EFI_STATUS\r
530Var_UpdateDriverOption (\r
531 IN BMM_CALLBACK_DATA *CallbackData,\r
532 IN EFI_HII_HANDLE HiiHandle,\r
533 IN UINT16 *DescriptionData,\r
534 IN UINT16 *OptionalData,\r
535 IN UINT8 ForceReconnect\r
536 )\r
537{\r
538 UINT16 Index;\r
539 UINT16 *DriverOrderList;\r
540 UINT16 *NewDriverOrderList;\r
541 UINT16 DriverString[12];\r
542 UINTN DriverOrderListSize;\r
543 VOID *Buffer;\r
544 UINTN BufferSize;\r
545 UINT8 *Ptr;\r
546 BM_MENU_ENTRY *NewMenuEntry;\r
547 BM_LOAD_CONTEXT *NewLoadContext;\r
548 BOOLEAN OptionalDataExist;\r
549 EFI_STATUS Status;\r
550\r
551 OptionalDataExist = FALSE;\r
552\r
553 Index = BOpt_GetDriverOptionNumber ();\r
554 UnicodeSPrint (\r
555 DriverString,\r
556 sizeof (DriverString),\r
557 L"Driver%04x",\r
558 Index\r
559 );\r
560\r
561 if (*DescriptionData == 0x0000) {\r
d91cb870 562 StrCpyS (DescriptionData, MAX_MENU_NUMBER, DriverString);\r
143f0b1d
ED
563 }\r
564\r
565 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
566 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
567\r
568 if (*OptionalData != 0x0000) {\r
569 OptionalDataExist = TRUE;\r
570 BufferSize += StrSize (OptionalData);\r
571 }\r
572\r
573 Buffer = AllocateZeroPool (BufferSize);\r
574 if (NULL == Buffer) {\r
575 return EFI_OUT_OF_RESOURCES;\r
576 }\r
577\r
578 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
579 if (NULL == NewMenuEntry) {\r
580 FreePool (Buffer);\r
581 return EFI_OUT_OF_RESOURCES;\r
582 }\r
583\r
584 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
585 NewLoadContext->Deleted = FALSE;\r
586 NewLoadContext->LoadOptionSize = BufferSize;\r
587 Ptr = (UINT8 *) Buffer;\r
588 NewLoadContext->LoadOption = Ptr;\r
589 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
590 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
591 NewLoadContext->IsActive = TRUE;\r
592 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
593\r
594 Ptr += sizeof (UINT32);\r
595 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
596 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
597\r
598 Ptr += sizeof (UINT16);\r
599 CopyMem (\r
600 Ptr,\r
601 DescriptionData,\r
602 StrSize (DescriptionData)\r
603 );\r
604\r
605 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
606 ASSERT (NewLoadContext->Description != NULL);\r
607 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
608 CopyMem (\r
609 NewLoadContext->Description,\r
610 (VOID *) Ptr,\r
611 StrSize (DescriptionData)\r
612 );\r
613\r
614 Ptr += StrSize (DescriptionData);\r
615 CopyMem (\r
616 Ptr,\r
617 CallbackData->LoadContext->FilePathList,\r
618 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
619 );\r
620\r
621 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
622 ASSERT (NewLoadContext->FilePathList != NULL);\r
623\r
624 CopyMem (\r
625 NewLoadContext->FilePathList,\r
626 (VOID *) Ptr,\r
627 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
628 );\r
629\r
630 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);\r
631 NewMenuEntry->OptionNumber = Index;\r
632 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
633 CallbackData,\r
634 DriverOptionStrDepository\r
635 );\r
636 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
637\r
638 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
639 CallbackData,\r
640 DriverOptionHelpStrDepository\r
641 );\r
642 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
643\r
644 if (OptionalDataExist) {\r
645 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
646\r
647 CopyMem (\r
648 Ptr,\r
649 OptionalData,\r
650 StrSize (OptionalData)\r
651 );\r
652 }\r
653\r
654 Status = gRT->SetVariable (\r
655 DriverString,\r
656 &gEfiGlobalVariableGuid,\r
657 VAR_FLAG,\r
658 BufferSize,\r
659 Buffer\r
660 );\r
661 ASSERT_EFI_ERROR (Status);\r
d6da3fb0 662 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);\r
143f0b1d
ED
663 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
664 ASSERT (NewDriverOrderList != NULL);\r
d6da3fb0
DB
665 if (DriverOrderList != NULL){\r
666 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
667 }\r
143f0b1d
ED
668 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
669 if (DriverOrderList != NULL) {\r
670 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
671 }\r
672\r
673 Status = gRT->SetVariable (\r
674 L"DriverOrder",\r
675 &gEfiGlobalVariableGuid,\r
676 VAR_FLAG,\r
677 DriverOrderListSize + sizeof (UINT16),\r
678 NewDriverOrderList\r
679 );\r
680 ASSERT_EFI_ERROR (Status);\r
681 if (DriverOrderList != NULL) {\r
682 FreePool (DriverOrderList);\r
683 }\r
684 DriverOrderList = NULL;\r
685 FreePool (NewDriverOrderList);\r
686 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
687 DriverOptionMenu.MenuNumber++;\r
688\r
689 *DescriptionData = 0x0000;\r
690 *OptionalData = 0x0000;\r
691 return EFI_SUCCESS;\r
692}\r
693\r
694/**\r
695 This function create a currently loaded Boot Option from \r
696 the BMM. It then appends this Boot Option to the end of \r
697 the "BootOrder" list. It also append this Boot Opotion to the end\r
698 of BootOptionMenu.\r
699\r
700 @param CallbackData The BMM context data.\r
701 @param NvRamMap The file explorer formset internal state.\r
702\r
703 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
704 @retval EFI_SUCCESS If function completes successfully.\r
705\r
706**/\r
707EFI_STATUS\r
708Var_UpdateBootOption (\r
709 IN BMM_CALLBACK_DATA *CallbackData,\r
710 IN FILE_EXPLORER_NV_DATA *NvRamMap\r
711 )\r
712{\r
713 UINT16 *BootOrderList;\r
714 UINT16 *NewBootOrderList;\r
715 UINTN BootOrderListSize;\r
716 UINT16 BootString[10];\r
717 VOID *Buffer;\r
718 UINTN BufferSize;\r
719 UINT8 *Ptr;\r
720 UINT16 Index;\r
721 BM_MENU_ENTRY *NewMenuEntry;\r
722 BM_LOAD_CONTEXT *NewLoadContext;\r
723 BOOLEAN OptionalDataExist;\r
724 EFI_STATUS Status;\r
725\r
726 OptionalDataExist = FALSE;\r
727\r
728 Index = BOpt_GetBootOptionNumber () ;\r
729 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
730\r
a22a50fa
DB
731 if (NvRamMap->BootDescriptionData[0] == 0x0000) {\r
732 StrCpyS (NvRamMap->BootDescriptionData, sizeof (NvRamMap->BootDescriptionData) / sizeof (NvRamMap->BootDescriptionData[0]), BootString);\r
143f0b1d
ED
733 }\r
734\r
a22a50fa 735 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData);\r
143f0b1d
ED
736 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
737\r
a22a50fa 738 if (NvRamMap->BootOptionalData[0] != 0x0000) {\r
143f0b1d 739 OptionalDataExist = TRUE;\r
a22a50fa 740 BufferSize += StrSize (NvRamMap->BootOptionalData);\r
143f0b1d
ED
741 }\r
742\r
743 Buffer = AllocateZeroPool (BufferSize);\r
744 if (NULL == Buffer) {\r
745 return EFI_OUT_OF_RESOURCES;\r
746 }\r
747\r
748 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
749 if (NULL == NewMenuEntry) {\r
750 return EFI_OUT_OF_RESOURCES;\r
751 }\r
752\r
753 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
754 NewLoadContext->Deleted = FALSE;\r
755 NewLoadContext->LoadOptionSize = BufferSize;\r
756 Ptr = (UINT8 *) Buffer;\r
757 NewLoadContext->LoadOption = Ptr;\r
758 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
759 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
760 NewLoadContext->IsActive = TRUE;\r
761 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
762\r
763 Ptr += sizeof (UINT32);\r
764 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
765 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
766 Ptr += sizeof (UINT16);\r
767\r
768 CopyMem (\r
769 Ptr,\r
a22a50fa
DB
770 NvRamMap->BootDescriptionData,\r
771 StrSize (NvRamMap->BootDescriptionData)\r
143f0b1d
ED
772 );\r
773\r
a22a50fa 774 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));\r
143f0b1d
ED
775 ASSERT (NewLoadContext->Description != NULL);\r
776\r
777 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
778 CopyMem (\r
779 NewLoadContext->Description,\r
780 (VOID *) Ptr,\r
a22a50fa 781 StrSize (NvRamMap->BootDescriptionData)\r
143f0b1d
ED
782 );\r
783\r
a22a50fa 784 Ptr += StrSize (NvRamMap->BootDescriptionData);\r
143f0b1d
ED
785 CopyMem (\r
786 Ptr,\r
787 CallbackData->LoadContext->FilePathList,\r
788 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
789 );\r
790\r
791 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
792 ASSERT (NewLoadContext->FilePathList != NULL);\r
793\r
794 CopyMem (\r
795 NewLoadContext->FilePathList,\r
796 (VOID *) Ptr,\r
797 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
798 );\r
799\r
800 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);\r
801 NewMenuEntry->OptionNumber = Index;\r
802 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
803 CallbackData,\r
804 BootOptionStrDepository\r
805 );\r
806 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
807\r
808 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
809 CallbackData,\r
810 BootOptionHelpStrDepository\r
811 );\r
812 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
813\r
814 if (OptionalDataExist) {\r
815 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
816\r
a22a50fa 817 CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData));\r
143f0b1d
ED
818 }\r
819\r
820 Status = gRT->SetVariable (\r
821 BootString,\r
822 &gEfiGlobalVariableGuid,\r
823 VAR_FLAG,\r
824 BufferSize,\r
825 Buffer\r
826 );\r
827 ASSERT_EFI_ERROR (Status);\r
828\r
d6da3fb0 829 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);\r
143f0b1d
ED
830 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
831 ASSERT (NewBootOrderList != NULL);\r
d6da3fb0
DB
832 if (BootOrderList != NULL){\r
833 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
834 }\r
143f0b1d
ED
835 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
836\r
837 if (BootOrderList != NULL) {\r
838 FreePool (BootOrderList);\r
839 }\r
840\r
841 Status = gRT->SetVariable (\r
842 L"BootOrder",\r
843 &gEfiGlobalVariableGuid,\r
844 VAR_FLAG,\r
845 BootOrderListSize + sizeof (UINT16),\r
846 NewBootOrderList\r
847 );\r
848 ASSERT_EFI_ERROR (Status);\r
849\r
850 FreePool (NewBootOrderList);\r
851 NewBootOrderList = NULL;\r
852 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
853 BootOptionMenu.MenuNumber++;\r
854\r
a22a50fa
DB
855 NvRamMap->BootDescriptionData[0] = 0x0000;\r
856 NvRamMap->BootOptionalData[0] = 0x0000;\r
143f0b1d
ED
857 return EFI_SUCCESS;\r
858}\r
859\r
860/**\r
861 This function update the "BootNext" EFI Variable. If there is \r
862 no "BootNext" specified in BMM, this EFI Variable is deleted.\r
863 It also update the BMM context data specified the "BootNext"\r
864 vaule.\r
865\r
866 @param CallbackData The BMM context data.\r
867\r
868 @retval EFI_SUCCESS The function complete successfully.\r
869 @return The EFI variable can be saved. See gRT->SetVariable \r
870 for detail return information.\r
871\r
872**/\r
873EFI_STATUS\r
874Var_UpdateBootNext (\r
875 IN BMM_CALLBACK_DATA *CallbackData\r
876 )\r
877{\r
878 BM_MENU_ENTRY *NewMenuEntry;\r
879 BM_LOAD_CONTEXT *NewLoadContext;\r
880 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
881 UINT16 Index;\r
882 EFI_STATUS Status;\r
883\r
884 Status = EFI_SUCCESS;\r
885 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
886 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
887 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
888 ASSERT (NULL != NewMenuEntry);\r
889\r
890 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
891 NewLoadContext->IsBootNext = FALSE;\r
892 }\r
893\r
894 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
895 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
896 return EFI_SUCCESS;\r
897 }\r
898\r
899 NewMenuEntry = BOpt_GetMenuEntry (\r
900 &BootOptionMenu,\r
901 CurrentFakeNVMap->BootNext\r
902 );\r
903 ASSERT (NewMenuEntry != NULL);\r
904\r
905 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
906 Status = gRT->SetVariable (\r
907 L"BootNext",\r
908 &gEfiGlobalVariableGuid,\r
909 VAR_FLAG,\r
910 sizeof (UINT16),\r
911 &NewMenuEntry->OptionNumber\r
912 );\r
913 NewLoadContext->IsBootNext = TRUE;\r
914 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
915 return Status;\r
916}\r
917\r
918/**\r
919 This function update the "BootOrder" EFI Variable based on\r
920 BMM Formset's NV map. It then refresh BootOptionMenu\r
921 with the new "BootOrder" list.\r
922\r
923 @param CallbackData The BMM context data.\r
924\r
925 @retval EFI_SUCCESS The function complete successfully.\r
926 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
927 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
928\r
929**/\r
930EFI_STATUS\r
931Var_UpdateBootOrder (\r
932 IN BMM_CALLBACK_DATA *CallbackData\r
933 )\r
934{\r
935 EFI_STATUS Status;\r
936 UINT16 Index;\r
937 UINT16 OrderIndex;\r
938 UINT16 *BootOrder;\r
939 UINTN BootOrderSize;\r
940 UINT16 OptionNumber;\r
941\r
942 //\r
943 // First check whether BootOrder is present in current configuration\r
944 //\r
945 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);\r
946 if (BootOrder == NULL) {\r
947 return EFI_OUT_OF_RESOURCES;\r
948 }\r
949\r
950 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));\r
951\r
952 //\r
953 // OptionOrder is subset of BootOrder\r
954 //\r
955 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {\r
956 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
957 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {\r
958 OptionNumber = BootOrder[Index];\r
959 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));\r
960 BootOrder[OrderIndex] = OptionNumber;\r
961 }\r
962 }\r
963 }\r
964\r
965 Status = gRT->SetVariable (\r
966 L"BootOrder",\r
967 &gEfiGlobalVariableGuid,\r
968 VAR_FLAG,\r
969 BootOrderSize,\r
970 BootOrder\r
971 );\r
972 FreePool (BootOrder);\r
973\r
974 BOpt_FreeMenu (&BootOptionMenu);\r
975 BOpt_GetBootOptions (CallbackData);\r
976\r
977 return Status;\r
978\r
979}\r
980\r
981/**\r
982 This function update the "DriverOrder" EFI Variable based on\r
983 BMM Formset's NV map. It then refresh DriverOptionMenu\r
984 with the new "DriverOrder" list.\r
985\r
986 @param CallbackData The BMM context data.\r
987\r
988 @retval EFI_SUCCESS The function complete successfully.\r
989 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
990 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
991\r
992**/\r
993EFI_STATUS\r
994Var_UpdateDriverOrder (\r
995 IN BMM_CALLBACK_DATA *CallbackData\r
996 )\r
997{\r
998 EFI_STATUS Status;\r
999 UINT16 Index;\r
1000 UINT16 *DriverOrderList;\r
1001 UINT16 *NewDriverOrderList;\r
1002 UINTN DriverOrderListSize;\r
1003\r
1004 DriverOrderList = NULL;\r
1005 DriverOrderListSize = 0;\r
1006\r
1007 //\r
1008 // First check whether DriverOrder is present in current configuration\r
1009 //\r
1010 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);\r
1011 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
1012\r
1013 if (NewDriverOrderList == NULL) {\r
1014 return EFI_OUT_OF_RESOURCES;\r
1015 }\r
1016 //\r
1017 // If exists, delete it to hold new DriverOrder\r
1018 //\r
1019 if (DriverOrderList != NULL) {\r
1020 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
1021 FreePool (DriverOrderList);\r
1022 }\r
1023\r
1024 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));\r
1025 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
1026 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);\r
1027 }\r
1028\r
1029 Status = gRT->SetVariable (\r
1030 L"DriverOrder",\r
1031 &gEfiGlobalVariableGuid,\r
1032 VAR_FLAG,\r
1033 DriverOrderListSize,\r
1034 NewDriverOrderList\r
1035 );\r
1036 if (EFI_ERROR (Status)) {\r
1037 return Status;\r
1038 }\r
1039\r
1040 BOpt_FreeMenu (&DriverOptionMenu);\r
1041 BOpt_GetDriverOptions (CallbackData);\r
1042 return EFI_SUCCESS;\r
1043}\r
1044\r
1045/**\r
1046 Update the Text Mode of Console.\r
1047\r
1048 @param CallbackData The context data for BMM.\r
1049\r
1050 @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
1051 @return Other value if the Text Mode of Console is not updated.\r
1052\r
1053**/\r
1054EFI_STATUS\r
1055Var_UpdateConMode (\r
1056 IN BMM_CALLBACK_DATA *CallbackData\r
1057 )\r
1058{\r
1059 EFI_STATUS Status;\r
1060 UINTN Mode;\r
1061 CONSOLE_OUT_MODE ModeInfo;\r
1062\r
1063 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
1064\r
1065 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
1066 if (!EFI_ERROR(Status)) {\r
377680ae
ED
1067 Status = PcdSet32S (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);\r
1068 if (!EFI_ERROR (Status)) {\r
1069 Status = PcdSet32S (PcdSetupConOutRow, (UINT32) ModeInfo.Row);\r
1070 }\r
143f0b1d
ED
1071 }\r
1072\r
377680ae 1073 return Status;\r
143f0b1d 1074}\r