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