dpath.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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. // Guid has format of IEEE-EUI64
  525. CatPrint(Str, L"I1394(%016lx)", F1394->Guid);
  526. }
  527. static VOID
  528. _DevPathUsb (
  529. IN OUT POOL_PRINT *Str,
  530. IN VOID *DevPath
  531. )
  532. {
  533. USB_DEVICE_PATH *Usb;
  534. Usb = DevPath;
  535. CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ;
  536. }
  537. static VOID
  538. _DevPathI2O (
  539. IN OUT POOL_PRINT *Str,
  540. IN VOID *DevPath
  541. )
  542. {
  543. I2O_DEVICE_PATH *I2O;
  544. I2O = DevPath;
  545. CatPrint(Str, L"I2O(0x%X)", I2O->Tid);
  546. }
  547. static VOID
  548. _DevPathMacAddr (
  549. IN OUT POOL_PRINT *Str,
  550. IN VOID *DevPath
  551. )
  552. {
  553. MAC_ADDR_DEVICE_PATH *MAC;
  554. UINTN HwAddressSize;
  555. UINTN Index;
  556. MAC = DevPath;
  557. /* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */
  558. HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ;
  559. HwAddressSize -= sizeof( MAC-> Header ) ;
  560. HwAddressSize -= sizeof( MAC-> IfType ) ;
  561. if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
  562. HwAddressSize = 6;
  563. }
  564. CatPrint(Str, L"Mac(");
  565. for(Index = 0; Index < HwAddressSize; Index++) {
  566. CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
  567. }
  568. if ( MAC-> IfType != 0 ) {
  569. CatPrint(Str, L",%d" , MAC-> IfType ) ;
  570. }
  571. CatPrint(Str, L")");
  572. }
  573. static VOID
  574. CatPrintIPv4(
  575. IN OUT POOL_PRINT * Str ,
  576. IN EFI_IPv4_ADDRESS * Address
  577. )
  578. {
  579. CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ,
  580. Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ;
  581. }
  582. static BOOLEAN
  583. IsNotNullIPv4(
  584. IN EFI_IPv4_ADDRESS * Address
  585. )
  586. {
  587. UINT8 val ;
  588. val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ;
  589. val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ;
  590. return val != 0 ;
  591. }
  592. static VOID
  593. CatPrintNetworkProtocol(
  594. IN OUT POOL_PRINT * Str ,
  595. IN UINT16 Proto
  596. )
  597. {
  598. if ( Proto == 6 ) {
  599. CatPrint( Str , L"TCP" ) ;
  600. } else if ( Proto == 17 ) {
  601. CatPrint( Str , L"UDP" ) ;
  602. } else {
  603. CatPrint( Str , L"%d" , Proto ) ;
  604. }
  605. }
  606. static VOID
  607. _DevPathIPv4 (
  608. IN OUT POOL_PRINT *Str,
  609. IN VOID *DevPath
  610. )
  611. {
  612. IPv4_DEVICE_PATH *IP;
  613. BOOLEAN show ;
  614. IP = DevPath;
  615. CatPrint( Str , L"IPv4(") ;
  616. CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ;
  617. CatPrint( Str , L",") ;
  618. CatPrintNetworkProtocol( Str , IP-> Protocol ) ;
  619. CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ;
  620. show = IsNotNullIPv4( & IP-> LocalIpAddress ) ;
  621. if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
  622. /* only version 2 includes gateway and netmask */
  623. show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
  624. show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
  625. }
  626. if ( show ) {
  627. CatPrint( Str , L"," ) ;
  628. CatPrintIPv4( Str , & IP-> LocalIpAddress ) ;
  629. if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) {
  630. /* only version 2 includes gateway and netmask */
  631. show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ;
  632. show |= IsNotNullIPv4( & IP-> SubnetMask ) ;
  633. if ( show ) {
  634. CatPrint( Str , L",") ;
  635. CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ;
  636. if ( IsNotNullIPv4( & IP-> SubnetMask ) ) {
  637. CatPrint( Str , L",") ;
  638. CatPrintIPv4( Str , & IP-> SubnetMask ) ;
  639. }
  640. }
  641. }
  642. }
  643. CatPrint( Str , L")") ;
  644. }
  645. #define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) )
  646. static VOID
  647. CatPrintIPv6(
  648. IN OUT POOL_PRINT * Str ,
  649. IN EFI_IPv6_ADDRESS * Address
  650. )
  651. {
  652. CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" ,
  653. CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) ,
  654. CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ,
  655. CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) ,
  656. CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) ,
  657. CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) ,
  658. CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) ,
  659. CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) ,
  660. CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ;
  661. }
  662. static VOID
  663. _DevPathIPv6 (
  664. IN OUT POOL_PRINT *Str,
  665. IN VOID *DevPath
  666. )
  667. {
  668. IPv6_DEVICE_PATH *IP;
  669. IP = DevPath;
  670. CatPrint( Str , L"IPv6(") ;
  671. CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ;
  672. CatPrint( Str , L",") ;
  673. CatPrintNetworkProtocol( Str, IP-> Protocol ) ;
  674. CatPrint( Str , L",%s," , IP-> IPAddressOrigin ?
  675. ( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" :
  676. L"StatefulAutoConfigure" ) : L"Static" ) ;
  677. CatPrintIPv6( Str , & IP-> LocalIpAddress ) ;
  678. if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) {
  679. CatPrint( Str , L",") ;
  680. CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ;
  681. CatPrint( Str , L",") ;
  682. CatPrint( Str , L"%d" , & IP-> PrefixLength ) ;
  683. }
  684. CatPrint( Str , L")") ;
  685. }
  686. static VOID
  687. _DevPathUri (
  688. IN OUT POOL_PRINT *Str,
  689. IN VOID *DevPath
  690. )
  691. {
  692. URI_DEVICE_PATH *Uri;
  693. Uri = DevPath;
  694. CatPrint( Str, L"Uri(%a)", Uri->Uri );
  695. }
  696. static VOID
  697. _DevPathInfiniBand (
  698. IN OUT POOL_PRINT *Str,
  699. IN VOID *DevPath
  700. )
  701. {
  702. INFINIBAND_DEVICE_PATH *InfiniBand;
  703. InfiniBand = DevPath;
  704. CatPrint(Str, L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)",
  705. InfiniBand->ResourceFlags, InfiniBand->PortGid, InfiniBand->ServiceId,
  706. InfiniBand->TargetPortId, InfiniBand->DeviceId);
  707. }
  708. static VOID
  709. _DevPathUart (
  710. IN OUT POOL_PRINT *Str,
  711. IN VOID *DevPath
  712. )
  713. {
  714. UART_DEVICE_PATH *Uart;
  715. CHAR8 Parity;
  716. Uart = DevPath;
  717. switch (Uart->Parity) {
  718. case 0 : Parity = 'D'; break;
  719. case 1 : Parity = 'N'; break;
  720. case 2 : Parity = 'E'; break;
  721. case 3 : Parity = 'O'; break;
  722. case 4 : Parity = 'M'; break;
  723. case 5 : Parity = 'S'; break;
  724. default : Parity = 'x'; break;
  725. }
  726. if (Uart->BaudRate == 0) {
  727. CatPrint(Str, L"Uart(DEFAULT,");
  728. } else {
  729. CatPrint(Str, L"Uart(%ld,", Uart->BaudRate);
  730. }
  731. if (Uart->DataBits == 0) {
  732. CatPrint(Str, L"DEFAULT,");
  733. } else {
  734. CatPrint(Str, L"%d,", Uart->DataBits);
  735. }
  736. CatPrint(Str, L"%c,", Parity);
  737. switch (Uart->StopBits) {
  738. case 0 : CatPrint(Str, L"D)"); break;
  739. case 1 : CatPrint(Str, L"1)"); break;
  740. case 2 : CatPrint(Str, L"1.5)"); break;
  741. case 3 : CatPrint(Str, L"2)"); break;
  742. default : CatPrint(Str, L"x)"); break;
  743. }
  744. }
  745. static VOID
  746. _DevPathSata (
  747. IN OUT POOL_PRINT *Str,
  748. IN VOID *DevPath
  749. )
  750. {
  751. SATA_DEVICE_PATH * Sata ;
  752. Sata = DevPath;
  753. CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber ,
  754. Sata-> PortMultiplierPortNumber , Sata-> Lun ) ;
  755. }
  756. static VOID
  757. _DevPathHardDrive (
  758. IN OUT POOL_PRINT *Str,
  759. IN VOID *DevPath
  760. )
  761. {
  762. HARDDRIVE_DEVICE_PATH *Hd;
  763. Hd = DevPath;
  764. switch (Hd->SignatureType) {
  765. case SIGNATURE_TYPE_MBR:
  766. CatPrint(Str, L"HD(%d,MBR,0x%08x)",
  767. Hd->PartitionNumber,
  768. *((UINT32 *)(&(Hd->Signature[0])))
  769. );
  770. break;
  771. case SIGNATURE_TYPE_GUID:
  772. CatPrint(Str, L"HD(%d,GPT,%g)",
  773. Hd->PartitionNumber,
  774. (EFI_GUID *) &(Hd->Signature[0])
  775. );
  776. break;
  777. default:
  778. CatPrint(Str, L"HD(%d,%d,0)",
  779. Hd->PartitionNumber,
  780. Hd->SignatureType
  781. );
  782. break;
  783. }
  784. }
  785. static VOID
  786. _DevPathCDROM (
  787. IN OUT POOL_PRINT *Str,
  788. IN VOID *DevPath
  789. )
  790. {
  791. CDROM_DEVICE_PATH *Cd;
  792. Cd = DevPath;
  793. CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ;
  794. }
  795. static VOID
  796. _DevPathFilePath (
  797. IN OUT POOL_PRINT *Str,
  798. IN VOID *DevPath
  799. )
  800. {
  801. FILEPATH_DEVICE_PATH *Fp;
  802. Fp = DevPath;
  803. CatPrint(Str, L"%s", Fp->PathName);
  804. }
  805. static VOID
  806. _DevPathMediaProtocol (
  807. IN OUT POOL_PRINT *Str,
  808. IN VOID *DevPath
  809. )
  810. {
  811. MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
  812. MediaProt = DevPath;
  813. CatPrint(Str, L"%g", &MediaProt->Protocol);
  814. }
  815. static VOID
  816. _DevPathBssBss (
  817. IN OUT POOL_PRINT *Str,
  818. IN VOID *DevPath
  819. )
  820. {
  821. BBS_BBS_DEVICE_PATH *Bss;
  822. CHAR16 *Type;
  823. Bss = DevPath;
  824. switch (Bss->DeviceType) {
  825. case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
  826. case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
  827. case BBS_TYPE_CDROM: Type = L"CDROM"; break;
  828. case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
  829. case BBS_TYPE_USB: Type = L"Usb"; break;
  830. case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
  831. default: Type = L"?"; break;
  832. }
  833. CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
  834. }
  835. static VOID
  836. _DevPathEndInstance (
  837. IN OUT POOL_PRINT *Str,
  838. IN VOID *DevPath EFI_UNUSED
  839. )
  840. {
  841. CatPrint(Str, L",");
  842. }
  843. /**
  844. * Print unknown device node.
  845. * UEFI 2.4 § 9.6.1.6 table 89.
  846. */
  847. static VOID
  848. _DevPathNodeUnknown (
  849. IN OUT POOL_PRINT *Str,
  850. IN VOID *DevPath
  851. )
  852. {
  853. EFI_DEVICE_PATH * Path ;
  854. UINT8 * value ;
  855. int length , index ;
  856. Path = DevPath ;
  857. value = DevPath ;
  858. value += 4 ;
  859. switch ( Path-> Type ) {
  860. case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */
  861. CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ;
  862. break ;
  863. }
  864. case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */
  865. CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ;
  866. break ;
  867. }
  868. case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */
  869. CatPrint( Str , L"Msg(%d" , Path-> SubType ) ;
  870. break ;
  871. }
  872. case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */
  873. CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ;
  874. break ;
  875. }
  876. case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */
  877. CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ;
  878. break ;
  879. }
  880. default : { /* Unknown Device Path */
  881. CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ;
  882. break ;
  883. }
  884. }
  885. length = DevicePathNodeLength( Path ) ;
  886. for ( index = 0 ; index < length ; index ++ ) {
  887. if ( index == 0 ) CatPrint( Str , L",0x" ) ;
  888. CatPrint( Str , L"%02x" , * value ) ;
  889. value ++ ;
  890. }
  891. CatPrint( Str , L")" ) ;
  892. }
  893. /*
  894. * Table to convert "Type" and "SubType" to a "convert to text" function/
  895. * Entries hold "Type" and "SubType" for know values.
  896. * Special "SubType" 0 is used as default for known type with unknown subtype.
  897. */
  898. typedef struct {
  899. UINT8 Type;
  900. UINT8 SubType;
  901. VOID (*Function)(POOL_PRINT *, VOID *);
  902. } DevPathTable_Type;
  903. DevPathTable_Type DevPathTable[] = {
  904. { HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci},
  905. { HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard},
  906. { HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap},
  907. { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor},
  908. { HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController},
  909. { ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi},
  910. { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi},
  911. { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi},
  912. { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre},
  913. { MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394},
  914. { MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb},
  915. { MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O},
  916. { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr},
  917. { MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4},
  918. { MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6},
  919. { MESSAGING_DEVICE_PATH, MSG_URI_DP, _DevPathUri},
  920. { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand},
  921. { MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart},
  922. { MESSAGING_DEVICE_PATH , MSG_SATA_DP , _DevPathSata } ,
  923. { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor},
  924. { MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive},
  925. { MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM},
  926. { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor},
  927. { MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath},
  928. { MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol},
  929. { BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss},
  930. { END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance},
  931. { 0, 0, NULL}
  932. };
  933. CHAR16 *
  934. DevicePathToStr (
  935. EFI_DEVICE_PATH *DevPath
  936. )
  937. /*++
  938. Turns the Device Path into a printable string. Allcoates
  939. the string from pool. The caller must FreePool the returned
  940. string.
  941. --*/
  942. {
  943. POOL_PRINT Str;
  944. EFI_DEVICE_PATH *DevPathNode;
  945. VOID (*DumpNode)(POOL_PRINT *, VOID *);
  946. UINTN Index, NewSize;
  947. ZeroMem(&Str, sizeof(Str));
  948. //
  949. // Unpacked the device path
  950. //
  951. DevPath = UnpackDevicePath(DevPath);
  952. ASSERT (DevPath);
  953. //
  954. // Process each device path node
  955. //
  956. DevPathNode = DevPath;
  957. while (!IsDevicePathEnd(DevPathNode)) {
  958. //
  959. // Find the handler to dump this device path node
  960. //
  961. DumpNode = NULL;
  962. for (Index = 0; DevPathTable[Index].Function; Index += 1) {
  963. if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
  964. DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
  965. DumpNode = DevPathTable[Index].Function;
  966. break;
  967. }
  968. }
  969. //
  970. // If not found, use a generic function
  971. //
  972. if (!DumpNode) {
  973. DumpNode = _DevPathNodeUnknown;
  974. }
  975. //
  976. // Put a path seperator in if needed
  977. //
  978. if (Str.len && DumpNode != _DevPathEndInstance) {
  979. CatPrint (&Str, L"/");
  980. }
  981. //
  982. // Print this node of the device path
  983. //
  984. DumpNode (&Str, DevPathNode);
  985. //
  986. // Next device path node
  987. //
  988. DevPathNode = NextDevicePathNode(DevPathNode);
  989. }
  990. //
  991. // Shrink pool used for string allocation
  992. //
  993. FreePool (DevPath);
  994. NewSize = (Str.len + 1) * sizeof(CHAR16);
  995. Str.str = ReallocatePool (Str.str, NewSize, NewSize);
  996. Str.str[Str.len] = 0;
  997. return Str.str;
  998. }
  999. BOOLEAN
  1000. LibMatchDevicePaths (
  1001. IN EFI_DEVICE_PATH *Multi,
  1002. IN EFI_DEVICE_PATH *Single
  1003. )
  1004. {
  1005. EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
  1006. UINTN Size;
  1007. if (!Multi || !Single) {
  1008. return FALSE;
  1009. }
  1010. DevicePath = Multi;
  1011. while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) {
  1012. if (CompareMem (Single, DevicePathInst, Size) == 0) {
  1013. return TRUE;
  1014. }
  1015. }
  1016. return FALSE;
  1017. }
  1018. EFI_DEVICE_PATH *
  1019. LibDuplicateDevicePathInstance (
  1020. IN EFI_DEVICE_PATH *DevPath
  1021. )
  1022. {
  1023. EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp;
  1024. UINTN Size = 0;
  1025. //
  1026. // get the size of an instance from the input
  1027. //
  1028. Temp = DevPath;
  1029. DevicePathInst = DevicePathInstance (&Temp, &Size);
  1030. //
  1031. // Make a copy and set proper end type
  1032. //
  1033. NewDevPath = NULL;
  1034. if (Size) {
  1035. NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
  1036. }
  1037. if (NewDevPath) {
  1038. CopyMem (NewDevPath, DevicePathInst, Size);
  1039. Temp = NextDevicePathNode(NewDevPath);
  1040. SetDevicePathEndNode(Temp);
  1041. }
  1042. return NewDevPath;
  1043. }