xref: /DragonStub/lib/dpath.c (revision 9835e11ebe95ed8372ac2a6671de07cc970cdee0)
1530d68baSNigel Croxon /*++
2530d68baSNigel Croxon 
3530d68baSNigel Croxon Copyright (c) 1998  Intel Corporation
4530d68baSNigel Croxon 
5530d68baSNigel Croxon Module Name:
6530d68baSNigel Croxon 
7530d68baSNigel Croxon     dpath.c
8530d68baSNigel Croxon 
9530d68baSNigel Croxon Abstract:
10530d68baSNigel Croxon     MBR & Device Path functions
11530d68baSNigel Croxon 
12530d68baSNigel Croxon 
13530d68baSNigel Croxon 
14530d68baSNigel Croxon Revision History
15530d68baSNigel Croxon 
16530d68baSNigel Croxon 2014/04 B.Burette - updated device path text representation, conforming to
17530d68baSNigel Croxon 	UEFI specification 2.4 (dec. 2013). More specifically:
18530d68baSNigel Croxon 	- § 9.3.5: added some media types ie. Sata()
19530d68baSNigel Croxon 	- § 9.6.1.2: Acpi(PNP0A03,0) makes more sense when displayed as PciRoot(0)
20530d68baSNigel Croxon 	- § 9.6.1.5: use commas (instead of '|') between option specific parameters
21530d68baSNigel Croxon 	- § 9.6.1.6: hex values in device paths must be preceded by "0x" or "0X"
22530d68baSNigel Croxon 
23530d68baSNigel Croxon --*/
24530d68baSNigel Croxon 
25530d68baSNigel Croxon #include "lib.h"
26530d68baSNigel Croxon 
27530d68baSNigel Croxon #define ALIGN_SIZE(a)   ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
28530d68baSNigel Croxon 
29530d68baSNigel Croxon 
30530d68baSNigel Croxon 
31530d68baSNigel Croxon EFI_DEVICE_PATH *
DevicePathFromHandle(IN EFI_HANDLE Handle)32530d68baSNigel Croxon DevicePathFromHandle (
33530d68baSNigel Croxon     IN EFI_HANDLE       Handle
34530d68baSNigel Croxon     )
35530d68baSNigel Croxon {
36530d68baSNigel Croxon     EFI_STATUS          Status;
37530d68baSNigel Croxon     EFI_DEVICE_PATH     *DevicePath;
38530d68baSNigel Croxon 
39530d68baSNigel Croxon     Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath);
40530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
41530d68baSNigel Croxon         DevicePath = NULL;
42530d68baSNigel Croxon     }
43530d68baSNigel Croxon 
44530d68baSNigel Croxon     return DevicePath;
45530d68baSNigel Croxon }
46530d68baSNigel Croxon 
47530d68baSNigel Croxon 
48530d68baSNigel Croxon EFI_DEVICE_PATH *
DevicePathInstance(IN OUT EFI_DEVICE_PATH ** DevicePath,OUT UINTN * Size)49530d68baSNigel Croxon DevicePathInstance (
50530d68baSNigel Croxon     IN OUT EFI_DEVICE_PATH  **DevicePath,
51530d68baSNigel Croxon     OUT UINTN               *Size
52530d68baSNigel Croxon     )
53530d68baSNigel Croxon {
54530d68baSNigel Croxon     EFI_DEVICE_PATH         *Start, *Next, *DevPath;
55530d68baSNigel Croxon     UINTN                   Count;
56530d68baSNigel Croxon 
57530d68baSNigel Croxon     DevPath = *DevicePath;
58530d68baSNigel Croxon     Start = DevPath;
59530d68baSNigel Croxon 
60530d68baSNigel Croxon     if (!DevPath) {
61530d68baSNigel Croxon         return NULL;
62530d68baSNigel Croxon     }
63530d68baSNigel Croxon 
64530d68baSNigel Croxon     //
65530d68baSNigel Croxon     // Check for end of device path type
66530d68baSNigel Croxon     //
67530d68baSNigel Croxon 
68530d68baSNigel Croxon     for (Count = 0; ; Count++) {
69530d68baSNigel Croxon         Next = NextDevicePathNode(DevPath);
70530d68baSNigel Croxon 
71530d68baSNigel Croxon         if (IsDevicePathEndType(DevPath)) {
72530d68baSNigel Croxon             break;
73530d68baSNigel Croxon         }
74530d68baSNigel Croxon 
75530d68baSNigel Croxon         if (Count > 01000) {
76530d68baSNigel Croxon             //
77530d68baSNigel Croxon             // BugBug: Debug code to catch bogus device paths
78530d68baSNigel Croxon             //
79530d68baSNigel Croxon             DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) ));
80530d68baSNigel Croxon             DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start);
81530d68baSNigel Croxon             break;
82530d68baSNigel Croxon         }
83530d68baSNigel Croxon 
84530d68baSNigel Croxon         DevPath = Next;
85530d68baSNigel Croxon     }
86530d68baSNigel Croxon 
87530d68baSNigel Croxon     ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE ||
88530d68baSNigel Croxon             DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE);
89530d68baSNigel Croxon 
90530d68baSNigel Croxon     //
91530d68baSNigel Croxon     // Set next position
92530d68baSNigel Croxon     //
93530d68baSNigel Croxon 
94530d68baSNigel Croxon     if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
95530d68baSNigel Croxon         Next = NULL;
96530d68baSNigel Croxon     }
97530d68baSNigel Croxon 
98530d68baSNigel Croxon     *DevicePath = Next;
99530d68baSNigel Croxon 
100530d68baSNigel Croxon     //
101530d68baSNigel Croxon     // Return size and start of device path instance
102530d68baSNigel Croxon     //
103530d68baSNigel Croxon 
104530d68baSNigel Croxon     *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start);
105530d68baSNigel Croxon     return Start;
106530d68baSNigel Croxon }
107530d68baSNigel Croxon 
108530d68baSNigel Croxon UINTN
DevicePathInstanceCount(IN EFI_DEVICE_PATH * DevicePath)109530d68baSNigel Croxon DevicePathInstanceCount (
110530d68baSNigel Croxon     IN EFI_DEVICE_PATH      *DevicePath
111530d68baSNigel Croxon     )
112530d68baSNigel Croxon {
113530d68baSNigel Croxon     UINTN       Count, Size;
114530d68baSNigel Croxon 
115530d68baSNigel Croxon     Count = 0;
116530d68baSNigel Croxon     while (DevicePathInstance(&DevicePath, &Size)) {
117530d68baSNigel Croxon         Count += 1;
118530d68baSNigel Croxon     }
119530d68baSNigel Croxon 
120530d68baSNigel Croxon     return Count;
121530d68baSNigel Croxon }
122530d68baSNigel Croxon 
123530d68baSNigel Croxon 
124530d68baSNigel Croxon EFI_DEVICE_PATH *
AppendDevicePath(IN EFI_DEVICE_PATH * Src1,IN EFI_DEVICE_PATH * Src2)125530d68baSNigel Croxon AppendDevicePath (
126530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Src1,
127530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Src2
128530d68baSNigel Croxon     )
129530d68baSNigel Croxon // Src1 may have multiple "instances" and each instance is appended
130530d68baSNigel Croxon // Src2 is appended to each instance is Src1.  (E.g., it's possible
131530d68baSNigel Croxon // to append a new instance to the complete device path by passing
132530d68baSNigel Croxon // it in Src2)
133530d68baSNigel Croxon {
134530d68baSNigel Croxon     UINTN               Src1Size, Src1Inst, Src2Size, Size;
135530d68baSNigel Croxon     EFI_DEVICE_PATH     *Dst, *Inst;
136530d68baSNigel Croxon     UINT8               *DstPos;
137530d68baSNigel Croxon 
138530d68baSNigel Croxon     //
139530d68baSNigel Croxon     // If there's only 1 path, just duplicate it
140530d68baSNigel Croxon     //
141530d68baSNigel Croxon 
142530d68baSNigel Croxon     if (!Src1) {
143530d68baSNigel Croxon         ASSERT (!IsDevicePathUnpacked (Src2));
144530d68baSNigel Croxon         return DuplicateDevicePath (Src2);
145530d68baSNigel Croxon     }
146530d68baSNigel Croxon 
147530d68baSNigel Croxon     if (!Src2) {
148530d68baSNigel Croxon         ASSERT (!IsDevicePathUnpacked (Src1));
149530d68baSNigel Croxon         return DuplicateDevicePath (Src1);
150530d68baSNigel Croxon     }
151530d68baSNigel Croxon 
152530d68baSNigel Croxon     //
153530d68baSNigel Croxon     // Verify we're not working with unpacked paths
154530d68baSNigel Croxon     //
155530d68baSNigel Croxon 
156530d68baSNigel Croxon //    ASSERT (!IsDevicePathUnpacked (Src1));
157530d68baSNigel Croxon //    ASSERT (!IsDevicePathUnpacked (Src2));
158530d68baSNigel Croxon 
159530d68baSNigel Croxon     //
160530d68baSNigel Croxon     // Append Src2 to every instance in Src1
161530d68baSNigel Croxon     //
162530d68baSNigel Croxon 
163530d68baSNigel Croxon     Src1Size = DevicePathSize(Src1);
164530d68baSNigel Croxon     Src1Inst = DevicePathInstanceCount(Src1);
165530d68baSNigel Croxon     Src2Size = DevicePathSize(Src2);
166530d68baSNigel Croxon     Size = Src1Size * Src1Inst + Src2Size;
167530d68baSNigel Croxon 
168530d68baSNigel Croxon     Dst = AllocatePool (Size);
169530d68baSNigel Croxon     if (Dst) {
170530d68baSNigel Croxon         DstPos = (UINT8 *) Dst;
171530d68baSNigel Croxon 
172530d68baSNigel Croxon         //
173530d68baSNigel Croxon         // Copy all device path instances
174530d68baSNigel Croxon         //
175530d68baSNigel Croxon 
176530d68baSNigel Croxon         while ((Inst = DevicePathInstance (&Src1, &Size))) {
177530d68baSNigel Croxon 
178530d68baSNigel Croxon             CopyMem(DstPos, Inst, Size);
179530d68baSNigel Croxon             DstPos += Size;
180530d68baSNigel Croxon 
181530d68baSNigel Croxon             CopyMem(DstPos, Src2, Src2Size);
182530d68baSNigel Croxon             DstPos += Src2Size;
183530d68baSNigel Croxon 
184530d68baSNigel Croxon             CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
185530d68baSNigel Croxon             DstPos += sizeof(EFI_DEVICE_PATH);
186530d68baSNigel Croxon         }
187530d68baSNigel Croxon 
188530d68baSNigel Croxon         // Change last end marker
189530d68baSNigel Croxon         DstPos -= sizeof(EFI_DEVICE_PATH);
190530d68baSNigel Croxon         CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH));
191530d68baSNigel Croxon     }
192530d68baSNigel Croxon 
193530d68baSNigel Croxon     return Dst;
194530d68baSNigel Croxon }
195530d68baSNigel Croxon 
196530d68baSNigel Croxon 
197530d68baSNigel Croxon EFI_DEVICE_PATH *
AppendDevicePathNode(IN EFI_DEVICE_PATH * Src1,IN EFI_DEVICE_PATH * Src2)198530d68baSNigel Croxon AppendDevicePathNode (
199530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Src1,
200530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Src2
201530d68baSNigel Croxon     )
202530d68baSNigel Croxon // Src1 may have multiple "instances" and each instance is appended
203530d68baSNigel Croxon // Src2 is a signal device path node (without a terminator) that is
204530d68baSNigel Croxon // appended to each instance is Src1.
205530d68baSNigel Croxon {
206530d68baSNigel Croxon     EFI_DEVICE_PATH     *Temp, *Eop;
207530d68baSNigel Croxon     UINTN               Length;
208530d68baSNigel Croxon 
209530d68baSNigel Croxon     //
210530d68baSNigel Croxon     // Build a Src2 that has a terminator on it
211530d68baSNigel Croxon     //
212530d68baSNigel Croxon 
213530d68baSNigel Croxon     Length = DevicePathNodeLength(Src2);
214530d68baSNigel Croxon     Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
215530d68baSNigel Croxon     if (!Temp) {
216530d68baSNigel Croxon         return NULL;
217530d68baSNigel Croxon     }
218530d68baSNigel Croxon 
219530d68baSNigel Croxon     CopyMem (Temp, Src2, Length);
220530d68baSNigel Croxon     Eop = NextDevicePathNode(Temp);
221530d68baSNigel Croxon     SetDevicePathEndNode(Eop);
222530d68baSNigel Croxon 
223530d68baSNigel Croxon     //
224530d68baSNigel Croxon     // Append device paths
225530d68baSNigel Croxon     //
226530d68baSNigel Croxon 
227530d68baSNigel Croxon     Src1 = AppendDevicePath (Src1, Temp);
228530d68baSNigel Croxon     FreePool (Temp);
229530d68baSNigel Croxon     return Src1;
230530d68baSNigel Croxon }
231530d68baSNigel Croxon 
232530d68baSNigel Croxon 
233530d68baSNigel Croxon EFI_DEVICE_PATH *
FileDevicePath(IN EFI_HANDLE Device OPTIONAL,IN CHAR16 * FileName)234530d68baSNigel Croxon FileDevicePath (
235530d68baSNigel Croxon     IN EFI_HANDLE       Device  OPTIONAL,
236530d68baSNigel Croxon     IN CHAR16           *FileName
237530d68baSNigel Croxon     )
238530d68baSNigel Croxon /*++
239530d68baSNigel Croxon 
240530d68baSNigel Croxon     N.B. Results are allocated from pool.  The caller must FreePool
241530d68baSNigel Croxon     the resulting device path structure
242530d68baSNigel Croxon 
243530d68baSNigel Croxon --*/
244530d68baSNigel Croxon {
245530d68baSNigel Croxon     UINTN                   Size;
246530d68baSNigel Croxon     FILEPATH_DEVICE_PATH    *FilePath;
247530d68baSNigel Croxon     EFI_DEVICE_PATH         *Eop, *DevicePath;
248530d68baSNigel Croxon 
249530d68baSNigel Croxon     Size = StrSize(FileName);
250530d68baSNigel Croxon     FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
251530d68baSNigel Croxon     DevicePath = NULL;
252530d68baSNigel Croxon 
253530d68baSNigel Croxon     if (FilePath) {
254530d68baSNigel Croxon 
255530d68baSNigel Croxon         //
256530d68baSNigel Croxon         // Build a file path
257530d68baSNigel Croxon         //
258530d68baSNigel Croxon 
259530d68baSNigel Croxon         FilePath->Header.Type = MEDIA_DEVICE_PATH;
260530d68baSNigel Croxon         FilePath->Header.SubType = MEDIA_FILEPATH_DP;
261530d68baSNigel Croxon         SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
262530d68baSNigel Croxon         CopyMem (FilePath->PathName, FileName, Size);
263530d68baSNigel Croxon         Eop = NextDevicePathNode(&FilePath->Header);
264530d68baSNigel Croxon         SetDevicePathEndNode(Eop);
265530d68baSNigel Croxon 
266530d68baSNigel Croxon         //
267530d68baSNigel Croxon         // Append file path to device's device path
268530d68baSNigel Croxon         //
269530d68baSNigel Croxon 
270530d68baSNigel Croxon         DevicePath = (EFI_DEVICE_PATH *) FilePath;
271530d68baSNigel Croxon         if (Device) {
272530d68baSNigel Croxon             DevicePath = AppendDevicePath (
273530d68baSNigel Croxon                             DevicePathFromHandle(Device),
274530d68baSNigel Croxon                             DevicePath
275530d68baSNigel Croxon                             );
276530d68baSNigel Croxon 
277530d68baSNigel Croxon             FreePool(FilePath);
278530d68baSNigel Croxon         }
279530d68baSNigel Croxon     }
280530d68baSNigel Croxon 
281530d68baSNigel Croxon     return DevicePath;
282530d68baSNigel Croxon }
283530d68baSNigel Croxon 
284530d68baSNigel Croxon 
285530d68baSNigel Croxon 
286530d68baSNigel Croxon UINTN
DevicePathSize(IN EFI_DEVICE_PATH * DevPath)287530d68baSNigel Croxon DevicePathSize (
288530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *DevPath
289530d68baSNigel Croxon     )
290530d68baSNigel Croxon {
291530d68baSNigel Croxon     EFI_DEVICE_PATH     *Start;
292530d68baSNigel Croxon 
293530d68baSNigel Croxon     //
294530d68baSNigel Croxon     // Search for the end of the device path structure
295530d68baSNigel Croxon     //
296530d68baSNigel Croxon 
297530d68baSNigel Croxon     Start = DevPath;
298530d68baSNigel Croxon     while (!IsDevicePathEnd(DevPath)) {
299530d68baSNigel Croxon         DevPath = NextDevicePathNode(DevPath);
300530d68baSNigel Croxon     }
301530d68baSNigel Croxon 
302530d68baSNigel Croxon     //
303530d68baSNigel Croxon     // Compute the size
304530d68baSNigel Croxon     //
305530d68baSNigel Croxon 
306530d68baSNigel Croxon     return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH);
307530d68baSNigel Croxon }
308530d68baSNigel Croxon 
309530d68baSNigel Croxon EFI_DEVICE_PATH *
DuplicateDevicePath(IN EFI_DEVICE_PATH * DevPath)310530d68baSNigel Croxon DuplicateDevicePath (
311530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *DevPath
312530d68baSNigel Croxon     )
313530d68baSNigel Croxon {
314530d68baSNigel Croxon     EFI_DEVICE_PATH     *NewDevPath;
315530d68baSNigel Croxon     UINTN               Size;
316530d68baSNigel Croxon 
317530d68baSNigel Croxon 
318530d68baSNigel Croxon     //
319530d68baSNigel Croxon     // Compute the size
320530d68baSNigel Croxon     //
321530d68baSNigel Croxon 
322530d68baSNigel Croxon     Size = DevicePathSize (DevPath);
323530d68baSNigel Croxon 
324530d68baSNigel Croxon     //
325530d68baSNigel Croxon     // Make a copy
326530d68baSNigel Croxon     //
327530d68baSNigel Croxon 
328530d68baSNigel Croxon     NewDevPath = AllocatePool (Size);
329530d68baSNigel Croxon     if (NewDevPath) {
330530d68baSNigel Croxon         CopyMem (NewDevPath, DevPath, Size);
331530d68baSNigel Croxon     }
332530d68baSNigel Croxon 
333530d68baSNigel Croxon     return NewDevPath;
334530d68baSNigel Croxon }
335530d68baSNigel Croxon 
336530d68baSNigel Croxon EFI_DEVICE_PATH *
UnpackDevicePath(IN EFI_DEVICE_PATH * DevPath)337530d68baSNigel Croxon UnpackDevicePath (
338530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *DevPath
339530d68baSNigel Croxon     )
340530d68baSNigel Croxon {
341530d68baSNigel Croxon     EFI_DEVICE_PATH     *Src, *Dest, *NewPath;
342530d68baSNigel Croxon     UINTN               Size;
343530d68baSNigel Croxon 
344530d68baSNigel Croxon     //
345530d68baSNigel Croxon     // Walk device path and round sizes to valid boundries
346530d68baSNigel Croxon     //
347530d68baSNigel Croxon 
348530d68baSNigel Croxon     Src = DevPath;
349530d68baSNigel Croxon     Size = 0;
350530d68baSNigel Croxon     for (; ;) {
351530d68baSNigel Croxon         Size += DevicePathNodeLength(Src);
352530d68baSNigel Croxon         Size += ALIGN_SIZE(Size);
353530d68baSNigel Croxon 
354530d68baSNigel Croxon         if (IsDevicePathEnd(Src)) {
355530d68baSNigel Croxon             break;
356530d68baSNigel Croxon         }
357530d68baSNigel Croxon 
358530d68baSNigel Croxon         Src = NextDevicePathNode(Src);
359530d68baSNigel Croxon     }
360530d68baSNigel Croxon 
361530d68baSNigel Croxon 
362530d68baSNigel Croxon     //
363530d68baSNigel Croxon     // Allocate space for the unpacked path
364530d68baSNigel Croxon     //
365530d68baSNigel Croxon 
366530d68baSNigel Croxon     NewPath = AllocateZeroPool (Size);
367530d68baSNigel Croxon     if (NewPath) {
368530d68baSNigel Croxon 
369530d68baSNigel Croxon         ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
370530d68baSNigel Croxon 
371530d68baSNigel Croxon         //
372530d68baSNigel Croxon         // Copy each node
373530d68baSNigel Croxon         //
374530d68baSNigel Croxon 
375530d68baSNigel Croxon         Src = DevPath;
376530d68baSNigel Croxon         Dest = NewPath;
377530d68baSNigel Croxon         for (; ;) {
378530d68baSNigel Croxon             Size = DevicePathNodeLength(Src);
379530d68baSNigel Croxon             CopyMem (Dest, Src, Size);
380530d68baSNigel Croxon             Size += ALIGN_SIZE(Size);
381530d68baSNigel Croxon             SetDevicePathNodeLength (Dest, Size);
382530d68baSNigel Croxon             Dest->Type |= EFI_DP_TYPE_UNPACKED;
383530d68baSNigel Croxon             Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size);
384530d68baSNigel Croxon 
385530d68baSNigel Croxon             if (IsDevicePathEnd(Src)) {
386530d68baSNigel Croxon                 break;
387530d68baSNigel Croxon             }
388530d68baSNigel Croxon 
389530d68baSNigel Croxon             Src = NextDevicePathNode(Src);
390530d68baSNigel Croxon         }
391530d68baSNigel Croxon     }
392530d68baSNigel Croxon 
393530d68baSNigel Croxon     return NewPath;
394530d68baSNigel Croxon }
395530d68baSNigel Croxon 
396530d68baSNigel Croxon 
397530d68baSNigel Croxon EFI_DEVICE_PATH*
AppendDevicePathInstance(IN EFI_DEVICE_PATH * Src,IN EFI_DEVICE_PATH * Instance)398530d68baSNigel Croxon AppendDevicePathInstance (
399530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Src,
400530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *Instance
401530d68baSNigel Croxon     )
402530d68baSNigel Croxon {
403530d68baSNigel Croxon     UINT8           *Ptr;
404530d68baSNigel Croxon     EFI_DEVICE_PATH *DevPath;
405530d68baSNigel Croxon     UINTN           SrcSize;
406530d68baSNigel Croxon     UINTN           InstanceSize;
407530d68baSNigel Croxon 
408530d68baSNigel Croxon     if (Src == NULL) {
409530d68baSNigel Croxon         return DuplicateDevicePath (Instance);
410530d68baSNigel Croxon     }
411530d68baSNigel Croxon     SrcSize = DevicePathSize(Src);
412530d68baSNigel Croxon     InstanceSize = DevicePathSize(Instance);
413530d68baSNigel Croxon     Ptr = AllocatePool (SrcSize + InstanceSize);
414530d68baSNigel Croxon     DevPath = (EFI_DEVICE_PATH *)Ptr;
415530d68baSNigel Croxon     ASSERT(DevPath);
416530d68baSNigel Croxon 
417530d68baSNigel Croxon     CopyMem (Ptr, Src, SrcSize);
418530d68baSNigel Croxon //    FreePool (Src);
419530d68baSNigel Croxon 
420530d68baSNigel Croxon     while (!IsDevicePathEnd(DevPath)) {
421530d68baSNigel Croxon         DevPath = NextDevicePathNode(DevPath);
422530d68baSNigel Croxon     }
423530d68baSNigel Croxon     //
424530d68baSNigel Croxon     // Convert the End to an End Instance, since we are
425530d68baSNigel Croxon     //  appending another instacne after this one its a good
426530d68baSNigel Croxon     //  idea.
427530d68baSNigel Croxon     //
428530d68baSNigel Croxon     DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
429530d68baSNigel Croxon 
430530d68baSNigel Croxon     DevPath = NextDevicePathNode(DevPath);
431530d68baSNigel Croxon     CopyMem (DevPath, Instance, InstanceSize);
432530d68baSNigel Croxon     return (EFI_DEVICE_PATH *)Ptr;
433530d68baSNigel Croxon }
434530d68baSNigel Croxon 
435530d68baSNigel Croxon EFI_STATUS
LibDevicePathToInterface(IN EFI_GUID * Protocol,IN EFI_DEVICE_PATH * FilePath,OUT VOID ** Interface)436530d68baSNigel Croxon LibDevicePathToInterface (
437530d68baSNigel Croxon     IN EFI_GUID             *Protocol,
438530d68baSNigel Croxon     IN EFI_DEVICE_PATH      *FilePath,
439530d68baSNigel Croxon     OUT VOID                **Interface
440530d68baSNigel Croxon     )
441530d68baSNigel Croxon {
442530d68baSNigel Croxon     EFI_STATUS              Status;
443530d68baSNigel Croxon     EFI_HANDLE              Device;
444530d68baSNigel Croxon 
445530d68baSNigel Croxon     Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device);
446530d68baSNigel Croxon 
447530d68baSNigel Croxon     if (!EFI_ERROR(Status)) {
448530d68baSNigel Croxon 
449530d68baSNigel Croxon         // If we didn't get a direct match return not found
450530d68baSNigel Croxon         Status = EFI_NOT_FOUND;
451530d68baSNigel Croxon 
452530d68baSNigel Croxon         if (IsDevicePathEnd(FilePath)) {
453530d68baSNigel Croxon 
454530d68baSNigel Croxon             //
455530d68baSNigel Croxon             // It was a direct match, lookup the protocol interface
456530d68baSNigel Croxon             //
457530d68baSNigel Croxon 
458530d68baSNigel Croxon             Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface);
459530d68baSNigel Croxon         }
460530d68baSNigel Croxon     }
461530d68baSNigel Croxon 
462530d68baSNigel Croxon     //
463530d68baSNigel Croxon     // If there was an error, do not return an interface
464530d68baSNigel Croxon     //
465530d68baSNigel Croxon 
466530d68baSNigel Croxon     if (EFI_ERROR(Status)) {
467530d68baSNigel Croxon         *Interface = NULL;
468530d68baSNigel Croxon     }
469530d68baSNigel Croxon 
470530d68baSNigel Croxon     return Status;
471530d68baSNigel Croxon }
472530d68baSNigel Croxon 
473530d68baSNigel Croxon static VOID
_DevPathPci(IN OUT POOL_PRINT * Str,IN VOID * DevPath)474530d68baSNigel Croxon _DevPathPci (
475530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
476530d68baSNigel Croxon     IN VOID                 *DevPath
477530d68baSNigel Croxon     )
478530d68baSNigel Croxon {
479530d68baSNigel Croxon     PCI_DEVICE_PATH         *Pci;
480530d68baSNigel Croxon 
481530d68baSNigel Croxon     Pci = DevPath;
482530d68baSNigel Croxon     CatPrint(Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
483530d68baSNigel Croxon }
484530d68baSNigel Croxon 
485530d68baSNigel Croxon static VOID
_DevPathPccard(IN OUT POOL_PRINT * Str,IN VOID * DevPath)486530d68baSNigel Croxon _DevPathPccard (
487530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
488530d68baSNigel Croxon     IN VOID                 *DevPath
489530d68baSNigel Croxon     )
490530d68baSNigel Croxon {
491530d68baSNigel Croxon     PCCARD_DEVICE_PATH      *Pccard;
492530d68baSNigel Croxon 
493530d68baSNigel Croxon     Pccard = DevPath;
494530d68baSNigel Croxon     CatPrint(Str, L"Pccard(0x%x)", Pccard-> FunctionNumber );
495530d68baSNigel Croxon }
496530d68baSNigel Croxon 
497530d68baSNigel Croxon static VOID
_DevPathMemMap(IN OUT POOL_PRINT * Str,IN VOID * DevPath)498530d68baSNigel Croxon _DevPathMemMap (
499530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
500530d68baSNigel Croxon     IN VOID                 *DevPath
501530d68baSNigel Croxon     )
502530d68baSNigel Croxon {
503530d68baSNigel Croxon     MEMMAP_DEVICE_PATH      *MemMap;
504530d68baSNigel Croxon 
505530d68baSNigel Croxon     MemMap = DevPath;
506530d68baSNigel Croxon     CatPrint(Str, L"MemMap(%d,0x%x,0x%x)",
507530d68baSNigel Croxon         MemMap->MemoryType,
508530d68baSNigel Croxon         MemMap->StartingAddress,
509530d68baSNigel Croxon         MemMap->EndingAddress
510530d68baSNigel Croxon         );
511530d68baSNigel Croxon }
512530d68baSNigel Croxon 
513530d68baSNigel Croxon static VOID
_DevPathController(IN OUT POOL_PRINT * Str,IN VOID * DevPath)514530d68baSNigel Croxon _DevPathController (
515530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
516530d68baSNigel Croxon     IN VOID                 *DevPath
517530d68baSNigel Croxon     )
518530d68baSNigel Croxon {
519530d68baSNigel Croxon     CONTROLLER_DEVICE_PATH  *Controller;
520530d68baSNigel Croxon 
521530d68baSNigel Croxon     Controller = DevPath;
522530d68baSNigel Croxon     CatPrint(Str, L"Ctrl(%d)",
523530d68baSNigel Croxon         Controller->Controller
524530d68baSNigel Croxon         );
525530d68baSNigel Croxon }
526530d68baSNigel Croxon 
527530d68baSNigel Croxon static VOID
_DevPathVendor(IN OUT POOL_PRINT * Str,IN VOID * DevPath)528530d68baSNigel Croxon _DevPathVendor (
529530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
530530d68baSNigel Croxon     IN VOID                 *DevPath
531530d68baSNigel Croxon     )
532530d68baSNigel Croxon {
533530d68baSNigel Croxon     VENDOR_DEVICE_PATH                  *Vendor;
534530d68baSNigel Croxon     CHAR16                              *Type;
535530d68baSNigel Croxon     UNKNOWN_DEVICE_VENDOR_DEVICE_PATH   *UnknownDevPath;
536530d68baSNigel Croxon 
537530d68baSNigel Croxon     Vendor = DevPath;
538530d68baSNigel Croxon     switch (DevicePathType(&Vendor->Header)) {
539530d68baSNigel Croxon     case HARDWARE_DEVICE_PATH:  Type = L"Hw";        break;
540530d68baSNigel Croxon     case MESSAGING_DEVICE_PATH: Type = L"Msg";       break;
541530d68baSNigel Croxon     case MEDIA_DEVICE_PATH:     Type = L"Media";     break;
542530d68baSNigel Croxon     default:                    Type = L"?";         break;
543530d68baSNigel Croxon     }
544530d68baSNigel Croxon 
545530d68baSNigel Croxon     CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid);
546530d68baSNigel Croxon     if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) {
547530d68baSNigel Croxon         //
548530d68baSNigel Croxon         // GUID used by EFI to enumerate an EDD 1.1 device
549530d68baSNigel Croxon         //
550530d68baSNigel Croxon         UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor;
551530d68baSNigel Croxon         CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
552530d68baSNigel Croxon     } else {
553530d68baSNigel Croxon         CatPrint(Str, L")");
554530d68baSNigel Croxon     }
555530d68baSNigel Croxon }
556530d68baSNigel Croxon 
557530d68baSNigel Croxon 
558530d68baSNigel Croxon /*
559530d68baSNigel Croxon   Type: 2 (ACPI Device Path) SubType: 1 (ACPI Device Path)
560530d68baSNigel Croxon  */
561530d68baSNigel Croxon static VOID
_DevPathAcpi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)562530d68baSNigel Croxon _DevPathAcpi (
563530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
564530d68baSNigel Croxon     IN VOID                 *DevPath
565530d68baSNigel Croxon     )
566530d68baSNigel Croxon {
567530d68baSNigel Croxon     ACPI_HID_DEVICE_PATH        *Acpi;
568530d68baSNigel Croxon 
569530d68baSNigel Croxon     Acpi = DevPath;
570530d68baSNigel Croxon     if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
571530d68baSNigel Croxon         switch ( EISA_ID_TO_NUM( Acpi-> HID ) ) {
572530d68baSNigel Croxon             case 0x301 : {
573530d68baSNigel Croxon                 CatPrint( Str , L"Keyboard(%d)" , Acpi-> UID ) ;
574530d68baSNigel Croxon                 break ;
575530d68baSNigel Croxon             }
576530d68baSNigel Croxon             case 0x401 : {
577530d68baSNigel Croxon                 CatPrint( Str , L"ParallelPort(%d)" , Acpi-> UID ) ;
578530d68baSNigel Croxon                 break ;
579530d68baSNigel Croxon             }
580530d68baSNigel Croxon             case 0x501 : {
581530d68baSNigel Croxon                 CatPrint( Str , L"Serial(%d)" , Acpi-> UID ) ;
582530d68baSNigel Croxon                 break ;
583530d68baSNigel Croxon             }
584530d68baSNigel Croxon             case 0x604 : {
585530d68baSNigel Croxon                 CatPrint( Str , L"Floppy(%d)" , Acpi-> UID ) ;
586530d68baSNigel Croxon                 break ;
587530d68baSNigel Croxon             }
588530d68baSNigel Croxon             case 0xa03 : {
589530d68baSNigel Croxon                 CatPrint( Str , L"PciRoot(%d)" , Acpi-> UID ) ;
590530d68baSNigel Croxon                 break ;
591530d68baSNigel Croxon             }
592530d68baSNigel Croxon             case 0xa08 : {
593530d68baSNigel Croxon                 CatPrint( Str , L"PcieRoot(%d)" , Acpi-> UID ) ;
594530d68baSNigel Croxon                 break ;
595530d68baSNigel Croxon             }
596530d68baSNigel Croxon             default : {
597530d68baSNigel Croxon                 CatPrint( Str , L"Acpi(PNP%04x" , EISA_ID_TO_NUM( Acpi-> HID ) ) ;
598530d68baSNigel Croxon                 if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
599530d68baSNigel Croxon                 CatPrint( Str , L")" ) ;
600530d68baSNigel Croxon                 break ;
601530d68baSNigel Croxon             }
602530d68baSNigel Croxon 	}
603530d68baSNigel Croxon     } else {
604530d68baSNigel Croxon         CatPrint( Str , L"Acpi(0x%X" , Acpi-> HID ) ;
605530d68baSNigel Croxon         if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ;
606530d68baSNigel Croxon         CatPrint( Str , L")" , Acpi-> HID , Acpi-> UID ) ;
607530d68baSNigel Croxon     }
608530d68baSNigel Croxon }
609530d68baSNigel Croxon 
610530d68baSNigel Croxon 
611530d68baSNigel Croxon static VOID
_DevPathAtapi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)612530d68baSNigel Croxon _DevPathAtapi (
613530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
614530d68baSNigel Croxon     IN VOID                 *DevPath
615530d68baSNigel Croxon     )
616530d68baSNigel Croxon {
617530d68baSNigel Croxon     ATAPI_DEVICE_PATH       *Atapi;
618530d68baSNigel Croxon 
619530d68baSNigel Croxon     Atapi = DevPath;
620530d68baSNigel Croxon     CatPrint(Str, L"Ata(%s,%s)",
621530d68baSNigel Croxon         Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
622530d68baSNigel Croxon         Atapi->SlaveMaster ? L"Slave" : L"Master"
623530d68baSNigel Croxon         );
624530d68baSNigel Croxon }
625530d68baSNigel Croxon 
626530d68baSNigel Croxon static VOID
_DevPathScsi(IN OUT POOL_PRINT * Str,IN VOID * DevPath)627530d68baSNigel Croxon _DevPathScsi (
628530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
629530d68baSNigel Croxon     IN VOID                 *DevPath
630530d68baSNigel Croxon     )
631530d68baSNigel Croxon {
632530d68baSNigel Croxon     SCSI_DEVICE_PATH        *Scsi;
633530d68baSNigel Croxon 
634530d68baSNigel Croxon     Scsi = DevPath;
635530d68baSNigel Croxon     CatPrint(Str, L"Scsi(%d,%d)", Scsi->Pun, Scsi->Lun);
636530d68baSNigel Croxon }
637530d68baSNigel Croxon 
638530d68baSNigel Croxon 
639530d68baSNigel Croxon static VOID
_DevPathFibre(IN OUT POOL_PRINT * Str,IN VOID * DevPath)640530d68baSNigel Croxon _DevPathFibre (
641530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
642530d68baSNigel Croxon     IN VOID                 *DevPath
643530d68baSNigel Croxon     )
644530d68baSNigel Croxon {
645530d68baSNigel Croxon     FIBRECHANNEL_DEVICE_PATH    *Fibre;
646530d68baSNigel Croxon 
647530d68baSNigel Croxon     Fibre = DevPath;
648530d68baSNigel Croxon     CatPrint( Str , L"Fibre%s(0x%016lx,0x%016lx)" ,
649530d68baSNigel Croxon         DevicePathType( & Fibre-> Header ) == MSG_FIBRECHANNEL_DP ? L"" : L"Ex" ,
650530d68baSNigel Croxon         Fibre-> WWN , Fibre-> Lun ) ;
651530d68baSNigel Croxon }
652530d68baSNigel Croxon 
653530d68baSNigel Croxon static VOID
_DevPath1394(IN OUT POOL_PRINT * Str,IN VOID * DevPath)654530d68baSNigel Croxon _DevPath1394 (
655530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
656530d68baSNigel Croxon     IN VOID                 *DevPath
657530d68baSNigel Croxon     )
658530d68baSNigel Croxon {
659530d68baSNigel Croxon     F1394_DEVICE_PATH       *F1394;
660530d68baSNigel Croxon 
661530d68baSNigel Croxon     F1394 = DevPath;
662d34132e6SNigel Croxon     // Guid has format of IEEE-EUI64
663d34132e6SNigel Croxon     CatPrint(Str, L"I1394(%016lx)", F1394->Guid);
664530d68baSNigel Croxon }
665530d68baSNigel Croxon 
666530d68baSNigel Croxon 
667530d68baSNigel Croxon 
668530d68baSNigel Croxon static VOID
_DevPathUsb(IN OUT POOL_PRINT * Str,IN VOID * DevPath)669530d68baSNigel Croxon _DevPathUsb (
670530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
671530d68baSNigel Croxon     IN VOID                 *DevPath
672530d68baSNigel Croxon     )
673530d68baSNigel Croxon {
674530d68baSNigel Croxon     USB_DEVICE_PATH         *Usb;
675530d68baSNigel Croxon 
676530d68baSNigel Croxon     Usb = DevPath;
677530d68baSNigel Croxon     CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ;
678530d68baSNigel Croxon }
679530d68baSNigel Croxon 
680530d68baSNigel Croxon 
681530d68baSNigel Croxon static VOID
_DevPathI2O(IN OUT POOL_PRINT * Str,IN VOID * DevPath)682530d68baSNigel Croxon _DevPathI2O (
683530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
684530d68baSNigel Croxon     IN VOID                 *DevPath
685530d68baSNigel Croxon     )
686530d68baSNigel Croxon {
687530d68baSNigel Croxon     I2O_DEVICE_PATH         *I2O;
688530d68baSNigel Croxon 
689530d68baSNigel Croxon     I2O = DevPath;
690530d68baSNigel Croxon     CatPrint(Str, L"I2O(0x%X)", I2O->Tid);
691530d68baSNigel Croxon }
692530d68baSNigel Croxon 
693530d68baSNigel Croxon static VOID
_DevPathMacAddr(IN OUT POOL_PRINT * Str,IN VOID * DevPath)694530d68baSNigel Croxon _DevPathMacAddr (
695530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
696530d68baSNigel Croxon     IN VOID                 *DevPath
697530d68baSNigel Croxon     )
698530d68baSNigel Croxon {
699530d68baSNigel Croxon     MAC_ADDR_DEVICE_PATH    *MAC;
700530d68baSNigel Croxon     UINTN                   HwAddressSize;
701530d68baSNigel Croxon     UINTN                   Index;
702530d68baSNigel Croxon 
703530d68baSNigel Croxon     MAC = DevPath;
704530d68baSNigel Croxon 
705530d68baSNigel Croxon     /* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */
706530d68baSNigel Croxon     HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ;
707530d68baSNigel Croxon     HwAddressSize -= sizeof( MAC-> Header ) ;
708530d68baSNigel Croxon     HwAddressSize -= sizeof( MAC-> IfType ) ;
709530d68baSNigel Croxon     if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
710530d68baSNigel Croxon         HwAddressSize = 6;
711530d68baSNigel Croxon     }
712530d68baSNigel Croxon 
713530d68baSNigel Croxon     CatPrint(Str, L"Mac(");
714530d68baSNigel Croxon 
715530d68baSNigel Croxon     for(Index = 0; Index < HwAddressSize; Index++) {
716530d68baSNigel Croxon         CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
717530d68baSNigel Croxon     }
718530d68baSNigel Croxon     if ( MAC-> IfType != 0 ) {
719530d68baSNigel Croxon         CatPrint(Str, L",%d" , MAC-> IfType ) ;
720530d68baSNigel Croxon     }
721530d68baSNigel Croxon     CatPrint(Str, L")");
722530d68baSNigel Croxon }
723530d68baSNigel Croxon 
724530d68baSNigel Croxon static VOID
CatPrintIPv4(IN OUT POOL_PRINT * Str,IN EFI_IPv4_ADDRESS * Address)725530d68baSNigel Croxon CatPrintIPv4(
726530d68baSNigel Croxon     IN OUT POOL_PRINT * Str ,
727530d68baSNigel Croxon     IN EFI_IPv4_ADDRESS * Address
728530d68baSNigel Croxon     )
729530d68baSNigel Croxon {
730530d68baSNigel Croxon     CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ,
731530d68baSNigel Croxon         Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ;
732530d68baSNigel Croxon }
733530d68baSNigel Croxon 
734530d68baSNigel Croxon static BOOLEAN
IsNotNullIPv4(IN EFI_IPv4_ADDRESS * Address)735530d68baSNigel Croxon IsNotNullIPv4(
736530d68baSNigel Croxon     IN EFI_IPv4_ADDRESS * Address
737530d68baSNigel Croxon     )
738530d68baSNigel Croxon {
739530d68baSNigel Croxon     UINT8 val ;
740530d68baSNigel Croxon     val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ;
741530d68baSNigel Croxon     val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ;
742530d68baSNigel Croxon     return val != 0 ;
743530d68baSNigel Croxon }
744530d68baSNigel Croxon 
745530d68baSNigel Croxon static VOID
CatPrintNetworkProtocol(IN OUT POOL_PRINT * Str,IN UINT16 Proto)746530d68baSNigel Croxon CatPrintNetworkProtocol(
747530d68baSNigel Croxon     IN OUT POOL_PRINT * Str ,
748530d68baSNigel Croxon     IN UINT16 Proto
749530d68baSNigel Croxon     )
750530d68baSNigel Croxon {
751530d68baSNigel Croxon     if ( Proto == 6 ) {
752530d68baSNigel Croxon         CatPrint( Str , L"TCP" ) ;
753530d68baSNigel Croxon     } else if ( Proto == 17 ) {
754530d68baSNigel Croxon         CatPrint( Str , L"UDP" ) ;
755530d68baSNigel Croxon     } else {
756530d68baSNigel Croxon         CatPrint( Str , L"%d" , Proto ) ;
757530d68baSNigel Croxon     }
758530d68baSNigel Croxon }
759530d68baSNigel Croxon 
760530d68baSNigel Croxon static VOID
_DevPathIPv4(IN OUT POOL_PRINT * Str,IN VOID * DevPath)761530d68baSNigel Croxon _DevPathIPv4 (
762530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
763530d68baSNigel Croxon     IN VOID                 *DevPath
764530d68baSNigel Croxon     )
765530d68baSNigel Croxon {
766530d68baSNigel Croxon     IPv4_DEVICE_PATH     *IP;
767530d68baSNigel Croxon     BOOLEAN show ;
768530d68baSNigel Croxon 
769530d68baSNigel Croxon     IP = DevPath;
770530d68baSNigel Croxon     CatPrint( Str , L"IPv4(") ;
771530d68baSNigel Croxon     CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ;
772530d68baSNigel Croxon     CatPrint( Str , L",") ;
773530d68baSNigel Croxon     CatPrintNetworkProtocol( Str , IP-> Protocol ) ;
774530d68baSNigel Croxon     CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ;
775530d68baSNigel Croxon     show = IsNotNullIPv4( & IP-> LocalIpAddress ) ;
776530d68baSNigel Croxon     if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
777530d68baSNigel Croxon         /* only version 2 includes gateway and netmask */
778530d68baSNigel Croxon         show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
779530d68baSNigel Croxon         show |= IsNotNullIPv4( & IP-> SubnetMask  ) ;
780530d68baSNigel Croxon     }
781530d68baSNigel Croxon     if ( show ) {
782530d68baSNigel Croxon         CatPrint( Str , L"," ) ;
783530d68baSNigel Croxon         CatPrintIPv4( Str , & IP-> LocalIpAddress ) ;
784530d68baSNigel Croxon         if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
785530d68baSNigel Croxon             /* only version 2 includes gateway and netmask */
786530d68baSNigel Croxon             show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
787530d68baSNigel Croxon             show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
788530d68baSNigel Croxon             if ( show ) {
789530d68baSNigel Croxon                 CatPrint( Str , L",") ;
790530d68baSNigel Croxon                 CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ;
791530d68baSNigel Croxon                 if ( IsNotNullIPv4( & IP-> SubnetMask ) ) {
792530d68baSNigel Croxon                     CatPrint( Str , L",") ;
793530d68baSNigel Croxon                     CatPrintIPv4( Str , & IP-> SubnetMask ) ;
794530d68baSNigel Croxon                 }
795530d68baSNigel Croxon             }
796530d68baSNigel Croxon         }
797530d68baSNigel Croxon     }
798530d68baSNigel Croxon     CatPrint( Str , L")") ;
799530d68baSNigel Croxon }
800530d68baSNigel Croxon 
801530d68baSNigel Croxon #define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) )
802530d68baSNigel Croxon static VOID
CatPrintIPv6(IN OUT POOL_PRINT * Str,IN EFI_IPv6_ADDRESS * Address)803530d68baSNigel Croxon CatPrintIPv6(
804530d68baSNigel Croxon     IN OUT POOL_PRINT * Str ,
805530d68baSNigel Croxon     IN EFI_IPv6_ADDRESS * Address
806530d68baSNigel Croxon     )
807530d68baSNigel Croxon {
808530d68baSNigel Croxon     CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" ,
809530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) ,
810530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ,
811530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) ,
812530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) ,
813530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) ,
814530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) ,
815530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) ,
816530d68baSNigel Croxon         CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ;
817530d68baSNigel Croxon }
818530d68baSNigel Croxon 
819530d68baSNigel Croxon static VOID
_DevPathIPv6(IN OUT POOL_PRINT * Str,IN VOID * DevPath)820530d68baSNigel Croxon _DevPathIPv6 (
821530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
822530d68baSNigel Croxon     IN VOID                 *DevPath
823530d68baSNigel Croxon     )
824530d68baSNigel Croxon {
825530d68baSNigel Croxon     IPv6_DEVICE_PATH     *IP;
826530d68baSNigel Croxon 
827530d68baSNigel Croxon     IP = DevPath;
828530d68baSNigel Croxon     CatPrint( Str , L"IPv6(") ;
829530d68baSNigel Croxon     CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ;
830530d68baSNigel Croxon     CatPrint( Str , L",") ;
831530d68baSNigel Croxon     CatPrintNetworkProtocol( Str, IP-> Protocol ) ;
832530d68baSNigel Croxon     CatPrint( Str , L",%s," , IP-> IPAddressOrigin ?
833530d68baSNigel Croxon         ( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" :
834530d68baSNigel Croxon         L"StatefulAutoConfigure" ) : L"Static" ) ;
835530d68baSNigel Croxon     CatPrintIPv6( Str , & IP-> LocalIpAddress ) ;
836530d68baSNigel Croxon     if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) {
837530d68baSNigel Croxon         CatPrint( Str , L",") ;
838530d68baSNigel Croxon         CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ;
839530d68baSNigel Croxon         CatPrint( Str , L",") ;
840530d68baSNigel Croxon         CatPrint( Str , L"%d" , & IP-> PrefixLength ) ;
841530d68baSNigel Croxon     }
842530d68baSNigel Croxon     CatPrint( Str , L")") ;
843530d68baSNigel Croxon }
844530d68baSNigel Croxon 
845530d68baSNigel Croxon static VOID
_DevPathUri(IN OUT POOL_PRINT * Str,IN VOID * DevPath)846ad7f0d4bSNigel Croxon _DevPathUri (
847ad7f0d4bSNigel Croxon     IN OUT POOL_PRINT       *Str,
848ad7f0d4bSNigel Croxon     IN VOID                 *DevPath
849ad7f0d4bSNigel Croxon     )
850ad7f0d4bSNigel Croxon {
851ad7f0d4bSNigel Croxon     URI_DEVICE_PATH  *Uri;
852ad7f0d4bSNigel Croxon 
853ad7f0d4bSNigel Croxon     Uri = DevPath;
854ad7f0d4bSNigel Croxon 
855ad7f0d4bSNigel Croxon     CatPrint( Str, L"Uri(%a)", Uri->Uri );
856ad7f0d4bSNigel Croxon }
857ad7f0d4bSNigel Croxon 
858ad7f0d4bSNigel Croxon static VOID
_DevPathInfiniBand(IN OUT POOL_PRINT * Str,IN VOID * DevPath)859530d68baSNigel Croxon _DevPathInfiniBand (
860530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
861530d68baSNigel Croxon     IN VOID                 *DevPath
862530d68baSNigel Croxon     )
863530d68baSNigel Croxon {
864530d68baSNigel Croxon     INFINIBAND_DEVICE_PATH  *InfiniBand;
865530d68baSNigel Croxon 
866530d68baSNigel Croxon     InfiniBand = DevPath;
867530d68baSNigel Croxon     CatPrint(Str, L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)",
868530d68baSNigel Croxon         InfiniBand->ResourceFlags, InfiniBand->PortGid, InfiniBand->ServiceId,
869530d68baSNigel Croxon         InfiniBand->TargetPortId, InfiniBand->DeviceId);
870530d68baSNigel Croxon }
871530d68baSNigel Croxon 
872530d68baSNigel Croxon static VOID
_DevPathUart(IN OUT POOL_PRINT * Str,IN VOID * DevPath)873530d68baSNigel Croxon _DevPathUart (
874530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
875530d68baSNigel Croxon     IN VOID                 *DevPath
876530d68baSNigel Croxon     )
877530d68baSNigel Croxon {
878530d68baSNigel Croxon     UART_DEVICE_PATH  *Uart;
879530d68baSNigel Croxon     CHAR8             Parity;
880530d68baSNigel Croxon 
881530d68baSNigel Croxon     Uart = DevPath;
882530d68baSNigel Croxon     switch (Uart->Parity) {
883530d68baSNigel Croxon         case 0  : Parity = 'D'; break;
884530d68baSNigel Croxon         case 1  : Parity = 'N'; break;
885530d68baSNigel Croxon         case 2  : Parity = 'E'; break;
886530d68baSNigel Croxon         case 3  : Parity = 'O'; break;
887530d68baSNigel Croxon         case 4  : Parity = 'M'; break;
888530d68baSNigel Croxon         case 5  : Parity = 'S'; break;
889530d68baSNigel Croxon         default : Parity = 'x'; break;
890530d68baSNigel Croxon     }
891530d68baSNigel Croxon 
892530d68baSNigel Croxon     if (Uart->BaudRate == 0) {
893d34132e6SNigel Croxon         CatPrint(Str, L"Uart(DEFAULT,");
894530d68baSNigel Croxon     } else {
895d34132e6SNigel Croxon         CatPrint(Str, L"Uart(%ld,", Uart->BaudRate);
896530d68baSNigel Croxon     }
897530d68baSNigel Croxon 
898530d68baSNigel Croxon     if (Uart->DataBits == 0) {
899d34132e6SNigel Croxon         CatPrint(Str, L"DEFAULT,");
900530d68baSNigel Croxon     } else {
901d34132e6SNigel Croxon         CatPrint(Str, L"%d,", Uart->DataBits);
902530d68baSNigel Croxon     }
903530d68baSNigel Croxon 
904d34132e6SNigel Croxon     CatPrint(Str, L"%c,", Parity);
905d34132e6SNigel Croxon 
906530d68baSNigel Croxon     switch (Uart->StopBits) {
907530d68baSNigel Croxon         case 0  : CatPrint(Str, L"D)");   break;
908530d68baSNigel Croxon         case 1  : CatPrint(Str, L"1)");   break;
909530d68baSNigel Croxon         case 2  : CatPrint(Str, L"1.5)"); break;
910530d68baSNigel Croxon         case 3  : CatPrint(Str, L"2)");   break;
911530d68baSNigel Croxon         default : CatPrint(Str, L"x)");   break;
912530d68baSNigel Croxon     }
913530d68baSNigel Croxon }
914530d68baSNigel Croxon 
915530d68baSNigel Croxon static VOID
_DevPathSata(IN OUT POOL_PRINT * Str,IN VOID * DevPath)916530d68baSNigel Croxon _DevPathSata (
917530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
918530d68baSNigel Croxon     IN VOID                 *DevPath
919530d68baSNigel Croxon     )
920530d68baSNigel Croxon {
921530d68baSNigel Croxon     SATA_DEVICE_PATH * Sata ;
922530d68baSNigel Croxon 
923530d68baSNigel Croxon     Sata = DevPath;
924530d68baSNigel Croxon     CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber ,
925530d68baSNigel Croxon         Sata-> PortMultiplierPortNumber , Sata-> Lun ) ;
926530d68baSNigel Croxon }
927530d68baSNigel Croxon 
928530d68baSNigel Croxon static VOID
_DevPathHardDrive(IN OUT POOL_PRINT * Str,IN VOID * DevPath)929530d68baSNigel Croxon _DevPathHardDrive (
930530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
931530d68baSNigel Croxon     IN VOID                 *DevPath
932530d68baSNigel Croxon     )
933530d68baSNigel Croxon {
934530d68baSNigel Croxon     HARDDRIVE_DEVICE_PATH   *Hd;
935530d68baSNigel Croxon 
936530d68baSNigel Croxon     Hd = DevPath;
937530d68baSNigel Croxon     switch (Hd->SignatureType) {
938530d68baSNigel Croxon         case SIGNATURE_TYPE_MBR:
939d34132e6SNigel Croxon             CatPrint(Str, L"HD(%d,MBR,0x%08x)",
940530d68baSNigel Croxon                 Hd->PartitionNumber,
941530d68baSNigel Croxon                 *((UINT32 *)(&(Hd->Signature[0])))
942530d68baSNigel Croxon                 );
943530d68baSNigel Croxon             break;
944530d68baSNigel Croxon         case SIGNATURE_TYPE_GUID:
945d34132e6SNigel Croxon             CatPrint(Str, L"HD(%d,GPT,%g)",
946530d68baSNigel Croxon                 Hd->PartitionNumber,
947530d68baSNigel Croxon                 (EFI_GUID *) &(Hd->Signature[0])
948530d68baSNigel Croxon                 );
949530d68baSNigel Croxon             break;
950530d68baSNigel Croxon         default:
951d34132e6SNigel Croxon             CatPrint(Str, L"HD(%d,%d,0)",
952530d68baSNigel Croxon                 Hd->PartitionNumber,
953530d68baSNigel Croxon                 Hd->SignatureType
954530d68baSNigel Croxon                 );
955530d68baSNigel Croxon             break;
956530d68baSNigel Croxon     }
957530d68baSNigel Croxon }
958530d68baSNigel Croxon 
959530d68baSNigel Croxon static VOID
_DevPathCDROM(IN OUT POOL_PRINT * Str,IN VOID * DevPath)960530d68baSNigel Croxon _DevPathCDROM (
961530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
962530d68baSNigel Croxon     IN VOID                 *DevPath
963530d68baSNigel Croxon     )
964530d68baSNigel Croxon {
965530d68baSNigel Croxon     CDROM_DEVICE_PATH       *Cd;
966530d68baSNigel Croxon 
967530d68baSNigel Croxon     Cd = DevPath;
968530d68baSNigel Croxon     CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ;
969530d68baSNigel Croxon }
970530d68baSNigel Croxon 
971530d68baSNigel Croxon static VOID
_DevPathFilePath(IN OUT POOL_PRINT * Str,IN VOID * DevPath)972530d68baSNigel Croxon _DevPathFilePath (
973530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
974530d68baSNigel Croxon     IN VOID                 *DevPath
975530d68baSNigel Croxon     )
976530d68baSNigel Croxon {
977530d68baSNigel Croxon     FILEPATH_DEVICE_PATH    *Fp;
978530d68baSNigel Croxon 
979530d68baSNigel Croxon     Fp = DevPath;
980530d68baSNigel Croxon     CatPrint(Str, L"%s", Fp->PathName);
981530d68baSNigel Croxon }
982530d68baSNigel Croxon 
983530d68baSNigel Croxon static VOID
_DevPathMediaProtocol(IN OUT POOL_PRINT * Str,IN VOID * DevPath)984530d68baSNigel Croxon _DevPathMediaProtocol (
985530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
986530d68baSNigel Croxon     IN VOID                 *DevPath
987530d68baSNigel Croxon     )
988530d68baSNigel Croxon {
989530d68baSNigel Croxon     MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;
990530d68baSNigel Croxon 
991530d68baSNigel Croxon     MediaProt = DevPath;
992530d68baSNigel Croxon     CatPrint(Str, L"%g", &MediaProt->Protocol);
993530d68baSNigel Croxon }
994530d68baSNigel Croxon 
995530d68baSNigel Croxon static VOID
_DevPathBssBss(IN OUT POOL_PRINT * Str,IN VOID * DevPath)996530d68baSNigel Croxon _DevPathBssBss (
997530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
998530d68baSNigel Croxon     IN VOID                 *DevPath
999530d68baSNigel Croxon     )
1000530d68baSNigel Croxon {
1001530d68baSNigel Croxon     BBS_BBS_DEVICE_PATH     *Bss;
1002530d68baSNigel Croxon     CHAR16                  *Type;
1003530d68baSNigel Croxon 
1004530d68baSNigel Croxon     Bss = DevPath;
1005530d68baSNigel Croxon     switch (Bss->DeviceType) {
1006530d68baSNigel Croxon     case BBS_TYPE_FLOPPY:               Type = L"Floppy";       break;
1007530d68baSNigel Croxon     case BBS_TYPE_HARDDRIVE:            Type = L"Harddrive";    break;
1008530d68baSNigel Croxon     case BBS_TYPE_CDROM:                Type = L"CDROM";        break;
1009530d68baSNigel Croxon     case BBS_TYPE_PCMCIA:               Type = L"PCMCIA";       break;
1010530d68baSNigel Croxon     case BBS_TYPE_USB:                  Type = L"Usb";          break;
1011530d68baSNigel Croxon     case BBS_TYPE_EMBEDDED_NETWORK:     Type = L"Net";          break;
1012530d68baSNigel Croxon     default:                            Type = L"?";            break;
1013530d68baSNigel Croxon     }
1014530d68baSNigel Croxon 
1015530d68baSNigel Croxon     CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
1016530d68baSNigel Croxon }
1017530d68baSNigel Croxon 
1018530d68baSNigel Croxon 
1019530d68baSNigel Croxon static VOID
_DevPathEndInstance(IN OUT POOL_PRINT * Str,IN VOID * DevPath EFI_UNUSED)1020530d68baSNigel Croxon _DevPathEndInstance (
1021530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
10225ff74ecaSNigel Croxon     IN VOID                 *DevPath EFI_UNUSED
1023530d68baSNigel Croxon     )
1024530d68baSNigel Croxon {
1025530d68baSNigel Croxon     CatPrint(Str, L",");
1026530d68baSNigel Croxon }
1027530d68baSNigel Croxon 
1028530d68baSNigel Croxon /**
1029530d68baSNigel Croxon  * Print unknown device node.
1030530d68baSNigel Croxon  * UEFI 2.4 § 9.6.1.6 table 89.
1031530d68baSNigel Croxon  */
1032530d68baSNigel Croxon 
1033530d68baSNigel Croxon static VOID
_DevPathNodeUnknown(IN OUT POOL_PRINT * Str,IN VOID * DevPath)1034530d68baSNigel Croxon _DevPathNodeUnknown (
1035530d68baSNigel Croxon     IN OUT POOL_PRINT       *Str,
1036530d68baSNigel Croxon     IN VOID                 *DevPath
1037530d68baSNigel Croxon     )
1038530d68baSNigel Croxon {
1039530d68baSNigel Croxon     EFI_DEVICE_PATH * Path ;
1040530d68baSNigel Croxon     UINT8 * value ;
1041530d68baSNigel Croxon     int length , index ;
1042530d68baSNigel Croxon     Path = DevPath ;
1043530d68baSNigel Croxon     value = DevPath ;
1044530d68baSNigel Croxon     value += 4 ;
1045530d68baSNigel Croxon     switch ( Path-> Type ) {
1046530d68baSNigel Croxon         case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */
1047530d68baSNigel Croxon             CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ;
1048530d68baSNigel Croxon             break ;
1049530d68baSNigel Croxon         }
1050530d68baSNigel Croxon         case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */
1051530d68baSNigel Croxon             CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ;
1052530d68baSNigel Croxon             break ;
1053530d68baSNigel Croxon         }
1054530d68baSNigel Croxon         case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */
1055530d68baSNigel Croxon             CatPrint( Str , L"Msg(%d" , Path-> SubType ) ;
1056530d68baSNigel Croxon             break ;
1057530d68baSNigel Croxon         }
1058530d68baSNigel Croxon         case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */
1059530d68baSNigel Croxon             CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ;
1060530d68baSNigel Croxon             break ;
1061530d68baSNigel Croxon         }
1062530d68baSNigel Croxon         case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */
1063530d68baSNigel Croxon             CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ;
1064530d68baSNigel Croxon             break ;
1065530d68baSNigel Croxon         }
1066530d68baSNigel Croxon         default : { /* Unknown Device Path */
1067530d68baSNigel Croxon             CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ;
1068530d68baSNigel Croxon             break ;
1069530d68baSNigel Croxon         }
1070530d68baSNigel Croxon     }
1071530d68baSNigel Croxon     length = DevicePathNodeLength( Path ) ;
1072530d68baSNigel Croxon     for ( index = 0 ; index < length ; index ++ ) {
1073530d68baSNigel Croxon         if ( index == 0 ) CatPrint( Str , L",0x" ) ;
1074530d68baSNigel Croxon         CatPrint( Str , L"%02x" , * value ) ;
1075530d68baSNigel Croxon 	value ++ ;
1076530d68baSNigel Croxon     }
1077530d68baSNigel Croxon     CatPrint( Str , L")" ) ;
1078530d68baSNigel Croxon }
1079530d68baSNigel Croxon 
1080530d68baSNigel Croxon 
1081530d68baSNigel Croxon /*
1082530d68baSNigel Croxon  * Table to convert "Type" and "SubType" to a "convert to text" function/
1083530d68baSNigel Croxon  * Entries hold "Type" and "SubType" for know values.
1084530d68baSNigel Croxon  * Special "SubType" 0 is used as default for known type with unknown subtype.
1085530d68baSNigel Croxon  */
1086*99730f29SCallum Farmer typedef struct {
1087530d68baSNigel Croxon     UINT8   Type;
1088530d68baSNigel Croxon     UINT8   SubType;
1089530d68baSNigel Croxon     VOID    (*Function)(POOL_PRINT *, VOID *);
1090*99730f29SCallum Farmer } DevPathTable_Type;
1091*99730f29SCallum Farmer DevPathTable_Type DevPathTable[] = {
1092530d68baSNigel Croxon 	{ HARDWARE_DEVICE_PATH,   HW_PCI_DP,                        _DevPathPci},
1093530d68baSNigel Croxon 	{ HARDWARE_DEVICE_PATH,   HW_PCCARD_DP,                     _DevPathPccard},
1094530d68baSNigel Croxon 	{ HARDWARE_DEVICE_PATH,   HW_MEMMAP_DP,                     _DevPathMemMap},
1095530d68baSNigel Croxon 	{ HARDWARE_DEVICE_PATH,   HW_VENDOR_DP,                     _DevPathVendor},
1096530d68baSNigel Croxon 	{ HARDWARE_DEVICE_PATH,   HW_CONTROLLER_DP,                 _DevPathController},
1097530d68baSNigel Croxon 	{ ACPI_DEVICE_PATH,       ACPI_DP,                          _DevPathAcpi},
1098530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_ATAPI_DP,                     _DevPathAtapi},
1099530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_SCSI_DP,                      _DevPathScsi},
1100530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_FIBRECHANNEL_DP,              _DevPathFibre},
1101530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_1394_DP,                      _DevPath1394},
1102530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_USB_DP,                       _DevPathUsb},
1103530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_I2O_DP,                       _DevPathI2O},
1104530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_MAC_ADDR_DP,                  _DevPathMacAddr},
1105530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_IPv4_DP,                      _DevPathIPv4},
1106530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_IPv6_DP,                      _DevPathIPv6},
1107ad7f0d4bSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_URI_DP,                       _DevPathUri},
1108530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_INFINIBAND_DP,                _DevPathInfiniBand},
1109530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_UART_DP,                      _DevPathUart},
1110530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH , MSG_SATA_DP ,                     _DevPathSata } ,
1111530d68baSNigel Croxon 	{ MESSAGING_DEVICE_PATH,  MSG_VENDOR_DP,                    _DevPathVendor},
1112530d68baSNigel Croxon 	{ MEDIA_DEVICE_PATH,      MEDIA_HARDDRIVE_DP,               _DevPathHardDrive},
1113530d68baSNigel Croxon 	{ MEDIA_DEVICE_PATH,      MEDIA_CDROM_DP,                   _DevPathCDROM},
1114530d68baSNigel Croxon 	{ MEDIA_DEVICE_PATH,      MEDIA_VENDOR_DP,                  _DevPathVendor},
1115530d68baSNigel Croxon 	{ MEDIA_DEVICE_PATH,      MEDIA_FILEPATH_DP,                _DevPathFilePath},
1116530d68baSNigel Croxon 	{ MEDIA_DEVICE_PATH,      MEDIA_PROTOCOL_DP,                _DevPathMediaProtocol},
1117530d68baSNigel Croxon 	{ BBS_DEVICE_PATH,        BBS_BBS_DP,                       _DevPathBssBss},
1118530d68baSNigel Croxon 	{ END_DEVICE_PATH_TYPE,   END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
1119530d68baSNigel Croxon 	{ 0,                      0,                          NULL}
1120530d68baSNigel Croxon };
1121530d68baSNigel Croxon 
1122530d68baSNigel Croxon 
1123530d68baSNigel Croxon CHAR16 *
DevicePathToStr(EFI_DEVICE_PATH * DevPath)1124530d68baSNigel Croxon DevicePathToStr (
1125530d68baSNigel Croxon     EFI_DEVICE_PATH     *DevPath
1126530d68baSNigel Croxon     )
1127530d68baSNigel Croxon /*++
1128530d68baSNigel Croxon 
1129530d68baSNigel Croxon     Turns the Device Path into a printable string.  Allcoates
1130530d68baSNigel Croxon     the string from pool.  The caller must FreePool the returned
1131530d68baSNigel Croxon     string.
1132530d68baSNigel Croxon 
1133530d68baSNigel Croxon --*/
1134530d68baSNigel Croxon {
1135530d68baSNigel Croxon     POOL_PRINT          Str;
1136530d68baSNigel Croxon     EFI_DEVICE_PATH     *DevPathNode;
1137530d68baSNigel Croxon     VOID                (*DumpNode)(POOL_PRINT *, VOID *);
1138530d68baSNigel Croxon     UINTN               Index, NewSize;
1139530d68baSNigel Croxon 
1140530d68baSNigel Croxon     ZeroMem(&Str, sizeof(Str));
1141530d68baSNigel Croxon 
1142530d68baSNigel Croxon     //
1143530d68baSNigel Croxon     // Unpacked the device path
1144530d68baSNigel Croxon     //
1145530d68baSNigel Croxon 
1146530d68baSNigel Croxon     DevPath = UnpackDevicePath(DevPath);
1147530d68baSNigel Croxon     ASSERT (DevPath);
1148530d68baSNigel Croxon 
1149530d68baSNigel Croxon 
1150530d68baSNigel Croxon     //
1151530d68baSNigel Croxon     // Process each device path node
1152530d68baSNigel Croxon     //
1153530d68baSNigel Croxon 
1154530d68baSNigel Croxon     DevPathNode = DevPath;
1155530d68baSNigel Croxon     while (!IsDevicePathEnd(DevPathNode)) {
1156530d68baSNigel Croxon         //
1157530d68baSNigel Croxon         // Find the handler to dump this device path node
1158530d68baSNigel Croxon         //
1159530d68baSNigel Croxon 
1160530d68baSNigel Croxon         DumpNode = NULL;
1161530d68baSNigel Croxon         for (Index = 0; DevPathTable[Index].Function; Index += 1) {
1162530d68baSNigel Croxon 
1163530d68baSNigel Croxon             if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
1164530d68baSNigel Croxon                 DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
1165530d68baSNigel Croxon                 DumpNode = DevPathTable[Index].Function;
1166530d68baSNigel Croxon                 break;
1167530d68baSNigel Croxon             }
1168530d68baSNigel Croxon         }
1169530d68baSNigel Croxon 
1170530d68baSNigel Croxon         //
1171530d68baSNigel Croxon         // If not found, use a generic function
1172530d68baSNigel Croxon         //
1173530d68baSNigel Croxon 
1174530d68baSNigel Croxon         if (!DumpNode) {
1175530d68baSNigel Croxon             DumpNode = _DevPathNodeUnknown;
1176530d68baSNigel Croxon         }
1177530d68baSNigel Croxon 
1178530d68baSNigel Croxon         //
1179530d68baSNigel Croxon         //  Put a path seperator in if needed
1180530d68baSNigel Croxon         //
1181530d68baSNigel Croxon 
1182530d68baSNigel Croxon         if (Str.len  &&  DumpNode != _DevPathEndInstance) {
1183530d68baSNigel Croxon             CatPrint (&Str, L"/");
1184530d68baSNigel Croxon         }
1185530d68baSNigel Croxon 
1186530d68baSNigel Croxon         //
1187530d68baSNigel Croxon         // Print this node of the device path
1188530d68baSNigel Croxon         //
1189530d68baSNigel Croxon 
1190530d68baSNigel Croxon         DumpNode (&Str, DevPathNode);
1191530d68baSNigel Croxon 
1192530d68baSNigel Croxon         //
1193530d68baSNigel Croxon         // Next device path node
1194530d68baSNigel Croxon         //
1195530d68baSNigel Croxon 
1196530d68baSNigel Croxon         DevPathNode = NextDevicePathNode(DevPathNode);
1197530d68baSNigel Croxon     }
1198530d68baSNigel Croxon 
1199530d68baSNigel Croxon     //
1200530d68baSNigel Croxon     // Shrink pool used for string allocation
1201530d68baSNigel Croxon     //
1202530d68baSNigel Croxon 
1203530d68baSNigel Croxon     FreePool (DevPath);
1204530d68baSNigel Croxon     NewSize = (Str.len + 1) * sizeof(CHAR16);
1205530d68baSNigel Croxon     Str.str = ReallocatePool (Str.str, NewSize, NewSize);
1206530d68baSNigel Croxon     Str.str[Str.len] = 0;
1207530d68baSNigel Croxon     return Str.str;
1208530d68baSNigel Croxon }
1209530d68baSNigel Croxon 
1210530d68baSNigel Croxon BOOLEAN
LibMatchDevicePaths(IN EFI_DEVICE_PATH * Multi,IN EFI_DEVICE_PATH * Single)1211530d68baSNigel Croxon LibMatchDevicePaths (
1212530d68baSNigel Croxon     IN  EFI_DEVICE_PATH *Multi,
1213530d68baSNigel Croxon     IN  EFI_DEVICE_PATH *Single
1214530d68baSNigel Croxon     )
1215530d68baSNigel Croxon {
1216530d68baSNigel Croxon     EFI_DEVICE_PATH     *DevicePath, *DevicePathInst;
1217530d68baSNigel Croxon     UINTN               Size;
1218530d68baSNigel Croxon 
1219530d68baSNigel Croxon     if (!Multi || !Single) {
1220530d68baSNigel Croxon         return FALSE;
1221530d68baSNigel Croxon     }
1222530d68baSNigel Croxon 
1223530d68baSNigel Croxon     DevicePath = Multi;
1224530d68baSNigel Croxon     while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
1225530d68baSNigel Croxon         if (CompareMem (Single, DevicePathInst, Size) == 0) {
1226530d68baSNigel Croxon             return TRUE;
1227530d68baSNigel Croxon         }
1228530d68baSNigel Croxon     }
1229530d68baSNigel Croxon     return FALSE;
1230530d68baSNigel Croxon }
1231530d68baSNigel Croxon 
1232530d68baSNigel Croxon EFI_DEVICE_PATH *
LibDuplicateDevicePathInstance(IN EFI_DEVICE_PATH * DevPath)1233530d68baSNigel Croxon LibDuplicateDevicePathInstance (
1234530d68baSNigel Croxon     IN EFI_DEVICE_PATH  *DevPath
1235530d68baSNigel Croxon     )
1236530d68baSNigel Croxon {
1237530d68baSNigel Croxon     EFI_DEVICE_PATH     *NewDevPath,*DevicePathInst,*Temp;
1238530d68baSNigel Croxon     UINTN               Size = 0;
1239530d68baSNigel Croxon 
1240530d68baSNigel Croxon     //
1241530d68baSNigel Croxon     // get the size of an instance from the input
1242530d68baSNigel Croxon     //
1243530d68baSNigel Croxon 
1244530d68baSNigel Croxon     Temp = DevPath;
1245530d68baSNigel Croxon     DevicePathInst = DevicePathInstance (&Temp, &Size);
1246530d68baSNigel Croxon 
1247530d68baSNigel Croxon     //
1248530d68baSNigel Croxon     // Make a copy and set proper end type
1249530d68baSNigel Croxon     //
1250530d68baSNigel Croxon     NewDevPath = NULL;
1251530d68baSNigel Croxon     if (Size) {
1252530d68baSNigel Croxon         NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
1253530d68baSNigel Croxon     }
1254530d68baSNigel Croxon 
1255530d68baSNigel Croxon     if (NewDevPath) {
1256530d68baSNigel Croxon         CopyMem (NewDevPath, DevicePathInst, Size);
1257530d68baSNigel Croxon         Temp = NextDevicePathNode(NewDevPath);
1258530d68baSNigel Croxon         SetDevicePathEndNode(Temp);
1259530d68baSNigel Croxon     }
1260530d68baSNigel Croxon 
1261530d68baSNigel Croxon     return NewDevPath;
1262530d68baSNigel Croxon }
1263530d68baSNigel Croxon 
1264