Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1036 lines
23 KiB

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