]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BootOption.c
ArmPlatformPkg/Bds: Remove Linux specific boot path
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootOption.c
CommitLineData
ea46ebbe 1/** @file\r
2*\r
c75d3eb6 3* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
ea46ebbe 4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
c0b2e477 15#include <Guid/ArmGlobalVariableHob.h>\r
ea46ebbe 16#include "BdsInternal.h"\r
17\r
ea46ebbe 18EFI_STATUS\r
19BootOptionStart (\r
20 IN BDS_LOAD_OPTION *BootOption\r
21 )\r
22{\r
8b129b7b
OM
23 EFI_STATUS Status;\r
24 UINT16 LoadOptionIndexSize;\r
4c8bb1eb 25\r
8b129b7b
OM
26 // Connect all the drivers if the EFI Application is not a EFI OS Loader\r
27 if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) {\r
28 BdsConnectAllDrivers ();\r
29 }\r
91213ad3 30\r
8b129b7b
OM
31 // Set BootCurrent variable\r
32 LoadOptionIndexSize = sizeof (UINT16);\r
33 gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
34 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
35 LoadOptionIndexSize, &(BootOption->LoadOptionIndex));\r
91213ad3 36\r
8b129b7b
OM
37 Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData);\r
38\r
39 // Clear BootCurrent variable\r
40 LoadOptionIndexSize = sizeof (UINT16);\r
41 gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
42 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
43 0, NULL);\r
ea46ebbe 44\r
45 return Status;\r
46}\r
47\r
ea46ebbe 48EFI_STATUS\r
49BootOptionList (\r
50 IN OUT LIST_ENTRY *BootOptionList\r
51 )\r
52{\r
a6e97d28 53 EFI_STATUS Status;\r
54 UINTN Index;\r
55 UINT16* BootOrder;\r
56 UINTN BootOrderSize;\r
57 BDS_LOAD_OPTION* BdsLoadOption;\r
58 BDS_LOAD_OPTION_ENTRY* BdsLoadOptionEntry;\r
ea46ebbe 59\r
60 InitializeListHead (BootOptionList);\r
61\r
62 // Get the Boot Option Order from the environment variable\r
c0b2e477 63 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 64 if (EFI_ERROR(Status)) {\r
65 return Status;\r
66 }\r
67\r
68 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
4aa24170 69 Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);\r
ea46ebbe 70 if (!EFI_ERROR(Status)) {\r
a6e97d28 71 BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool(sizeof(BDS_LOAD_OPTION_ENTRY));\r
72 BdsLoadOptionEntry->BdsLoadOption = BdsLoadOption;\r
73 InsertTailList (BootOptionList,&BdsLoadOptionEntry->Link);\r
ea46ebbe 74 }\r
75 }\r
76\r
b148591a 77 FreePool (BootOrder);\r
78\r
ea46ebbe 79 return EFI_SUCCESS;\r
80}\r
81\r
ea46ebbe 82STATIC\r
83EFI_STATUS\r
84BootOptionSetFields (\r
c60ea9a8 85 IN BDS_LOAD_OPTION* BootOption,\r
86 IN UINT32 Attributes,\r
87 IN CHAR16* BootDescription,\r
88 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
90a44ec4
OM
89 IN UINT8* OptionalData,\r
90 IN UINTN OptionalDataSize\r
ea46ebbe 91 )\r
92{\r
459823d9 93 EFI_LOAD_OPTION *EfiLoadOption;\r
2ccfb71e 94 UINTN EfiLoadOptionSize;\r
95 UINTN BootDescriptionSize;\r
2ccfb71e 96 UINT16 FilePathListLength;\r
97 UINT8* EfiLoadOptionPtr;\r
ea46ebbe 98\r
99 // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
100 if (BootOption->LoadOption) {\r
90a44ec4 101 FreePool (BootOption->LoadOption);\r
ea46ebbe 102 }\r
103\r
2ccfb71e 104 BootDescriptionSize = StrSize (BootDescription);\r
90a44ec4 105\r
ea46ebbe 106 // Compute the size of the FilePath list\r
2ccfb71e 107 FilePathListLength = GetUnalignedDevicePathSize (DevicePath);\r
656416bc 108\r
ea46ebbe 109 // Allocate the memory for the EFI Load Option\r
90a44ec4 110 EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + OptionalDataSize;\r
459823d9
AB
111 EfiLoadOption = (EFI_LOAD_OPTION *)AllocatePool(EfiLoadOptionSize);\r
112 EfiLoadOptionPtr = (UINT8 *)EfiLoadOption;\r
ea46ebbe 113\r
114 //\r
115 // Populate the EFI Load Option and BDS Boot Option structures\r
116 //\r
117\r
118 // Attributes fields\r
119 BootOption->Attributes = Attributes;\r
120 *(UINT32*)EfiLoadOptionPtr = Attributes;\r
121 EfiLoadOptionPtr += sizeof(UINT32);\r
122\r
123 // FilePath List fields\r
124 BootOption->FilePathListLength = FilePathListLength;\r
125 *(UINT16*)EfiLoadOptionPtr = FilePathListLength;\r
126 EfiLoadOptionPtr += sizeof(UINT16);\r
127\r
128 // Boot description fields\r
129 BootOption->Description = (CHAR16*)EfiLoadOptionPtr;\r
130 CopyMem (EfiLoadOptionPtr, BootDescription, BootDescriptionSize);\r
131 EfiLoadOptionPtr += BootDescriptionSize;\r
132\r
133 // File path fields\r
134 BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr;\r
2ccfb71e 135 CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength);\r
136 EfiLoadOptionPtr += FilePathListLength;\r
ea46ebbe 137\r
138 // Optional Data fields, Do unaligned writes\r
2ccfb71e 139 BootOption->OptionalData = EfiLoadOptionPtr;\r
ea46ebbe 140\r
8b129b7b
OM
141 if (OptionalData != NULL) {\r
142 CopyMem (BootOption->OptionalData, OptionalData, OptionalDataSize);\r
656416bc 143 }\r
8b129b7b 144\r
2ccfb71e 145 BootOption->OptionalDataSize = OptionalDataSize;\r
146\r
6bab33c7 147 // If this function is called at the creation of the Boot Device entry (not at the update) the\r
148 // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
149 if (BootOption->LoadOptionSize == 0) {\r
2ccfb71e 150 BootOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
6bab33c7 151 }\r
152\r
ea46ebbe 153 // Fill the EFI Load option fields\r
ea46ebbe 154 BootOption->LoadOption = EfiLoadOption;\r
155 BootOption->LoadOptionSize = EfiLoadOptionSize;\r
156\r
157 return EFI_SUCCESS;\r
158}\r
159\r
160EFI_STATUS\r
161BootOptionCreate (\r
c60ea9a8 162 IN UINT32 Attributes,\r
163 IN CHAR16* BootDescription,\r
ea46ebbe 164 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
90a44ec4
OM
165 IN UINT8* OptionalData,\r
166 IN UINTN OptionalDataSize,\r
a6e97d28 167 OUT BDS_LOAD_OPTION** BdsLoadOption\r
ea46ebbe 168 )\r
169{\r
a6e97d28 170 EFI_STATUS Status;\r
171 BDS_LOAD_OPTION_ENTRY* BootOptionEntry;\r
172 BDS_LOAD_OPTION* BootOption;\r
173 CHAR16 BootVariableName[9];\r
174 UINT16* BootOrder;\r
175 UINTN BootOrderSize;\r
ea46ebbe 176\r
177 //\r
178 // Allocate and fill the memory for the BDS Load Option structure\r
179 //\r
a6e97d28 180 BootOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof (BDS_LOAD_OPTION_ENTRY));\r
181 InitializeListHead (&BootOptionEntry->Link);\r
182 BootOptionEntry->BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
ea46ebbe 183\r
a6e97d28 184 BootOption = BootOptionEntry->BdsLoadOption;\r
8b129b7b 185 BootOptionSetFields (BootOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
ea46ebbe 186\r
187 //\r
188 // Set the related environment variables\r
189 //\r
190\r
191 // Create Boot#### environment variable\r
192 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
193 Status = gRT->SetVariable (\r
194 BootVariableName,\r
195 &gEfiGlobalVariableGuid,\r
196 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
197 BootOption->LoadOptionSize,\r
198 BootOption->LoadOption\r
199 );\r
200\r
201 // Add the new Boot Index to the list\r
c0b2e477 202 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 203 if (!EFI_ERROR(Status)) {\r
204 BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
205 // Add the new index at the end\r
206 BootOrder[BootOrderSize / sizeof(UINT16)] = BootOption->LoadOptionIndex;\r
207 BootOrderSize += sizeof(UINT16);\r
208 } else {\r
209 // BootOrder does not exist. Create it\r
210 BootOrderSize = sizeof(UINT16);\r
211 BootOrder = &(BootOption->LoadOptionIndex);\r
212 }\r
213\r
214 // Update (or Create) the BootOrder environment variable\r
215 Status = gRT->SetVariable (\r
216 L"BootOrder",\r
217 &gEfiGlobalVariableGuid,\r
218 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
219 BootOrderSize,\r
220 BootOrder\r
221 );\r
222\r
b148591a 223 // We only free it if the UEFI Variable 'BootOrder' was already existing\r
224 if (BootOrderSize > sizeof(UINT16)) {\r
225 FreePool (BootOrder);\r
226 }\r
227\r
ea46ebbe 228 *BdsLoadOption = BootOption;\r
229 return Status;\r
230}\r
231\r
232EFI_STATUS\r
233BootOptionUpdate (\r
2ccfb71e 234 IN BDS_LOAD_OPTION* BdsLoadOption,\r
235 IN UINT32 Attributes,\r
236 IN CHAR16* BootDescription,\r
ea46ebbe 237 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
90a44ec4
OM
238 IN UINT8* OptionalData,\r
239 IN UINTN OptionalDataSize\r
ea46ebbe 240 )\r
241{\r
242 EFI_STATUS Status;\r
ea46ebbe 243 CHAR16 BootVariableName[9];\r
244\r
245 // Update the BDS Load Option structure\r
8b129b7b 246 BootOptionSetFields (BdsLoadOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
ea46ebbe 247\r
248 // Update the related environment variables\r
6bab33c7 249 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
250\r
ea46ebbe 251 Status = gRT->SetVariable (\r
252 BootVariableName,\r
253 &gEfiGlobalVariableGuid,\r
254 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
6bab33c7 255 BdsLoadOption->LoadOptionSize,\r
256 BdsLoadOption->LoadOption\r
ea46ebbe 257 );\r
258\r
259 return Status;\r
260}\r
261\r
262EFI_STATUS\r
263BootOptionDelete (\r
264 IN BDS_LOAD_OPTION *BootOption\r
265 )\r
266{\r
a6e97d28 267 UINTN Index;\r
268 UINTN BootOrderSize;\r
269 UINT16* BootOrder;\r
270 UINTN BootOrderCount;\r
c41bffd3 271 CHAR16 BootVariableName[9];\r
a6e97d28 272 EFI_STATUS Status;\r
ea46ebbe 273\r
274 // Remove the entry from the BootOrder environment variable\r
c0b2e477 275 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 276 if (!EFI_ERROR(Status)) {\r
277 BootOrderCount = BootOrderSize / sizeof(UINT16);\r
278\r
279 // Find the index of the removed entry\r
280 for (Index = 0; Index < BootOrderCount; Index++) {\r
281 if (BootOrder[Index] == BootOption->LoadOptionIndex) {\r
282 // If it the last entry we do not need to rearrange the BootOrder list\r
283 if (Index + 1 != BootOrderCount) {\r
9127a094 284 CopyMem (\r
285 &BootOrder[Index],\r
286 &BootOrder[Index + 1],\r
287 (BootOrderCount - (Index + 1)) * sizeof(UINT16)\r
288 );\r
ea46ebbe 289 }\r
290 break;\r
291 }\r
292 }\r
293\r
294 // Update the BootOrder environment variable\r
295 Status = gRT->SetVariable (\r
296 L"BootOrder",\r
297 &gEfiGlobalVariableGuid,\r
298 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
299 BootOrderSize - sizeof(UINT16),\r
300 BootOrder\r
301 );\r
302 }\r
303\r
c41bffd3
HL
304 // Delete Boot#### environment variable\r
305 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
306 Status = gRT->SetVariable (\r
307 BootVariableName,\r
308 &gEfiGlobalVariableGuid,\r
309 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
310 0,\r
311 NULL\r
312 );\r
313\r
b148591a 314 FreePool (BootOrder);\r
315\r
c41bffd3 316 return Status;\r
ea46ebbe 317}\r