]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c
Handle the case when OpROM wants to completely remove itself.
[mirror_edk2.git] / MdePkg / Library / UefiDevicePathLibDevicePathProtocol / UefiDevicePathLib.c
... / ...
CommitLineData
1/** @file\r
2 Library instance that implement UEFI Device Path Library class based on protocol\r
3 gEfiDevicePathUtilitiesProtocolGuid.\r
4\r
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16\r
17#include <Uefi.h>\r
18\r
19#include <Protocol/DevicePathUtilities.h>\r
20\r
21#include <Library/DevicePathLib.h>\r
22#include <Library/DebugLib.h>\r
23#include <Library/BaseLib.h>\r
24#include <Library/MemoryAllocationLib.h>\r
25#include <Library/BaseMemoryLib.h>\r
26#include <Library/UefiBootServicesTableLib.h>\r
27\r
28EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathUtilities = NULL;\r
29\r
30//\r
31// Template for an end-of-device path node.\r
32//\r
33GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = {\r
34 END_DEVICE_PATH_TYPE,\r
35 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
36 {\r
37 END_DEVICE_PATH_LENGTH,\r
38 0\r
39 }\r
40};\r
41\r
42/**\r
43 The constructor function caches the pointer to DevicePathUtilites protocol.\r
44 \r
45 The constructor function locates DevicePathUtilities protocol from protocol database.\r
46 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
47\r
48 @param ImageHandle The firmware allocated handle for the EFI image.\r
49 @param SystemTable A pointer to the EFI System Table.\r
50 \r
51 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
52\r
53**/\r
54EFI_STATUS\r
55EFIAPI\r
56DevicePathLibConstructor (\r
57 IN EFI_HANDLE ImageHandle,\r
58 IN EFI_SYSTEM_TABLE *SystemTable\r
59 )\r
60{\r
61 EFI_STATUS Status;\r
62\r
63 Status = gBS->LocateProtocol (\r
64 &gEfiDevicePathUtilitiesProtocolGuid,\r
65 NULL,\r
66 (VOID**) &mDevicePathUtilities\r
67 );\r
68 ASSERT_EFI_ERROR (Status);\r
69 ASSERT (mDevicePathUtilities != NULL);\r
70\r
71 return Status;\r
72}\r
73\r
74/**\r
75 Returns the Type field of a device path node.\r
76\r
77 Returns the Type field of the device path node specified by Node.\r
78\r
79 If Node is NULL, then ASSERT().\r
80\r
81 @param Node A pointer to a device path node data structure.\r
82\r
83 @return The Type field of the device path node specified by Node.\r
84\r
85**/\r
86UINT8\r
87EFIAPI\r
88DevicePathType (\r
89 IN CONST VOID *Node\r
90 )\r
91{\r
92 ASSERT (Node != NULL);\r
93 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;\r
94}\r
95\r
96/**\r
97 Returns the SubType field of a device path node.\r
98\r
99 Returns the SubType field of the device path node specified by Node.\r
100\r
101 If Node is NULL, then ASSERT().\r
102\r
103 @param Node A pointer to a device path node data structure.\r
104\r
105 @return The SubType field of the device path node specified by Node.\r
106\r
107**/\r
108UINT8\r
109EFIAPI\r
110DevicePathSubType (\r
111 IN CONST VOID *Node\r
112 )\r
113{\r
114 ASSERT (Node != NULL);\r
115 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;\r
116}\r
117\r
118/**\r
119 Returns the 16-bit Length field of a device path node.\r
120\r
121 Returns the 16-bit Length field of the device path node specified by Node. \r
122 Node is not required to be aligned on a 16-bit boundary, so it is recommended\r
123 that a function such as ReadUnaligned16() be used to extract the contents of \r
124 the Length field.\r
125\r
126 If Node is NULL, then ASSERT().\r
127\r
128 @param Node A pointer to a device path node data structure.\r
129\r
130 @return The 16-bit Length field of the device path node specified by Node.\r
131\r
132**/\r
133UINTN\r
134EFIAPI\r
135DevicePathNodeLength (\r
136 IN CONST VOID *Node\r
137 )\r
138{\r
139 ASSERT (Node != NULL);\r
140 return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);\r
141}\r
142\r
143/**\r
144 Returns a pointer to the next node in a device path.\r
145\r
146 Returns a pointer to the device path node that follows the device path node \r
147 specified by Node.\r
148\r
149 If Node is NULL, then ASSERT().\r
150\r
151 @param Node A pointer to a device path node data structure.\r
152\r
153 @return a pointer to the device path node that follows the device path node \r
154 specified by Node.\r
155\r
156**/\r
157EFI_DEVICE_PATH_PROTOCOL *\r
158EFIAPI\r
159NextDevicePathNode (\r
160 IN CONST VOID *Node\r
161 )\r
162{\r
163 ASSERT (Node != NULL);\r
164 return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node));\r
165}\r
166\r
167/**\r
168 Determines if a device path node is an end node of a device path.\r
169 This includes nodes that are the end of a device path instance and nodes that \r
170 are the end of an entire device path.\r
171\r
172 Determines if the device path node specified by Node is an end node of a device path. \r
173 This includes nodes that are the end of a device path instance and nodes that are the \r
174 end of an entire device path. If Node represents an end node of a device path, \r
175 then TRUE is returned. Otherwise, FALSE is returned.\r
176\r
177 If Node is NULL, then ASSERT().\r
178\r
179 @param Node A pointer to a device path node data structure.\r
180\r
181 @retval TRUE The device path node specified by Node is an end node of a device path.\r
182 @retval FALSE The device path node specified by Node is not an end node of \r
183 a device path.\r
184 \r
185**/\r
186BOOLEAN\r
187EFIAPI\r
188IsDevicePathEndType (\r
189 IN CONST VOID *Node\r
190 )\r
191{\r
192 ASSERT (Node != NULL);\r
193 return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);\r
194}\r
195\r
196/**\r
197 Determines if a device path node is an end node of an entire device path.\r
198\r
199 Determines if a device path node specified by Node is an end node of an entire \r
200 device path.\r
201 If Node represents the end of an entire device path, then TRUE is returned. \r
202 Otherwise, FALSE is returned.\r
203\r
204 If Node is NULL, then ASSERT().\r
205\r
206 @param Node A pointer to a device path node data structure.\r
207\r
208 @retval TRUE The device path node specified by Node is the end of an entire device path.\r
209 @retval FALSE The device path node specified by Node is not the end of an entire device path.\r
210\r
211**/\r
212BOOLEAN\r
213EFIAPI\r
214IsDevicePathEnd (\r
215 IN CONST VOID *Node\r
216 )\r
217{\r
218 ASSERT (Node != NULL);\r
219 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);\r
220}\r
221\r
222/**\r
223 Determines if a device path node is an end node of a device path instance.\r
224\r
225 Determines if a device path node specified by Node is an end node of a device \r
226 path instance.\r
227 If Node represents the end of a device path instance, then TRUE is returned. \r
228 Otherwise, FALSE is returned.\r
229\r
230 If Node is NULL, then ASSERT().\r
231\r
232 @param Node A pointer to a device path node data structure.\r
233\r
234 @retval TRUE The device path node specified by Node is the end of a device \r
235 path instance.\r
236 @retval FALSE The device path node specified by Node is not the end of a \r
237 device path instance.\r
238\r
239**/\r
240BOOLEAN\r
241EFIAPI\r
242IsDevicePathEndInstance (\r
243 IN CONST VOID *Node\r
244 )\r
245{\r
246 ASSERT (Node != NULL);\r
247 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);\r
248}\r
249\r
250/**\r
251 Sets the length, in bytes, of a device path node.\r
252\r
253 Sets the length of the device path node specified by Node to the value specified \r
254 by NodeLength. NodeLength is returned. Node is not required to be aligned on \r
255 a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16()\r
256 be used to set the contents of the Length field.\r
257\r
258 If Node is NULL, then ASSERT().\r
259 If NodeLength >= 0x10000, then ASSERT().\r
260\r
261 @param Node A pointer to a device path node data structure.\r
262 @param Length The length, in bytes, of the device path node.\r
263\r
264 @return Length\r
265\r
266**/\r
267UINT16\r
268EFIAPI\r
269SetDevicePathNodeLength (\r
270 IN OUT VOID *Node,\r
271 IN UINTN Length\r
272 )\r
273{\r
274 ASSERT (Node != NULL);\r
275 ASSERT (Length < 0x10000);\r
276 return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));\r
277}\r
278\r
279/**\r
280 Fills in all the fields of a device path node that is the end of an entire device path.\r
281\r
282 Fills in all the fields of a device path node specified by Node so Node represents \r
283 the end of an entire device path. The Type field of Node is set to \r
284 END_DEVICE_PATH_TYPE, the SubType field of Node is set to \r
285 END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to \r
286 END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary, \r
287 so it is recommended that a function such as WriteUnaligned16() be used to set \r
288 the contents of the Length field. \r
289\r
290 If Node is NULL, then ASSERT(). \r
291\r
292 @param Node A pointer to a device path node data structure.\r
293\r
294**/\r
295VOID\r
296EFIAPI\r
297SetDevicePathEndNode (\r
298 OUT VOID *Node\r
299 )\r
300{\r
301 ASSERT (Node != NULL);\r
302 CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));\r
303}\r
304\r
305/**\r
306 Returns the size of a device path in bytes.\r
307\r
308 This function returns the size, in bytes, of the device path data structure specified by\r
309 DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned.\r
310\r
311 @param DevicePath A pointer to a device path data structure.\r
312 \r
313 @retval 0 If DevicePath is NULL.\r
314 @retval Others The size of a device path in bytes.\r
315\r
316**/\r
317UINTN\r
318EFIAPI\r
319GetDevicePathSize (\r
320 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
321 )\r
322{\r
323 return mDevicePathUtilities->GetDevicePathSize (DevicePath);\r
324}\r
325\r
326/**\r
327 Creates a new copy of an existing device path.\r
328\r
329 This function allocates space for a new copy of the device path specified by \r
330 DevicePath. If DevicePath is NULL, then NULL is returned. \r
331 If the memory is successfully allocated, then the\r
332 contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer\r
333 is returned. Otherwise, NULL is returned. \r
334 The memory for the new device path is allocated from EFI boot services memory. \r
335 It is the responsibility of the caller to free the memory allocated. \r
336 \r
337 @param DevicePath A pointer to a device path data structure.\r
338\r
339 @retval NULL If DevicePath is NULL.\r
340 @retval Others A pointer to the duplicated device path.\r
341 \r
342**/\r
343EFI_DEVICE_PATH_PROTOCOL *\r
344EFIAPI\r
345DuplicateDevicePath (\r
346 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
347 )\r
348{\r
349 return mDevicePathUtilities->DuplicateDevicePath (DevicePath);\r
350}\r
351\r
352/**\r
353 Creates a new device path by appending a second device path to a first device path.\r
354\r
355 This function creates a new device path by appending a copy of SecondDevicePath to a copy of\r
356 FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from\r
357 SecondDevicePath is retained. The newly created device path is returned. \r
358 If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned. \r
359 If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned. \r
360 If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is\r
361 returned. \r
362 If there is not enough memory for the newly allocated buffer, then NULL is returned.\r
363 The memory for the new device path is allocated from EFI boot services memory. It is the\r
364 responsibility of the caller to free the memory allocated.\r
365\r
366 @param FirstDevicePath A pointer to a device path data structure.\r
367 @param SecondDevicePath A pointer to a device path data structure.\r
368 \r
369 @retval NULL If there is not enough memory for the newly allocated buffer.\r
370 @retval Others A pointer to the new device path if success.\r
371 Or a copy an end-of-device-path if both FirstDevicePath and \r
372 SecondDevicePath are NULL.\r
373\r
374**/\r
375EFI_DEVICE_PATH_PROTOCOL *\r
376EFIAPI\r
377AppendDevicePath (\r
378 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL\r
379 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL\r
380 )\r
381{\r
382 return mDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath);\r
383}\r
384\r
385/**\r
386 Creates a new path by appending the device node to the device path.\r
387\r
388 This function creates a new device path by appending a copy of the device node \r
389 specified by DevicePathNode to a copy of the device path specified by DevicePath \r
390 in an allocated buffer.\r
391 The end-of-device-path device node is moved after the end of the appended device node.\r
392 If DevicePathNode is NULL then a copy of DevicePath is returned.\r
393 If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device \r
394 path device node is returned.\r
395 If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path \r
396 device node is returned.\r
397 If there is not enough memory to allocate space for the new device path, then \r
398 NULL is returned. \r
399 The memory is allocated from EFI boot services memory. It is the responsibility \r
400 of the caller to free the memory allocated.\r
401\r
402 @param DevicePath A pointer to a device path data structure.\r
403 @param DevicePathNode A pointer to a single device path node.\r
404\r
405 @retval NULL If there is not enough memory for the new device path.\r
406 @retval Others A pointer to the new device path if success.\r
407 A copy of DevicePathNode followed by an end-of-device-path node \r
408 if both FirstDevicePath and SecondDevicePath are NULL.\r
409 A copy of an end-of-device-path node if both FirstDevicePath \r
410 and SecondDevicePath are NULL.\r
411\r
412**/\r
413EFI_DEVICE_PATH_PROTOCOL *\r
414EFIAPI\r
415AppendDevicePathNode (\r
416 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL\r
417 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL\r
418 )\r
419{\r
420 return mDevicePathUtilities->AppendDeviceNode (DevicePath, DevicePathNode);\r
421}\r
422\r
423/**\r
424 Creates a new device path by appending the specified device path instance to \r
425 the specified device path.\r
426 \r
427 This function creates a new device path by appending a copy of the device path \r
428 instance specified by DevicePathInstance to a copy of the device path specified \r
429 by DevicePath in a allocated buffer.\r
430 The end-of-device-path device node is moved after the end of the appended device \r
431 path instance and a new end-of-device-path-instance node is inserted between. \r
432 If DevicePath is NULL, then a copy if DevicePathInstance is returned.\r
433 If DevicePathInstance is NULL, then NULL is returned.\r
434 If there is not enough memory to allocate space for the new device path, then \r
435 NULL is returned. \r
436 The memory is allocated from EFI boot services memory. It is the responsibility \r
437 of the caller to free the memory allocated.\r
438 \r
439 @param DevicePath A pointer to a device path data structure.\r
440 @param DevicePathInstance A pointer to a device path instance.\r
441\r
442 @return A pointer to the new device path.\r
443\r
444**/\r
445EFI_DEVICE_PATH_PROTOCOL *\r
446EFIAPI\r
447AppendDevicePathInstance (\r
448 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL\r
449 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL\r
450 )\r
451{\r
452 return mDevicePathUtilities->AppendDevicePathInstance (DevicePath, DevicePathInstance);\r
453}\r
454\r
455/**\r
456 Creates a copy of the current device path instance and returns a pointer to the \r
457 next device path instance.\r
458\r
459 This function creates a copy of the current device path instance. It also updates \r
460 DevicePath to point to the next device path instance in the device path (or NULL \r
461 if no more) and updates Size to hold the size of the device path instance copy.\r
462 If DevicePath is NULL, then NULL is returned.\r
463 If there is not enough memory to allocate space for the new device path, then \r
464 NULL is returned. \r
465 The memory is allocated from EFI boot services memory. It is the responsibility \r
466 of the caller to free the memory allocated.\r
467 If Size is NULL, then ASSERT().\r
468 \r
469 @param DevicePath On input, this holds the pointer to the current \r
470 device path instance. On output, this holds \r
471 the pointer to the next device path instance \r
472 or NULL if there are no more device path\r
473 instances in the device path pointer to a \r
474 device path data structure.\r
475 @param Size On output, this holds the size of the device \r
476 path instance, in bytes or zero, if DevicePath \r
477 is NULL.\r
478\r
479 @return A pointer to the current device path instance.\r
480\r
481**/\r
482EFI_DEVICE_PATH_PROTOCOL *\r
483EFIAPI\r
484GetNextDevicePathInstance (\r
485 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
486 OUT UINTN *Size\r
487 )\r
488{\r
489 ASSERT (Size != NULL);\r
490 return mDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size);\r
491}\r
492\r
493/**\r
494 Creates a device node.\r
495\r
496 This function creates a new device node in a newly allocated buffer of size \r
497 NodeLength and initializes the device path node header with NodeType and NodeSubType. \r
498 The new device path node is returned.\r
499 If NodeLength is smaller than a device path header, then NULL is returned. \r
500 If there is not enough memory to allocate space for the new device path, then \r
501 NULL is returned. \r
502 The memory is allocated from EFI boot services memory. It is the responsibility \r
503 of the caller to\r
504 free the memory allocated.\r
505\r
506 @param NodeType The device node type for the new device node.\r
507 @param NodeSubType The device node sub-type for the new device node.\r
508 @param NodeLength The length of the new device node.\r
509\r
510 @return The new device path.\r
511\r
512**/\r
513EFI_DEVICE_PATH_PROTOCOL *\r
514EFIAPI\r
515CreateDeviceNode (\r
516 IN UINT8 NodeType,\r
517 IN UINT8 NodeSubType,\r
518 IN UINT16 NodeLength\r
519 )\r
520{\r
521 return mDevicePathUtilities->CreateDeviceNode (NodeType, NodeSubType, NodeLength);\r
522}\r
523\r
524/**\r
525 Determines if a device path is single or multi-instance.\r
526\r
527 This function returns TRUE if the device path specified by DevicePath is \r
528 multi-instance.\r
529 Otherwise, FALSE is returned. If DevicePath is NULL, then FALSE is returned.\r
530\r
531 @param DevicePath A pointer to a device path data structure.\r
532\r
533 @retval TRUE DevicePath is multi-instance.\r
534 @retval FALSE DevicePath is not multi-instance or DevicePath \r
535 is NULL.\r
536\r
537**/\r
538BOOLEAN\r
539EFIAPI\r
540IsDevicePathMultiInstance (\r
541 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
542 )\r
543{\r
544 return mDevicePathUtilities->IsDevicePathMultiInstance (DevicePath);\r
545}\r
546\r
547/**\r
548 Retrieves the device path protocol from a handle.\r
549\r
550 This function returns the device path protocol from the handle specified by Handle. \r
551 If Handle is NULL or Handle does not contain a device path protocol, then NULL \r
552 is returned.\r
553 \r
554 @param Handle The handle from which to retrieve the device \r
555 path protocol.\r
556\r
557 @return The device path protocol from the handle specified by Handle.\r
558\r
559**/\r
560EFI_DEVICE_PATH_PROTOCOL *\r
561EFIAPI\r
562DevicePathFromHandle (\r
563 IN EFI_HANDLE Handle\r
564 )\r
565{\r
566 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
567 EFI_STATUS Status;\r
568\r
569 Status = gBS->HandleProtocol (\r
570 Handle,\r
571 &gEfiDevicePathProtocolGuid,\r
572 (VOID *) &DevicePath\r
573 );\r
574 if (EFI_ERROR (Status)) {\r
575 DevicePath = NULL;\r
576 }\r
577 return DevicePath;\r
578}\r
579\r
580/**\r
581 Allocates a device path for a file and appends it to an existing device path.\r
582\r
583 If Device is a valid device handle that contains a device path protocol, then \r
584 a device path for the file specified by FileName is allocated and appended to \r
585 the device path associated with the handle Device. The allocated device path \r
586 is returned. If Device is NULL or Device is a handle that does not support the \r
587 device path protocol, then a device path containing a single device path node \r
588 for the file specified by FileName is allocated and returned.\r
589 The memory for the new device path is allocated from EFI boot services memory. \r
590 It is the responsibility of the caller to free the memory allocated.\r
591 \r
592 If FileName is NULL, then ASSERT().\r
593 If FileName is not aligned on a 16-bit boundary, then ASSERT().\r
594\r
595 @param Device A pointer to a device handle. This parameter \r
596 is optional and may be NULL.\r
597 @param FileName A pointer to a Null-terminated Unicode string.\r
598\r
599 @return The allocated device path.\r
600\r
601**/\r
602EFI_DEVICE_PATH_PROTOCOL *\r
603EFIAPI\r
604FileDevicePath (\r
605 IN EFI_HANDLE Device, OPTIONAL\r
606 IN CONST CHAR16 *FileName\r
607 )\r
608{\r
609 UINTN Size;\r
610 FILEPATH_DEVICE_PATH *FilePath;\r
611 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
612 EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;\r
613\r
614 DevicePath = NULL;\r
615\r
616 Size = StrSize (FileName);\r
617 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);\r
618 if (FileDevicePath != NULL) {\r
619 FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;\r
620 FilePath->Header.Type = MEDIA_DEVICE_PATH;\r
621 FilePath->Header.SubType = MEDIA_FILEPATH_DP;\r
622 CopyMem (&FilePath->PathName, FileName, Size);\r
623 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);\r
624 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));\r
625\r
626 if (Device != NULL) {\r
627 DevicePath = DevicePathFromHandle (Device);\r
628 }\r
629\r
630 DevicePath = AppendDevicePath (DevicePath, FileDevicePath);\r
631 FreePool (FileDevicePath);\r
632 }\r
633\r
634 return DevicePath;\r
635}\r