xref: /dragonfly/lib/libefivar/uefi-dputil.c (revision 4661c169)
1 /*-
2  * Copyright (c) 2017 Netflix, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: head/lib/libefivar/uefi-dputil.c 343755 2019-02-04 21:28:25Z imp $
26  */
27 
28 /*
29  * Routines to format EFI_DEVICE_PATHs from the UEFI standard. Much of
30  * this file is taken from EDK2 and rototilled.
31  */
32 
33 #include <efivar.h>
34 #include <limits.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/endian.h>
38 
39 #include "efi-osdep.h"
40 
41 #include "uefi-dplib.h"
42 
43 /* XXX maybe I should include the entire DevicePathUtilities.c and ifdef out what we don't use */
44 
45 /*
46  * Taken from MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c
47  * hash a11928f3310518ab1c6fd34e8d0fdbb72de9602c 2017-Mar-01
48  */
49 
50 /** @file
51   Device Path services. The thing to remember is device paths are built out of
52   nodes. The device path is terminated by an end node that is length
53   sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
54   all over this file.
55 
56   The only place where multi-instance device paths are supported is in
57   environment varibles. Multi-instance device paths should never be placed
58   on a Handle.
59 
60   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
61   This program and the accompanying materials
62   are licensed and made available under the terms and conditions of the BSD License
63   which accompanies this distribution.  The full text of the license may be found at
64   http://opensource.org/licenses/bsd-license.php.
65 
66   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
67   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
68 
69 **/
70 
71 //
72 // Template for an end-of-device path node.
73 //
74 static CONST EFI_DEVICE_PATH_PROTOCOL  mUefiDevicePathLibEndDevicePath = {
75   END_DEVICE_PATH_TYPE,
76   END_ENTIRE_DEVICE_PATH_SUBTYPE,
77   {
78     END_DEVICE_PATH_LENGTH,
79     0
80   }
81 };
82 
83 
84 /**
85   Returns the size of a device path in bytes.
86 
87   This function returns the size, in bytes, of the device path data structure
88   specified by DevicePath including the end of device path node.
89   If DevicePath is NULL or invalid, then 0 is returned.
90 
91   @param  DevicePath  A pointer to a device path data structure.
92 
93   @retval 0           If DevicePath is NULL or invalid.
94   @retval Others      The size of a device path in bytes.
95 
96 **/
97 UINTN
98 EFIAPI
GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath)99 GetDevicePathSize (
100   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
101   )
102 {
103   CONST EFI_DEVICE_PATH_PROTOCOL  *Start;
104 
105   if (DevicePath == NULL) {
106     return 0;
107   }
108 
109   if (!IsDevicePathValid (DevicePath, 0)) {
110     return 0;
111   }
112 
113   //
114   // Search for the end of the device path structure
115   //
116   Start = DevicePath;
117   while (!IsDevicePathEnd (DevicePath)) {
118     DevicePath = NextDevicePathNode (DevicePath);
119   }
120 
121   //
122   // Compute the size and add back in the size of the end device path structure
123   //
124   return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);
125 }
126 
127 /**
128   Determine whether a given device path is valid.
129   If DevicePath is NULL, then ASSERT().
130 
131   @param  DevicePath  A pointer to a device path data structure.
132   @param  MaxSize     The maximum size of the device path data structure.
133 
134   @retval TRUE        DevicePath is valid.
135   @retval FALSE       The length of any node in the DevicePath is less
136                       than sizeof (EFI_DEVICE_PATH_PROTOCOL).
137   @retval FALSE       If MaxSize is not zero, the size of the DevicePath
138                       exceeds MaxSize.
139   @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
140                       count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
141 **/
142 BOOLEAN
143 EFIAPI
IsDevicePathValid(IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN UINTN MaxSize)144 IsDevicePathValid (
145   IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
146   IN       UINTN                    MaxSize
147   )
148 {
149   UINTN Count;
150   UINTN Size;
151   UINTN NodeLength;
152 
153   ASSERT (DevicePath != NULL);
154 
155   if (MaxSize == 0) {
156     MaxSize = MAX_UINTN;
157   }
158 
159   //
160   // Validate the input size big enough to touch the first node.
161   //
162   if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
163     return FALSE;
164   }
165 
166   for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
167     NodeLength = DevicePathNodeLength (DevicePath);
168     if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
169       return FALSE;
170     }
171 
172     if (NodeLength > MAX_UINTN - Size) {
173       return FALSE;
174     }
175     Size += NodeLength;
176 
177     //
178     // Validate next node before touch it.
179     //
180     if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
181       return FALSE;
182     }
183 
184     if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
185       Count++;
186       if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
187         return FALSE;
188       }
189     }
190   }
191 
192   //
193   // Only return TRUE when the End Device Path node is valid.
194   //
195   return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
196 }
197 
198 /**
199   Returns the Type field of a device path node.
200 
201   Returns the Type field of the device path node specified by Node.
202 
203   If Node is NULL, then ASSERT().
204 
205   @param  Node      A pointer to a device path node data structure.
206 
207   @return The Type field of the device path node specified by Node.
208 
209 **/
210 UINT8
211 EFIAPI
DevicePathType(IN CONST VOID * Node)212 DevicePathType (
213   IN CONST VOID  *Node
214   )
215 {
216   ASSERT (Node != NULL);
217   return ((const EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;
218 }
219 
220 
221 /**
222   Returns the SubType field of a device path node.
223 
224   Returns the SubType field of the device path node specified by Node.
225 
226   If Node is NULL, then ASSERT().
227 
228   @param  Node      A pointer to a device path node data structure.
229 
230   @return The SubType field of the device path node specified by Node.
231 
232 **/
233 UINT8
234 EFIAPI
DevicePathSubType(IN CONST VOID * Node)235 DevicePathSubType (
236   IN CONST VOID  *Node
237   )
238 {
239   ASSERT (Node != NULL);
240   return ((const EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;
241 }
242 
243 /**
244   Returns the 16-bit Length field of a device path node.
245 
246   Returns the 16-bit Length field of the device path node specified by Node.
247   Node is not required to be aligned on a 16-bit boundary, so it is recommended
248   that a function such as ReadUnaligned16() be used to extract the contents of
249   the Length field.
250 
251   If Node is NULL, then ASSERT().
252 
253   @param  Node      A pointer to a device path node data structure.
254 
255   @return The 16-bit Length field of the device path node specified by Node.
256 
257 **/
258 UINTN
259 EFIAPI
DevicePathNodeLength(IN CONST VOID * Node)260 DevicePathNodeLength (
261   IN CONST VOID  *Node
262   )
263 {
264   ASSERT (Node != NULL);
265   return ((const EFI_DEVICE_PATH_PROTOCOL *)Node)->Length[0] |
266       (((const EFI_DEVICE_PATH_PROTOCOL *)Node)->Length[1] << 8);
267 }
268 
269 /**
270   Returns a pointer to the next node in a device path.
271 
272   Returns a pointer to the device path node that follows the device path node
273   specified by Node.
274 
275   If Node is NULL, then ASSERT().
276 
277   @param  Node      A pointer to a device path node data structure.
278 
279   @return a pointer to the device path node that follows the device path node
280   specified by Node.
281 
282 **/
283 EFI_DEVICE_PATH_PROTOCOL *
284 EFIAPI
NextDevicePathNode(IN CONST VOID * Node)285 NextDevicePathNode (
286   IN CONST VOID  *Node
287   )
288 {
289   ASSERT (Node != NULL);
290   return ((EFI_DEVICE_PATH_PROTOCOL *)(__DECONST(UINT8 *, Node) + DevicePathNodeLength(Node)));
291 }
292 
293 /**
294   Determines if a device path node is an end node of a device path.
295   This includes nodes that are the end of a device path instance and nodes that
296   are the end of an entire device path.
297 
298   Determines if the device path node specified by Node is an end node of a device path.
299   This includes nodes that are the end of a device path instance and nodes that are the
300   end of an entire device path.  If Node represents an end node of a device path,
301   then TRUE is returned.  Otherwise, FALSE is returned.
302 
303   If Node is NULL, then ASSERT().
304 
305   @param  Node      A pointer to a device path node data structure.
306 
307   @retval TRUE      The device path node specified by Node is an end node of a
308                     device path.
309   @retval FALSE     The device path node specified by Node is not an end node of
310                     a device path.
311 
312 **/
313 BOOLEAN
314 EFIAPI
IsDevicePathEndType(IN CONST VOID * Node)315 IsDevicePathEndType (
316   IN CONST VOID  *Node
317   )
318 {
319   ASSERT (Node != NULL);
320   return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE);
321 }
322 
323 /**
324   Determines if a device path node is an end node of an entire device path.
325 
326   Determines if a device path node specified by Node is an end node of an entire
327   device path. If Node represents the end of an entire device path, then TRUE is
328   returned.  Otherwise, FALSE is returned.
329 
330   If Node is NULL, then ASSERT().
331 
332   @param  Node      A pointer to a device path node data structure.
333 
334   @retval TRUE      The device path node specified by Node is the end of an entire
335                     device path.
336   @retval FALSE     The device path node specified by Node is not the end of an
337                     entire device path.
338 
339 **/
340 BOOLEAN
341 EFIAPI
IsDevicePathEnd(IN CONST VOID * Node)342 IsDevicePathEnd (
343   IN CONST VOID  *Node
344   )
345 {
346   ASSERT (Node != NULL);
347   return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
348 }
349 
350 /**
351   Fills in all the fields of a device path node that is the end of an entire device path.
352 
353   Fills in all the fields of a device path node specified by Node so Node represents
354   the end of an entire device path.  The Type field of Node is set to
355   END_DEVICE_PATH_TYPE, the SubType field of Node is set to
356   END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to
357   END_DEVICE_PATH_LENGTH.  Node is not required to be aligned on a 16-bit boundary,
358   so it is recommended that a function such as WriteUnaligned16() be used to set
359   the contents of the Length field.
360 
361   If Node is NULL, then ASSERT().
362 
363   @param  Node      A pointer to a device path node data structure.
364 
365 **/
366 VOID
367 EFIAPI
SetDevicePathEndNode(OUT VOID * Node)368 SetDevicePathEndNode (
369   OUT VOID  *Node
370   )
371 {
372   ASSERT (Node != NULL);
373   memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
374 }
375 
376 /**
377   Sets the length, in bytes, of a device path node.
378 
379   Sets the length of the device path node specified by Node to the value specified
380   by NodeLength.  NodeLength is returned.  Node is not required to be aligned on
381   a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16()
382   be used to set the contents of the Length field.
383 
384   If Node is NULL, then ASSERT().
385   If NodeLength >= SIZE_64KB, then ASSERT().
386   If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT().
387 
388   @param  Node      A pointer to a device path node data structure.
389   @param  Length    The length, in bytes, of the device path node.
390 
391   @return Length
392 
393 **/
394 UINT16
395 EFIAPI
SetDevicePathNodeLength(IN OUT VOID * Node,IN UINTN Length)396 SetDevicePathNodeLength (
397   IN OUT VOID  *Node,
398   IN UINTN     Length
399   )
400 {
401   ASSERT (Node != NULL);
402   ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB));
403 //  return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
404   le16enc(&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
405   return Length;
406 }
407 
408 /**
409   Creates a device node.
410 
411   This function creates a new device node in a newly allocated buffer of size
412   NodeLength and initializes the device path node header with NodeType and NodeSubType.
413   The new device path node is returned.
414   If NodeLength is smaller than a device path header, then NULL is returned.
415   If there is not enough memory to allocate space for the new device path, then
416   NULL is returned.
417   The memory is allocated from EFI boot services memory. It is the responsibility
418   of the caller to free the memory allocated.
419 
420   @param  NodeType                   The device node type for the new device node.
421   @param  NodeSubType                The device node sub-type for the new device node.
422   @param  NodeLength                 The length of the new device node.
423 
424   @return The new device path.
425 
426 **/
427 EFI_DEVICE_PATH_PROTOCOL *
428 EFIAPI
CreateDeviceNode(IN UINT8 NodeType,IN UINT8 NodeSubType,IN UINT16 NodeLength)429 CreateDeviceNode (
430   IN UINT8                           NodeType,
431   IN UINT8                           NodeSubType,
432   IN UINT16                          NodeLength
433   )
434 {
435   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
436 
437   if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
438     //
439     // NodeLength is less than the size of the header.
440     //
441     return NULL;
442   }
443 
444   DevicePath = AllocateZeroPool (NodeLength);
445   if (DevicePath != NULL) {
446      DevicePath->Type    = NodeType;
447      DevicePath->SubType = NodeSubType;
448      SetDevicePathNodeLength (DevicePath, NodeLength);
449   }
450 
451   return DevicePath;
452 }
453 
454 /**
455   Creates a new copy of an existing device path.
456 
457   This function allocates space for a new copy of the device path specified by DevicePath.
458   If DevicePath is NULL, then NULL is returned.  If the memory is successfully
459   allocated, then the contents of DevicePath are copied to the newly allocated
460   buffer, and a pointer to that buffer is returned.  Otherwise, NULL is returned.
461   The memory for the new device path is allocated from EFI boot services memory.
462   It is the responsibility of the caller to free the memory allocated.
463 
464   @param  DevicePath    A pointer to a device path data structure.
465 
466   @retval NULL          DevicePath is NULL or invalid.
467   @retval Others        A pointer to the duplicated device path.
468 
469 **/
470 EFI_DEVICE_PATH_PROTOCOL *
471 EFIAPI
DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath)472 DuplicateDevicePath (
473   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
474   )
475 {
476   UINTN                     Size;
477 
478   //
479   // Compute the size
480   //
481   Size = GetDevicePathSize (DevicePath);
482   if (Size == 0) {
483     return NULL;
484   }
485 
486   //
487   // Allocate space for duplicate device path
488   //
489 
490   return AllocateCopyPool (Size, DevicePath);
491 }
492 
493 /**
494   Creates a new device path by appending a second device path to a first device path.
495 
496   This function creates a new device path by appending a copy of SecondDevicePath
497   to a copy of FirstDevicePath in a newly allocated buffer.  Only the end-of-device-path
498   device node from SecondDevicePath is retained. The newly created device path is
499   returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of
500   SecondDevicePath is returned.  If SecondDevicePath is NULL, then it is ignored,
501   and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and
502   SecondDevicePath are NULL, then a copy of an end-of-device-path is returned.
503 
504   If there is not enough memory for the newly allocated buffer, then NULL is returned.
505   The memory for the new device path is allocated from EFI boot services memory.
506   It is the responsibility of the caller to free the memory allocated.
507 
508   @param  FirstDevicePath            A pointer to a device path data structure.
509   @param  SecondDevicePath           A pointer to a device path data structure.
510 
511   @retval NULL      If there is not enough memory for the newly allocated buffer.
512   @retval NULL      If FirstDevicePath or SecondDevicePath is invalid.
513   @retval Others    A pointer to the new device path if success.
514                     Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL.
515 
516 **/
517 EFI_DEVICE_PATH_PROTOCOL *
518 EFIAPI
AppendDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL * FirstDevicePath,OPTIONAL IN CONST EFI_DEVICE_PATH_PROTOCOL * SecondDevicePath OPTIONAL)519 AppendDevicePath (
520   IN CONST EFI_DEVICE_PATH_PROTOCOL  *FirstDevicePath,  OPTIONAL
521   IN CONST EFI_DEVICE_PATH_PROTOCOL  *SecondDevicePath  OPTIONAL
522   )
523 {
524   UINTN                     Size;
525   UINTN                     Size1;
526   UINTN                     Size2;
527   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
528   EFI_DEVICE_PATH_PROTOCOL  *DevicePath2;
529 
530   //
531   // If there's only 1 path, just duplicate it.
532   //
533   if (FirstDevicePath == NULL) {
534     return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath);
535   }
536 
537   if (SecondDevicePath == NULL) {
538     return DuplicateDevicePath (FirstDevicePath);
539   }
540 
541   if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) {
542     return NULL;
543   }
544 
545   //
546   // Allocate space for the combined device path. It only has one end node of
547   // length EFI_DEVICE_PATH_PROTOCOL.
548   //
549   Size1         = GetDevicePathSize (FirstDevicePath);
550   Size2         = GetDevicePathSize (SecondDevicePath);
551   Size          = Size1 + Size2 - END_DEVICE_PATH_LENGTH;
552 
553   NewDevicePath = AllocatePool (Size);
554 
555   if (NewDevicePath != NULL) {
556     NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1);
557     //
558     // Over write FirstDevicePath EndNode and do the copy
559     //
560     DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath +
561                   (Size1 - END_DEVICE_PATH_LENGTH));
562     CopyMem (DevicePath2, SecondDevicePath, Size2);
563   }
564 
565   return NewDevicePath;
566 }
567 
568 /**
569   Creates a new path by appending the device node to the device path.
570 
571   This function creates a new device path by appending a copy of the device node
572   specified by DevicePathNode to a copy of the device path specified by DevicePath
573   in an allocated buffer. The end-of-device-path device node is moved after the
574   end of the appended device node.
575   If DevicePathNode is NULL then a copy of DevicePath is returned.
576   If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device
577   path device node is returned.
578   If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path
579   device node is returned.
580   If there is not enough memory to allocate space for the new device path, then
581   NULL is returned.
582   The memory is allocated from EFI boot services memory. It is the responsibility
583   of the caller to free the memory allocated.
584 
585   @param  DevicePath                 A pointer to a device path data structure.
586   @param  DevicePathNode             A pointer to a single device path node.
587 
588   @retval NULL      If there is not enough memory for the new device path.
589   @retval Others    A pointer to the new device path if success.
590                     A copy of DevicePathNode followed by an end-of-device-path node
591                     if both FirstDevicePath and SecondDevicePath are NULL.
592                     A copy of an end-of-device-path node if both FirstDevicePath
593                     and SecondDevicePath are NULL.
594 
595 **/
596 EFI_DEVICE_PATH_PROTOCOL *
597 EFIAPI
AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath,OPTIONAL IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePathNode OPTIONAL)598 AppendDevicePathNode (
599   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,     OPTIONAL
600   IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode  OPTIONAL
601   )
602 {
603   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
604   EFI_DEVICE_PATH_PROTOCOL  *NextNode;
605   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
606   UINTN                     NodeLength;
607 
608   if (DevicePathNode == NULL) {
609     return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath);
610   }
611   //
612   // Build a Node that has a terminator on it
613   //
614   NodeLength = DevicePathNodeLength (DevicePathNode);
615 
616   TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH);
617   if (TempDevicePath == NULL) {
618     return NULL;
619   }
620   TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength);
621   //
622   // Add and end device path node to convert Node to device path
623   //
624   NextNode = NextDevicePathNode (TempDevicePath);
625   SetDevicePathEndNode (NextNode);
626   //
627   // Append device paths
628   //
629   NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath);
630 
631   FreePool (TempDevicePath);
632 
633   return NewDevicePath;
634 }
635