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.

244 lines
6.6 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 <udp_api.h>
  15. #include <tftp_api.h>
  16. #include "bldr.h"
  17. #include "efi.h"
  18. #include "efip.h"
  19. #include "bldria64.h"
  20. #include "extern.h"
  21. //
  22. // We'll use this to keep track of which port we're communicating through.
  23. //
  24. EFI_PXE_BASE_CODE_UDP_PORT MachineLocalPort = 2000;
  25. #define UDP_STALL_TIME (40000)
  26. #define UDP_RETRY_COUNT (10)
  27. extern VOID
  28. FwStallExecution(
  29. IN ULONG Microseconds
  30. );
  31. VOID
  32. RomSetReceiveStatus (
  33. IN USHORT UnicastUdpDestinationPort
  34. #if 0
  35. ,
  36. IN USHORT MulticastUdpDestinationPort,
  37. IN ULONG MulticastUdpDestinationAddress,
  38. IN USHORT MulticastUdpSourcePort,
  39. IN ULONG MulticastUdpSourceAddress
  40. #endif
  41. )
  42. {
  43. return;
  44. } // RomSetReceiveStatus
  45. ULONG
  46. RomSendUdpPacket (
  47. IN PVOID Buffer,
  48. IN ULONG Length,
  49. IN ULONG RemoteHost,
  50. IN USHORT pServerPort
  51. )
  52. {
  53. EFI_STATUS EfiStatus = EFI_SUCCESS;
  54. EFI_IP_ADDRESS DestinationIpAddress;
  55. INTN Count = 0;
  56. EFI_PXE_BASE_CODE_UDP_PORT ServerPort = pServerPort;
  57. UINTN BufferLength = Length;
  58. PVOID MyBuffer = NULL;
  59. //
  60. // Get the server's EFI_IP_ADDRESS from the handle to the PXE base code.
  61. //
  62. for( Count = 0; Count < 4; Count++ ) {
  63. DestinationIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
  64. }
  65. FlipToPhysical();
  66. //
  67. // Make sure the address is a physical address, then do the UdpWrite.
  68. //
  69. MyBuffer = (PVOID)((ULONG_PTR)Buffer & ~KSEG0_BASE);
  70. Count = UDP_RETRY_COUNT;
  71. do {
  72. EfiStatus = PXEClient->UdpWrite( PXEClient,
  73. 0,
  74. &DestinationIpAddress,
  75. &ServerPort,
  76. NULL,
  77. NULL,
  78. &MachineLocalPort,
  79. NULL,
  80. NULL,
  81. &BufferLength,
  82. MyBuffer );
  83. //
  84. // This is really gross, but on retail builds with no debugger, EFI will go
  85. // off in the weeds unless we slow down transactions over the network. So
  86. // after Udp operations, take a short nap.
  87. //
  88. if( EfiStatus == EFI_TIMEOUT ) {
  89. FwStallExecution( UDP_STALL_TIME );
  90. }
  91. Count--;
  92. } while( (EfiStatus == EFI_TIMEOUT) && (Count > 0) );
  93. FlipToVirtual();
  94. if( EfiStatus != EFI_SUCCESS ) {
  95. if( BdDebuggerEnabled ) {
  96. DbgPrint( "RomSendUdpPacket: UdpWrite failed. MachineLocalPort: %d ServerPort: %d (%d)\r\n", MachineLocalPort, ServerPort, EfiStatus );
  97. }
  98. return 0;
  99. }
  100. return (ULONG)BufferLength;
  101. } // RomSendUdpPacket
  102. ULONG
  103. RomReceiveUdpPacket (
  104. IN PVOID Buffer,
  105. IN ULONG Length,
  106. IN ULONG Timeout,
  107. IN OUT PULONG RemoteHost,
  108. IN OUT PUSHORT LocalPort
  109. )
  110. {
  111. EFI_STATUS EfiStatus = EFI_SUCCESS;
  112. UINTN BufferLength = Length;
  113. EFI_IP_ADDRESS ServerIpAddress;
  114. EFI_IP_ADDRESS MyIpAddress;
  115. INTN Count = 0;
  116. EFI_PXE_BASE_CODE_UDP_PORT ServerPort = (EFI_PXE_BASE_CODE_UDP_PORT)(0xFAB); // hardcode to 4011
  117. PVOID MyBuffer = NULL;
  118. ULONG startTime;
  119. //
  120. // Get The server's EFI_IP_ADDRESS from the handle to the PXE base code.
  121. //
  122. for( Count = 0; Count < 4; Count++ ) {
  123. ServerIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
  124. }
  125. //
  126. // Get our EFI_IP_ADDRESS from the handle to the PXE base code.
  127. //
  128. for( Count = 0; Count < 4; Count++ ) {
  129. MyIpAddress.v4.Addr[Count] = PXEClient->Mode->StationIp.v4.Addr[Count];
  130. }
  131. startTime = SysGetRelativeTime();
  132. if ( Timeout < 2 ) Timeout = 2;
  133. //
  134. // Make sure the address is a physical address, then do the UdpReceive.
  135. //
  136. MyBuffer = (PVOID)((ULONG_PTR)Buffer & ~KSEG0_BASE);
  137. while ( (SysGetRelativeTime() - startTime) < Timeout ) {
  138. FlipToPhysical();
  139. //
  140. // By setting flags to 0, we are setting a receive filter
  141. // which says we'll only receive a packet from the specified
  142. // IP address and port, sent to the specified IP address and
  143. // port.
  144. //
  145. EfiStatus = PXEClient->UdpRead( PXEClient,
  146. 0,
  147. &MyIpAddress,
  148. &MachineLocalPort,
  149. &ServerIpAddress,
  150. &ServerPort,
  151. NULL, // &HeaderLength
  152. NULL, // HeaderBuffer
  153. &BufferLength,
  154. MyBuffer );
  155. //
  156. // This is really gross, but on retail builds with no debugger, EFI will go
  157. // off in the weeds unless we slow down transactions over the network. So
  158. // after Udp operations, take a short nap. We must be in physical mode
  159. // when we call this API.
  160. //
  161. if( EfiStatus == EFI_TIMEOUT ) {
  162. FwStallExecution( UDP_STALL_TIME );
  163. }
  164. //
  165. // back into virtual mode -- we're either going to break out or do another
  166. // loop, and the SysGetRelativeTime call wants us in physical mode.
  167. //
  168. FlipToVirtual();
  169. if (EfiStatus == EFI_SUCCESS) {
  170. break;
  171. }
  172. }
  173. if( EfiStatus != EFI_SUCCESS ) {
  174. if( BdDebuggerEnabled ) {
  175. DbgPrint( "RomReceiveUdpPacket: UdpRead failed. MachineLocalPort: %d ServerPort: %d (%d)\r\n", MachineLocalPort, ServerPort, EfiStatus );
  176. }
  177. return 0;
  178. }
  179. return (ULONG)BufferLength;
  180. } // RomReceiveUdpPacket
  181. ULONG
  182. RomGetNicType (
  183. OUT t_PXENV_UNDI_GET_NIC_TYPE *NicType
  184. )
  185. {
  186. return 0;
  187. }