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