3 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Device Path services. The thing to remember is device paths are built out of
19 nodes. The device path is terminated by an end node that is length
20 sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
23 The only place where multi-instance device paths are supported is in
24 environment varibles. Multi-instance device paths should never be placed
30 #include "EfiRuntimeLib.h"
31 #include "RtDevicePath.h"
32 #include EFI_GUID_DEFINITION (FrameworkDevicePath)
33 #include EFI_PROTOCOL_DEFINITION (DevicePath)
37 InternalAllocatePool (
38 IN UINTN AllocationSize
44 Allocate BootServicesData pool.
48 AllocationSize - The size to allocate
52 Pointer of the buffer allocated.
59 gBS
->AllocatePool (EfiBootServicesData
, AllocationSize
, &Memory
);
65 InternalAllocateCopyPool (
66 IN UINTN AllocationSize
,
73 Allocate BootServicesData pool and use a buffer provided by
78 AllocationSize - The size to allocate
80 Buffer - Buffer that will be filled into the buffer allocated
84 Pointer of the buffer allocated.
91 gBS
->AllocatePool (EfiBootServicesData
, AllocationSize
, &Memory
);
93 gBS
->CopyMem (Memory
, Buffer
, AllocationSize
);
101 InternalAllocateZeroPool (
102 IN UINTN AllocationSize
108 Allocate BootServicesData pool and zero it.
112 AllocationSize - The size to allocate
116 Pointer of the buffer allocated.
122 Memory
= InternalAllocatePool (AllocationSize
);
123 if (Memory
!= NULL
) {
124 gBS
->SetMem (Memory
, AllocationSize
, 0);
130 EFI_DEVICE_PATH_PROTOCOL
*
131 RtEfiDevicePathInstance (
132 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
138 Function retrieves the next device path instance from a device path data structure.
141 DevicePath - A pointer to a device path data structure.
143 Size - A pointer to the size of a device path instance in bytes.
147 This function returns a pointer to the current device path instance.
148 In addition, it returns the size in bytes of the current device path instance in Size,
149 and a pointer to the next device path instance in DevicePath.
150 If there are no more device path instances in DevicePath, then DevicePath will be set to NULL.
154 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
155 EFI_DEVICE_PATH_PROTOCOL
*ReturnValue
;
158 if (*DevicePath
== NULL
) {
167 // Find the end of the device path instance
169 DevPath
= *DevicePath
;
170 while (!IsDevicePathEndType (DevPath
)) {
171 DevPath
= NextDevicePathNode (DevPath
);
175 // Compute the size of the device path instance
178 *Size
= ((UINTN
) DevPath
- (UINTN
) (*DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
182 // Make a copy and return the device path instance
184 Temp
= DevPath
->SubType
;
185 DevPath
->SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
186 ReturnValue
= RtEfiDuplicateDevicePath (*DevicePath
);
187 DevPath
->SubType
= Temp
;
190 // If DevPath is the end of an entire device path, then another instance
191 // does not follow, so *DevicePath is set to NULL.
193 if (DevicePathSubType (DevPath
) == END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
196 *DevicePath
= NextDevicePathNode (DevPath
);
203 RtEfiIsDevicePathMultiInstance (
204 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
209 Return TRUE is this is a multi instance device path.
212 DevicePath - A pointer to a device path data structure.
216 TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
221 EFI_DEVICE_PATH_PROTOCOL
*Node
;
223 if (DevicePath
== NULL
) {
228 while (!EfiIsDevicePathEnd (Node
)) {
229 if (EfiIsDevicePathEndInstance (Node
)) {
233 Node
= EfiNextDevicePathNode (Node
);
240 RtEfiDevicePathSize (
241 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
247 Calculate the space size of a device path.
251 DevicePath - A specified device path
259 EFI_DEVICE_PATH_PROTOCOL
*Start
;
261 if (DevicePath
== NULL
) {
266 // Search for the end of the device path structure
269 while (!EfiIsDevicePathEnd (DevicePath
)) {
270 DevicePath
= EfiNextDevicePathNode (DevicePath
);
274 // Compute the size and add back in the size of the end device path structure
276 return ((UINTN
) DevicePath
- (UINTN
) Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
279 EFI_DEVICE_PATH_PROTOCOL
*
280 RtEfiDevicePathFromHandle (
287 Get the device path protocol interface installed on a specified handle.
291 Handle - a specified handle
295 The device path protocol interface installed on that handle.
299 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
302 gBS
->HandleProtocol (
304 &gEfiDevicePathProtocolGuid
,
310 EFI_DEVICE_PATH_PROTOCOL
*
311 RtEfiDuplicateDevicePath (
312 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
318 Duplicate a device path structure.
322 DevicePath - The device path to duplicated.
326 The duplicated device path.
330 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
333 if (DevicePath
== NULL
) {
340 Size
= RtEfiDevicePathSize (DevicePath
);
346 // Allocate space for duplicate device path
348 NewDevicePath
= InternalAllocateCopyPool (Size
, DevicePath
);
350 return NewDevicePath
;
353 EFI_DEVICE_PATH_PROTOCOL
*
354 RtEfiAppendDevicePath (
355 IN EFI_DEVICE_PATH_PROTOCOL
*Src1
,
356 IN EFI_DEVICE_PATH_PROTOCOL
*Src2
361 Function is used to append a Src1 and Src2 together.
364 Src1 - A pointer to a device path data structure.
366 Src2 - A pointer to a device path data structure.
370 A pointer to the new device path is returned.
371 NULL is returned if space for the new device path could not be allocated from pool.
372 It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
379 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
380 EFI_DEVICE_PATH_PROTOCOL
*SecondDevicePath
;
383 // If there's only 1 path, just duplicate it
386 ASSERT (!IsDevicePathUnpacked (Src2
));
387 return RtEfiDuplicateDevicePath (Src2
);
391 ASSERT (!IsDevicePathUnpacked (Src1
));
392 return RtEfiDuplicateDevicePath (Src1
);
396 // Allocate space for the combined device path. It only has one end node of
397 // length EFI_DEVICE_PATH_PROTOCOL
399 Size1
= RtEfiDevicePathSize (Src1
);
400 Size2
= RtEfiDevicePathSize (Src2
);
401 Size
= Size1
+ Size2
- sizeof (EFI_DEVICE_PATH_PROTOCOL
);
403 NewDevicePath
= InternalAllocateCopyPool (Size
, Src1
);
405 if (NewDevicePath
!= NULL
) {
408 // Over write Src1 EndNode and do the copy
410 SecondDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ((CHAR8
*) NewDevicePath
+ (Size1
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
411 EfiCopyMem (SecondDevicePath
, Src2
, Size2
);
414 return NewDevicePath
;
417 EFI_DEVICE_PATH_PROTOCOL
*
418 RtEfiAppendDevicePathNode (
419 IN EFI_DEVICE_PATH_PROTOCOL
*Src1
,
420 IN EFI_DEVICE_PATH_PROTOCOL
*Node
425 Function is used to append a device path node to the end of another device path.
428 Src1 - A pointer to a device path data structure.
430 Node - A pointer to a device path data structure.
433 This function returns a pointer to the new device path.
434 If there is not enough temporary pool memory available to complete this function,
435 then NULL is returned.
440 EFI_DEVICE_PATH_PROTOCOL
*Temp
;
441 EFI_DEVICE_PATH_PROTOCOL
*NextNode
;
442 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
446 // Build a Node that has a terminator on it
448 NodeLength
= DevicePathNodeLength (Node
);
450 Temp
= InternalAllocateCopyPool (NodeLength
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
), Node
);
456 // Add and end device path node to convert Node to device path
458 NextNode
= NextDevicePathNode (Temp
);
459 SetDevicePathEndNode (NextNode
);
462 // Append device paths
464 NewDevicePath
= RtEfiAppendDevicePath (Src1
, Temp
);
465 gBS
->FreePool (Temp
);
466 return NewDevicePath
;
469 EFI_DEVICE_PATH_PROTOCOL
*
470 RtEfiFileDevicePath (
471 IN EFI_HANDLE Device OPTIONAL
,
478 This function allocates a device path for a file and appends it to an existiong
482 Device - A pointer to a device handle.
484 FileName - A pointer to a Null-terminated Unicodestring.
487 A device path contain the file name.
492 FILEPATH_DEVICE_PATH
*FilePath
;
493 EFI_DEVICE_PATH_PROTOCOL
*Eop
;
494 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
496 for (Size
= 0; FileName
[Size
] != 0; Size
++)
498 Size
= (Size
+ 1) * 2;
500 FilePath
= InternalAllocateZeroPool (Size
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
));
504 if (FilePath
!= NULL
) {
509 FilePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
510 FilePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
511 SetDevicePathNodeLength (&FilePath
->Header
, Size
+ SIZE_OF_FILEPATH_DEVICE_PATH
);
512 EfiCopyMem (FilePath
->PathName
, FileName
, Size
);
513 Eop
= NextDevicePathNode (&FilePath
->Header
);
514 SetDevicePathEndNode (Eop
);
517 // Append file path to device's device path
520 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
;
521 if (Device
!= NULL
) {
522 DevicePath
= RtEfiAppendDevicePath (
523 RtEfiDevicePathFromHandle (Device
),
527 gBS
->FreePool (FilePath
);
534 EFI_DEVICE_PATH_PROTOCOL
*
535 RtEfiAppendDevicePathInstance (
536 IN EFI_DEVICE_PATH_PROTOCOL
*Src
,
537 IN EFI_DEVICE_PATH_PROTOCOL
*Instance
543 Append a device path instance to another.
547 Src - The device path instance to be appended with.
548 Instance - The device path instance appending the other.
552 The contaction of these two.
557 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
562 return RtEfiDuplicateDevicePath (Instance
);
565 SrcSize
= RtEfiDevicePathSize (Src
);
566 InstanceSize
= RtEfiDevicePathSize (Instance
);
568 Ptr
= InternalAllocateCopyPool (SrcSize
+ InstanceSize
, Src
);
571 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
573 while (!IsDevicePathEnd (DevPath
)) {
574 DevPath
= NextDevicePathNode (DevPath
);
577 // Convert the End to an End Instance, since we are
578 // appending another instacne after this one its a good
581 DevPath
->SubType
= END_INSTANCE_DEVICE_PATH_SUBTYPE
;
583 DevPath
= NextDevicePathNode (DevPath
);
584 EfiCopyMem (DevPath
, Instance
, InstanceSize
);
587 return (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
592 RtEfiInitializeFwVolDevicepathNode (
593 IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvDevicePathNode
,
594 IN EFI_GUID
*NameGuid
600 Initialize a Firmware Volume (FV) Media Device Path node.
602 Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
603 so as we move to UEFI 2.0 support we must use a mechanism that conforms with
604 the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
605 device path is defined for PIWG extensions of device path. If the code
606 is compiled to conform with the UEFI 2.0 specification use the new device path
607 else use the old form for backwards compatability.
611 FvDevicePathNode - Pointer to a FV device path node to initialize
612 NameGuid - FV file name to use in FvDevicePathNode
621 // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
622 // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with
623 // EFI 1.10 and UEFI 2.10.
625 FvDevicePathNode
->Header
.Type
= MEDIA_DEVICE_PATH
;
626 FvDevicePathNode
->Header
.SubType
= MEDIA_FV_FILEPATH_DP
;
627 SetDevicePathNodeLength (&FvDevicePathNode
->Header
, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
));
629 EfiCopyMem (&FvDevicePathNode
->NameGuid
, NameGuid
, sizeof(EFI_GUID
));
634 RtEfiGetNameGuidFromFwVolDevicePathNode (
635 IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvDevicePathNode
641 Check to see if the Firmware Volume (FV) Media Device Path is valid.
643 Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum
644 so as we move to UEFI 2.0 support we must use a mechanism that conforms with
645 the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed
646 device path is defined for PIWG extensions of device path. If the code
647 is compiled to conform with the UEFI 2.0 specification use the new device path
648 else use the old form for backwards compatability. The return value to this
649 function points to a location in FvDevicePathNode and it does not allocate
650 new memory for the GUID pointer that is returned.
654 FvDevicePathNode - Pointer to FV device path to check
658 NULL - FvDevicePathNode is not valid.
659 Other - FvDevicePathNode is valid and pointer to NameGuid was returned.
664 // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
665 // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with
666 // EFI 1.10 and UEFI 2.10.
668 if (DevicePathType (&FvDevicePathNode
->Header
) == MEDIA_DEVICE_PATH
&&
669 DevicePathSubType (&FvDevicePathNode
->Header
) == MEDIA_FV_FILEPATH_DP
) {
670 return &FvDevicePathNode
->NameGuid
;