dpath.c revision 76d05dc695b06c4e987bb8078f78032441e1430c
1/*++
2
3Copyright (c) 1998  Intel Corporation
4
5Module Name:
6
7    dpath.c
8
9Abstract:
10    MBR & Device Path functions
11
12
13
14Revision History
15
16--*/
17
18#include "lib.h"
19
20#define ALIGN_SIZE(a)   ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
21
22
23
24EFI_DEVICE_PATH *
25DevicePathFromHandle (
26    IN EFI_HANDLE       Handle
27    )
28{
29    EFI_STATUS          Status;
30    EFI_DEVICE_PATH     *DevicePath;
31
32    Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
33    if (EFI_ERROR(Status)) {
34        DevicePath = NULL;
35    }
36
37    return DevicePath;
38}
39
40
41EFI_DEVICE_PATH *
42DevicePathInstance (
43    IN OUT EFI_DEVICE_PATH  **DevicePath,
44    OUT UINTN               *Size
45    )
46{
47    EFI_DEVICE_PATH         *Start, *Next, *DevPath;
48    UINTN                   Count;
49
50    DevPath = *DevicePath;
51    Start = DevPath;
52
53    if (!DevPath) {
54        return NULL;
55    }
56
57    //
58    // Check for end of device path type
59    //
60
61    for (Count = 0; ; Count++) {
62        Next = NextDevicePathNode(DevPath);
63
64        if (IsDevicePathEndType(DevPath)) {
65            break;
66        }
67
68        if (Count > 01000) {
69            //
70            // BugBug: Debug code to catch bogus device paths
71            //
72            DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
73            DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
74            break;
75        }
76
77        DevPath = Next;
78    }
79
80    ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
81            DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
82
83    //
84    // Set next position
85    //
86
87    if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
88        Next = NULL;
89    }
90
91    *DevicePath = Next;
92
93    //
94    // Return size and start of device path instance
95    //
96
97    *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
98    return Start;
99}
100
101UINTN
102DevicePathInstanceCount (
103    IN EFI_DEVICE_PATH      *DevicePath
104    )
105{
106    UINTN       Count, Size;
107
108    Count = 0;
109    while (DevicePathInstance(&DevicePath, &Size)) {
110        Count += 1;
111    }
112
113    return Count;
114}
115
116
117EFI_DEVICE_PATH *
118AppendDevicePath (
119    IN EFI_DEVICE_PATH  *Src1,
120    IN EFI_DEVICE_PATH  *Src2
121    )
122// Src1 may have multiple "instances" and each instance is appended
123// Src2 is appended to each instance is Src1.  (E.g., it's possible
124// to append a new instance to the complete device path by passing
125// it in Src2)
126{
127    UINTN               Src1Size, Src1Inst, Src2Size, Size;
128    EFI_DEVICE_PATH     *Dst, *Inst;
129    UINT8               *DstPos;
130
131    //
132    // If there's only 1 path, just duplicate it
133    //
134
135    if (!Src1) {
136        ASSERT (!IsDevicePathUnpacked (Src2));
137        return DuplicateDevicePath (Src2);
138    }
139
140    if (!Src2) {
141        ASSERT (!IsDevicePathUnpacked (Src1));
142        return DuplicateDevicePath (Src1);
143    }
144
145    //
146    // Verify we're not working with unpacked paths
147    //
148
149//    ASSERT (!IsDevicePathUnpacked (Src1));
150//    ASSERT (!IsDevicePathUnpacked (Src2));
151
152    //
153    // Append Src2 to every instance in Src1
154    //
155
156    Src1Size = DevicePathSize(Src1);
157    Src1Inst = DevicePathInstanceCount(Src1);
158    Src2Size = DevicePathSize(Src2);
159    Size = Src1Size * Src1Inst + Src2Size;
160
161    Dst = AllocatePool (Size);
162    if (Dst) {
163        DstPos = (UINT8 *) Dst;
164
165        //
166        // Copy all device path instances
167        //
168
169        while ((Inst = DevicePathInstance (&Src1, &Size))) {
170
171            CopyMem(DstPos, Inst, Size);
172            DstPos += Size;
173
174            CopyMem(DstPos, Src2, Src2Size);
175            DstPos += Src2Size;
176
177            CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
178            DstPos += sizeof(EFI_DEVICE_PATH);
179        }
180
181        // Change last end marker
182        DstPos -= sizeof(EFI_DEVICE_PATH);
183        CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
184    }
185
186    return Dst;
187}
188
189
190EFI_DEVICE_PATH *
191AppendDevicePathNode (
192    IN EFI_DEVICE_PATH  *Src1,
193    IN EFI_DEVICE_PATH  *Src2
194    )
195// Src1 may have multiple "instances" and each instance is appended
196// Src2 is a signal device path node (without a terminator) that is
197// appended to each instance is Src1.
198{
199    EFI_DEVICE_PATH     *Temp, *Eop;
200    UINTN               Length;
201
202    //
203    // Build a Src2 that has a terminator on it
204    //
205
206    Length = DevicePathNodeLength(Src2);
207    Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
208    if (!Temp) {
209        return NULL;
210    }
211
212    CopyMem (Temp, Src2, Length);
213    Eop = NextDevicePathNode(Temp);
214    SetDevicePathEndNode(Eop);
215
216    //
217    // Append device paths
218    //
219
220    Src1 = AppendDevicePath (Src1, Temp);
221    FreePool (Temp);
222    return Src1;
223}
224
225
226EFI_DEVICE_PATH *
227FileDevicePath (
228    IN EFI_HANDLE       Device  OPTIONAL,
229    IN CHAR16           *FileName
230    )
231/*++
232
233    N.B. Results are allocated from pool.  The caller must FreePool
234    the resulting device path structure
235
236--*/
237{
238    UINTN                   Size;
239    FILEPATH_DEVICE_PATH    *FilePath;
240    EFI_DEVICE_PATH         *Eop, *DevicePath;
241
242    Size = StrSize(FileName);
243    FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
244    DevicePath = NULL;
245
246    if (FilePath) {
247
248        //
249        // Build a file path
250        //
251
252        FilePath->Header.Type = MEDIA_DEVICE_PATH;
253        FilePath->Header.SubType = MEDIA_FILEPATH_DP;
254        SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
255        CopyMem (FilePath->PathName, FileName, Size);
256        Eop = NextDevicePathNode(&FilePath->Header);
257        SetDevicePathEndNode(Eop);
258
259        //
260        // Append file path to device's device path
261        //
262
263        DevicePath = (EFI_DEVICE_PATH *) FilePath;
264        if (Device) {
265            DevicePath = AppendDevicePath (
266                            DevicePathFromHandle(Device),
267                            DevicePath
268                            );
269
270            FreePool(FilePath);
271        }
272    }
273
274    return DevicePath;
275}
276
277
278
279UINTN
280DevicePathSize (
281    IN EFI_DEVICE_PATH  *DevPath
282    )
283{
284    EFI_DEVICE_PATH     *Start;
285
286    //
287    // Search for the end of the device path structure
288    //
289
290    Start = DevPath;
291    while (!IsDevicePathEnd(DevPath)) {
292        DevPath = NextDevicePathNode(DevPath);
293    }
294
295    //
296    // Compute the size
297    //
298
299    return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
300}
301
302EFI_DEVICE_PATH *
303DuplicateDevicePath (
304    IN EFI_DEVICE_PATH  *DevPath
305    )
306{
307    EFI_DEVICE_PATH     *NewDevPath;
308    UINTN               Size;
309
310
311    //
312    // Compute the size
313    //
314
315    Size = DevicePathSize (DevPath);
316
317    //
318    // Make a copy
319    //
320
321    NewDevPath = AllocatePool (Size);
322    if (NewDevPath) {
323        CopyMem (NewDevPath, DevPath, Size);
324    }
325
326    return NewDevPath;
327}
328
329EFI_DEVICE_PATH *
330UnpackDevicePath (
331    IN EFI_DEVICE_PATH  *DevPath
332    )
333{
334    EFI_DEVICE_PATH     *Src, *Dest, *NewPath;
335    UINTN               Size;
336
337    //
338    // Walk device path and round sizes to valid boundries
339    //
340
341    Src = DevPath;
342    Size = 0;
343    for (; ;) {
344        Size += DevicePathNodeLength(Src);
345        Size += ALIGN_SIZE(Size);
346
347        if (IsDevicePathEnd(Src)) {
348            break;
349        }
350
351        Src = NextDevicePathNode(Src);
352    }
353
354
355    //
356    // Allocate space for the unpacked path
357    //
358
359    NewPath = AllocateZeroPool (Size);
360    if (NewPath) {
361
362        ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
363
364        //
365        // Copy each node
366        //
367
368        Src = DevPath;
369        Dest = NewPath;
370        for (; ;) {
371            Size = DevicePathNodeLength(Src);
372            CopyMem (Dest, Src, Size);
373            Size += ALIGN_SIZE(Size);
374            SetDevicePathNodeLength (Dest, Size);
375            Dest->Type |= EFI_DP_TYPE_UNPACKED;
376            Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
377
378            if (IsDevicePathEnd(Src)) {
379                break;
380            }
381
382            Src = NextDevicePathNode(Src);
383        }
384    }
385
386    return NewPath;
387}
388
389
390EFI_DEVICE_PATH*
391AppendDevicePathInstance (
392    IN EFI_DEVICE_PATH  *Src,
393    IN EFI_DEVICE_PATH  *Instance
394    )
395{
396    UINT8           *Ptr;
397    EFI_DEVICE_PATH *DevPath;
398    UINTN           SrcSize;
399    UINTN           InstanceSize;
400
401    if (Src == NULL) {
402        return DuplicateDevicePath (Instance);
403    }
404    SrcSize = DevicePathSize(Src);
405    InstanceSize = DevicePathSize(Instance);
406    Ptr = AllocatePool (SrcSize + InstanceSize);
407    DevPath = (EFI_DEVICE_PATH *)Ptr;
408    ASSERT(DevPath);
409
410    CopyMem (Ptr, Src, SrcSize);
411//    FreePool (Src);
412
413    while (!IsDevicePathEnd(DevPath)) {
414        DevPath = NextDevicePathNode(DevPath);
415    }
416    //
417    // Convert the End to an End Instance, since we are
418    //  appending another instacne after this one its a good
419    //  idea.
420    //
421    DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
422
423    DevPath = NextDevicePathNode(DevPath);
424    CopyMem (DevPath, Instance, InstanceSize);
425    return (EFI_DEVICE_PATH *)Ptr;
426}
427
428EFI_STATUS
429LibDevicePathToInterface (
430    IN EFI_GUID             *Protocol,
431    IN EFI_DEVICE_PATH      *FilePath,
432    OUT VOID                **Interface
433    )
434{
435    EFI_STATUS              Status;
436    EFI_HANDLE              Device;
437
438    Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
439
440    if (!EFI_ERROR(Status)) {
441
442        // If we didn't get a direct match return not found
443        Status = EFI_NOT_FOUND;
444
445        if (IsDevicePathEnd(FilePath)) {
446
447            //
448            // It was a direct match, lookup the protocol interface
449            //
450
451            Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
452        }
453    }
454
455    //
456    // If there was an error, do not return an interface
457    //
458
459    if (EFI_ERROR(Status)) {
460        *Interface = NULL;
461    }
462
463    return Status;
464}
465
466VOID
467_DevPathPci (
468    IN OUT POOL_PRINT       *Str,
469    IN VOID                 *DevPath
470    )
471{
472    PCI_DEVICE_PATH         *Pci;
473
474    Pci = DevPath;
475    CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
476}
477
478VOID
479_DevPathPccard (
480    IN OUT POOL_PRINT       *Str,
481    IN VOID                 *DevPath
482    )
483{
484    PCCARD_DEVICE_PATH      *Pccard;
485
486    Pccard = DevPath;
487    CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
488}
489
490VOID
491_DevPathMemMap (
492    IN OUT POOL_PRINT       *Str,
493    IN VOID                 *DevPath
494    )
495{
496    MEMMAP_DEVICE_PATH      *MemMap;
497
498    MemMap = DevPath;
499    CatPrint(Str, L"MemMap(%d:%x-%x)",
500        MemMap->MemoryType,
501        MemMap->StartingAddress,
502        MemMap->EndingAddress
503        );
504}
505
506VOID
507_DevPathController (
508    IN OUT POOL_PRINT       *Str,
509    IN VOID                 *DevPath
510    )
511{
512    CONTROLLER_DEVICE_PATH  *Controller;
513
514    Controller = DevPath;
515    CatPrint(Str, L"Ctrl(%d)",
516        Controller->Controller
517        );
518}
519
520VOID
521_DevPathVendor (
522    IN OUT POOL_PRINT       *Str,
523    IN VOID                 *DevPath
524    )
525{
526    VENDOR_DEVICE_PATH                  *Vendor;
527    CHAR16                              *Type;
528    UNKNOWN_DEVICE_VENDOR_DEVICE_PATH   *UnknownDevPath;
529
530    Vendor = DevPath;
531    switch (DevicePathType(&Vendor->Header)) {
532    case HARDWARE_DEVICE_PATH:  Type = L"Hw";        break;
533    case MESSAGING_DEVICE_PATH: Type = L"Msg";       break;
534    case MEDIA_DEVICE_PATH:     Type = L"Media";     break;
535    default:                    Type = L"?";         break;
536    }
537
538    CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
539    if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
540        //
541        // GUID used by EFI to enumerate an EDD 1.1 device
542        //
543        UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
544        CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
545    } else {
546        CatPrint(Str, L")");
547    }
548}
549
550
551VOID
552_DevPathAcpi (
553    IN OUT POOL_PRINT       *Str,
554    IN VOID                 *DevPath
555    )
556{
557    ACPI_HID_DEVICE_PATH        *Acpi;
558
559    Acpi = DevPath;
560    if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
561        CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
562    } else {
563        CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
564    }
565}
566
567
568VOID
569_DevPathAtapi (
570    IN OUT POOL_PRINT       *Str,
571    IN VOID                 *DevPath
572    )
573{
574    ATAPI_DEVICE_PATH       *Atapi;
575
576    Atapi = DevPath;
577    CatPrint(Str, L"Ata(%s,%s)",
578        Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
579        Atapi->SlaveMaster ? L"Slave" : L"Master"
580        );
581}
582
583VOID
584_DevPathScsi (
585    IN OUT POOL_PRINT       *Str,
586    IN VOID                 *DevPath
587    )
588{
589    SCSI_DEVICE_PATH        *Scsi;
590
591    Scsi = DevPath;
592    CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
593}
594
595
596VOID
597_DevPathFibre (
598    IN OUT POOL_PRINT       *Str,
599    IN VOID                 *DevPath
600    )
601{
602    FIBRECHANNEL_DEVICE_PATH    *Fibre;
603
604    Fibre = DevPath;
605    CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
606}
607
608VOID
609_DevPath1394 (
610    IN OUT POOL_PRINT       *Str,
611    IN VOID                 *DevPath
612    )
613{
614    F1394_DEVICE_PATH       *F1394;
615
616    F1394 = DevPath;
617    CatPrint(Str, L"1394(%g)", &F1394->Guid);
618}
619
620
621
622VOID
623_DevPathUsb (
624    IN OUT POOL_PRINT       *Str,
625    IN VOID                 *DevPath
626    )
627{
628    USB_DEVICE_PATH         *Usb;
629
630    Usb = DevPath;
631    CatPrint(Str, L"Usb(%x)", Usb->Port);
632}
633
634
635VOID
636_DevPathI2O (
637    IN OUT POOL_PRINT       *Str,
638    IN VOID                 *DevPath
639    )
640{
641    I2O_DEVICE_PATH         *I2O;
642
643    I2O = DevPath;
644    CatPrint(Str, L"I2O(%x)", I2O->Tid);
645}
646
647VOID
648_DevPathMacAddr (
649    IN OUT POOL_PRINT       *Str,
650    IN VOID                 *DevPath
651    )
652{
653    MAC_ADDR_DEVICE_PATH    *MAC;
654    UINTN                   HwAddressSize;
655    UINTN                   Index;
656
657    MAC = DevPath;
658
659    HwAddressSize = sizeof(EFI_MAC_ADDRESS);
660    if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
661        HwAddressSize = 6;
662    }
663
664    CatPrint(Str, L"Mac(");
665
666    for(Index = 0; Index < HwAddressSize; Index++) {
667        CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
668    }
669    CatPrint(Str, L")");
670}
671
672VOID
673_DevPathIPv4 (
674    IN OUT POOL_PRINT       *Str,
675    IN VOID                 *DevPath
676    )
677{
678    IPv4_DEVICE_PATH     *IP;
679
680    IP = DevPath;
681    CatPrint(Str, L"IPv4(not-done)");
682}
683
684VOID
685_DevPathIPv6 (
686    IN OUT POOL_PRINT       *Str,
687    IN VOID                 *DevPath
688    )
689{
690    IPv6_DEVICE_PATH     *IP;
691
692    IP = DevPath;
693    CatPrint(Str, L"IP-v6(not-done)");
694}
695
696VOID
697_DevPathInfiniBand (
698    IN OUT POOL_PRINT       *Str,
699    IN VOID                 *DevPath
700    )
701{
702    INFINIBAND_DEVICE_PATH  *InfiniBand;
703
704    InfiniBand = DevPath;
705    CatPrint(Str, L"InfiniBand(not-done)");
706}
707
708VOID
709_DevPathUart (
710    IN OUT POOL_PRINT       *Str,
711    IN VOID                 *DevPath
712    )
713{
714    UART_DEVICE_PATH  *Uart;
715    CHAR8             Parity;
716
717    Uart = DevPath;
718    switch (Uart->Parity) {
719        case 0  : Parity = 'D'; break;
720        case 1  : Parity = 'N'; break;
721        case 2  : Parity = 'E'; break;
722        case 3  : Parity = 'O'; break;
723        case 4  : Parity = 'M'; break;
724        case 5  : Parity = 'S'; break;
725        default : Parity = 'x'; break;
726    }
727
728    if (Uart->BaudRate == 0) {
729        CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
730    } else {
731        CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
732    }
733
734    if (Uart->DataBits == 0) {
735        CatPrint(Str, L"D");
736    } else {
737        CatPrint(Str, L"%d",Uart->DataBits);
738    }
739
740    switch (Uart->StopBits) {
741        case 0  : CatPrint(Str, L"D)");   break;
742        case 1  : CatPrint(Str, L"1)");   break;
743        case 2  : CatPrint(Str, L"1.5)"); break;
744        case 3  : CatPrint(Str, L"2)");   break;
745        default : CatPrint(Str, L"x)");   break;
746    }
747}
748
749
750VOID
751_DevPathHardDrive (
752    IN OUT POOL_PRINT       *Str,
753    IN VOID                 *DevPath
754    )
755{
756    HARDDRIVE_DEVICE_PATH   *Hd;
757
758    Hd = DevPath;
759    switch (Hd->SignatureType) {
760        case SIGNATURE_TYPE_MBR:
761            CatPrint(Str, L"HD(Part%d,Sig%08X)",
762                Hd->PartitionNumber,
763                *((UINT32 *)(&(Hd->Signature[0])))
764                );
765            break;
766        case SIGNATURE_TYPE_GUID:
767            CatPrint(Str, L"HD(Part%d,Sig%g)",
768                Hd->PartitionNumber,
769                (EFI_GUID *) &(Hd->Signature[0])
770                );
771            break;
772        default:
773            CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
774                Hd->PartitionNumber,
775                Hd->MBRType,
776                Hd->SignatureType
777                );
778            break;
779    }
780}
781
782VOID
783_DevPathCDROM (
784    IN OUT POOL_PRINT       *Str,
785    IN VOID                 *DevPath
786    )
787{
788    CDROM_DEVICE_PATH       *Cd;
789
790    Cd = DevPath;
791    CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
792}
793
794VOID
795_DevPathFilePath (
796    IN OUT POOL_PRINT       *Str,
797    IN VOID                 *DevPath
798    )
799{
800    FILEPATH_DEVICE_PATH    *Fp;
801
802    Fp = DevPath;
803    CatPrint(Str, L"%s", Fp->PathName);
804}
805
806VOID
807_DevPathMediaProtocol (
808    IN OUT POOL_PRINT       *Str,
809    IN VOID                 *DevPath
810    )
811{
812    MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
813
814    MediaProt = DevPath;
815    CatPrint(Str, L"%g", &MediaProt->Protocol);
816}
817
818VOID
819_DevPathBssBss (
820    IN OUT POOL_PRINT       *Str,
821    IN VOID                 *DevPath
822    )
823{
824    BBS_BBS_DEVICE_PATH     *Bss;
825    CHAR16                  *Type;
826
827    Bss = DevPath;
828    switch (Bss->DeviceType) {
829    case BBS_TYPE_FLOPPY:               Type = L"Floppy";       break;
830    case BBS_TYPE_HARDDRIVE:            Type = L"Harddrive";    break;
831    case BBS_TYPE_CDROM:                Type = L"CDROM";        break;
832    case BBS_TYPE_PCMCIA:               Type = L"PCMCIA";       break;
833    case BBS_TYPE_USB:                  Type = L"Usb";          break;
834    case BBS_TYPE_EMBEDDED_NETWORK:     Type = L"Net";          break;
835    default:                            Type = L"?";            break;
836    }
837
838    CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
839}
840
841
842VOID
843_DevPathEndInstance (
844    IN OUT POOL_PRINT       *Str,
845    IN VOID                 *DevPath
846    )
847{
848    CatPrint(Str, L",");
849}
850
851VOID
852_DevPathNodeUnknown (
853    IN OUT POOL_PRINT       *Str,
854    IN VOID                 *DevPath
855    )
856{
857    CatPrint(Str, L"?");
858}
859
860
861struct {
862    UINT8   Type;
863    UINT8   SubType;
864    VOID    (*Function)(POOL_PRINT *, VOID *);
865} DevPathTable[] = {
866	{ HARDWARE_DEVICE_PATH,   HW_PCI_DP,                        _DevPathPci},
867	{ HARDWARE_DEVICE_PATH,   HW_PCCARD_DP,                     _DevPathPccard},
868	{ HARDWARE_DEVICE_PATH,   HW_MEMMAP_DP,                     _DevPathMemMap},
869	{ HARDWARE_DEVICE_PATH,   HW_VENDOR_DP,                     _DevPathVendor},
870	{ HARDWARE_DEVICE_PATH,   HW_CONTROLLER_DP,                 _DevPathController},
871	{ ACPI_DEVICE_PATH,       ACPI_DP,                          _DevPathAcpi},
872	{ MESSAGING_DEVICE_PATH,  MSG_ATAPI_DP,                     _DevPathAtapi},
873	{ MESSAGING_DEVICE_PATH,  MSG_SCSI_DP,                      _DevPathScsi},
874	{ MESSAGING_DEVICE_PATH,  MSG_FIBRECHANNEL_DP,              _DevPathFibre},
875	{ MESSAGING_DEVICE_PATH,  MSG_1394_DP,                      _DevPath1394},
876	{ MESSAGING_DEVICE_PATH,  MSG_USB_DP,                       _DevPathUsb},
877	{ MESSAGING_DEVICE_PATH,  MSG_I2O_DP,                       _DevPathI2O},
878	{ MESSAGING_DEVICE_PATH,  MSG_MAC_ADDR_DP,                  _DevPathMacAddr},
879	{ MESSAGING_DEVICE_PATH,  MSG_IPv4_DP,                      _DevPathIPv4},
880	{ MESSAGING_DEVICE_PATH,  MSG_IPv6_DP,                      _DevPathIPv6},
881	{ MESSAGING_DEVICE_PATH,  MSG_INFINIBAND_DP,                _DevPathInfiniBand},
882	{ MESSAGING_DEVICE_PATH,  MSG_UART_DP,                      _DevPathUart},
883	{ MESSAGING_DEVICE_PATH,  MSG_VENDOR_DP,                    _DevPathVendor},
884	{ MEDIA_DEVICE_PATH,      MEDIA_HARDDRIVE_DP,               _DevPathHardDrive},
885	{ MEDIA_DEVICE_PATH,      MEDIA_CDROM_DP,                   _DevPathCDROM},
886	{ MEDIA_DEVICE_PATH,      MEDIA_VENDOR_DP,                  _DevPathVendor},
887	{ MEDIA_DEVICE_PATH,      MEDIA_FILEPATH_DP,                _DevPathFilePath},
888	{ MEDIA_DEVICE_PATH,      MEDIA_PROTOCOL_DP,                _DevPathMediaProtocol},
889	{ BBS_DEVICE_PATH,        BBS_BBS_DP,                       _DevPathBssBss},
890	{ END_DEVICE_PATH_TYPE,   END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
891	{ 0,                      0,                          NULL}
892};
893
894
895CHAR16 *
896DevicePathToStr (
897    EFI_DEVICE_PATH     *DevPath
898    )
899/*++
900
901    Turns the Device Path into a printable string.  Allcoates
902    the string from pool.  The caller must FreePool the returned
903    string.
904
905--*/
906{
907    POOL_PRINT          Str;
908    EFI_DEVICE_PATH     *DevPathNode;
909    VOID                (*DumpNode)(POOL_PRINT *, VOID *);
910    UINTN               Index, NewSize;
911
912    ZeroMem(&Str, sizeof(Str));
913
914    //
915    // Unpacked the device path
916    //
917
918    DevPath = UnpackDevicePath(DevPath);
919    ASSERT (DevPath);
920
921
922    //
923    // Process each device path node
924    //
925
926    DevPathNode = DevPath;
927    while (!IsDevicePathEnd(DevPathNode)) {
928        //
929        // Find the handler to dump this device path node
930        //
931
932        DumpNode = NULL;
933        for (Index = 0; DevPathTable[Index].Function; Index += 1) {
934
935            if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
936                DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
937                DumpNode = DevPathTable[Index].Function;
938                break;
939            }
940        }
941
942        //
943        // If not found, use a generic function
944        //
945
946        if (!DumpNode) {
947            DumpNode = _DevPathNodeUnknown;
948        }
949
950        //
951        //  Put a path seperator in if needed
952        //
953
954        if (Str.len  &&  DumpNode != _DevPathEndInstance) {
955            CatPrint (&Str, L"/");
956        }
957
958        //
959        // Print this node of the device path
960        //
961
962        DumpNode (&Str, DevPathNode);
963
964        //
965        // Next device path node
966        //
967
968        DevPathNode = NextDevicePathNode(DevPathNode);
969    }
970
971    //
972    // Shrink pool used for string allocation
973    //
974
975    FreePool (DevPath);
976    NewSize = (Str.len + 1) * sizeof(CHAR16);
977    Str.str = ReallocatePool (Str.str, NewSize, NewSize);
978    Str.str[Str.len] = 0;
979    return Str.str;
980}
981
982BOOLEAN
983LibMatchDevicePaths (
984    IN  EFI_DEVICE_PATH *Multi,
985    IN  EFI_DEVICE_PATH *Single
986    )
987{
988    EFI_DEVICE_PATH     *DevicePath, *DevicePathInst;
989    UINTN               Size;
990
991    if (!Multi || !Single) {
992        return FALSE;
993    }
994
995    DevicePath = Multi;
996    while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
997        if (CompareMem (Single, DevicePathInst, Size) == 0) {
998            return TRUE;
999        }
1000    }
1001    return FALSE;
1002}
1003
1004EFI_DEVICE_PATH *
1005LibDuplicateDevicePathInstance (
1006    IN EFI_DEVICE_PATH  *DevPath
1007    )
1008{
1009    EFI_DEVICE_PATH     *NewDevPath,*DevicePathInst,*Temp;
1010    UINTN               Size = 0;
1011
1012    //
1013    // get the size of an instance from the input
1014    //
1015
1016    Temp = DevPath;
1017    DevicePathInst = DevicePathInstance (&Temp, &Size);
1018
1019    //
1020    // Make a copy and set proper end type
1021    //
1022    NewDevPath = NULL;
1023    if (Size) {
1024        NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1025    }
1026
1027    if (NewDevPath) {
1028        CopyMem (NewDevPath, DevicePathInst, Size);
1029        Temp = NextDevicePathNode(NewDevPath);
1030        SetDevicePathEndNode(Temp);
1031    }
1032
1033    return NewDevPath;
1034}
1035
1036