]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/BdsLib/BdsFilePath.c
ArmPkg/ArmCacheMaintenanceLib: Fixed comment (and coding style)
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsFilePath.c
CommitLineData
1e57a462 1/** @file\r
2*\r
d8f36fb5 3* Copyright (c) 2011-2014, 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
17#include <Protocol/UsbIo.h>\r
18#include <Protocol/DiskIo.h>\r
19#include <Protocol/LoadedImage.h>\r
2edb5ad3 20#include <Protocol/SimpleNetwork.h>\r
1e57a462 21\r
22#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))\r
23\r
24// Extract the FilePath from the Device Path\r
25CHAR16*\r
26BdsExtractFilePathFromDevicePath (\r
27 IN CONST CHAR16 *StrDevicePath,\r
28 IN UINTN NumberDevicePathNode\r
29 )\r
30{\r
31 UINTN Node;\r
32 CHAR16 *Str;\r
33\r
34 Str = (CHAR16*)StrDevicePath;\r
35 Node = 0;\r
36 while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {\r
37 if ((*Str == L'/') || (*Str == L'\\')) {\r
38 Node++;\r
39 }\r
40 Str++;\r
41 }\r
42\r
43 if (*Str == L'\0') {\r
44 return NULL;\r
45 } else {\r
46 return Str;\r
47 }\r
48}\r
49\r
50BOOLEAN\r
51BdsIsRemovableUsb (\r
52 IN EFI_DEVICE_PATH* DevicePath\r
53 )\r
54{\r
55 return ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&\r
56 ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) ||\r
57 (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)));\r
58}\r
59\r
60EFI_STATUS\r
61BdsGetDeviceUsb (\r
62 IN EFI_DEVICE_PATH* RemovableDevicePath,\r
63 OUT EFI_HANDLE* DeviceHandle,\r
64 OUT EFI_DEVICE_PATH** NewDevicePath\r
65 )\r
66{\r
67 EFI_STATUS Status;\r
68 UINTN Index;\r
69 UINTN UsbIoHandleCount;\r
70 EFI_HANDLE *UsbIoBuffer;\r
71 EFI_DEVICE_PATH* UsbIoDevicePath;\r
72 EFI_DEVICE_PATH* TmpDevicePath;\r
73 USB_WWID_DEVICE_PATH* WwidDevicePath1;\r
74 USB_WWID_DEVICE_PATH* WwidDevicePath2;\r
75 USB_CLASS_DEVICE_PATH* UsbClassDevicePath1;\r
76 USB_CLASS_DEVICE_PATH* UsbClassDevicePath2;\r
77\r
78 // Get all the UsbIo handles\r
79 UsbIoHandleCount = 0;\r
80 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);\r
6f711615 81 if (EFI_ERROR (Status) || (UsbIoHandleCount == 0)) {\r
1e57a462 82 return Status;\r
83 }\r
84\r
85 // Check if one of the handles matches the USB description\r
86 for (Index = 0; Index < UsbIoHandleCount; Index++) {\r
87 Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbIoDevicePath);\r
6f711615 88 if (!EFI_ERROR (Status)) {\r
1e57a462 89 TmpDevicePath = UsbIoDevicePath;\r
90 while (!IsDevicePathEnd (TmpDevicePath)) {\r
91 // Check if the Device Path node is a USB Removable device Path node\r
92 if (BdsIsRemovableUsb (TmpDevicePath)) {\r
93 if (TmpDevicePath->SubType == MSG_USB_WWID_DP) {\r
94 WwidDevicePath1 = (USB_WWID_DEVICE_PATH*)RemovableDevicePath;\r
95 WwidDevicePath2 = (USB_WWID_DEVICE_PATH*)TmpDevicePath;\r
96 if ((WwidDevicePath1->VendorId == WwidDevicePath2->VendorId) &&\r
97 (WwidDevicePath1->ProductId == WwidDevicePath2->ProductId) &&\r
6f711615 98 (CompareMem (WwidDevicePath1+1, WwidDevicePath2+1, DevicePathNodeLength(WwidDevicePath1)-sizeof (USB_WWID_DEVICE_PATH)) == 0))\r
1e57a462 99 {\r
100 *DeviceHandle = UsbIoBuffer[Index];\r
101 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
6f711615 102 *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath));\r
1e57a462 103 return EFI_SUCCESS;\r
104 }\r
105 } else {\r
106 UsbClassDevicePath1 = (USB_CLASS_DEVICE_PATH*)RemovableDevicePath;\r
107 UsbClassDevicePath2 = (USB_CLASS_DEVICE_PATH*)TmpDevicePath;\r
108 if ((UsbClassDevicePath1->VendorId != 0xFFFF) && (UsbClassDevicePath1->VendorId == UsbClassDevicePath2->VendorId) &&\r
109 (UsbClassDevicePath1->ProductId != 0xFFFF) && (UsbClassDevicePath1->ProductId == UsbClassDevicePath2->ProductId) &&\r
110 (UsbClassDevicePath1->DeviceClass != 0xFF) && (UsbClassDevicePath1->DeviceClass == UsbClassDevicePath2->DeviceClass) &&\r
111 (UsbClassDevicePath1->DeviceSubClass != 0xFF) && (UsbClassDevicePath1->DeviceSubClass == UsbClassDevicePath2->DeviceSubClass) &&\r
112 (UsbClassDevicePath1->DeviceProtocol != 0xFF) && (UsbClassDevicePath1->DeviceProtocol == UsbClassDevicePath2->DeviceProtocol))\r
113 {\r
114 *DeviceHandle = UsbIoBuffer[Index];\r
115 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
6f711615 116 *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath));\r
1e57a462 117 return EFI_SUCCESS;\r
118 }\r
119 }\r
120 }\r
121 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
122 }\r
123\r
124 }\r
125 }\r
126\r
127 return EFI_NOT_FOUND;\r
128}\r
129\r
130BOOLEAN\r
131BdsIsRemovableHd (\r
132 IN EFI_DEVICE_PATH* DevicePath\r
133 )\r
134{\r
6f711615 135 return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP);\r
1e57a462 136}\r
137\r
138EFI_STATUS\r
139BdsGetDeviceHd (\r
140 IN EFI_DEVICE_PATH* RemovableDevicePath,\r
141 OUT EFI_HANDLE* DeviceHandle,\r
142 OUT EFI_DEVICE_PATH** NewDevicePath\r
143 )\r
144{\r
145 EFI_STATUS Status;\r
146 UINTN Index;\r
147 UINTN PartitionHandleCount;\r
148 EFI_HANDLE *PartitionBuffer;\r
149 EFI_DEVICE_PATH* PartitionDevicePath;\r
150 EFI_DEVICE_PATH* TmpDevicePath;\r
151 HARDDRIVE_DEVICE_PATH* HardDriveDevicePath1;\r
152 HARDDRIVE_DEVICE_PATH* HardDriveDevicePath2;\r
153\r
154 // Get all the DiskIo handles\r
155 PartitionHandleCount = 0;\r
156 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer);\r
6f711615 157 if (EFI_ERROR (Status) || (PartitionHandleCount == 0)) {\r
1e57a462 158 return Status;\r
159 }\r
160\r
161 // Check if one of the handles matches the Hard Disk Description\r
162 for (Index = 0; Index < PartitionHandleCount; Index++) {\r
163 Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath);\r
6f711615 164 if (!EFI_ERROR (Status)) {\r
1e57a462 165 TmpDevicePath = PartitionDevicePath;\r
166 while (!IsDevicePathEnd (TmpDevicePath)) {\r
167 // Check if the Device Path node is a HD Removable device Path node\r
168 if (BdsIsRemovableHd (TmpDevicePath)) {\r
169 HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath;\r
170 HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath;\r
171 if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) &&\r
6f711615 172 (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature, (EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) &&\r
1e57a462 173 (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber))\r
174 {\r
175 *DeviceHandle = PartitionBuffer[Index];\r
176 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path\r
6f711615 177 *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode (RemovableDevicePath));\r
1e57a462 178 return EFI_SUCCESS;\r
179 }\r
180 }\r
181 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
182 }\r
183\r
184 }\r
185 }\r
186\r
187 return EFI_NOT_FOUND;\r
188}\r
189\r
190/*BOOLEAN\r
191BdsIsRemovableCdrom (\r
192 IN EFI_DEVICE_PATH* DevicePath\r
193 )\r
194{\r
6f711615 195 return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_CDROM_DP);\r
1e57a462 196}\r
197\r
198EFI_STATUS\r
199BdsGetDeviceCdrom (\r
200 IN EFI_DEVICE_PATH* RemovableDevicePath,\r
201 OUT EFI_HANDLE* DeviceHandle,\r
202 OUT EFI_DEVICE_PATH** DevicePath\r
203 )\r
204{\r
205 ASSERT(0);\r
206 return EFI_UNSUPPORTED;\r
207}*/\r
208\r
209typedef BOOLEAN\r
210(*BDS_IS_REMOVABLE) (\r
211 IN EFI_DEVICE_PATH* DevicePath\r
212 );\r
213\r
214typedef EFI_STATUS\r
215(*BDS_GET_DEVICE) (\r
216 IN EFI_DEVICE_PATH* RemovableDevicePath,\r
217 OUT EFI_HANDLE* DeviceHandle,\r
218 OUT EFI_DEVICE_PATH** DevicePath\r
219 );\r
220\r
221typedef struct {\r
222 BDS_IS_REMOVABLE IsRemovable;\r
223 BDS_GET_DEVICE GetDevice;\r
224} BDS_REMOVABLE_DEVICE_SUPPORT;\r
225\r
226BDS_REMOVABLE_DEVICE_SUPPORT RemovableDeviceSupport[] = {\r
227 { BdsIsRemovableUsb, BdsGetDeviceUsb },\r
228 { BdsIsRemovableHd, BdsGetDeviceHd },\r
229 //{ BdsIsRemovableCdrom, BdsGetDeviceCdrom }\r
230};\r
231\r
232STATIC\r
233BOOLEAN\r
234IsRemovableDevice (\r
235 IN EFI_DEVICE_PATH* DevicePath\r
236 )\r
237{\r
238 UINTN Index;\r
239 EFI_DEVICE_PATH* TmpDevicePath;\r
240\r
241 TmpDevicePath = DevicePath;\r
242 while (!IsDevicePathEnd (TmpDevicePath)) {\r
6f711615 243 for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {\r
244 if (RemovableDeviceSupport[Index].IsRemovable (TmpDevicePath)) {\r
1e57a462 245 return TRUE;\r
246 }\r
247 }\r
248 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
249 }\r
250\r
251 return FALSE;\r
252}\r
253\r
254STATIC\r
255EFI_STATUS\r
256TryRemovableDevice (\r
257 IN EFI_DEVICE_PATH* DevicePath,\r
258 OUT EFI_HANDLE* DeviceHandle,\r
259 OUT EFI_DEVICE_PATH** NewDevicePath\r
260 )\r
261{\r
262 EFI_STATUS Status;\r
263 UINTN Index;\r
264 EFI_DEVICE_PATH* TmpDevicePath;\r
265 BDS_REMOVABLE_DEVICE_SUPPORT* RemovableDevice;\r
266 EFI_DEVICE_PATH* RemovableDevicePath;\r
267 BOOLEAN RemovableFound;\r
268\r
269 RemovableDevice = NULL;\r
270 RemovableDevicePath = NULL;\r
271 RemovableFound = FALSE;\r
272 TmpDevicePath = DevicePath;\r
273\r
274 while (!IsDevicePathEnd (TmpDevicePath) && !RemovableFound) {\r
6f711615 275 for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {\r
1e57a462 276 RemovableDevice = &RemovableDeviceSupport[Index];\r
6f711615 277 if (RemovableDevice->IsRemovable (TmpDevicePath)) {\r
1e57a462 278 RemovableDevicePath = TmpDevicePath;\r
279 RemovableFound = TRUE;\r
280 break;\r
281 }\r
282 }\r
283 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
284 }\r
285\r
286 if (!RemovableFound) {\r
287 return EFI_NOT_FOUND;\r
288 }\r
289\r
290 // Search into the current started drivers\r
291 Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);\r
292 if (Status == EFI_NOT_FOUND) {\r
293 // Connect all the drivers\r
294 BdsConnectAllDrivers ();\r
295\r
296 // Search again into all the drivers\r
297 Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);\r
298 }\r
299\r
300 return Status;\r
301}\r
302\r
10ddca8d 303STATIC
1e57a462 304EFI_STATUS\r
10ddca8d
MS
305BdsConnectAndUpdateDevicePath (
306 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
307 OUT EFI_HANDLE *Handle,
308 OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath
1e57a462 309 )\r
310{\r
311 EFI_DEVICE_PATH* Remaining;\r
312 EFI_DEVICE_PATH* NewDevicePath;\r
313 EFI_STATUS Status;\r
314\r
10ddca8d 315 if ((DevicePath == NULL) || (*DevicePath == NULL) || (Handle == NULL)) {
1e57a462 316 return EFI_INVALID_PARAMETER;\r
317 }\r
318\r
319 do {\r
10ddca8d 320 Remaining = *DevicePath;
1e57a462 321 // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns\r
322 // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified\r
323 // to point to the remaining part of the device path\r
324 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);\r
325 if (!EFI_ERROR (Status)) {\r
326 // Recursive = FALSE: We do not want to start all the device tree\r
327 Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
328 }\r
329\r
330 /*// We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling\r
6f711615 331 // NextDevicePathNode () will return an undetermined Device Path Node\r
1e57a462 332 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
333 RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);\r
334 }*/\r
335 } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining));\r
336\r
337 if (!EFI_ERROR (Status)) {\r
338 // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver\r
339 // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)\r
10ddca8d 340 Remaining = *DevicePath;
6f711615 341 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);\r
1e57a462 342 if (!EFI_ERROR (Status)) {\r
343 Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);\r
344 if (EFI_ERROR (Status)) {\r
345 // If the last node is a Memory Map Device Path just return EFI_SUCCESS.\r
346 if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {\r
347 Status = EFI_SUCCESS;\r
348 }\r
349 }\r
350 }\r
351 } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) {\r
352\r
353 /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly\r
354 if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {\r
355 Status = EFI_SUCCESS;\r
356 } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {\r
357 Status = EFI_SUCCESS;\r
358 }*/\r
359\r
360 //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath\r
361 Status = EFI_SUCCESS;\r
362 } else {\r
10ddca8d 363 Status = TryRemovableDevice (*DevicePath, Handle, &NewDevicePath);
1e57a462 364 if (!EFI_ERROR (Status)) {\r
10ddca8d
MS
365 Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath);
366 *DevicePath = NewDevicePath;
367 return Status;
1e57a462 368 }\r
369 }\r
370\r
371 if (RemainingDevicePath) {\r
372 *RemainingDevicePath = Remaining;\r
373 }\r
374\r
375 return Status;\r
376}\r
377\r
10ddca8d
MS
378/**
379 Connect a Device Path and return the handle of the driver that support this DevicePath
380
381 @param DevicePath Device Path of the File to connect
382 @param Handle Handle of the driver that support this DevicePath
383 @param RemainingDevicePath Remaining DevicePath nodes that do not match the driver DevicePath
384
385 @retval EFI_SUCCESS A driver that matches the Device Path has been found
386 @retval EFI_NOT_FOUND No handles match the search.
387 @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL
388
389**/\r
390EFI_STATUS
391BdsConnectDevicePath (
392 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
393 OUT EFI_HANDLE *Handle,
394 OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath
395 )
396{
397 return BdsConnectAndUpdateDevicePath (&DevicePath, Handle, RemainingDevicePath);
398}
399
1e57a462 400BOOLEAN\r
401BdsFileSystemSupport (\r
402 IN EFI_DEVICE_PATH *DevicePath,\r
403 IN EFI_HANDLE Handle,\r
404 IN EFI_DEVICE_PATH *RemainingDevicePath\r
405 )\r
406{\r
407 EFI_STATUS Status;\r
408 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;\r
409\r
6f711615 410 Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);\r
1e57a462 411\r
6f711615 412 return (!EFI_ERROR (Status) && IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP));\r
1e57a462 413}\r
414\r
415EFI_STATUS\r
416BdsFileSystemLoadImage (\r
417 IN EFI_DEVICE_PATH *DevicePath,\r
418 IN EFI_HANDLE Handle,\r
419 IN EFI_DEVICE_PATH *RemainingDevicePath,\r
420 IN EFI_ALLOCATE_TYPE Type,\r
421 IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
422 OUT UINTN *ImageSize\r
423 )\r
424{\r
425 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
426 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;\r
427 EFI_FILE_PROTOCOL *Fs;\r
428 EFI_STATUS Status;\r
429 EFI_FILE_INFO *FileInfo;\r
430 EFI_FILE_PROTOCOL *File;\r
431 UINTN Size;\r
432\r
6f711615 433 ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP));\r
1e57a462 434\r
435 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath;\r
436\r
6f711615 437 Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);\r
438 if (EFI_ERROR (Status)) {\r
1e57a462 439 return Status;\r
440 }\r
441\r
442 // Try to Open the volume and get root directory\r
443 Status = FsProtocol->OpenVolume (FsProtocol, &Fs);\r
6f711615 444 if (EFI_ERROR (Status)) {\r
1e57a462 445 return Status;\r
446 }\r
447\r
448 File = NULL;\r
6f711615 449 Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0);\r
450 if (EFI_ERROR (Status)) {\r
1e57a462 451 return Status;\r
452 }\r
453\r
454 Size = 0;\r
6f711615 455 File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);\r
1e57a462 456 FileInfo = AllocatePool (Size);\r
6f711615 457 Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);\r
458 if (EFI_ERROR (Status)) {\r
1e57a462 459 return Status;\r
460 }\r
461\r
462 // Get the file size\r
463 Size = FileInfo->FileSize;\r
464 if (ImageSize) {\r
465 *ImageSize = Size;\r
466 }\r
6f711615 467 FreePool (FileInfo);\r
1e57a462 468\r
469 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
470 // Try to allocate in any pages if failed to allocate memory at the defined location\r
471 if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
472 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
473 }\r
6f711615 474 if (!EFI_ERROR (Status)) {\r
1e57a462 475 Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));\r
476 }\r
477\r
478 return Status;\r
479}\r
480\r
481BOOLEAN\r
482BdsMemoryMapSupport (\r
483 IN EFI_DEVICE_PATH *DevicePath,\r
484 IN EFI_HANDLE Handle,\r
485 IN EFI_DEVICE_PATH *RemainingDevicePath\r
486 )\r
487{\r
6f711615 488 return IS_DEVICE_PATH_NODE (DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP) ||\r
489 IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP);\r
1e57a462 490}\r
491\r
492EFI_STATUS\r
493BdsMemoryMapLoadImage (\r
494 IN EFI_DEVICE_PATH *DevicePath,\r
495 IN EFI_HANDLE Handle,\r
496 IN EFI_DEVICE_PATH *RemainingDevicePath,\r
497 IN EFI_ALLOCATE_TYPE Type,\r
498 IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
499 OUT UINTN *ImageSize\r
500 )\r
501{\r
502 EFI_STATUS Status;\r
503 MEMMAP_DEVICE_PATH* MemMapPathDevicePath;\r
504 UINTN Size;\r
505\r
6f711615 506 if (IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP)) {\r
1e57a462 507 MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)RemainingDevicePath;\r
508 } else {\r
6f711615 509 ASSERT (IS_DEVICE_PATH_NODE (DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP));\r
1e57a462 510 MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)DevicePath;\r
511 }\r
512\r
513 Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress;\r
514 if (Size == 0) {\r
515 return EFI_INVALID_PARAMETER;\r
516 }\r
517\r
518 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
519 // Try to allocate in any pages if failed to allocate memory at the defined location\r
520 if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
521 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image);\r
522 }\r
6f711615 523 if (!EFI_ERROR (Status)) {\r
1e57a462 524 CopyMem ((VOID*)(UINTN)(*Image), (CONST VOID*)(UINTN)MemMapPathDevicePath->StartingAddress, Size);\r
525\r
526 if (ImageSize != NULL) {\r
527 *ImageSize = Size;\r
528 }\r
529 }\r
530\r
531 return Status;\r
532}\r
533\r
534BOOLEAN\r
535BdsFirmwareVolumeSupport (\r
536 IN EFI_DEVICE_PATH *DevicePath,\r
537 IN EFI_HANDLE Handle,\r
538 IN EFI_DEVICE_PATH *RemainingDevicePath\r
539 )\r
540{\r
6f711615 541 return IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP);\r
1e57a462 542}\r
543\r
544EFI_STATUS\r
545BdsFirmwareVolumeLoadImage (\r
546 IN EFI_DEVICE_PATH *DevicePath,\r
547 IN EFI_HANDLE Handle,\r
548 IN EFI_DEVICE_PATH *RemainingDevicePath,\r
549 IN EFI_ALLOCATE_TYPE Type,\r
550 IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
551 OUT UINTN *ImageSize\r
552 )\r
553{\r
554 EFI_STATUS Status;\r
555 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r
556 EFI_GUID *FvNameGuid;\r
557 EFI_SECTION_TYPE SectionType;\r
558 EFI_FV_FILETYPE FvType;\r
559 EFI_FV_FILE_ATTRIBUTES Attrib;\r
560 UINT32 AuthenticationStatus;\r
561 VOID* ImageBuffer;\r
562\r
6f711615 563 ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP));\r
1e57a462 564\r
6f711615 565 Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol);\r
566 if (EFI_ERROR (Status)) {\r
1e57a462 567 return Status;\r
568 }\r
569\r
570 FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)RemainingDevicePath);\r
571 if (FvNameGuid == NULL) {\r
572 Status = EFI_INVALID_PARAMETER;\r
573 }\r
574\r
575 SectionType = EFI_SECTION_PE32;\r
576 AuthenticationStatus = 0;\r
577 //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file.\r
578 ImageBuffer = NULL;\r
579 Status = FwVol->ReadSection (\r
580 FwVol,\r
581 FvNameGuid,\r
582 SectionType,\r
583 0,\r
584 &ImageBuffer,\r
585 ImageSize,\r
586 &AuthenticationStatus\r
587 );\r
588 if (!EFI_ERROR (Status)) {\r
589#if 0\r
590 // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements\r
591 if (Type != AllocateAnyPages) {\r
592 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image);\r
6f711615 593 if (!EFI_ERROR (Status)) {\r
1e57a462 594 CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);\r
595 FreePool (ImageBuffer);\r
596 }\r
597 }\r
598#else\r
599 // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation\r
600 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
601 // Try to allocate in any pages if failed to allocate memory at the defined location\r
602 if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
603 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
604 }\r
6f711615 605 if (!EFI_ERROR (Status)) {\r
1e57a462 606 CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);\r
607 FreePool (ImageBuffer);\r
608 }\r
609#endif\r
610 } else {\r
611 // Try a raw file, since a PE32 SECTION does not exist\r
612 Status = FwVol->ReadFile (\r
613 FwVol,\r
614 FvNameGuid,\r
615 NULL,\r
616 ImageSize,\r
617 &FvType,\r
618 &Attrib,\r
619 &AuthenticationStatus\r
620 );\r
6f711615 621 if (!EFI_ERROR (Status)) {\r
1e57a462 622 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
623 // Try to allocate in any pages if failed to allocate memory at the defined location\r
624 if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) {\r
625 Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);\r
626 }\r
6f711615 627 if (!EFI_ERROR (Status)) {\r
1e57a462 628 Status = FwVol->ReadFile (\r
629 FwVol,\r
630 FvNameGuid,\r
631 (VOID*)(UINTN)(*Image),\r
632 ImageSize,\r
633 &FvType,\r
634 &Attrib,\r
635 &AuthenticationStatus\r
636 );\r
637 }\r
638 }\r
639 }\r
640 return Status;\r
641}\r
642\r
643BOOLEAN\r
644BdsPxeSupport (\r
645 IN EFI_DEVICE_PATH* DevicePath,\r
646 IN EFI_HANDLE Handle,\r
647 IN EFI_DEVICE_PATH* RemainingDevicePath\r
648 )\r
649{\r
650 EFI_STATUS Status;\r
651 EFI_PXE_BASE_CODE_PROTOCOL* PxeBcProtocol;\r
652\r
6f711615 653 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
1e57a462 654 return FALSE;\r
655 }\r
656\r
657 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
658 if (EFI_ERROR (Status)) {\r
659 return FALSE;\r
660 } else {\r
661 return TRUE;\r
662 }\r
663}\r
664\r
665EFI_STATUS\r
666BdsPxeLoadImage (\r
667 IN EFI_DEVICE_PATH* DevicePath,\r
668 IN EFI_HANDLE Handle,\r
669 IN EFI_DEVICE_PATH* RemainingDevicePath,\r
670 IN EFI_ALLOCATE_TYPE Type,\r
671 IN OUT EFI_PHYSICAL_ADDRESS *Image,\r
672 OUT UINTN *ImageSize\r
673 )\r
674{\r
675 EFI_STATUS Status;\r
676 EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol;\r
677 UINTN BufferSize;\r
2edb5ad3 678 EFI_PXE_BASE_CODE_PROTOCOL *Pxe;\r
1e57a462 679\r
680 // Get Load File Protocol attached to the PXE protocol\r
681 Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol);\r
682 if (EFI_ERROR (Status)) {\r
683 return Status;\r
684 }\r
685\r
686 Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, NULL);\r
687 if (Status == EFI_BUFFER_TOO_SMALL) {\r
688 Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(BufferSize), Image);\r
6f711615 689 if (EFI_ERROR (Status)) {\r
1e57a462 690 return Status;\r
691 }\r
692\r
693 Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image));\r
6f711615 694 if (!EFI_ERROR (Status) && (ImageSize != NULL)) {\r
1e57a462 695 *ImageSize = BufferSize;\r
696 }\r
697 }\r
698\r
2edb5ad3 699 if (Status == EFI_ALREADY_STARTED) {\r
700 Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);\r
701 if (!EFI_ERROR(Status)) {\r
702 // If PXE is already started, we stop it\r
703 Pxe->Stop (Pxe);\r
704 // And we try again\r
705 return BdsPxeLoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, ImageSize);\r
706 }\r
707 }\r
1e57a462 708 return Status;\r
709}\r
710\r
711BOOLEAN\r
712BdsTftpSupport (\r
713 IN EFI_DEVICE_PATH* DevicePath,\r
714 IN EFI_HANDLE Handle,\r
715 IN EFI_DEVICE_PATH* RemainingDevicePath\r
716 )\r
717{\r
718 EFI_STATUS Status;\r
719 EFI_DEVICE_PATH *NextDevicePath;\r
720 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
721\r
722 // Validate the Remaining Device Path\r
6f711615 723 if (IsDevicePathEnd (RemainingDevicePath)) {\r
1e57a462 724 return FALSE;\r
725 }\r
6f711615 726 if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP) &&\r
727 !IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv6_DP)) {\r
1e57a462 728 return FALSE;\r
729 }\r
730 NextDevicePath = NextDevicePathNode (RemainingDevicePath);\r
6f711615 731 if (IsDevicePathEnd (NextDevicePath)) {\r
1e57a462 732 return FALSE;\r
733 }\r
6f711615 734 if (!IS_DEVICE_PATH_NODE (NextDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) {\r
1e57a462 735 return FALSE;\r
736 }\r
737\r
738 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
739 if (EFI_ERROR (Status)) {\r
740 return FALSE;\r
741 } else {\r
742 return TRUE;\r
743 }\r
744}\r
745\r
746EFI_STATUS\r
747BdsTftpLoadImage (\r
748 IN EFI_DEVICE_PATH* DevicePath,\r
749 IN EFI_HANDLE Handle,\r
750 IN EFI_DEVICE_PATH* RemainingDevicePath,\r
751 IN EFI_ALLOCATE_TYPE Type,\r
752 IN OUT EFI_PHYSICAL_ADDRESS *Image,\r
753 OUT UINTN *ImageSize\r
754 )\r
755{\r
756 EFI_STATUS Status;\r
757 EFI_PXE_BASE_CODE_PROTOCOL *Pxe;\r
758 UINT64 TftpBufferSize;\r
1e57a462 759 EFI_IP_ADDRESS ServerIp;\r
760 IPv4_DEVICE_PATH* IPv4DevicePathNode;\r
761 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
762 EFI_IP_ADDRESS LocalIp;\r
2edb5ad3 763 CHAR8* AsciiPathName;\r
764 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1e57a462 765\r
6f711615 766 ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));\r
1e57a462 767\r
768 IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;\r
769 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);\r
770\r
771 Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);\r
6f711615 772 if (EFI_ERROR (Status)) {\r
1e57a462 773 return Status;\r
774 }\r
775\r
776 Status = Pxe->Start (Pxe, FALSE);\r
6f711615 777 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
1e57a462 778 return Status;\r
779 }\r
780\r
2edb5ad3 781 do {\r
782 if (!IPv4DevicePathNode->StaticIpAddress) {\r
783 Status = Pxe->Dhcp (Pxe, TRUE);\r
784 } else {\r
785 CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
786 Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);\r
787 }\r
788\r
789 // If an IP Address has already been set and a different static IP address is requested then restart\r
790 // the Network service.\r
791 if (Status == EFI_ALREADY_STARTED) {\r
792 Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&Snp);\r
793 if (!EFI_ERROR (Status) && IPv4DevicePathNode->StaticIpAddress &&\r
794 (CompareMem (&Snp->Mode->CurrentAddress, &IPv4DevicePathNode->LocalIpAddress, sizeof(EFI_MAC_ADDRESS)) != 0))\r
795 {\r
796 Pxe->Stop (Pxe);\r
797 Status = Pxe->Start (Pxe, FALSE);\r
798 if (EFI_ERROR(Status)) {\r
799 break;\r
800 }\r
801 // After restarting the PXE protocol, we want to try again with our new IP Address\r
802 Status = EFI_ALREADY_STARTED;\r
803 }\r
804 }\r
805 } while (Status == EFI_ALREADY_STARTED);\r
806\r
807 if (EFI_ERROR(Status)) {\r
1e57a462 808 return Status;\r
809 }\r
810\r
811 CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
812\r
2edb5ad3 813 // Convert the Unicode PathName to Ascii\r
814 AsciiPathName = AllocatePool ((StrLen (FilePathDevicePath->PathName) + 1) * sizeof (CHAR8));\r
815 if (AsciiPathName == NULL) {\r
816 return EFI_OUT_OF_RESOURCES;\r
817 }\r
818 UnicodeStrToAsciiStr (FilePathDevicePath->PathName, AsciiPathName);\r
819\r
d8f36fb5 820 // Try to get the size (required the TFTP server to have "tsize" extension)\r
1e57a462 821 Status = Pxe->Mtftp (\r
822 Pxe,\r
823 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,\r
824 NULL,\r
825 FALSE,\r
826 &TftpBufferSize,\r
827 NULL,\r
828 &ServerIp,\r
2edb5ad3 829 (UINT8*)AsciiPathName,\r
1e57a462 830 NULL,\r
2edb5ad3 831 FALSE\r
1e57a462 832 );\r
d8f36fb5
OM
833 // Pxe.Mtftp replies EFI_PROTOCOL_ERROR if tsize is not supported by the TFTP server\r
834 if (EFI_ERROR (Status) && (Status != EFI_PROTOCOL_ERROR)) {\r
2edb5ad3 835 if (Status == EFI_TFTP_ERROR) {\r
836 DEBUG((EFI_D_ERROR, "TFTP Error: Fail to get the size of the file\n"));\r
837 }\r
838 goto EXIT;\r
1e57a462 839 }\r
840\r
d8f36fb5
OM
841 //\r
842 // Two cases:\r
843 // 1) the file size is unknown (tsize extension not supported)\r
844 // 2) tsize returned the file size\r
845 //\r
846 if (Status == EFI_PROTOCOL_ERROR) {\r
847 for (TftpBufferSize = SIZE_8MB; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize); TftpBufferSize += SIZE_8MB) {\r
848 // Allocate a buffer to hold the whole file.\r
849 Status = gBS->AllocatePages (\r
850 Type,\r
851 EfiBootServicesCode,\r
852 EFI_SIZE_TO_PAGES (TftpBufferSize),\r
853 Image\r
854 );\r
855 if (EFI_ERROR (Status)) {\r
856 DEBUG ((EFI_D_ERROR, "Failed to allocate space for image: %r\n", Status));\r
857 goto EXIT;\r
858 }\r
1e57a462 859\r
d8f36fb5
OM
860 Status = Pxe->Mtftp (\r
861 Pxe,\r
862 EFI_PXE_BASE_CODE_TFTP_READ_FILE,\r
863 (VOID *)(UINTN)*Image,\r
864 FALSE,\r
865 &TftpBufferSize,\r
866 NULL,\r
867 &ServerIp,\r
868 (UINT8*)AsciiPathName,\r
869 NULL,\r
870 FALSE\r
871 );\r
872 if (EFI_ERROR (Status)) {\r
873 gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));\r
874 } else {\r
875 *ImageSize = (UINTN)TftpBufferSize;\r
876 break;\r
877 }\r
878 }\r
1aaa6f61 879 } else {\r
d8f36fb5
OM
880 // Allocate a buffer to hold the whole file.\r
881 Status = gBS->AllocatePages (\r
882 Type,\r
883 EfiBootServicesCode,\r
884 EFI_SIZE_TO_PAGES (TftpBufferSize),\r
885 Image\r
886 );\r
887 if (EFI_ERROR (Status)) {\r
888 DEBUG ((EFI_D_ERROR, "Failed to allocate space for kernel image: %r\n", Status));\r
889 goto EXIT;\r
890 }\r
891\r
892 Status = Pxe->Mtftp (\r
893 Pxe,\r
894 EFI_PXE_BASE_CODE_TFTP_READ_FILE,\r
895 (VOID *)(UINTN)*Image,\r
896 FALSE,\r
897 &TftpBufferSize,\r
898 NULL,\r
899 &ServerIp,\r
900 (UINT8*)AsciiPathName,\r
901 NULL,\r
902 FALSE\r
903 );\r
904 if (EFI_ERROR (Status)) {\r
905 gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));\r
906 } else {\r
907 *ImageSize = (UINTN)TftpBufferSize;\r
908 }\r
1e57a462 909 }\r
910\r
2edb5ad3 911EXIT:\r
912 FreePool (AsciiPathName);\r
1e57a462 913 return Status;\r
914}\r
915\r
916BDS_FILE_LOADER FileLoaders[] = {\r
917 { BdsFileSystemSupport, BdsFileSystemLoadImage },\r
918 { BdsFirmwareVolumeSupport, BdsFirmwareVolumeLoadImage },\r
919 //{ BdsLoadFileSupport, BdsLoadFileLoadImage },\r
920 { BdsMemoryMapSupport, BdsMemoryMapLoadImage },\r
921 { BdsPxeSupport, BdsPxeLoadImage },\r
922 { BdsTftpSupport, BdsTftpLoadImage },\r
923 { NULL, NULL }\r
924};\r
925\r
926EFI_STATUS\r
10ddca8d
MS
927BdsLoadImageAndUpdateDevicePath (
928 IN OUT EFI_DEVICE_PATH **DevicePath,
1e57a462 929 IN EFI_ALLOCATE_TYPE Type,\r
930 IN OUT EFI_PHYSICAL_ADDRESS* Image,\r
931 OUT UINTN *FileSize\r
932 )\r
933{\r
934 EFI_STATUS Status;\r
935 EFI_HANDLE Handle;\r
936 EFI_DEVICE_PATH *RemainingDevicePath;\r
937 BDS_FILE_LOADER* FileLoader;\r
938\r
10ddca8d 939 Status = BdsConnectAndUpdateDevicePath (DevicePath, &Handle, &RemainingDevicePath);
1e57a462 940 if (EFI_ERROR (Status)) {\r
941 return Status;\r
942 }\r
943\r
944 FileLoader = FileLoaders;\r
945 while (FileLoader->Support != NULL) {\r
10ddca8d
MS
946 if (FileLoader->Support (*DevicePath, Handle, RemainingDevicePath)) {
947 return FileLoader->LoadImage (*DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize);
1e57a462 948 }\r
949 FileLoader++;\r
950 }\r
951\r
952 return EFI_UNSUPPORTED;\r
953}\r
954\r
10ddca8d
MS
955EFI_STATUS\r
956BdsLoadImage (
957 IN EFI_DEVICE_PATH *DevicePath,
958 IN EFI_ALLOCATE_TYPE Type,
959 IN OUT EFI_PHYSICAL_ADDRESS* Image,
960 OUT UINTN *FileSize
961 )
962{
963 return BdsLoadImageAndUpdateDevicePath (&DevicePath, Type, Image, FileSize);
964}
965
1e57a462 966/**\r
967 Start an EFI Application from a Device Path\r
968\r
969 @param ParentImageHandle Handle of the calling image\r
970 @param DevicePath Location of the EFI Application\r
971\r
972 @retval EFI_SUCCESS All drivers have been connected\r
973 @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
974 @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
975\r
976**/\r
977EFI_STATUS\r
978BdsStartEfiApplication (\r
979 IN EFI_HANDLE ParentImageHandle,\r
980 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
981 IN UINTN LoadOptionsSize,\r
982 IN VOID* LoadOptions\r
983 )\r
984{\r
985 EFI_STATUS Status;\r
986 EFI_HANDLE ImageHandle;\r
987 EFI_PHYSICAL_ADDRESS BinaryBuffer;\r
988 UINTN BinarySize;\r
989 EFI_LOADED_IMAGE_PROTOCOL* LoadedImage;\r
990\r
991 // Find the nearest supported file loader\r
10ddca8d 992 Status = BdsLoadImageAndUpdateDevicePath (&DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize);
6f711615 993 if (EFI_ERROR (Status)) {\r
1e57a462 994 return Status;\r
995 }\r
996\r
997 // Load the image from the Buffer with Boot Services function\r
998 Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);\r
6f711615 999 if (EFI_ERROR (Status)) {\r
1e57a462 1000 return Status;\r
1001 }\r
1002\r
1003 // Passed LoadOptions to the EFI Application\r
1004 if (LoadOptionsSize != 0) {\r
1005 Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
6f711615 1006 if (EFI_ERROR (Status)) {\r
1e57a462 1007 return Status;\r
1008 }\r
1009\r
1010 LoadedImage->LoadOptionsSize = LoadOptionsSize;\r
1011 LoadedImage->LoadOptions = LoadOptions;\r
1012 }\r
1013\r
1014 // Before calling the image, enable the Watchdog Timer for the 5 Minute period\r
1015 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
1016 // Start the image\r
1017 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
1018 // Clear the Watchdog Timer after the image returns\r
1019 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
1020\r
1021 return Status;\r
1022}\r