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