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