3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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 Implementation file for Device Path Utilities Protocol
22 #include <protocol/DevicePathUtilities.h>
23 #include <protocol/DevicePath.h>
24 #include "DevicePath.h"
28 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
33 Returns the size of the device path, in bytes.
36 DevicePath - Points to the start of the EFI device path.
39 Size - Size of the specified device path, in bytes, including the end-of-path tag.
43 CONST EFI_DEVICE_PATH_PROTOCOL
*Start
;
45 if (DevicePath
== NULL
) {
50 // Search for the end of the device path structure
52 Start
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
;
53 while (!IsDevicePathEnd (DevicePath
)) {
54 DevicePath
= NextDevicePathNode (DevicePath
);
58 // Compute the size and add back in the size of the end device path structure
60 return ((UINTN
) DevicePath
- (UINTN
) Start
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
63 EFI_DEVICE_PATH_PROTOCOL
*
65 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
70 Create a duplicate of the specified path.
73 DevicePath - Points to the source EFI device path.
76 Pointer - A pointer to the duplicate device path.
77 NULL - Insufficient memory.
81 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
84 if (DevicePath
== NULL
) {
91 Size
= GetDevicePathSize (DevicePath
);
97 // Allocate space for duplicate device path
99 NewDevicePath
= AllocateCopyPool (Size
, (VOID
*) DevicePath
);
101 return NewDevicePath
;
104 EFI_DEVICE_PATH_PROTOCOL
*
106 IN CONST EFI_DEVICE_PATH_PROTOCOL
*Src1
,
107 IN CONST EFI_DEVICE_PATH_PROTOCOL
*Src2
112 Create a new path by appending the second device path to the first.
115 Src1 - Points to the first device path. If NULL, then it is ignored.
116 Src2 - Points to the second device path. If NULL, then it is ignored.
119 Pointer - A pointer to the newly created device path.
120 NULL - Memory could not be allocated
121 or either DevicePath or DeviceNode is NULL.
128 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
129 EFI_DEVICE_PATH_PROTOCOL
*SecondDevicePath
;
132 // If there's only 1 path, just duplicate it
135 ASSERT (!IsDevicePathUnpacked (Src2
));
136 return DuplicateDevicePath (Src2
);
140 ASSERT (!IsDevicePathUnpacked (Src1
));
141 return DuplicateDevicePath (Src1
);
145 // Allocate space for the combined device path. It only has one end node of
146 // length EFI_DEVICE_PATH_PROTOCOL
148 Size1
= GetDevicePathSize (Src1
);
149 Size2
= GetDevicePathSize (Src2
);
150 Size
= Size1
+ Size2
- sizeof (EFI_DEVICE_PATH_PROTOCOL
);
152 NewDevicePath
= AllocateCopyPool (Size
, (VOID
*) Src1
);
154 if (NewDevicePath
!= NULL
) {
156 // Over write Src1 EndNode and do the copy
158 SecondDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) ((CHAR8
*) NewDevicePath
+ (Size1
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
159 CopyMem (SecondDevicePath
, (VOID
*) Src2
, Size2
);
162 return NewDevicePath
;
165 EFI_DEVICE_PATH_PROTOCOL
*
167 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
168 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DeviceNode
173 Creates a new path by appending the device node to the device path.
176 DevicePath - Points to the device path.
177 DeviceNode - Points to the device node.
180 Pointer - A pointer to the allocated device node.
181 NULL - Memory could not be allocated
182 or either DevicePath or DeviceNode is NULL.
186 EFI_DEVICE_PATH_PROTOCOL
*Temp
;
187 EFI_DEVICE_PATH_PROTOCOL
*NextNode
;
188 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
191 if ((DevicePath
== NULL
) || (DeviceNode
== NULL
)) {
196 // Build a Node that has a terminator on it
198 NodeLength
= DevicePathNodeLength (DeviceNode
);
200 Temp
= AllocateCopyPool (NodeLength
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
), (VOID
*) DeviceNode
);
206 // Add and end device path node to convert Node to device path
208 NextNode
= NextDevicePathNode (Temp
);
209 SetDevicePathEndNode (NextNode
);
212 // Append device paths
214 NewDevicePath
= AppendDevicePath (DevicePath
, Temp
);
215 gBS
->FreePool (Temp
);
216 return NewDevicePath
;
219 EFI_DEVICE_PATH_PROTOCOL
*
220 AppendDevicePathInstance (
221 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
222 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
227 Creates a new path by appending the specified device path instance to the specified device path.
230 DevicePath - Points to the device path. If NULL, then ignored.
231 DevicePathInstance - Points to the device path instance.
234 Pointer - A pointer to the newly created device path
235 NULL - Memory could not be allocated or DevicePathInstance is NULL.
240 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
244 if (DevicePathInstance
== NULL
) {
248 if (DevicePath
== NULL
) {
249 return DuplicateDevicePath (DevicePathInstance
);
252 SrcSize
= GetDevicePathSize (DevicePath
);
253 InstanceSize
= GetDevicePathSize (DevicePathInstance
);
255 Ptr
= AllocateCopyPool (SrcSize
+ InstanceSize
, (VOID
*) DevicePath
);
258 DevPath
= (EFI_DEVICE_PATH_PROTOCOL
*) (Ptr
+ (SrcSize
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)));
260 // Convert the End to an End Instance, since we are
261 // appending another instacne after this one its a good
264 DevPath
->SubType
= END_INSTANCE_DEVICE_PATH_SUBTYPE
;
266 DevPath
= NextDevicePathNode (DevPath
);
267 CopyMem (DevPath
, (VOID
*) DevicePathInstance
, InstanceSize
);
270 return (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
273 EFI_DEVICE_PATH_PROTOCOL
*
274 GetNextDevicePathInstance (
275 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathInstance
,
276 OUT UINTN
*DevicePathInstanceSize
281 Creates a copy of the current device path instance and returns a pointer to the next device path instance.
284 DevicePathInstance - On input, this holds the pointer to the current device path
285 instance. On output, this holds the pointer to the next
286 device path instance or NULL if there are no more device
287 path instances in the device path.
288 DevicePathInstanceSize - On output, this holds the size of the device path instance,
289 in bytes or zero, if DevicePathInstance is zero.
292 Pointer - A pointer to the copy of the current device path instance.
293 NULL - DevicePathInstace was NULL on entry or there was insufficient memory.
297 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
298 EFI_DEVICE_PATH_PROTOCOL
*ReturnValue
;
301 if (*DevicePathInstance
== NULL
) {
302 if (DevicePathInstanceSize
!= NULL
) {
303 *DevicePathInstanceSize
= 0;
310 // Find the end of the device path instance
312 DevPath
= *DevicePathInstance
;
313 while (!IsDevicePathEndType (DevPath
)) {
314 DevPath
= NextDevicePathNode (DevPath
);
318 // Compute the size of the device path instance
320 if (DevicePathInstanceSize
!= NULL
) {
321 *DevicePathInstanceSize
= ((UINTN
) DevPath
- (UINTN
) (*DevicePathInstance
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
325 // Make a copy and return the device path instance
327 Temp
= DevPath
->SubType
;
328 DevPath
->SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
329 ReturnValue
= DuplicateDevicePath (*DevicePathInstance
);
330 DevPath
->SubType
= Temp
;
333 // If DevPath is the end of an entire device path, then another instance
334 // does not follow, so *DevicePath is set to NULL.
336 if (DevicePathSubType (DevPath
) == END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
337 *DevicePathInstance
= NULL
;
339 *DevicePathInstance
= NextDevicePathNode (DevPath
);
346 IsDevicePathMultiInstance (
347 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
352 Returns whether a device path is multi-instance.
355 DevicePath - Points to the device path. If NULL, then ignored.
358 TRUE - The device path has more than one instance
359 FALSE - The device path is empty or contains only a single instance.
363 CONST EFI_DEVICE_PATH_PROTOCOL
*Node
;
365 if (DevicePath
== NULL
) {
370 while (!IsDevicePathEnd (Node
)) {
371 if (EfiIsDevicePathEndInstance (Node
)) {
375 Node
= NextDevicePathNode (Node
);
381 EFI_DEVICE_PATH_PROTOCOL
*
384 IN UINT8 NodeSubType
,
390 Creates a device node
393 NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for
395 NodeSubType - NodeSubType is the device node sub-type
396 EFI_DEVICE_PATH.SubType) for the new device node.
397 NodeLength - NodeLength is the length of the device node
398 (EFI_DEVICE_PATH.Length) for the new device node.
401 Pointer - A pointer to the newly created device node.
402 NULL - NodeLength is less than
403 the size of the header or there was insufficient memory.
407 EFI_DEVICE_PATH_PROTOCOL
*Node
;
409 if (NodeLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
413 Node
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocateZeroPool ((UINTN
) NodeLength
);
415 Node
->Type
= NodeType
;
416 Node
->SubType
= NodeSubType
;
417 SetDevicePathNodeLength (Node
, NodeLength
);