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