]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/UiApp/BootMaint/Variable.c
UiApp: Update copyright info, cover old code existed in old BdsDxe driver.
[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
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
562 StrCpy (DescriptionData, DriverString);\r
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
662 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);\r
663 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
664 ASSERT (NewDriverOrderList != NULL);\r
665 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
666 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
667 if (DriverOrderList != NULL) {\r
668 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
669 }\r
670\r
671 Status = gRT->SetVariable (\r
672 L"DriverOrder",\r
673 &gEfiGlobalVariableGuid,\r
674 VAR_FLAG,\r
675 DriverOrderListSize + sizeof (UINT16),\r
676 NewDriverOrderList\r
677 );\r
678 ASSERT_EFI_ERROR (Status);\r
679 if (DriverOrderList != NULL) {\r
680 FreePool (DriverOrderList);\r
681 }\r
682 DriverOrderList = NULL;\r
683 FreePool (NewDriverOrderList);\r
684 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
685 DriverOptionMenu.MenuNumber++;\r
686\r
687 *DescriptionData = 0x0000;\r
688 *OptionalData = 0x0000;\r
689 return EFI_SUCCESS;\r
690}\r
691\r
692/**\r
693 This function create a currently loaded Boot Option from \r
694 the BMM. It then appends this Boot Option to the end of \r
695 the "BootOrder" list. It also append this Boot Opotion to the end\r
696 of BootOptionMenu.\r
697\r
698 @param CallbackData The BMM context data.\r
699 @param NvRamMap The file explorer formset internal state.\r
700\r
701 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
702 @retval EFI_SUCCESS If function completes successfully.\r
703\r
704**/\r
705EFI_STATUS\r
706Var_UpdateBootOption (\r
707 IN BMM_CALLBACK_DATA *CallbackData,\r
708 IN FILE_EXPLORER_NV_DATA *NvRamMap\r
709 )\r
710{\r
711 UINT16 *BootOrderList;\r
712 UINT16 *NewBootOrderList;\r
713 UINTN BootOrderListSize;\r
714 UINT16 BootString[10];\r
715 VOID *Buffer;\r
716 UINTN BufferSize;\r
717 UINT8 *Ptr;\r
718 UINT16 Index;\r
719 BM_MENU_ENTRY *NewMenuEntry;\r
720 BM_LOAD_CONTEXT *NewLoadContext;\r
721 BOOLEAN OptionalDataExist;\r
722 EFI_STATUS Status;\r
723\r
724 OptionalDataExist = FALSE;\r
725\r
726 Index = BOpt_GetBootOptionNumber () ;\r
727 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
728\r
729 if (NvRamMap->DescriptionData[0] == 0x0000) {\r
730 StrCpy (NvRamMap->DescriptionData, BootString);\r
731 }\r
732\r
733 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
734 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
735\r
736 if (NvRamMap->OptionalData[0] != 0x0000) {\r
737 OptionalDataExist = TRUE;\r
738 BufferSize += StrSize (NvRamMap->OptionalData);\r
739 }\r
740\r
741 Buffer = AllocateZeroPool (BufferSize);\r
742 if (NULL == Buffer) {\r
743 return EFI_OUT_OF_RESOURCES;\r
744 }\r
745\r
746 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
747 if (NULL == NewMenuEntry) {\r
748 return EFI_OUT_OF_RESOURCES;\r
749 }\r
750\r
751 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
752 NewLoadContext->Deleted = FALSE;\r
753 NewLoadContext->LoadOptionSize = BufferSize;\r
754 Ptr = (UINT8 *) Buffer;\r
755 NewLoadContext->LoadOption = Ptr;\r
756 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
757 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
758 NewLoadContext->IsActive = TRUE;\r
759 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
760\r
761 Ptr += sizeof (UINT32);\r
762 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
763 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
764 Ptr += sizeof (UINT16);\r
765\r
766 CopyMem (\r
767 Ptr,\r
768 NvRamMap->DescriptionData,\r
769 StrSize (NvRamMap->DescriptionData)\r
770 );\r
771\r
772 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
773 ASSERT (NewLoadContext->Description != NULL);\r
774\r
775 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
776 CopyMem (\r
777 NewLoadContext->Description,\r
778 (VOID *) Ptr,\r
779 StrSize (NvRamMap->DescriptionData)\r
780 );\r
781\r
782 Ptr += StrSize (NvRamMap->DescriptionData);\r
783 CopyMem (\r
784 Ptr,\r
785 CallbackData->LoadContext->FilePathList,\r
786 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
787 );\r
788\r
789 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
790 ASSERT (NewLoadContext->FilePathList != NULL);\r
791\r
792 CopyMem (\r
793 NewLoadContext->FilePathList,\r
794 (VOID *) Ptr,\r
795 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
796 );\r
797\r
798 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);\r
799 NewMenuEntry->OptionNumber = Index;\r
800 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
801 CallbackData,\r
802 BootOptionStrDepository\r
803 );\r
804 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
805\r
806 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
807 CallbackData,\r
808 BootOptionHelpStrDepository\r
809 );\r
810 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
811\r
812 if (OptionalDataExist) {\r
813 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
814\r
815 CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
816 }\r
817\r
818 Status = gRT->SetVariable (\r
819 BootString,\r
820 &gEfiGlobalVariableGuid,\r
821 VAR_FLAG,\r
822 BufferSize,\r
823 Buffer\r
824 );\r
825 ASSERT_EFI_ERROR (Status);\r
826\r
827 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);\r
828 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
829 ASSERT (NewBootOrderList != NULL);\r
830 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
831 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
832\r
833 if (BootOrderList != NULL) {\r
834 FreePool (BootOrderList);\r
835 }\r
836\r
837 Status = gRT->SetVariable (\r
838 L"BootOrder",\r
839 &gEfiGlobalVariableGuid,\r
840 VAR_FLAG,\r
841 BootOrderListSize + sizeof (UINT16),\r
842 NewBootOrderList\r
843 );\r
844 ASSERT_EFI_ERROR (Status);\r
845\r
846 FreePool (NewBootOrderList);\r
847 NewBootOrderList = NULL;\r
848 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
849 BootOptionMenu.MenuNumber++;\r
850\r
851 NvRamMap->DescriptionData[0] = 0x0000;\r
852 NvRamMap->OptionalData[0] = 0x0000;\r
853 return EFI_SUCCESS;\r
854}\r
855\r
856/**\r
857 This function update the "BootNext" EFI Variable. If there is \r
858 no "BootNext" specified in BMM, this EFI Variable is deleted.\r
859 It also update the BMM context data specified the "BootNext"\r
860 vaule.\r
861\r
862 @param CallbackData The BMM context data.\r
863\r
864 @retval EFI_SUCCESS The function complete successfully.\r
865 @return The EFI variable can be saved. See gRT->SetVariable \r
866 for detail return information.\r
867\r
868**/\r
869EFI_STATUS\r
870Var_UpdateBootNext (\r
871 IN BMM_CALLBACK_DATA *CallbackData\r
872 )\r
873{\r
874 BM_MENU_ENTRY *NewMenuEntry;\r
875 BM_LOAD_CONTEXT *NewLoadContext;\r
876 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
877 UINT16 Index;\r
878 EFI_STATUS Status;\r
879\r
880 Status = EFI_SUCCESS;\r
881 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
882 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
883 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
884 ASSERT (NULL != NewMenuEntry);\r
885\r
886 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
887 NewLoadContext->IsBootNext = FALSE;\r
888 }\r
889\r
890 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
891 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
892 return EFI_SUCCESS;\r
893 }\r
894\r
895 NewMenuEntry = BOpt_GetMenuEntry (\r
896 &BootOptionMenu,\r
897 CurrentFakeNVMap->BootNext\r
898 );\r
899 ASSERT (NewMenuEntry != NULL);\r
900\r
901 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
902 Status = gRT->SetVariable (\r
903 L"BootNext",\r
904 &gEfiGlobalVariableGuid,\r
905 VAR_FLAG,\r
906 sizeof (UINT16),\r
907 &NewMenuEntry->OptionNumber\r
908 );\r
909 NewLoadContext->IsBootNext = TRUE;\r
910 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
911 return Status;\r
912}\r
913\r
914/**\r
915 This function update the "BootOrder" EFI Variable based on\r
916 BMM Formset's NV map. It then refresh BootOptionMenu\r
917 with the new "BootOrder" list.\r
918\r
919 @param CallbackData The BMM context data.\r
920\r
921 @retval EFI_SUCCESS The function complete successfully.\r
922 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
923 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
924\r
925**/\r
926EFI_STATUS\r
927Var_UpdateBootOrder (\r
928 IN BMM_CALLBACK_DATA *CallbackData\r
929 )\r
930{\r
931 EFI_STATUS Status;\r
932 UINT16 Index;\r
933 UINT16 OrderIndex;\r
934 UINT16 *BootOrder;\r
935 UINTN BootOrderSize;\r
936 UINT16 OptionNumber;\r
937\r
938 //\r
939 // First check whether BootOrder is present in current configuration\r
940 //\r
941 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);\r
942 if (BootOrder == NULL) {\r
943 return EFI_OUT_OF_RESOURCES;\r
944 }\r
945\r
946 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));\r
947\r
948 //\r
949 // OptionOrder is subset of BootOrder\r
950 //\r
951 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {\r
952 for (Index = OrderIndex; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
953 if ((BootOrder[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {\r
954 OptionNumber = BootOrder[Index];\r
955 CopyMem (&BootOrder[OrderIndex + 1], &BootOrder[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));\r
956 BootOrder[OrderIndex] = OptionNumber;\r
957 }\r
958 }\r
959 }\r
960\r
961 Status = gRT->SetVariable (\r
962 L"BootOrder",\r
963 &gEfiGlobalVariableGuid,\r
964 VAR_FLAG,\r
965 BootOrderSize,\r
966 BootOrder\r
967 );\r
968 FreePool (BootOrder);\r
969\r
970 BOpt_FreeMenu (&BootOptionMenu);\r
971 BOpt_GetBootOptions (CallbackData);\r
972\r
973 return Status;\r
974\r
975}\r
976\r
977/**\r
978 This function update the "DriverOrder" EFI Variable based on\r
979 BMM Formset's NV map. It then refresh DriverOptionMenu\r
980 with the new "DriverOrder" list.\r
981\r
982 @param CallbackData The BMM context data.\r
983\r
984 @retval EFI_SUCCESS The function complete successfully.\r
985 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
986 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
987\r
988**/\r
989EFI_STATUS\r
990Var_UpdateDriverOrder (\r
991 IN BMM_CALLBACK_DATA *CallbackData\r
992 )\r
993{\r
994 EFI_STATUS Status;\r
995 UINT16 Index;\r
996 UINT16 *DriverOrderList;\r
997 UINT16 *NewDriverOrderList;\r
998 UINTN DriverOrderListSize;\r
999\r
1000 DriverOrderList = NULL;\r
1001 DriverOrderListSize = 0;\r
1002\r
1003 //\r
1004 // First check whether DriverOrder is present in current configuration\r
1005 //\r
1006 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);\r
1007 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
1008\r
1009 if (NewDriverOrderList == NULL) {\r
1010 return EFI_OUT_OF_RESOURCES;\r
1011 }\r
1012 //\r
1013 // If exists, delete it to hold new DriverOrder\r
1014 //\r
1015 if (DriverOrderList != NULL) {\r
1016 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
1017 FreePool (DriverOrderList);\r
1018 }\r
1019\r
1020 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));\r
1021 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
1022 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);\r
1023 }\r
1024\r
1025 Status = gRT->SetVariable (\r
1026 L"DriverOrder",\r
1027 &gEfiGlobalVariableGuid,\r
1028 VAR_FLAG,\r
1029 DriverOrderListSize,\r
1030 NewDriverOrderList\r
1031 );\r
1032 if (EFI_ERROR (Status)) {\r
1033 return Status;\r
1034 }\r
1035\r
1036 BOpt_FreeMenu (&DriverOptionMenu);\r
1037 BOpt_GetDriverOptions (CallbackData);\r
1038 return EFI_SUCCESS;\r
1039}\r
1040\r
1041/**\r
1042 Update the Text Mode of Console.\r
1043\r
1044 @param CallbackData The context data for BMM.\r
1045\r
1046 @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
1047 @return Other value if the Text Mode of Console is not updated.\r
1048\r
1049**/\r
1050EFI_STATUS\r
1051Var_UpdateConMode (\r
1052 IN BMM_CALLBACK_DATA *CallbackData\r
1053 )\r
1054{\r
1055 EFI_STATUS Status;\r
1056 UINTN Mode;\r
1057 CONSOLE_OUT_MODE ModeInfo;\r
1058\r
1059 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
1060\r
1061 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
1062 if (!EFI_ERROR(Status)) {\r
1063 PcdSet32 (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);\r
1064 PcdSet32 (PcdSetupConOutRow, (UINT32) ModeInfo.Row);\r
1065 }\r
1066\r
1067 return EFI_SUCCESS;\r
1068}\r