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