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