dpath.c 31 KB

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