]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c
Handle the case when OpROM wants to completely remove itself.
[mirror_edk2.git] / MdePkg / Library / UefiDevicePathLibDevicePathProtocol / UefiDevicePathLib.c
CommitLineData
e386b444 1/** @file\r
f008fc32 2 Library instance that implement UEFI Device Path Library class based on protocol\r
3 gEfiDevicePathUtilitiesProtocolGuid.\r
e386b444 4\r
58380e9c 5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
19388d29 6 This program and the accompanying materials\r
e386b444 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
2fc59a00 9 http://opensource.org/licenses/bsd-license.php.\r
e386b444 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
e386b444 14**/\r
15\r
c892d846 16\r
c7d265a9 17#include <Uefi.h>\r
c892d846 18\r
c7d265a9 19#include <Protocol/DevicePathUtilities.h>\r
c892d846 20\r
c7d265a9 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
e386b444 27\r
fe467413 28EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathUtilities = NULL;\r
e386b444 29\r
3dc728fb 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
e386b444 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
3dc728fb 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
5cba121d 87EFIAPI\r
3dc728fb 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
5cba121d 109EFIAPI\r
3dc728fb 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
5cba121d 134EFIAPI\r
3dc728fb 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
58380e9c 146 Returns a pointer to the device path node that follows the device path node \r
147 specified by Node.\r
3dc728fb 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
58380e9c 153 @return a pointer to the device path node that follows the device path node \r
154 specified by Node.\r
3dc728fb 155\r
156**/\r
157EFI_DEVICE_PATH_PROTOCOL *\r
5cba121d 158EFIAPI\r
3dc728fb 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
58380e9c 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
3dc728fb 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
58380e9c 182 @retval FALSE The device path node specified by Node is not an end node of \r
183 a device path.\r
3dc728fb 184 \r
185**/\r
186BOOLEAN\r
5cba121d 187EFIAPI\r
3dc728fb 188IsDevicePathEndType (\r
189 IN CONST VOID *Node\r
190 )\r
191{\r
192 ASSERT (Node != NULL);\r
a357faa3 193 return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);\r
3dc728fb 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
58380e9c 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
3dc728fb 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
5cba121d 213EFIAPI\r
3dc728fb 214IsDevicePathEnd (\r
215 IN CONST VOID *Node\r
216 )\r
217{\r
218 ASSERT (Node != NULL);\r
1bfc7438 219 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);\r
3dc728fb 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
58380e9c 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
3dc728fb 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
58380e9c 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
3dc728fb 238\r
239**/\r
240BOOLEAN\r
5cba121d 241EFIAPI\r
3dc728fb 242IsDevicePathEndInstance (\r
243 IN CONST VOID *Node\r
244 )\r
245{\r
246 ASSERT (Node != NULL);\r
1bfc7438 247 return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);\r
3dc728fb 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
5cba121d 268EFIAPI\r
3dc728fb 269SetDevicePathNodeLength (\r
9bb407c6 270 IN OUT VOID *Node,\r
8f0dd97e 271 IN UINTN Length\r
3dc728fb 272 )\r
273{\r
274 ASSERT (Node != NULL);\r
8f0dd97e 275 ASSERT (Length < 0x10000);\r
276 return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));\r
3dc728fb 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
5cba121d 296EFIAPI\r
3dc728fb 297SetDevicePathEndNode (\r
9bb407c6 298 OUT VOID *Node\r
3dc728fb 299 )\r
300{\r
301 ASSERT (Node != NULL);\r
302 CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));\r
303}\r
304\r
e386b444 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
3e5c3238 312 \r
313 @retval 0 If DevicePath is NULL.\r
314 @retval Others The size of a device path in bytes.\r
e386b444 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
6a3f4ef9 327 Creates a new copy of an existing device path.\r
e386b444 328\r
58380e9c 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
e386b444 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
3e5c3238 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
e386b444 336 \r
337 @param DevicePath A pointer to a device path data structure.\r
338\r
3e5c3238 339 @retval NULL If DevicePath is NULL.\r
340 @retval Others A pointer to the duplicated device path.\r
341 \r
e386b444 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
98a14db6 360 If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is\r
361 returned. \r
e386b444 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
3e5c3238 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
58380e9c 371 Or a copy an end-of-device-path if both FirstDevicePath and \r
372 SecondDevicePath are NULL.\r
e386b444 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
58380e9c 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
e386b444 391 The end-of-device-path device node is moved after the end of the appended device node.\r
98a14db6 392 If DevicePathNode is NULL then a copy of DevicePath is returned.\r
58380e9c 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
e386b444 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
3e5c3238 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
58380e9c 409 A copy of an end-of-device-path node if both FirstDevicePath \r
410 and SecondDevicePath are NULL.\r
e386b444 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
58380e9c 424 Creates a new device path by appending the specified device path instance to \r
425 the specified device path.\r
e386b444 426 \r
58380e9c 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
e386b444 432 If DevicePath is NULL, then a copy if DevicePathInstance is returned.\r
433 If DevicePathInstance is NULL, then NULL is returned.\r
58380e9c 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
e386b444 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
58380e9c 456 Creates a copy of the current device path instance and returns a pointer to the \r
457 next device path instance.\r
e386b444 458\r
58380e9c 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
e386b444 462 If DevicePath is NULL, then NULL is returned.\r
58380e9c 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
e386b444 467 If Size is NULL, then ASSERT().\r
468 \r
58380e9c 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
e386b444 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
3e5c3238 494 Creates a device node.\r
e386b444 495\r
58380e9c 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
e386b444 499 If NodeLength is smaller than a device path header, then NULL is returned. \r
58380e9c 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
e386b444 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
3e5c3238 510 @return The new device path.\r
e386b444 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
58380e9c 527 This function returns TRUE if the device path specified by DevicePath is \r
528 multi-instance.\r
e386b444 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
58380e9c 534 @retval FALSE DevicePath is not multi-instance or DevicePath \r
535 is NULL.\r
e386b444 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
58380e9c 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
e386b444 553 \r
58380e9c 554 @param Handle The handle from which to retrieve the device \r
555 path protocol.\r
e386b444 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
58380e9c 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
3e5c3238 591 \r
e386b444 592 If FileName is NULL, then ASSERT().\r
3e5c3238 593 If FileName is not aligned on a 16-bit boundary, then ASSERT().\r
e386b444 594\r
58380e9c 595 @param Device A pointer to a device handle. This parameter \r
596 is optional and may be NULL.\r
e386b444 597 @param FileName A pointer to a Null-terminated Unicode string.\r
598\r
3e5c3238 599 @return The allocated device path.\r
e386b444 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
e5dab016 617 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);\r
e386b444 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