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