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