]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBootMaintUi.c
IntelFrameworkModulePkg/LegacyBootMaintUiLib: Refine the code
[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 BBS_TYPE BbsType;
724 UINT16 *Default;
725 UINT16 Index;
726 UINT16 Key;
727 CHAR16 String[100];
728 CHAR16 *TypeStr;
729 CHAR16 *TypeStrHelp;
730 CHAR16 *FormTitle;
731 VOID *OptionsOpCodeHandle;
732 VOID *DefaultOpCodeHandle;
733
734 Key = 0;
735 StrRef = 0;
736 StrRefHelp = 0;
737 OptionMenu = NULL;
738 TypeStr = NULL;
739 TypeStrHelp = NULL;
740 Default = NULL;
741 BbsType = BBS_FLOPPY;
742
743 RefreshLegacyUpdateData();
744
745 //
746 // Create oneof option list
747 //
748 switch (UpdatePageId) {
749 case FORM_FLOPPY_BOOT_ID:
750 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyFDMenu;
751 Key = (UINT16) LEGACY_FD_QUESTION_ID;
752 TypeStr = STR_FLOPPY;
753 TypeStrHelp = STR_FLOPPY_HELP;
754 FormTitle = STR_FLOPPY_TITLE;
755 BbsType = BBS_FLOPPY;
756 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD;
757 break;
758
759 case FORM_HARDDISK_BOOT_ID:
760 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyHDMenu;
761 Key = (UINT16) LEGACY_HD_QUESTION_ID;
762 TypeStr = STR_HARDDISK;
763 TypeStrHelp = STR_HARDDISK_HELP;
764 FormTitle = STR_HARDDISK_TITLE;
765 BbsType = BBS_HARDDISK;
766 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD;
767 break;
768
769 case FORM_CDROM_BOOT_ID:
770 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyCDMenu;
771 Key = (UINT16) LEGACY_CD_QUESTION_ID;
772 TypeStr = STR_CDROM;
773 TypeStrHelp = STR_CDROM_HELP;
774 FormTitle = STR_CDROM_TITLE;
775 BbsType = BBS_CDROM;
776 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD;
777 break;
778
779 case FORM_NET_BOOT_ID:
780 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyNETMenu;
781 Key = (UINT16) LEGACY_NET_QUESTION_ID;
782 TypeStr = STR_NET;
783 TypeStrHelp = STR_NET_HELP;
784 FormTitle = STR_NET_TITLE;
785 BbsType = BBS_EMBED_NETWORK;
786 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET;
787 break;
788
789 case FORM_BEV_BOOT_ID:
790 OptionMenu = (LEGACY_MENU_OPTION *) &LegacyBEVMenu;
791 Key = (UINT16) LEGACY_BEV_QUESTION_ID;
792 TypeStr = STR_BEV;
793 TypeStrHelp = STR_BEV_HELP;
794 FormTitle = STR_BEV_TITLE;
795 BbsType = BBS_BEV_DEVICE;
796 Default = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV;
797 break;
798
799 default:
800 DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));
801 return;
802 }
803
804 HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL);
805
806 CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu);
807
808 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
809 ASSERT (OptionsOpCodeHandle != NULL);
810
811
812 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
813 NewMenuEntry = GetMenuEntry (OptionMenu, Index);
814 //
815 // Create OneOf for each legacy device
816 //
817 HiiCreateOneOfOptionOpCode (
818 OptionsOpCodeHandle,
819 NewMenuEntry->DisplayStringToken,
820 0,
821 EFI_IFR_TYPE_NUM_SIZE_16,
822 ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex
823 );
824 }
825
826 //
827 // Create OneOf for item "Disabled"
828 //
829 HiiCreateOneOfOptionOpCode (
830 OptionsOpCodeHandle,
831 STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE),
832 0,
833 EFI_IFR_TYPE_NUM_SIZE_16,
834 0xFF
835 );
836
837 //
838 // Create oneof tag here for FD/HD/CD #1 #2
839 //
840 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
841 DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
842 ASSERT (DefaultOpCodeHandle != NULL);
843
844 HiiCreateDefaultOpCode (
845 DefaultOpCodeHandle,
846 EFI_HII_DEFAULT_CLASS_STANDARD,
847 EFI_IFR_TYPE_NUM_SIZE_16,
848 *Default++
849 );
850
851 //
852 // Create the string for oneof tag
853 //
854 UnicodeSPrint (String, sizeof (String), TypeStr, Index);
855 StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);
856
857 UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);
858 StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);
859
860 HiiCreateOneOfOpCode (
861 mLegacyStartOpCodeHandle,
862 (EFI_QUESTION_ID) (Key + Index),
863 VARSTORE_ID_LEGACY_BOOT,
864 (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET),
865 StrRef,
866 StrRefHelp,
867 EFI_IFR_FLAG_CALLBACK,
868 EFI_IFR_NUMERIC_SIZE_2,
869 OptionsOpCodeHandle,
870 DefaultOpCodeHandle //NULL //
871 );
872
873 HiiFreeOpCodeHandle (DefaultOpCodeHandle);
874 }
875
876 HiiUpdateForm (
877 mLegacyBootOptionPrivate->HiiHandle,
878 &mLegacyBootOptionGuid,
879 LEGACY_ORDER_CHANGE_FORM_ID,
880 mLegacyStartOpCodeHandle,
881 mLegacyEndOpCodeHandle
882 );
883
884 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
885 }
886
887
888 /**
889 Adjust question value when one question value has been changed.
890
891 @param QuestionId The question id for the value changed question.
892 @param Value The value for the changed question.
893
894 **/
895 VOID
896 AdjustOptionValue (
897 IN UINT16 QuestionId,
898 IN EFI_IFR_TYPE_VALUE *Value
899 )
900 {
901 UINTN Number;
902 BBS_TYPE BbsType;
903 LEGACY_DEV_ORDER_ENTRY *DevOrder;
904 UINT16 *Default;
905 LEGACY_BOOT_NV_DATA *CurrentNVMap;
906 UINT16 *CurrentVal;
907 UINTN Index;
908 UINTN Index2;
909 UINTN Index3;
910 UINTN NewValuePos;
911 UINTN OldValue;
912 UINTN NewValue;
913 UINT8 *DisMap;
914 UINTN Pos;
915 UINTN Bit;
916
917 Number = 0;
918 BbsType = BBS_UNKNOWN;
919 CurrentVal = 0;
920 DevOrder = NULL;
921 Default = NULL;
922 NewValue = 0;
923 NewValuePos = 0;
924 OldValue = 0;
925
926 //
927 // Update Select FD/HD/CD/NET/BEV Order Form
928 //
929 ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER));
930
931 CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData;
932 HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap);
933 DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap;
934
935 if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) {
936 Number = (UINT16) LegacyFDMenu.MenuNumber;
937 BbsType = BBS_FLOPPY;
938 CurrentVal = CurrentNVMap->LegacyFD;
939 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD;
940 } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) {
941 Number = (UINT16) LegacyHDMenu.MenuNumber;
942 BbsType = BBS_HARDDISK;
943 CurrentVal = CurrentNVMap->LegacyHD;
944 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD;
945 } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) {
946 Number = (UINT16) LegacyCDMenu.MenuNumber;
947 BbsType = BBS_CDROM;
948 CurrentVal = CurrentNVMap->LegacyCD;
949 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD;
950 } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) {
951 Number = (UINT16) LegacyNETMenu.MenuNumber;
952 BbsType = BBS_EMBED_NETWORK;
953 CurrentVal = CurrentNVMap->LegacyNET;
954 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET;
955 } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) {
956 Number = (UINT16) LegacyBEVMenu.MenuNumber;
957 BbsType = BBS_BEV_DEVICE;
958 CurrentVal = CurrentNVMap->LegacyBEV;
959 Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV;
960 }
961
962 //
963 // First, find the different position
964 // if there is change, it should be only one
965 //
966 for (Index = 0; Index < Number; Index++) {
967 if (CurrentVal[Index] != Default[Index]) {
968 OldValue = Default[Index];
969 NewValue = CurrentVal[Index];
970 break;
971 }
972 }
973
974 if (Index != Number) {
975 //
976 // there is change, now process
977 //
978 if (0xFF == NewValue) {
979 //
980 // This item will be disable
981 // Just move the items behind this forward to overlap it
982 //
983 Pos = OldValue / 8;
984 Bit = 7 - (OldValue % 8);
985 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
986 for (Index2 = Index; Index2 < Number - 1; Index2++) {
987 CurrentVal[Index2] = CurrentVal[Index2 + 1];
988 }
989
990 CurrentVal[Index2] = 0xFF;
991 } else {
992 for (Index2 = 0; Index2 < Number; Index2++) {
993 if (Index2 == Index) {
994 continue;
995 }
996
997 if (Default[Index2] == NewValue) {
998 //
999 // If NewValue is in OldLegacyDev array
1000 // remember its old position
1001 //
1002 NewValuePos = Index2;
1003 break;
1004 }
1005 }
1006
1007 if (Index2 != Number) {
1008 //
1009 // We will change current item to an existing item
1010 // (It's hard to describe here, please read code, it's like a cycle-moving)
1011 //
1012 for (Index2 = NewValuePos; Index2 != Index;) {
1013 if (NewValuePos < Index) {
1014 CurrentVal[Index2] = Default[Index2 + 1];
1015 Index2++;
1016 } else {
1017 CurrentVal[Index2] = Default[Index2 - 1];
1018 Index2--;
1019 }
1020 }
1021 } else {
1022 //
1023 // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
1024 // so we should modify DisMap to reflect the change
1025 //
1026 Pos = NewValue / 8;
1027 Bit = 7 - (NewValue % 8);
1028 DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
1029 if (0xFF != OldValue) {
1030 //
1031 // Because NewValue is a item that was disabled before
1032 // so after changing the OldValue should be disabled
1033 // actually we are doing a swap of enable-disable states of two items
1034 //
1035 Pos = OldValue / 8;
1036 Bit = 7 - (OldValue % 8);
1037 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
1038 }
1039 }
1040 }
1041 //
1042 // To prevent DISABLE appears in the middle of the list
1043 // we should perform a re-ordering
1044 //
1045 Index3 = Index;
1046 Index = 0;
1047 while (Index < Number) {
1048 if (0xFF != CurrentVal[Index]) {
1049 Index++;
1050 continue;
1051 }
1052
1053 Index2 = Index;
1054 Index2++;
1055 while (Index2 < Number) {
1056 if (0xFF != CurrentVal[Index2]) {
1057 break;
1058 }
1059
1060 Index2++;
1061 }
1062
1063 if (Index2 < Number) {
1064 CurrentVal[Index] = CurrentVal[Index2];
1065 CurrentVal[Index2] = 0xFF;
1066 }
1067
1068 Index++;
1069 }
1070
1071 //
1072 // Return correct question value.
1073 //
1074 Value->u16 = CurrentVal[Index3];
1075 CopyMem (Default, CurrentVal, sizeof (UINT16) * Number);
1076 }
1077
1078 //
1079 // Pass changed uncommitted data back to Form Browser
1080 //
1081 HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL);
1082 }
1083
1084 /**
1085 This call back function is registered with Boot Manager formset.
1086 When user selects a boot option, this call back function will
1087 be triggered. The boot option is saved for later processing.
1088
1089
1090 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1091 @param Action Specifies the type of action taken by the browser.
1092 @param QuestionId A unique value which is sent to the original exporting driver
1093 so that it can identify the type of data to expect.
1094 @param Type The type of value for the question.
1095 @param Value A pointer to the data being sent to the original exporting driver.
1096 @param ActionRequest On return, points to the action requested by the callback function.
1097
1098 @retval EFI_SUCCESS The callback successfully handled the action.
1099 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
1100
1101 **/
1102 EFI_STATUS
1103 EFIAPI
1104 LegacyBootOptionCallback (
1105 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1106 IN EFI_BROWSER_ACTION Action,
1107 IN EFI_QUESTION_ID QuestionId,
1108 IN UINT8 Type,
1109 IN EFI_IFR_TYPE_VALUE *Value,
1110 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1111 )
1112 {
1113 if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING) {
1114 //
1115 // Do nothing for other UEFI Action. Only do call back when data is changed.
1116 //
1117 return EFI_UNSUPPORTED;
1118 }
1119
1120 if ((Value == NULL) || (ActionRequest == NULL)) {
1121 return EFI_INVALID_PARAMETER;
1122 }
1123
1124 if (Action == EFI_BROWSER_ACTION_CHANGING) {
1125 switch (QuestionId) {
1126 case FORM_FLOPPY_BOOT_ID:
1127 case FORM_HARDDISK_BOOT_ID:
1128 case FORM_CDROM_BOOT_ID:
1129 case FORM_NET_BOOT_ID:
1130 case FORM_BEV_BOOT_ID:
1131 UpdateLegacyDeviceOrderPage (QuestionId);
1132 break;
1133
1134 default:
1135 break;
1136 }
1137 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
1138 if ((Value == NULL) || (ActionRequest == NULL)) {
1139 return EFI_INVALID_PARAMETER;
1140 }
1141
1142 if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) {
1143 AdjustOptionValue(QuestionId, Value);
1144 }
1145 }
1146 return EFI_SUCCESS;
1147 }
1148
1149
1150 /**
1151 Create a menu entry by given menu type.
1152
1153 @param MenuType The Menu type to be created.
1154
1155 @retval NULL If failed to create the menu.
1156 @return the new menu entry.
1157
1158 **/
1159 LEGACY_MENU_ENTRY *
1160 CreateMenuEntry (
1161 VOID
1162 )
1163 {
1164 LEGACY_MENU_ENTRY *MenuEntry;
1165
1166 //
1167 // Create new menu entry
1168 //
1169 MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY));
1170 if (MenuEntry == NULL) {
1171 return NULL;
1172 }
1173
1174 MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT));
1175 if (MenuEntry->VariableContext == NULL) {
1176 FreePool (MenuEntry);
1177 return NULL;
1178 }
1179
1180 MenuEntry->Signature = LEGACY_MENU_ENTRY_SIGNATURE;
1181 return MenuEntry;
1182 }
1183
1184 /**
1185
1186 Base on the L"LegacyDevOrder" variable to build the current order data.
1187
1188 **/
1189 VOID
1190 GetLegacyOptionsOrder (
1191 VOID
1192 )
1193 {
1194 UINTN VarSize;
1195 UINT8 *VarData;
1196 UINT8 *VarTmp;
1197 LEGACY_DEV_ORDER_ENTRY *DevOrder;
1198 UINT16 *LegacyDev;
1199 UINTN Index;
1200 LEGACY_MENU_OPTION *OptionMenu;
1201 UINT16 VarDevOrder;
1202 UINTN Pos;
1203 UINTN Bit;
1204 UINT8 *DisMap;
1205 UINTN TotalLength;
1206
1207 LegacyDev = NULL;
1208 OptionMenu = NULL;
1209
1210 DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap));
1211
1212 //
1213 // Get Device Order from variable
1214 //
1215 GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize);
1216 VarTmp = VarData;
1217 if (NULL != VarData) {
1218 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;
1219 while (VarData < VarTmp + VarSize) {
1220 switch (DevOrder->BbsType) {
1221 case BBS_FLOPPY:
1222 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD;
1223 OptionMenu = &LegacyFDMenu;
1224 break;
1225
1226 case BBS_HARDDISK:
1227 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD;
1228 OptionMenu = &LegacyHDMenu;
1229 break;
1230
1231 case BBS_CDROM:
1232 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD;
1233 OptionMenu = &LegacyCDMenu;
1234 break;
1235
1236 case BBS_EMBED_NETWORK:
1237 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET;
1238 OptionMenu = &LegacyNETMenu;
1239 break;
1240
1241 case BBS_BEV_DEVICE:
1242 LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV;
1243 OptionMenu = &LegacyBEVMenu;
1244 break;
1245
1246 case BBS_UNKNOWN:
1247 default:
1248 ASSERT (FALSE);
1249 DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n"));
1250 break;
1251 }
1252
1253 //
1254 // Create oneof tag here for FD/HD/CD #1 #2
1255 //
1256 for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
1257 TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16);
1258 VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength);
1259
1260 if (0xFF00 == (VarDevOrder & 0xFF00)) {
1261 LegacyDev[Index] = 0xFF;
1262 Pos = (VarDevOrder & 0xFF) / 8;
1263 Bit = 7 - ((VarDevOrder & 0xFF) % 8);
1264 DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
1265 } else {
1266 LegacyDev[Index] = VarDevOrder & 0xFF;
1267 }
1268 }
1269
1270 VarData ++;
1271 VarData += *(UINT16 *) VarData;
1272 DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;
1273 }
1274 }
1275
1276 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));
1277 CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));
1278 }
1279
1280 /**
1281
1282 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
1283
1284 **/
1285 VOID
1286 GetLegacyOptions (
1287 VOID
1288 )
1289 {
1290 LEGACY_MENU_ENTRY *NewMenuEntry;
1291 LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;
1292 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
1293 UINTN BootOptionCount;
1294 UINT16 Index;
1295 UINTN FDNum;
1296 UINTN HDNum;
1297 UINTN CDNum;
1298 UINTN NETNum;
1299 UINTN BEVNum;
1300
1301 //
1302 // Initialize Bbs Table Context from BBS info data
1303 //
1304 InitializeListHead (&LegacyFDMenu.Head);
1305 InitializeListHead (&LegacyHDMenu.Head);
1306 InitializeListHead (&LegacyCDMenu.Head);
1307 InitializeListHead (&LegacyNETMenu.Head);
1308 InitializeListHead (&LegacyBEVMenu.Head);
1309
1310 FDNum = 0;
1311 HDNum = 0;
1312 CDNum = 0;
1313 NETNum = 0;
1314 BEVNum = 0;
1315
1316 EfiBootManagerConnectAll ();
1317
1318 //
1319 // for better user experience
1320 // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option
1321 // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option
1322 //
1323 EfiBootManagerRefreshAllBootOption ();
1324
1325 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
1326 for (Index = 0; Index < BootOptionCount; Index++) {
1327 if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||
1328 (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)
1329 ) {
1330 continue;
1331 }
1332 ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));
1333 NewMenuEntry = CreateMenuEntry ();
1334 ASSERT (NewMenuEntry != NULL);
1335
1336 NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
1337 NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex;
1338 NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description);
1339 ASSERT (NewLegacyDevContext->Description != NULL);
1340
1341 NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
1342 NewMenuEntry->HelpString = NULL;
1343
1344 switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {
1345 case BBS_TYPE_FLOPPY:
1346 InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
1347 FDNum++;
1348 break;
1349
1350 case BBS_TYPE_HARDDRIVE:
1351 InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
1352 HDNum++;
1353 break;
1354
1355 case BBS_TYPE_CDROM:
1356 InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
1357 CDNum++;
1358 break;
1359
1360 case BBS_TYPE_EMBEDDED_NETWORK:
1361 InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
1362 NETNum++;
1363 break;
1364
1365 case BBS_TYPE_BEV:
1366 InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
1367 BEVNum++;
1368 break;
1369 }
1370 }
1371
1372 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
1373
1374 LegacyFDMenu.MenuNumber = FDNum;
1375 LegacyHDMenu.MenuNumber = HDNum;
1376 LegacyCDMenu.MenuNumber = CDNum;
1377 LegacyNETMenu.MenuNumber = NETNum;
1378 LegacyBEVMenu.MenuNumber = BEVNum;
1379 }
1380
1381
1382 /**
1383
1384 Install Boot Manager Menu driver.
1385
1386 @param ImageHandle The image handle.
1387 @param SystemTable The system table.
1388
1389 @retval EFI_SUCEESS Install Boot manager menu success.
1390 @retval Other Return error status.
1391
1392 **/
1393 EFI_STATUS
1394 EFIAPI
1395 LegacyBootMaintUiLibConstructor (
1396 IN EFI_HANDLE ImageHandle,
1397 IN EFI_SYSTEM_TABLE *SystemTable
1398 )
1399 {
1400 EFI_STATUS Status;
1401 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
1402 LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData;
1403
1404 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
1405 if (!EFI_ERROR (Status)) {
1406 //
1407 // Create LegacyBootOptionData structures for Driver Callback
1408 //
1409 LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA));
1410 ASSERT (LegacyBootOptionData != NULL);
1411
1412 LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA));
1413 ASSERT (LegacyBootOptionData->MaintainMapData != NULL);
1414
1415 LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig;
1416 LegacyBootOptionData->ConfigAccess.RouteConfig = LegacyBootOptionRouteConfig;
1417 LegacyBootOptionData->ConfigAccess.Callback = LegacyBootOptionCallback;
1418
1419 //
1420 // Install Device Path Protocol and Config Access protocol to driver handle
1421 //
1422 Status = gBS->InstallMultipleProtocolInterfaces (
1423 &LegacyBootOptionData->DriverHandle,
1424 &gEfiDevicePathProtocolGuid,
1425 &mLegacyBootOptionHiiVendorDevicePath,
1426 &gEfiHiiConfigAccessProtocolGuid,
1427 &LegacyBootOptionData->ConfigAccess,
1428 NULL
1429 );
1430 ASSERT_EFI_ERROR (Status);
1431
1432 //
1433 // Publish our HII data
1434 //
1435 LegacyBootOptionData->HiiHandle = HiiAddPackages (
1436 &mLegacyBootOptionGuid,
1437 LegacyBootOptionData->DriverHandle,
1438 LegacyBootMaintUiVfrBin,
1439 LegacyBootMaintUiLibStrings,
1440 NULL
1441 );
1442 ASSERT (LegacyBootOptionData->HiiHandle != NULL);
1443
1444 mLegacyBootOptionPrivate = LegacyBootOptionData;
1445
1446 GetLegacyOptions ();
1447
1448 GetLegacyOptionsOrder();
1449 }
1450
1451 return EFI_SUCCESS;
1452 }
1453
1454 /**
1455 Destructor of Customized Display Library Instance.
1456
1457 @param ImageHandle The firmware allocated handle for the EFI image.
1458 @param SystemTable A pointer to the EFI System Table.
1459
1460 @retval EFI_SUCCESS The destructor completed successfully.
1461 @retval Other value The destructor did not complete successfully.
1462
1463 **/
1464 EFI_STATUS
1465 EFIAPI
1466 LegacyBootMaintUiLibDestructor (
1467 IN EFI_HANDLE ImageHandle,
1468 IN EFI_SYSTEM_TABLE *SystemTable
1469 )
1470 {
1471 EFI_STATUS Status;
1472
1473 if (mLegacyBootOptionPrivate->DriverHandle != NULL) {
1474 Status = gBS->UninstallMultipleProtocolInterfaces (
1475 mLegacyBootOptionPrivate->DriverHandle,
1476 &gEfiDevicePathProtocolGuid,
1477 &mLegacyBootOptionHiiVendorDevicePath,
1478 &gEfiHiiConfigAccessProtocolGuid,
1479 &mLegacyBootOptionPrivate->ConfigAccess,
1480 NULL
1481 );
1482 ASSERT_EFI_ERROR (Status);
1483
1484 HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle);
1485
1486 FreePool (mLegacyBootOptionPrivate->MaintainMapData);
1487 FreePool (mLegacyBootOptionPrivate);
1488 }
1489
1490 return EFI_SUCCESS;
1491 }
1492