]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c
Add comment to explain use of the types "int" and "unsigned int" in the implementatio...
[mirror_edk2.git] / MdePkg / Library / UefiDevicePathLib / UefiDevicePathLib.c
CommitLineData
e386b444 1/** @file\r
2 Device Path services. The thing to remember is device paths are built out of\r
3 nodes. The device path is terminated by an end node that is length\r
4 sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)\r
5 all over this file.\r
6\r
7 The only place where multi-instance device paths are supported is in\r
8 environment varibles. Multi-instance device paths should never be placed\r
9 on a Handle.\r
10\r
373ade0e 11 Copyright (c) 2006 - 2008, Intel Corporation \r
e386b444 12 All rights reserved. This program and the accompanying materials \r
13 are licensed and made available under the terms and conditions of the BSD License \r
14 which accompanies this distribution. The full text of the license may be found at \r
15 http://opensource.org/licenses/bsd-license.php \r
16\r
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
19\r
e386b444 20**/\r
21\r
c892d846 22\r
c7d265a9 23#include <Uefi.h>\r
c892d846 24\r
c7d265a9 25#include <Protocol/DevicePath.h>\r
c892d846 26\r
c7d265a9 27#include <Library/DevicePathLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/MemoryAllocationLib.h>\r
31#include <Library/UefiBootServicesTableLib.h>\r
32#include <Library/BaseLib.h>\r
e386b444 33\r
98a14db6 34//\r
35// Template for an end-of-device path node.\r
36//\r
34abfd7c 37GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = {\r
98a14db6 38 END_DEVICE_PATH_TYPE,\r
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
697f4d59 40 {\r
41 END_DEVICE_PATH_LENGTH,\r
42 0\r
43 }\r
98a14db6 44};\r
45\r
e386b444 46/**\r
47 Returns the size of a device path in bytes.\r
48\r
49 This function returns the size, in bytes, of the device path data structure specified by\r
50 DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned.\r
51\r
52 @param DevicePath A pointer to a device path data structure.\r
3e5c3238 53 \r
54 @retval 0 If DevicePath is NULL.\r
55 @retval Others The size of a device path in bytes.\r
e386b444 56\r
57**/\r
58UINTN\r
59EFIAPI\r
60GetDevicePathSize (\r
61 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
62 )\r
63{\r
64 CONST EFI_DEVICE_PATH_PROTOCOL *Start;\r
65\r
66 if (DevicePath == NULL) {\r
67 return 0;\r
68 }\r
69\r
70 //\r
71 // Search for the end of the device path structure\r
72 //\r
73 Start = DevicePath;\r
e5dab016 74 while (!IsDevicePathEnd (DevicePath)) {\r
75 DevicePath = NextDevicePathNode (DevicePath);\r
e386b444 76 }\r
77\r
78 //\r
79 // Compute the size and add back in the size of the end device path structure\r
80 //\r
e5dab016 81 return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);\r
e386b444 82}\r
83\r
84/**\r
6a3f4ef9 85 Creates a new copy of an existing device path.\r
e386b444 86\r
87 This function allocates space for a new copy of the device path specified by DevicePath. If\r
88 DevicePath is NULL, then NULL is returned. If the memory is successfully allocated, then the\r
89 contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer\r
90 is returned. Otherwise, NULL is returned. \r
3e5c3238 91 The memory for the new device path is allocated from EFI boot services memory. \r
92 It is the responsibility of the caller to free the memory allocated. \r
e386b444 93 \r
94 @param DevicePath A pointer to a device path data structure.\r
95\r
3e5c3238 96 @retval NULL If DevicePath is NULL.\r
97 @retval Others A pointer to the duplicated device path.\r
98 \r
e386b444 99**/\r
100EFI_DEVICE_PATH_PROTOCOL *\r
101EFIAPI\r
102DuplicateDevicePath (\r
103 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
104 )\r
105{\r
e386b444 106 UINTN Size;\r
107\r
108 //\r
109 // Compute the size\r
110 //\r
111 Size = GetDevicePathSize (DevicePath);\r
112 if (Size == 0) {\r
113 return NULL;\r
114 }\r
115\r
116 //\r
117 // Allocate space for duplicate device path\r
118 //\r
e386b444 119\r
f008fc32 120 return AllocateCopyPool (Size, DevicePath);\r
e386b444 121}\r
122\r
123/**\r
124 Creates a new device path by appending a second device path to a first device path.\r
125\r
126 This function creates a new device path by appending a copy of SecondDevicePath to a copy of\r
127 FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from\r
128 SecondDevicePath is retained. The newly created device path is returned. \r
129 If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned. \r
130 If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned. \r
98a14db6 131 If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is\r
132 returned. \r
e386b444 133 If there is not enough memory for the newly allocated buffer, then NULL is returned.\r
134 The memory for the new device path is allocated from EFI boot services memory. It is the\r
135 responsibility of the caller to free the memory allocated.\r
136\r
137 @param FirstDevicePath A pointer to a device path data structure.\r
138 @param SecondDevicePath A pointer to a device path data structure.\r
3e5c3238 139 \r
140 @retval NULL If there is not enough memory for the newly allocated buffer.\r
141 @retval Others A pointer to the new device path if success.\r
142 Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.\r
e386b444 143\r
144**/\r
145EFI_DEVICE_PATH_PROTOCOL *\r
146EFIAPI\r
147AppendDevicePath (\r
148 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL\r
149 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL\r
150 )\r
151{\r
152 UINTN Size;\r
153 UINTN Size1;\r
154 UINTN Size2;\r
155 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
156 EFI_DEVICE_PATH_PROTOCOL *DevicePath2;\r
157\r
158 //\r
159 // If there's only 1 path, just duplicate it.\r
160 //\r
161 if (FirstDevicePath == NULL) {\r
34abfd7c 162 return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath);\r
e386b444 163 }\r
164\r
165 if (SecondDevicePath == NULL) {\r
166 return DuplicateDevicePath (FirstDevicePath);\r
167 }\r
168\r
169 //\r
170 // Allocate space for the combined device path. It only has one end node of\r
171 // length EFI_DEVICE_PATH_PROTOCOL.\r
172 //\r
173 Size1 = GetDevicePathSize (FirstDevicePath);\r
174 Size2 = GetDevicePathSize (SecondDevicePath);\r
e5dab016 175 Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH;\r
e386b444 176\r
177 NewDevicePath = AllocatePool (Size);\r
178\r
179 if (NewDevicePath != NULL) {\r
180 NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1);\r
181 //\r
182 // Over write FirstDevicePath EndNode and do the copy\r
183 //\r
184 DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath +\r
e5dab016 185 (Size1 - END_DEVICE_PATH_LENGTH));\r
e386b444 186 CopyMem (DevicePath2, SecondDevicePath, Size2);\r
187 }\r
188\r
189 return NewDevicePath;\r
190}\r
191\r
192/**\r
193 Creates a new path by appending the device node to the device path.\r
194\r
195 This function creates a new device path by appending a copy of the device node specified by\r
196 DevicePathNode to a copy of the device path specified by DevicePath in an allocated buffer.\r
197 The end-of-device-path device node is moved after the end of the appended device node.\r
98a14db6 198 If DevicePathNode is NULL then a copy of DevicePath is returned.\r
6336a895 199 If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device path device\r
200 node is returned.\r
98a14db6 201 If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path device node\r
202 is returned.\r
e386b444 203 If there is not enough memory to allocate space for the new device path, then NULL is returned. \r
204 The memory is allocated from EFI boot services memory. It is the responsibility of the caller to\r
205 free the memory allocated.\r
206\r
207 @param DevicePath A pointer to a device path data structure.\r
208 @param DevicePathNode A pointer to a single device path node.\r
209\r
3e5c3238 210 @retval NULL If there is not enough memory for the new device path.\r
211 @retval Others A pointer to the new device path if success.\r
212 A copy of DevicePathNode followed by an end-of-device-path node \r
213 if both FirstDevicePath and SecondDevicePath are NULL.\r
214 A copy of an end-of-device-path node if both FirstDevicePath and SecondDevicePath are NULL.\r
e386b444 215\r
216**/\r
217EFI_DEVICE_PATH_PROTOCOL *\r
218EFIAPI\r
219AppendDevicePathNode (\r
220 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL\r
221 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL\r
222 )\r
223{\r
224 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
225 EFI_DEVICE_PATH_PROTOCOL *NextNode;\r
226 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
227 UINTN NodeLength;\r
228\r
98a14db6 229 if (DevicePathNode == NULL) {\r
34abfd7c 230 return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath);\r
e386b444 231 }\r
232 //\r
233 // Build a Node that has a terminator on it\r
234 //\r
235 NodeLength = DevicePathNodeLength (DevicePathNode);\r
236\r
e5dab016 237 TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH);\r
e386b444 238 if (TempDevicePath == NULL) {\r
239 return NULL;\r
240 }\r
241 TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength);\r
242 //\r
243 // Add and end device path node to convert Node to device path\r
244 //\r
245 NextNode = NextDevicePathNode (TempDevicePath);\r
246 SetDevicePathEndNode (NextNode);\r
247 //\r
248 // Append device paths\r
249 //\r
250 NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath);\r
251\r
252 FreePool (TempDevicePath);\r
253\r
254 return NewDevicePath;\r
255}\r
256\r
257/**\r
258 Creates a new device path by appending the specified device path instance to the specified device\r
259 path.\r
260 \r
261 This function creates a new device path by appending a copy of the device path instance specified\r
262 by DevicePathInstance to a copy of the device path secified by DevicePath in a allocated buffer.\r
263 The end-of-device-path device node is moved after the end of the appended device path instance\r
264 and a new end-of-device-path-instance node is inserted between. \r
265 If DevicePath is NULL, then a copy if DevicePathInstance is returned.\r
266 If DevicePathInstance is NULL, then NULL is returned.\r
267 If there is not enough memory to allocate space for the new device path, then NULL is returned. \r
268 The memory is allocated from EFI boot services memory. It is the responsibility of the caller to\r
269 free the memory allocated.\r
270 \r
271 @param DevicePath A pointer to a device path data structure.\r
272 @param DevicePathInstance A pointer to a device path instance.\r
273\r
274 @return A pointer to the new device path.\r
275\r
276**/\r
277EFI_DEVICE_PATH_PROTOCOL *\r
278EFIAPI\r
279AppendDevicePathInstance (\r
280 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL\r
281 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL\r
282 )\r
283{\r
284 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
285 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
286 UINTN SrcSize;\r
287 UINTN InstanceSize;\r
288\r
289 if (DevicePath == NULL) {\r
290 return DuplicateDevicePath (DevicePathInstance);\r
291 }\r
292\r
293 if (DevicePathInstance == NULL) {\r
294 return NULL;\r
295 }\r
296\r
297 SrcSize = GetDevicePathSize (DevicePath);\r
298 InstanceSize = GetDevicePathSize (DevicePathInstance);\r
299\r
300 NewDevicePath = AllocatePool (SrcSize + InstanceSize);\r
301 if (NewDevicePath != NULL) {\r
302 \r
303 TempDevicePath = CopyMem (NewDevicePath, DevicePath, SrcSize);;\r
304 \r
305 while (!IsDevicePathEnd (TempDevicePath)) {\r
306 TempDevicePath = NextDevicePathNode (TempDevicePath);\r
307 }\r
308 \r
309 TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;\r
310 TempDevicePath = NextDevicePathNode (TempDevicePath);\r
311 CopyMem (TempDevicePath, DevicePathInstance, InstanceSize);\r
312 }\r
313\r
314 return NewDevicePath;\r
315}\r
316\r
317/**\r
318 Creates a copy of the current device path instance and returns a pointer to the next device path\r
319 instance.\r
320\r
321 This function creates a copy of the current device path instance. It also updates DevicePath to\r
322 point to the next device path instance in the device path (or NULL if no more) and updates Size\r
323 to hold the size of the device path instance copy.\r
324 If DevicePath is NULL, then NULL is returned.\r
325 If there is not enough memory to allocate space for the new device path, then NULL is returned. \r
326 The memory is allocated from EFI boot services memory. It is the responsibility of the caller to\r
327 free the memory allocated.\r
328 If Size is NULL, then ASSERT().\r
329 \r
330 @param DevicePath On input, this holds the pointer to the current device path\r
331 instance. On output, this holds the pointer to the next device\r
332 path instance or NULL if there are no more device path\r
333 instances in the device path pointer to a device path data\r
334 structure.\r
335 @param Size On output, this holds the size of the device path instance, in\r
336 bytes or zero, if DevicePath is NULL.\r
337\r
338 @return A pointer to the current device path instance.\r
339\r
340**/\r
341EFI_DEVICE_PATH_PROTOCOL *\r
342EFIAPI\r
343GetNextDevicePathInstance (\r
344 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
345 OUT UINTN *Size\r
346 )\r
347{\r
348 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
349 EFI_DEVICE_PATH_PROTOCOL *ReturnValue;\r
350 UINT8 Temp;\r
351\r
352 ASSERT (Size != NULL);\r
353\r
354 if (DevicePath == NULL || *DevicePath == NULL) {\r
355 *Size = 0;\r
356 return NULL;\r
357 }\r
358\r
359 //\r
360 // Find the end of the device path instance\r
361 //\r
362 DevPath = *DevicePath;\r
363 while (!IsDevicePathEndType (DevPath)) {\r
364 DevPath = NextDevicePathNode (DevPath);\r
365 }\r
366\r
367 //\r
368 // Compute the size of the device path instance\r
369 //\r
370 *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
371 \r
372 //\r
373 // Make a copy and return the device path instance\r
374 //\r
375 Temp = DevPath->SubType;\r
376 DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
377 ReturnValue = DuplicateDevicePath (*DevicePath);\r
378 DevPath->SubType = Temp;\r
379\r
380 //\r
381 // If DevPath is the end of an entire device path, then another instance\r
382 // does not follow, so *DevicePath is set to NULL.\r
383 //\r
384 if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {\r
385 *DevicePath = NULL;\r
386 } else {\r
387 *DevicePath = NextDevicePathNode (DevPath);\r
388 }\r
389\r
390 return ReturnValue;\r
391}\r
392\r
393/**\r
3e5c3238 394 Creates a device node.\r
e386b444 395\r
396 This function creates a new device node in a newly allocated buffer of size NodeLength and\r
397 initializes the device path node header with NodeType and NodeSubType. The new device path node\r
398 is returned.\r
399 If NodeLength is smaller than a device path header, then NULL is returned. \r
400 If there is not enough memory to allocate space for the new device path, then NULL is returned. \r
401 The memory is allocated from EFI boot services memory. It is the responsibility of the caller to\r
402 free the memory allocated.\r
403\r
404 @param NodeType The device node type for the new device node.\r
405 @param NodeSubType The device node sub-type for the new device node.\r
406 @param NodeLength The length of the new device node.\r
407\r
3e5c3238 408 @return The new device path.\r
e386b444 409\r
410**/\r
411EFI_DEVICE_PATH_PROTOCOL *\r
412EFIAPI\r
413CreateDeviceNode (\r
414 IN UINT8 NodeType,\r
415 IN UINT8 NodeSubType,\r
416 IN UINT16 NodeLength\r
417 )\r
418{\r
419 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
420\r
421 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
422 //\r
423 // NodeLength is less than the size of the header.\r
424 //\r
425 return NULL;\r
426 }\r
427 \r
6577541d 428 DevicePath = AllocateZeroPool (NodeLength);\r
e386b444 429 if (DevicePath != NULL) {\r
430 DevicePath->Type = NodeType;\r
431 DevicePath->SubType = NodeSubType;\r
432 SetDevicePathNodeLength (DevicePath, NodeLength);\r
433 }\r
434\r
435 return DevicePath;\r
436}\r
437\r
438/**\r
439 Determines if a device path is single or multi-instance.\r
440\r
441 This function returns TRUE if the device path specified by DevicePath is multi-instance.\r
442 Otherwise, FALSE is returned. If DevicePath is NULL, then FALSE is returned.\r
443\r
444 @param DevicePath A pointer to a device path data structure.\r
445\r
446 @retval TRUE DevicePath is multi-instance.\r
447 @retval FALSE DevicePath is not multi-instance or DevicePath is NULL.\r
448\r
449**/\r
450BOOLEAN\r
451EFIAPI\r
452IsDevicePathMultiInstance (\r
453 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
454 )\r
455{\r
456 CONST EFI_DEVICE_PATH_PROTOCOL *Node;\r
457\r
458 if (DevicePath == NULL) {\r
459 return FALSE;\r
460 }\r
461\r
462 Node = DevicePath;\r
e5dab016 463 while (!IsDevicePathEnd (Node)) {\r
464 if (IsDevicePathEndInstance (Node)) {\r
e386b444 465 return TRUE;\r
466 }\r
467\r
e5dab016 468 Node = NextDevicePathNode (Node);\r
e386b444 469 }\r
470\r
471 return FALSE;\r
472}\r
473\r
474\r
475/**\r
476 Retrieves the device path protocol from a handle.\r
477\r
478 This function returns the device path protocol from the handle specified by Handle. If Handle is\r
479 NULL or Handle does not contain a device path protocol, then NULL is returned.\r
480 \r
481 @param Handle The handle from which to retrieve the device path protocol.\r
482\r
483 @return The device path protocol from the handle specified by Handle.\r
484\r
485**/\r
486EFI_DEVICE_PATH_PROTOCOL *\r
487EFIAPI\r
488DevicePathFromHandle (\r
489 IN EFI_HANDLE Handle\r
490 )\r
491{\r
492 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
493 EFI_STATUS Status;\r
494\r
495 Status = gBS->HandleProtocol (\r
496 Handle,\r
497 &gEfiDevicePathProtocolGuid,\r
498 (VOID *) &DevicePath\r
499 );\r
500 if (EFI_ERROR (Status)) {\r
501 DevicePath = NULL;\r
502 }\r
503 return DevicePath;\r
504}\r
505\r
506/**\r
507 Allocates a device path for a file and appends it to an existing device path.\r
508\r
509 If Device is a valid device handle that contains a device path protocol, then a device path for\r
510 the file specified by FileName is allocated and appended to the device path associated with the\r
511 handle Device. The allocated device path is returned. If Device is NULL or Device is a handle\r
512 that does not support the device path protocol, then a device path containing a single device\r
513 path node for the file specified by FileName is allocated and returned.\r
3e5c3238 514 The memory for the new device path is allocated from EFI boot services memory. It is the responsibility\r
515 of the caller to free the memory allocated.\r
516 \r
e386b444 517 If FileName is NULL, then ASSERT().\r
3e5c3238 518 If FileName is not aligned on a 16-bit boundary, then ASSERT().\r
e386b444 519\r
520 @param Device A pointer to a device handle. This parameter is optional and\r
521 may be NULL.\r
522 @param FileName A pointer to a Null-terminated Unicode string.\r
523\r
3e5c3238 524 @return The allocated device path.\r
e386b444 525\r
526**/\r
527EFI_DEVICE_PATH_PROTOCOL *\r
528EFIAPI\r
529FileDevicePath (\r
530 IN EFI_HANDLE Device, OPTIONAL\r
531 IN CONST CHAR16 *FileName\r
532 )\r
533{\r
e5dab016 534 UINT16 Size;\r
e386b444 535 FILEPATH_DEVICE_PATH *FilePath;\r
536 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
537 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;\r
538\r
539 DevicePath = NULL;\r
540\r
e5dab016 541 Size = (UINT16) StrSize (FileName);\r
542 \r
543 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);\r
e386b444 544 if (FileDevicePath != NULL) {\r
545 FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;\r
546 FilePath->Header.Type = MEDIA_DEVICE_PATH;\r
547 FilePath->Header.SubType = MEDIA_FILEPATH_DP;\r
548 CopyMem (&FilePath->PathName, FileName, Size);\r
549 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);\r
550 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));\r
551\r
552 if (Device != NULL) {\r
553 DevicePath = DevicePathFromHandle (Device);\r
554 }\r
555\r
556 DevicePath = AppendDevicePath (DevicePath, FileDevicePath);\r
557 FreePool (FileDevicePath);\r
558 }\r
559\r
560 return DevicePath;\r
561}\r
562\r