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