]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/BdsLib/BdsLoadOption.c
ArmPkg/BdsLib: Increase fallback tftp buffer size
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsLoadOption.c
CommitLineData
1e57a462 1/** @file\r
2*\r
c0b2e477 3* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
1e57a462 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
18BootOptionParseLoadOption (\r
459823d9 19 IN EFI_LOAD_OPTION *EfiLoadOption,\r
1e57a462 20 IN UINTN EfiLoadOptionSize,\r
21 IN OUT BDS_LOAD_OPTION **BdsLoadOption\r
22 )\r
23{\r
24 BDS_LOAD_OPTION *LoadOption;\r
25 UINTN DescriptionLength;\r
459823d9 26 UINTN EfiLoadOptionPtr;\r
1e57a462 27\r
28 if (EfiLoadOption == NULL) {\r
29 return EFI_INVALID_PARAMETER;\r
30 }\r
31\r
32 if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {\r
33 return EFI_BAD_BUFFER_SIZE;\r
34 }\r
35\r
36 if (*BdsLoadOption == NULL) {\r
37 LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
38 if (LoadOption == NULL) {\r
39 return EFI_OUT_OF_RESOURCES;\r
40 }\r
41 } else {\r
42 LoadOption = *BdsLoadOption;\r
43 }\r
44\r
459823d9 45 EfiLoadOptionPtr = (UINTN)EfiLoadOption;\r
1e57a462 46 LoadOption->LoadOption = EfiLoadOption;\r
47 LoadOption->LoadOptionSize = EfiLoadOptionSize;\r
48\r
459823d9
AB
49 LoadOption->Attributes = *(UINT32*)EfiLoadOptionPtr;\r
50 LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOptionPtr + sizeof(UINT32));\r
51 LoadOption->Description = (CHAR16*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16));\r
1e57a462 52 DescriptionLength = StrSize (LoadOption->Description);\r
459823d9 53 LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);\r
1e57a462 54\r
55 // If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data\r
459823d9 56 if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - EfiLoadOptionPtr) == EfiLoadOptionSize) {\r
1e57a462 57 LoadOption->OptionalData = NULL;\r
58 LoadOption->OptionalDataSize = 0;\r
59 } else {\r
60 LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);\r
459823d9 61 LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - EfiLoadOptionPtr);\r
1e57a462 62 }\r
63\r
64 if (*BdsLoadOption == NULL) {\r
65 *BdsLoadOption = LoadOption;\r
66 }\r
67\r
68 return EFI_SUCCESS;\r
69}\r
70\r
71EFI_STATUS\r
72BootOptionFromLoadOptionVariable (\r
73 IN CHAR16* BootVariableName,\r
74 OUT BDS_LOAD_OPTION** BdsLoadOption\r
75 )\r
76{\r
77 EFI_STATUS Status;\r
459823d9 78 EFI_LOAD_OPTION *EfiLoadOption;\r
1e57a462 79 UINTN EfiLoadOptionSize;\r
80\r
c0b2e477 81 Status = GetGlobalEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);\r
1e57a462 82 if (!EFI_ERROR(Status)) {\r
83 *BdsLoadOption = NULL;\r
84 Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);\r
85 }\r
86\r
87 return Status;\r
88}\r
89\r
90EFI_STATUS\r
91BootOptionFromLoadOptionIndex (\r
92 IN UINT16 LoadOptionIndex,\r
93 OUT BDS_LOAD_OPTION **BdsLoadOption\r
94 )\r
95{\r
96 CHAR16 BootVariableName[9];\r
97 EFI_STATUS Status;\r
98\r
99 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);\r
100\r
101 Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);\r
102 if (!EFI_ERROR(Status)) {\r
103 (*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;\r
104 }\r
105\r
106 return Status;\r
107}\r
108\r
109EFI_STATUS\r
110BootOptionToLoadOptionVariable (\r
111 IN BDS_LOAD_OPTION* BdsLoadOption\r
112 )\r
113{\r
114 EFI_STATUS Status;\r
115 UINTN DescriptionSize;\r
116 //UINT16 FilePathListLength;\r
117 EFI_DEVICE_PATH_PROTOCOL* DevicePathNode;\r
118 UINTN NodeLength;\r
119 UINT8* EfiLoadOptionPtr;\r
120 VOID* OldLoadOption;\r
121 CHAR16 BootVariableName[9];\r
122 UINTN BootOrderSize;\r
123 UINT16* BootOrder;\r
124\r
125 // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
126 if (BdsLoadOption->LoadOptionSize > 0) {\r
127 OldLoadOption = BdsLoadOption->LoadOption;\r
128 } else {\r
129 OldLoadOption = NULL;\r
130\r
131 // If this function is called at the creation of the Boot Device entry (not at the update) the\r
132 // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
133 BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
134\r
135 //TODO: Add to the the Boot Entry List\r
136 }\r
137\r
138 DescriptionSize = StrSize(BdsLoadOption->Description);\r
139\r
140 // Ensure the FilePathListLength information is correct\r
141 ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);\r
142\r
143 // Allocate the memory for the EFI Load Option\r
144 BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;\r
145\r
459823d9 146 BdsLoadOption->LoadOption = (EFI_LOAD_OPTION *)AllocateZeroPool (BdsLoadOption->LoadOptionSize);\r
1e57a462 147 if (BdsLoadOption->LoadOption == NULL) {\r
148 return EFI_OUT_OF_RESOURCES;\r
149 }\r
150\r
459823d9 151 EfiLoadOptionPtr = (UINT8 *) BdsLoadOption->LoadOption;\r
1e57a462 152\r
153 //\r
154 // Populate the EFI Load Option and BDS Boot Option structures\r
155 //\r
156\r
157 // Attributes fields\r
158 *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;\r
159 EfiLoadOptionPtr += sizeof(UINT32);\r
160\r
161 // FilePath List fields\r
162 *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;\r
163 EfiLoadOptionPtr += sizeof(UINT16);\r
164\r
165 // Boot description fields\r
166 CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);\r
167 EfiLoadOptionPtr += DescriptionSize;\r
168\r
169 // File path fields\r
170 DevicePathNode = BdsLoadOption->FilePathList;\r
171 while (!IsDevicePathEndType (DevicePathNode)) {\r
172 NodeLength = DevicePathNodeLength(DevicePathNode);\r
173 CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);\r
174 EfiLoadOptionPtr += NodeLength;\r
175 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
176 }\r
177\r
178 // Set the End Device Path Type\r
179 SetDevicePathEndNode (EfiLoadOptionPtr);\r
180 EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);\r
181\r
182 // Fill the Optional Data\r
183 if (BdsLoadOption->OptionalDataSize > 0) {\r
184 CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);\r
185 }\r
186\r
187 // Case where the fields have been updated\r
188 if (OldLoadOption) {\r
189 // Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption\r
190 BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);\r
191 // Free the old packed structure\r
192 FreePool (OldLoadOption);\r
193 }\r
194\r
195 // Create/Update Boot#### environment variable\r
196 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
197 Status = gRT->SetVariable (\r
198 BootVariableName,\r
199 &gEfiGlobalVariableGuid,\r
200 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
201 BdsLoadOption->LoadOptionSize,\r
202 BdsLoadOption->LoadOption\r
203 );\r
204\r
205 // When it is a new entry we must add the entry to the BootOrder\r
206 if (OldLoadOption == NULL) {\r
207 // Add the new Boot Index to the list\r
c0b2e477 208 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
1e57a462 209 if (!EFI_ERROR(Status)) {\r
210 BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
211 // Add the new index at the end\r
212 BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;\r
213 BootOrderSize += sizeof(UINT16);\r
214 } else {\r
215 // BootOrder does not exist. Create it\r
216 BootOrderSize = sizeof(UINT16);\r
217 BootOrder = &(BdsLoadOption->LoadOptionIndex);\r
218 }\r
219\r
220 // Update (or Create) the BootOrder environment variable\r
221 gRT->SetVariable (\r
222 L"BootOrder",\r
223 &gEfiGlobalVariableGuid,\r
224 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
225 BootOrderSize,\r
226 BootOrder\r
227 );\r
228 DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));\r
229\r
c0b2e477 230 // Free memory allocated by GetGlobalEnvironmentVariable\r
1e57a462 231 if (!EFI_ERROR(Status)) {\r
232 FreePool (BootOrder);\r
233 }\r
234 } else {\r
235 DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));\r
236 }\r
237\r
238 return EFI_SUCCESS;\r
239}\r
240\r
241UINT16\r
242BootOptionAllocateBootIndex (\r
243 VOID\r
244 )\r
245{\r
246 EFI_STATUS Status;\r
247 UINTN Index;\r
248 UINT32 BootIndex;\r
249 UINT16 *BootOrder;\r
250 UINTN BootOrderSize;\r
251 BOOLEAN Found;\r
252\r
253 // Get the Boot Option Order from the environment variable\r
c0b2e477 254 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
1e57a462 255 if (!EFI_ERROR(Status)) {\r
256 for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {\r
257 Found = FALSE;\r
258 for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
259 if (BootOrder[Index] == BootIndex) {\r
260 Found = TRUE;\r
261 break;\r
262 }\r
263 }\r
264 if (!Found) {\r
265 return BootIndex;\r
266 }\r
267 }\r
268 FreePool (BootOrder);\r
269 }\r
270 // Return the first index\r
271 return 0;\r
272}\r