]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c
Refine code to follow good coding style.
[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
69fc8f08 4Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials\r
5c08e117 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "BootMaint.h"\r
16\r
17/**\r
18 Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
19 After deleting this boot option, call Var_ChangeBootOrder to\r
20 make sure BootOrder is in valid state.\r
21\r
22 @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to \r
23 BM_LOAD_CONTEXT marked for deletion is deleted.\r
24 @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.\r
25 @return Others If failed to update the "BootOrder" variable after deletion. \r
26\r
27**/\r
28EFI_STATUS\r
29Var_DelBootOption (\r
30 VOID\r
31 )\r
32{\r
33 BM_MENU_ENTRY *NewMenuEntry;\r
34 BM_LOAD_CONTEXT *NewLoadContext;\r
35 UINT16 BootString[10];\r
36 EFI_STATUS Status;\r
37 UINTN Index;\r
38 UINTN Index2;\r
39\r
40 Status = EFI_SUCCESS;\r
41 Index2 = 0;\r
42 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
43 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
44 if (NULL == NewMenuEntry) {\r
45 return EFI_NOT_FOUND;\r
46 }\r
47\r
48 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
49 if (!NewLoadContext->Deleted) {\r
50 continue;\r
51 }\r
52\r
53 UnicodeSPrint (\r
54 BootString,\r
55 sizeof (BootString),\r
56 L"Boot%04x",\r
57 NewMenuEntry->OptionNumber\r
58 );\r
59\r
60 EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
61 Index2++;\r
62 //\r
63 // If current Load Option is the same as BootNext,\r
64 // must delete BootNext in order to make sure\r
65 // there will be no panic on next boot\r
66 //\r
67 if (NewLoadContext->IsBootNext) {\r
68 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
69 }\r
70\r
71 RemoveEntryList (&NewMenuEntry->Link);\r
72 BOpt_DestroyMenuEntry (NewMenuEntry);\r
73 NewMenuEntry = NULL;\r
74 }\r
75\r
76 BootOptionMenu.MenuNumber -= Index2;\r
77\r
78 Status = Var_ChangeBootOrder ();\r
79 return Status;\r
80}\r
81\r
82/**\r
83 After any operation on Boot####, there will be a discrepancy in BootOrder.\r
84 Since some are missing but in BootOrder, while some are present but are\r
85 not reflected by BootOrder. Then a function rebuild BootOrder from\r
86 scratch by content from BootOptionMenu is needed.\r
87\r
88\r
89 \r
90\r
91 @retval EFI_SUCCESS The boot order is updated successfully.\r
92 @return EFI_STATUS other than EFI_SUCCESS if failed to\r
93 Set the "BootOrder" EFI Variable.\r
94\r
95**/\r
96EFI_STATUS\r
97Var_ChangeBootOrder (\r
98 VOID\r
99 )\r
100{\r
101\r
102 EFI_STATUS Status;\r
103 BM_MENU_ENTRY *NewMenuEntry;\r
104 UINT16 *BootOrderList;\r
105 UINT16 *BootOrderListPtr;\r
106 UINTN BootOrderListSize;\r
107 UINTN Index;\r
108\r
109 BootOrderList = NULL;\r
110 BootOrderListSize = 0;\r
111\r
112 //\r
113 // First check whether BootOrder is present in current configuration\r
114 //\r
115 BootOrderList = BdsLibGetVariableAndSize (\r
116 L"BootOrder",\r
117 &gEfiGlobalVariableGuid,\r
118 &BootOrderListSize\r
119 );\r
120\r
121 //\r
122 // If exists, delete it to hold new BootOrder\r
123 //\r
124 if (BootOrderList != NULL) {\r
125 EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
126 FreePool (BootOrderList);\r
127 BootOrderList = NULL;\r
128 }\r
129 //\r
130 // Maybe here should be some check method to ensure that\r
131 // no new added boot options will be added\r
132 // but the setup engine now will give only one callback\r
133 // that is to say, user are granted only one chance to\r
134 // decide whether the boot option will be added or not\r
135 // there should be no indictor to show whether this\r
136 // is a "new" boot option\r
137 //\r
138 BootOrderListSize = BootOptionMenu.MenuNumber;\r
139\r
140 if (BootOrderListSize > 0) {\r
141 BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
142 ASSERT (BootOrderList != NULL);\r
143 BootOrderListPtr = BootOrderList;\r
144\r
145 //\r
146 // Get all current used Boot#### from BootOptionMenu.\r
147 // OptionNumber in each BM_LOAD_OPTION is really its\r
148 // #### value.\r
149 //\r
150 for (Index = 0; Index < BootOrderListSize; Index++) {\r
151 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
152 *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
153 BootOrderList++;\r
154 }\r
155\r
156 BootOrderList = BootOrderListPtr;\r
157\r
158 //\r
159 // After building the BootOrderList, write it back\r
160 //\r
161 Status = gRT->SetVariable (\r
162 L"BootOrder",\r
163 &gEfiGlobalVariableGuid,\r
16e5944a 164 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 165 BootOrderListSize * sizeof (UINT16),\r
166 BootOrderList\r
167 );\r
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
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
16e5944a 339 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 340 GetDevicePathSize (OutDevicePath),\r
341 OutDevicePath\r
342 );\r
69fc8f08
RN
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
5c08e117 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
16e5944a 354 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 355 GetDevicePathSize (InpDevicePath),\r
356 InpDevicePath\r
357 );\r
69fc8f08
RN
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
5c08e117 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
16e5944a 369 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 370 GetDevicePathSize (ErrDevicePath),\r
371 ErrDevicePath\r
372 );\r
69fc8f08
RN
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
5c08e117 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 < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])));\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
8e491a81 463 ChangeTerminalDevicePath (&TerminalDevicePath, TRUE);\r
5c08e117 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
16e5944a 475 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 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 StrCpy (DescriptionData, 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
cb7d01c0 656 NewMenuEntry->DisplayStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
5c08e117 657\r
658 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
659 CallbackData,\r
660 DriverOptionHelpStrDepository\r
661 );\r
cb7d01c0 662 NewMenuEntry->HelpStringToken = HiiSetString (HiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
5c08e117 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
16e5944a 677 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 678 BufferSize,\r
679 Buffer\r
680 );\r
69fc8f08
RN
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
5c08e117 694\r
69fc8f08
RN
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
5c08e117 710\r
8acb3f7b
ED
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
69fc8f08
RN
721 *DescriptionData = 0x0000;\r
722 *OptionalData = 0x0000;\r
723 }\r
724 }\r
5c08e117 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
be9304f3
ED
765 if (NvRamMap->BootDescriptionData[0] == 0x0000) {\r
766 StrCpy (NvRamMap->BootDescriptionData, BootString);\r
5c08e117 767 }\r
768\r
be9304f3 769 BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->BootDescriptionData);\r
5c08e117 770 BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
771\r
be9304f3 772 if (NvRamMap->BootOptionalData[0] != 0x0000) {\r
5c08e117 773 OptionalDataExist = TRUE;\r
be9304f3 774 BufferSize += StrSize (NvRamMap->BootOptionalData);\r
5c08e117 775 }\r
776\r
777 Buffer = AllocateZeroPool (BufferSize);\r
778 if (NULL == Buffer) {\r
779 return EFI_OUT_OF_RESOURCES;\r
780 }\r
781\r
782 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
783 if (NULL == NewMenuEntry) {\r
784 return EFI_OUT_OF_RESOURCES;\r
785 }\r
786\r
787 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
788 NewLoadContext->Deleted = FALSE;\r
789 NewLoadContext->LoadOptionSize = BufferSize;\r
790 Ptr = (UINT8 *) Buffer;\r
791 NewLoadContext->LoadOption = Ptr;\r
792 *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
793 NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
794 NewLoadContext->IsActive = TRUE;\r
795 NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
796\r
797 Ptr += sizeof (UINT32);\r
798 *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
799 NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
800 Ptr += sizeof (UINT16);\r
801\r
802 CopyMem (\r
803 Ptr,\r
be9304f3
ED
804 NvRamMap->BootDescriptionData,\r
805 StrSize (NvRamMap->BootDescriptionData)\r
5c08e117 806 );\r
807\r
be9304f3 808 NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->BootDescriptionData));\r
5c08e117 809 ASSERT (NewLoadContext->Description != NULL);\r
810\r
811 NewMenuEntry->DisplayString = NewLoadContext->Description;\r
812 CopyMem (\r
813 NewLoadContext->Description,\r
814 (VOID *) Ptr,\r
be9304f3 815 StrSize (NvRamMap->BootDescriptionData)\r
5c08e117 816 );\r
817\r
be9304f3 818 Ptr += StrSize (NvRamMap->BootDescriptionData);\r
5c08e117 819 CopyMem (\r
820 Ptr,\r
821 CallbackData->LoadContext->FilePathList,\r
822 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
823 );\r
824\r
825 NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
826 ASSERT (NewLoadContext->FilePathList != NULL);\r
827\r
828 CopyMem (\r
829 NewLoadContext->FilePathList,\r
830 (VOID *) Ptr,\r
831 GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
832 );\r
833\r
834 NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
835 NewMenuEntry->OptionNumber = Index;\r
836 NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
837 CallbackData,\r
838 BootOptionStrDepository\r
839 );\r
cb7d01c0 840 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL);\r
5c08e117 841\r
842 NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
843 CallbackData,\r
844 BootOptionHelpStrDepository\r
845 );\r
cb7d01c0 846 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL);\r
5c08e117 847\r
848 if (OptionalDataExist) {\r
849 Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
850\r
be9304f3 851 CopyMem (Ptr, NvRamMap->BootOptionalData, StrSize (NvRamMap->BootOptionalData));\r
5c08e117 852 }\r
853\r
854 Status = gRT->SetVariable (\r
855 BootString,\r
856 &gEfiGlobalVariableGuid,\r
16e5944a 857 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 858 BufferSize,\r
859 Buffer\r
860 );\r
69fc8f08 861 if (!EFI_ERROR (Status)) {\r
5c08e117 862\r
69fc8f08
RN
863 BootOrderList = BdsLibGetVariableAndSize (\r
864 L"BootOrder",\r
865 &gEfiGlobalVariableGuid,\r
866 &BootOrderListSize\r
867 );\r
868 ASSERT (BootOrderList != NULL);\r
869 NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
870 ASSERT (NewBootOrderList != NULL);\r
871 CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
872 NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
873\r
874 if (BootOrderList != NULL) {\r
875 FreePool (BootOrderList);\r
876 }\r
877\r
878 Status = gRT->SetVariable (\r
5c08e117 879 L"BootOrder",\r
880 &gEfiGlobalVariableGuid,\r
69fc8f08
RN
881 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
882 BootOrderListSize + sizeof (UINT16),\r
883 NewBootOrderList\r
5c08e117 884 );\r
69fc8f08 885 if (!EFI_ERROR (Status)) {\r
5c08e117 886\r
69fc8f08
RN
887 FreePool (NewBootOrderList);\r
888 NewBootOrderList = NULL;\r
889 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
890 BootOptionMenu.MenuNumber++;\r
5c08e117 891\r
8acb3f7b
ED
892 //\r
893 // Update "change driver order" page used data, append the new add driver\r
894 // option at the end.\r
895 //\r
896 Index = 0;\r
897 while (CallbackData->BmmFakeNvData.BootOptionOrder[Index] != 0) {\r
898 Index++;\r
899 }\r
900 CallbackData->BmmFakeNvData.BootOptionOrder[Index] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
901\r
be9304f3
ED
902 NvRamMap->BootDescriptionData[0] = 0x0000;\r
903 NvRamMap->BootOptionalData[0] = 0x0000;\r
69fc8f08
RN
904 }\r
905 }\r
5c08e117 906 return EFI_SUCCESS;\r
907}\r
908\r
909/**\r
910 This function update the "BootNext" EFI Variable. If there is \r
ef841267 911 no "BootNext" specified in BMM, this EFI Variable is deleted.\r
5c08e117 912 It also update the BMM context data specified the "BootNext"\r
913 vaule.\r
914\r
915 @param CallbackData The BMM context data.\r
916\r
917 @retval EFI_SUCCESS The function complete successfully.\r
918 @return The EFI variable can be saved. See gRT->SetVariable \r
919 for detail return information.\r
920\r
921**/\r
922EFI_STATUS\r
923Var_UpdateBootNext (\r
924 IN BMM_CALLBACK_DATA *CallbackData\r
925 )\r
926{\r
927 BM_MENU_ENTRY *NewMenuEntry;\r
928 BM_LOAD_CONTEXT *NewLoadContext;\r
929 BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
930 UINT16 Index;\r
931 EFI_STATUS Status;\r
932\r
933 Status = EFI_SUCCESS;\r
934 CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
935 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
936 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
937 ASSERT (NULL != NewMenuEntry);\r
938\r
939 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
940 NewLoadContext->IsBootNext = FALSE;\r
941 }\r
942\r
943 if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
944 EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
945 return EFI_SUCCESS;\r
946 }\r
947\r
948 NewMenuEntry = BOpt_GetMenuEntry (\r
949 &BootOptionMenu,\r
950 CurrentFakeNVMap->BootNext\r
951 );\r
952 ASSERT (NewMenuEntry != NULL);\r
953\r
954 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
955 Status = gRT->SetVariable (\r
956 L"BootNext",\r
957 &gEfiGlobalVariableGuid,\r
16e5944a 958 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 959 sizeof (UINT16),\r
960 &NewMenuEntry->OptionNumber\r
961 );\r
962 NewLoadContext->IsBootNext = TRUE;\r
963 CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
964 return Status;\r
965}\r
966\r
967/**\r
968 This function update the "BootOrder" EFI Variable based on\r
969 BMM Formset's NV map. It then refresh BootOptionMenu\r
970 with the new "BootOrder" list.\r
971\r
972 @param CallbackData The BMM context data.\r
973\r
974 @retval EFI_SUCCESS The function complete successfully.\r
975 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
976 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
977\r
978**/\r
979EFI_STATUS\r
980Var_UpdateBootOrder (\r
981 IN BMM_CALLBACK_DATA *CallbackData\r
982 )\r
983{\r
984 EFI_STATUS Status;\r
985 UINT16 Index;\r
22d1f978 986 UINT16 OrderIndex;\r
5c08e117 987 UINT16 *BootOrderList;\r
5c08e117 988 UINTN BootOrderListSize;\r
22d1f978 989 UINT16 OptionNumber;\r
5c08e117 990\r
991 BootOrderList = NULL;\r
992 BootOrderListSize = 0;\r
993\r
994 //\r
995 // First check whether BootOrder is present in current configuration\r
996 //\r
997 BootOrderList = BdsLibGetVariableAndSize (\r
998 L"BootOrder",\r
999 &gEfiGlobalVariableGuid,\r
1000 &BootOrderListSize\r
1001 );\r
22d1f978 1002 if (BootOrderList == NULL) {\r
5c08e117 1003 return EFI_OUT_OF_RESOURCES;\r
1004 }\r
1005\r
be9304f3 1006 ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionOrder) / sizeof (CallbackData->BmmFakeNvData.BootOptionOrder[0])));\r
22d1f978 1007\r
be9304f3 1008 for (OrderIndex = 0; (OrderIndex < BootOptionMenu.MenuNumber) && (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] != 0); OrderIndex++) {\r
22d1f978 1009 for (Index = OrderIndex; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
be9304f3 1010 if ((BootOrderList[Index] == (UINT16) (CallbackData->BmmFakeNvData.BootOptionOrder[OrderIndex] - 1)) && (OrderIndex != Index)) {\r
22d1f978
RN
1011 OptionNumber = BootOrderList[Index];\r
1012 CopyMem (&BootOrderList[OrderIndex + 1], &BootOrderList[OrderIndex], (Index - OrderIndex) * sizeof (UINT16));\r
1013 BootOrderList[OrderIndex] = OptionNumber;\r
1014 }\r
1015 }\r
5c08e117 1016 }\r
1017\r
1018 Status = gRT->SetVariable (\r
1019 L"BootOrder",\r
1020 &gEfiGlobalVariableGuid,\r
16e5944a 1021 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 1022 BootOrderListSize,\r
22d1f978 1023 BootOrderList\r
5c08e117 1024 );\r
69fc8f08
RN
1025 //\r
1026 // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
1027 //\r
1028 ASSERT_EFI_ERROR (Status);\r
22d1f978 1029 FreePool (BootOrderList);\r
5c08e117 1030\r
16e5944a
RN
1031 GroupMultipleLegacyBootOption4SameType ();\r
1032\r
5c08e117 1033 BOpt_FreeMenu (&BootOptionMenu);\r
1034 BOpt_GetBootOptions (CallbackData);\r
1035\r
22d1f978 1036 return Status;\r
5c08e117 1037\r
1038}\r
1039\r
1040/**\r
1041 This function update the "DriverOrder" EFI Variable based on\r
1042 BMM Formset's NV map. It then refresh DriverOptionMenu\r
1043 with the new "DriverOrder" list.\r
1044\r
1045 @param CallbackData The BMM context data.\r
1046\r
1047 @retval EFI_SUCCESS The function complete successfully.\r
1048 @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
1049 @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
1050\r
1051**/\r
1052EFI_STATUS\r
1053Var_UpdateDriverOrder (\r
1054 IN BMM_CALLBACK_DATA *CallbackData\r
1055 )\r
1056{\r
1057 EFI_STATUS Status;\r
1058 UINT16 Index;\r
1059 UINT16 *DriverOrderList;\r
1060 UINT16 *NewDriverOrderList;\r
1061 UINTN DriverOrderListSize;\r
1062\r
1063 DriverOrderList = NULL;\r
1064 DriverOrderListSize = 0;\r
1065\r
1066 //\r
1067 // First check whether DriverOrder is present in current configuration\r
1068 //\r
1069 DriverOrderList = BdsLibGetVariableAndSize (\r
1070 L"DriverOrder",\r
1071 &gEfiGlobalVariableGuid,\r
1072 &DriverOrderListSize\r
1073 );\r
1074\r
1075 NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
1076\r
1077 if (NewDriverOrderList == NULL) {\r
1078 return EFI_OUT_OF_RESOURCES;\r
1079 }\r
1080 //\r
1081 // If exists, delete it to hold new DriverOrder\r
1082 //\r
1083 if (DriverOrderList != NULL) {\r
1084 EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
1085 FreePool (DriverOrderList);\r
1086 }\r
1087\r
be9304f3 1088 ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0])));\r
b452ca89 1089 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
be9304f3 1090 NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1);\r
5c08e117 1091 }\r
1092\r
1093 Status = gRT->SetVariable (\r
1094 L"DriverOrder",\r
1095 &gEfiGlobalVariableGuid,\r
16e5944a 1096 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 1097 DriverOrderListSize,\r
1098 NewDriverOrderList\r
1099 );\r
69fc8f08
RN
1100 //\r
1101 // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
1102 //\r
1103 ASSERT_EFI_ERROR (Status);\r
1104 \r
5c08e117 1105 BOpt_FreeMenu (&DriverOptionMenu);\r
1106 BOpt_GetDriverOptions (CallbackData);\r
1107 return EFI_SUCCESS;\r
1108}\r
1109\r
1110/**\r
e24fc103 1111 Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable\r
5c08e117 1112 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
1113 is also updated.\r
1114\r
1115 @param CallbackData The context data for BMM.\r
720624cc 1116 @param FormId The form id.\r
5c08e117 1117\r
1118 @return EFI_SUCCESS The function completed successfully.\r
e24fc103 1119 @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found.\r
5c08e117 1120 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource\r
1121**/\r
1122EFI_STATUS\r
1123Var_UpdateBBSOption (\r
be9304f3
ED
1124 IN BMM_CALLBACK_DATA *CallbackData,\r
1125 IN EFI_FORM_ID FormId\r
5c08e117 1126 )\r
1127{\r
1128 UINTN Index;\r
1129 UINTN Index2;\r
1130 VOID *BootOptionVar;\r
1131 CHAR16 VarName[100];\r
1132 UINTN OptionSize;\r
5c08e117 1133 EFI_STATUS Status;\r
5c08e117 1134 UINT32 *Attribute;\r
1135 BM_MENU_OPTION *OptionMenu;\r
5c08e117 1136 UINT8 *LegacyDev;\r
1137 UINT8 *VarData;\r
1138 UINTN VarSize;\r
e24fc103 1139 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
5c08e117 1140 UINT8 *OriginalPtr;\r
1141 UINT8 *DisMap;\r
1142 UINTN Pos;\r
1143 UINTN Bit;\r
1144 UINT16 *NewOrder;\r
1145 UINT16 Tmp;\r
22d1f978
RN
1146 UINT16 *EnBootOption;\r
1147 UINTN EnBootOptionCount;\r
1148 UINT16 *DisBootOption;\r
1149 UINTN DisBootOptionCount;\r
5c08e117 1150\r
5c08e117 1151 DisMap = NULL;\r
1152 NewOrder = NULL;\r
1153\r
be9304f3 1154 switch (FormId) {\r
22d1f978
RN
1155 case FORM_SET_FD_ORDER_ID:\r
1156 OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
1157 LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;\r
1158 CallbackData->BbsType = BBS_FLOPPY;\r
1159 break;\r
1160\r
1161 case FORM_SET_HD_ORDER_ID:\r
5c08e117 1162 OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
1163 LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;\r
1164 CallbackData->BbsType = BBS_HARDDISK;\r
22d1f978
RN
1165 break;\r
1166\r
1167 case FORM_SET_CD_ORDER_ID:\r
1168 OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
1169 LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;\r
1170 CallbackData->BbsType = BBS_CDROM;\r
1171 break;\r
1172\r
1173 case FORM_SET_NET_ORDER_ID:\r
1174 OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
1175 LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;\r
1176 CallbackData->BbsType = BBS_EMBED_NETWORK;\r
1177 break;\r
1178\r
1179 default:\r
1180 ASSERT (FORM_SET_BEV_ORDER_ID == CallbackData->BmmPreviousPageId);\r
1181 OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
1182 LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;\r
1183 CallbackData->BbsType = BBS_BEV_DEVICE;\r
1184 break;\r
5c08e117 1185 }\r
1186\r
1187 DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
1188 Status = EFI_SUCCESS;\r
1189\r
ce5fad41 1190\r
5c08e117 1191 //\r
1192 // Update the Variable "LegacyDevOrder"\r
1193 //\r
1194 VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
1195 VAR_LEGACY_DEV_ORDER,\r
e24fc103 1196 &gEfiLegacyDevOrderVariableGuid,\r
5c08e117 1197 &VarSize\r
1198 );\r
1199\r
1200 if (VarData == NULL) {\r
1201 return EFI_NOT_FOUND;\r
1202 }\r
1203\r
1204 OriginalPtr = VarData;\r
e24fc103 1205 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;\r
5c08e117 1206\r
22d1f978 1207 while (VarData < OriginalPtr + VarSize) {\r
5c08e117 1208 if (DevOrder->BbsType == CallbackData->BbsType) {\r
1209 break;\r
1210 }\r
1211\r
22d1f978 1212 VarData += sizeof (BBS_TYPE) + DevOrder->Length;\r
e24fc103 1213 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;\r
5c08e117 1214 }\r
1215\r
22d1f978 1216 if (VarData >= OriginalPtr + VarSize) {\r
5c08e117 1217 FreePool (OriginalPtr);\r
1218 return EFI_NOT_FOUND;\r
1219 }\r
1220\r
22d1f978 1221 NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length));\r
5c08e117 1222 if (NewOrder == NULL) {\r
22d1f978 1223 FreePool (OriginalPtr);\r
5c08e117 1224 return EFI_OUT_OF_RESOURCES;\r
1225 }\r
1226\r
1227 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1228 if (0xFF == LegacyDev[Index]) {\r
1229 break;\r
1230 }\r
1231\r
1232 NewOrder[Index] = LegacyDev[Index];\r
1233 }\r
1234 //\r
1235 // Only the enable/disable state of each boot device with same device type can be changed,\r
1236 // so we can count on the index information in DevOrder.\r
1237 // DisMap bit array is the only reliable source to check a device's en/dis state,\r
1238 // so we use DisMap to set en/dis state of each item in NewOrder array\r
1239 //\r
1240 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
22d1f978 1241 Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF);\r
5c08e117 1242 Pos = Tmp / 8;\r
1243 Bit = 7 - (Tmp % 8);\r
1244 if ((DisMap[Pos] & (1 << Bit)) != 0) {\r
1245 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
1246 Index++;\r
1247 }\r
1248 }\r
1249\r
1250 CopyMem (\r
22d1f978 1251 DevOrder->Data,\r
5c08e117 1252 NewOrder,\r
22d1f978 1253 DevOrder->Length - sizeof (DevOrder->Length)\r
5c08e117 1254 );\r
1255 FreePool (NewOrder);\r
1256\r
1257 Status = gRT->SetVariable (\r
1258 VAR_LEGACY_DEV_ORDER,\r
e24fc103 1259 &gEfiLegacyDevOrderVariableGuid,\r
be9198c9 1260 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
5c08e117 1261 VarSize,\r
1262 OriginalPtr\r
1263 );\r
1264\r
5c08e117 1265\r
1266 //\r
22d1f978 1267 // Update BootOrder and Boot####.Attribute\r
5c08e117 1268 //\r
22d1f978
RN
1269 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order\r
1270 //\r
1271 ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1);\r
16e5944a 1272\r
22d1f978 1273 OrderLegacyBootOption4SameType (\r
22d1f978
RN
1274 DevOrder->Data,\r
1275 DevOrder->Length / sizeof (UINT16) - 1,\r
16e5944a 1276 &EnBootOption,\r
22d1f978 1277 &EnBootOptionCount,\r
16e5944a 1278 &DisBootOption,\r
22d1f978
RN
1279 &DisBootOptionCount\r
1280 );\r
5c08e117 1281\r
22d1f978
RN
1282 //\r
1283 // 2. Deactivate the DisBootOption and activate the EnBootOption\r
1284 //\r
1285 for (Index = 0; Index < DisBootOptionCount; Index++) {\r
1286 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]);\r
1287 BootOptionVar = BdsLibGetVariableAndSize (\r
1288 VarName,\r
1289 &gEfiGlobalVariableGuid,\r
1290 &OptionSize\r
1291 );\r
1292 if (BootOptionVar != NULL) {\r
1293 Attribute = (UINT32 *) BootOptionVar;\r
5c08e117 1294 *Attribute &= ~LOAD_OPTION_ACTIVE;\r
5c08e117 1295\r
22d1f978
RN
1296 Status = gRT->SetVariable (\r
1297 VarName,\r
1298 &gEfiGlobalVariableGuid,\r
16e5944a 1299 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
22d1f978
RN
1300 OptionSize,\r
1301 BootOptionVar\r
1302 );\r
69fc8f08
RN
1303 //\r
1304 // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
1305 //\r
1306 ASSERT_EFI_ERROR (Status);\r
5c08e117 1307\r
22d1f978 1308 FreePool (BootOptionVar);\r
5c08e117 1309 }\r
22d1f978 1310 }\r
5c08e117 1311\r
22d1f978
RN
1312 for (Index = 0; Index < EnBootOptionCount; Index++) {\r
1313 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]);\r
1314 BootOptionVar = BdsLibGetVariableAndSize (\r
1315 VarName,\r
1316 &gEfiGlobalVariableGuid,\r
1317 &OptionSize\r
1318 );\r
1319 if (BootOptionVar != NULL) {\r
1320 Attribute = (UINT32 *) BootOptionVar;\r
1321 *Attribute |= LOAD_OPTION_ACTIVE;\r
5c08e117 1322\r
22d1f978
RN
1323 Status = gRT->SetVariable (\r
1324 VarName,\r
1325 &gEfiGlobalVariableGuid,\r
16e5944a 1326 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
22d1f978
RN
1327 OptionSize,\r
1328 BootOptionVar\r
1329 );\r
69fc8f08
RN
1330 //\r
1331 // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
1332 //\r
1333 ASSERT_EFI_ERROR (Status);\r
5c08e117 1334\r
22d1f978
RN
1335 FreePool (BootOptionVar);\r
1336 }\r
5c08e117 1337 }\r
1338\r
1339 BOpt_GetBootOptions (CallbackData);\r
22d1f978
RN
1340\r
1341 FreePool (OriginalPtr);\r
1342 FreePool (EnBootOption);\r
1343 FreePool (DisBootOption);\r
5c08e117 1344 return Status;\r
1345}\r
1346\r
1347/**\r
1348 Update the Text Mode of Console.\r
1349\r
1350 @param CallbackData The context data for BMM.\r
1351\r
1352 @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
1353 @return Other value if the Text Mode of Console is not updated.\r
1354\r
1355**/\r
1356EFI_STATUS\r
1357Var_UpdateConMode (\r
1358 IN BMM_CALLBACK_DATA *CallbackData\r
1359 )\r
1360{\r
1361 EFI_STATUS Status;\r
1362 UINTN Mode;\r
1363 CONSOLE_OUT_MODE ModeInfo;\r
1364\r
1365 Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
1366\r
1367 Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
6aa22a17 1368 if (!EFI_ERROR(Status)) {\r
32bc1227 1369 PcdSet32 (PcdSetupConOutColumn, (UINT32) ModeInfo.Column);\r
1370 PcdSet32 (PcdSetupConOutRow, (UINT32) ModeInfo.Row);\r
5c08e117 1371 }\r
1372\r
6aa22a17 1373 return EFI_SUCCESS;\r
5c08e117 1374}\r