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.

1296 lines
31 KiB

  1. #include "bldr.h"
  2. #include "bootefi.h"
  3. #include "efi.h"
  4. #include "smbios.h"
  5. #include "stdlib.h"
  6. extern EFI_SYSTEM_TABLE *EfiST;
  7. extern EFI_BOOT_SERVICES *EfiBS;
  8. INTN
  9. RUNTIMEFUNCTION
  10. CompareGuid(
  11. IN EFI_GUID *Guid1,
  12. IN EFI_GUID *Guid2
  13. )
  14. /*++
  15. Routine Description:
  16. Compares two GUIDs
  17. Arguments:
  18. Guid1 - guid to compare
  19. Guid2 - guid to compare
  20. Returns:
  21. = 0 if Guid1 == Guid2
  22. --*/
  23. {
  24. INT32 *g1, *g2, r;
  25. //
  26. // Compare 32 bits at a time
  27. //
  28. g1 = (INT32 *) Guid1;
  29. g2 = (INT32 *) Guid2;
  30. r = g1[0] - g2[0];
  31. r |= g1[1] - g2[1];
  32. r |= g1[2] - g2[2];
  33. r |= g1[3] - g2[3];
  34. return r;
  35. }
  36. EFI_STATUS
  37. GetSystemConfigurationTable(
  38. IN EFI_GUID *TableGuid,
  39. IN OUT VOID **Table
  40. )
  41. {
  42. UINTN Index;
  43. //
  44. // ST is system table
  45. //
  46. for(Index=0;Index<EfiST->NumberOfTableEntries;Index++) {
  47. if (CompareGuid(TableGuid,&(EfiST->ConfigurationTable[Index].VendorGuid))==0) {
  48. *Table = EfiST->ConfigurationTable[Index].VendorTable;
  49. return EFI_SUCCESS;
  50. }
  51. }
  52. return EFI_NOT_FOUND;
  53. }
  54. ARC_STATUS
  55. BlGetEfiProtocolHandles(
  56. IN EFI_GUID *ProtocolType,
  57. OUT EFI_HANDLE **pHandleArray,
  58. OUT ULONG *NumberOfDevices
  59. )
  60. /*++
  61. Routine Description:
  62. Finds all of the handles that support a given protocol type.
  63. This routine requires that BlInitializeMemory() has already been
  64. called.
  65. Arguments:
  66. ProtocolType - GUID that describes handle type to search for.
  67. pHandleArray - receives an array of handles that support the specified
  68. protocol.
  69. The page that these handles reside in can be freed via
  70. BlFreeDescriptor.
  71. NumberOfDevices - receives the number of device handles that support the
  72. given protocol
  73. Returns:
  74. ARC_STATUS indicating outcome.
  75. --*/
  76. {
  77. EFI_HANDLE *HandleArray = NULL;
  78. ULONGLONG HandleArraySize = 0;
  79. ULONG MemoryPage;
  80. ARC_STATUS ArcStatus;
  81. EFI_STATUS EfiStatus;
  82. *pHandleArray = NULL;
  83. *NumberOfDevices = 0;
  84. //
  85. // Change to physical mode so that we can make EFI calls
  86. //
  87. FlipToPhysical();
  88. // EfiST->ConOut->OutputString(EfiST->ConOut, L"In BlGetEfiProtocolHandles\r\n");
  89. //
  90. // Try to find out how much space we need.
  91. //
  92. EfiStatus = EfiBS->LocateHandle (
  93. ByProtocol,
  94. ProtocolType,
  95. 0,
  96. (UINTN *) &HandleArraySize,
  97. HandleArray
  98. );
  99. FlipToVirtual();
  100. if (EfiStatus != EFI_BUFFER_TOO_SMALL) {
  101. //
  102. // yikes. something is really messed up. return failure.
  103. //
  104. // EfiST->ConOut->OutputString(EfiST->ConOut, L"LocateHandle returned failure\r\n");
  105. return(EINVAL);
  106. }
  107. // EfiST->ConOut->OutputString(EfiST->ConOut, L"About to BlAllocateAlignedDescriptor\r\n");
  108. //
  109. // allocate space for the handles.
  110. //
  111. ArcStatus = BlAllocateAlignedDescriptor(
  112. LoaderFirmwareTemporary,
  113. 0,
  114. (ULONG)(HandleArraySize >> PAGE_SIZE),
  115. 0,
  116. &MemoryPage);
  117. if (ArcStatus != ESUCCESS) {
  118. // EfiST->ConOut->OutputString(EfiST->ConOut, L"BlAllocateAlignedDescriptor failed\r\n");
  119. return(ArcStatus);
  120. }
  121. HandleArray = (EFI_HANDLE *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  122. FlipToPhysical();
  123. RtlZeroMemory(HandleArray, HandleArraySize);
  124. // EfiST->ConOut->OutputString(EfiST->ConOut, L"calling LocateHandle again\r\n");
  125. //
  126. // now get the handles now that we have enough space.
  127. //
  128. EfiStatus = EfiBS->LocateHandle (
  129. ByProtocol,
  130. ProtocolType,
  131. 0,
  132. (UINTN *) &HandleArraySize,
  133. (EFI_HANDLE *)HandleArray
  134. );
  135. // EfiST->ConOut->OutputString(EfiST->ConOut, L"back from LocateHandle\r\n");
  136. FlipToVirtual();
  137. if (EFI_ERROR(EfiStatus)) {
  138. //
  139. // cleanup and return
  140. //
  141. // EfiST->ConOut->OutputString(EfiST->ConOut, L"LocateHandle failed\r\n");
  142. BlFreeDescriptor( MemoryPage );
  143. return(EINVAL);
  144. }
  145. // EfiST->ConOut->OutputString(EfiST->ConOut, L"LocateHandle succeeded, return success\r\n");
  146. *NumberOfDevices = (ULONG)(HandleArraySize / sizeof (EFI_HANDLE));
  147. *pHandleArray = HandleArray;
  148. // BlPrint(TEXT("BlGetEfiProtocolHandles: found %x devices\r\n"), *NumberOfDevices );
  149. return(ESUCCESS);
  150. }
  151. CHAR16 *sprintf_buf;
  152. UINT16 count;
  153. VOID
  154. __cdecl
  155. putbuf(CHAR16 c)
  156. {
  157. *sprintf_buf++ = c;
  158. count++;
  159. }
  160. VOID
  161. bzero(CHAR16 *cp, int len)
  162. {
  163. while (len--) {
  164. *(cp + len) = 0;
  165. }
  166. }
  167. VOID
  168. __cdecl
  169. doprnt(VOID (*func)(CHAR16 c), const CHAR16 *fmt, va_list args);
  170. //
  171. // BUGBUG this is a semi-sprintf hacked together just to get it to work
  172. //
  173. UINT16
  174. __cdecl
  175. wsprintf(CHAR16 *buf, const CHAR16 *fmt, ...)
  176. {
  177. va_list args;
  178. sprintf_buf = buf;
  179. va_start(args, fmt);
  180. doprnt(putbuf, fmt, args);
  181. va_end(args);
  182. putbuf('\0');
  183. return count--;
  184. }
  185. void
  186. __cdecl
  187. printbase(VOID (*func)(CHAR16), ULONG x, int base, int width)
  188. {
  189. static CHAR16 itoa[] = L"0123456789abcdef";
  190. ULONG j;
  191. LONG k;
  192. CHAR16 buf[32], *s = buf;
  193. bzero(buf, 16);
  194. if (x == 0 ) {
  195. *s++ = itoa[0];
  196. }
  197. while (x) {
  198. j = x % base;
  199. *s++ = itoa[j];
  200. x -= j;
  201. x /= base;
  202. }
  203. if( s-buf < width ) {
  204. for( k = 0; k < width - (s-buf); k++ ) {
  205. func('0');
  206. }
  207. }
  208. for (--s; s >= buf; --s) {
  209. func(*s);
  210. }
  211. }
  212. void
  213. __cdecl
  214. printguid(
  215. VOID (*func)( CHAR16),
  216. GUID *pGuid
  217. )
  218. {
  219. ULONG u;
  220. func(L'{');
  221. printbase(func, pGuid->Data1, 16, 8);
  222. func(L'-');
  223. printbase(func, pGuid->Data2, 16, 4);
  224. func(L'-');
  225. printbase(func, pGuid->Data3, 16, 4);
  226. func(L'-');
  227. printbase(func, pGuid->Data4[0], 16, 2);
  228. printbase(func, pGuid->Data4[1], 16, 2);
  229. func(L'-');
  230. printbase(func, pGuid->Data4[2], 16, 2);
  231. printbase(func, pGuid->Data4[3], 16, 2);
  232. printbase(func, pGuid->Data4[4], 16, 2);
  233. printbase(func, pGuid->Data4[5], 16, 2);
  234. printbase(func, pGuid->Data4[6], 16, 2);
  235. printbase(func, pGuid->Data4[7], 16, 2);
  236. func(L'}');
  237. }
  238. void
  239. __cdecl
  240. doprnt(VOID (*func)( CHAR16 c), const CHAR16 *fmt, va_list args)
  241. {
  242. ULONG x;
  243. LONG l;
  244. LONG width;
  245. CHAR16 c, *s;
  246. GUID * g;
  247. count = 0;
  248. while (c = *fmt++) {
  249. if (c != '%') {
  250. func(c);
  251. continue;
  252. }
  253. width=0;
  254. c=*fmt++;
  255. if(c == '0') {
  256. while( c = *fmt++) {
  257. if (!isdigit(c)) {
  258. break;
  259. }
  260. width = width*10;
  261. width = width+(c-48);
  262. }
  263. }
  264. fmt--; // back it up one char
  265. switch (c = *fmt++) {
  266. case 'x':
  267. x = va_arg(args, ULONG);
  268. printbase(func, x, 16, width);
  269. break;
  270. case 'o':
  271. x = va_arg(args, ULONG);
  272. printbase(func, x, 8, width);
  273. break;
  274. case 'd':
  275. l = va_arg(args, LONG);
  276. if (l < 0) {
  277. func('-');
  278. l = -l;
  279. }
  280. printbase(func, (ULONG) l, 10, width);
  281. break;
  282. case 'u':
  283. l = va_arg(args, ULONG);
  284. printbase(func, (ULONG) l, 10, width);
  285. break;
  286. case 'g':
  287. g = va_arg(args, GUID *);
  288. printguid(func, g);
  289. break;
  290. case 'c':
  291. c = va_arg(args, CHAR16);
  292. func(c);
  293. break;
  294. case 's':
  295. s = va_arg(args, CHAR16 *);
  296. while (*s) {
  297. func(*s++);
  298. }
  299. break;
  300. default:
  301. func(c);
  302. break;
  303. }
  304. }
  305. }
  306. VOID
  307. CatPrint(
  308. IN UNICODE_STRING *String,
  309. IN CHAR16* Format,
  310. ...
  311. )
  312. {
  313. CHAR16* pString = String->Buffer;
  314. va_list args;
  315. if (*pString != '\0') {
  316. pString = String->Buffer + wcslen(String->Buffer);
  317. }
  318. sprintf_buf = pString;
  319. va_start(args, Format);
  320. doprnt(putbuf, Format, args);
  321. va_end(args);
  322. putbuf('\0');
  323. }
  324. VOID
  325. _DevPathPci (
  326. IN OUT UNICODE_STRING *Str,
  327. IN VOID *DevPath
  328. )
  329. {
  330. PCI_DEVICE_PATH UNALIGNED *Pci;
  331. Pci = DevPath;
  332. CatPrint(Str, L"Pci(%x|%x)", Pci->Device, Pci->Function);
  333. }
  334. VOID
  335. _DevPathPccard (
  336. IN OUT UNICODE_STRING *Str,
  337. IN VOID *DevPath
  338. )
  339. {
  340. PCCARD_DEVICE_PATH UNALIGNED *Pccard;
  341. Pccard = DevPath;
  342. CatPrint(Str, L"Pccard(Socket%x)", Pccard->SocketNumber);
  343. }
  344. VOID
  345. _DevPathMemMap (
  346. IN OUT UNICODE_STRING *Str,
  347. IN VOID *DevPath
  348. )
  349. {
  350. MEMMAP_DEVICE_PATH UNALIGNED *MemMap;
  351. MemMap = DevPath;
  352. CatPrint(Str, L"MemMap(%d:%x-%x)",
  353. MemMap->MemoryType,
  354. MemMap->StartingAddress,
  355. MemMap->EndingAddress
  356. );
  357. }
  358. VOID
  359. _DevPathController (
  360. IN OUT UNICODE_STRING *Str,
  361. IN VOID *DevPath
  362. )
  363. {
  364. CONTROLLER_DEVICE_PATH UNALIGNED *Controller;
  365. Controller = DevPath;
  366. CatPrint(Str, L"Ctrl(%d)",
  367. Controller->Controller
  368. );
  369. }
  370. VOID
  371. _DevPathVendor (
  372. IN OUT UNICODE_STRING *Str,
  373. IN VOID *DevPath
  374. )
  375. {
  376. VENDOR_DEVICE_PATH UNALIGNED *Vendor;
  377. CHAR16 *Type;
  378. UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UNALIGNED *UnknownDevPath;
  379. EFI_GUID UnknownDevice = UNKNOWN_DEVICE_GUID;
  380. EFI_GUID VendorGuid;
  381. Vendor = DevPath;
  382. switch (DevicePathType(&Vendor->Header)) {
  383. case HARDWARE_DEVICE_PATH: Type = L"Hw"; break;
  384. case MESSAGING_DEVICE_PATH: Type = L"Msg"; break;
  385. case MEDIA_DEVICE_PATH: Type = L"Media"; break;
  386. default: Type = L"?"; break;
  387. }
  388. RtlCopyMemory( &VendorGuid, &Vendor->Guid, sizeof(EFI_GUID));
  389. CatPrint(Str, L"Ven%s(%g", Type, &VendorGuid);
  390. if (CompareGuid (&VendorGuid, &UnknownDevice) == 0) {
  391. /*
  392. * GUID used by EFI to enumerate an EDD 1.1 device
  393. */
  394. UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UNALIGNED *)Vendor;
  395. CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter);
  396. } else {
  397. CatPrint(Str, L")");
  398. }
  399. }
  400. VOID
  401. _DevPathAcpi (
  402. IN OUT UNICODE_STRING *Str,
  403. IN VOID *DevPath
  404. )
  405. {
  406. ACPI_HID_DEVICE_PATH UNALIGNED *Acpi;
  407. Acpi = DevPath;
  408. if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
  409. CatPrint(Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
  410. } else {
  411. CatPrint(Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID);
  412. }
  413. }
  414. VOID
  415. _DevPathAtapi (
  416. IN OUT UNICODE_STRING *Str,
  417. IN VOID *DevPath
  418. )
  419. {
  420. ATAPI_DEVICE_PATH UNALIGNED *Atapi;
  421. Atapi = DevPath;
  422. CatPrint(Str, L"Ata(%s,%s)",
  423. Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
  424. Atapi->SlaveMaster ? L"Slave" : L"Master"
  425. );
  426. }
  427. VOID
  428. _DevPathScsi (
  429. IN OUT UNICODE_STRING *Str,
  430. IN VOID *DevPath
  431. )
  432. {
  433. SCSI_DEVICE_PATH UNALIGNED *Scsi;
  434. Scsi = DevPath;
  435. CatPrint(Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun);
  436. }
  437. VOID
  438. _DevPathFibre (
  439. IN OUT UNICODE_STRING *Str,
  440. IN VOID *DevPath
  441. )
  442. {
  443. FIBRECHANNEL_DEVICE_PATH UNALIGNED *Fibre;
  444. Fibre = DevPath;
  445. CatPrint(Str, L"Fibre(%lx)", Fibre->WWN);
  446. }
  447. VOID
  448. _DevPath1394 (
  449. IN OUT UNICODE_STRING *Str,
  450. IN VOID *DevPath
  451. )
  452. {
  453. F1394_DEVICE_PATH UNALIGNED *F1394;
  454. F1394 = DevPath;
  455. CatPrint(Str, L"1394(%g)", &F1394->Guid);
  456. }
  457. VOID
  458. _DevPathUsb (
  459. IN OUT UNICODE_STRING *Str,
  460. IN VOID *DevPath
  461. )
  462. {
  463. USB_DEVICE_PATH UNALIGNED *Usb;
  464. Usb = DevPath;
  465. CatPrint(Str, L"Usb(%x)", Usb->Port);
  466. }
  467. VOID
  468. _DevPathI2O (
  469. IN OUT UNICODE_STRING *Str,
  470. IN VOID *DevPath
  471. )
  472. {
  473. I2O_DEVICE_PATH UNALIGNED *I2O;
  474. I2O = DevPath;
  475. CatPrint(Str, L"I2O(%x)", I2O->Tid);
  476. }
  477. VOID
  478. _DevPathMacAddr (
  479. IN OUT UNICODE_STRING *Str,
  480. IN VOID *DevPath
  481. )
  482. {
  483. MAC_ADDR_DEVICE_PATH UNALIGNED *MAC;
  484. UINTN HwAddressSize;
  485. UINTN Index;
  486. MAC = DevPath;
  487. HwAddressSize = sizeof(EFI_MAC_ADDRESS);
  488. if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
  489. HwAddressSize = 6;
  490. }
  491. CatPrint(Str, L"Mac(");
  492. for(Index = 0; Index < HwAddressSize; Index++) {
  493. CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]);
  494. }
  495. CatPrint(Str, L")");
  496. }
  497. VOID
  498. _DevPathIPv4 (
  499. IN OUT UNICODE_STRING *Str,
  500. IN VOID *DevPath
  501. )
  502. {
  503. IPv4_DEVICE_PATH UNALIGNED *IP;
  504. IP = DevPath;
  505. CatPrint(Str, L"IPv4(not-done)");
  506. }
  507. VOID
  508. _DevPathIPv6 (
  509. IN OUT UNICODE_STRING *Str,
  510. IN VOID *DevPath
  511. )
  512. {
  513. IPv6_DEVICE_PATH UNALIGNED *IP;
  514. IP = DevPath;
  515. CatPrint(Str, L"IP-v6(not-done)");
  516. }
  517. VOID
  518. _DevPathInfiniBand (
  519. IN OUT UNICODE_STRING *Str,
  520. IN VOID *DevPath
  521. )
  522. {
  523. INFINIBAND_DEVICE_PATH UNALIGNED *InfiniBand;
  524. InfiniBand = DevPath;
  525. CatPrint(Str, L"InfiniBand(not-done)");
  526. }
  527. VOID
  528. _DevPathUart (
  529. IN OUT UNICODE_STRING *Str,
  530. IN VOID *DevPath
  531. )
  532. {
  533. UART_DEVICE_PATH UNALIGNED *Uart;
  534. CHAR8 Parity;
  535. Uart = DevPath;
  536. switch (Uart->Parity) {
  537. case 0 : Parity = 'D'; break;
  538. case 1 : Parity = 'N'; break;
  539. case 2 : Parity = 'E'; break;
  540. case 3 : Parity = 'O'; break;
  541. case 4 : Parity = 'M'; break;
  542. case 5 : Parity = 'S'; break;
  543. default : Parity = 'x'; break;
  544. }
  545. if (Uart->BaudRate == 0) {
  546. CatPrint(Str, L"Uart(DEFAULT %c",Uart->BaudRate,Parity);
  547. } else {
  548. CatPrint(Str, L"Uart(%d %c",Uart->BaudRate,Parity);
  549. }
  550. if (Uart->DataBits == 0) {
  551. CatPrint(Str, L"D");
  552. } else {
  553. CatPrint(Str, L"%d",Uart->DataBits);
  554. }
  555. switch (Uart->StopBits) {
  556. case 0 : CatPrint(Str, L"D)"); break;
  557. case 1 : CatPrint(Str, L"1)"); break;
  558. case 2 : CatPrint(Str, L"1.5)"); break;
  559. case 3 : CatPrint(Str, L"2)"); break;
  560. default : CatPrint(Str, L"x)"); break;
  561. }
  562. }
  563. VOID
  564. _DevPathHardDrive (
  565. IN OUT UNICODE_STRING *Str,
  566. IN VOID *DevPath
  567. )
  568. {
  569. HARDDRIVE_DEVICE_PATH UNALIGNED *Hd;
  570. Hd = DevPath;
  571. switch (Hd->SignatureType) {
  572. case SIGNATURE_TYPE_MBR:
  573. CatPrint(Str, L"HD(Part%d,Sig%08X)",
  574. Hd->PartitionNumber,
  575. *((UINT32 *)(&(Hd->Signature[0])))
  576. );
  577. break;
  578. case SIGNATURE_TYPE_GUID:
  579. CatPrint(Str, L"HD(Part%d,Sig%g)",
  580. Hd->PartitionNumber,
  581. (EFI_GUID *) &(Hd->Signature[0])
  582. );
  583. break;
  584. default:
  585. CatPrint(Str, L"HD(Part%d,MBRType=%02x,SigType=%02x)",
  586. Hd->PartitionNumber,
  587. Hd->MBRType,
  588. Hd->SignatureType
  589. );
  590. break;
  591. }
  592. }
  593. VOID
  594. _DevPathCDROM (
  595. IN OUT UNICODE_STRING *Str,
  596. IN VOID *DevPath
  597. )
  598. {
  599. CDROM_DEVICE_PATH UNALIGNED *Cd;
  600. Cd = DevPath;
  601. CatPrint(Str, L"CDROM(Entry%x)", Cd->BootEntry);
  602. }
  603. VOID
  604. _DevPathFilePath (
  605. IN OUT UNICODE_STRING *Str,
  606. IN VOID *DevPath
  607. )
  608. {
  609. FILEPATH_DEVICE_PATH UNALIGNED *Fp;
  610. Fp = DevPath;
  611. CatPrint(Str, L"%s", Fp->PathName);
  612. }
  613. VOID
  614. _DevPathMediaProtocol (
  615. IN OUT UNICODE_STRING *Str,
  616. IN VOID *DevPath
  617. )
  618. {
  619. MEDIA_PROTOCOL_DEVICE_PATH UNALIGNED *MediaProt;
  620. MediaProt = DevPath;
  621. CatPrint(Str, L"%g", &MediaProt->Protocol);
  622. }
  623. VOID
  624. _DevPathBssBss (
  625. IN OUT UNICODE_STRING *Str,
  626. IN VOID *DevPath
  627. )
  628. {
  629. BBS_BBS_DEVICE_PATH UNALIGNED *Bss;
  630. CHAR16 *Type;
  631. Bss = DevPath;
  632. switch (Bss->DeviceType) {
  633. case BBS_TYPE_FLOPPY: Type = L"Floppy"; break;
  634. case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break;
  635. case BBS_TYPE_CDROM: Type = L"CDROM"; break;
  636. case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break;
  637. case BBS_TYPE_USB: Type = L"Usb"; break;
  638. case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break;
  639. default: Type = L"?"; break;
  640. }
  641. CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String);
  642. }
  643. VOID
  644. _DevPathEndInstance (
  645. IN OUT UNICODE_STRING *Str,
  646. IN VOID *DevPath
  647. )
  648. {
  649. CatPrint(Str, L",");
  650. }
  651. VOID
  652. _DevPathNodeUnknown (
  653. IN OUT UNICODE_STRING *Str,
  654. IN VOID *DevPath
  655. )
  656. {
  657. CatPrint(Str, L"?");
  658. }
  659. struct {
  660. UINT8 Type;
  661. UINT8 SubType;
  662. VOID (*Function)(UNICODE_STRING *, VOID *);
  663. } DevPathTable[] = {
  664. HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci,
  665. HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard,
  666. HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap,
  667. HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor,
  668. HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController,
  669. ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi,
  670. MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi,
  671. MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi,
  672. MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre,
  673. MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394,
  674. MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb,
  675. MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O,
  676. MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr,
  677. MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4,
  678. MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6,
  679. MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand,
  680. MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart,
  681. MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor,
  682. MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive,
  683. MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM,
  684. MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor,
  685. MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath,
  686. MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol,
  687. BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss,
  688. END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance,
  689. 0, 0, NULL
  690. };
  691. #define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
  692. EFI_DEVICE_PATH UNALIGNED *
  693. UnpackDevicePath (
  694. IN EFI_DEVICE_PATH UNALIGNED *DevPath
  695. )
  696. {
  697. EFI_DEVICE_PATH UNALIGNED *Src, *Dest, *NewPath;
  698. UINTN Size;
  699. /*
  700. * Walk device path and round sizes to valid boundries
  701. * */
  702. Src = DevPath;
  703. Size = 0;
  704. for (; ;) {
  705. Size += DevicePathNodeLength(Src);
  706. Size += ALIGN_SIZE(Size);
  707. if (IsDevicePathEnd(Src)) {
  708. break;
  709. }
  710. Src = NextDevicePathNode(Src);
  711. }
  712. /*
  713. * Allocate space for the unpacked path
  714. */
  715. NewPath = NULL;
  716. EfiBS->AllocatePool(
  717. EfiLoaderData,
  718. Size,
  719. (VOID **) &NewPath );
  720. if (NewPath) {
  721. RtlZeroMemory( NewPath, Size );
  722. ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0);
  723. /*
  724. * Copy each node
  725. */
  726. Src = DevPath;
  727. Dest = NewPath;
  728. for (; ;) {
  729. Size = DevicePathNodeLength(Src);
  730. RtlCopyMemory (Dest, Src, Size);
  731. Size += ALIGN_SIZE(Size);
  732. SetDevicePathNodeLength (Dest, Size);
  733. Dest->Type |= EFI_DP_TYPE_UNPACKED;
  734. Dest = (EFI_DEVICE_PATH UNALIGNED *) (((UINT8 *) Dest) + Size);
  735. if (IsDevicePathEnd(Src)) {
  736. break;
  737. }
  738. Src = NextDevicePathNode(Src);
  739. }
  740. }
  741. return NewPath;
  742. }
  743. WCHAR DbgDevicePathStringBuffer[1000];
  744. CHAR16 *
  745. DevicePathToStr (
  746. EFI_DEVICE_PATH UNALIGNED *DevPath
  747. )
  748. /*++
  749. Turns the Device Path into a printable string. Allcoates
  750. the string from pool. The caller must FreePool the returned
  751. string.
  752. --*/
  753. {
  754. UNICODE_STRING Str;
  755. EFI_DEVICE_PATH UNALIGNED *DevPathNode;
  756. VOID (*DumpNode)(UNICODE_STRING *, VOID *);
  757. UINTN Index, NewSize;
  758. RtlZeroMemory(DbgDevicePathStringBuffer, sizeof(DbgDevicePathStringBuffer));
  759. Str.Buffer= DbgDevicePathStringBuffer;
  760. Str.Length = sizeof(DbgDevicePathStringBuffer);
  761. Str.MaximumLength = sizeof(DbgDevicePathStringBuffer);
  762. /*
  763. * Unpacked the device path
  764. */
  765. DevPath = UnpackDevicePath(DevPath);
  766. ASSERT (DevPath);
  767. /*
  768. * Process each device path node
  769. * */
  770. DevPathNode = DevPath;
  771. while (!IsDevicePathEnd(DevPathNode)) {
  772. /*
  773. * Find the handler to dump this device path node
  774. */
  775. DumpNode = NULL;
  776. for (Index = 0; DevPathTable[Index].Function; Index += 1) {
  777. if (DevicePathType(DevPathNode) == DevPathTable[Index].Type &&
  778. DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) {
  779. DumpNode = DevPathTable[Index].Function;
  780. break;
  781. }
  782. }
  783. /*
  784. * If not found, use a generic function
  785. */
  786. if (!DumpNode) {
  787. DumpNode = _DevPathNodeUnknown;
  788. }
  789. /*
  790. * Put a path seperator in if needed
  791. */
  792. if (Str.Length && DumpNode != _DevPathEndInstance) {
  793. CatPrint (&Str, L"/");
  794. }
  795. /*
  796. * Print this node of the device path
  797. */
  798. DumpNode (&Str, DevPathNode);
  799. /*
  800. * Next device path node
  801. */
  802. DevPathNode = NextDevicePathNode(DevPathNode);
  803. }
  804. /*
  805. * Shrink pool used for string allocation
  806. */
  807. EfiBS->FreePool (DevPath);
  808. return Str.Buffer;
  809. }
  810. PVOID
  811. FindSMBIOSTable(
  812. UCHAR RequestedTableType
  813. )
  814. /*++
  815. Routine Description:
  816. This routine searches through the SMBIOS tables for the specified table
  817. type.
  818. Arguments:
  819. RequestedTableType - Which SMBIOS table are we looking for?
  820. Return Value:
  821. NULL - THe specified table was not found.
  822. PVOID - A pointer to the specified table.
  823. --*/
  824. {
  825. extern PVOID SMBiosTable;
  826. PUCHAR StartPtr = NULL;
  827. PUCHAR EndPtr = NULL;
  828. PSMBIOS_EPS_HEADER SMBiosEPSHeader = NULL;
  829. PDMIBIOS_EPS_HEADER DMIBiosEPSHeader = NULL;
  830. PSMBIOS_STRUCT_HEADER SMBiosHeader = NULL;
  831. if( SMBiosTable == NULL ) {
  832. return NULL;
  833. }
  834. //
  835. // Set up our search pointers.
  836. //
  837. SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)SMBiosTable;
  838. DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
  839. StartPtr = (PUCHAR)ULongToPtr(DMIBiosEPSHeader->StructureTableAddress);
  840. EndPtr = StartPtr + DMIBiosEPSHeader->StructureTableLength;
  841. if( BdDebuggerEnabled ) {
  842. DbgPrint( "FindSMBIOSTable: About to start searching for table type %d at address (%x)...\r\n",
  843. RequestedTableType,
  844. PtrToUlong(StartPtr) );
  845. }
  846. while( StartPtr < EndPtr ) {
  847. SMBiosHeader = (PSMBIOS_STRUCT_HEADER)StartPtr;
  848. if( SMBiosHeader->Type == RequestedTableType ) {
  849. // This is the table we're looking for.
  850. if( BdDebuggerEnabled ) {
  851. DbgPrint( "FindSMBIOSTable: Found requested table type %d at address %x\r\n",
  852. RequestedTableType,
  853. PtrToUlong(StartPtr) );
  854. }
  855. return (PVOID)StartPtr;
  856. } else {
  857. //
  858. // It's not him. Go to the next table.
  859. //
  860. if( BdDebuggerEnabled ) {
  861. DbgPrint( "FindSMBIOSTable: Inspected table type %d at address %x\r\n",
  862. SMBiosHeader->Type,
  863. PtrToUlong(StartPtr) );
  864. }
  865. StartPtr += SMBiosHeader->Length;
  866. //
  867. // jump over any trailing string-list that may be appeneded onto the
  868. // end of this table.
  869. //
  870. while ( (*((USHORT UNALIGNED *)StartPtr) != 0) &&
  871. (StartPtr < EndPtr) ) {
  872. StartPtr++;
  873. }
  874. StartPtr += 2;
  875. }
  876. }
  877. return NULL;
  878. }
  879. VOID
  880. EfiCheckFirmwareRevision(
  881. VOID
  882. )
  883. /*++
  884. Routine Description:
  885. This routine will retrieve the BIOS revision value then parse it to determine
  886. if the revision is new enough.
  887. If the revision is not new enough, we won't be returning from this function.
  888. Arguments:
  889. None.
  890. Return Value:
  891. None.
  892. --*/
  893. {
  894. #define FIRMWARE_MINIMUM_SOFTSUR (103)
  895. #define FIRMWARE_MINIMUM_LION (71)
  896. PUCHAR FirmwareString = NULL;
  897. PUCHAR VendorString = NULL;
  898. PUCHAR TmpPtr = NULL;
  899. ULONG FirmwareVersion = 0;
  900. ULONG FirmwareMinimum = 0;
  901. BOOLEAN IsSoftSur = FALSE;
  902. BOOLEAN IsVendorIntel = FALSE;
  903. WCHAR OutputBuffer[256];
  904. PSMBIOS_BIOS_INFORMATION_STRUCT BiosInfoHeader = NULL;
  905. ULONG i = 0;
  906. BiosInfoHeader = (PSMBIOS_BIOS_INFORMATION_STRUCT)FindSMBIOSTable( SMBIOS_BIOS_INFORMATION_TYPE );
  907. if( BiosInfoHeader ) {
  908. //
  909. // Get the firmware version string.
  910. //
  911. if( (ULONG)BiosInfoHeader->Version > 0 ) {
  912. // Jump to the end of the formatted portion of the SMBIOS table.
  913. FirmwareString = (PUCHAR)BiosInfoHeader + BiosInfoHeader->Length;
  914. //
  915. // Now jump over some number of strings to get to our string.
  916. //
  917. // This is a bit scary because we're trusting what SMBIOS
  918. // has handed us. If he gave us something bogus, then
  919. // we're about run off the end of the world looking for NULL
  920. // string terminators.
  921. //
  922. for( i = 0; i < ((ULONG)BiosInfoHeader->Version-1); i++ ) {
  923. while( *FirmwareString != 0 ) {
  924. FirmwareString++;
  925. }
  926. FirmwareString++;
  927. }
  928. //
  929. // Determine platform and firmware version.
  930. //
  931. // FirmwareString should look something like:
  932. // W460GXBS2.86E.0103B.P05.200103281759
  933. // -------- ----
  934. // | |
  935. // | ------- Firmware version
  936. // |
  937. // -------------------- Platform identifier. "W460GXBS" means softsur.
  938. // Anything else means Lion.
  939. //
  940. //
  941. if( FirmwareString ) {
  942. IsSoftSur = !strncmp( FirmwareString, "W460GXBS", 8 );
  943. // Get the minimum firmware that's okay, based on the platform.
  944. FirmwareMinimum = (IsSoftSur) ? FIRMWARE_MINIMUM_SOFTSUR : FIRMWARE_MINIMUM_LION;
  945. // Get the version.
  946. TmpPtr = strchr( FirmwareString, '.' );
  947. if( TmpPtr ) {
  948. TmpPtr++;
  949. TmpPtr = strchr( TmpPtr, '.' );
  950. if( TmpPtr ) {
  951. TmpPtr++;
  952. FirmwareVersion = strtoul( TmpPtr, NULL, 10 );
  953. #if DBG
  954. swprintf( OutputBuffer,
  955. L"EfiCheckFirmwareRevision: Successfully retrieved the Firmware String: %S\r\n",
  956. FirmwareString );
  957. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer );
  958. swprintf( OutputBuffer,
  959. L"EfiCheckFirmwareRevision: Detected platform: %S\r\n",
  960. IsSoftSur ? "Softsur" : "Lion" );
  961. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer );
  962. swprintf( OutputBuffer,
  963. L"EfiCheckFirmwareRevision: FirmwareVersion: %d\r\n",
  964. FirmwareVersion );
  965. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer );
  966. swprintf( OutputBuffer,
  967. L"EfiCheckFirmwareRevision: Minimum FirmwareVersion requirement: %d\r\n",
  968. FirmwareMinimum );
  969. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer );
  970. #endif
  971. }
  972. }
  973. }
  974. }
  975. //
  976. // Get the BIOS vendor and see if it's Intel.
  977. //
  978. if( (ULONG)BiosInfoHeader->Vendor > 0 ) {
  979. // Jump to the end of the formatted portion of the SMBIOS table.
  980. VendorString = (PUCHAR)BiosInfoHeader + BiosInfoHeader->Length;
  981. //
  982. // Now jump over some number of strings to get to our string.
  983. //
  984. for( i = 0; i < ((ULONG)BiosInfoHeader->Vendor-1); i++ ) {
  985. while( *VendorString != 0 ) {
  986. VendorString++;
  987. }
  988. VendorString++;
  989. }
  990. //
  991. // Remember firmware vendor.
  992. //
  993. if( VendorString ) {
  994. IsVendorIntel = !_strnicmp( VendorString, "INTEL", 5 );
  995. #if DBG
  996. swprintf( OutputBuffer,
  997. L"EfiCheckFirmwareRevision: Firmware Vendor String: %S\r\n",
  998. VendorString );
  999. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer );
  1000. #endif
  1001. }
  1002. }
  1003. }
  1004. if( (FirmwareVersion) &&
  1005. (IsVendorIntel) ) {
  1006. if( FirmwareVersion < FirmwareMinimum ) {
  1007. swprintf(OutputBuffer, L"Your system's firmware version is less than %d.\n\r", FirmwareMinimum);
  1008. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer);
  1009. swprintf(OutputBuffer, L"You must upgrade your system firmware in order to proceed.\n\r" );
  1010. EfiST->ConOut->OutputString(EfiST->ConOut, OutputBuffer);
  1011. while( 1 );
  1012. }
  1013. }
  1014. }