]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c
IntelFrameworkModulePkg/LegacyBootMaintUiLib: Add NULL pointer check
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / LegacyBootMaintUiLib / LegacyBootMaintUi.c
... / ...
CommitLineData
1/** @file\r
2 Legacy Boot Maintainence UI implementation.\r
3\r
4Copyright (c) 2004 - 2016, 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\r
16#include "LegacyBootMaintUi.h"\r
17\r
18LEGACY_BOOT_OPTION_CALLBACK_DATA *mLegacyBootOptionPrivate = NULL;\r
19EFI_GUID mLegacyBootOptionGuid = LEGACY_BOOT_OPTION_FORMSET_GUID;\r
20CHAR16 mLegacyBootStorageName[] = L"LegacyBootData";\r
21BBS_TYPE mBbsType[] = {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_NETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN};\r
22BOOLEAN mFirstEnterLegacyForm = FALSE;\r
23\r
24\r
25///\r
26/// Legacy FD Info from LegacyBios.GetBbsInfo()\r
27///\r
28LEGACY_MENU_OPTION LegacyFDMenu = {\r
29 LEGACY_MENU_OPTION_SIGNATURE,\r
30 {NULL},\r
31 0\r
32};\r
33\r
34///\r
35/// Legacy HD Info from LegacyBios.GetBbsInfo()\r
36///\r
37LEGACY_MENU_OPTION LegacyHDMenu = {\r
38 LEGACY_MENU_OPTION_SIGNATURE,\r
39 {NULL},\r
40 0\r
41};\r
42\r
43///\r
44/// Legacy CD Info from LegacyBios.GetBbsInfo()\r
45///\r
46LEGACY_MENU_OPTION LegacyCDMenu = {\r
47 LEGACY_MENU_OPTION_SIGNATURE,\r
48 {NULL},\r
49 0\r
50};\r
51\r
52///\r
53/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
54///\r
55LEGACY_MENU_OPTION LegacyNETMenu = {\r
56 LEGACY_MENU_OPTION_SIGNATURE,\r
57 {NULL},\r
58 0\r
59};\r
60\r
61///\r
62/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
63///\r
64LEGACY_MENU_OPTION LegacyBEVMenu = {\r
65 LEGACY_MENU_OPTION_SIGNATURE,\r
66 {NULL},\r
67 0\r
68};\r
69\r
70\r
71VOID *mLegacyStartOpCodeHandle = NULL;\r
72VOID *mLegacyEndOpCodeHandle = NULL;\r
73EFI_IFR_GUID_LABEL *mLegacyStartLabel = NULL;\r
74EFI_IFR_GUID_LABEL *mLegacyEndLabel = NULL;\r
75\r
76\r
77HII_VENDOR_DEVICE_PATH mLegacyBootOptionHiiVendorDevicePath = {\r
78 {\r
79 {\r
80 HARDWARE_DEVICE_PATH,\r
81 HW_VENDOR_DP,\r
82 {\r
83 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
84 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
85 }\r
86 }, \r
87 { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } }\r
88 },\r
89 {\r
90 END_DEVICE_PATH_TYPE,\r
91 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
92 { \r
93 (UINT8) (END_DEVICE_PATH_LENGTH),\r
94 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
95 }\r
96 }\r
97};\r
98\r
99/**\r
100\r
101 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
102\r
103**/\r
104VOID\r
105GetLegacyOptions (\r
106 VOID\r
107 );\r
108\r
109\r
110/**\r
111\r
112 Base on the L"LegacyDevOrder" variable to build the current order data.\r
113\r
114**/\r
115VOID\r
116GetLegacyOptionsOrder (\r
117 VOID\r
118 );\r
119\r
120/**\r
121 Re-order the Boot Option according to the DevOrder.\r
122\r
123 The routine re-orders the Boot Option in BootOption array according to\r
124 the order specified by DevOrder.\r
125\r
126 @param DevOrder Pointer to buffer containing the BBS Index,\r
127 high 8-bit value 0xFF indicating a disabled boot option\r
128 @param DevOrderCount Count of the BBS Index\r
129 @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers\r
130 @param EnBootOptionCount Count of the enabled Boot Option Numbers\r
131 @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers\r
132 @param DisBootOptionCount Count of the disabled Boot Option Numbers\r
133\r
134 @return EFI_SUCCESS The function completed successfully.\r
135 @retval other Contain some error, details see the status return by gRT->SetVariable.\r
136**/\r
137EFI_STATUS\r
138OrderLegacyBootOption4SameType (\r
139 UINT16 *DevOrder,\r
140 UINTN DevOrderCount,\r
141 UINT16 **EnBootOption,\r
142 UINTN *EnBootOptionCount,\r
143 UINT16 **DisBootOption,\r
144 UINTN *DisBootOptionCount\r
145 )\r
146{\r
147 EFI_STATUS Status;\r
148 UINT16 *NewBootOption;\r
149 UINT16 *BootOrder;\r
150 UINTN BootOrderSize;\r
151 UINTN Index;\r
152 UINTN StartPosition;\r
153 \r
154 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
155 \r
156 CHAR16 OptionName[sizeof ("Boot####")];\r
157 UINT16 *BbsIndexArray;\r
158 UINT16 *DeviceTypeArray;\r
159\r
160 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);\r
161 ASSERT (BootOrder != NULL);\r
162\r
163 BbsIndexArray = AllocatePool (BootOrderSize);\r
164 DeviceTypeArray = AllocatePool (BootOrderSize);\r
165 *EnBootOption = AllocatePool (BootOrderSize);\r
166 *DisBootOption = AllocatePool (BootOrderSize);\r
167 *DisBootOptionCount = 0;\r
168 *EnBootOptionCount = 0;\r
169 Index = 0;\r
170 Status = EFI_SUCCESS;\r
171\r
172 ASSERT (BbsIndexArray != NULL);\r
173 ASSERT (DeviceTypeArray != NULL);\r
174 ASSERT (*EnBootOption != NULL);\r
175 ASSERT (*DisBootOption != NULL);\r
176\r
177 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
178 \r
179 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);\r
180 Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);\r
181 ASSERT_EFI_ERROR (Status);\r
182 \r
183 if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) &&\r
184 (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) {\r
185 //\r
186 // Legacy Boot Option\r
187 //\r
188 ASSERT (BootOption.OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));\r
189\r
190 DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType;\r
191 BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption.OptionalData)->BbsIndex;\r
192 } else {\r
193 DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN;\r
194 BbsIndexArray [Index] = 0xFFFF;\r
195 }\r
196 EfiBootManagerFreeLoadOption (&BootOption);\r
197 }\r
198\r
199 //\r
200 // Record the corresponding Boot Option Numbers according to the DevOrder\r
201 // Record the EnBootOption and DisBootOption according to the DevOrder\r
202 //\r
203 StartPosition = BootOrderSize / sizeof (UINT16);\r
204 NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16));\r
205 ASSERT (NewBootOption != NULL);\r
206 while (DevOrderCount-- != 0) {\r
207 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
208 if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) {\r
209 StartPosition = MIN (StartPosition, Index);\r
210 NewBootOption[DevOrderCount] = BootOrder[Index];\r
211 \r
212 if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {\r
213 (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index];\r
214 (*DisBootOptionCount)++;\r
215 } else {\r
216 (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index];\r
217 (*EnBootOptionCount)++;\r
218 }\r
219 break;\r
220 }\r
221 }\r
222 }\r
223\r
224 //\r
225 // Overwrite the old BootOption\r
226 //\r
227 CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));\r
228 Status = gRT->SetVariable (\r
229 L"BootOrder",\r
230 &gEfiGlobalVariableGuid,\r
231 VAR_FLAG,\r
232 BootOrderSize,\r
233 BootOrder\r
234 );\r
235\r
236 FreePool (NewBootOption);\r
237 FreePool (DeviceTypeArray);\r
238 FreePool (BbsIndexArray);\r
239\r
240 return Status;\r
241}\r
242\r
243/**\r
244 Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable\r
245 is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
246 is also updated.\r
247\r
248 @param NVMapData The data for egacy BBS boot.\r
249\r
250 @return EFI_SUCCESS The function completed successfully.\r
251 @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can not be found.\r
252 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource\r
253 @retval other Contain some error, details see the status return by gRT->SetVariable.\r
254**/\r
255EFI_STATUS\r
256UpdateBBSOption (\r
257 IN LEGACY_BOOT_NV_DATA *NVMapData\r
258 )\r
259{\r
260 UINTN Index;\r
261 UINTN Index2;\r
262 UINTN CurrentType;\r
263 VOID *BootOptionVar;\r
264 CHAR16 VarName[100];\r
265 UINTN OptionSize;\r
266 EFI_STATUS Status;\r
267 UINT32 *Attribute;\r
268 LEGACY_MENU_OPTION *OptionMenu;\r
269 UINT16 *LegacyDev;\r
270 UINT16 *InitialLegacyDev;\r
271 UINT8 *VarData;\r
272 UINTN VarSize;\r
273 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
274 UINT8 *OriginalPtr;\r
275 UINT8 *DisMap;\r
276 UINTN Pos;\r
277 UINTN Bit;\r
278 UINT16 *NewOrder;\r
279 UINT16 Tmp;\r
280 UINT16 *EnBootOption;\r
281 UINTN EnBootOptionCount;\r
282 UINT16 *DisBootOption;\r
283 UINTN DisBootOptionCount;\r
284 UINTN BufferSize;\r
285 \r
286\r
287 DisMap = NULL;\r
288 NewOrder = NULL;\r
289 CurrentType = 0;\r
290 EnBootOption = NULL;\r
291 DisBootOption = NULL;\r
292\r
293 \r
294 DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap;\r
295 Status = EFI_SUCCESS;\r
296\r
297 //\r
298 // Update the Variable "LegacyDevOrder"\r
299 //\r
300 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize);\r
301 if (VarData == NULL) {\r
302 return EFI_NOT_FOUND;\r
303 }\r
304 OriginalPtr = VarData;\r
305\r
306 while (mBbsType[CurrentType] != BBS_UNKNOWN) {\r
307 switch (mBbsType[CurrentType]) {\r
308 case BBS_FLOPPY:\r
309 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu;\r
310 LegacyDev = NVMapData->LegacyFD;\r
311 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD;\r
312 BufferSize = sizeof (NVMapData->LegacyFD);\r
313 break;\r
314\r
315 case BBS_HARDDISK:\r
316 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu;\r
317 LegacyDev = NVMapData->LegacyHD;\r
318 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD;\r
319\r
320 BufferSize = sizeof (NVMapData->LegacyHD);\r
321 break;\r
322\r
323 case BBS_CDROM:\r
324 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu;\r
325 LegacyDev = NVMapData->LegacyCD;\r
326 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD;\r
327 BufferSize = sizeof (NVMapData->LegacyCD);\r
328 break;\r
329\r
330 case BBS_EMBED_NETWORK:\r
331 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu;\r
332 LegacyDev = NVMapData->LegacyNET;\r
333 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET;\r
334 BufferSize = sizeof (NVMapData->LegacyNET);\r
335 break;\r
336\r
337 default:\r
338 ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE);\r
339 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu;\r
340 LegacyDev = NVMapData->LegacyBEV;\r
341 InitialLegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV;\r
342 BufferSize = sizeof (NVMapData->LegacyBEV);\r
343 break;\r
344 }\r
345\r
346 //\r
347 // Check whether has value changed.\r
348 //\r
349 if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) {\r
350 CurrentType++;\r
351 continue;\r
352 }\r
353\r
354 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr;\r
355 while (VarData < OriginalPtr + VarSize) {\r
356 if (DevOrder->BbsType == mBbsType[CurrentType]) {\r
357 break;\r
358 }\r
359\r
360 VarData += sizeof (BBS_TYPE) + DevOrder->Length;\r
361 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;\r
362 }\r
363\r
364 if (VarData >= OriginalPtr + VarSize) {\r
365 FreePool (OriginalPtr);\r
366 return EFI_NOT_FOUND;\r
367 }\r
368\r
369 NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length));\r
370 if (NewOrder == NULL) {\r
371 FreePool (OriginalPtr);\r
372 return EFI_OUT_OF_RESOURCES;\r
373 }\r
374\r
375 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
376 if (0xFF == LegacyDev[Index]) {\r
377 break;\r
378 }\r
379\r
380 NewOrder[Index] = LegacyDev[Index];\r
381 }\r
382\r
383 //\r
384 // Only the enable/disable state of each boot device with same device type can be changed,\r
385 // so we can count on the index information in DevOrder.\r
386 // DisMap bit array is the only reliable source to check a device's en/dis state,\r
387 // so we use DisMap to set en/dis state of each item in NewOrder array\r
388 //\r
389 for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
390 Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF);\r
391 Pos = Tmp / 8;\r
392 Bit = 7 - (Tmp % 8);\r
393 if ((DisMap[Pos] & (1 << Bit)) != 0) {\r
394 NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
395 Index++;\r
396 }\r
397 }\r
398\r
399 CopyMem (\r
400 DevOrder->Data,\r
401 NewOrder,\r
402 DevOrder->Length - sizeof (DevOrder->Length)\r
403 );\r
404 FreePool (NewOrder);\r
405\r
406 //\r
407 // Update BootOrder and Boot####.Attribute\r
408 //\r
409 // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order\r
410 //\r
411 ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1);\r
412\r
413 Status = OrderLegacyBootOption4SameType (\r
414 DevOrder->Data,\r
415 DevOrder->Length / sizeof (UINT16) - 1,\r
416 &EnBootOption,\r
417 &EnBootOptionCount,\r
418 &DisBootOption,\r
419 &DisBootOptionCount\r
420 );\r
421 if (EFI_ERROR(Status)) {\r
422 goto Fail;\r
423 }\r
424\r
425 //\r
426 // 2. Deactivate the DisBootOption and activate the EnBootOption\r
427 //\r
428 for (Index = 0; Index < DisBootOptionCount; Index++) {\r
429 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]);\r
430 GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize);\r
431 if (BootOptionVar != NULL) {\r
432 Attribute = (UINT32 *) BootOptionVar;\r
433 *Attribute &= ~LOAD_OPTION_ACTIVE;\r
434\r
435 Status = gRT->SetVariable (\r
436 VarName,\r
437 &gEfiGlobalVariableGuid,\r
438 VAR_FLAG,\r
439 OptionSize,\r
440 BootOptionVar\r
441 );\r
442\r
443 FreePool (BootOptionVar);\r
444 }\r
445 }\r
446\r
447 for (Index = 0; Index < EnBootOptionCount; Index++) {\r
448 UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]);\r
449 GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize);\r
450 if (BootOptionVar != NULL) {\r
451 Attribute = (UINT32 *) BootOptionVar;\r
452 *Attribute |= LOAD_OPTION_ACTIVE;\r
453\r
454 Status = gRT->SetVariable (\r
455 VarName,\r
456 &gEfiGlobalVariableGuid,\r
457 VAR_FLAG,\r
458 OptionSize,\r
459 BootOptionVar\r
460 );\r
461\r
462 FreePool (BootOptionVar);\r
463 }\r
464 }\r
465\r
466\r
467 FreePool (EnBootOption);\r
468 FreePool (DisBootOption);\r
469\r
470 CurrentType++;\r
471 }\r
472 \r
473 Status = gRT->SetVariable (\r
474 VAR_LEGACY_DEV_ORDER,\r
475 &gEfiLegacyDevOrderVariableGuid,\r
476 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
477 VarSize,\r
478 OriginalPtr\r
479 );\r
480\r
481Fail:\r
482 if (EnBootOption != NULL) {\r
483 FreePool (EnBootOption);\r
484 }\r
485\r
486 if (DisBootOption != NULL) {\r
487 FreePool (DisBootOption);\r
488 }\r
489\r
490 FreePool (OriginalPtr);\r
491 return Status;\r
492}\r
493\r
494/**\r
495 This function allows a caller to extract the current configuration for one\r
496 or more named elements from the target driver.\r
497\r
498\r
499 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
500 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
501 @param Progress On return, points to a character in the Request string.\r
502 Points to the string's null terminator if request was successful.\r
503 Points to the most recent '&' before the first failing name/value\r
504 pair (or the beginning of the string if the failure is in the\r
505 first name/value pair) if the request was not successful.\r
506 @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
507 has all values filled in for the names in the Request string.\r
508 String to be allocated by the called function.\r
509\r
510 @retval EFI_SUCCESS The Results is filled with the requested values.\r
511 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
512 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
513 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
514\r
515**/\r
516EFI_STATUS\r
517EFIAPI\r
518LegacyBootOptionExtractConfig (\r
519 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
520 IN CONST EFI_STRING Request,\r
521 OUT EFI_STRING *Progress,\r
522 OUT EFI_STRING *Results\r
523 )\r
524{\r
525 if (Progress == NULL || Results == NULL) {\r
526 return EFI_INVALID_PARAMETER;\r
527 }\r
528 *Progress = Request;\r
529 return EFI_NOT_FOUND;\r
530}\r
531\r
532/**\r
533 This function processes the results of changes in configuration.\r
534\r
535\r
536 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
537 @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
538 @param Progress A pointer to a string filled in with the offset of the most\r
539 recent '&' before the first failing name/value pair (or the\r
540 beginning of the string if the failure is in the first\r
541 name/value pair) or the terminating NULL if all was successful.\r
542\r
543 @retval EFI_SUCCESS The Results is processed successfully.\r
544 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
545 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
546\r
547**/\r
548EFI_STATUS\r
549EFIAPI\r
550LegacyBootOptionRouteConfig (\r
551 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
552 IN CONST EFI_STRING Configuration,\r
553 OUT EFI_STRING *Progress\r
554 )\r
555{\r
556 EFI_STATUS Status;\r
557 EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;\r
558 LEGACY_BOOT_NV_DATA *CurrentNVMapData;\r
559 UINTN BufferSize;\r
560\r
561\r
562 if (Configuration == NULL || Progress == NULL) {\r
563 return EFI_INVALID_PARAMETER;\r
564 }\r
565\r
566 //\r
567 // Check routing data in <ConfigHdr>.\r
568 // Note: there is no name for Name/Value storage, only GUID will be checked\r
569 //\r
570 if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacyBootStorageName)) {\r
571 return EFI_NOT_FOUND;\r
572 }\r
573\r
574 Status = gBS->LocateProtocol (\r
575 &gEfiHiiConfigRoutingProtocolGuid, \r
576 NULL, \r
577 (VOID **) &ConfigRouting\r
578 );\r
579 if (EFI_ERROR (Status)) {\r
580 return Status;\r
581 }\r
582\r
583 //\r
584 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
585 //\r
586 CurrentNVMapData = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData;\r
587 Status = ConfigRouting->ConfigToBlock (\r
588 ConfigRouting,\r
589 Configuration,\r
590 (UINT8 *) CurrentNVMapData,\r
591 &BufferSize,\r
592 Progress\r
593 );\r
594 ASSERT_EFI_ERROR (Status); \r
595\r
596 Status = UpdateBBSOption (CurrentNVMapData);\r
597\r
598 return Status;\r
599}\r
600\r
601/**\r
602 Refresh the global UpdateData structure.\r
603\r
604**/\r
605VOID\r
606RefreshLegacyUpdateData (\r
607 VOID\r
608 )\r
609{\r
610 //\r
611 // Free current updated date\r
612 //\r
613 if (mLegacyStartOpCodeHandle != NULL) {\r
614 HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle);\r
615 }\r
616 if (mLegacyEndOpCodeHandle != NULL) {\r
617 HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle);\r
618 }\r
619\r
620 //\r
621 // Create new OpCode Handle\r
622 //\r
623 mLegacyStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
624 mLegacyEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
625\r
626 //\r
627 // Create Hii Extend Label OpCode as the start opcode\r
628 //\r
629 mLegacyStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
630 mLegacyStartOpCodeHandle,\r
631 &gEfiIfrTianoGuid,\r
632 NULL,\r
633 sizeof (EFI_IFR_GUID_LABEL)\r
634 );\r
635 mLegacyStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
636\r
637 mLegacyStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID;\r
638\r
639 //\r
640 // Create Hii Extend Label OpCode as the start opcode\r
641 //\r
642 mLegacyEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
643 mLegacyEndOpCodeHandle,\r
644 &gEfiIfrTianoGuid,\r
645 NULL,\r
646 sizeof (EFI_IFR_GUID_LABEL)\r
647 );\r
648 mLegacyEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
649\r
650 mLegacyEndLabel->Number = FORM_BOOT_LEGACY_LABEL_END;\r
651\r
652}\r
653\r
654/**\r
655 Get the Menu Entry from the list in Menu Entry List.\r
656\r
657 If MenuNumber is great or equal to the number of Menu\r
658 Entry in the list, then ASSERT.\r
659\r
660 @param MenuOption The Menu Entry List to read the menu entry.\r
661 @param MenuNumber The index of Menu Entry.\r
662\r
663 @return The Menu Entry.\r
664\r
665**/\r
666LEGACY_MENU_ENTRY *\r
667GetMenuEntry (\r
668 LEGACY_MENU_OPTION *MenuOption,\r
669 UINTN MenuNumber\r
670 )\r
671{\r
672 LEGACY_MENU_ENTRY *NewMenuEntry;\r
673 UINTN Index;\r
674 LIST_ENTRY *List;\r
675\r
676 ASSERT (MenuNumber < MenuOption->MenuNumber);\r
677\r
678 List = MenuOption->Head.ForwardLink;\r
679 for (Index = 0; Index < MenuNumber; Index++) {\r
680 List = List->ForwardLink;\r
681 }\r
682\r
683 NewMenuEntry = CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SIGNATURE);\r
684\r
685 return NewMenuEntry;\r
686}\r
687\r
688/**\r
689 Create string tokens for a menu from its help strings and display strings\r
690 \r
691 @param HiiHandle Hii Handle of the package to be updated.\r
692 @param MenuOption The Menu whose string tokens need to be created\r
693\r
694**/\r
695VOID\r
696CreateLegacyMenuStringToken (\r
697 IN EFI_HII_HANDLE HiiHandle,\r
698 IN LEGACY_MENU_OPTION *MenuOption\r
699 )\r
700{\r
701 LEGACY_MENU_ENTRY *NewMenuEntry;\r
702 UINTN Index;\r
703\r
704 for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
705 NewMenuEntry = GetMenuEntry (MenuOption, Index);\r
706\r
707 NewMenuEntry->DisplayStringToken = HiiSetString (\r
708 HiiHandle,\r
709 0,\r
710 NewMenuEntry->DisplayString,\r
711 NULL\r
712 );\r
713\r
714 if (NULL == NewMenuEntry->HelpString) {\r
715 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
716 } else {\r
717 NewMenuEntry->HelpStringToken = HiiSetString (\r
718 HiiHandle,\r
719 0,\r
720 NewMenuEntry->HelpString,\r
721 NULL\r
722 );\r
723 }\r
724 }\r
725}\r
726\r
727/**\r
728 Create a dynamic page so that Legacy Device boot order\r
729 can be set for specified device type.\r
730\r
731 @param UpdatePageId The form ID. It also spefies the legacy device type.\r
732\r
733\r
734**/\r
735VOID\r
736UpdateLegacyDeviceOrderPage (\r
737 IN UINT16 UpdatePageId\r
738 )\r
739{\r
740 LEGACY_MENU_OPTION *OptionMenu;\r
741 LEGACY_MENU_ENTRY *NewMenuEntry;\r
742 EFI_STRING_ID StrRef;\r
743 EFI_STRING_ID StrRefHelp;\r
744 UINT16 *Default;\r
745 UINT16 Index;\r
746 UINT16 Key;\r
747 CHAR16 String[100];\r
748 CHAR16 *TypeStr;\r
749 CHAR16 *TypeStrHelp;\r
750 CHAR16 *FormTitle;\r
751 VOID *OptionsOpCodeHandle;\r
752 VOID *DefaultOpCodeHandle;\r
753\r
754 Key = 0;\r
755 StrRef = 0;\r
756 StrRefHelp = 0;\r
757 OptionMenu = NULL;\r
758 TypeStr = NULL;\r
759 TypeStrHelp = NULL;\r
760 Default = NULL;\r
761\r
762 RefreshLegacyUpdateData();\r
763\r
764 //\r
765 // Create oneof option list\r
766 //\r
767 switch (UpdatePageId) {\r
768 case FORM_FLOPPY_BOOT_ID:\r
769 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu;\r
770 Key = (UINT16) LEGACY_FD_QUESTION_ID;\r
771 TypeStr = STR_FLOPPY;\r
772 TypeStrHelp = STR_FLOPPY_HELP;\r
773 FormTitle = STR_FLOPPY_TITLE;\r
774 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD;\r
775 break;\r
776\r
777 case FORM_HARDDISK_BOOT_ID:\r
778 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu;\r
779 Key = (UINT16) LEGACY_HD_QUESTION_ID;\r
780 TypeStr = STR_HARDDISK;\r
781 TypeStrHelp = STR_HARDDISK_HELP;\r
782 FormTitle = STR_HARDDISK_TITLE;\r
783 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD;\r
784 break;\r
785\r
786 case FORM_CDROM_BOOT_ID:\r
787 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu;\r
788 Key = (UINT16) LEGACY_CD_QUESTION_ID;\r
789 TypeStr = STR_CDROM;\r
790 TypeStrHelp = STR_CDROM_HELP;\r
791 FormTitle = STR_CDROM_TITLE;\r
792 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD;\r
793 break;\r
794\r
795 case FORM_NET_BOOT_ID:\r
796 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu;\r
797 Key = (UINT16) LEGACY_NET_QUESTION_ID;\r
798 TypeStr = STR_NET;\r
799 TypeStrHelp = STR_NET_HELP;\r
800 FormTitle = STR_NET_TITLE;\r
801 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET;\r
802 break;\r
803\r
804 case FORM_BEV_BOOT_ID:\r
805 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu;\r
806 Key = (UINT16) LEGACY_BEV_QUESTION_ID;\r
807 TypeStr = STR_BEV;\r
808 TypeStrHelp = STR_BEV_HELP;\r
809 FormTitle = STR_BEV_TITLE;\r
810 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV;\r
811 break;\r
812\r
813 default:\r
814 DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));\r
815 return;\r
816 }\r
817 \r
818 HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL);\r
819\r
820 CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu);\r
821\r
822 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();\r
823 ASSERT (OptionsOpCodeHandle != NULL);\r
824\r
825\r
826 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
827 NewMenuEntry = GetMenuEntry (OptionMenu, Index);\r
828 //\r
829 // Create OneOf for each legacy device\r
830 //\r
831 HiiCreateOneOfOptionOpCode (\r
832 OptionsOpCodeHandle,\r
833 NewMenuEntry->DisplayStringToken,\r
834 0,\r
835 EFI_IFR_TYPE_NUM_SIZE_16,\r
836 ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex\r
837 );\r
838 }\r
839\r
840 //\r
841 // Create OneOf for item "Disabled"\r
842 //\r
843 HiiCreateOneOfOptionOpCode (\r
844 OptionsOpCodeHandle,\r
845 STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE),\r
846 0,\r
847 EFI_IFR_TYPE_NUM_SIZE_16,\r
848 0xFF\r
849 );\r
850\r
851 //\r
852 // Create oneof tag here for FD/HD/CD #1 #2\r
853 //\r
854 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
855 DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();\r
856 ASSERT (DefaultOpCodeHandle != NULL);\r
857\r
858 HiiCreateDefaultOpCode (\r
859 DefaultOpCodeHandle, \r
860 EFI_HII_DEFAULT_CLASS_STANDARD, \r
861 EFI_IFR_TYPE_NUM_SIZE_16, \r
862 *Default++\r
863 );\r
864 \r
865 //\r
866 // Create the string for oneof tag\r
867 //\r
868 UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
869 StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);\r
870\r
871 UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
872 StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);\r
873\r
874 HiiCreateOneOfOpCode (\r
875 mLegacyStartOpCodeHandle,\r
876 (EFI_QUESTION_ID) (Key + Index),\r
877 VARSTORE_ID_LEGACY_BOOT,\r
878 (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET),\r
879 StrRef,\r
880 StrRefHelp,\r
881 EFI_IFR_FLAG_CALLBACK,\r
882 EFI_IFR_NUMERIC_SIZE_2,\r
883 OptionsOpCodeHandle,\r
884 DefaultOpCodeHandle //NULL //\r
885 );\r
886 \r
887 HiiFreeOpCodeHandle (DefaultOpCodeHandle);\r
888 }\r
889\r
890 HiiUpdateForm (\r
891 mLegacyBootOptionPrivate->HiiHandle,\r
892 &mLegacyBootOptionGuid,\r
893 LEGACY_ORDER_CHANGE_FORM_ID,\r
894 mLegacyStartOpCodeHandle, \r
895 mLegacyEndOpCodeHandle \r
896 );\r
897\r
898 HiiFreeOpCodeHandle (OptionsOpCodeHandle);\r
899}\r
900\r
901\r
902/**\r
903 Adjust question value when one question value has been changed.\r
904\r
905 @param QuestionId The question id for the value changed question.\r
906 @param Value The value for the changed question.\r
907\r
908**/\r
909VOID\r
910AdjustOptionValue (\r
911 IN UINT16 QuestionId,\r
912 IN EFI_IFR_TYPE_VALUE *Value\r
913 )\r
914{\r
915 UINTN Number;\r
916 UINT16 *Default;\r
917 LEGACY_BOOT_NV_DATA *CurrentNVMap;\r
918 UINT16 *CurrentVal;\r
919 UINTN Index;\r
920 UINTN Index2;\r
921 UINTN Index3;\r
922 UINTN NewValuePos;\r
923 UINTN OldValue;\r
924 UINTN NewValue;\r
925 UINT8 *DisMap;\r
926 UINTN Pos;\r
927 UINTN Bit;\r
928\r
929 Number = 0;\r
930 CurrentVal = 0;\r
931 Default = NULL;\r
932 NewValue = 0;\r
933 NewValuePos = 0;\r
934 OldValue = 0;\r
935\r
936 //\r
937 // Update Select FD/HD/CD/NET/BEV Order Form\r
938 //\r
939 ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER));\r
940\r
941 CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData;\r
942 HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap);\r
943 DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap;\r
944\r
945 if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) {\r
946 Number = (UINT16) LegacyFDMenu.MenuNumber;\r
947 CurrentVal = CurrentNVMap->LegacyFD;\r
948 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD;\r
949 } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) {\r
950 Number = (UINT16) LegacyHDMenu.MenuNumber;\r
951 CurrentVal = CurrentNVMap->LegacyHD;\r
952 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD;\r
953 } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) {\r
954 Number = (UINT16) LegacyCDMenu.MenuNumber;\r
955 CurrentVal = CurrentNVMap->LegacyCD;\r
956 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD;\r
957 } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) {\r
958 Number = (UINT16) LegacyNETMenu.MenuNumber;\r
959 CurrentVal = CurrentNVMap->LegacyNET;\r
960 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET;\r
961 } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) {\r
962 Number = (UINT16) LegacyBEVMenu.MenuNumber;\r
963 CurrentVal = CurrentNVMap->LegacyBEV;\r
964 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV;\r
965 }\r
966 \r
967 //\r
968 // First, find the different position\r
969 // if there is change, it should be only one\r
970 //\r
971 for (Index = 0; Index < Number; Index++) {\r
972 if (CurrentVal[Index] != Default[Index]) {\r
973 OldValue = Default[Index];\r
974 NewValue = CurrentVal[Index];\r
975 break;\r
976 }\r
977 }\r
978\r
979 if (Index != Number) {\r
980 //\r
981 // there is change, now process\r
982 //\r
983 if (0xFF == NewValue) {\r
984 //\r
985 // This item will be disable\r
986 // Just move the items behind this forward to overlap it\r
987 //\r
988 Pos = OldValue / 8;\r
989 Bit = 7 - (OldValue % 8);\r
990 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
991 for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
992 CurrentVal[Index2] = CurrentVal[Index2 + 1];\r
993 }\r
994\r
995 CurrentVal[Index2] = 0xFF;\r
996 } else {\r
997 for (Index2 = 0; Index2 < Number; Index2++) {\r
998 if (Index2 == Index) {\r
999 continue;\r
1000 }\r
1001\r
1002 if (Default[Index2] == NewValue) {\r
1003 //\r
1004 // If NewValue is in OldLegacyDev array\r
1005 // remember its old position\r
1006 //\r
1007 NewValuePos = Index2;\r
1008 break;\r
1009 }\r
1010 }\r
1011\r
1012 if (Index2 != Number) {\r
1013 //\r
1014 // We will change current item to an existing item\r
1015 // (It's hard to describe here, please read code, it's like a cycle-moving)\r
1016 //\r
1017 for (Index2 = NewValuePos; Index2 != Index;) {\r
1018 if (NewValuePos < Index) {\r
1019 CurrentVal[Index2] = Default[Index2 + 1];\r
1020 Index2++;\r
1021 } else {\r
1022 CurrentVal[Index2] = Default[Index2 - 1];\r
1023 Index2--;\r
1024 }\r
1025 }\r
1026 } else {\r
1027 //\r
1028 // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
1029 // so we should modify DisMap to reflect the change\r
1030 //\r
1031 Pos = NewValue / 8;\r
1032 Bit = 7 - (NewValue % 8);\r
1033 DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));\r
1034 if (0xFF != OldValue) {\r
1035 //\r
1036 // Because NewValue is a item that was disabled before\r
1037 // so after changing the OldValue should be disabled\r
1038 // actually we are doing a swap of enable-disable states of two items\r
1039 //\r
1040 Pos = OldValue / 8;\r
1041 Bit = 7 - (OldValue % 8);\r
1042 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
1043 }\r
1044 }\r
1045 }\r
1046 //\r
1047 // To prevent DISABLE appears in the middle of the list\r
1048 // we should perform a re-ordering\r
1049 //\r
1050 Index3 = Index;\r
1051 Index = 0;\r
1052 while (Index < Number) {\r
1053 if (0xFF != CurrentVal[Index]) {\r
1054 Index++;\r
1055 continue;\r
1056 }\r
1057\r
1058 Index2 = Index;\r
1059 Index2++;\r
1060 while (Index2 < Number) {\r
1061 if (0xFF != CurrentVal[Index2]) {\r
1062 break;\r
1063 }\r
1064\r
1065 Index2++;\r
1066 }\r
1067\r
1068 if (Index2 < Number) {\r
1069 CurrentVal[Index] = CurrentVal[Index2];\r
1070 CurrentVal[Index2] = 0xFF;\r
1071 }\r
1072\r
1073 Index++;\r
1074 }\r
1075\r
1076 //\r
1077 // Return correct question value.\r
1078 //\r
1079 Value->u16 = CurrentVal[Index3];\r
1080 CopyMem (Default, CurrentVal, sizeof (UINT16) * Number);\r
1081 }\r
1082\r
1083 //\r
1084 // Pass changed uncommitted data back to Form Browser\r
1085 //\r
1086 HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL);\r
1087}\r
1088\r
1089/**\r
1090 This call back function is registered with Boot Manager formset.\r
1091 When user selects a boot option, this call back function will\r
1092 be triggered. The boot option is saved for later processing.\r
1093\r
1094\r
1095 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1096 @param Action Specifies the type of action taken by the browser.\r
1097 @param QuestionId A unique value which is sent to the original exporting driver\r
1098 so that it can identify the type of data to expect.\r
1099 @param Type The type of value for the question.\r
1100 @param Value A pointer to the data being sent to the original exporting driver.\r
1101 @param ActionRequest On return, points to the action requested by the callback function.\r
1102\r
1103 @retval EFI_SUCCESS The callback successfully handled the action.\r
1104 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
1105\r
1106**/\r
1107EFI_STATUS\r
1108EFIAPI\r
1109LegacyBootOptionCallback (\r
1110 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1111 IN EFI_BROWSER_ACTION Action,\r
1112 IN EFI_QUESTION_ID QuestionId,\r
1113 IN UINT8 Type,\r
1114 IN EFI_IFR_TYPE_VALUE *Value,\r
1115 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1116 )\r
1117{\r
1118 if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_FORM_OPEN) {\r
1119 //\r
1120 // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open.\r
1121 //\r
1122 return EFI_UNSUPPORTED;\r
1123 }\r
1124\r
1125 if ((Value == NULL) || (ActionRequest == NULL)) {\r
1126 return EFI_INVALID_PARAMETER;\r
1127 }\r
1128\r
1129 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
1130 if (QuestionId == FORM_FLOPPY_BOOT_ID) {\r
1131 if (!mFirstEnterLegacyForm) {\r
1132 //\r
1133 // The leagcyBootMaintUiLib depends on the LegacyBootManagerLib to realize its functionality.\r
1134 // We need to do the leagcy boot options related actions after the LegacyBootManagerLib has been initialized.\r
1135 // Opening the legacy menus is the appropriate time that the LegacyBootManagerLib has already been initialized.\r
1136 //\r
1137 mFirstEnterLegacyForm = TRUE;\r
1138 GetLegacyOptions ();\r
1139 GetLegacyOptionsOrder ();\r
1140 }\r
1141 }\r
1142 }\r
1143\r
1144 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
1145 switch (QuestionId) {\r
1146 case FORM_FLOPPY_BOOT_ID:\r
1147 case FORM_HARDDISK_BOOT_ID:\r
1148 case FORM_CDROM_BOOT_ID:\r
1149 case FORM_NET_BOOT_ID:\r
1150 case FORM_BEV_BOOT_ID:\r
1151 UpdateLegacyDeviceOrderPage (QuestionId);\r
1152 break;\r
1153\r
1154 default:\r
1155 break;\r
1156 }\r
1157 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1158 if ((Value == NULL) || (ActionRequest == NULL)) {\r
1159 return EFI_INVALID_PARAMETER;\r
1160 }\r
1161\r
1162 if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) {\r
1163 AdjustOptionValue(QuestionId, Value);\r
1164 }\r
1165 }\r
1166 return EFI_SUCCESS;\r
1167}\r
1168\r
1169\r
1170/**\r
1171 Create a menu entry by given menu type.\r
1172\r
1173 @param MenuType The Menu type to be created.\r
1174\r
1175 @retval NULL If failed to create the menu.\r
1176 @return the new menu entry.\r
1177\r
1178**/\r
1179LEGACY_MENU_ENTRY *\r
1180CreateMenuEntry (\r
1181 VOID\r
1182 )\r
1183{\r
1184 LEGACY_MENU_ENTRY *MenuEntry;\r
1185\r
1186 //\r
1187 // Create new menu entry\r
1188 //\r
1189 MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY));\r
1190 if (MenuEntry == NULL) {\r
1191 return NULL;\r
1192 }\r
1193\r
1194 MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT));\r
1195 if (MenuEntry->VariableContext == NULL) {\r
1196 FreePool (MenuEntry);\r
1197 return NULL;\r
1198 }\r
1199\r
1200 MenuEntry->Signature = LEGACY_MENU_ENTRY_SIGNATURE;\r
1201 return MenuEntry;\r
1202}\r
1203\r
1204/**\r
1205\r
1206 Base on the L"LegacyDevOrder" variable to build the current order data.\r
1207\r
1208**/\r
1209VOID\r
1210GetLegacyOptionsOrder (\r
1211 VOID\r
1212 )\r
1213{\r
1214 UINTN VarSize;\r
1215 UINT8 *VarData;\r
1216 UINT8 *VarTmp;\r
1217 LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
1218 UINT16 *LegacyDev;\r
1219 UINTN Index;\r
1220 LEGACY_MENU_OPTION *OptionMenu;\r
1221 UINT16 VarDevOrder;\r
1222 UINTN Pos;\r
1223 UINTN Bit;\r
1224 UINT8 *DisMap;\r
1225 UINTN TotalLength;\r
1226\r
1227 LegacyDev = NULL;\r
1228 OptionMenu = NULL;\r
1229\r
1230 DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap));\r
1231\r
1232 //\r
1233 // Get Device Order from variable\r
1234 //\r
1235 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize);\r
1236 VarTmp = VarData;\r
1237 if (NULL != VarData) {\r
1238 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;\r
1239 while (VarData < VarTmp + VarSize) {\r
1240 switch (DevOrder->BbsType) {\r
1241 case BBS_FLOPPY:\r
1242 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD;\r
1243 OptionMenu = &LegacyFDMenu;\r
1244 break;\r
1245 \r
1246 case BBS_HARDDISK:\r
1247 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD;\r
1248 OptionMenu = &LegacyHDMenu;\r
1249 break;\r
1250 \r
1251 case BBS_CDROM:\r
1252 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD;\r
1253 OptionMenu = &LegacyCDMenu;\r
1254 break;\r
1255 \r
1256 case BBS_EMBED_NETWORK:\r
1257 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET;\r
1258 OptionMenu = &LegacyNETMenu;\r
1259 break;\r
1260 \r
1261 case BBS_BEV_DEVICE:\r
1262 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV;\r
1263 OptionMenu = &LegacyBEVMenu;\r
1264 break;\r
1265 \r
1266 case BBS_UNKNOWN:\r
1267 default:\r
1268 ASSERT (FALSE);\r
1269 DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n"));\r
1270 break;\r
1271 }\r
1272\r
1273 //\r
1274 // Create oneof tag here for FD/HD/CD #1 #2\r
1275 //\r
1276 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1277 TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16);\r
1278 VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength);\r
1279\r
1280 if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
1281 LegacyDev[Index] = 0xFF;\r
1282 Pos = (VarDevOrder & 0xFF) / 8;\r
1283 Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
1284 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
1285 } else {\r
1286 LegacyDev[Index] = VarDevOrder & 0xFF;\r
1287 }\r
1288 }\r
1289\r
1290 VarData ++;\r
1291 VarData += *(UINT16 *) VarData;\r
1292 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;\r
1293 }\r
1294 }\r
1295\r
1296 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));\r
1297 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));\r
1298}\r
1299\r
1300/**\r
1301\r
1302 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
1303\r
1304**/\r
1305VOID\r
1306GetLegacyOptions (\r
1307 VOID\r
1308 )\r
1309{\r
1310 LEGACY_MENU_ENTRY *NewMenuEntry;\r
1311 LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
1312 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
1313 UINTN BootOptionCount;\r
1314 UINT16 Index;\r
1315 UINTN FDNum;\r
1316 UINTN HDNum;\r
1317 UINTN CDNum;\r
1318 UINTN NETNum;\r
1319 UINTN BEVNum;\r
1320\r
1321 //\r
1322 // Initialize Bbs Table Context from BBS info data\r
1323 //\r
1324 InitializeListHead (&LegacyFDMenu.Head);\r
1325 InitializeListHead (&LegacyHDMenu.Head);\r
1326 InitializeListHead (&LegacyCDMenu.Head);\r
1327 InitializeListHead (&LegacyNETMenu.Head);\r
1328 InitializeListHead (&LegacyBEVMenu.Head);\r
1329\r
1330 FDNum = 0;\r
1331 HDNum = 0;\r
1332 CDNum = 0;\r
1333 NETNum = 0;\r
1334 BEVNum = 0;\r
1335\r
1336 EfiBootManagerConnectAll ();\r
1337 \r
1338 //\r
1339 // for better user experience\r
1340 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option\r
1341 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option\r
1342 //\r
1343 EfiBootManagerRefreshAllBootOption ();\r
1344\r
1345 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
1346 for (Index = 0; Index < BootOptionCount; Index++) {\r
1347 if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||\r
1348 (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)\r
1349 ) {\r
1350 continue;\r
1351 }\r
1352 ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));\r
1353 NewMenuEntry = CreateMenuEntry ();\r
1354 ASSERT (NewMenuEntry != NULL);\r
1355\r
1356 NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
1357 NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex;\r
1358 NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description);\r
1359 ASSERT (NewLegacyDevContext->Description != NULL);\r
1360\r
1361 NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
1362 NewMenuEntry->HelpString = NULL;\r
1363\r
1364 switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {\r
1365 case BBS_TYPE_FLOPPY:\r
1366 InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
1367 FDNum++;\r
1368 break;\r
1369\r
1370 case BBS_TYPE_HARDDRIVE:\r
1371 InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
1372 HDNum++;\r
1373 break;\r
1374\r
1375 case BBS_TYPE_CDROM:\r
1376 InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
1377 CDNum++;\r
1378 break;\r
1379\r
1380 case BBS_TYPE_EMBEDDED_NETWORK:\r
1381 InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
1382 NETNum++;\r
1383 break;\r
1384\r
1385 case BBS_TYPE_BEV:\r
1386 InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
1387 BEVNum++;\r
1388 break;\r
1389 }\r
1390 }\r
1391\r
1392 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
1393\r
1394 LegacyFDMenu.MenuNumber = FDNum;\r
1395 LegacyHDMenu.MenuNumber = HDNum;\r
1396 LegacyCDMenu.MenuNumber = CDNum;\r
1397 LegacyNETMenu.MenuNumber = NETNum;\r
1398 LegacyBEVMenu.MenuNumber = BEVNum;\r
1399}\r
1400\r
1401\r
1402/**\r
1403\r
1404 Install Boot Manager Menu driver.\r
1405\r
1406 @param ImageHandle The image handle.\r
1407 @param SystemTable The system table.\r
1408\r
1409 @retval EFI_SUCEESS Install Boot manager menu success.\r
1410 @retval Other Return error status.\r
1411\r
1412**/\r
1413EFI_STATUS\r
1414EFIAPI\r
1415LegacyBootMaintUiLibConstructor (\r
1416 IN EFI_HANDLE ImageHandle,\r
1417 IN EFI_SYSTEM_TABLE *SystemTable\r
1418 )\r
1419{\r
1420 EFI_STATUS Status;\r
1421 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
1422 LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData;\r
1423\r
1424 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
1425 if (!EFI_ERROR (Status)) {\r
1426 //\r
1427 // Create LegacyBootOptionData structures for Driver Callback\r
1428 //\r
1429 LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA));\r
1430 ASSERT (LegacyBootOptionData != NULL);\r
1431 \r
1432 LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA));\r
1433 ASSERT (LegacyBootOptionData->MaintainMapData != NULL);\r
1434\r
1435 LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig;\r
1436 LegacyBootOptionData->ConfigAccess.RouteConfig = LegacyBootOptionRouteConfig;\r
1437 LegacyBootOptionData->ConfigAccess.Callback = LegacyBootOptionCallback;\r
1438\r
1439 //\r
1440 // Install Device Path Protocol and Config Access protocol to driver handle\r
1441 //\r
1442 Status = gBS->InstallMultipleProtocolInterfaces (\r
1443 &LegacyBootOptionData->DriverHandle,\r
1444 &gEfiDevicePathProtocolGuid,\r
1445 &mLegacyBootOptionHiiVendorDevicePath,\r
1446 &gEfiHiiConfigAccessProtocolGuid,\r
1447 &LegacyBootOptionData->ConfigAccess,\r
1448 NULL\r
1449 );\r
1450 ASSERT_EFI_ERROR (Status);\r
1451\r
1452 //\r
1453 // Publish our HII data\r
1454 //\r
1455 LegacyBootOptionData->HiiHandle = HiiAddPackages (\r
1456 &mLegacyBootOptionGuid,\r
1457 LegacyBootOptionData->DriverHandle,\r
1458 LegacyBootMaintUiVfrBin,\r
1459 LegacyBootMaintUiLibStrings,\r
1460 NULL\r
1461 );\r
1462 ASSERT (LegacyBootOptionData->HiiHandle != NULL);\r
1463\r
1464 mLegacyBootOptionPrivate = LegacyBootOptionData;\r
1465 }\r
1466\r
1467 return EFI_SUCCESS;\r
1468}\r
1469\r
1470/**\r
1471 Destructor of Customized Display Library Instance.\r
1472\r
1473 @param ImageHandle The firmware allocated handle for the EFI image.\r
1474 @param SystemTable A pointer to the EFI System Table.\r
1475\r
1476 @retval EFI_SUCCESS The destructor completed successfully.\r
1477 @retval Other value The destructor did not complete successfully.\r
1478\r
1479**/\r
1480EFI_STATUS\r
1481EFIAPI\r
1482LegacyBootMaintUiLibDestructor (\r
1483 IN EFI_HANDLE ImageHandle,\r
1484 IN EFI_SYSTEM_TABLE *SystemTable\r
1485 )\r
1486{\r
1487 EFI_STATUS Status;\r
1488\r
1489 if (mLegacyBootOptionPrivate != NULL && mLegacyBootOptionPrivate->DriverHandle != NULL) {\r
1490 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1491 mLegacyBootOptionPrivate->DriverHandle,\r
1492 &gEfiDevicePathProtocolGuid,\r
1493 &mLegacyBootOptionHiiVendorDevicePath,\r
1494 &gEfiHiiConfigAccessProtocolGuid,\r
1495 &mLegacyBootOptionPrivate->ConfigAccess,\r
1496 NULL\r
1497 );\r
1498 ASSERT_EFI_ERROR (Status);\r
1499 \r
1500 HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle);\r
1501\r
1502 FreePool (mLegacyBootOptionPrivate->MaintainMapData);\r
1503 FreePool (mLegacyBootOptionPrivate);\r
1504 }\r
1505\r
1506 return EFI_SUCCESS;\r
1507}\r
1508\r