newline added at end
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Library / EdkGenericBdsLib / DevicePath.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   DevicePath.c\r
15 \r
16 Abstract:\r
17 \r
18   BDS internal function define the default device path string, it can be\r
19   replaced by platform device path.\r
20 \r
21 --*/\r
22 \r
23 \r
24 #ifdef TIANO_EXTENSION_FLAG\r
25 EFI_GUID  UnknownDeviceGuid           = UNKNOWN_DEVICE_GUID;\r
26 #endif \r
27 \r
28 EFI_GUID  mEfiUnixThunkProtocolGuid  = EFI_UNIX_THUNK_PROTOCOL_GUID;\r
29 EFI_GUID  mEfiUnixUgaGuid            = EFI_UNIX_UGA_GUID;\r
30 EFI_GUID  mEfiMsgPcAnsiGuid           = DEVICE_PATH_MESSAGING_PC_ANSI;\r
31 EFI_GUID  mEfiMsgVt100Guid            = DEVICE_PATH_MESSAGING_VT_100;\r
32 EFI_GUID  mEfiMsgVt100PlusGuid        = DEVICE_PATH_MESSAGING_VT_100_PLUS;\r
33 EFI_GUID  mEfiMsgVt100Utf8Guid        = DEVICE_PATH_MESSAGING_VT_UTF8;\r
34 \r
35 VOID *\r
36 ReallocatePool (\r
37   IN VOID                 *OldPool,\r
38   IN UINTN                OldSize,\r
39   IN UINTN                NewSize\r
40   )\r
41 /*++\r
42 \r
43 Routine Description:\r
44 \r
45   Adjusts the size of a previously allocated buffer.\r
46 \r
47 Arguments:\r
48 \r
49   OldPool               - A pointer to the buffer whose size is being adjusted.\r
50 \r
51   OldSize               - The size of the current buffer.\r
52 \r
53   NewSize               - The size of the new buffer.\r
54 \r
55 Returns:\r
56 \r
57   EFI_SUCEESS           - The requested number of bytes were allocated.\r
58 \r
59   EFI_OUT_OF_RESOURCES  - The pool requested could not be allocated.\r
60 \r
61   EFI_INVALID_PARAMETER - The buffer was invalid.\r
62 \r
63 --*/\r
64 {\r
65   VOID  *NewPool;\r
66 \r
67   NewPool = NULL;\r
68   if (NewSize) {\r
69     NewPool = AllocateZeroPool (NewSize);\r
70   }\r
71 \r
72   if (OldPool) {\r
73     if (NewPool) {\r
74       CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
75     }\r
76 \r
77     gBS->FreePool (OldPool);\r
78   }\r
79 \r
80   return NewPool;\r
81 }\r
82 \r
83 CHAR16 *\r
84 CatPrint (\r
85   IN OUT POOL_PRINT   *Str,\r
86   IN CHAR16           *fmt,\r
87   ...\r
88   )\r
89 /*++\r
90 \r
91 Routine Description:\r
92 \r
93     Concatenates a formatted unicode string to allocated pool.  \r
94     The caller must free the resulting buffer.\r
95 \r
96 Arguments:\r
97 \r
98     Str         - Tracks the allocated pool, size in use, and \r
99                   amount of pool allocated.\r
100 \r
101     fmt         - The format string\r
102 \r
103 Returns:\r
104 \r
105     Allocated buffer with the formatted string printed in it.  \r
106     The caller must free the allocated buffer.   The buffer\r
107     allocation is not packed.\r
108 \r
109 --*/\r
110 {\r
111   UINT16  *AppendStr;\r
112   VA_LIST args;\r
113   UINTN   strsize;\r
114 \r
115   AppendStr = AllocateZeroPool (0x1000);\r
116   if (AppendStr == NULL) {\r
117     return Str->str;\r
118   }\r
119 \r
120   VA_START (args, fmt);\r
121   UnicodeVSPrint (AppendStr, 0x1000, fmt, args);\r
122   VA_END (args);\r
123   if (NULL == Str->str) {\r
124     strsize   = StrSize (AppendStr);\r
125     Str->str  = AllocateZeroPool (strsize);\r
126     ASSERT (Str->str != NULL);\r
127   } else {\r
128     strsize = StrSize (AppendStr) + StrSize (Str->str) - sizeof (UINT16);\r
129     Str->str = ReallocatePool (\r
130                 Str->str,\r
131                 StrSize (Str->str),\r
132                 strsize\r
133                 );\r
134     ASSERT (Str->str != NULL);\r
135   }\r
136 \r
137   Str->maxlen = MAX_CHAR * sizeof (UINT16);\r
138   if (strsize < Str->maxlen) {\r
139     StrCat (Str->str, AppendStr);\r
140     Str->len = strsize - sizeof (UINT16);\r
141   }\r
142 \r
143   gBS->FreePool (AppendStr);\r
144   return Str->str;\r
145 }\r
146 \r
147 EFI_DEVICE_PATH_PROTOCOL *\r
148 BdsLibUnpackDevicePath (\r
149   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
150   )\r
151 /*++\r
152 \r
153 Routine Description:\r
154 \r
155   Function unpacks a device path data structure so that all the nodes\r
156   of a device path are naturally aligned.\r
157 \r
158 Arguments:\r
159 \r
160   DevPath        - A pointer to a device path data structure\r
161 \r
162 Returns:\r
163 \r
164   If the memory for the device path is successfully allocated, then a \r
165   pointer to the new device path is returned.  Otherwise, NULL is returned.\r
166 \r
167 --*/\r
168 {\r
169   EFI_DEVICE_PATH_PROTOCOL  *Src;\r
170   EFI_DEVICE_PATH_PROTOCOL  *Dest;\r
171   EFI_DEVICE_PATH_PROTOCOL  *NewPath;\r
172   UINTN                     Size;\r
173 \r
174   //\r
175   // Walk device path and round sizes to valid boundries\r
176   //\r
177   Src   = DevPath;\r
178   Size  = 0;\r
179   for (;;) {\r
180     Size += DevicePathNodeLength (Src);\r
181     Size += ALIGN_SIZE (Size);\r
182 \r
183     if (IsDevicePathEnd (Src)) {\r
184       break;\r
185     }\r
186 \r
187     Src = NextDevicePathNode (Src);\r
188   }\r
189   //\r
190   // Allocate space for the unpacked path\r
191   //\r
192   NewPath = AllocateZeroPool (Size);\r
193   if (NewPath) {\r
194 \r
195     ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
196 \r
197     //\r
198     // Copy each node\r
199     //\r
200     Src   = DevPath;\r
201     Dest  = NewPath;\r
202     for (;;) {\r
203       Size = DevicePathNodeLength (Src);\r
204       CopyMem (Dest, Src, Size);\r
205       Size += ALIGN_SIZE (Size);\r
206       SetDevicePathNodeLength (Dest, Size);\r
207       Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
208       Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
209 \r
210       if (IsDevicePathEnd (Src)) {\r
211         break;\r
212       }\r
213 \r
214       Src = NextDevicePathNode (Src);\r
215     }\r
216   }\r
217 \r
218   return NewPath;\r
219 }\r
220 \r
221 VOID\r
222 DevPathPci (\r
223   IN OUT POOL_PRINT       *Str,\r
224   IN VOID                 *DevPath\r
225   )\r
226 {\r
227   PCI_DEVICE_PATH *Pci;\r
228 \r
229   Pci = DevPath;\r
230   CatPrint (Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);\r
231 }\r
232 \r
233 VOID\r
234 DevPathPccard (\r
235   IN OUT POOL_PRINT       *Str,\r
236   IN VOID                 *DevPath\r
237   )\r
238 {\r
239   PCCARD_DEVICE_PATH  *Pccard;\r
240 \r
241   Pccard = DevPath;\r
242   CatPrint (Str, L"Pcmcia(Function%x)", Pccard->FunctionNumber);\r
243 }\r
244 \r
245 VOID\r
246 DevPathMemMap (\r
247   IN OUT POOL_PRINT       *Str,\r
248   IN VOID                 *DevPath\r
249   )\r
250 {\r
251   MEMMAP_DEVICE_PATH  *MemMap;\r
252 \r
253   MemMap = DevPath;\r
254   CatPrint (\r
255     Str,\r
256     L"MemMap(%d:%.lx-%.lx)",\r
257     MemMap->MemoryType,\r
258     MemMap->StartingAddress,\r
259     MemMap->EndingAddress\r
260     );\r
261 }\r
262 \r
263 VOID\r
264 DevPathController (\r
265   IN OUT POOL_PRINT       *Str,\r
266   IN VOID                 *DevPath\r
267   )\r
268 {\r
269   CONTROLLER_DEVICE_PATH  *Controller;\r
270 \r
271   Controller = DevPath;\r
272   CatPrint (Str, L"Ctrl(%d)", Controller->ControllerNumber);\r
273 }\r
274 \r
275 VOID\r
276 DevPathVendor (\r
277   IN OUT POOL_PRINT       *Str,\r
278   IN VOID                 *DevPath\r
279   )\r
280 /*++\r
281 \r
282 Routine Description:\r
283 \r
284   Convert Vendor device path to device name\r
285 \r
286 Arguments:\r
287 \r
288   Str     - The buffer store device name\r
289   DevPath - Pointer to vendor device path\r
290 \r
291 Returns:\r
292 \r
293   When it return, the device name have been stored in *Str.\r
294 \r
295 --*/\r
296 {\r
297   VENDOR_DEVICE_PATH  *Vendor;\r
298   CHAR16              *Type;\r
299   INT32               *Temp;\r
300 \r
301   Vendor  = DevPath;\r
302   Temp    = (INT32 *) (&Vendor->Guid);\r
303 \r
304   switch (DevicePathType (&Vendor->Header)) {\r
305   case HARDWARE_DEVICE_PATH:\r
306     //\r
307     // If the device is an Unix device, we will give it a readable device name.\r
308     //\r
309     if (CompareGuid (&Vendor->Guid, &mEfiUnixThunkProtocolGuid)) {\r
310       CatPrint (Str, L"%s", L"UnixBus");\r
311       return ;\r
312     } else if (CompareGuid (&Vendor->Guid, &mEfiUnixUgaGuid)) {\r
313       CatPrint (Str, L"%s", L"UGA");\r
314       return ;\r
315     } else {\r
316       Type = L"Hw";\r
317       break;\r
318     }\r
319 \r
320   case MESSAGING_DEVICE_PATH:\r
321     //\r
322     // If the device is an Unix device, we will give it a readable device name.\r
323     //\r
324     if (CompareGuid (&Vendor->Guid, &mEfiMsgPcAnsiGuid)) {\r
325       CatPrint (Str, L"%s", L"PC-ANSI");\r
326       return ;\r
327     } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Guid)) {\r
328       CatPrint (Str, L"%s", L"VT100");\r
329       return ;\r
330     } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100PlusGuid)) {\r
331       CatPrint (Str, L"%s", L"VT100+");\r
332       return ;\r
333     } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Utf8Guid)) {\r
334       CatPrint (Str, L"%s", L"VT100-UTF8");\r
335       return ;\r
336     } else {\r
337       Type = L"Msg";\r
338       break;\r
339     }\r
340 \r
341   case MEDIA_DEVICE_PATH:\r
342     Type = L"Media";\r
343     break;\r
344 \r
345   default:\r
346     Type = L"?";\r
347     break;\r
348   }\r
349 \r
350   CatPrint (Str, L"Ven%s(%g)", Type, &Vendor->Guid);\r
351 }\r
352 \r
353 VOID\r
354 DevPathAcpi (\r
355   IN OUT POOL_PRINT       *Str,\r
356   IN VOID                 *DevPath\r
357   )\r
358 {\r
359   ACPI_HID_DEVICE_PATH  *Acpi;\r
360 \r
361   Acpi = DevPath;\r
362   if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
363     CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);\r
364   } else {\r
365     CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);\r
366   }\r
367 }\r
368 \r
369 VOID\r
370 DevPathAtapi (\r
371   IN OUT POOL_PRINT       *Str,\r
372   IN VOID                 *DevPath\r
373   )\r
374 {\r
375   ATAPI_DEVICE_PATH *Atapi;\r
376 \r
377   Atapi = DevPath;\r
378   CatPrint (\r
379     Str,\r
380     L"Ata(%s,%s)",\r
381     Atapi->PrimarySecondary ? L"Secondary" : L"Primary",\r
382     Atapi->SlaveMaster ? L"Slave" : L"Master"\r
383     );\r
384 }\r
385 \r
386 VOID\r
387 DevPathScsi (\r
388   IN OUT POOL_PRINT       *Str,\r
389   IN VOID                 *DevPath\r
390   )\r
391 {\r
392   SCSI_DEVICE_PATH  *Scsi;\r
393 \r
394   Scsi = DevPath;\r
395   CatPrint (Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);\r
396 }\r
397 \r
398 VOID\r
399 DevPathFibre (\r
400   IN OUT POOL_PRINT       *Str,\r
401   IN VOID                 *DevPath\r
402   )\r
403 {\r
404   FIBRECHANNEL_DEVICE_PATH  *Fibre;\r
405 \r
406   Fibre = DevPath;\r
407   CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
408 }\r
409 \r
410 VOID\r
411 DevPath1394 (\r
412   IN OUT POOL_PRINT       *Str,\r
413   IN VOID                 *DevPath\r
414   )\r
415 {\r
416   F1394_DEVICE_PATH *F1394;\r
417 \r
418   F1394 = DevPath;\r
419   CatPrint (Str, L"1394(%g)", &F1394->Guid);\r
420 }\r
421 \r
422 VOID\r
423 DevPathUsb (\r
424   IN OUT POOL_PRINT       *Str,\r
425   IN VOID                 *DevPath\r
426   )\r
427 {\r
428   USB_DEVICE_PATH *Usb;\r
429 \r
430   Usb = DevPath;\r
431   CatPrint (Str, L"Usb(%x, %x)", Usb->ParentPortNumber, Usb->InterfaceNumber);\r
432 }\r
433 \r
434 VOID\r
435 DevPathUsbClass (\r
436   IN OUT POOL_PRINT       *Str,\r
437   IN VOID                 *DevPath\r
438   )\r
439 {\r
440   USB_CLASS_DEVICE_PATH *UsbClass;\r
441 \r
442   UsbClass = DevPath;\r
443   CatPrint (\r
444     Str,\r
445     L"Usb Class(%x, %x, %x, %x, %x)",\r
446     UsbClass->VendorId,\r
447     UsbClass->ProductId,\r
448     UsbClass->DeviceClass,\r
449     UsbClass->DeviceSubClass,\r
450     UsbClass->DeviceProtocol\r
451     );\r
452 }\r
453 \r
454 VOID\r
455 DevPathI2O (\r
456   IN OUT POOL_PRINT       *Str,\r
457   IN VOID                 *DevPath\r
458   )\r
459 {\r
460   I2O_DEVICE_PATH *I2O;\r
461 \r
462   I2O = DevPath;\r
463   CatPrint (Str, L"I2O(%x)", I2O->Tid);\r
464 }\r
465 \r
466 VOID\r
467 DevPathMacAddr (\r
468   IN OUT POOL_PRINT       *Str,\r
469   IN VOID                 *DevPath\r
470   )\r
471 {\r
472   MAC_ADDR_DEVICE_PATH  *MAC;\r
473   UINTN                 HwAddressSize;\r
474   UINTN                 Index;\r
475 \r
476   MAC           = DevPath;\r
477 \r
478   HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
479   if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {\r
480     HwAddressSize = 6;\r
481   }\r
482 \r
483   CatPrint (Str, L"Mac(");\r
484 \r
485   for (Index = 0; Index < HwAddressSize; Index++) {\r
486     CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]);\r
487   }\r
488 \r
489   CatPrint (Str, L")");\r
490 }\r
491 \r
492 VOID\r
493 DevPathIPv4 (\r
494   IN OUT POOL_PRINT       *Str,\r
495   IN VOID                 *DevPath\r
496   )\r
497 {\r
498   IPv4_DEVICE_PATH  *IP;\r
499 \r
500   IP = DevPath;\r
501   CatPrint (\r
502     Str,\r
503     L"IPv4(%d.%d.%d.%d:%d)",\r
504     IP->RemoteIpAddress.Addr[0],\r
505     IP->RemoteIpAddress.Addr[1],\r
506     IP->RemoteIpAddress.Addr[2],\r
507     IP->RemoteIpAddress.Addr[3],\r
508     IP->RemotePort\r
509     );\r
510 }\r
511 \r
512 VOID\r
513 DevPathIPv6 (\r
514   IN OUT POOL_PRINT       *Str,\r
515   IN VOID                 *DevPath\r
516   )\r
517 {\r
518   IPv6_DEVICE_PATH  *IP;\r
519 \r
520   IP = DevPath;\r
521   CatPrint (Str, L"IP-v6(not-done)");\r
522 }\r
523 \r
524 VOID\r
525 DevPathInfiniBand (\r
526   IN OUT POOL_PRINT       *Str,\r
527   IN VOID                 *DevPath\r
528   )\r
529 {\r
530   INFINIBAND_DEVICE_PATH  *InfiniBand;\r
531 \r
532   InfiniBand = DevPath;\r
533   CatPrint (Str, L"InfiniBand(not-done)");\r
534 }\r
535 \r
536 VOID\r
537 DevPathUart (\r
538   IN OUT POOL_PRINT       *Str,\r
539   IN VOID                 *DevPath\r
540   )\r
541 {\r
542   UART_DEVICE_PATH  *Uart;\r
543   CHAR8             Parity;\r
544 \r
545   Uart = DevPath;\r
546   switch (Uart->Parity) {\r
547   case 0:\r
548     Parity = 'D';\r
549     break;\r
550 \r
551   case 1:\r
552     Parity = 'N';\r
553     break;\r
554 \r
555   case 2:\r
556     Parity = 'E';\r
557     break;\r
558 \r
559   case 3:\r
560     Parity = 'O';\r
561     break;\r
562 \r
563   case 4:\r
564     Parity = 'M';\r
565     break;\r
566 \r
567   case 5:\r
568     Parity = 'S';\r
569     break;\r
570 \r
571   default:\r
572     Parity = 'x';\r
573     break;\r
574   }\r
575 \r
576   if (Uart->BaudRate == 0) {\r
577     CatPrint (Str, L"Uart(DEFAULT %c", Parity);\r
578   } else {\r
579     CatPrint (Str, L"Uart(%d %c", Uart->BaudRate, Parity);\r
580   }\r
581 \r
582   if (Uart->DataBits == 0) {\r
583     CatPrint (Str, L"D");\r
584   } else {\r
585     CatPrint (Str, L"%d", Uart->DataBits);\r
586   }\r
587 \r
588   switch (Uart->StopBits) {\r
589   case 0:\r
590     CatPrint (Str, L"D)");\r
591     break;\r
592 \r
593   case 1:\r
594     CatPrint (Str, L"1)");\r
595     break;\r
596 \r
597   case 2:\r
598     CatPrint (Str, L"1.5)");\r
599     break;\r
600 \r
601   case 3:\r
602     CatPrint (Str, L"2)");\r
603     break;\r
604 \r
605   default:\r
606     CatPrint (Str, L"x)");\r
607     break;\r
608   }\r
609 }\r
610 \r
611 VOID\r
612 DevPathHardDrive (\r
613   IN OUT POOL_PRINT       *Str,\r
614   IN VOID                 *DevPath\r
615   )\r
616 {\r
617   HARDDRIVE_DEVICE_PATH *Hd;\r
618 \r
619   Hd = DevPath;\r
620   switch (Hd->SignatureType) {\r
621   case SIGNATURE_TYPE_MBR:\r
622     CatPrint (\r
623       Str,\r
624       L"HD(Part%d,Sig%08x)",\r
625       Hd->PartitionNumber,\r
626       *((UINT32 *) (&(Hd->Signature[0])))\r
627       );\r
628     break;\r
629 \r
630   case SIGNATURE_TYPE_GUID:\r
631     CatPrint (\r
632       Str,\r
633       L"HD(Part%d,Sig%g)",\r
634       Hd->PartitionNumber,\r
635       (EFI_GUID *) &(Hd->Signature[0])\r
636       );\r
637     break;\r
638 \r
639   default:\r
640     CatPrint (\r
641       Str,\r
642       L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
643       Hd->PartitionNumber,\r
644       Hd->MBRType,\r
645       Hd->SignatureType\r
646       );\r
647     break;\r
648   }\r
649 }\r
650 \r
651 VOID\r
652 DevPathCDROM (\r
653   IN OUT POOL_PRINT       *Str,\r
654   IN VOID                 *DevPath\r
655   )\r
656 {\r
657   CDROM_DEVICE_PATH *Cd;\r
658 \r
659   Cd = DevPath;\r
660   CatPrint (Str, L"CDROM(Entry%x)", Cd->BootEntry);\r
661 }\r
662 \r
663 VOID\r
664 DevPathFilePath (\r
665   IN OUT POOL_PRINT       *Str,\r
666   IN VOID                 *DevPath\r
667   )\r
668 {\r
669   FILEPATH_DEVICE_PATH  *Fp;\r
670 \r
671   Fp = DevPath;\r
672   CatPrint (Str, L"%s", Fp->PathName);\r
673 }\r
674 \r
675 VOID\r
676 DevPathMediaProtocol (\r
677   IN OUT POOL_PRINT       *Str,\r
678   IN VOID                 *DevPath\r
679   )\r
680 {\r
681   MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;\r
682 \r
683   MediaProt = DevPath;\r
684   CatPrint (Str, L"%g", &MediaProt->Protocol);\r
685 }\r
686 \r
687 VOID\r
688 DevPathFvFilePath (\r
689   IN OUT POOL_PRINT       *Str,\r
690   IN VOID                 *DevPath\r
691   )\r
692 {\r
693   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
694 \r
695   FvFilePath = DevPath;\r
696   CatPrint (Str, L"%g", &FvFilePath->NameGuid);\r
697 }\r
698 \r
699 VOID\r
700 DevPathBssBss (\r
701   IN OUT POOL_PRINT       *Str,\r
702   IN VOID                 *DevPath\r
703   )\r
704 {\r
705   BBS_BBS_DEVICE_PATH *Bbs;\r
706   CHAR16              *Type;\r
707 \r
708   Bbs = DevPath;\r
709   switch (Bbs->DeviceType) {\r
710   case BBS_TYPE_FLOPPY:\r
711     Type = L"Floppy";\r
712     break;\r
713 \r
714   case BBS_TYPE_HARDDRIVE:\r
715     Type = L"Harddrive";\r
716     break;\r
717 \r
718   case BBS_TYPE_CDROM:\r
719     Type = L"CDROM";\r
720     break;\r
721 \r
722   case BBS_TYPE_PCMCIA:\r
723     Type = L"PCMCIA";\r
724     break;\r
725 \r
726   case BBS_TYPE_USB:\r
727     Type = L"Usb";\r
728     break;\r
729 \r
730   case BBS_TYPE_EMBEDDED_NETWORK:\r
731     Type = L"Net";\r
732     break;\r
733 \r
734   default:\r
735     Type = L"?";\r
736     break;\r
737   }\r
738   //\r
739   // Since current Print function hasn't implemented %a (for ansi string)\r
740   // we will only print Unicode strings.\r
741   //\r
742   CatPrint (Str, L"Legacy-%s", Type);\r
743 }\r
744 \r
745 VOID\r
746 DevPathEndInstance (\r
747   IN OUT POOL_PRINT       *Str,\r
748   IN VOID                 *DevPath\r
749   )\r
750 {\r
751   CatPrint (Str, L",");\r
752 }\r
753 \r
754 VOID\r
755 DevPathNodeUnknown (\r
756   IN OUT POOL_PRINT       *Str,\r
757   IN VOID                 *DevPath\r
758   )\r
759 {\r
760   CatPrint (Str, L"?");\r
761 }\r
762 \r
763 DEVICE_PATH_STRING_TABLE  DevPathTable[] = {\r
764   {
765     HARDWARE_DEVICE_PATH,\r
766     HW_PCI_DP,\r
767     DevPathPci\r
768   },
769   {
770     HARDWARE_DEVICE_PATH,\r
771     HW_PCCARD_DP,\r
772     DevPathPccard\r
773   },
774   {
775     HARDWARE_DEVICE_PATH,\r
776     HW_MEMMAP_DP,\r
777     DevPathMemMap\r
778   },
779   {
780     HARDWARE_DEVICE_PATH,\r
781     HW_VENDOR_DP,\r
782     DevPathVendor\r
783   },
784   {
785     HARDWARE_DEVICE_PATH,\r
786     HW_CONTROLLER_DP,\r
787     DevPathController\r
788   },
789   {
790     ACPI_DEVICE_PATH,\r
791     ACPI_DP,\r
792     DevPathAcpi\r
793   },
794   {
795     MESSAGING_DEVICE_PATH,\r
796     MSG_ATAPI_DP,\r
797     DevPathAtapi\r
798   },
799   {
800     MESSAGING_DEVICE_PATH,\r
801     MSG_SCSI_DP,\r
802     DevPathScsi\r
803   },
804   {
805     MESSAGING_DEVICE_PATH,\r
806     MSG_FIBRECHANNEL_DP,\r
807     DevPathFibre\r
808   },
809   {
810     MESSAGING_DEVICE_PATH,\r
811     MSG_1394_DP,\r
812     DevPath1394\r
813   },
814   {
815     MESSAGING_DEVICE_PATH,\r
816     MSG_USB_DP,\r
817     DevPathUsb\r
818   },
819   {
820     MESSAGING_DEVICE_PATH,\r
821     MSG_USB_CLASS_DP,\r
822     DevPathUsbClass\r
823   },
824   {
825     MESSAGING_DEVICE_PATH,\r
826     MSG_I2O_DP,\r
827     DevPathI2O\r
828   },
829   {
830     MESSAGING_DEVICE_PATH,\r
831     MSG_MAC_ADDR_DP,\r
832     DevPathMacAddr\r
833   },
834   {
835     MESSAGING_DEVICE_PATH,\r
836     MSG_IPv4_DP,\r
837     DevPathIPv4\r
838   },
839   {
840     MESSAGING_DEVICE_PATH,\r
841     MSG_IPv6_DP,\r
842     DevPathIPv6\r
843   },
844   {
845     MESSAGING_DEVICE_PATH,\r
846     MSG_INFINIBAND_DP,\r
847     DevPathInfiniBand\r
848   },
849   {
850     MESSAGING_DEVICE_PATH,\r
851     MSG_UART_DP,\r
852     DevPathUart\r
853   },
854   {
855     MESSAGING_DEVICE_PATH,\r
856     MSG_VENDOR_DP,\r
857     DevPathVendor\r
858   },
859   {
860     MEDIA_DEVICE_PATH,\r
861     MEDIA_HARDDRIVE_DP,\r
862     DevPathHardDrive\r
863   },
864   {
865     MEDIA_DEVICE_PATH,\r
866     MEDIA_CDROM_DP,\r
867     DevPathCDROM\r
868   },
869   {
870     MEDIA_DEVICE_PATH,\r
871     MEDIA_VENDOR_DP,\r
872     DevPathVendor\r
873   },
874   {
875     MEDIA_DEVICE_PATH,\r
876     MEDIA_FILEPATH_DP,\r
877     DevPathFilePath\r
878   },
879   {
880     MEDIA_DEVICE_PATH,\r
881     MEDIA_PROTOCOL_DP,\r
882     DevPathMediaProtocol\r
883   },
884 \r
885 #if (EFI_SPECIFICATION_VERSION < 0x00020000)\r
886   {
887     MEDIA_DEVICE_PATH,\r
888     MEDIA_FV_FILEPATH_DP,\r
889     DevPathFvFilePath\r
890   },
891 #endif\r
892 \r
893   {
894     BBS_DEVICE_PATH,\r
895     BBS_BBS_DP,\r
896     DevPathBssBss\r
897   },
898   {
899     END_DEVICE_PATH_TYPE,\r
900     END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
901     DevPathEndInstance\r
902   },
903   {
904     0,\r
905     0,\r
906     NULL\r
907   }
908 };\r
909 \r
910 CHAR16 *\r
911 DevicePathToStr (\r
912   IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
913   )\r
914 /*++\r
915 \r
916   Turns the Device Path into a printable string.  Allcoates\r
917   the string from pool.  The caller must SafeFreePool the returned\r
918   string.\r
919 \r
920 --*/\r
921 {\r
922   POOL_PRINT                Str;\r
923   EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;\r
924   VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
925 \r
926   UINTN Index;\r
927   UINTN NewSize;\r
928 \r
929   ZeroMem (&Str, sizeof (Str));\r
930 \r
931   if (DevPath == NULL) {\r
932     goto Done;\r
933   }\r
934   //\r
935   // Unpacked the device path\r
936   //\r
937   DevPath = BdsLibUnpackDevicePath (DevPath);\r
938   ASSERT (DevPath);\r
939 \r
940   //\r
941   // Process each device path node\r
942   //\r
943   DevPathNode = DevPath;\r
944   while (!IsDevicePathEnd (DevPathNode)) {\r
945     //\r
946     // Find the handler to dump this device path node\r
947     //\r
948     DumpNode = NULL;\r
949     for (Index = 0; DevPathTable[Index].Function; Index += 1) {\r
950 \r
951       if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
952           DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
953           ) {\r
954         DumpNode = DevPathTable[Index].Function;\r
955         break;\r
956       }\r
957     }\r
958     //\r
959     // If not found, use a generic function\r
960     //\r
961     if (!DumpNode) {\r
962       DumpNode = DevPathNodeUnknown;\r
963     }\r
964     //\r
965     //  Put a path seperator in if needed\r
966     //\r
967     if (Str.len && DumpNode != DevPathEndInstance) {\r
968       CatPrint (&Str, L"/");\r
969     }\r
970     //\r
971     // Print this node of the device path\r
972     //\r
973     DumpNode (&Str, DevPathNode);\r
974 \r
975     //\r
976     // Next device path node\r
977     //\r
978     DevPathNode = NextDevicePathNode (DevPathNode);\r
979   }\r
980   //\r
981   // Shrink pool used for string allocation\r
982   //\r
983   gBS->FreePool (DevPath);\r
984 \r
985 Done:\r
986   NewSize = (Str.len + 1) * sizeof (CHAR16);\r
987   Str.str = ReallocatePool (Str.str, NewSize, NewSize);\r
988   ASSERT (Str.str != NULL);\r
989   Str.str[Str.len] = 0;\r
990   return Str.str;\r
991 }\r
992 \r
993 EFI_DEVICE_PATH_PROTOCOL *\r
994 LibDuplicateDevicePathInstance (\r
995   IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
996   )\r
997 /*++\r
998 \r
999 Routine Description:\r
1000 \r
1001   Function creates a device path data structure that identically matches the \r
1002   device path passed in.\r
1003 \r
1004 Arguments:\r
1005 \r
1006   DevPath      - A pointer to a device path data structure.\r
1007 \r
1008 Returns:\r
1009 \r
1010   The new copy of DevPath is created to identically match the input.  \r
1011   Otherwise, NULL is returned.\r
1012 \r
1013 --*/\r
1014 {\r
1015   EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;\r
1016   EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
1017   EFI_DEVICE_PATH_PROTOCOL  *Temp;\r
1018   UINTN                     Size;\r
1019 \r
1020   //\r
1021   // get the size of an instance from the input\r
1022   //\r
1023   Temp            = DevPath;\r
1024   DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);\r
1025 \r
1026   //\r
1027   // Make a copy\r
1028   //\r
1029   NewDevPath = NULL;\r
1030   if (Size) {\r
1031     NewDevPath = AllocateZeroPool (Size);\r
1032     ASSERT (NewDevPath != NULL);\r
1033   }\r
1034 \r
1035   if (NewDevPath) {\r
1036     CopyMem (NewDevPath, DevicePathInst, Size);\r
1037   }\r
1038 \r
1039   return NewDevPath;\r
1040 }\r