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