]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/DevicePath/Dxe/DevicePathUtilities.c
Someone lost a new line at the end of file, it causes GCC build error.
[mirror_edk2.git] / EdkModulePkg / Universal / DevicePath / Dxe / DevicePathUtilities.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 DevicePathUtilities.c
15
16 Abstract:
17
18 Implementation file for Device Path Utilities Protocol
19
20 --*/
21
22 #include <protocol/DevicePathUtilities.h>
23 #include <protocol/DevicePath.h>
24 #include "DevicePath.h"
25
26 UINTN
27 GetDevicePathSize (
28 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
29 )
30 /*++
31
32 Routine Description:
33 Returns the size of the device path, in bytes.
34
35 Arguments:
36 DevicePath - Points to the start of the EFI device path.
37
38 Returns:
39 Size - Size of the specified device path, in bytes, including the end-of-path tag.
40
41 --*/
42 {
43 CONST EFI_DEVICE_PATH_PROTOCOL *Start;
44
45 if (DevicePath == NULL) {
46 return 0;
47 }
48
49 //
50 // Search for the end of the device path structure
51 //
52 Start = (EFI_DEVICE_PATH_PROTOCOL *) DevicePath;
53 while (!IsDevicePathEnd (DevicePath)) {
54 DevicePath = NextDevicePathNode (DevicePath);
55 }
56
57 //
58 // Compute the size and add back in the size of the end device path structure
59 //
60 return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
61 }
62
63 EFI_DEVICE_PATH_PROTOCOL *
64 DuplicateDevicePath (
65 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
66 )
67 /*++
68
69 Routine Description:
70 Create a duplicate of the specified path.
71
72 Arguments:
73 DevicePath - Points to the source EFI device path.
74
75 Returns:
76 Pointer - A pointer to the duplicate device path.
77 NULL - Insufficient memory.
78
79 --*/
80 {
81 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
82 UINTN Size;
83
84 if (DevicePath == NULL) {
85 return NULL;
86 }
87
88 //
89 // Compute the size
90 //
91 Size = GetDevicePathSize (DevicePath);
92 if (Size == 0) {
93 return NULL;
94 }
95
96 //
97 // Allocate space for duplicate device path
98 //
99 NewDevicePath = AllocateCopyPool (Size, (VOID *) DevicePath);
100
101 return NewDevicePath;
102 }
103
104 EFI_DEVICE_PATH_PROTOCOL *
105 AppendDevicePath (
106 IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1,
107 IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2
108 )
109 /*++
110
111 Routine Description:
112 Create a new path by appending the second device path to the first.
113
114 Arguments:
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.
117
118 Returns:
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.
122
123 --*/
124 {
125 UINTN Size;
126 UINTN Size1;
127 UINTN Size2;
128 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
129 EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;
130
131 //
132 // If there's only 1 path, just duplicate it
133 //
134 if (Src1 == NULL) {
135 ASSERT (!IsDevicePathUnpacked (Src2));
136 return DuplicateDevicePath (Src2);
137 }
138
139 if (Src2 == NULL) {
140 ASSERT (!IsDevicePathUnpacked (Src1));
141 return DuplicateDevicePath (Src1);
142 }
143
144 //
145 // Allocate space for the combined device path. It only has one end node of
146 // length EFI_DEVICE_PATH_PROTOCOL
147 //
148 Size1 = GetDevicePathSize (Src1);
149 Size2 = GetDevicePathSize (Src2);
150 Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);
151
152 NewDevicePath = AllocateCopyPool (Size, (VOID *) Src1);
153
154 if (NewDevicePath != NULL) {
155 //
156 // Over write Src1 EndNode and do the copy
157 //
158 SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
159 CopyMem (SecondDevicePath, (VOID *) Src2, Size2);
160 }
161
162 return NewDevicePath;
163 }
164
165 EFI_DEVICE_PATH_PROTOCOL *
166 AppendDeviceNode (
167 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
168 IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode
169 )
170 /*++
171
172 Routine Description:
173 Creates a new path by appending the device node to the device path.
174
175 Arguments:
176 DevicePath - Points to the device path.
177 DeviceNode - Points to the device node.
178
179 Returns:
180 Pointer - A pointer to the allocated device node.
181 NULL - Memory could not be allocated
182 or either DevicePath or DeviceNode is NULL.
183
184 --*/
185 {
186 EFI_DEVICE_PATH_PROTOCOL *Temp;
187 EFI_DEVICE_PATH_PROTOCOL *NextNode;
188 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
189 UINTN NodeLength;
190
191 if ((DevicePath == NULL) || (DeviceNode == NULL)) {
192 return NULL;
193 }
194
195 //
196 // Build a Node that has a terminator on it
197 //
198 NodeLength = DevicePathNodeLength (DeviceNode);
199
200 Temp = AllocateCopyPool (NodeLength + sizeof (EFI_DEVICE_PATH_PROTOCOL), (VOID *) DeviceNode);
201 if (Temp == NULL) {
202 return NULL;
203 }
204
205 //
206 // Add and end device path node to convert Node to device path
207 //
208 NextNode = NextDevicePathNode (Temp);
209 SetDevicePathEndNode (NextNode);
210
211 //
212 // Append device paths
213 //
214 NewDevicePath = AppendDevicePath (DevicePath, Temp);
215 gBS->FreePool (Temp);
216 return NewDevicePath;
217 }
218
219 EFI_DEVICE_PATH_PROTOCOL *
220 AppendDevicePathInstance (
221 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
222 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
223 )
224 /*++
225
226 Routine Description:
227 Creates a new path by appending the specified device path instance to the specified device path.
228
229 Arguments:
230 DevicePath - Points to the device path. If NULL, then ignored.
231 DevicePathInstance - Points to the device path instance.
232
233 Returns:
234 Pointer - A pointer to the newly created device path
235 NULL - Memory could not be allocated or DevicePathInstance is NULL.
236
237 --*/
238 {
239 UINT8 *Ptr;
240 EFI_DEVICE_PATH_PROTOCOL *DevPath;
241 UINTN SrcSize;
242 UINTN InstanceSize;
243
244 if (DevicePathInstance == NULL) {
245 return NULL;
246 }
247
248 if (DevicePath == NULL) {
249 return DuplicateDevicePath (DevicePathInstance);
250 }
251
252 SrcSize = GetDevicePathSize (DevicePath);
253 InstanceSize = GetDevicePathSize (DevicePathInstance);
254
255 Ptr = AllocateCopyPool (SrcSize + InstanceSize, (VOID *) DevicePath);
256 if (Ptr != NULL) {
257
258 DevPath = (EFI_DEVICE_PATH_PROTOCOL *) (Ptr + (SrcSize - sizeof (EFI_DEVICE_PATH_PROTOCOL)));
259 //
260 // Convert the End to an End Instance, since we are
261 // appending another instacne after this one its a good
262 // idea.
263 //
264 DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
265
266 DevPath = NextDevicePathNode (DevPath);
267 CopyMem (DevPath, (VOID *) DevicePathInstance, InstanceSize);
268 }
269
270 return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
271 }
272
273 EFI_DEVICE_PATH_PROTOCOL *
274 GetNextDevicePathInstance (
275 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance,
276 OUT UINTN *DevicePathInstanceSize
277 )
278 /*++
279
280 Routine Description:
281 Creates a copy of the current device path instance and returns a pointer to the next device path instance.
282
283 Arguments:
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.
290
291 Returns:
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.
294
295 --*/
296 {
297 EFI_DEVICE_PATH_PROTOCOL *DevPath;
298 EFI_DEVICE_PATH_PROTOCOL *ReturnValue;
299 UINT8 Temp;
300
301 if (*DevicePathInstance == NULL) {
302 if (DevicePathInstanceSize != NULL) {
303 *DevicePathInstanceSize = 0;
304 }
305
306 return NULL;
307 }
308
309 //
310 // Find the end of the device path instance
311 //
312 DevPath = *DevicePathInstance;
313 while (!IsDevicePathEndType (DevPath)) {
314 DevPath = NextDevicePathNode (DevPath);
315 }
316
317 //
318 // Compute the size of the device path instance
319 //
320 if (DevicePathInstanceSize != NULL) {
321 *DevicePathInstanceSize = ((UINTN) DevPath - (UINTN) (*DevicePathInstance)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
322 }
323
324 //
325 // Make a copy and return the device path instance
326 //
327 Temp = DevPath->SubType;
328 DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
329 ReturnValue = DuplicateDevicePath (*DevicePathInstance);
330 DevPath->SubType = Temp;
331
332 //
333 // If DevPath is the end of an entire device path, then another instance
334 // does not follow, so *DevicePath is set to NULL.
335 //
336 if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
337 *DevicePathInstance = NULL;
338 } else {
339 *DevicePathInstance = NextDevicePathNode (DevPath);
340 }
341
342 return ReturnValue;
343 }
344
345 BOOLEAN
346 IsDevicePathMultiInstance (
347 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
348 )
349 /*++
350
351 Routine Description:
352 Returns whether a device path is multi-instance.
353
354 Arguments:
355 DevicePath - Points to the device path. If NULL, then ignored.
356
357 Returns:
358 TRUE - The device path has more than one instance
359 FALSE - The device path is empty or contains only a single instance.
360
361 --*/
362 {
363 CONST EFI_DEVICE_PATH_PROTOCOL *Node;
364
365 if (DevicePath == NULL) {
366 return FALSE;
367 }
368
369 Node = DevicePath;
370 while (!IsDevicePathEnd (Node)) {
371 if (EfiIsDevicePathEndInstance (Node)) {
372 return TRUE;
373 }
374
375 Node = NextDevicePathNode (Node);
376 }
377
378 return FALSE;
379 }
380
381 EFI_DEVICE_PATH_PROTOCOL *
382 CreateDeviceNode (
383 IN UINT8 NodeType,
384 IN UINT8 NodeSubType,
385 IN UINT16 NodeLength
386 )
387 /*++
388
389 Routine Description:
390 Creates a device node
391
392 Arguments:
393 NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for
394 the new device node.
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.
399
400 Returns:
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.
404
405 --*/
406 {
407 EFI_DEVICE_PATH_PROTOCOL *Node;
408
409 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
410 return NULL;
411 }
412
413 Node = (EFI_DEVICE_PATH_PROTOCOL *) AllocateZeroPool ((UINTN) NodeLength);
414 if (Node != NULL) {
415 Node->Type = NodeType;
416 Node->SubType = NodeSubType;
417 SetDevicePathNodeLength (Node, NodeLength);
418 }
419
420 return Node;
421 }