1 /** @file 2 PxeBc MTFTP functions. 3 4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "PxeBcImpl.h" 16 17 CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = { 18 "blksize", 19 "timeout", 20 "tsize", 21 "multicast" 22 }; 23 24 25 /** 26 This is a callback function when packets received/transmitted in Mtftp driver. 27 28 A callback function that is provided by the caller to intercept 29 the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the 30 EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept 31 EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to 32 EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). 33 34 @param This Pointer to Mtftp protocol instance 35 @param Token Pointer to Mtftp token 36 @param PacketLen Length of Mtftp packet 37 @param Packet Pointer to Mtftp packet 38 39 @retval EFI_SUCCESS Operation sucess 40 @retval EFI_ABORTED Abort transfer process 41 42 **/ 43 EFI_STATUS 44 EFIAPI 45 PxeBcCheckPacket ( 46 IN EFI_MTFTP4_PROTOCOL *This, 47 IN EFI_MTFTP4_TOKEN *Token, 48 IN UINT16 PacketLen, 49 IN EFI_MTFTP4_PACKET *Packet 50 ) 51 { 52 PXEBC_PRIVATE_DATA *Private; 53 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; 54 EFI_STATUS Status; 55 56 Private = (PXEBC_PRIVATE_DATA *) Token->Context; 57 Callback = Private->PxeBcCallback; 58 Status = EFI_SUCCESS; 59 60 if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) { 61 Private->Mode.TftpErrorReceived = TRUE; 62 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 63 AsciiStrnCpyS (Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1); 64 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 65 } 66 67 if (Callback != NULL) { 68 69 Status = Callback->Callback ( 70 Callback, 71 Private->Function, 72 TRUE, 73 PacketLen, 74 (EFI_PXE_BASE_CODE_PACKET *) Packet 75 ); 76 if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { 77 78 Status = EFI_ABORTED; 79 } else { 80 81 Status = EFI_SUCCESS; 82 } 83 } 84 85 return Status; 86 } 87 88 89 /** 90 This function is to get size of a file by Tftp. 91 92 @param Private Pointer to PxeBc private data 93 @param Config Pointer to Mtftp configuration data 94 @param Filename Pointer to file name 95 @param BlockSize Pointer to block size 96 @param BufferSize Pointer to buffer size 97 98 @retval EFI_SUCCESS Get the size of file success 99 @retval EFI_NOT_FOUND Parse the tftp ptions failed. 100 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 101 @retval Other Has not get the size of the file. 102 103 **/ 104 EFI_STATUS 105 PxeBcTftpGetFileSize ( 106 IN PXEBC_PRIVATE_DATA *Private, 107 IN EFI_MTFTP4_CONFIG_DATA *Config, 108 IN UINT8 *Filename, 109 IN UINTN *BlockSize, 110 IN OUT UINT64 *BufferSize 111 ) 112 { 113 EFI_MTFTP4_PROTOCOL *Mtftp4; 114 EFI_MTFTP4_OPTION ReqOpt[2]; 115 EFI_MTFTP4_PACKET *Packet; 116 EFI_MTFTP4_OPTION *Option; 117 UINT32 PktLen; 118 UINT8 OptBuf[128]; 119 UINT32 OptCnt; 120 EFI_STATUS Status; 121 122 *BufferSize = 0; 123 Status = EFI_DEVICE_ERROR; 124 Mtftp4 = Private->Mtftp4; 125 Packet = NULL; 126 Option = NULL; 127 PktLen = 0; 128 OptCnt = 1; 129 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 130 131 Status = Mtftp4->Configure (Mtftp4, Config); 132 if (EFI_ERROR (Status)) { 133 134 return Status; 135 } 136 137 ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; 138 UtoA10 (0, (CHAR8 *) OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 139 ReqOpt[0].ValueStr = OptBuf; 140 141 if (BlockSize != NULL) { 142 ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 143 ReqOpt[1].ValueStr = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1; 144 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1)); 145 OptCnt++; 146 } 147 148 Status = Mtftp4->GetInfo ( 149 Mtftp4, 150 NULL, 151 Filename, 152 NULL, 153 (UINT8) OptCnt, 154 ReqOpt, 155 &PktLen, 156 &Packet 157 ); 158 159 if (EFI_ERROR (Status)) { 160 if (Status == EFI_TFTP_ERROR) { 161 Private->Mode.TftpErrorReceived = TRUE; 162 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 163 AsciiStrnCpyS ( 164 Private->Mode.TftpError.ErrorString, 165 PXE_MTFTP_ERROR_STRING_LENGTH, 166 (CHAR8 *) Packet->Error.ErrorMessage, 167 PXE_MTFTP_ERROR_STRING_LENGTH - 1 168 ); 169 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 170 } 171 goto ON_ERROR; 172 } 173 174 OptCnt = 0; 175 176 Status = Mtftp4->ParseOptions ( 177 Mtftp4, 178 PktLen, 179 Packet, 180 (UINT32 *) &OptCnt, 181 &Option 182 ); 183 184 if (EFI_ERROR (Status)) { 185 186 goto ON_ERROR; 187 } 188 189 Status = EFI_NOT_FOUND; 190 191 while (OptCnt != 0) { 192 193 if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { 194 195 *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr); 196 Status = EFI_SUCCESS; 197 } 198 199 OptCnt--; 200 } 201 202 FreePool (Option); 203 204 ON_ERROR: 205 206 if (Packet != NULL) { 207 FreePool (Packet); 208 } 209 210 Mtftp4->Configure (Mtftp4, NULL); 211 212 return Status; 213 } 214 215 216 /** 217 This function is to get data of a file by Tftp. 218 219 @param Private Pointer to PxeBc private data 220 @param Config Pointer to Mtftp configuration data 221 @param Filename Pointer to file name 222 @param BlockSize Pointer to block size 223 @param BufferPtr Pointer to buffer 224 @param BufferSize Pointer to buffer size 225 @param DontUseBuffer Indicate whether with a receive buffer 226 227 @retval EFI_SUCCESS Read the data success from the special file. 228 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 229 @retval other Read data from file failed. 230 231 **/ 232 EFI_STATUS 233 PxeBcTftpReadFile ( 234 IN PXEBC_PRIVATE_DATA *Private, 235 IN EFI_MTFTP4_CONFIG_DATA *Config, 236 IN UINT8 *Filename, 237 IN UINTN *BlockSize, 238 IN UINT8 *BufferPtr, 239 IN OUT UINT64 *BufferSize, 240 IN BOOLEAN DontUseBuffer 241 ) 242 { 243 EFI_MTFTP4_PROTOCOL *Mtftp4; 244 EFI_MTFTP4_TOKEN Token; 245 EFI_MTFTP4_OPTION ReqOpt[1]; 246 UINT32 OptCnt; 247 UINT8 OptBuf[128]; 248 EFI_STATUS Status; 249 250 Status = EFI_DEVICE_ERROR; 251 Mtftp4 = Private->Mtftp4; 252 OptCnt = 0; 253 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 254 255 Status = Mtftp4->Configure (Mtftp4, Config); 256 if (EFI_ERROR (Status)) { 257 258 return Status; 259 } 260 261 if (BlockSize != NULL) { 262 263 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 264 ReqOpt[0].ValueStr = OptBuf; 265 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 266 OptCnt++; 267 } 268 269 Token.Event = NULL; 270 Token.OverrideData = NULL; 271 Token.Filename = Filename; 272 Token.ModeStr = NULL; 273 Token.OptionCount = OptCnt; 274 Token.OptionList = ReqOpt; 275 Token.Context = Private; 276 277 if (DontUseBuffer) { 278 Token.BufferSize = 0; 279 Token.Buffer = NULL; 280 } else { 281 Token.BufferSize = *BufferSize; 282 Token.Buffer = BufferPtr; 283 } 284 285 Token.CheckPacket = PxeBcCheckPacket; 286 Token.TimeoutCallback = NULL; 287 Token.PacketNeeded = NULL; 288 289 Status = Mtftp4->ReadFile (Mtftp4, &Token); 290 291 *BufferSize = Token.BufferSize; 292 293 Mtftp4->Configure (Mtftp4, NULL); 294 295 return Status; 296 } 297 298 299 /** 300 This function is put data of a file by Tftp. 301 302 @param Private Pointer to PxeBc private data 303 @param Config Pointer to Mtftp configuration data 304 @param Filename Pointer to file name 305 @param Overwrite Indicate whether with overwrite attribute 306 @param BlockSize Pointer to block size 307 @param BufferPtr Pointer to buffer 308 @param BufferSize Pointer to buffer size 309 310 @retval EFI_SUCCESS Write the data success into the special file. 311 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 312 @retval other Write data into file failed. 313 314 **/ 315 EFI_STATUS 316 PxeBcTftpWriteFile ( 317 IN PXEBC_PRIVATE_DATA *Private, 318 IN EFI_MTFTP4_CONFIG_DATA *Config, 319 IN UINT8 *Filename, 320 IN BOOLEAN Overwrite, 321 IN UINTN *BlockSize, 322 IN UINT8 *BufferPtr, 323 IN OUT UINT64 *BufferSize 324 ) 325 { 326 EFI_MTFTP4_PROTOCOL *Mtftp4; 327 EFI_MTFTP4_TOKEN Token; 328 EFI_MTFTP4_OPTION ReqOpt[1]; 329 UINT32 OptCnt; 330 UINT8 OptBuf[128]; 331 EFI_STATUS Status; 332 333 Status = EFI_DEVICE_ERROR; 334 Mtftp4 = Private->Mtftp4; 335 OptCnt = 0; 336 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 337 338 Status = Mtftp4->Configure (Mtftp4, Config); 339 if (EFI_ERROR (Status)) { 340 341 return Status; 342 } 343 344 if (BlockSize != NULL) { 345 346 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 347 ReqOpt[0].ValueStr = OptBuf; 348 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 349 OptCnt++; 350 } 351 352 Token.Event = NULL; 353 Token.OverrideData = NULL; 354 Token.Filename = Filename; 355 Token.ModeStr = NULL; 356 Token.OptionCount = OptCnt; 357 Token.OptionList = ReqOpt; 358 Token.BufferSize = *BufferSize; 359 Token.Buffer = BufferPtr; 360 Token.CheckPacket = PxeBcCheckPacket; 361 Token.TimeoutCallback = NULL; 362 Token.PacketNeeded = NULL; 363 364 Status = Mtftp4->WriteFile (Mtftp4, &Token); 365 *BufferSize = Token.BufferSize; 366 367 Mtftp4->Configure (Mtftp4, NULL); 368 369 return Status; 370 } 371 372 373 /** 374 This function is to get data(file) from a directory(may be a server) by Tftp. 375 376 @param Private Pointer to PxeBc private data. 377 @param Config Pointer to Mtftp configuration data. 378 @param Filename Pointer to file name. 379 @param BlockSize Pointer to block size. 380 @param BufferPtr Pointer to buffer. 381 @param BufferSize Pointer to buffer size. 382 @param DontUseBuffer Indicate whether with a receive buffer. 383 384 @retval EFI_SUCCES Get the data from the file included in directory success. 385 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 386 @retval other Operation failed. 387 388 **/ 389 EFI_STATUS 390 PxeBcTftpReadDirectory ( 391 IN PXEBC_PRIVATE_DATA *Private, 392 IN EFI_MTFTP4_CONFIG_DATA *Config, 393 IN UINT8 *Filename, 394 IN UINTN *BlockSize, 395 IN UINT8 *BufferPtr, 396 IN OUT UINT64 *BufferSize, 397 IN BOOLEAN DontUseBuffer 398 ) 399 { 400 EFI_MTFTP4_PROTOCOL *Mtftp4; 401 EFI_MTFTP4_TOKEN Token; 402 EFI_MTFTP4_OPTION ReqOpt[1]; 403 UINT32 OptCnt; 404 UINT8 OptBuf[128]; 405 EFI_STATUS Status; 406 407 Status = EFI_DEVICE_ERROR; 408 Mtftp4 = Private->Mtftp4; 409 OptCnt = 0; 410 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 411 412 Status = Mtftp4->Configure (Mtftp4, Config); 413 if (EFI_ERROR (Status)) { 414 415 return Status; 416 } 417 418 if (BlockSize != NULL) { 419 420 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 421 ReqOpt[0].ValueStr = OptBuf; 422 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 423 OptCnt++; 424 } 425 426 Token.Event = NULL; 427 Token.OverrideData = NULL; 428 Token.Filename = Filename; 429 Token.ModeStr = NULL; 430 Token.OptionCount = OptCnt; 431 Token.OptionList = ReqOpt; 432 Token.Context = Private; 433 434 if (DontUseBuffer) { 435 Token.BufferSize = 0; 436 Token.Buffer = NULL; 437 } else { 438 Token.BufferSize = *BufferSize; 439 Token.Buffer = BufferPtr; 440 } 441 442 Token.CheckPacket = PxeBcCheckPacket; 443 Token.TimeoutCallback = NULL; 444 Token.PacketNeeded = NULL; 445 446 Status = Mtftp4->ReadDirectory (Mtftp4, &Token); 447 448 *BufferSize = Token.BufferSize; 449 450 Mtftp4->Configure (Mtftp4, NULL); 451 452 return Status; 453 } 454 455