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