]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Library/EdkGenericBdsLib/DevicePath.c
Original range calculation in GetNextFile() is incorrect.
[mirror_edk2.git] / EdkUnixPkg / Library / EdkGenericBdsLib / DevicePath.c
CommitLineData
c9093a06 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 DevicePath.c\r
15\r
16Abstract:\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
25EFI_GUID UnknownDeviceGuid = UNKNOWN_DEVICE_GUID;\r
26#endif \r
27\r
28EFI_GUID mEfiUnixThunkProtocolGuid = EFI_UNIX_THUNK_PROTOCOL_GUID;\r
29EFI_GUID mEfiUnixUgaGuid = EFI_UNIX_UGA_GUID;\r
30EFI_GUID mEfiMsgPcAnsiGuid = DEVICE_PATH_MESSAGING_PC_ANSI;\r
31EFI_GUID mEfiMsgVt100Guid = DEVICE_PATH_MESSAGING_VT_100;\r
32EFI_GUID mEfiMsgVt100PlusGuid = DEVICE_PATH_MESSAGING_VT_100_PLUS;\r
33EFI_GUID mEfiMsgVt100Utf8Guid = DEVICE_PATH_MESSAGING_VT_UTF8;\r
34\r
35VOID *\r
36ReallocatePool (\r
37 IN VOID *OldPool,\r
38 IN UINTN OldSize,\r
39 IN UINTN NewSize\r
40 )\r
41/*++\r
42\r
43Routine Description:\r
44\r
45 Adjusts the size of a previously allocated buffer.\r
46\r
47Arguments:\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
55Returns:\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
83CHAR16 *\r
84CatPrint (\r
85 IN OUT POOL_PRINT *Str,\r
86 IN CHAR16 *fmt,\r
87 ...\r
88 )\r
89/*++\r
90\r
91Routine 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
96Arguments:\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
103Returns:\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
147EFI_DEVICE_PATH_PROTOCOL *\r
148BdsLibUnpackDevicePath (\r
149 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
150 )\r
151/*++\r
152\r
153Routine 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
158Arguments:\r
159\r
160 DevPath - A pointer to a device path data structure\r
161\r
162Returns:\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
221VOID\r
222DevPathPci (\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
233VOID\r
234DevPathPccard (\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
245VOID\r
246DevPathMemMap (\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
263VOID\r
264DevPathController (\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
275VOID\r
276DevPathVendor (\r
277 IN OUT POOL_PRINT *Str,\r
278 IN VOID *DevPath\r
279 )\r
280/*++\r
281\r
282Routine Description:\r
283\r
284 Convert Vendor device path to device name\r
285\r
286Arguments:\r
287\r
288 Str - The buffer store device name\r
289 DevPath - Pointer to vendor device path\r
290\r
291Returns:\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
353VOID\r
354DevPathAcpi (\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
369VOID\r
370DevPathAtapi (\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
386VOID\r
387DevPathScsi (\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
398VOID\r
399DevPathFibre (\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
410VOID\r
411DevPath1394 (\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
422VOID\r
423DevPathUsb (\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
434VOID\r
435DevPathUsbClass (\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
454VOID\r
455DevPathI2O (\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
466VOID\r
467DevPathMacAddr (\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
492VOID\r
493DevPathIPv4 (\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
512VOID\r
513DevPathIPv6 (\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
524VOID\r
525DevPathInfiniBand (\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
536VOID\r
537DevPathUart (\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
611VOID\r
612DevPathHardDrive (\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
651VOID\r
652DevPathCDROM (\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
663VOID\r
664DevPathFilePath (\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
675VOID\r
676DevPathMediaProtocol (\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
687VOID\r
688DevPathFvFilePath (\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
699VOID\r
700DevPathBssBss (\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
745VOID\r
746DevPathEndInstance (\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
754VOID\r
755DevPathNodeUnknown (\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
763DEVICE_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
910CHAR16 *\r
911DevicePathToStr (\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
985Done:\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
993EFI_DEVICE_PATH_PROTOCOL *\r
994LibDuplicateDevicePathInstance (\r
995 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
996 )\r
997/*++\r
998\r
999Routine 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
1004Arguments:\r
1005\r
1006 DevPath - A pointer to a device path data structure.\r
1007\r
1008Returns:\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