]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BootOption.c
ArmPkg/BdsLib: Remove Linux loader from BdsLib
[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
c60ea9a8 23 EFI_STATUS Status;\r
c60ea9a8 24 UINT32 LoaderType;\r
2ccfb71e 25 ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;\r
91213ad3 26 UINT16 LoadOptionIndexSize;\r
2ccfb71e 27\r
a6e97d28 28 if (IS_ARM_BDS_BOOTENTRY (BootOption)) {\r
2ccfb71e 29 Status = EFI_UNSUPPORTED;\r
30 OptionalData = BootOption->OptionalData;\r
31 LoaderType = ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);\r
32\r
33 if (LoaderType == BDS_LOADER_EFI_APPLICATION) {\r
5c670b21 34 if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) {\r
4c8bb1eb
OM
35 // Need to connect every drivers to ensure no dependencies are missing for the application\r
36 BdsConnectAllDrivers ();\r
37 }\r
2ccfb71e 38\r
c3b6d975 39 Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, 0, NULL);\r
2ccfb71e 40 } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
c75d3eb6 41 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
2ccfb71e 42 } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) {\r
c75d3eb6 43 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
a6e97d28 44 }\r
45 } else {\r
4c8bb1eb 46 // Connect all the drivers if the EFI Application is not a EFI OS Loader\r
5c670b21 47 if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) {\r
4c8bb1eb
OM
48 BdsConnectAllDrivers ();\r
49 }\r
50\r
91213ad3 51 // Set BootCurrent variable\r
52 LoadOptionIndexSize = sizeof(UINT16);\r
53 gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
54 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
55 LoadOptionIndexSize, &(BootOption->LoadOptionIndex));\r
56\r
c3b6d975 57 Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData);\r
91213ad3 58\r
59 // Clear BootCurrent variable\r
60 LoadOptionIndexSize = sizeof(UINT16);\r
61 gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
62 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
63 0, NULL);\r
a6e97d28 64 }\r
ea46ebbe 65\r
66 return Status;\r
67}\r
68\r
ea46ebbe 69EFI_STATUS\r
70BootOptionList (\r
71 IN OUT LIST_ENTRY *BootOptionList\r
72 )\r
73{\r
a6e97d28 74 EFI_STATUS Status;\r
75 UINTN Index;\r
76 UINT16* BootOrder;\r
77 UINTN BootOrderSize;\r
78 BDS_LOAD_OPTION* BdsLoadOption;\r
79 BDS_LOAD_OPTION_ENTRY* BdsLoadOptionEntry;\r
ea46ebbe 80\r
81 InitializeListHead (BootOptionList);\r
82\r
83 // Get the Boot Option Order from the environment variable\r
c0b2e477 84 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 85 if (EFI_ERROR(Status)) {\r
86 return Status;\r
87 }\r
88\r
89 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
4aa24170 90 Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);\r
ea46ebbe 91 if (!EFI_ERROR(Status)) {\r
a6e97d28 92 BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool(sizeof(BDS_LOAD_OPTION_ENTRY));\r
93 BdsLoadOptionEntry->BdsLoadOption = BdsLoadOption;\r
94 InsertTailList (BootOptionList,&BdsLoadOptionEntry->Link);\r
ea46ebbe 95 }\r
96 }\r
97\r
b148591a 98 FreePool (BootOrder);\r
99\r
ea46ebbe 100 return EFI_SUCCESS;\r
101}\r
102\r
ea46ebbe 103STATIC\r
104EFI_STATUS\r
105BootOptionSetFields (\r
c60ea9a8 106 IN BDS_LOAD_OPTION* BootOption,\r
107 IN UINT32 Attributes,\r
108 IN CHAR16* BootDescription,\r
109 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
2ccfb71e 110 IN ARM_BDS_LOADER_TYPE BootType,\r
90a44ec4
OM
111 IN UINT8* OptionalData,\r
112 IN UINTN OptionalDataSize\r
ea46ebbe 113 )\r
114{\r
459823d9 115 EFI_LOAD_OPTION *EfiLoadOption;\r
2ccfb71e 116 UINTN EfiLoadOptionSize;\r
117 UINTN BootDescriptionSize;\r
2ccfb71e 118 UINT16 FilePathListLength;\r
119 UINT8* EfiLoadOptionPtr;\r
120 UINT8* InitrdPathListPtr;\r
2ccfb71e 121 ARM_BDS_LINUX_ARGUMENTS* DestLinuxArguments;\r
122 ARM_BDS_LINUX_ARGUMENTS* SrcLinuxArguments;\r
90a44ec4 123 ARM_BDS_LOADER_ARGUMENTS* BootArguments;\r
ea46ebbe 124\r
125 // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
126 if (BootOption->LoadOption) {\r
90a44ec4 127 FreePool (BootOption->LoadOption);\r
ea46ebbe 128 }\r
129\r
2ccfb71e 130 BootDescriptionSize = StrSize (BootDescription);\r
90a44ec4
OM
131\r
132 // Fixup the size in case of entry specific to ArmPlatformPkg/Bds\r
2ccfb71e 133 if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
90a44ec4 134 OptionalDataSize += sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER);\r
2ccfb71e 135 }\r
ea46ebbe 136\r
137 // Compute the size of the FilePath list\r
2ccfb71e 138 FilePathListLength = GetUnalignedDevicePathSize (DevicePath);\r
656416bc 139\r
ea46ebbe 140 // Allocate the memory for the EFI Load Option\r
90a44ec4 141 EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + OptionalDataSize;\r
459823d9
AB
142 EfiLoadOption = (EFI_LOAD_OPTION *)AllocatePool(EfiLoadOptionSize);\r
143 EfiLoadOptionPtr = (UINT8 *)EfiLoadOption;\r
ea46ebbe 144\r
145 //\r
146 // Populate the EFI Load Option and BDS Boot Option structures\r
147 //\r
148\r
149 // Attributes fields\r
150 BootOption->Attributes = Attributes;\r
151 *(UINT32*)EfiLoadOptionPtr = Attributes;\r
152 EfiLoadOptionPtr += sizeof(UINT32);\r
153\r
154 // FilePath List fields\r
155 BootOption->FilePathListLength = FilePathListLength;\r
156 *(UINT16*)EfiLoadOptionPtr = FilePathListLength;\r
157 EfiLoadOptionPtr += sizeof(UINT16);\r
158\r
159 // Boot description fields\r
160 BootOption->Description = (CHAR16*)EfiLoadOptionPtr;\r
161 CopyMem (EfiLoadOptionPtr, BootDescription, BootDescriptionSize);\r
162 EfiLoadOptionPtr += BootDescriptionSize;\r
163\r
164 // File path fields\r
165 BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr;\r
2ccfb71e 166 CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength);\r
167 EfiLoadOptionPtr += FilePathListLength;\r
ea46ebbe 168\r
169 // Optional Data fields, Do unaligned writes\r
2ccfb71e 170 BootOption->OptionalData = EfiLoadOptionPtr;\r
ea46ebbe 171\r
2ccfb71e 172 if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
90a44ec4
OM
173 // Write the header\r
174 WriteUnaligned32 ((UINT32 *)EfiLoadOptionPtr, ARM_BDS_OPTIONAL_DATA_SIGNATURE);\r
175 WriteUnaligned32 ((UINT32 *)(EfiLoadOptionPtr + 4), BootType);\r
176\r
b4c22265
OM
177 // OptionalData should have been initialized by the caller of this function\r
178 ASSERT (OptionalData != NULL);\r
90a44ec4 179 BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)OptionalData;\r
2ccfb71e 180 SrcLinuxArguments = &(BootArguments->LinuxArguments);\r
181 DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments;\r
656416bc 182\r
2ccfb71e 183 WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize);\r
184 WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize);\r
656416bc 185\r
2ccfb71e 186 if (SrcLinuxArguments->CmdLineSize > 0) {\r
187 CopyMem ((VOID*)(DestLinuxArguments + 1), (VOID*)(SrcLinuxArguments + 1), SrcLinuxArguments->CmdLineSize);\r
2ccfb71e 188 }\r
656416bc 189\r
2ccfb71e 190 if (SrcLinuxArguments->InitrdSize > 0) {\r
191 InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize);\r
192 CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize);\r
656416bc 193 }\r
90a44ec4 194 } else {\r
b4c22265
OM
195 if (OptionalData != NULL) {\r
196 CopyMem (BootOption->OptionalData, OptionalData, OptionalDataSize);\r
197 }\r
656416bc 198 }\r
2ccfb71e 199 BootOption->OptionalDataSize = OptionalDataSize;\r
200\r
6bab33c7 201 // If this function is called at the creation of the Boot Device entry (not at the update) the\r
202 // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
203 if (BootOption->LoadOptionSize == 0) {\r
2ccfb71e 204 BootOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
6bab33c7 205 }\r
206\r
ea46ebbe 207 // Fill the EFI Load option fields\r
ea46ebbe 208 BootOption->LoadOption = EfiLoadOption;\r
209 BootOption->LoadOptionSize = EfiLoadOptionSize;\r
210\r
211 return EFI_SUCCESS;\r
212}\r
213\r
214EFI_STATUS\r
215BootOptionCreate (\r
c60ea9a8 216 IN UINT32 Attributes,\r
217 IN CHAR16* BootDescription,\r
ea46ebbe 218 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
2ccfb71e 219 IN ARM_BDS_LOADER_TYPE BootType,\r
90a44ec4
OM
220 IN UINT8* OptionalData,\r
221 IN UINTN OptionalDataSize,\r
a6e97d28 222 OUT BDS_LOAD_OPTION** BdsLoadOption\r
ea46ebbe 223 )\r
224{\r
a6e97d28 225 EFI_STATUS Status;\r
226 BDS_LOAD_OPTION_ENTRY* BootOptionEntry;\r
227 BDS_LOAD_OPTION* BootOption;\r
228 CHAR16 BootVariableName[9];\r
229 UINT16* BootOrder;\r
230 UINTN BootOrderSize;\r
ea46ebbe 231\r
232 //\r
233 // Allocate and fill the memory for the BDS Load Option structure\r
234 //\r
a6e97d28 235 BootOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof (BDS_LOAD_OPTION_ENTRY));\r
236 InitializeListHead (&BootOptionEntry->Link);\r
237 BootOptionEntry->BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
ea46ebbe 238\r
a6e97d28 239 BootOption = BootOptionEntry->BdsLoadOption;\r
90a44ec4 240 BootOptionSetFields (BootOption, Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize);\r
ea46ebbe 241\r
242 //\r
243 // Set the related environment variables\r
244 //\r
245\r
246 // Create Boot#### environment variable\r
247 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
248 Status = gRT->SetVariable (\r
249 BootVariableName,\r
250 &gEfiGlobalVariableGuid,\r
251 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
252 BootOption->LoadOptionSize,\r
253 BootOption->LoadOption\r
254 );\r
255\r
256 // Add the new Boot Index to the list\r
c0b2e477 257 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 258 if (!EFI_ERROR(Status)) {\r
259 BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
260 // Add the new index at the end\r
261 BootOrder[BootOrderSize / sizeof(UINT16)] = BootOption->LoadOptionIndex;\r
262 BootOrderSize += sizeof(UINT16);\r
263 } else {\r
264 // BootOrder does not exist. Create it\r
265 BootOrderSize = sizeof(UINT16);\r
266 BootOrder = &(BootOption->LoadOptionIndex);\r
267 }\r
268\r
269 // Update (or Create) the BootOrder environment variable\r
270 Status = gRT->SetVariable (\r
271 L"BootOrder",\r
272 &gEfiGlobalVariableGuid,\r
273 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
274 BootOrderSize,\r
275 BootOrder\r
276 );\r
277\r
b148591a 278 // We only free it if the UEFI Variable 'BootOrder' was already existing\r
279 if (BootOrderSize > sizeof(UINT16)) {\r
280 FreePool (BootOrder);\r
281 }\r
282\r
ea46ebbe 283 *BdsLoadOption = BootOption;\r
284 return Status;\r
285}\r
286\r
287EFI_STATUS\r
288BootOptionUpdate (\r
2ccfb71e 289 IN BDS_LOAD_OPTION* BdsLoadOption,\r
290 IN UINT32 Attributes,\r
291 IN CHAR16* BootDescription,\r
ea46ebbe 292 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
2ccfb71e 293 IN ARM_BDS_LOADER_TYPE BootType,\r
90a44ec4
OM
294 IN UINT8* OptionalData,\r
295 IN UINTN OptionalDataSize\r
ea46ebbe 296 )\r
297{\r
298 EFI_STATUS Status;\r
ea46ebbe 299 CHAR16 BootVariableName[9];\r
300\r
301 // Update the BDS Load Option structure\r
90a44ec4 302 BootOptionSetFields (BdsLoadOption, Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize);\r
ea46ebbe 303\r
304 // Update the related environment variables\r
6bab33c7 305 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
306\r
ea46ebbe 307 Status = gRT->SetVariable (\r
308 BootVariableName,\r
309 &gEfiGlobalVariableGuid,\r
310 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
6bab33c7 311 BdsLoadOption->LoadOptionSize,\r
312 BdsLoadOption->LoadOption\r
ea46ebbe 313 );\r
314\r
315 return Status;\r
316}\r
317\r
318EFI_STATUS\r
319BootOptionDelete (\r
320 IN BDS_LOAD_OPTION *BootOption\r
321 )\r
322{\r
a6e97d28 323 UINTN Index;\r
324 UINTN BootOrderSize;\r
325 UINT16* BootOrder;\r
326 UINTN BootOrderCount;\r
c41bffd3 327 CHAR16 BootVariableName[9];\r
a6e97d28 328 EFI_STATUS Status;\r
ea46ebbe 329\r
330 // Remove the entry from the BootOrder environment variable\r
c0b2e477 331 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
ea46ebbe 332 if (!EFI_ERROR(Status)) {\r
333 BootOrderCount = BootOrderSize / sizeof(UINT16);\r
334\r
335 // Find the index of the removed entry\r
336 for (Index = 0; Index < BootOrderCount; Index++) {\r
337 if (BootOrder[Index] == BootOption->LoadOptionIndex) {\r
338 // If it the last entry we do not need to rearrange the BootOrder list\r
339 if (Index + 1 != BootOrderCount) {\r
9127a094 340 CopyMem (\r
341 &BootOrder[Index],\r
342 &BootOrder[Index + 1],\r
343 (BootOrderCount - (Index + 1)) * sizeof(UINT16)\r
344 );\r
ea46ebbe 345 }\r
346 break;\r
347 }\r
348 }\r
349\r
350 // Update the BootOrder environment variable\r
351 Status = gRT->SetVariable (\r
352 L"BootOrder",\r
353 &gEfiGlobalVariableGuid,\r
354 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
355 BootOrderSize - sizeof(UINT16),\r
356 BootOrder\r
357 );\r
358 }\r
359\r
c41bffd3
HL
360 // Delete Boot#### environment variable\r
361 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
362 Status = gRT->SetVariable (\r
363 BootVariableName,\r
364 &gEfiGlobalVariableGuid,\r
365 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
366 0,\r
367 NULL\r
368 );\r
369\r
b148591a 370 FreePool (BootOrder);\r
371\r
c41bffd3 372 return Status;\r
ea46ebbe 373}\r