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