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.

475 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. rom.c
  5. Abstract:
  6. Boot loader ROM routines.
  7. Author:
  8. Chuck Lenzmeier (chuckl) December 27, 1996
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <bldrx86.h>
  15. #define PhysToSeg(x) (USHORT)((ULONG)(x) >> 4) & 0xffff
  16. #define PhysToOff(x) (USHORT)((ULONG)(x) & 0x0f)
  17. #include <pxe_cmn.h>
  18. #include <pxe_api.h>
  19. #include <tftp_api.h>
  20. #include <udp_api.h>
  21. #include <undi_api.h>
  22. #include <dhcp.h>
  23. #include <pxe.h>
  24. USHORT NetUnicastUdpDestinationPort = 0;
  25. #if 0
  26. USHORT NetMulticastUdpDestinationPort;
  27. ULONG NetMulticastUdpDestinationAddress;
  28. USHORT NetMulticastUdpSourcePort;
  29. ULONG NetMulticastUdpSourceAddress;
  30. #endif
  31. #if 0 && DBG
  32. #include <stdio.h>
  33. VOID
  34. RomDumpRawData (
  35. IN PUCHAR DataStart,
  36. IN ULONG DataLength,
  37. IN ULONG Offset
  38. );
  39. ULONG RomMaxDumpLength = 64;
  40. #endif
  41. #if 0
  42. //
  43. // chuckl: Don't do this. We added it as part of a solution a problem
  44. // with DEC cards and the boot floppy. We disabled broadcasts in
  45. // startrom\i386\main.c so that the card wouldn't overflow and lock up,
  46. // but we need to have broadcasts enabled in case the server needs to
  47. // ARP us. The purpose of this routine is to enable/disable broadcasts
  48. // during the receive loop, but that seems to put Compaq cards to sleep.
  49. // So we need to leave broadcasts enabled all the time. The DEC card
  50. // problem will have to be fixed another way.
  51. //
  52. VOID
  53. RomSetBroadcastStatus(
  54. BOOLEAN Enable
  55. )
  56. {
  57. t_PXENV_UNDI_SET_PACKET_FILTER UndiSetPF;
  58. USHORT status;
  59. UndiSetPF.Status = 0;
  60. if (Enable) {
  61. UndiSetPF.filter = FLTR_DIRECTED | FLTR_BRDCST;
  62. } else {
  63. UndiSetPF.filter = FLTR_DIRECTED;
  64. }
  65. status = NETPC_ROM_SERVICES( PXENV_UNDI_SET_PACKET_FILTER, &UndiSetPF );
  66. if ((status != 0) || (UndiSetPF.Status != 0)) {
  67. DPRINT( ERROR, ("RomSetBroadcastStatus: set packet filter failed %lx, %lx\n", status, UndiSetPF.Status ));
  68. }
  69. }
  70. #endif
  71. VOID
  72. RomSetReceiveStatus (
  73. IN USHORT UnicastUdpDestinationPort
  74. #if 0
  75. ,
  76. IN USHORT MulticastUdpDestinationPort,
  77. IN ULONG MulticastUdpDestinationAddress,
  78. IN USHORT MulticastUdpSourcePort,
  79. IN ULONG MulticastUdpSourceAddress
  80. #endif
  81. )
  82. {
  83. USHORT status;
  84. PUCHAR multicastAddress;
  85. union {
  86. t_PXENV_UDP_OPEN UdpOpen;
  87. t_PXENV_UNDI_SHUTDOWN UndiShutdown;
  88. } command;
  89. if ( UnicastUdpDestinationPort != 0 ) {
  90. //
  91. // If we haven't opened UDP in the ROM yet, do so now.
  92. //
  93. if ( NetUnicastUdpDestinationPort == 0 ) {
  94. command.UdpOpen.Status = 0;
  95. *(UINT32 *)command.UdpOpen.SrcIp = 0;
  96. status = NETPC_ROM_SERVICES( PXENV_UDP_OPEN, &command );
  97. if ( status != 0 ) {
  98. DPRINT( ERROR, ("RomSetReceiveStatus: error %d from UDP_OPEN\n", status) );
  99. }
  100. }
  101. NetUnicastUdpDestinationPort = UnicastUdpDestinationPort;
  102. #if 0
  103. NetMulticastUdpDestinationPort = MulticastUdpDestinationPort;
  104. NetMulticastUdpDestinationAddress = MulticastUdpDestinationAddress;
  105. NetMulticastUdpSourceAddress = MulticastUdpSourceAddress;
  106. NetMulticastUdpSourceAddress = MulticastUdpSourceAddress;
  107. #endif
  108. } else {
  109. //
  110. // This is a loader shutdown notification. Shut the NIC down.
  111. //
  112. // NB: This is irreversible!
  113. //
  114. command.UndiShutdown.Status = 0;
  115. status = NETPC_ROM_SERVICES( PXENV_UNDI_SHUTDOWN, &command );
  116. }
  117. return;
  118. } // RomSetReceiveStatus
  119. ULONG
  120. RomSendUdpPacket (
  121. IN PVOID Buffer,
  122. IN ULONG Length,
  123. IN ULONG RemoteHost,
  124. IN USHORT RemotePort
  125. )
  126. {
  127. USHORT status;
  128. t_PXENV_UDP_WRITE command;
  129. UCHAR tmpBuffer[MAXIMUM_TFTP_PACKET_LENGTH];
  130. #if 0 && DBG
  131. DPRINT( SEND_RECEIVE, ("RomSendUdpPacket: sending this packet:\n") );
  132. IF_DEBUG(SEND_RECEIVE) {
  133. RomDumpRawData( Buffer, Length, 0 );
  134. }
  135. #endif
  136. Length = ( MAXIMUM_TFTP_PACKET_LENGTH < Length ) ? MAXIMUM_TFTP_PACKET_LENGTH : Length;
  137. RtlCopyMemory( tmpBuffer, Buffer, Length );
  138. command.Status = 0;
  139. //
  140. // Determine whether we need to send via the gateway.
  141. //
  142. if ( (RemoteHost & NetLocalSubnetMask) == (NetLocalIpAddress & NetLocalSubnetMask) ) {
  143. *(UINT32 *)command.GatewayIp = 0;
  144. } else {
  145. *(UINT32 *)command.GatewayIp = NetGatewayIpAddress;
  146. }
  147. *(UINT32 *)command.DestIp = RemoteHost;
  148. command.DestPort = RemotePort;
  149. command.SrcPort = NetUnicastUdpDestinationPort;
  150. command.BufferSize = (USHORT)Length;
  151. command.BufferOffset = PhysToOff(tmpBuffer);
  152. command.BufferSegment = PhysToSeg(tmpBuffer);
  153. //DbgPrint( "UDP write pktaddr %lx = %x:%x\n", tmpBuffer, command.BufferSegment, command.BufferOffset );
  154. status = NETPC_ROM_SERVICES( PXENV_UDP_WRITE, &command );
  155. //DbgPrint( "UDP write status = %x\n", command.Status );
  156. if ( status == 0 ) {
  157. return Length;
  158. } else {
  159. return 0;
  160. }
  161. } // RomSendUdpPacket
  162. ULONG
  163. RomReceiveUdpPacket (
  164. IN PVOID Buffer,
  165. IN ULONG Length,
  166. IN ULONG Timeout,
  167. OUT PULONG RemoteHost,
  168. OUT PUSHORT RemotePort
  169. )
  170. {
  171. USHORT status;
  172. t_PXENV_UDP_READ command;
  173. ULONG startTime;
  174. UCHAR tmpBuffer[MAXIMUM_TFTP_PACKET_LENGTH];
  175. //
  176. // Turn on broadcasts while in the receive loop, in case
  177. // the other end needs to ARP to find us.
  178. //
  179. #if 0
  180. RomSetBroadcastStatus(TRUE);
  181. #endif
  182. startTime = SysGetRelativeTime();
  183. if ( Timeout < 2 ) Timeout = 2;
  184. while ( (SysGetRelativeTime() - startTime) < Timeout ) {
  185. command.Status = 0;
  186. *(UINT32 *)command.SrcIp = 0;
  187. *(UINT32 *)command.DestIp = 0;
  188. command.SrcPort = 0;
  189. command.DestPort = 0;
  190. command.BufferSize = (USHORT)Length;
  191. command.BufferOffset = PhysToOff(tmpBuffer);
  192. command.BufferSegment = PhysToSeg(tmpBuffer);
  193. //DbgPrint( "UDP read pktaddr %lx = %x:%x\n", tmpBuffer, command.BufferSegment, command.BufferOffset );
  194. status = NETPC_ROM_SERVICES( PXENV_UDP_READ, &command );
  195. if ( *(UINT32 *)command.SrcIp == 0 ) {
  196. continue;
  197. }
  198. //DbgPrint( "UDP read status = %x, src ip/port = %d.%d.%d.%d/%d, length = %x\n", command.Status,
  199. // command.SrcIp[0], command.SrcIp[1], command.SrcIp[2], command.SrcIp[3],
  200. // SWAP_WORD(command.SrcPort), command.BufferSize );
  201. //DbgPrint( " dest ip/port = %d.%d.%d.%d/%d\n",
  202. // command.DestIp[0], command.DestIp[1], command.DestIp[2], command.DestIp[3],
  203. // SWAP_WORD(command.DestPort) );
  204. #if 0
  205. if ( (command.DestIp[0] < 224) || (command.DestIp[0] > 239) ) {
  206. #endif
  207. //
  208. // This is a directed IP packet.
  209. //
  210. if ( !COMPARE_IP_ADDRESSES(command.DestIp, &NetLocalIpAddress) ||
  211. (command.DestPort != NetUnicastUdpDestinationPort)
  212. ) {
  213. // DPRINT( ERROR, (" Directed UDP packet to wrong port\n") );
  214. continue;
  215. }
  216. #if 0
  217. } else {
  218. //
  219. // This is a multicast IP packet.
  220. //
  221. if ( !COMPARE_IP_ADDRESSES(command.SrcIp, &NetMulticastUdpSourceAddress) ||
  222. !COMPARE_IP_ADDRESSES(command.DestIp, &NetMulticastUdpDestinationAddress) ||
  223. (command.SrcPort != NetMulticastUdpSourcePort) ||
  224. (command.DestPort != NetMulticastUdpDestinationPort) ) {
  225. DPRINT( ERROR, (" Multicast UDP packet with wrong source/destination\n") );
  226. continue;
  227. }
  228. }
  229. #endif
  230. //
  231. // We want this packet.
  232. //
  233. goto packet_received;
  234. }
  235. //
  236. // Timeout.
  237. //
  238. DPRINT( SEND_RECEIVE, ("RomReceiveUdpPacket: timeout\n") );
  239. #if 0
  240. RomSetBroadcastStatus(FALSE); // turn off broadcast reception
  241. #endif
  242. return 0;
  243. packet_received:
  244. //
  245. // Packet received.
  246. //
  247. RtlCopyMemory( Buffer, tmpBuffer, command.BufferSize );
  248. *RemoteHost = *(UINT32 *)command.SrcIp;
  249. *RemotePort = command.SrcPort;
  250. #if 0 && DBG
  251. if ( command.BufferSize != 0 ) {
  252. DPRINT( SEND_RECEIVE, ("RomReceiveUdpPacket: received this packet:\n") );
  253. IF_DEBUG(SEND_RECEIVE) {
  254. RomDumpRawData( Buffer, command.BufferSize, 0 );
  255. }
  256. }
  257. #endif
  258. #if 0
  259. RomSetBroadcastStatus(FALSE); // turn off broadcast reception
  260. #endif
  261. return command.BufferSize;
  262. } // RomReceiveUdpPacket
  263. ULONG
  264. RomGetNicType (
  265. OUT t_PXENV_UNDI_GET_NIC_TYPE *NicType
  266. )
  267. {
  268. return NETPC_ROM_SERVICES( PXENV_UNDI_GET_NIC_TYPE, NicType );
  269. }
  270. #if 0 && DBG
  271. VOID
  272. RomDumpRawData (
  273. IN PUCHAR DataStart,
  274. IN ULONG DataLength,
  275. IN ULONG Offset
  276. )
  277. {
  278. ULONG lastByte;
  279. UCHAR lineBuffer[88];
  280. PUCHAR bufferPtr;
  281. if ( DataLength > RomMaxDumpLength ) {
  282. DataLength = RomMaxDumpLength;
  283. }
  284. for ( lastByte = Offset + DataLength; Offset < lastByte; Offset += 16 ) {
  285. ULONG i;
  286. bufferPtr = lineBuffer;
  287. sprintf( bufferPtr, " %08x %04x: ", &DataStart[Offset], Offset );
  288. bufferPtr += 18;
  289. for ( i = 0; i < 16 && Offset + i < lastByte; i++ ) {
  290. sprintf( bufferPtr, "%02x", (UCHAR)DataStart[Offset + i] & (UCHAR)0xFF );
  291. bufferPtr += 2;
  292. if ( i == 7 ) {
  293. *bufferPtr++ = '-';
  294. } else {
  295. *bufferPtr++ = ' ';
  296. }
  297. }
  298. //
  299. // Print enough spaces so that the ASCII display lines up.
  300. //
  301. for ( ; i < 16; i++ ) {
  302. *bufferPtr++ = ' ';
  303. *bufferPtr++ = ' ';
  304. *bufferPtr++ = ' ';
  305. }
  306. *bufferPtr++ = ' ';
  307. *bufferPtr++ = ' ';
  308. *bufferPtr++ = '*';
  309. for ( i = 0; i < 16 && Offset + i < lastByte; i++ ) {
  310. if ( isprint( DataStart[Offset + i] ) ) {
  311. *bufferPtr++ = (CCHAR)DataStart[Offset + i];
  312. } else {
  313. *bufferPtr++ = '.';
  314. }
  315. }
  316. *bufferPtr = 0;
  317. DbgPrint( "%s*\n", lineBuffer );
  318. }
  319. return;
  320. } // RomDumpRawData
  321. #endif // DBG
  322. ARC_STATUS
  323. RomMtftpReadFile (
  324. IN PUCHAR FileName,
  325. IN PVOID Buffer,
  326. IN ULONG BufferLength,
  327. IN ULONG ServerIPAddress, // network byte order
  328. IN ULONG MCastIPAddress, // network byte order
  329. IN USHORT MCastCPort, // network byte order
  330. IN USHORT MCastSPort, // network byte order
  331. IN USHORT Timeout,
  332. IN USHORT Delay,
  333. OUT PULONG DownloadSize
  334. )
  335. {
  336. USHORT status;
  337. t_PXENV_TFTP_READ_FILE tftp;
  338. t_PXENV_UDP_CLOSE udpclose;
  339. if (DownloadSize != NULL) {
  340. *DownloadSize = 0;
  341. }
  342. ASSERT(strlen(FileName) < 128);
  343. memset( &tftp, 0 , sizeof( tftp ) );
  344. strcpy(tftp.FileName, FileName);
  345. tftp.BufferSize = BufferLength;
  346. tftp.BufferOffset = (UINT32)Buffer;
  347. if ( (ServerIPAddress & NetLocalSubnetMask) == (NetLocalIpAddress & NetLocalSubnetMask) ) {
  348. *((UINT32 *)tftp.GatewayIPAddress) = 0;
  349. } else {
  350. *((UINT32 *)tftp.GatewayIPAddress) = NetGatewayIpAddress;
  351. }
  352. *((UINT32 *)tftp.ServerIPAddress) = ServerIPAddress;
  353. *((UINT32 *)tftp.McastIPAddress) = MCastIPAddress;
  354. tftp.TFTPClntPort = MCastCPort;
  355. tftp.TFTPSrvPort = MCastSPort;
  356. tftp.TFTPOpenTimeOut = Timeout;
  357. tftp.TFTPReopenDelay = Delay;
  358. // make sure that any UDP sessions are already closed.
  359. status = NETPC_ROM_SERVICES( PXENV_UDP_CLOSE, &udpclose );
  360. status = NETPC_ROM_SERVICES( PXENV_TFTP_READ_FILE, &tftp );
  361. if (status != PXENV_EXIT_SUCCESS) {
  362. return EINVAL;
  363. }
  364. if (DownloadSize != NULL) {
  365. *DownloadSize = tftp.BufferSize;
  366. }
  367. return ESUCCESS;
  368. }