Leaked source code of windows server 2003
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.

1226 lines
38 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. helper.c
  5. Abstract:
  6. Helper functions for the loader.
  7. Author:
  8. Adam Barr (adamba) Aug 29, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. adamba 08-29-97 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include <pxe_cmn.h>
  18. #include <pxe_api.h>
  19. #include <undi_api.h>
  20. #include <ntexapi.h>
  21. #ifdef EFI
  22. #define BINL_PORT 0x0FAB // 4011 (decimal) in little-endian
  23. #else
  24. #define BINL_PORT 0xAB0F // 4011 (decimal) in big-endian
  25. #endif
  26. //
  27. // This removes macro redefinitions which appear because we define __RPC_DOS__,
  28. // but rpc.h defines __RPC_WIN32__
  29. //
  30. #pragma warning(disable:4005)
  31. //
  32. // As of 12/17/98, SECURITY_DOS is *not* defined - adamba
  33. //
  34. #if defined(SECURITY_DOS)
  35. //
  36. // These appear because we defined SECURITY_DOS
  37. //
  38. #define __far
  39. #define __pascal
  40. #define __loadds
  41. #endif
  42. #include <security.h>
  43. #include <rpc.h>
  44. #include <spseal.h>
  45. #ifdef EFI
  46. #include "bldr.h"
  47. #include "efi.h"
  48. #include "efip.h"
  49. #include "bldria64.h"
  50. #include "extern.h"
  51. extern EFI_HANDLE EfiImageHandle;
  52. #endif
  53. #if defined(SECURITY_DOS)
  54. //
  55. // PSECURITY_STRING is not supposed to be used when SECURITY_DOS is
  56. // defined -- it should be a WCHAR*. Unfortunately ntlmsp.h breaks
  57. // this rule and even uses the SECURITY_STRING structure, which there
  58. // is really no equivalent for in 16-bit mode.
  59. //
  60. typedef SEC_WCHAR * SECURITY_STRING; // more-or-less the intention where it is used
  61. typedef SEC_WCHAR * PSECURITY_STRING;
  62. #endif
  63. #include <ntlmsp.h>
  64. extern ULONG TftpSecurityHandle;
  65. extern CtxtHandle TftpClientContextHandle;
  66. extern BOOLEAN TftpClientContextHandleValid;
  67. //
  68. // From conn.c.
  69. //
  70. ULONG
  71. ConnItoa (
  72. IN ULONG Value,
  73. OUT PUCHAR Buffer
  74. );
  75. ULONG
  76. ConnSafeAtol (
  77. IN PUCHAR Buffer,
  78. IN PUCHAR BufferEnd
  79. );
  80. // for now, we pull the hack mac list and code so that we only support new ROMs
  81. #ifdef EFI
  82. #pragma pack(1)
  83. typedef struct {
  84. UINT16 VendorId;
  85. UINT16 DeviceId;
  86. UINT16 Command;
  87. UINT16 Status;
  88. UINT8 RevisionID;
  89. UINT8 ClassCode[3];
  90. UINT8 CacheLineSize;
  91. UINT8 LaytencyTimer;
  92. UINT8 HeaderType;
  93. UINT8 BIST;
  94. } PCI_DEVICE_INDEPENDENT_REGION;
  95. typedef struct {
  96. UINT32 Bar[6];
  97. UINT32 CISPtr;
  98. UINT16 SubsystemVendorID;
  99. UINT16 SubsystemID;
  100. UINT32 ExpansionRomBar;
  101. UINT32 Reserved[2];
  102. UINT8 InterruptLine;
  103. UINT8 InterruptPin;
  104. UINT8 MinGnt;
  105. UINT8 MaxLat;
  106. } PCI_DEVICE_HEADER_TYPE_REGION;
  107. typedef struct {
  108. PCI_DEVICE_INDEPENDENT_REGION Hdr;
  109. PCI_DEVICE_HEADER_TYPE_REGION Device;
  110. } PCI_TYPE00;
  111. typedef struct {
  112. UINT32 Bar[2];
  113. UINT8 PrimaryBus;
  114. UINT8 SecondaryBus;
  115. UINT8 SubordinateBus;
  116. UINT8 SecondaryLatencyTimer;
  117. UINT8 IoBase;
  118. UINT8 IoLimit;
  119. UINT16 SecondaryStatus;
  120. UINT16 MemoryBase;
  121. UINT16 MemoryLimit;
  122. UINT16 PrefetchableMemoryBase;
  123. UINT16 PrefetchableMemoryLimit;
  124. UINT32 PrefetchableBaseUpper32;
  125. UINT32 PrefetchableLimitUpper32;
  126. UINT16 IoBaseUpper16;
  127. UINT16 IoLimitUpper16;
  128. UINT32 Reserved;
  129. UINT32 ExpansionRomBAR;
  130. UINT8 InterruptLine;
  131. UINT8 InterruptPin;
  132. UINT16 BridgeControl;
  133. } PCI_BRIDGE_CONTROL_REGISTER;
  134. typedef struct {
  135. PCI_DEVICE_INDEPENDENT_REGION Hdr;
  136. PCI_BRIDGE_CONTROL_REGISTER Bridge;
  137. } PCI_TYPE01;
  138. NTSTATUS
  139. GetBusNumberFromAcpiPath(
  140. IN EFI_DEVICE_IO_INTERFACE *DeviceIo,
  141. IN UINTN UID,
  142. IN UINTN HID,
  143. OUT UINT16 *BusNumber
  144. )
  145. /*++
  146. Routine Description:
  147. Given an ACPI UID and HID, find the bus # corresponding to this data.
  148. Arguments:
  149. DeviceIo - pointer to device io interface.
  150. UID - unique id for acpi device
  151. HID - hardware id for acpi device
  152. BusNumber - receives bus # for device if found.
  153. This entire routine runs in physical mode.
  154. Return Value:
  155. STATUS_SUCCESS
  156. STATUS_UNSUCCESSFUL
  157. --*/
  158. {
  159. EFI_STATUS SegStatus = EFI_SUCCESS;
  160. EFI_STATUS BusStatus = EFI_SUCCESS;
  161. UINT32 Seg;
  162. UINT8 Bus;
  163. UINT64 PciAddress;
  164. EFI_DEVICE_PATH *PciDevicePath;
  165. EFI_DEVICE_PATH_ALIGNED DevicePathAligned;
  166. NTSTATUS ReturnCode = STATUS_UNSUCCESSFUL;
  167. //
  168. // walk through every segment and every bus looking for a bus that matches
  169. // the UID/HID that we're looking for.
  170. //
  171. for (Seg=0;!EFI_ERROR (SegStatus);Seg++) {
  172. PciAddress = Seg << 32;
  173. SegStatus = DeviceIo->PciDevicePath(DeviceIo, PciAddress, &PciDevicePath);
  174. if (!EFI_ERROR (SegStatus)) {
  175. //
  176. // Segment exists
  177. //
  178. for (Bus=0;!EFI_ERROR (BusStatus);Bus++) {
  179. PciAddress = (Seg << 32) | (Bus << 24);
  180. BusStatus = DeviceIo->PciDevicePath(DeviceIo, PciAddress, &PciDevicePath);
  181. //
  182. // Bus exists
  183. //
  184. if (!EFI_ERROR (BusStatus)) {
  185. EfiAlignDp(
  186. &DevicePathAligned,
  187. PciDevicePath,
  188. DevicePathNodeLength(PciDevicePath) );
  189. //
  190. // now see if the acpi device path for the bus matches the UID
  191. // and HID passed in.
  192. //
  193. while ( DevicePathAligned.DevPath.Type != END_DEVICE_PATH_TYPE) {
  194. if ( (DevicePathAligned.DevPath.Type == ACPI_DEVICE_PATH) &&
  195. (DevicePathAligned.DevPath.SubType == ACPI_DP)) {
  196. ACPI_HID_DEVICE_PATH *AcpiDevicePath;
  197. AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)&DevicePathAligned;
  198. if (AcpiDevicePath->UID == UID &&
  199. AcpiDevicePath->HID == HID) {
  200. //
  201. // success. return bus number.
  202. //
  203. *BusNumber = Bus;
  204. ReturnCode = STATUS_SUCCESS;
  205. goto exit;
  206. }
  207. }
  208. //
  209. // Get the next structure in our packed array.
  210. //
  211. PciDevicePath = NextDevicePathNode( PciDevicePath );
  212. EfiAlignDp(&DevicePathAligned,
  213. PciDevicePath,
  214. DevicePathNodeLength(PciDevicePath));
  215. }
  216. }
  217. }
  218. }
  219. }
  220. exit:
  221. return(ReturnCode);
  222. }
  223. NTSTATUS
  224. NetQueryCardInfo(
  225. IN OUT PNET_CARD_INFO CardInfo
  226. )
  227. /*++
  228. Routine Description:
  229. This routine queries the ROM for information about the card.
  230. Arguments:
  231. CardInfo - returns the structure defining the card.
  232. Return Value:
  233. STATUS_SUCCESS
  234. STATUS_UNSUCCESSFUL
  235. --*/
  236. {
  237. EFI_STATUS Status = EFI_UNSUPPORTED;
  238. EFI_DEVICE_PATH *DevicePath = NULL;
  239. EFI_DEVICE_PATH *OriginalRootDevicePath = NULL;
  240. EFI_DEVICE_PATH_ALIGNED DevicePathAligned;
  241. UINT16 BusNumber = 0;
  242. UINT8 DeviceNumber = 0;
  243. UINT8 FunctionNumber = 0;
  244. BOOLEAN FoundACPIDevice = FALSE;
  245. BOOLEAN FoundPCIDevice = FALSE;
  246. EFI_GUID DeviceIoProtocol = DEVICE_IO_PROTOCOL;
  247. EFI_GUID EFIPciIoProtocol = EFI_PCI_IO_PROTOCOL;
  248. EFI_HANDLE MyHandle;
  249. EFI_DEVICE_IO_INTERFACE *IoDev;
  250. EFI_LOADED_IMAGE *EfiImageInfo;
  251. EFI_PCI_IO_INTERFACE *PciIoDev;
  252. EFI_HANDLE PciIoHandle;
  253. UINT16 SegmentNumber = 0;
  254. UINTN Seg = 0;
  255. UINTN Bus = 0;
  256. UINTN Dev = 0;
  257. UINTN Func = 0;
  258. UINTN HID;
  259. UINTN UID;
  260. BOOLEAN PciIoProtocolSupported = TRUE;
  261. RtlZeroMemory(CardInfo, sizeof(NET_CARD_INFO));
  262. //
  263. // Get the image info for the loader
  264. //
  265. FlipToPhysical();
  266. Status = EfiST->BootServices->HandleProtocol (EfiImageHandle,
  267. &EfiLoadedImageProtocol,
  268. &EfiImageInfo);
  269. FlipToVirtual();
  270. if (Status != EFI_SUCCESS)
  271. {
  272. if( BdDebuggerEnabled ) {
  273. DbgPrint( "NetQueryCardInfo: HandleProtocol failed -LoadedImageProtocol (%d)\n", Status);
  274. }
  275. return (NTSTATUS)Status;
  276. }
  277. //
  278. // get the device path to the image
  279. //
  280. FlipToPhysical();
  281. Status = EfiST->BootServices->HandleProtocol (EfiImageInfo->DeviceHandle,
  282. &EfiDevicePathProtocol,
  283. &DevicePath);
  284. FlipToVirtual();
  285. if (Status != EFI_SUCCESS)
  286. {
  287. if( BdDebuggerEnabled ) {
  288. DbgPrint( "NetQueryCardInfo: HandleProtocol failed -DevicePathProtocol (%d)\n", Status);
  289. }
  290. return (NTSTATUS)Status;
  291. }
  292. FlipToPhysical();
  293. EfiAlignDp( &DevicePathAligned,
  294. DevicePath,
  295. DevicePathNodeLength(DevicePath));
  296. Status = EfiST->BootServices->LocateDevicePath ( &EFIPciIoProtocol,
  297. &DevicePath,
  298. &PciIoHandle);
  299. FlipToVirtual();
  300. //
  301. // we may be on an older system that doesn't support the pci io
  302. // protocol
  303. //
  304. if (Status != EFI_SUCCESS) {
  305. PciIoProtocolSupported = FALSE;
  306. }
  307. //
  308. // Save off this root DevicePath in case we need it later.
  309. //
  310. OriginalRootDevicePath = DevicePath;
  311. //
  312. // Now we need to read the PCI header information from the specific
  313. // card.
  314. //
  315. //
  316. // use the pci io protocol if it's supported to get the bus dev func for
  317. // the card.
  318. //
  319. if (PciIoProtocolSupported) {
  320. FlipToPhysical();
  321. Status = EfiST->BootServices->HandleProtocol (PciIoHandle,
  322. &EFIPciIoProtocol,
  323. &PciIoDev);
  324. FlipToVirtual();
  325. if (Status != EFI_SUCCESS)
  326. {
  327. if( BdDebuggerEnabled ) {
  328. DbgPrint( "NetQueryCardInfo: HandleProtocol failed -EFIPciIoProtocol (%d)\n", Status);
  329. }
  330. return (NTSTATUS)Status;
  331. }
  332. // find the location of the device - segment, bus, dev and func
  333. FlipToPhysical();
  334. Status = PciIoDev->GetLocation(PciIoDev,
  335. &Seg,
  336. &Bus,
  337. &Dev,
  338. &Func );
  339. SegmentNumber = (UINT16)Seg;
  340. BusNumber = (UINT16)Bus;
  341. DeviceNumber = (UINT8)Dev;
  342. FunctionNumber = (UINT8)Func;
  343. FlipToVirtual();
  344. if (Status != EFI_SUCCESS)
  345. {
  346. if( BdDebuggerEnabled ) {
  347. DbgPrint( "NetQueryCardInfo: EfiPciIo failed -GetLocation (%d)\n", Status);
  348. }
  349. return (NTSTATUS)Status;
  350. }
  351. FoundPCIDevice = TRUE;
  352. FoundACPIDevice = TRUE;
  353. }
  354. //
  355. // if the pci io protocol is not supported we do it the old way.
  356. // this involves walking the device path till we get to the device.
  357. // note that we make a questionable assumption here, that the UID for
  358. // the acpi device path is really the bus number. it works on some
  359. // machines, but the pci io protocol is better as it removes this
  360. // assumption.
  361. //
  362. // AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)&DevicePathAligned;
  363. // BusNumber = AcpiDevicePath->UID
  364. //
  365. // PciDevicePath = (PCI_DEVICE_PATH *)&DevicePathAligned;
  366. // DeviceNumber = PciDevicePath->Device
  367. // FunctionNumber = PciDevicePath->Function
  368. //
  369. if (!PciIoProtocolSupported) {
  370. FlipToPhysical();
  371. Status = EfiST->BootServices->LocateDevicePath ( &DeviceIoProtocol,
  372. &DevicePath,
  373. &MyHandle);
  374. if (Status != EFI_SUCCESS) {
  375. FlipToVirtual();
  376. if( BdDebuggerEnabled ) {
  377. DbgPrint( "NetQueryCardInfo: LocateDevicePath failed -IoProtocol (%d)\n", Status);
  378. }
  379. return (NTSTATUS)Status;
  380. }
  381. Status = EfiST->BootServices->HandleProtocol(
  382. MyHandle,
  383. &DeviceIoProtocol,
  384. &IoDev);
  385. if (Status != EFI_SUCCESS) {
  386. FlipToVirtual();
  387. if( BdDebuggerEnabled ) {
  388. DbgPrint( "NetQueryCardInfo: HandleProtocol failed -IoProtocol (%d)\n", Status);
  389. }
  390. return (NTSTATUS)Status;
  391. }
  392. while( DevicePathAligned.DevPath.Type != END_DEVICE_PATH_TYPE) {
  393. if( (DevicePathAligned.DevPath.Type == ACPI_DEVICE_PATH) &&
  394. (DevicePathAligned.DevPath.SubType == ACPI_DP) &&
  395. (FoundACPIDevice == FALSE)) {
  396. //
  397. // We'll find the BusNumber here.
  398. //
  399. ACPI_HID_DEVICE_PATH *AcpiDevicePath;
  400. AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)&DevicePathAligned;
  401. UID = AcpiDevicePath->UID;
  402. HID = AcpiDevicePath->HID;
  403. Status = (NTSTATUS)GetBusNumberFromAcpiPath(IoDev, UID,HID, &BusNumber);
  404. FoundACPIDevice = TRUE;
  405. if (! NT_SUCCESS(Status)) {
  406. FlipToVirtual();
  407. if (BdDebuggerEnabled) {
  408. DbgPrint( "NetQueryCardInfo: GetBusNumberFromAcpiPath failed (%x)\n", Status);
  409. }
  410. Status = ENODEV;
  411. return (NTSTATUS)Status;
  412. }
  413. }
  414. if( (DevicePathAligned.DevPath.Type == HARDWARE_DEVICE_PATH) &&
  415. (DevicePathAligned.DevPath.SubType == HW_PCI_DP) ) {
  416. //
  417. // We'll find DeviceNumber and FunctionNumber here.
  418. //
  419. PCI_DEVICE_PATH *PciDevicePath;
  420. if ( FoundPCIDevice ) {
  421. //
  422. // we have already found a PCI device. that device must have
  423. // been a bridge. we must find the new bus # on the downstream
  424. // side of the bridge
  425. //
  426. UINT64 BridgeAddress;
  427. PCI_TYPE01 PciBridge;
  428. EFI_DEVICE_PATH *BridgeDevicePath;
  429. //
  430. // Get a Handle for the device
  431. //
  432. BridgeDevicePath = OriginalRootDevicePath;
  433. Status = EfiST->BootServices->LocateDevicePath( &DeviceIoProtocol,
  434. &BridgeDevicePath,
  435. &MyHandle );
  436. if( Status != EFI_SUCCESS ) {
  437. FlipToVirtual();
  438. if (BdDebuggerEnabled) {
  439. DbgPrint( "NetQueryCardInfo: LocateDevicePath(bridge) failed (%x)\n", Status);
  440. }
  441. return (NTSTATUS)Status;
  442. }
  443. Status = EfiST->BootServices->HandleProtocol( MyHandle,
  444. &DeviceIoProtocol,
  445. (VOID*)&IoDev );
  446. if( Status != EFI_SUCCESS ) {
  447. FlipToVirtual();
  448. if (BdDebuggerEnabled) {
  449. DbgPrint( "NetQueryCardInfo: HandleProtocol(bridge) failed (%X)\n", Status);
  450. }
  451. return (NTSTATUS)Status;
  452. }
  453. //
  454. // Generate the address, then read the PCI header from the device.
  455. //
  456. BridgeAddress = EFI_PCI_ADDRESS( BusNumber, DeviceNumber, FunctionNumber );
  457. RtlZeroMemory(&PciBridge, sizeof(PCI_TYPE01));
  458. Status = IoDev->Pci.Read( IoDev,
  459. IO_UINT32,
  460. BridgeAddress,
  461. sizeof(PCI_TYPE01) / sizeof(UINT32),
  462. &PciBridge );
  463. if( Status != EFI_SUCCESS ) {
  464. FlipToVirtual();
  465. if (BdDebuggerEnabled) {
  466. DbgPrint( "NetQueryCardInfo: Pci.Read(bridge) failed (%X)\r\n", Status);
  467. }
  468. return (NTSTATUS)Status;
  469. }
  470. //
  471. // Bridges are requred to store 3 registers. the PrimaryBus, SecondaryBus and
  472. // SubordinateBus. The PrimaryBus is the Bus number on the upstream side of
  473. // the bridge. The SecondaryBus is the Bus number on the downstream side
  474. // and the SubordinateBus is the greatest bus number that can be reached through
  475. // the particular bus. we simply want to change BusNumber to the SecondaryBus
  476. //
  477. BusNumber = (UINT16) PciBridge.Bridge.SecondaryBus;
  478. }
  479. PciDevicePath = (PCI_DEVICE_PATH *)&DevicePathAligned;
  480. DeviceNumber = PciDevicePath->Device;
  481. FunctionNumber = PciDevicePath->Function;
  482. FoundPCIDevice = TRUE;
  483. }
  484. //
  485. // Get the next structure in our packed array.
  486. //
  487. DevicePath = NextDevicePathNode( DevicePath );
  488. EfiAlignDp(&DevicePathAligned,
  489. DevicePath,
  490. DevicePathNodeLength(DevicePath));
  491. }
  492. FlipToVirtual();
  493. }
  494. //
  495. // Derive the function pointer that will allow us to read from
  496. // PCI space.
  497. //
  498. DevicePath = OriginalRootDevicePath;
  499. FlipToPhysical();
  500. Status = EfiST->BootServices->LocateDevicePath( &DeviceIoProtocol,
  501. &DevicePath,
  502. &MyHandle );
  503. FlipToVirtual();
  504. if( Status != EFI_SUCCESS ) {
  505. if (BdDebuggerEnabled) {
  506. DbgPrint( "NetQueryCardInfo: LocateDevicePath failed (%X)\n", Status);
  507. }
  508. return (NTSTATUS)Status;
  509. }
  510. FlipToPhysical();
  511. Status = EfiST->BootServices->HandleProtocol( MyHandle,
  512. &DeviceIoProtocol,
  513. (VOID*)&IoDev );
  514. FlipToVirtual();
  515. if( Status != EFI_SUCCESS ) {
  516. if (BdDebuggerEnabled) {
  517. DbgPrint( "NetQueryCardInfo: HandleProtocol(2) failed (%X)\n", Status);
  518. }
  519. return (NTSTATUS)Status;
  520. }
  521. //
  522. // We've got the Bus, Device, and Function number for this device. Go read
  523. // his header (with the PCI-Read function that we just derived) and get
  524. // the information we're after.
  525. //
  526. if( FoundPCIDevice && FoundACPIDevice ) {
  527. UINT64 Address;
  528. PCI_TYPE00 Pci;
  529. if (BdDebuggerEnabled) {
  530. DbgPrint( "NetQueryCardInfo: Found all the config info for the device.\n" );
  531. DbgPrint( " BusNumber: %d DeviceNumber: %d FunctionNumber: %d\n", BusNumber, DeviceNumber, FunctionNumber );
  532. }
  533. //
  534. // Generate the address, then read the PCI header from the device.
  535. //
  536. Address = EFI_PCI_ADDRESS( BusNumber, DeviceNumber, FunctionNumber );
  537. RtlZeroMemory(&Pci, sizeof(PCI_TYPE00));
  538. FlipToPhysical();
  539. Status = IoDev->Pci.Read( IoDev,
  540. IO_UINT32,
  541. Address,
  542. sizeof(PCI_TYPE00) / sizeof(UINT32),
  543. &Pci );
  544. FlipToVirtual();
  545. if( Status != EFI_SUCCESS ) {
  546. if (BdDebuggerEnabled) {
  547. DbgPrint( "NetQueryCardInfo: Pci.Read failed (%X)\n", Status);
  548. }
  549. return (NTSTATUS)Status;
  550. }
  551. //
  552. // It all worked. Copy the information from the device into
  553. // the CardInfo structure and exit.
  554. //
  555. CardInfo->NicType = 2; // He's PCI
  556. CardInfo->pci.Vendor_ID = Pci.Hdr.VendorId;
  557. CardInfo->pci.Dev_ID = Pci.Hdr.DeviceId;
  558. CardInfo->pci.Rev = Pci.Hdr.RevisionID;
  559. // BusDevFunc is defined as 16 bits built as follows:
  560. // 15-8 --------------------------- Bus Number
  561. // 7-3 ----------------------- Device Number
  562. // 2-0 ------------------- Function Number
  563. CardInfo->pci.BusDevFunc = ((BusNumber & 0xFF) << 8);
  564. CardInfo->pci.BusDevFunc |= ((DeviceNumber & 0x1F) << 3);
  565. CardInfo->pci.BusDevFunc |= (FunctionNumber & 0x7);
  566. // SubSys_ID is actually ((SubsystemID << 16) | SubsystemVendorID)
  567. CardInfo->pci.Subsys_ID = Pci.Device.SubsystemID;
  568. CardInfo->pci.Subsys_ID = (CardInfo->pci.Subsys_ID << 16) | (Pci.Device.SubsystemVendorID);
  569. #if DBG
  570. if (BdDebuggerEnabled) {
  571. DbgPrint( "\n" );
  572. DbgPrint( "NetQueryCardInfo: Pci.Hdr.VendorId %x\n", Pci.Hdr.VendorId );
  573. DbgPrint( " Pci.Hdr.DeviceId %x\n", Pci.Hdr.DeviceId );
  574. DbgPrint( " Pci.Hdr.Command %x\n", Pci.Hdr.Command );
  575. DbgPrint( " Pci.Hdr.Status %x\n", Pci.Hdr.Status );
  576. DbgPrint( " Pci.Hdr.RevisionID %x\n", Pci.Hdr.RevisionID );
  577. DbgPrint( " Pci.Hdr.HeaderType %x\n", Pci.Hdr.HeaderType );
  578. DbgPrint( " Pci.Hdr.BIST %x\n", Pci.Hdr.BIST );
  579. DbgPrint( " Pci.Device.SubsystemVendorID %x\n", Pci.Device.SubsystemVendorID );
  580. DbgPrint( " Pci.Device.SubsystemID %x\n", Pci.Device.SubsystemID );
  581. DbgPrint( "\n" );
  582. DbgPrint( "NetQueryCardInfo: CardInfo->NicType %x\n", CardInfo->NicType );
  583. DbgPrint( " CardInfo->pci.Vendor_ID %x\n", CardInfo->pci.Vendor_ID );
  584. DbgPrint( " CardInfo->pci.Dev_ID %x\n", CardInfo->pci.Dev_ID );
  585. DbgPrint( " CardInfo->pci.Rev %x\n", CardInfo->pci.Rev );
  586. DbgPrint( " CardInfo->pci.Subsys_ID %x\n", CardInfo->pci.Subsys_ID );
  587. DbgPrint( "\n" );
  588. }
  589. #endif
  590. Status = STATUS_SUCCESS;
  591. } else {
  592. if (BdDebuggerEnabled) {
  593. DbgPrint( "NetQueryCardInfo: Failed to find all the config info for the device.\n" );
  594. }
  595. Status = STATUS_UNSUCCESSFUL;
  596. }
  597. return (NTSTATUS)Status;
  598. }
  599. #else
  600. NTSTATUS
  601. NetQueryCardInfo(
  602. IN OUT PNET_CARD_INFO CardInfo
  603. )
  604. /*++
  605. Routine Description:
  606. This routine queries the ROM for information about the card.
  607. Arguments:
  608. CardInfo - returns the structure defining the card.
  609. Return Value:
  610. STATUS_SUCCESS
  611. STATUS_UNSUCCESSFUL
  612. --*/
  613. {
  614. ULONG status;
  615. t_PXENV_UNDI_GET_NIC_TYPE nicType;
  616. RtlZeroMemory(CardInfo, sizeof(NET_CARD_INFO));
  617. status = RomGetNicType( &nicType );
  618. if ((status != PXENV_EXIT_SUCCESS) || (nicType.Status != PXENV_EXIT_SUCCESS)) {
  619. #if DBG
  620. DbgPrint( "RomGetNicType returned 0x%x, nicType.Status = 0x%x. Time to upgrade your netcard ROM\n",
  621. status, nicType.Status );
  622. #endif
  623. status = STATUS_UNSUCCESSFUL;
  624. } else {
  625. #if DBG
  626. if ( nicType.NicType == 2 ) {
  627. DbgPrint( "Vendor_ID: %04x, Dev_ID: %04x\n",
  628. nicType.pci_pnp_info.pci.Vendor_ID,
  629. nicType.pci_pnp_info.pci.Dev_ID );
  630. DbgPrint( "Base_Class: %02x, Sub_Class: %02x, Prog_Intf: %02x\n",
  631. nicType.pci_pnp_info.pci.Base_Class,
  632. nicType.pci_pnp_info.pci.Sub_Class,
  633. nicType.pci_pnp_info.pci.Prog_Intf );
  634. DbgPrint( "Rev: %02x, BusDevFunc: %04x, SubSystem: %04x\n",
  635. nicType.pci_pnp_info.pci.Rev,
  636. nicType.pci_pnp_info.pci.BusDevFunc,
  637. nicType.pci_pnp_info.pci.Subsys_ID );
  638. } else {
  639. DbgPrint( "NicType: 0x%x EISA_Dev_ID: %08x\n",
  640. nicType.NicType,
  641. nicType.pci_pnp_info.pnp.EISA_Dev_ID );
  642. DbgPrint( "Base_Class: %02x, Sub_Class: %02x, Prog_Intf: %02x\n",
  643. nicType.pci_pnp_info.pnp.Base_Class,
  644. nicType.pci_pnp_info.pnp.Sub_Class,
  645. nicType.pci_pnp_info.pnp.Prog_Intf );
  646. DbgPrint( "CardSelNum: %04x\n",
  647. nicType.pci_pnp_info.pnp.CardSelNum );
  648. }
  649. #endif
  650. //
  651. // The call worked, so copy the information.
  652. //
  653. CardInfo->NicType = nicType.NicType;
  654. if (nicType.NicType == 2) {
  655. CardInfo->pci.Vendor_ID = nicType.pci_pnp_info.pci.Vendor_ID;
  656. CardInfo->pci.Dev_ID = nicType.pci_pnp_info.pci.Dev_ID;
  657. CardInfo->pci.Base_Class = nicType.pci_pnp_info.pci.Base_Class;
  658. CardInfo->pci.Sub_Class = nicType.pci_pnp_info.pci.Sub_Class;
  659. CardInfo->pci.Prog_Intf = nicType.pci_pnp_info.pci.Prog_Intf;
  660. CardInfo->pci.Rev = nicType.pci_pnp_info.pci.Rev;
  661. CardInfo->pci.BusDevFunc = nicType.pci_pnp_info.pci.BusDevFunc;
  662. CardInfo->pci.Subsys_ID = nicType.pci_pnp_info.pci.Subsys_ID;
  663. status = STATUS_SUCCESS;
  664. } else {
  665. status = STATUS_UNSUCCESSFUL;
  666. }
  667. }
  668. return status;
  669. }
  670. #endif // EFI
  671. NTSTATUS
  672. UdpSendAndReceiveForNetQuery(
  673. IN PVOID SendBuffer,
  674. IN ULONG SendBufferLength,
  675. IN ULONG SendRemoteHost,
  676. IN USHORT SendRemotePort,
  677. IN ULONG SendRetryCount,
  678. IN PVOID ReceiveBuffer,
  679. IN ULONG ReceiveBufferLength,
  680. IN ULONG ReceiveTimeout,
  681. IN ULONG ReceiveSignatureCount,
  682. IN PCHAR ReceiveSignatures[]
  683. )
  684. {
  685. ULONG i, j;
  686. ULONG length;
  687. ULONG RemoteHost;
  688. USHORT RemotePort;
  689. //
  690. // Try sending the packet SendRetryCount times, until we receive
  691. // a response with the right signature, waiting ReceiveTimeout
  692. // each time.
  693. //
  694. for (i = 0; i < SendRetryCount; i++) {
  695. length = UdpSend(
  696. SendBuffer,
  697. SendBufferLength,
  698. SendRemoteHost,
  699. SendRemotePort);
  700. if ( length != SendBufferLength ) {
  701. DbgPrint("UdpSend only sent %d bytes, not %d\n", length, SendBufferLength);
  702. return STATUS_UNEXPECTED_NETWORK_ERROR;
  703. }
  704. ReReceive:
  705. //
  706. // NULL out the first 12 bytes in case we get shorter data.
  707. //
  708. memset(ReceiveBuffer, 0x0, 12);
  709. length = UdpReceive(
  710. ReceiveBuffer,
  711. ReceiveBufferLength,
  712. &RemoteHost,
  713. &RemotePort,
  714. ReceiveTimeout);
  715. if ( length == 0 ) {
  716. DPRINT( ERROR, ("UdpReceive timed out\n") );
  717. continue;
  718. }
  719. //
  720. // Make sure the signature is one of the ones we expect.
  721. //
  722. for (j = 0; j < ReceiveSignatureCount; j++) {
  723. if (memcmp(ReceiveBuffer, ReceiveSignatures[j], 4) == 0) {
  724. return STATUS_SUCCESS;
  725. }
  726. }
  727. DbgPrint("UdpReceive got wrong signature\n");
  728. // ISSUE NTRAID #60513: CLEAN THIS UP -- but the idea is not to UdpSend
  729. // again just because we got a bad signature. Still need to respect the
  730. // original ReceiveTimeout however!
  731. goto ReReceive;
  732. }
  733. //
  734. // We timed out.
  735. //
  736. return STATUS_IO_TIMEOUT;
  737. }
  738. #define NETCARD_REQUEST_RESPONSE_BUFFER_SIZE 4096
  739. NTSTATUS
  740. NetQueryDriverInfo(
  741. IN PNET_CARD_INFO CardInfo,
  742. IN PCHAR SetupPath,
  743. IN PCHAR NtBootPathName,
  744. IN OUT PWCHAR HardwareId,
  745. IN ULONG HardwareIdLength,
  746. IN OUT PWCHAR DriverName,
  747. IN OUT PCHAR DriverNameAnsi OPTIONAL,
  748. IN ULONG DriverNameLength,
  749. IN OUT PWCHAR ServiceName,
  750. IN ULONG ServiceNameLength,
  751. OUT PCHAR * Registry,
  752. OUT ULONG * RegistryLength
  753. )
  754. /*++
  755. Routine Description:
  756. This routine does an exchange with the server to get information
  757. about the card described by CardInfo.
  758. Arguments:
  759. CardInfo - Information about the card.
  760. SetupPath - UNC path (with only a single leading backslash) to our setup directory
  761. NtBootPathName - UNC path (with only a single leading backslash) to our boot directory
  762. HardwareId - returns the hardware ID of the card.
  763. HardwareIdLength - the length (in bytes) of the passed-in HardwareId buffer.
  764. DriverName - returns the name of the driver.
  765. DriverNameAnsi - if present, returns the name of the driver in ANSI.
  766. DriverNameLength - the length (in bytes) of the passed-in DriverName buffer
  767. (it is assumed that DriverNameAnsi is at least half this length).
  768. ServiceName - returns the service key of the driver.
  769. ServiceNameLength - the length (in bytes) of the passed-in ServiceName buffer.
  770. Registry - if needed, allocates and returns extra registry parameters
  771. for the card.
  772. RegistryLength - the length of Registry.
  773. Return Value:
  774. STATUS_SUCCESS
  775. STATUS_BUFFER_OVERFLOW if either of the buffers are too small.
  776. STATUS_INSUFFICIENT_RESOURCES if we cannot allocate memory for Registry.
  777. STATUS_IO_TIMEOUT if we can't get a response from the server.
  778. --*/
  779. {
  780. NTSTATUS Status;
  781. USHORT localPort;
  782. PNETCARD_REQUEST_PACKET requestPacket;
  783. PCHAR ReceiveSignatures[2];
  784. PCHAR ReceiveBuffer;
  785. ULONG GuidLength;
  786. PUCHAR Guid;
  787. ULONG sendSize;
  788. PNETCARD_REQUEST_PACKET allocatedRequestPacket = NULL;
  789. ARC_STATUS ArcStatus;
  790. //
  791. // Get the local UDP port.
  792. //
  793. localPort = UdpUnicastDestinationPort;
  794. //
  795. // Construct the outgoing packet. Also allocate memory for
  796. // the receive packet.
  797. //
  798. sendSize = sizeof(NETCARD_REQUEST_PACKET) +
  799. ((SetupPath) ? (strlen(SetupPath) + 1) : 0);
  800. requestPacket = BlAllocateHeap( sendSize );
  801. if (requestPacket == NULL) {
  802. Status = STATUS_BUFFER_OVERFLOW;
  803. goto done;
  804. }
  805. ReceiveBuffer = BlAllocateHeap( NETCARD_REQUEST_RESPONSE_BUFFER_SIZE );
  806. if (ReceiveBuffer == NULL) {
  807. Status = STATUS_BUFFER_OVERFLOW;
  808. goto done;
  809. }
  810. RtlCopyMemory(requestPacket->Signature, NetcardRequestSignature, sizeof(requestPacket->Signature));
  811. requestPacket->Length = sizeof(NETCARD_REQUEST_PACKET) - FIELD_OFFSET(NETCARD_REQUEST_PACKET, Version);
  812. requestPacket->Version = OSCPKT_NETCARD_REQUEST_VERSION;
  813. #if defined(_IA64_)
  814. requestPacket->Architecture = PROCESSOR_ARCHITECTURE_IA64;
  815. #endif
  816. #if defined(_X86_)
  817. requestPacket->Architecture = PROCESSOR_ARCHITECTURE_INTEL;
  818. #endif
  819. requestPacket->SetupDirectoryLength = SetupPath ? (strlen( SetupPath ) + 1) : 0;
  820. if (requestPacket->SetupDirectoryLength) {
  821. requestPacket->SetupDirectoryPath[0] = '\\';
  822. strcpy( &requestPacket->SetupDirectoryPath[1], SetupPath );
  823. }
  824. ArcStatus = GetGuid(&Guid, &GuidLength);
  825. if (ArcStatus != ESUCCESS) {
  826. //
  827. // normalize the error and exit.
  828. //
  829. switch (ArcStatus) {
  830. case ENOMEM:
  831. Status = STATUS_NO_MEMORY;
  832. goto done;
  833. break;
  834. case ENODEV:
  835. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  836. goto done;
  837. break;
  838. default:
  839. Status = STATUS_UNSUCCESSFUL;
  840. goto done;
  841. break;
  842. }
  843. }
  844. if (GuidLength == sizeof(requestPacket->Guid)) {
  845. memcpy(requestPacket->Guid, Guid, GuidLength);
  846. }
  847. RtlCopyMemory(&requestPacket->CardInfo, CardInfo, sizeof(NET_CARD_INFO));
  848. ReceiveSignatures[0] = NetcardResponseSignature;
  849. ReceiveSignatures[1] = NetcardErrorSignature;
  850. Status = UdpSendAndReceiveForNetQuery(
  851. requestPacket,
  852. sendSize,
  853. NetServerIpAddress,
  854. BINL_PORT,
  855. 100, // retry count
  856. ReceiveBuffer,
  857. NETCARD_REQUEST_RESPONSE_BUFFER_SIZE,
  858. 60, // receive timeout... may have to parse INF files
  859. 2,
  860. ReceiveSignatures
  861. );
  862. if (Status == STATUS_SUCCESS) {
  863. PWCHAR stringInPacket;
  864. ULONG maxOffset;
  865. UNICODE_STRING uString;
  866. ULONG len;
  867. PNETCARD_RESPONSE_PACKET responsePacket;
  868. responsePacket = (PNETCARD_RESPONSE_PACKET)ReceiveBuffer;
  869. if (responsePacket->Status != STATUS_SUCCESS) {
  870. Status = responsePacket->Status;
  871. goto done;
  872. }
  873. if (responsePacket->Length < sizeof( NETCARD_RESPONSE_PACKET )) {
  874. Status = STATUS_UNSUCCESSFUL;
  875. goto done;
  876. }
  877. //
  878. // The exchange succeeded, so copy the results back.
  879. //
  880. maxOffset = NETCARD_REQUEST_RESPONSE_BUFFER_SIZE -
  881. sizeof( NETCARD_RESPONSE_PACKET );
  882. if (responsePacket->HardwareIdOffset < sizeof(NETCARD_RESPONSE_PACKET) ||
  883. responsePacket->HardwareIdOffset >= maxOffset ) {
  884. Status = STATUS_BUFFER_OVERFLOW;
  885. goto done;
  886. }
  887. //
  888. // pick up the hardwareId string. It's given to us as an offset
  889. // within the packet to a unicode null terminated string.
  890. //
  891. stringInPacket = (PWCHAR)(PCHAR)((PCHAR)responsePacket +
  892. responsePacket->HardwareIdOffset );
  893. RtlInitUnicodeString( &uString, stringInPacket );
  894. if (uString.Length + sizeof(WCHAR) > HardwareIdLength) {
  895. Status = STATUS_BUFFER_OVERFLOW;
  896. goto done;
  897. }
  898. RtlCopyMemory( HardwareId, uString.Buffer, uString.Length + sizeof(WCHAR));
  899. //
  900. // pick up the driverName string. It's given to us as an offset
  901. // within the packet to a unicode null terminated string.
  902. //
  903. stringInPacket = (PWCHAR)(PCHAR)((PCHAR)responsePacket +
  904. responsePacket->DriverNameOffset );
  905. RtlInitUnicodeString( &uString, stringInPacket );
  906. if (uString.Length + sizeof(WCHAR) > DriverNameLength) {
  907. Status = STATUS_BUFFER_OVERFLOW;
  908. goto done;
  909. }
  910. RtlCopyMemory( DriverName, uString.Buffer, uString.Length + sizeof(WCHAR));
  911. //
  912. // we convert this one into ansi if the caller requested
  913. //
  914. if (ARGUMENT_PRESENT(DriverNameAnsi)) {
  915. RtlUnicodeToMultiByteN( DriverNameAnsi,
  916. DriverNameLength,
  917. NULL,
  918. uString.Buffer,
  919. uString.Length + sizeof(WCHAR));
  920. }
  921. //
  922. // pick up the serviceName string. It's given to us as an offset
  923. // within the packet to a unicode null terminated string.
  924. //
  925. stringInPacket = (PWCHAR)(PCHAR)((PCHAR)responsePacket +
  926. responsePacket->ServiceNameOffset );
  927. RtlInitUnicodeString( &uString, stringInPacket );
  928. if (uString.Length + sizeof(WCHAR) > ServiceNameLength) {
  929. Status = STATUS_BUFFER_OVERFLOW;
  930. goto done;
  931. }
  932. RtlCopyMemory( ServiceName, uString.Buffer, uString.Length + sizeof(WCHAR));
  933. //
  934. // If any extra registry params were passed back, allocate/copy those.
  935. //
  936. *RegistryLength = responsePacket->RegistryLength;
  937. if (*RegistryLength) {
  938. *Registry = BlAllocateHeap(*RegistryLength);
  939. if (*Registry == NULL) {
  940. Status = STATUS_INSUFFICIENT_RESOURCES;
  941. goto done;
  942. }
  943. stringInPacket = (PWCHAR)(PCHAR)((PCHAR)responsePacket +
  944. responsePacket->RegistryOffset );
  945. RtlCopyMemory(*Registry, stringInPacket, *RegistryLength);
  946. } else {
  947. *Registry = NULL;
  948. }
  949. }
  950. done:
  951. if (requestPacket) {
  952. //
  953. // we would free this memory
  954. // if the loader had a free routine
  955. //
  956. // free(requestPacket);
  957. }
  958. return Status;
  959. }