]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
Refine BdsDxe driver and GenericBdsLib library so that the GenericBdsLib doesn't...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / BootMaint / BBSsupport.c
1 /** @file
2 This function deal with the legacy boot option, it create, delete
3 and manage the legacy boot option, all legacy boot option is getting from
4 the legacy BBS table.
5
6 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "BBSsupport.h"
18
19 #pragma pack(1)
20 typedef struct {
21 BBS_TABLE BbsEntry;
22 UINT16 BbsIndex;
23 } LEGACY_BOOT_OPTION_BBS_DATA;
24 #pragma pack()
25
26 /**
27 Re-order the Boot Option according to the DevOrder.
28
29 The routine re-orders the Boot Option in BootOption array according to
30 the order specified by DevOrder.
31
32 @param DevOrder Pointer to buffer containing the BBS Index,
33 high 8-bit value 0xFF indicating a disabled boot option
34 @param DevOrderCount Count of the BBS Index
35 @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers
36 @param EnBootOptionCount Count of the enabled Boot Option Numbers
37 @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers
38 @param DisBootOptionCount Count of the disabled Boot Option Numbers
39 **/
40 VOID
41 OrderLegacyBootOption4SameType (
42 UINT16 *DevOrder,
43 UINTN DevOrderCount,
44 UINT16 **EnBootOption,
45 UINTN *EnBootOptionCount,
46 UINT16 **DisBootOption,
47 UINTN *DisBootOptionCount
48 )
49 {
50 EFI_STATUS Status;
51 UINT16 *NewBootOption;
52 UINT16 *BootOrder;
53 UINTN BootOrderSize;
54 UINTN Index;
55 UINTN StartPosition;
56
57 BDS_COMMON_OPTION *BootOption;
58
59 CHAR16 OptionName[sizeof ("Boot####")];
60 UINT16 *BbsIndexArray;
61 UINT16 *DeviceTypeArray;
62 LIST_ENTRY List;
63
64 BootOrder = BdsLibGetVariableAndSize (
65 L"BootOrder",
66 &gEfiGlobalVariableGuid,
67 &BootOrderSize
68 );
69 ASSERT (BootOrder != NULL);
70
71 BbsIndexArray = AllocatePool (BootOrderSize);
72 DeviceTypeArray = AllocatePool (BootOrderSize);
73 *EnBootOption = AllocatePool (BootOrderSize);
74 *DisBootOption = AllocatePool (BootOrderSize);
75 *DisBootOptionCount = 0;
76 *EnBootOptionCount = 0;
77 Index = 0;
78
79 ASSERT (*EnBootOption != NULL);
80 ASSERT (*DisBootOption != NULL);
81
82 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
83
84 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
85 InitializeListHead (&List);
86 BootOption = BdsLibVariableToOption (&List, OptionName);
87 ASSERT_EFI_ERROR (BootOption != NULL);
88
89 if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) &&
90 (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) {
91 //
92 // Legacy Boot Option
93 //
94 ASSERT (BootOption->LoadOptionsSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));
95
96 DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType;
97 BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption->LoadOptions)->BbsIndex;
98 } else {
99 DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN;
100 BbsIndexArray [Index] = 0xFFFF;
101 }
102 FreePool (BootOption->DevicePath);
103 FreePool (BootOption->Description);
104 FreePool (BootOption->LoadOptions);
105 FreePool (BootOption);
106 }
107
108 //
109 // Record the corresponding Boot Option Numbers according to the DevOrder
110 // Record the EnBootOption and DisBootOption according to the DevOrder
111 //
112 StartPosition = BootOrderSize / sizeof (UINT16);
113 NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16));
114 while (DevOrderCount-- != 0) {
115 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
116 if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) {
117 StartPosition = MIN (StartPosition, Index);
118 NewBootOption[DevOrderCount] = BootOrder[Index];
119
120 if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {
121 (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index];
122 (*DisBootOptionCount)++;
123 } else {
124 (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index];
125 (*EnBootOptionCount)++;
126 }
127 break;
128 }
129 }
130 }
131
132 //
133 // Overwrite the old BootOption
134 //
135 CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));
136 Status = gRT->SetVariable (
137 L"BootOrder",
138 &gEfiGlobalVariableGuid,
139 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
140 BootOrderSize,
141 BootOrder
142 );
143 ASSERT_EFI_ERROR (Status);
144
145 FreePool (NewBootOption);
146 FreePool (DeviceTypeArray);
147 FreePool (BbsIndexArray);
148 }
149
150 /**
151 Group the legacy boot options in the BootOption.
152
153 The routine assumes the boot options in the beginning that covers all the device
154 types are ordered properly and re-position the following boot options just after
155 the corresponding boot options with the same device type.
156 For example:
157 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]
158 Assuming [Harddisk1 CdRom2 Efi1] is ordered properly
159 Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]
160
161 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]
162 Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly
163 Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]
164
165 **/
166 VOID
167 GroupMultipleLegacyBootOption4SameType (
168 VOID
169 )
170 {
171 UINTN Index;
172 UINTN DeviceIndex;
173 UINTN DeviceTypeIndex[7];
174 UINTN *NextIndex;
175 UINT16 OptionNumber;
176 UINT16 *BootOrder;
177 UINTN BootOrderSize;
178 CHAR16 OptionName[sizeof ("Boot####")];
179 BDS_COMMON_OPTION *BootOption;
180 LIST_ENTRY List;
181
182 SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff);
183
184 BootOrder = BdsLibGetVariableAndSize (
185 L"BootOrder",
186 &gEfiGlobalVariableGuid,
187 &BootOrderSize
188 );
189
190 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
191 UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
192 InitializeListHead (&List);
193 BootOption = BdsLibVariableToOption (&List, OptionName);
194 ASSERT_EFI_ERROR (BootOption != NULL);
195
196 if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) &&
197 (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) {
198 //
199 // Legacy Boot Option
200 //
201 ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF) < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]));
202 NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF];
203
204 if (*NextIndex == (UINTN) -1) {
205 //
206 // *NextIndex is the Index in BootOrder to put the next Option Number for the same type
207 //
208 *NextIndex = Index + 1;
209 } else {
210 //
211 // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position
212 //
213 OptionNumber = BootOrder[Index];
214 CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));
215 BootOrder[*NextIndex] = OptionNumber;
216
217 //
218 // Update the DeviceTypeIndex array to reflect the right shift operation
219 //
220 for (DeviceIndex = 0; DeviceIndex < sizeof (DeviceTypeIndex) / sizeof (DeviceTypeIndex[0]); DeviceIndex++) {
221 if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {
222 DeviceTypeIndex[DeviceIndex]++;
223 }
224 }
225 }
226 }
227 FreePool (BootOption->DevicePath);
228 FreePool (BootOption->Description);
229 FreePool (BootOption->LoadOptions);
230 FreePool (BootOption);
231 }
232
233 gRT->SetVariable (
234 L"BootOrder",
235 &gEfiGlobalVariableGuid,
236 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
237 BootOrderSize,
238 BootOrder
239 );
240 FreePool (BootOrder);
241 }
242