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