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