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