TianoCore EDK2 master
Loading...
Searching...
No Matches
DevicePathUtilities.c
Go to the documentation of this file.
1
16#include "UefiDevicePathLib.h"
17
18//
19// Template for an end-of-device path node.
20//
21GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = {
22 END_DEVICE_PATH_TYPE,
23 END_ENTIRE_DEVICE_PATH_SUBTYPE,
24 {
25 END_DEVICE_PATH_LENGTH,
26 0
27 }
28};
29
46BOOLEAN
47EFIAPI
50 IN UINTN MaxSize
51 )
52{
53 UINTN Count;
54 UINTN Size;
55 UINTN NodeLength;
56
57 //
58 // Validate the input whether exists and its size big enough to touch the first node
59 //
60 if ((DevicePath == NULL) || ((MaxSize > 0) && (MaxSize < END_DEVICE_PATH_LENGTH))) {
61 return FALSE;
62 }
63
64 if (MaxSize == 0) {
65 MaxSize = MAX_UINTN;
66 }
67
68 for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
69 NodeLength = DevicePathNodeLength (DevicePath);
70 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
71 return FALSE;
72 }
73
74 if (NodeLength > MAX_UINTN - Size) {
75 return FALSE;
76 }
77
78 Size += NodeLength;
79
80 //
81 // Validate next node before touch it.
82 //
83 if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
84 return FALSE;
85 }
86
87 if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
88 Count++;
89 if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
90 return FALSE;
91 }
92 }
93
94 //
95 // FilePath must be a NULL-terminated string.
96 //
97 if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
98 (DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP) &&
99 (*(CHAR16 *)((UINT8 *)DevicePath + NodeLength - 2) != 0))
100 {
101 return FALSE;
102 }
103 }
104
105 //
106 // Only return TRUE when the End Device Path node is valid.
107 //
108 return (BOOLEAN)(DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
109}
110
123UINT8
124EFIAPI
126 IN CONST VOID *Node
127 )
128{
129 ASSERT (Node != NULL);
130 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type;
131}
132
145UINT8
146EFIAPI
148 IN CONST VOID *Node
149 )
150{
151 ASSERT (Node != NULL);
152 return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType;
153}
154
170UINTN
171EFIAPI
173 IN CONST VOID *Node
174 )
175{
176 ASSERT (Node != NULL);
177 return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);
178}
179
195EFIAPI
197 IN CONST VOID *Node
198 )
199{
200 ASSERT (Node != NULL);
201 return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength (Node));
202}
203
224BOOLEAN
225EFIAPI
227 IN CONST VOID *Node
228 )
229{
230 ASSERT (Node != NULL);
231 return (BOOLEAN)(DevicePathType (Node) == END_DEVICE_PATH_TYPE);
232}
233
251BOOLEAN
252EFIAPI
254 IN CONST VOID *Node
255 )
256{
257 ASSERT (Node != NULL);
258 return (BOOLEAN)(IsDevicePathEndType (Node) && DevicePathSubType (Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
259}
260
278BOOLEAN
279EFIAPI
281 IN CONST VOID *Node
282 )
283{
284 ASSERT (Node != NULL);
285 return (BOOLEAN)(IsDevicePathEndType (Node) && DevicePathSubType (Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
286}
287
306UINT16
307EFIAPI
309 IN OUT VOID *Node,
310 IN UINTN Length
311 )
312{
313 ASSERT (Node != NULL);
314 ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB));
315 return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length));
316}
317
334VOID
335EFIAPI
337 OUT VOID *Node
338 )
339{
340 ASSERT (Node != NULL);
341 CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
342}
343
357UINTN
358EFIAPI
361 )
362{
364
365 if (DevicePath == NULL) {
366 return 0;
367 }
368
369 if (!IsDevicePathValid (DevicePath, 0)) {
370 return 0;
371 }
372
373 //
374 // Search for the end of the device path structure
375 //
376 Start = DevicePath;
377 while (!IsDevicePathEnd (DevicePath)) {
378 DevicePath = NextDevicePathNode (DevicePath);
379 }
380
381 //
382 // Compute the size and add back in the size of the end device path structure
383 //
384 return ((UINTN)DevicePath - (UINTN)Start) + DevicePathNodeLength (DevicePath);
385}
386
404EFIAPI
407 )
408{
409 UINTN Size;
410
411 //
412 // Compute the size
413 //
414 Size = GetDevicePathSize (DevicePath);
415 if (Size == 0) {
416 return NULL;
417 }
418
419 //
420 // Allocate space for duplicate device path
421 //
422
423 return AllocateCopyPool (Size, DevicePath);
424}
425
451EFIAPI
453 IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath OPTIONAL,
454 IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL
455 )
456{
457 UINTN Size;
458 UINTN Size1;
459 UINTN Size2;
460 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
461 EFI_DEVICE_PATH_PROTOCOL *DevicePath2;
462
463 //
464 // If there's only 1 path, just duplicate it.
465 //
466 if (FirstDevicePath == NULL) {
467 return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath);
468 }
469
470 if (SecondDevicePath == NULL) {
471 return DuplicateDevicePath (FirstDevicePath);
472 }
473
474 if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) {
475 return NULL;
476 }
477
478 //
479 // Allocate space for the combined device path. It only has one end node of
480 // length EFI_DEVICE_PATH_PROTOCOL.
481 //
482 Size1 = GetDevicePathSize (FirstDevicePath);
483 Size2 = GetDevicePathSize (SecondDevicePath);
484 Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH;
485
486 NewDevicePath = AllocatePool (Size);
487
488 if (NewDevicePath != NULL) {
489 NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1);
490 //
491 // Over write FirstDevicePath EndNode and do the copy
492 //
493 DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath +
494 (Size1 - END_DEVICE_PATH_LENGTH));
495 CopyMem (DevicePath2, SecondDevicePath, Size2);
496 }
497
498 return NewDevicePath;
499}
500
530EFIAPI
532 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
533 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL
534 )
535{
536 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
537 EFI_DEVICE_PATH_PROTOCOL *NextNode;
538 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
539 UINTN NodeLength;
540
541 if (DevicePathNode == NULL) {
542 return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath);
543 }
544
545 //
546 // Build a Node that has a terminator on it
547 //
548 NodeLength = DevicePathNodeLength (DevicePathNode);
549
550 TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH);
551 if (TempDevicePath == NULL) {
552 return NULL;
553 }
554
555 TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength);
556 //
557 // Add and end device path node to convert Node to device path
558 //
559 NextNode = NextDevicePathNode (TempDevicePath);
560 SetDevicePathEndNode (NextNode);
561 //
562 // Append device paths
563 //
564 NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath);
565
566 FreePool (TempDevicePath);
567
568 return NewDevicePath;
569}
570
595EFIAPI
597 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
598 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL
599 )
600{
601 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
602 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
603 UINTN SrcSize;
604 UINTN InstanceSize;
605
606 if (DevicePath == NULL) {
607 return DuplicateDevicePath (DevicePathInstance);
608 }
609
610 if (DevicePathInstance == NULL) {
611 return NULL;
612 }
613
614 if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) {
615 return NULL;
616 }
617
618 SrcSize = GetDevicePathSize (DevicePath);
619 InstanceSize = GetDevicePathSize (DevicePathInstance);
620
621 NewDevicePath = AllocatePool (SrcSize + InstanceSize);
622 if (NewDevicePath != NULL) {
623 TempDevicePath = CopyMem (NewDevicePath, DevicePath, SrcSize);
624
625 while (!IsDevicePathEnd (TempDevicePath)) {
626 TempDevicePath = NextDevicePathNode (TempDevicePath);
627 }
628
629 TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
630 TempDevicePath = NextDevicePathNode (TempDevicePath);
631 CopyMem (TempDevicePath, DevicePathInstance, InstanceSize);
632 }
633
634 return NewDevicePath;
635}
636
666EFIAPI
668 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
669 OUT UINTN *Size
670 )
671{
673 EFI_DEVICE_PATH_PROTOCOL *ReturnValue;
674 UINT8 Temp;
675
676 ASSERT (Size != NULL);
677
678 if ((DevicePath == NULL) || (*DevicePath == NULL)) {
679 *Size = 0;
680 return NULL;
681 }
682
683 if (!IsDevicePathValid (*DevicePath, 0)) {
684 return NULL;
685 }
686
687 //
688 // Find the end of the device path instance
689 //
690 DevPath = *DevicePath;
691 while (!IsDevicePathEndType (DevPath)) {
692 DevPath = NextDevicePathNode (DevPath);
693 }
694
695 //
696 // Compute the size of the device path instance
697 //
698 *Size = ((UINTN)DevPath - (UINTN)(*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
699
700 //
701 // Make a copy and return the device path instance
702 //
703 Temp = DevPath->SubType;
704 DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
705 ReturnValue = DuplicateDevicePath (*DevicePath);
706 DevPath->SubType = Temp;
707
708 //
709 // If DevPath is the end of an entire device path, then another instance
710 // does not follow, so *DevicePath is set to NULL.
711 //
712 if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
713 *DevicePath = NULL;
714 } else {
715 *DevicePath = NextDevicePathNode (DevPath);
716 }
717
718 return ReturnValue;
719}
720
741EFIAPI
743 IN UINT8 NodeType,
744 IN UINT8 NodeSubType,
745 IN UINT16 NodeLength
746 )
747{
748 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
749
750 if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
751 //
752 // NodeLength is less than the size of the header.
753 //
754 return NULL;
755 }
756
757 DevicePath = AllocateZeroPool (NodeLength);
758 if (DevicePath != NULL) {
759 DevicePath->Type = NodeType;
760 DevicePath->SubType = NodeSubType;
761 SetDevicePathNodeLength (DevicePath, NodeLength);
762 }
763
764 return DevicePath;
765}
766
782BOOLEAN
783EFIAPI
786 )
787{
789
790 if (DevicePath == NULL) {
791 return FALSE;
792 }
793
794 if (!IsDevicePathValid (DevicePath, 0)) {
795 return FALSE;
796 }
797
798 Node = DevicePath;
799 while (!IsDevicePathEnd (Node)) {
800 if (IsDevicePathEndInstance (Node)) {
801 return TRUE;
802 }
803
804 Node = NextDevicePathNode (Node);
805 }
806
807 return FALSE;
808}
809
832EFIAPI
834 IN EFI_HANDLE Device OPTIONAL,
835 IN CONST CHAR16 *FileName
836 )
837{
838 UINTN Size;
839 FILEPATH_DEVICE_PATH *FilePath;
840 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
842
843 DevicePath = NULL;
844
845 Size = StrSize (FileName);
846 FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
847 if (FileDevicePath != NULL) {
849 FilePath->Header.Type = MEDIA_DEVICE_PATH;
850 FilePath->Header.SubType = MEDIA_FILEPATH_DP;
851 CopyMem (&FilePath->PathName, FileName, Size);
852 SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
853 SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
854
855 if (Device != NULL) {
856 DevicePath = DevicePathFromHandle (Device);
857 }
858
859 DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
861 }
862
863 return DevicePath;
864}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
Definition: Unaligned.c:29
UINT16 EFIAPI WriteUnaligned16(OUT UINT16 *Buffer, IN UINT16 Value)
Definition: Unaligned.c:61
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define MEDIA_FILEPATH_DP
Definition: DevicePath.h:1098
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibAppendDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL)
UINTN EFIAPI DevicePathNodeLength(IN CONST VOID *Node)
UINTN EFIAPI UefiDevicePathLibGetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibAppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI FileDevicePath(IN EFI_HANDLE Device OPTIONAL, IN CONST CHAR16 *FileName)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathValid(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibAppendDevicePathInstance(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibDuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
BOOLEAN EFIAPI UefiDevicePathLibIsDevicePathMultiInstance(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
BOOLEAN EFIAPI IsDevicePathEndType(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibGetNextDevicePathInstance(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size)
VOID EFIAPI SetDevicePathEndNode(OUT VOID *Node)
BOOLEAN EFIAPI IsDevicePathEndInstance(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI UefiDevicePathLibCreateDeviceNode(IN UINT8 NodeType, IN UINT8 NodeSubType, IN UINT16 NodeLength)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33