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