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.

511 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. tftp.c
  5. Abstract:
  6. Boot loader TFTP routines.
  7. Author:
  8. Chuck Lenzmeier (chuckl) December 27, 1996
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // This removes macro redefinitions which appear because we define __RPC_DOS__,
  16. // but rpc.h defines __RPC_WIN32__
  17. //
  18. #pragma warning(disable:4005)
  19. //
  20. // As of 12/17/98, SECURITY_DOS is *not* defined - adamba
  21. //
  22. #if defined(SECURITY_DOS)
  23. //
  24. // These appear because we defined SECURITY_DOS
  25. //
  26. #define __far
  27. #define __pascal
  28. #define __loadds
  29. #endif
  30. #include <security.h>
  31. #include <rpc.h>
  32. #include <spseal.h>
  33. #if defined(_X86_)
  34. #include <bldrx86.h>
  35. #endif
  36. #if defined(SECURITY_DOS)
  37. //
  38. // PSECURITY_STRING is not supposed to be used when SECURITY_DOS is
  39. // defined -- it should be a WCHAR*. Unfortunately ntlmsp.h breaks
  40. // this rule and even uses the SECURITY_STRING structure, which there
  41. // is really no equivalent for in 16-bit mode.
  42. //
  43. typedef SEC_WCHAR * SECURITY_STRING; // more-or-less the intention where it is used
  44. typedef SEC_WCHAR * PSECURITY_STRING;
  45. #endif
  46. #include <ntlmsp.h>
  47. #if DBG
  48. ULONG NetDebugFlag =
  49. DEBUG_ERROR |
  50. DEBUG_CONN_ERROR |
  51. //DEBUG_LOUD |
  52. //DEBUG_REAL_LOUD |
  53. //DEBUG_STATISTICS |
  54. //DEBUG_SEND_RECEIVE |
  55. //DEBUG_TRACE |
  56. //DEBUG_ARP |
  57. //DEBUG_INITIAL_BREAK |
  58. 0;
  59. #endif
  60. //
  61. // Global variables
  62. //
  63. CONNECTION NetTftpConnection;
  64. UCHAR NetTftpPacket[3][MAXIMUM_TFTP_PACKET_LENGTH];
  65. //
  66. // Local declarations.
  67. //
  68. NTSTATUS
  69. TftpGet (
  70. IN PCONNECTION Connection,
  71. IN PTFTP_REQUEST Request
  72. );
  73. NTSTATUS
  74. TftpPut (
  75. IN PCONNECTION Connection,
  76. IN PTFTP_REQUEST Request
  77. );
  78. NTSTATUS
  79. TftpGetPut (
  80. IN PTFTP_REQUEST Request
  81. )
  82. {
  83. NTSTATUS status;
  84. PCONNECTION connection = NULL;
  85. ULONG FileSize;
  86. ULONG basePage;
  87. #if 0 && DBG
  88. LARGE_INTEGER startTime;
  89. LARGE_INTEGER endTime;
  90. LARGE_INTEGER elapsedTime;
  91. LARGE_INTEGER frequency;
  92. ULONG seconds;
  93. ULONG secondsFraction;
  94. ULONG bps;
  95. ULONG bpsFraction;
  96. #endif
  97. #ifndef EFI
  98. //
  99. // We don't need to do any of this initialization if
  100. // we're in EFI.
  101. //
  102. FileSize = Request->MaximumLength;
  103. status = ConnInitialize(
  104. &connection,
  105. Request->Operation,
  106. Request->ServerIpAddress,
  107. TFTP_PORT,
  108. Request->RemoteFileName,
  109. 0,
  110. &FileSize
  111. );
  112. if ( !NT_SUCCESS(status) ) {
  113. return status;
  114. }
  115. #if 0 && DBG
  116. IF_DEBUG(STATISTICS) {
  117. startTime = KeQueryPerformanceCounter( &frequency );
  118. }
  119. #endif
  120. if ( Request->Operation == TFTP_RRQ ) {
  121. if ( Request->MemoryAddress != NULL ) {
  122. if ( Request->MaximumLength < FileSize ) {
  123. ConnError(
  124. connection,
  125. connection->RemoteHost,
  126. connection->RemotePort,
  127. TFTP_ERROR_UNDEFINED,
  128. "File too big"
  129. );
  130. return STATUS_INSUFFICIENT_RESOURCES;
  131. }
  132. } else {
  133. //
  134. // NB: (ChuckL) Removed code added by MattH to check for
  135. // allocation >= 1/3 of (BlUsableLimit - BlUsableBase)
  136. // because calling code now sets BlUsableLimit to 1 GB
  137. // or higher.
  138. //
  139. status = BlAllocateAlignedDescriptor(
  140. Request->MemoryType,
  141. 0,
  142. BYTES_TO_PAGES(FileSize),
  143. 0,
  144. &basePage
  145. );
  146. if (status != ESUCCESS) {
  147. ConnError(
  148. connection,
  149. connection->RemoteHost,
  150. connection->RemotePort,
  151. TFTP_ERROR_UNDEFINED,
  152. "File too big"
  153. );
  154. return STATUS_INSUFFICIENT_RESOURCES;
  155. }
  156. Request->MemoryAddress = (PUCHAR)(KSEG0_BASE | (basePage << PAGE_SHIFT));
  157. Request->MaximumLength = FileSize;
  158. DPRINT( REAL_LOUD, ("TftpGetPut: allocated %d bytes at 0x%08x\n",
  159. Request->MaximumLength, Request->MemoryAddress) );
  160. }
  161. status = TftpGet( connection, Request );
  162. } else {
  163. status = TftpPut( connection, Request );
  164. }
  165. #else // #ifndef EFI
  166. if ( Request->Operation == TFTP_RRQ ) {
  167. status = TftpGet( connection, Request );
  168. } else {
  169. status = TftpPut( connection, Request );
  170. }
  171. if( status != STATUS_SUCCESS ) {
  172. status = STATUS_INSUFFICIENT_RESOURCES;
  173. }
  174. #endif // #ifndef EFI
  175. if ( !NT_SUCCESS(status) ) {
  176. return status;
  177. }
  178. return status;
  179. } // TftpGetPut
  180. //#if 0
  181. #ifdef EFI
  182. extern VOID
  183. FlipToPhysical (
  184. );
  185. extern VOID
  186. FlipToVirtual (
  187. );
  188. NTSTATUS
  189. TftpGet (
  190. IN OUT PCONNECTION Connection,
  191. IN PTFTP_REQUEST Request
  192. )
  193. {
  194. EFI_STATUS Status;
  195. CHAR16 *Size = NULL;
  196. PVOID MyBuffer = NULL;
  197. EFI_IP_ADDRESS MyServerIpAddress;
  198. INTN Count = 0;
  199. INTN BufferSizeX = sizeof(CHAR16);
  200. ULONG basePage;
  201. UINTN BlockSize = 512;
  202. //
  203. // They sent us an IP address as a ULONG. We need to convert
  204. // that into an EFI_IP_ADDRESS.
  205. //
  206. for( Count = 0; Count < 4; Count++ ) {
  207. MyServerIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
  208. }
  209. //
  210. // Get the file size, allocate some memory, then get the file.
  211. //
  212. FlipToPhysical();
  213. Status = PXEClient->Mtftp( PXEClient,
  214. EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
  215. Size,
  216. TRUE,
  217. &BufferSizeX,
  218. &BlockSize,
  219. &MyServerIpAddress,
  220. Request->RemoteFileName,
  221. 0,
  222. FALSE );
  223. FlipToVirtual();
  224. if( Status != EFI_SUCCESS ) {
  225. return (NTSTATUS)Status;
  226. }
  227. Status = BlAllocateAlignedDescriptor(
  228. Request->MemoryType,
  229. 0,
  230. (ULONG) BYTES_TO_PAGES(BufferSizeX),
  231. 0,
  232. &basePage
  233. );
  234. if ( Status != ESUCCESS ) {
  235. if( BdDebuggerEnabled ) {
  236. DbgPrint( "TftpGet: BlAllocate failed! (%d)\n", Status );
  237. }
  238. return STATUS_INSUFFICIENT_RESOURCES;
  239. }
  240. Request->MemoryAddress = (PUCHAR)(KSEG0_BASE | ((ULONGLONG)basePage << PAGE_SHIFT) );
  241. Request->MaximumLength = (ULONG)BufferSizeX;
  242. //
  243. // Make sure we send EFI a physical address.
  244. //
  245. MyBuffer = (PVOID)((ULONGLONG)(Request->MemoryAddress) & ~KSEG0_BASE);
  246. FlipToPhysical();
  247. Status = PXEClient->Mtftp( PXEClient,
  248. EFI_PXE_BASE_CODE_TFTP_READ_FILE,
  249. MyBuffer,
  250. TRUE,
  251. &BufferSizeX,
  252. NULL,
  253. &MyServerIpAddress,
  254. Request->RemoteFileName,
  255. 0,
  256. FALSE );
  257. FlipToVirtual();
  258. if( Status != EFI_SUCCESS ) {
  259. if( BdDebuggerEnabled ) {
  260. DbgPrint( "TftpGet: GetFile failed! (%d)\n", Status );
  261. }
  262. return (NTSTATUS)Status;
  263. }
  264. Request->BytesTransferred = (ULONG)BufferSizeX;
  265. return (NTSTATUS)Status;
  266. } // TftpGet
  267. NTSTATUS
  268. TftpPut (
  269. IN OUT PCONNECTION Connection,
  270. IN PTFTP_REQUEST Request
  271. )
  272. {
  273. EFI_STATUS Status;
  274. EFI_IP_ADDRESS MyServerIpAddress;
  275. INTN Count = 0;
  276. PVOID MyBuffer = NULL;
  277. //
  278. // They sent us an IP address as a ULONG. We need to convert
  279. // that into an EFI_IP_ADDRESS.
  280. //
  281. for( Count = 0; Count < 4; Count++ ) {
  282. MyServerIpAddress.v4.Addr[Count] = PXEClient->Mode->ProxyOffer.Dhcpv4.BootpSiAddr[Count];
  283. }
  284. //
  285. // Make sure we send EFI a physical address.
  286. //
  287. MyBuffer = (PVOID)((ULONGLONG)(Request->MemoryAddress) & ~KSEG0_BASE);
  288. FlipToPhysical();
  289. Status = PXEClient->Mtftp( PXEClient,
  290. EFI_PXE_BASE_CODE_TFTP_WRITE_FILE,
  291. MyBuffer,
  292. TRUE,
  293. (UINTN *)(&Request->MaximumLength),
  294. NULL,
  295. &MyServerIpAddress,
  296. Request->RemoteFileName,
  297. 0,
  298. FALSE );
  299. FlipToVirtual();
  300. if( Status != EFI_SUCCESS ) {
  301. if( BdDebuggerEnabled ) {
  302. DbgPrint( "TftpPut: WriteFile failed! (%d)\n", Status );
  303. }
  304. }
  305. return (NTSTATUS)Status;
  306. } // TftpPut
  307. #else //#ifdef EFI
  308. NTSTATUS
  309. TftpGet (
  310. IN OUT PCONNECTION Connection,
  311. IN PTFTP_REQUEST Request
  312. )
  313. {
  314. NTSTATUS status;
  315. PTFTP_PACKET packet;
  316. ULONG length;
  317. ULONG offset;
  318. PUCHAR packetData;
  319. ULONG lastProgressPercent = -1;
  320. ULONG currentProgressPercent;
  321. DPRINT( TRACE, ("TftpGet\n") );
  322. offset = 0;
  323. if ( Request->ShowProgress ) {
  324. BlUpdateProgressBar(0);
  325. }
  326. do {
  327. status = ConnReceive( Connection, &packet );
  328. if ( !NT_SUCCESS(status) ) {
  329. break;
  330. }
  331. length = Connection->CurrentLength - 4;
  332. packetData = packet->Data;
  333. if ( (offset + length) > Request->MaximumLength ) {
  334. length = Request->MaximumLength - offset;
  335. }
  336. RtlCopyMemory( Request->MemoryAddress + offset, packetData, length );
  337. offset += length;
  338. if ( Request->ShowProgress ) {
  339. currentProgressPercent = (ULONG)(((ULONGLONG)offset * 100) / Request->MaximumLength);
  340. if ( currentProgressPercent != lastProgressPercent ) {
  341. BlUpdateProgressBar( currentProgressPercent );
  342. }
  343. lastProgressPercent = currentProgressPercent;
  344. }
  345. //
  346. // End the loop when we get a packet smaller than the max size --
  347. // the extra check is to handle the first packet (length == offset)
  348. // since we get NTLMSSP_MESSAGE_SIGNATURE_SIZE bytes less.
  349. //
  350. } while ( (length == Connection->BlockSize));
  351. Request->BytesTransferred = offset;
  352. return status;
  353. } // TftpGet
  354. NTSTATUS
  355. TftpPut (
  356. IN OUT PCONNECTION Connection,
  357. IN PTFTP_REQUEST Request
  358. )
  359. {
  360. NTSTATUS status;
  361. PTFTP_PACKET packet;
  362. ULONG length;
  363. ULONG offset;
  364. DPRINT( TRACE, ("TftpPut\n") );
  365. offset = 0;
  366. do {
  367. packet = ConnPrepareSend( Connection );
  368. length = Connection->BlockSize;
  369. if ( (offset + length) > Request->MaximumLength ) {
  370. length = Request->MaximumLength - offset;
  371. }
  372. RtlCopyMemory( packet->Data, Request->MemoryAddress + offset, length );
  373. status = ConnSend( Connection, length );
  374. if ( !NT_SUCCESS(status) ) {
  375. break;
  376. }
  377. offset += length;
  378. } while ( length == Connection->BlockSize );
  379. Request->BytesTransferred = offset;
  380. if ( NT_SUCCESS(status) ) {
  381. status = ConnWaitForFinalAck( Connection );
  382. }
  383. return status;
  384. } // TftpPut
  385. #endif // #if defined(_IA64_)