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