3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BdsInternal.h"
17 #include <Protocol/UsbIo.h>
18 #include <Protocol/DiskIo.h>
20 #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
22 // Extract the FilePath from the Device Path
24 BdsExtractFilePathFromDevicePath (
25 IN CONST CHAR16
*StrDevicePath
,
26 IN UINTN NumberDevicePathNode
32 Str
= (CHAR16
*)StrDevicePath
;
34 while ((Str
!= NULL
) && (*Str
!= L
'\0') && (Node
< NumberDevicePathNode
)) {
35 if ((*Str
== L
'/') || (*Str
== L
'\\')) {
50 IN EFI_DEVICE_PATH
* DevicePath
53 return ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) &&
54 ((DevicePathSubType (DevicePath
) == MSG_USB_CLASS_DP
) ||
55 (DevicePathSubType (DevicePath
) == MSG_USB_WWID_DP
)));
60 IN EFI_DEVICE_PATH
* RemovableDevicePath
,
61 OUT EFI_HANDLE
* DeviceHandle
,
62 OUT EFI_DEVICE_PATH
** NewDevicePath
67 UINTN UsbIoHandleCount
;
68 EFI_HANDLE
*UsbIoBuffer
;
69 EFI_DEVICE_PATH
* UsbIoDevicePath
;
70 EFI_DEVICE_PATH
* TmpDevicePath
;
71 USB_WWID_DEVICE_PATH
* WwidDevicePath1
;
72 USB_WWID_DEVICE_PATH
* WwidDevicePath2
;
73 USB_CLASS_DEVICE_PATH
* UsbClassDevicePath1
;
74 USB_CLASS_DEVICE_PATH
* UsbClassDevicePath2
;
76 // Get all the UsbIo handles
78 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiUsbIoProtocolGuid
, NULL
, &UsbIoHandleCount
, &UsbIoBuffer
);
79 if (EFI_ERROR(Status
) || (UsbIoHandleCount
== 0)) {
83 // Check if one of the handles matches the USB description
84 for (Index
= 0; Index
< UsbIoHandleCount
; Index
++) {
85 Status
= gBS
->HandleProtocol (UsbIoBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*) &UsbIoDevicePath
);
86 if (!EFI_ERROR(Status
)) {
87 TmpDevicePath
= UsbIoDevicePath
;
88 while (!IsDevicePathEnd (TmpDevicePath
)) {
89 // Check if the Device Path node is a USB Removable device Path node
90 if (BdsIsRemovableUsb (TmpDevicePath
)) {
91 if (TmpDevicePath
->SubType
== MSG_USB_WWID_DP
) {
92 WwidDevicePath1
= (USB_WWID_DEVICE_PATH
*)RemovableDevicePath
;
93 WwidDevicePath2
= (USB_WWID_DEVICE_PATH
*)TmpDevicePath
;
94 if ((WwidDevicePath1
->VendorId
== WwidDevicePath2
->VendorId
) &&
95 (WwidDevicePath1
->ProductId
== WwidDevicePath2
->ProductId
) &&
96 (CompareMem (WwidDevicePath1
+1, WwidDevicePath2
+1, DevicePathNodeLength(WwidDevicePath1
)-sizeof(USB_WWID_DEVICE_PATH
)) == 0))
98 *DeviceHandle
= UsbIoBuffer
[Index
];
99 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
100 *NewDevicePath
= AppendDevicePath (UsbIoDevicePath
, NextDevicePathNode(RemovableDevicePath
));
104 UsbClassDevicePath1
= (USB_CLASS_DEVICE_PATH
*)RemovableDevicePath
;
105 UsbClassDevicePath2
= (USB_CLASS_DEVICE_PATH
*)TmpDevicePath
;
106 if ((UsbClassDevicePath1
->VendorId
!= 0xFFFF) && (UsbClassDevicePath1
->VendorId
== UsbClassDevicePath2
->VendorId
) &&
107 (UsbClassDevicePath1
->ProductId
!= 0xFFFF) && (UsbClassDevicePath1
->ProductId
== UsbClassDevicePath2
->ProductId
) &&
108 (UsbClassDevicePath1
->DeviceClass
!= 0xFF) && (UsbClassDevicePath1
->DeviceClass
== UsbClassDevicePath2
->DeviceClass
) &&
109 (UsbClassDevicePath1
->DeviceSubClass
!= 0xFF) && (UsbClassDevicePath1
->DeviceSubClass
== UsbClassDevicePath2
->DeviceSubClass
) &&
110 (UsbClassDevicePath1
->DeviceProtocol
!= 0xFF) && (UsbClassDevicePath1
->DeviceProtocol
== UsbClassDevicePath2
->DeviceProtocol
))
112 *DeviceHandle
= UsbIoBuffer
[Index
];
113 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
114 *NewDevicePath
= AppendDevicePath (UsbIoDevicePath
, NextDevicePathNode(RemovableDevicePath
));
119 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
125 return EFI_NOT_FOUND
;
130 IN EFI_DEVICE_PATH
* DevicePath
133 return IS_DEVICE_PATH_NODE(DevicePath
, MEDIA_DEVICE_PATH
, MEDIA_HARDDRIVE_DP
);
138 IN EFI_DEVICE_PATH
* RemovableDevicePath
,
139 OUT EFI_HANDLE
* DeviceHandle
,
140 OUT EFI_DEVICE_PATH
** NewDevicePath
145 UINTN PartitionHandleCount
;
146 EFI_HANDLE
*PartitionBuffer
;
147 EFI_DEVICE_PATH
* PartitionDevicePath
;
148 EFI_DEVICE_PATH
* TmpDevicePath
;
149 HARDDRIVE_DEVICE_PATH
* HardDriveDevicePath1
;
150 HARDDRIVE_DEVICE_PATH
* HardDriveDevicePath2
;
152 // Get all the DiskIo handles
153 PartitionHandleCount
= 0;
154 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDiskIoProtocolGuid
, NULL
, &PartitionHandleCount
, &PartitionBuffer
);
155 if (EFI_ERROR(Status
) || (PartitionHandleCount
== 0)) {
159 // Check if one of the handles matches the Hard Disk Description
160 for (Index
= 0; Index
< PartitionHandleCount
; Index
++) {
161 Status
= gBS
->HandleProtocol (PartitionBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*) &PartitionDevicePath
);
162 if (!EFI_ERROR(Status
)) {
163 TmpDevicePath
= PartitionDevicePath
;
164 while (!IsDevicePathEnd (TmpDevicePath
)) {
165 // Check if the Device Path node is a HD Removable device Path node
166 if (BdsIsRemovableHd (TmpDevicePath
)) {
167 HardDriveDevicePath1
= (HARDDRIVE_DEVICE_PATH
*)RemovableDevicePath
;
168 HardDriveDevicePath2
= (HARDDRIVE_DEVICE_PATH
*)TmpDevicePath
;
169 if ((HardDriveDevicePath1
->SignatureType
== HardDriveDevicePath2
->SignatureType
) &&
170 (CompareGuid ((EFI_GUID
*)HardDriveDevicePath1
->Signature
,(EFI_GUID
*)HardDriveDevicePath2
->Signature
) == TRUE
) &&
171 (HardDriveDevicePath1
->PartitionNumber
== HardDriveDevicePath2
->PartitionNumber
))
173 *DeviceHandle
= PartitionBuffer
[Index
];
174 // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
175 *NewDevicePath
= AppendDevicePath (PartitionDevicePath
, NextDevicePathNode(RemovableDevicePath
));
179 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
185 return EFI_NOT_FOUND
;
189 BdsIsRemovableCdrom (
190 IN EFI_DEVICE_PATH* DevicePath
193 return IS_DEVICE_PATH_NODE(DevicePath, MEDIA_DEVICE_PATH, MEDIA_CDROM_DP);
198 IN EFI_DEVICE_PATH* RemovableDevicePath,
199 OUT EFI_HANDLE* DeviceHandle,
200 OUT EFI_DEVICE_PATH** DevicePath
204 return EFI_UNSUPPORTED;
208 (*BDS_IS_REMOVABLE
) (
209 IN EFI_DEVICE_PATH
* DevicePath
214 IN EFI_DEVICE_PATH
* RemovableDevicePath
,
215 OUT EFI_HANDLE
* DeviceHandle
,
216 OUT EFI_DEVICE_PATH
** DevicePath
220 BDS_IS_REMOVABLE IsRemovable
;
221 BDS_GET_DEVICE GetDevice
;
222 } BDS_REMOVABLE_DEVICE_SUPPORT
;
224 BDS_REMOVABLE_DEVICE_SUPPORT RemovableDeviceSupport
[] = {
225 { BdsIsRemovableUsb
, BdsGetDeviceUsb
},
226 { BdsIsRemovableHd
, BdsGetDeviceHd
},
227 //{ BdsIsRemovableCdrom, BdsGetDeviceCdrom }
233 IN EFI_DEVICE_PATH
* DevicePath
237 EFI_DEVICE_PATH
* TmpDevicePath
;
239 TmpDevicePath
= DevicePath
;
240 while (!IsDevicePathEnd (TmpDevicePath
)) {
241 for (Index
= 0; Index
< sizeof(RemovableDeviceSupport
) / sizeof(BDS_REMOVABLE_DEVICE_SUPPORT
); Index
++) {
242 if (RemovableDeviceSupport
[Index
].IsRemovable(TmpDevicePath
)) {
246 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
255 IN EFI_DEVICE_PATH
* DevicePath
,
256 OUT EFI_HANDLE
* DeviceHandle
,
257 OUT EFI_DEVICE_PATH
** NewDevicePath
262 EFI_DEVICE_PATH
* TmpDevicePath
;
263 BDS_REMOVABLE_DEVICE_SUPPORT
* RemovableDevice
;
264 EFI_DEVICE_PATH
* RemovableDevicePath
;
265 BOOLEAN RemovableFound
;
267 RemovableDevice
= NULL
;
268 RemovableDevicePath
= NULL
;
269 RemovableFound
= FALSE
;
270 TmpDevicePath
= DevicePath
;
272 while (!IsDevicePathEnd (TmpDevicePath
) && !RemovableFound
) {
273 for (Index
= 0; Index
< sizeof(RemovableDeviceSupport
) / sizeof(BDS_REMOVABLE_DEVICE_SUPPORT
); Index
++) {
274 RemovableDevice
= &RemovableDeviceSupport
[Index
];
275 if (RemovableDevice
->IsRemovable(TmpDevicePath
)) {
276 RemovableDevicePath
= TmpDevicePath
;
277 RemovableFound
= TRUE
;
281 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
284 if (!RemovableFound
) {
285 return EFI_NOT_FOUND
;
288 // Search into the current started drivers
289 Status
= RemovableDevice
->GetDevice (RemovableDevicePath
, DeviceHandle
, NewDevicePath
);
290 if (Status
== EFI_NOT_FOUND
) {
291 // Connect all the drivers
292 BdsConnectAllDrivers ();
294 // Search again into all the drivers
295 Status
= RemovableDevice
->GetDevice (RemovableDevicePath
, DeviceHandle
, NewDevicePath
);
302 Connect a Device Path and return the handle of the driver that support this DevicePath
304 @param DevicePath Device Path of the File to connect
305 @param Handle Handle of the driver that support this DevicePath
306 @param RemainingDevicePath Remaining DevicePath nodes that do not match the driver DevicePath
308 @retval EFI_SUCCESS A driver that matches the Device Path has been found
309 @retval EFI_NOT_FOUND No handles match the search.
310 @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL
314 BdsConnectDevicePath (
315 IN EFI_DEVICE_PATH_PROTOCOL
* DevicePath
,
316 OUT EFI_HANDLE
*Handle
,
317 OUT EFI_DEVICE_PATH_PROTOCOL
**RemainingDevicePath
320 EFI_DEVICE_PATH
* Remaining
;
321 EFI_DEVICE_PATH
* NewDevicePath
;
324 if ((DevicePath
== NULL
) || (Handle
== NULL
)) {
325 return EFI_INVALID_PARAMETER
;
329 Remaining
= DevicePath
;
330 // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
331 // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
332 // to point to the remaining part of the device path
333 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &Remaining
, Handle
);
334 if (!EFI_ERROR (Status
)) {
335 // Recursive = FALSE: We do not want to start all the device tree
336 Status
= gBS
->ConnectController (*Handle
, NULL
, Remaining
, FALSE
);
339 /*// We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling
340 // NextDevicePathNode() will return an undetermined Device Path Node
341 if (!IsDevicePathEnd (RemainingDevicePath)) {
342 RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
344 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (Remaining
));
346 if (!EFI_ERROR (Status
)) {
347 // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
348 // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
349 Remaining
= DevicePath
;
350 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
,&Remaining
,Handle
);
351 if (!EFI_ERROR (Status
)) {
352 Status
= gBS
->ConnectController (*Handle
, NULL
, Remaining
, FALSE
);
353 if (EFI_ERROR (Status
)) {
354 // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
355 if ((Remaining
->Type
== HARDWARE_DEVICE_PATH
) && (Remaining
->SubType
== HW_MEMMAP_DP
)) {
356 Status
= EFI_SUCCESS
;
360 } else if (!IsDevicePathEnd (Remaining
) && !IsRemovableDevice (Remaining
)) {
362 /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly
363 if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {
364 Status = EFI_SUCCESS;
365 } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
366 Status = EFI_SUCCESS;
369 //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath
370 Status
= EFI_SUCCESS
;
372 Status
= TryRemovableDevice (DevicePath
, Handle
, &NewDevicePath
);
373 if (!EFI_ERROR (Status
)) {
374 return BdsConnectDevicePath (NewDevicePath
, Handle
, RemainingDevicePath
);
378 if (RemainingDevicePath
) {
379 *RemainingDevicePath
= Remaining
;
386 BdsFileSystemSupport (
387 IN EFI_DEVICE_PATH
*DevicePath
,
388 IN EFI_HANDLE Handle
,
389 IN EFI_DEVICE_PATH
*RemainingDevicePath
393 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*FsProtocol
;
395 Status
= gBS
->HandleProtocol (Handle
,&gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FsProtocol
);
397 return (!EFI_ERROR(Status
) && IS_DEVICE_PATH_NODE(RemainingDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
));
401 BdsFileSystemLoadImage (
402 IN EFI_DEVICE_PATH
*DevicePath
,
403 IN EFI_HANDLE Handle
,
404 IN EFI_DEVICE_PATH
*RemainingDevicePath
,
405 IN EFI_ALLOCATE_TYPE Type
,
406 IN OUT EFI_PHYSICAL_ADDRESS
* Image
,
410 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
411 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*FsProtocol
;
412 EFI_FILE_PROTOCOL
*Fs
;
414 EFI_FILE_INFO
*FileInfo
;
415 EFI_FILE_PROTOCOL
*File
;
418 ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
));
420 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)RemainingDevicePath
;
422 Status
= gBS
->HandleProtocol(Handle
,&gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FsProtocol
);
423 if (EFI_ERROR(Status
)) {
427 // Try to Open the volume and get root directory
428 Status
= FsProtocol
->OpenVolume (FsProtocol
, &Fs
);
429 if (EFI_ERROR(Status
)) {
434 Status
= Fs
->Open(Fs
, &File
, FilePathDevicePath
->PathName
, EFI_FILE_MODE_READ
, 0);
435 if (EFI_ERROR(Status
)) {
440 File
->GetInfo(File
, &gEfiFileInfoGuid
, &Size
, NULL
);
441 FileInfo
= AllocatePool (Size
);
442 Status
= File
->GetInfo(File
, &gEfiFileInfoGuid
, &Size
, FileInfo
);
443 if (EFI_ERROR(Status
)) {
448 Size
= FileInfo
->FileSize
;
454 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
455 // Try to allocate in any pages if failed to allocate memory at the defined location
456 if ((Status
== EFI_OUT_OF_RESOURCES
) && (Type
!= AllocateAnyPages
)) {
457 Status
= gBS
->AllocatePages (AllocateAnyPages
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
459 if (!EFI_ERROR(Status
)) {
460 Status
= File
->Read (File
, &Size
, (VOID
*)(UINTN
)(*Image
));
467 BdsMemoryMapSupport (
468 IN EFI_DEVICE_PATH
*DevicePath
,
469 IN EFI_HANDLE Handle
,
470 IN EFI_DEVICE_PATH
*RemainingDevicePath
473 return IS_DEVICE_PATH_NODE(RemainingDevicePath
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
477 BdsMemoryMapLoadImage (
478 IN EFI_DEVICE_PATH
*DevicePath
,
479 IN EFI_HANDLE Handle
,
480 IN EFI_DEVICE_PATH
*RemainingDevicePath
,
481 IN EFI_ALLOCATE_TYPE Type
,
482 IN OUT EFI_PHYSICAL_ADDRESS
* Image
,
487 MEMMAP_DEVICE_PATH
* MemMapPathDevicePath
;
490 ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
));
492 MemMapPathDevicePath
= (MEMMAP_DEVICE_PATH
*)RemainingDevicePath
;
494 Size
= MemMapPathDevicePath
->EndingAddress
- MemMapPathDevicePath
->StartingAddress
;
496 return EFI_INVALID_PARAMETER
;
499 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
500 // Try to allocate in any pages if failed to allocate memory at the defined location
501 if ((Status
== EFI_OUT_OF_RESOURCES
) && (Type
!= AllocateAnyPages
)) {
502 Status
= gBS
->AllocatePages (AllocateAnyPages
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
504 if (!EFI_ERROR(Status
)) {
505 CopyMem ((VOID
*)(UINTN
)(*Image
), (CONST VOID
*)(UINTN
)MemMapPathDevicePath
->StartingAddress
, Size
);
507 if (ImageSize
!= NULL
) {
516 BdsFirmwareVolumeSupport (
517 IN EFI_DEVICE_PATH
*DevicePath
,
518 IN EFI_HANDLE Handle
,
519 IN EFI_DEVICE_PATH
*RemainingDevicePath
522 return IS_DEVICE_PATH_NODE(RemainingDevicePath
, MEDIA_DEVICE_PATH
, MEDIA_PIWG_FW_FILE_DP
);
526 BdsFirmwareVolumeLoadImage (
527 IN EFI_DEVICE_PATH
*DevicePath
,
528 IN EFI_HANDLE Handle
,
529 IN EFI_DEVICE_PATH
*RemainingDevicePath
,
530 IN EFI_ALLOCATE_TYPE Type
,
531 IN OUT EFI_PHYSICAL_ADDRESS
* Image
,
536 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
537 EFI_GUID
*FvNameGuid
;
538 EFI_SECTION_TYPE SectionType
;
539 EFI_FV_FILETYPE FvType
;
540 EFI_FV_FILE_ATTRIBUTES Attrib
;
541 UINT32 AuthenticationStatus
;
544 ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath
, MEDIA_DEVICE_PATH
, MEDIA_PIWG_FW_FILE_DP
));
546 Status
= gBS
->HandleProtocol(Handle
,&gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FwVol
);
547 if (EFI_ERROR(Status
)) {
551 FvNameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)RemainingDevicePath
);
552 if (FvNameGuid
== NULL
) {
553 Status
= EFI_INVALID_PARAMETER
;
556 SectionType
= EFI_SECTION_PE32
;
557 AuthenticationStatus
= 0;
558 //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file.
560 Status
= FwVol
->ReadSection (
567 &AuthenticationStatus
569 if (!EFI_ERROR (Status
)) {
571 // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements
572 if (Type
!= AllocateAnyPages
) {
573 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(*ImageSize
),Image
);
574 if (!EFI_ERROR(Status
)) {
575 CopyMem ((VOID
*)(UINTN
)(*Image
), ImageBuffer
, *ImageSize
);
576 FreePool (ImageBuffer
);
580 // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation
581 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(*ImageSize
), Image
);
582 // Try to allocate in any pages if failed to allocate memory at the defined location
583 if ((Status
== EFI_OUT_OF_RESOURCES
) && (Type
!= AllocateAnyPages
)) {
584 Status
= gBS
->AllocatePages (AllocateAnyPages
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
586 if (!EFI_ERROR(Status
)) {
587 CopyMem ((VOID
*)(UINTN
)(*Image
), ImageBuffer
, *ImageSize
);
588 FreePool (ImageBuffer
);
592 // Try a raw file, since a PE32 SECTION does not exist
593 Status
= FwVol
->ReadFile (
600 &AuthenticationStatus
602 if (!EFI_ERROR(Status
)) {
603 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(*ImageSize
), Image
);
604 // Try to allocate in any pages if failed to allocate memory at the defined location
605 if ((Status
== EFI_OUT_OF_RESOURCES
) && (Type
!= AllocateAnyPages
)) {
606 Status
= gBS
->AllocatePages (AllocateAnyPages
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(Size
), Image
);
608 if (!EFI_ERROR(Status
)) {
609 Status
= FwVol
->ReadFile (
612 (VOID
*)(UINTN
)(*Image
),
616 &AuthenticationStatus
626 IN EFI_DEVICE_PATH
* DevicePath
,
627 IN EFI_HANDLE Handle
,
628 IN EFI_DEVICE_PATH
* RemainingDevicePath
632 EFI_PXE_BASE_CODE_PROTOCOL
* PxeBcProtocol
;
634 if (!IsDevicePathEnd(RemainingDevicePath
)) {
638 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
639 if (EFI_ERROR (Status
)) {
648 IN EFI_DEVICE_PATH
* DevicePath
,
649 IN EFI_HANDLE Handle
,
650 IN EFI_DEVICE_PATH
* RemainingDevicePath
,
651 IN EFI_ALLOCATE_TYPE Type
,
652 IN OUT EFI_PHYSICAL_ADDRESS
*Image
,
657 EFI_LOAD_FILE_PROTOCOL
*LoadFileProtocol
;
660 // Get Load File Protocol attached to the PXE protocol
661 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadFileProtocolGuid
, (VOID
**)&LoadFileProtocol
);
662 if (EFI_ERROR (Status
)) {
666 Status
= LoadFileProtocol
->LoadFile (LoadFileProtocol
, DevicePath
, TRUE
, &BufferSize
, NULL
);
667 if (Status
== EFI_BUFFER_TOO_SMALL
) {
668 Status
= gBS
->AllocatePages (Type
, EfiBootServicesCode
, EFI_SIZE_TO_PAGES(BufferSize
), Image
);
669 if (EFI_ERROR(Status
)) {
673 Status
= LoadFileProtocol
->LoadFile (LoadFileProtocol
, DevicePath
, TRUE
, &BufferSize
, (VOID
*)(UINTN
)(*Image
));
674 if (!EFI_ERROR(Status
) && (ImageSize
!= NULL
)) {
675 *ImageSize
= BufferSize
;
684 IN EFI_DEVICE_PATH
* DevicePath
,
685 IN EFI_HANDLE Handle
,
686 IN EFI_DEVICE_PATH
* RemainingDevicePath
690 EFI_DEVICE_PATH
*NextDevicePath
;
691 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
693 // Validate the Remaining Device Path
694 if (IsDevicePathEnd(RemainingDevicePath
)) {
697 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
698 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
701 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
702 if (IsDevicePathEnd(NextDevicePath
)) {
705 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
709 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
710 if (EFI_ERROR (Status
)) {
719 IN EFI_DEVICE_PATH
* DevicePath
,
720 IN EFI_HANDLE Handle
,
721 IN EFI_DEVICE_PATH
* RemainingDevicePath
,
722 IN EFI_ALLOCATE_TYPE Type
,
723 IN OUT EFI_PHYSICAL_ADDRESS
*Image
,
728 EFI_PXE_BASE_CODE_PROTOCOL
*Pxe
;
729 UINT64 TftpBufferSize
;
731 EFI_IP_ADDRESS ServerIp
;
732 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
733 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
734 EFI_IP_ADDRESS LocalIp
;
736 ASSERT(IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
));
738 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)RemainingDevicePath
;
739 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
741 Status
= gBS
->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid
, NULL
, (VOID
**)&Pxe
);
742 if (EFI_ERROR(Status
)) {
746 Status
= Pxe
->Start (Pxe
, FALSE
);
747 if (EFI_ERROR(Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
751 if (!IPv4DevicePathNode
->StaticIpAddress
) {
752 Status
= Pxe
->Dhcp(Pxe
, TRUE
);
754 CopyMem (&LocalIp
.v4
, &IPv4DevicePathNode
->LocalIpAddress
, sizeof (EFI_IPv4_ADDRESS
));
755 Status
= Pxe
->SetStationIp (Pxe
, &LocalIp
, NULL
);
757 if (EFI_ERROR(Status
)) {
761 CopyMem (&ServerIp
.v4
, &IPv4DevicePathNode
->RemoteIpAddress
, sizeof (EFI_IPv4_ADDRESS
));
763 Status
= Pxe
->Mtftp (
765 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
,
771 (UINT8
*)FilePathDevicePath
->PathName
,
775 if (EFI_ERROR(Status
)) {
779 // Allocate a buffer to hold the whole file.
780 TftpBuffer
= AllocatePool(TftpBufferSize
);
781 if (TftpBuffer
== NULL
) {
782 return EFI_OUT_OF_RESOURCES
;
785 Status
= Pxe
->Mtftp (
787 EFI_PXE_BASE_CODE_TFTP_READ_FILE
,
793 (UINT8
*)FilePathDevicePath
->PathName
,
797 if (EFI_ERROR(Status
)) {
798 FreePool(TftpBuffer
);
799 } else if (ImageSize
!= NULL
) {
800 *ImageSize
= (UINTN
)TftpBufferSize
;
806 BDS_FILE_LOADER FileLoaders
[] = {
807 { BdsFileSystemSupport
, BdsFileSystemLoadImage
},
808 { BdsFirmwareVolumeSupport
, BdsFirmwareVolumeLoadImage
},
809 //{ BdsLoadFileSupport, BdsLoadFileLoadImage },
810 { BdsMemoryMapSupport
, BdsMemoryMapLoadImage
},
811 { BdsPxeSupport
, BdsPxeLoadImage
},
812 { BdsTftpSupport
, BdsTftpLoadImage
},
818 IN EFI_DEVICE_PATH
*DevicePath
,
819 IN EFI_ALLOCATE_TYPE Type
,
820 IN OUT EFI_PHYSICAL_ADDRESS
* Image
,
826 EFI_DEVICE_PATH
*RemainingDevicePath
;
827 BDS_FILE_LOADER
* FileLoader
;
829 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
830 if (EFI_ERROR (Status
)) {
834 FileLoader
= FileLoaders
;
835 while (FileLoader
->Support
!= NULL
) {
836 if (FileLoader
->Support (DevicePath
, Handle
, RemainingDevicePath
)) {
837 return FileLoader
->LoadImage (DevicePath
, Handle
, RemainingDevicePath
, Type
, Image
, FileSize
);
842 return EFI_UNSUPPORTED
;
846 Start an EFI Application from a Device Path
848 @param ParentImageHandle Handle of the calling image
849 @param DevicePath Location of the EFI Application
851 @retval EFI_SUCCESS All drivers have been connected
852 @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
853 @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
857 BdsStartEfiApplication (
858 IN EFI_HANDLE ParentImageHandle
,
859 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
863 EFI_HANDLE ImageHandle
;
864 EFI_PHYSICAL_ADDRESS BinaryBuffer
;
867 // Find the nearest supported file loader
868 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
,&BinaryBuffer
,&BinarySize
);
869 if (EFI_ERROR(Status
)) {
873 // Load the image from the Buffer with Boot Services function
874 Status
= gBS
->LoadImage (TRUE
, ParentImageHandle
, DevicePath
, (VOID
*)(UINTN
)BinaryBuffer
, BinarySize
, &ImageHandle
);
875 if (EFI_ERROR(Status
)) {
879 // Before calling the image, enable the Watchdog Timer for the 5 Minute period
880 gBS
->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL
);
882 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
883 // Clear the Watchdog Timer after the image returns
884 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);