]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
Clean up BootMaint module in BdsDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BootMaint / Variable.c
CommitLineData
fd6a62f3 1/** @file\r
2 Variable operation that will be used by bootmaint\r
93e3992d 3\r
fd6a62f3 4Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
93e3992d 5All rights reserved. This 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
fd6a62f3 13**/\r
93e3992d 14\r
15#include "BootMaint.h"\r
16\r
b30312ba 17/**\r
93e3992d 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
93e3992d 22\r
b30312ba 23 @param VOID EDES_TODO: Add parameter description\r
24\r
dce655e8 25 @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to \r
26 BM_LOAD_CONTEXT marked for deletion is deleted\r
27 @return Others If failed to update the "BootOrder" variable after deletion. \r
93e3992d 28\r
b30312ba 29**/\r
30EFI_STATUS\r
31Var_DelBootOption (\r
32 VOID\r
33 )\r
93e3992d 34{\r
35 BM_MENU_ENTRY *NewMenuEntry;\r
36 BM_LOAD_CONTEXT *NewLoadContext;\r
37 UINT16 BootString[10];\r
38 EFI_STATUS Status;\r
39 UINTN Index;\r
40 UINTN Index2;\r
41\r
42 Status = EFI_SUCCESS;\r
43 Index2 = 0;\r
44 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
45 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
46 if (NULL == NewMenuEntry) {\r
47 return EFI_NOT_FOUND;\r
48 }\r
49\r
50 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
51 if (!NewLoadContext->Deleted) {\r
52 continue;\r
53 }\r
54\r
55 UnicodeSPrint (\r
56 BootString,\r
57 sizeof (BootString),\r
58 L"Boot%04x",\r
59 NewMenuEntry->OptionNumber\r
60 );\r
61\r
62 EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
63 Index2++;\r
64 //\r
65 // If current Load Option is the same as BootNext,\r
66 // must delete BootNext in order to make sure\r
67 // there will be no panic on next boot\r
68 //\r
69 if (NewLoadContext->IsBootNext) {\r
70 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
71 }\r
72\r
73 RemoveEntryList (&NewMenuEntry->Link);\r
74 BOpt_DestroyMenuEntry (NewMenuEntry);\r
75 NewMenuEntry = NULL;\r
76 }\r
77\r
78 BootOptionMenu.MenuNumber -= Index2;\r
79\r
80 Status = Var_ChangeBootOrder ();\r
81 return Status;\r
82}\r
83\r
b30312ba 84/**\r
93e3992d 85 After any operation on Boot####, there will be a discrepancy in BootOrder.\r
86 Since some are missing but in BootOrder, while some are present but are\r
87 not reflected by BootOrder. Then a function rebuild BootOrder from\r
88 scratch by content from BootOptionMenu is needed.\r
89\r
93e3992d 90\r
dce655e8 91 @param VOID\r
b30312ba 92\r
dce655e8 93 @retval EFI_SUCCESS The boot order is updated successfully.\r
94 @return EFI_STATUS other than EFI_SUCCESS if failed to\r
95 Set the "BootOrder" EFI Variable.\r
93e3992d 96\r
b30312ba 97**/\r
98EFI_STATUS\r
99Var_ChangeBootOrder (\r
100 VOID\r
101 )\r
93e3992d 102{\r
103\r
104 EFI_STATUS Status;\r
105 BM_MENU_ENTRY *NewMenuEntry;\r
106 UINT16 *BootOrderList;\r
107 UINT16 *BootOrderListPtr;\r
108 UINTN BootOrderListSize;\r
109 UINTN Index;\r
110\r
111 BootOrderList = NULL;\r
112 BootOrderListSize = 0;\r
113\r
114 //\r
115 // First check whether BootOrder is present in current configuration\r
116 //\r
117 BootOrderList = BdsLibGetVariableAndSize (\r
118 L"BootOrder",\r
119 &gEfiGlobalVariableGuid,\r
120 &BootOrderListSize\r
121 );\r
122\r
123 //\r
124 // If exists, delete it to hold new BootOrder\r
125 //\r
a78b08d1 126 if (BootOrderList != NULL) {\r
93e3992d 127 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
128 SafeFreePool (BootOrderList);\r
129 BootOrderList = NULL;\r
130 }\r
131 //\r
132 // Maybe here should be some check method to ensure that\r
133 // no new added boot options will be added\r
134 // but the setup engine now will give only one callback\r
135 // that is to say, user are granted only one chance to\r
136 // decide whether the boot option will be added or not\r
137 // there should be no indictor to show whether this\r
138 // is a "new" boot option\r
139 //\r
140 BootOrderListSize = BootOptionMenu.MenuNumber;\r
141\r
142 if (BootOrderListSize > 0) {\r
dce655e8 143 BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
93e3992d 144 ASSERT (BootOrderList != NULL);\r
145 BootOrderListPtr = BootOrderList;\r
146\r
147 //\r
148 // Get all current used Boot#### from BootOptionMenu.\r
149 // OptionNumber in each BM_LOAD_OPTION is really its\r
150 // #### value.\r
151 //\r
152 for (Index = 0; Index < BootOrderListSize; Index++) {\r
153 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
154 *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
155 BootOrderList++;\r
156 }\r
157\r
158 BootOrderList = BootOrderListPtr;\r
159\r
160 //\r
161 // After building the BootOrderList, write it back\r
162 //\r
163 Status = gRT->SetVariable (\r
164 L"BootOrder",\r
165 &gEfiGlobalVariableGuid,\r
166 VAR_FLAG,\r
167 BootOrderListSize * sizeof (UINT16),\r
168 BootOrderList\r
169 );\r
170 if (EFI_ERROR (Status)) {\r
171 return Status;\r
172 }\r
173 }\r
174 return EFI_SUCCESS;\r
175}\r
176\r
b30312ba 177/**\r
93e3992d 178 Delete Load Option that represent a Deleted state in BootOptionMenu.\r
179 After deleting this Driver option, call Var_ChangeDriverOrder to\r
180 make sure DriverOrder is in valid state.\r
181\r
93e3992d 182\r
dce655e8 183 @param VOID\r
b30312ba 184\r
dce655e8 185 @retval EFI_SUCCESS Load Option is successfully updated.\r
186 @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI\r
187 Variable.\r
93e3992d 188\r
b30312ba 189**/\r
190EFI_STATUS\r
191Var_DelDriverOption (\r
192 VOID\r
193 )\r
93e3992d 194{\r
195 BM_MENU_ENTRY *NewMenuEntry;\r
196 BM_LOAD_CONTEXT *NewLoadContext;\r
197 UINT16 DriverString[12];\r
198 EFI_STATUS Status;\r
199 UINTN Index;\r
200 UINTN Index2;\r
201\r
202 Status = EFI_SUCCESS;\r
203 Index2 = 0;\r
204 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
205 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
206 if (NULL == NewMenuEntry) {\r
207 return EFI_NOT_FOUND;\r
208 }\r
209\r
210 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
211 if (!NewLoadContext->Deleted) {\r
212 continue;\r
213 }\r
214\r
215 UnicodeSPrint (\r
216 DriverString,\r
217 sizeof (DriverString),\r
218 L"Driver%04x",\r
219 NewMenuEntry->OptionNumber\r
220 );\r
221\r
222 EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
223 Index2++;\r
224\r
225 RemoveEntryList (&NewMenuEntry->Link);\r
226 BOpt_DestroyMenuEntry (NewMenuEntry);\r
227 NewMenuEntry = NULL;\r
228 }\r
229\r
230 DriverOptionMenu.MenuNumber -= Index2;\r
231\r
232 Status = Var_ChangeDriverOrder ();\r
233 return Status;\r
234}\r
235\r
b30312ba 236/**\r
93e3992d 237 After any operation on Driver####, there will be a discrepancy in\r
238 DriverOrder. Since some are missing but in DriverOrder, while some\r
239 are present but are not reflected by DriverOrder. Then a function\r
240 rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
241 needed.\r
242\r
93e3992d 243\r
dce655e8 244 @param VOID\r
93e3992d 245\r
dce655e8 246 @retval EFI_SUCCESS The driver order is updated successfully.\r
247 @return EFI_STATUS other than EFI_SUCCESS if failed to\r
248 Set the "DriverOrder" EFI Variable.\r
b30312ba 249\r
250**/\r
251EFI_STATUS\r
252Var_ChangeDriverOrder (\r
253 VOID\r
254 )\r
93e3992d 255{\r
256 EFI_STATUS Status;\r
257 BM_MENU_ENTRY *NewMenuEntry;\r
258 UINT16 *DriverOrderList;\r
259 UINT16 *DriverOrderListPtr;\r
260 UINTN DriverOrderListSize;\r
261 UINTN Index;\r
262\r
263 DriverOrderList = NULL;\r
264 DriverOrderListSize = 0;\r
265\r
266 //\r
267 // First check whether DriverOrder is present in current configuration\r
268 //\r
269 DriverOrderList = BdsLibGetVariableAndSize (\r
270 L"DriverOrder",\r
271 &gEfiGlobalVariableGuid,\r
272 &DriverOrderListSize\r
273 );\r
274\r
275 //\r
276 // If exists, delete it to hold new DriverOrder\r
277 //\r
a78b08d1 278 if (DriverOrderList != NULL) {\r
93e3992d 279 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
280 SafeFreePool (DriverOrderList);\r
281 DriverOrderList = NULL;\r
282 }\r
283\r
284 DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
285\r
286 if (DriverOrderListSize > 0) {\r
dce655e8 287 DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
93e3992d 288 ASSERT (DriverOrderList != NULL);\r
289 DriverOrderListPtr = DriverOrderList;\r
290\r
291 //\r
292 // Get all current used Driver#### from DriverOptionMenu.\r
293 // OptionNumber in each BM_LOAD_OPTION is really its\r
294 // #### value.\r
295 //\r
296 for (Index = 0; Index < DriverOrderListSize; Index++) {\r
297 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
298 *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
299 DriverOrderList++;\r
300 }\r
301\r
302 DriverOrderList = DriverOrderListPtr;\r
303\r
304 //\r
305 // After building the DriverOrderList, write it back\r
306 //\r
307 Status = gRT->SetVariable (\r
308 L"DriverOrder",\r
309 &gEfiGlobalVariableGuid,\r
310 VAR_FLAG,\r
311 DriverOrderListSize * sizeof (UINT16),\r
312 DriverOrderList\r
313 );\r
314 if (EFI_ERROR (Status)) {\r
315 return Status;\r
316 }\r
317 }\r
318 return EFI_SUCCESS;\r
319}\r
320\r
b30312ba 321/**\r
dce655e8 322 Update the device path of "ConOut", "ConIn" and "ErrOut" \r
323 based on the new BaudRate, Data Bits, parity and Stop Bits\r
324 set.\r
b30312ba 325\r
dce655e8 326 @param VOID\r
b30312ba 327\r
dce655e8 328 @return VOID\r
b30312ba 329\r
330**/\r
93e3992d 331VOID\r
332Var_UpdateAllConsoleOption (\r
333 VOID\r
334 )\r
335{\r
336 EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;\r
337 EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;\r
338 EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;\r
339 EFI_STATUS Status;\r
340\r
341 OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
342 InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
343 ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
a78b08d1 344 if (OutDevicePath != NULL) {\r
93e3992d 345 ChangeVariableDevicePath (OutDevicePath);\r
346 Status = gRT->SetVariable (\r
347 L"ConOut",\r
348 &gEfiGlobalVariableGuid,\r
349 VAR_FLAG,\r
350 GetDevicePathSize (OutDevicePath),\r
351 OutDevicePath\r
352 );\r
353 ASSERT (!EFI_ERROR (Status));\r
354 }\r
355\r
a78b08d1 356 if (InpDevicePath != NULL) {\r
93e3992d 357 ChangeVariableDevicePath (InpDevicePath);\r
358 Status = gRT->SetVariable (\r
359 L"ConIn",\r
360 &gEfiGlobalVariableGuid,\r
361 VAR_FLAG,\r
362 GetDevicePathSize (InpDevicePath),\r
363 InpDevicePath\r
364 );\r
365 ASSERT (!EFI_ERROR (Status));\r
366 }\r
367\r
a78b08d1 368 if (ErrDevicePath != NULL) {\r
93e3992d 369 ChangeVariableDevicePath (ErrDevicePath);\r
370 Status = gRT->SetVariable (\r
371 L"ErrOut",\r
372 &gEfiGlobalVariableGuid,\r
373 VAR_FLAG,\r
374 GetDevicePathSize (ErrDevicePath),\r
375 ErrDevicePath\r
376 );\r
377 ASSERT (!EFI_ERROR (Status));\r
378 }\r
379}\r
380\r
b30312ba 381/**\r
dce655e8 382 This function delete and build multi-instance device path for\r
383 specified type of console device.\r
384\r
385 This function clear the EFI variable defined by ConsoleName and\r
386 gEfiGlobalVariableGuid. It then build the multi-instance device\r
387 path by appending the device path of the Console (In/Out/Err) instance \r
388 in ConsoleMenu. Then it scan all corresponding console device by\r
389 scanning Terminal (built from device supporting Serial I/O instances)\r
390 devices in TerminalMenu. At last, it save a EFI variable specifed\r
391 by ConsoleName and gEfiGlobalVariableGuid.\r
392\r
393 @param ConsoleName The name for the console device type. They are\r
394 usually "ConIn", "ConOut" and "ErrOut".\r
395 @param ConsoleMenu The console memu which is a list of console devices.\r
396 @param UpdatePageId The flag specifying which type of console device\r
397 to be processed.\r
398\r
399 @retval EFI_SUCCESS The function complete successfully.\r
400 @return The EFI variable can be saved. See gRT->SetVariable \r
401 for detail return information.\r
b30312ba 402\r
403**/\r
93e3992d 404EFI_STATUS\r
405Var_UpdateConsoleOption (\r
406 IN UINT16 *ConsoleName,\r
407 IN BM_MENU_OPTION *ConsoleMenu,\r
408 IN UINT16 UpdatePageId\r
409 )\r
410{\r
411 EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
412 BM_MENU_ENTRY *NewMenuEntry;\r
413 BM_CONSOLE_CONTEXT *NewConsoleContext;\r
414 BM_TERMINAL_CONTEXT *NewTerminalContext;\r
415 EFI_STATUS Status;\r
416 VENDOR_DEVICE_PATH Vendor;\r
417 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
418 UINTN Index;\r
419\r
420 ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
421 if (ConDevicePath != NULL) {\r
422 EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
423 SafeFreePool (ConDevicePath);\r
424 ConDevicePath = NULL;\r
425 };\r
426\r
427 //\r
dce655e8 428 // First add all console input device from console input menu\r
93e3992d 429 //\r
430 for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
431 NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
93e3992d 432\r
433 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
434 if (NewConsoleContext->IsActive) {\r
435 ConDevicePath = AppendDevicePathInstance (\r
436 ConDevicePath,\r
437 NewConsoleContext->DevicePath\r
438 );\r
439 }\r
440 }\r
441\r
442 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
443 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
93e3992d 444\r
445 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
a78b08d1 446 if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||\r
447 ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
448 ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))\r
93e3992d 449 ) {\r
450 Vendor.Header.Type = MESSAGING_DEVICE_PATH;\r
451 Vendor.Header.SubType = MSG_VENDOR_DP;\r
452 CopyMem (\r
453 &Vendor.Guid,\r
dce655e8 454 &TerminalTypeGuid[NewTerminalContext->TerminalType],\r
93e3992d 455 sizeof (EFI_GUID)\r
456 );\r
457 SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
458 TerminalDevicePath = AppendDevicePathNode (\r
459 NewTerminalContext->DevicePath,\r
460 (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
461 );\r
462 ASSERT (TerminalDevicePath != NULL);\r
463 ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
464 ConDevicePath = AppendDevicePathInstance (\r
465 ConDevicePath,\r
466 TerminalDevicePath\r
467 );\r
468 }\r
469 }\r
470\r
a78b08d1 471 if (ConDevicePath != NULL) {\r
93e3992d 472 Status = gRT->SetVariable (\r
473 ConsoleName,\r
474 &gEfiGlobalVariableGuid,\r
475 VAR_FLAG,\r
476 GetDevicePathSize (ConDevicePath),\r
477 ConDevicePath\r
478 );\r
479 if (EFI_ERROR (Status)) {\r
480 return Status;\r
481 }\r
482 }\r
483\r
484 return EFI_SUCCESS;\r
485\r
486}\r
487\r
b30312ba 488/**\r
dce655e8 489 This function delete and build multi-instance device path ConIn\r
490 console device.\r
b30312ba 491\r
b30312ba 492\r
dce655e8 493 @param VOID\r
b30312ba 494\r
dce655e8 495 @retval EFI_SUCCESS The function complete successfully.\r
496 @return The EFI variable can be saved. See gRT->SetVariable \r
497 for detail return information.\r
b30312ba 498**/\r
93e3992d 499EFI_STATUS\r
500Var_UpdateConsoleInpOption (\r
501 VOID\r
502 )\r
503{\r
504 return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
505}\r
506\r
b30312ba 507/**\r
dce655e8 508 This function delete and build multi-instance device path ConOut\r
509 console device.\r
b30312ba 510\r
b30312ba 511\r
dce655e8 512 @param VOID\r
b30312ba 513\r
dce655e8 514 @retval EFI_SUCCESS The function complete successfully.\r
515 @return The EFI variable can be saved. See gRT->SetVariable \r
516 for detail return information.\r
b30312ba 517**/\r
93e3992d 518EFI_STATUS\r
519Var_UpdateConsoleOutOption (\r
520 VOID\r
521 )\r
522{\r
523 return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
524}\r
525\r
b30312ba 526/**\r
dce655e8 527 This function delete and build multi-instance device path ErrOut\r
528 console device.\r
b30312ba 529\r
b30312ba 530\r
dce655e8 531 @param VOID\r
b30312ba 532\r
dce655e8 533 @retval EFI_SUCCESS The function complete successfully.\r
534 @return The EFI variable can be saved. See gRT->SetVariable \r
535 for detail return information.\r
b30312ba 536**/\r
93e3992d 537EFI_STATUS\r
538Var_UpdateErrorOutOption (\r
539 VOID\r
540 )\r
541{\r
542 return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
543}\r
544\r
b30312ba 545/**\r
dce655e8 546 This function create a currently loaded Drive Option from \r
547 the BMM. It then appends this Driver Option to the end of \r
548 the "DriverOrder" list. It append this Driver Opotion to the end\r
549 of DriverOptionMenu.\r
550\r
551 @param CallbackData The BMM context data.\r
552 @param HiiHandle The HII handle associated with the BMM formset.\r
553 @param DescriptionData The description of this driver option.\r
554 @param OptionalData The optional load option.\r
b30312ba 555 @param ForceReconnect EDES_TODO: Add parameter description\r
556\r
dce655e8 557 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
558 @retval EFI_SUCCESS If function completes successfully.\r
b30312ba 559\r
560**/\r
93e3992d 561EFI_STATUS\r
562Var_UpdateDriverOption (\r
563 IN BMM_CALLBACK_DATA *CallbackData,\r
564 IN EFI_HII_HANDLE HiiHandle,\r
565 IN UINT16 *DescriptionData,\r
566 IN UINT16 *OptionalData,\r
567 IN UINT8 ForceReconnect\r
568 )\r
569{\r
570 UINT16 Index;\r
571 UINT16 *DriverOrderList;\r
572 UINT16 *NewDriverOrderList;\r
573 UINT16 DriverString[12];\r
574 UINTN DriverOrderListSize;\r
575 VOID *Buffer;\r
576 UINTN BufferSize;\r
577 UINT8 *Ptr;\r
578 BM_MENU_ENTRY *NewMenuEntry;\r
579 BM_LOAD_CONTEXT *NewLoadContext;\r
580 BOOLEAN OptionalDataExist;\r
581 EFI_STATUS Status;\r
582\r
583 OptionalDataExist = FALSE;\r
584\r
585 Index = BOpt_GetDriverOptionNumber ();\r
586 UnicodeSPrint (\r
587 DriverString,\r
588 sizeof (DriverString),\r
589 L"Driver%04x",\r
590 Index\r
591 );\r
592\r
593 if (*DescriptionData == 0x0000) {\r
594 StrCpy (DescriptionData, DriverString);\r
595 }\r
596\r
597 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
598 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
599\r
600 if (*OptionalData != 0x0000) {\r
601 OptionalDataExist = TRUE;\r
602 BufferSize += StrSize (OptionalData);\r
603 }\r
604\r
dce655e8 605 Buffer = AllocateZeroPool (BufferSize);\r
93e3992d 606 if (NULL == Buffer) {\r
607 return EFI_OUT_OF_RESOURCES;\r
608 }\r
609\r
610 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
611 if (NULL == NewMenuEntry) {\r
612 return EFI_OUT_OF_RESOURCES;\r
613 }\r
614\r
615 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
616 NewLoadContext->Deleted = FALSE;\r
617 NewLoadContext->LoadOptionSize = BufferSize;\r
618 Ptr = (UINT8 *) Buffer;\r
619 NewLoadContext->LoadOption = Ptr;\r
620 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
621 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
622 NewLoadContext->IsActive = TRUE;\r
623 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
624\r
625 Ptr += sizeof (UINT32);\r
626 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
627 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
628\r
629 Ptr += sizeof (UINT16);\r
630 CopyMem (\r
631 Ptr,\r
632 DescriptionData,\r
633 StrSize (DescriptionData)\r
634 );\r
635\r
dce655e8 636 NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
93e3992d 637 ASSERT (NewLoadContext->Description != NULL);\r
638 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
639 CopyMem (\r
640 NewLoadContext->Description,\r
641 (VOID *) Ptr,\r
642 StrSize (DescriptionData)\r
643 );\r
644\r
645 Ptr += StrSize (DescriptionData);\r
646 CopyMem (\r
647 Ptr,\r
648 CallbackData->LoadContext->FilePathList,\r
649 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
650 );\r
651\r
dce655e8 652 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
93e3992d 653 ASSERT (NewLoadContext->FilePathList != NULL);\r
654\r
655 CopyMem (\r
656 NewLoadContext->FilePathList,\r
657 (VOID *) Ptr,\r
658 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
659 );\r
660\r
661 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
662 NewMenuEntry->OptionNumber = Index;\r
663 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
664 CallbackData,\r
665 DriverOptionStrDepository\r
666 );\r
9226efe5 667 HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
93e3992d 668\r
669 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
670 CallbackData,\r
671 DriverOptionHelpStrDepository\r
672 );\r
9226efe5 673 HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
93e3992d 674\r
675 if (OptionalDataExist) {\r
676 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
677\r
678 CopyMem (\r
679 Ptr,\r
680 OptionalData,\r
681 StrSize (OptionalData)\r
682 );\r
683 }\r
684\r
685 Status = gRT->SetVariable (\r
686 DriverString,\r
687 &gEfiGlobalVariableGuid,\r
688 VAR_FLAG,\r
689 BufferSize,\r
690 Buffer\r
691 );\r
692 ASSERT_EFI_ERROR (Status);\r
693 DriverOrderList = BdsLibGetVariableAndSize (\r
694 L"DriverOrder",\r
695 &gEfiGlobalVariableGuid,\r
696 &DriverOrderListSize\r
697 );\r
dce655e8 698 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
93e3992d 699 ASSERT (NewDriverOrderList != NULL);\r
700 CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
701 NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
702 if (DriverOrderList != NULL) {\r
703 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
704 }\r
705\r
706 Status = gRT->SetVariable (\r
707 L"DriverOrder",\r
708 &gEfiGlobalVariableGuid,\r
709 VAR_FLAG,\r
710 DriverOrderListSize + sizeof (UINT16),\r
711 NewDriverOrderList\r
712 );\r
713 ASSERT_EFI_ERROR (Status);\r
714 SafeFreePool (DriverOrderList);\r
715 DriverOrderList = NULL;\r
716 SafeFreePool (NewDriverOrderList);\r
717 NewDriverOrderList = NULL;\r
718 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
719 DriverOptionMenu.MenuNumber++;\r
720\r
721 *DescriptionData = 0x0000;\r
722 *OptionalData = 0x0000;\r
723 return EFI_SUCCESS;\r
724}\r
725\r
b30312ba 726/**\r
dce655e8 727 This function create a currently loaded Boot Option from \r
728 the BMM. It then appends this Boot Option to the end of \r
729 the "BootOrder" list. It also append this Boot Opotion to the end\r
730 of BootOptionMenu.\r
b30312ba 731\r
dce655e8 732 @param CallbackData The BMM context data.\r
733 @param NvRamMap The file explorer formset internal state.\r
b30312ba 734\r
dce655e8 735 @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
736 @retval EFI_SUCCESS If function completes successfully.\r
b30312ba 737\r
738**/\r
dce655e8 739\r
93e3992d 740EFI_STATUS\r
741Var_UpdateBootOption (\r
742 IN BMM_CALLBACK_DATA *CallbackData,\r
743 IN FILE_EXPLORER_NV_DATA *NvRamMap\r
744 )\r
745{\r
746 UINT16 *BootOrderList;\r
747 UINT16 *NewBootOrderList;\r
748 UINTN BootOrderListSize;\r
749 UINT16 BootString[10];\r
750 VOID *Buffer;\r
751 UINTN BufferSize;\r
752 UINT8 *Ptr;\r
753 UINT16 Index;\r
754 BM_MENU_ENTRY *NewMenuEntry;\r
755 BM_LOAD_CONTEXT *NewLoadContext;\r
756 BOOLEAN OptionalDataExist;\r
757 EFI_STATUS Status;\r
758\r
759 OptionalDataExist = FALSE;\r
760\r
761 Index = BOpt_GetBootOptionNumber () ;\r
762 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
763\r
764 if (NvRamMap->DescriptionData[0] == 0x0000) {\r
765 StrCpy (NvRamMap->DescriptionData, BootString);\r
766 }\r
767\r
768 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
769 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
770\r
771 if (NvRamMap->OptionalData[0] != 0x0000) {\r
772 OptionalDataExist = TRUE;\r
773 BufferSize += StrSize (NvRamMap->OptionalData);\r
774 }\r
775\r
dce655e8 776 Buffer = AllocateZeroPool (BufferSize);\r
93e3992d 777 if (NULL == Buffer) {\r
778 return EFI_OUT_OF_RESOURCES;\r
779 }\r
780\r
781 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
782 if (NULL == NewMenuEntry) {\r
783 return EFI_OUT_OF_RESOURCES;\r
784 }\r
785\r
786 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
787 NewLoadContext->Deleted = FALSE;\r
788 NewLoadContext->LoadOptionSize = BufferSize;\r
789 Ptr = (UINT8 *) Buffer;\r
790 NewLoadContext->LoadOption = Ptr;\r
791 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
792 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
793 NewLoadContext->IsActive = TRUE;\r
794 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
795\r
796 Ptr += sizeof (UINT32);\r
797 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
798 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
799 Ptr += sizeof (UINT16);\r
800\r
801 CopyMem (\r
802 Ptr,\r
803 NvRamMap->DescriptionData,\r
804 StrSize (NvRamMap->DescriptionData)\r
805 );\r
806\r
dce655e8 807 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
93e3992d 808 ASSERT (NewLoadContext->Description != NULL);\r
809\r
810 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
811 CopyMem (\r
812 NewLoadContext->Description,\r
813 (VOID *) Ptr,\r
814 StrSize (NvRamMap->DescriptionData)\r
815 );\r
816\r
817 Ptr += StrSize (NvRamMap->DescriptionData);\r
818 CopyMem (\r
819 Ptr,\r
820 CallbackData->LoadContext->FilePathList,\r
821 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
822 );\r
823\r
dce655e8 824 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
93e3992d 825 ASSERT (NewLoadContext->FilePathList != NULL);\r
826\r
827 CopyMem (\r
828 NewLoadContext->FilePathList,\r
829 (VOID *) Ptr,\r
830 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
831 );\r
832\r
833 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
834 NewMenuEntry->OptionNumber = Index;\r
835 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
836 CallbackData,\r
837 BootOptionStrDepository\r
838 );\r
9226efe5 839 HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
93e3992d 840\r
841 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
842 CallbackData,\r
843 BootOptionHelpStrDepository\r
844 );\r
9226efe5 845 HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
93e3992d 846\r
847 if (OptionalDataExist) {\r
848 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
849\r
850 CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
851 }\r
852\r
853 Status = gRT->SetVariable (\r
854 BootString,\r
855 &gEfiGlobalVariableGuid,\r
856 VAR_FLAG,\r
857 BufferSize,\r
858 Buffer\r
859 );\r
860 ASSERT_EFI_ERROR (Status);\r
861\r
862 BootOrderList = BdsLibGetVariableAndSize (\r
863 L"BootOrder",\r
864 &gEfiGlobalVariableGuid,\r
865 &BootOrderListSize\r
866 );\r
867\r
dce655e8 868 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
93e3992d 869 ASSERT (NewBootOrderList != NULL);\r
870 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
871 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
872\r
873 if (BootOrderList != NULL) {\r
874 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
875 }\r
876\r
877 Status = gRT->SetVariable (\r
878 L"BootOrder",\r
879 &gEfiGlobalVariableGuid,\r
880 VAR_FLAG,\r
881 BootOrderListSize + sizeof (UINT16),\r
882 NewBootOrderList\r
883 );\r
884 ASSERT_EFI_ERROR (Status);\r
885\r
886 SafeFreePool (BootOrderList);\r
887 BootOrderList = NULL;\r
888 SafeFreePool (NewBootOrderList);\r
889 NewBootOrderList = NULL;\r
890 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
891 BootOptionMenu.MenuNumber++;\r
892\r
893 NvRamMap->DescriptionData[0] = 0x0000;\r
894 NvRamMap->OptionalData[0] = 0x0000;\r
895 return EFI_SUCCESS;\r
896}\r
897\r
b30312ba 898/**\r
dce655e8 899 This function update the "BootNext" EFI Variable. If there is \r
900 no "BootNex" specified in BMM, this EFI Variable is deleted.\r
901 It also update the BMM context data specified the "BootNext"\r
902 vaule.\r
b30312ba 903\r
dce655e8 904 @param CallbackData The BMM context data.\r
b30312ba 905\r
dce655e8 906 @retval EFI_SUCCESS The function complete successfully.\r
907 @return The EFI variable can be saved. See gRT->SetVariable \r
908 for detail return information.\r
b30312ba 909\r
910**/\r
93e3992d 911EFI_STATUS\r
912Var_UpdateBootNext (\r
913 IN BMM_CALLBACK_DATA *CallbackData\r
914 )\r
915{\r
916 BM_MENU_ENTRY *NewMenuEntry;\r
917 BM_LOAD_CONTEXT *NewLoadContext;\r
918 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
919 UINT16 Index;\r
920 EFI_STATUS Status;\r
921\r
922 Status = EFI_SUCCESS;\r
923 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
924 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
925 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
dce655e8 926 ASSERT (NULL != NewMenuEntry);\r
93e3992d 927\r
928 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
929 NewLoadContext->IsBootNext = FALSE;\r
930 }\r
931\r
932 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
933 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
934 return EFI_SUCCESS;\r
935 }\r
936\r
937 NewMenuEntry = BOpt_GetMenuEntry (\r
938 &BootOptionMenu,\r
939 CurrentFakeNVMap->BootNext\r
940 );\r
dce655e8 941 ASSERT (NewMenuEntry != NULL);\r
93e3992d 942\r
943 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
944 Status = gRT->SetVariable (\r
945 L"BootNext",\r
946 &gEfiGlobalVariableGuid,\r
947 VAR_FLAG,\r
948 sizeof (UINT16),\r
949 &NewMenuEntry->OptionNumber\r
950 );\r
951 NewLoadContext->IsBootNext = TRUE;\r
952 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
953 return Status;\r
954}\r
955\r
b30312ba 956/**\r
dce655e8 957 This function update the "BootOrder" EFI Variable based on\r
958 BMM Formset's NV map. It then refresh BootOptionMenu\r
959 with the new "BootOrder" list.\r
b30312ba 960\r
dce655e8 961 @param CallbackData The BMM context data.\r
b30312ba 962\r
dce655e8 963 @retval EFI_SUCCESS The function complete successfully.\r
964 @retval EFI_SUCCESS Not enough memory to complete the function.\r
965 @return The EFI variable can be saved. See gRT->SetVariable \r
966 for detail return information.\r
b30312ba 967\r
968**/\r
93e3992d 969EFI_STATUS\r
970Var_UpdateBootOrder (\r
971 IN BMM_CALLBACK_DATA *CallbackData\r
972 )\r
973{\r
974 EFI_STATUS Status;\r
975 UINT16 Index;\r
976 UINT16 *BootOrderList;\r
977 UINT16 *NewBootOrderList;\r
978 UINTN BootOrderListSize;\r
93e3992d 979\r
980 BootOrderList = NULL;\r
981 BootOrderListSize = 0;\r
982\r
983 //\r
984 // First check whether BootOrder is present in current configuration\r
985 //\r
986 BootOrderList = BdsLibGetVariableAndSize (\r
987 L"BootOrder",\r
988 &gEfiGlobalVariableGuid,\r
989 &BootOrderListSize\r
990 );\r
991\r
dce655e8 992 NewBootOrderList = AllocateZeroPool (BootOrderListSize);\r
a78b08d1 993 if (NewBootOrderList == NULL) {\r
93e3992d 994 return EFI_OUT_OF_RESOURCES;\r
995 }\r
996\r
93e3992d 997 //\r
998 // If exists, delete it to hold new BootOrder\r
999 //\r
a78b08d1 1000 if (BootOrderList != NULL) {\r
93e3992d 1001 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
1002 }\r
1003\r
1004 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
1005 NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
1006 }\r
1007\r
1008 Status = gRT->SetVariable (\r
1009 L"BootOrder",\r
1010 &gEfiGlobalVariableGuid,\r
1011 VAR_FLAG,\r
1012 BootOrderListSize,\r
1013 NewBootOrderList\r
1014 );\r
1015 SafeFreePool (BootOrderList);\r
1016 SafeFreePool (NewBootOrderList);\r
93e3992d 1017 if (EFI_ERROR (Status)) {\r
1018 return Status;\r
1019 }\r
1020\r
1021 BOpt_FreeMenu (&BootOptionMenu);\r
1022 BOpt_GetBootOptions (CallbackData);\r
1023\r
1024 return EFI_SUCCESS;\r
1025\r
1026}\r
1027\r
b30312ba 1028/**\r
dce655e8 1029 This function update the "DriverOrder" EFI Variable based on\r
1030 BMM Formset's NV map. It then refresh DriverOptionMenu\r
1031 with the new "DriverOrder" list.\r
b30312ba 1032\r
dce655e8 1033 @param CallbackData The BMM context data.\r
b30312ba 1034\r
dce655e8 1035 @retval EFI_SUCCESS The function complete successfully.\r
1036 @retval EFI_SUCCESS Not enough memory to complete the function.\r
1037 @return The EFI variable can be saved. See gRT->SetVariable \r
1038 for detail return information.\r
b30312ba 1039\r
1040**/\r
93e3992d 1041EFI_STATUS\r
1042Var_UpdateDriverOrder (\r
1043 IN BMM_CALLBACK_DATA *CallbackData\r
1044 )\r
1045{\r
1046 EFI_STATUS Status;\r
1047 UINT16 Index;\r
1048 UINT16 *DriverOrderList;\r
1049 UINT16 *NewDriverOrderList;\r
1050 UINTN DriverOrderListSize;\r
1051\r
1052 DriverOrderList = NULL;\r
1053 DriverOrderListSize = 0;\r
1054\r
1055 //\r
1056 // First check whether DriverOrder is present in current configuration\r
1057 //\r
1058 DriverOrderList = BdsLibGetVariableAndSize (\r
1059 L"DriverOrder",\r
1060 &gEfiGlobalVariableGuid,\r
1061 &DriverOrderListSize\r
1062 );\r
1063\r
dce655e8 1064 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
93e3992d 1065\r
a78b08d1 1066 if (NewDriverOrderList == NULL) {\r
93e3992d 1067 return EFI_OUT_OF_RESOURCES;\r
1068 }\r
1069 //\r
1070 // If exists, delete it to hold new DriverOrder\r
1071 //\r
a78b08d1 1072 if (DriverOrderList != NULL) {\r
93e3992d 1073 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
1074 }\r
1075\r
1076 for (Index = 0; Index < DriverOrderListSize; Index++) {\r
1077 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
1078 }\r
1079\r
1080 Status = gRT->SetVariable (\r
1081 L"DriverOrder",\r
1082 &gEfiGlobalVariableGuid,\r
1083 VAR_FLAG,\r
1084 DriverOrderListSize,\r
1085 NewDriverOrderList\r
1086 );\r
1087 if (EFI_ERROR (Status)) {\r
1088 return Status;\r
1089 }\r
1090\r
1091 SafeFreePool (DriverOrderList);\r
1092\r
1093 BOpt_FreeMenu (&DriverOptionMenu);\r
1094 BOpt_GetDriverOptions (CallbackData);\r
1095 return EFI_SUCCESS;\r
1096}\r
1097\r
b30312ba 1098/**\r
dce655e8 1099 Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable\r
1100 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
1101 is also updated.\r
b30312ba 1102\r
dce655e8 1103 @param CallbackData The context data for BMM.\r
b30312ba 1104\r
dce655e8 1105 @return EFI_SUCCESS The function completed successfully.\r
1106 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.\r
b30312ba 1107\r
1108**/\r
93e3992d 1109EFI_STATUS\r
1110Var_UpdateBBSOption (\r
1111 IN BMM_CALLBACK_DATA *CallbackData\r
1112 )\r
1113{\r
1114 UINTN Index;\r
1115 UINTN Index2;\r
1116 VOID *BootOptionVar;\r
1117 CHAR16 VarName[100];\r
1118 UINTN OptionSize;\r
1119 UINT8 *Ptr;\r
1120 EFI_STATUS Status;\r
1121 CHAR16 DescString[100];\r
1122 CHAR8 DescAsciiString[100];\r
1123 UINTN NewOptionSize;\r
1124 UINT8 *NewOptionPtr;\r
1125 UINT8 *TempPtr;\r
1126 UINT32 *Attribute;\r
1127 BM_MENU_OPTION *OptionMenu;\r
1128 BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;\r
1129 UINT8 *LegacyDev;\r
1130 UINT8 *VarData;\r
1131 UINTN VarSize;\r
1132 BM_MENU_ENTRY *NewMenuEntry;\r
1133 BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
1134 UINT8 *OriginalPtr;\r
1135 UINT8 *DisMap;\r
1136 UINTN Pos;\r
1137 UINTN Bit;\r
1138 UINT16 *NewOrder;\r
1139 UINT16 Tmp;\r
1140\r
1141 LegacyDeviceContext = NULL;\r
1142 DisMap = NULL;\r
1143 NewOrder = NULL;\r
1144\r
1145 if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1146 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
1147 LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;\r
1148 CallbackData->BbsType = BBS_FLOPPY;\r
1149 } else {\r
1150 if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1151 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
1152 LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;\r
1153 CallbackData->BbsType = BBS_HARDDISK;\r
1154 } else {\r
1155 if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1156 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
1157 LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;\r
1158 CallbackData->BbsType = BBS_CDROM;\r
1159 } else {\r
1160 if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1161 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
1162 LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;\r
1163 CallbackData->BbsType = BBS_EMBED_NETWORK;\r
1164 } else {\r
1165 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
1166 LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;\r
1167 CallbackData->BbsType = BBS_BEV_DEVICE;\r
1168 }\r
1169 }\r
1170 }\r
1171 }\r
1172\r
1173 DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
1174 Status = EFI_SUCCESS;\r
1175\r
1176 //\r
1177 // Find the first device's context\r
1178 // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
1179 // because we just use it to fill the desc string, and user can not see the string in UI\r
1180 //\r
1181 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1182 NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
1183 LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
1184 if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
1185 DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
1186 break;\r
1187 }\r
1188 }\r
1189 //\r
1190 // Update the Variable "LegacyDevOrder"\r
1191 //\r
1192 VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
5f597758 1193 VAR_LEGACY_DEV_ORDER,\r
93e3992d 1194 &EfiLegacyDevOrderGuid,\r
1195 &VarSize\r
1196 );\r
1197\r
1198 if (NULL == VarData) {\r
1199 return EFI_NOT_FOUND;\r
1200 }\r
1201\r
1202 OriginalPtr = VarData;\r
1203 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
1204\r
1205 while (VarData < VarData + VarSize) {\r
1206 if (DevOrder->BbsType == CallbackData->BbsType) {\r
1207 break;\r
1208 }\r
1209\r
1210 VarData += sizeof (BBS_TYPE);\r
1211 VarData += *(UINT16 *) VarData;\r
1212 DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
1213 }\r
1214\r
1215 if (VarData >= VarData + VarSize) {\r
1216 SafeFreePool (OriginalPtr);\r
1217 return EFI_NOT_FOUND;\r
1218 }\r
1219\r
dce655e8 1220 NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
93e3992d 1221 if (NULL == NewOrder) {\r
1222 SafeFreePool (VarData);\r
1223 return EFI_OUT_OF_RESOURCES;\r
1224 }\r
1225\r
1226 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1227 if (0xFF == LegacyDev[Index]) {\r
1228 break;\r
1229 }\r
1230\r
1231 NewOrder[Index] = LegacyDev[Index];\r
1232 }\r
1233 //\r
1234 // Only the enable/disable state of each boot device with same device type can be changed,\r
1235 // so we can count on the index information in DevOrder.\r
1236 // DisMap bit array is the only reliable source to check a device's en/dis state,\r
1237 // so we use DisMap to set en/dis state of each item in NewOrder array\r
1238 //\r
1239 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
1240 Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
1241 Tmp &= 0xFF;\r
1242 Pos = Tmp / 8;\r
1243 Bit = 7 - (Tmp % 8);\r
a78b08d1 1244 if ((DisMap[Pos] & (1 << Bit)) != 0) {\r
93e3992d 1245 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
1246 Index++;\r
1247 }\r
1248 }\r
1249\r
1250 CopyMem (\r
1251 (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
1252 NewOrder,\r
1253 DevOrder->Length - sizeof (UINT16)\r
1254 );\r
1255 SafeFreePool (NewOrder);\r
1256\r
1257 Status = gRT->SetVariable (\r
5f597758 1258 VAR_LEGACY_DEV_ORDER,\r
93e3992d 1259 &EfiLegacyDevOrderGuid,\r
1260 VAR_FLAG,\r
1261 VarSize,\r
1262 OriginalPtr\r
1263 );\r
1264\r
1265 SafeFreePool (OriginalPtr);\r
1266\r
1267 //\r
1268 // Update Optional Data of Boot####\r
1269 //\r
1270 BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
1271\r
1272 if (NULL != BootOptionVar) {\r
1273 CopyMem (\r
1274 DescString,\r
1275 LegacyDeviceContext->Description,\r
1276 StrSize (LegacyDeviceContext->Description)\r
1277 );\r
1278\r
1279 UnicodeToAscii (DescString, StrSize (DescString), DescAsciiString);\r
1280\r
1281 NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +\r
1282 sizeof (BBS_BBS_DEVICE_PATH);\r
1283 NewOptionSize += AsciiStrLen (DescAsciiString) +\r
1284 EFI_END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);\r
1285\r
1286 UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
1287\r
1288 Ptr = BootOptionVar;\r
1289\r
1290 Attribute = (UINT32 *) Ptr;\r
1291 *Attribute |= LOAD_OPTION_ACTIVE;\r
1292 if (0xFF == LegacyDev[0]) {\r
1293 //\r
1294 // Disable this legacy boot option\r
1295 //\r
1296 *Attribute &= ~LOAD_OPTION_ACTIVE;\r
1297 }\r
1298\r
1299 Ptr += sizeof (UINT32);\r
1300\r
1301 Ptr += sizeof (UINT16);\r
1302 Ptr += StrSize ((CHAR16 *) Ptr);\r
1303\r
dce655e8 1304 NewOptionPtr = AllocateZeroPool (NewOptionSize);\r
93e3992d 1305 if (NULL == NewOptionPtr) {\r
1306 return EFI_OUT_OF_RESOURCES;\r
1307 }\r
1308\r
1309 TempPtr = NewOptionPtr;\r
1310\r
1311 //\r
1312 // Attribute\r
1313 //\r
1314 CopyMem (\r
1315 TempPtr,\r
1316 BootOptionVar,\r
1317 sizeof (UINT32)\r
1318 );\r
1319\r
1320 TempPtr += sizeof (UINT32);\r
1321\r
1322 //\r
1323 // BBS device path Length\r
1324 //\r
1325 *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +\r
1326 AsciiStrLen (DescAsciiString) +\r
1327 EFI_END_DEVICE_PATH_LENGTH);\r
1328\r
1329 TempPtr += sizeof (UINT16);\r
1330\r
1331 //\r
1332 // Description string\r
1333 //\r
1334 CopyMem (\r
1335 TempPtr,\r
1336 DescString,\r
1337 StrSize (DescString)\r
1338 );\r
1339\r
1340 TempPtr += StrSize (DescString);\r
1341\r
1342 //\r
1343 // BBS device path\r
1344 //\r
1345 CopyMem (\r
1346 TempPtr,\r
1347 Ptr,\r
1348 sizeof (BBS_BBS_DEVICE_PATH)\r
1349 );\r
1350\r
1351 CopyMem (\r
1352 ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,\r
1353 DescAsciiString,\r
1354 AsciiStrSize (DescAsciiString)\r
1355 );\r
1356\r
1357 SetDevicePathNodeLength (\r
1358 (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,\r
1359 sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)\r
1360 );\r
1361\r
1362 TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);\r
1363\r
1364 //\r
1365 // End node\r
1366 //\r
1367 CopyMem (\r
1368 TempPtr,\r
1369 EndDevicePath,\r
1370 EFI_END_DEVICE_PATH_LENGTH\r
1371 );\r
1372 TempPtr += EFI_END_DEVICE_PATH_LENGTH;\r
1373\r
1374 //\r
1375 // Now TempPtr point to optional data, i.e. Bbs Table\r
1376 //\r
1377 CopyMem (\r
1378 TempPtr,\r
1379 LegacyDeviceContext->BbsTable,\r
1380 sizeof (BBS_TABLE)\r
1381 );\r
1382\r
1383 //\r
1384 // Now TempPtr point to BBS index\r
1385 //\r
1386 TempPtr += sizeof (BBS_TABLE);\r
1387 *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
1388\r
1389 Status = gRT->SetVariable (\r
1390 VarName,\r
1391 &gEfiGlobalVariableGuid,\r
1392 VAR_FLAG,\r
1393 NewOptionSize,\r
1394 NewOptionPtr\r
1395 );\r
1396\r
1397 SafeFreePool (NewOptionPtr);\r
1398 SafeFreePool (BootOptionVar);\r
1399 }\r
1400\r
1401 BOpt_GetBootOptions (CallbackData);\r
1402 return Status;\r
1403}\r
1404\r
b30312ba 1405/**\r
dce655e8 1406 Update the Text Mode of Console.\r
b30312ba 1407\r
dce655e8 1408 @param CallbackData The context data for BMM.\r
b30312ba 1409\r
dce655e8 1410 @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
1411 @return Other value if the Text Mode of Console is not updated.\r
b30312ba 1412\r
1413**/\r
93e3992d 1414EFI_STATUS\r
1415Var_UpdateConMode (\r
1416 IN BMM_CALLBACK_DATA *CallbackData\r
1417 )\r
1418{\r
1419 EFI_STATUS Status;\r
1420 UINTN Mode;\r
1421 CONSOLE_OUT_MODE ModeInfo;\r
1422\r
1423 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
1424\r
1425 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
1426 if (EFI_ERROR(Status)) {\r
1427 ModeInfo.Column = 80;\r
1428 ModeInfo.Row = 25;\r
1429 }\r
1430\r
1431 Status = gRT->SetVariable (\r
1432 VarConOutMode,\r
1433 &gEfiGenericPlatformVariableGuid,\r
1434 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1435 sizeof (CONSOLE_OUT_MODE),\r
1436 &ModeInfo\r
1437 );\r
1438\r
1439 return Status;\r
1440}\r