1/** @file 2 Functions implementation related with Mtftp for UefiPxeBc Driver. 3 4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14**/ 15 16#include "PxeBcImpl.h" 17 18CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = { 19 "blksize", 20 "timeout", 21 "tsize", 22 "multicast" 23}; 24 25 26/** 27 This is a callback function when packets are received or transmitted in Mtftp driver. 28 29 A callback function that is provided by the caller to intercept 30 the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP6_OPCODE_DATA8 packets processed in the 31 EFI_MTFTP6_PROTOCOL.ReadFile() function, and alternatively to intercept 32 EFI_MTFTP6_OPCODE_OACK or EFI_MTFTP6_OPCODE_ERROR packets during a call to 33 EFI_MTFTP6_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). 34 35 @param[in] This Pointer to EFI_MTFTP6_PROTOCOL. 36 @param[in] Token Pointer to EFI_MTFTP6_TOKEN. 37 @param[in] PacketLen Length of EFI_MTFTP6_PACKET. 38 @param[in] Packet Pointer to EFI_MTFTP6_PACKET to be checked. 39 40 @retval EFI_SUCCESS The current operation succeeded. 41 @retval EFI_ABORTED Abort the current transfer process. 42 43**/ 44EFI_STATUS 45EFIAPI 46PxeBcMtftp6CheckPacket ( 47 IN EFI_MTFTP6_PROTOCOL *This, 48 IN EFI_MTFTP6_TOKEN *Token, 49 IN UINT16 PacketLen, 50 IN EFI_MTFTP6_PACKET *Packet 51 ) 52{ 53 PXEBC_PRIVATE_DATA *Private; 54 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; 55 EFI_STATUS Status; 56 57 Private = (PXEBC_PRIVATE_DATA *) Token->Context; 58 Callback = Private->PxeBcCallback; 59 Status = EFI_SUCCESS; 60 61 if (Packet->OpCode == EFI_MTFTP6_OPCODE_ERROR) { 62 // 63 // Store the tftp error message into mode data and set the received flag. 64 // 65 Private->Mode.TftpErrorReceived = TRUE; 66 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 67 AsciiStrnCpyS ( 68 Private->Mode.TftpError.ErrorString, 69 PXE_MTFTP_ERROR_STRING_LENGTH, 70 (CHAR8 *) Packet->Error.ErrorMessage, 71 PXE_MTFTP_ERROR_STRING_LENGTH - 1 72 ); 73 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 74 } 75 76 if (Callback != NULL) { 77 // 78 // Callback to user if has when received any tftp packet. 79 // 80 Status = Callback->Callback ( 81 Callback, 82 Private->Function, 83 TRUE, 84 PacketLen, 85 (EFI_PXE_BASE_CODE_PACKET *) Packet 86 ); 87 if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { 88 // 89 // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. 90 // 91 Status = EFI_ABORTED; 92 } else { 93 // 94 // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. 95 // 96 Status = EFI_SUCCESS; 97 } 98 } 99 100 return Status; 101} 102 103 104/** 105 This function is to get the size of a file using Tftp. 106 107 @param[in] Private Pointer to PxeBc private data. 108 @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. 109 @param[in] Filename Pointer to boot file name. 110 @param[in] BlockSize Pointer to required block size. 111 @param[in, out] BufferSize Pointer to buffer size. 112 113 @retval EFI_SUCCESS Sucessfully obtained the size of file. 114 @retval EFI_NOT_FOUND Parse the tftp ptions failed. 115 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 116 @retval Others Has not obtained the size of the file. 117 118**/ 119EFI_STATUS 120PxeBcMtftp6GetFileSize ( 121 IN PXEBC_PRIVATE_DATA *Private, 122 IN EFI_MTFTP6_CONFIG_DATA *Config, 123 IN UINT8 *Filename, 124 IN UINTN *BlockSize, 125 IN OUT UINT64 *BufferSize 126 ) 127{ 128 EFI_MTFTP6_PROTOCOL *Mtftp6; 129 EFI_MTFTP6_OPTION ReqOpt[2]; 130 EFI_MTFTP6_PACKET *Packet; 131 EFI_MTFTP6_OPTION *Option; 132 UINT32 PktLen; 133 UINT8 OptBuf[128]; 134 UINT32 OptCnt; 135 EFI_STATUS Status; 136 137 *BufferSize = 0; 138 Status = EFI_DEVICE_ERROR; 139 Mtftp6 = Private->Mtftp6; 140 Packet = NULL; 141 Option = NULL; 142 PktLen = 0; 143 OptCnt = 1; 144 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 145 146 Status = Mtftp6->Configure (Mtftp6, Config); 147 if (EFI_ERROR (Status)) { 148 return Status; 149 } 150 151 // 152 // Build the required options for get info. 153 // 154 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; 155 PxeBcUintnToAscDec (0, OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 156 ReqOpt[0].ValueStr = OptBuf; 157 158 if (BlockSize != NULL) { 159 ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 160 ReqOpt[1].ValueStr = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1); 161 PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1)); 162 OptCnt++; 163 } 164 165 Status = Mtftp6->GetInfo ( 166 Mtftp6, 167 NULL, 168 Filename, 169 NULL, 170 (UINT8) OptCnt, 171 ReqOpt, 172 &PktLen, 173 &Packet 174 ); 175 if (EFI_ERROR (Status)) { 176 if (Status == EFI_TFTP_ERROR) { 177 // 178 // Store the tftp error message into mode data and set the received flag. 179 // 180 Private->Mode.TftpErrorReceived = TRUE; 181 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 182 AsciiStrnCpyS ( 183 Private->Mode.TftpError.ErrorString, 184 PXE_MTFTP_ERROR_STRING_LENGTH, 185 (CHAR8 *) Packet->Error.ErrorMessage, 186 PXE_MTFTP_ERROR_STRING_LENGTH - 1 187 ); 188 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 189 } 190 goto ON_ERROR; 191 } 192 193 // 194 // Parse the options in the reply packet. 195 // 196 OptCnt = 0; 197 Status = Mtftp6->ParseOptions ( 198 Mtftp6, 199 PktLen, 200 Packet, 201 (UINT32 *) &OptCnt, 202 &Option 203 ); 204 if (EFI_ERROR (Status)) { 205 goto ON_ERROR; 206 } 207 208 // 209 // Parse out the value of "tsize" option. 210 // 211 Status = EFI_NOT_FOUND; 212 while (OptCnt != 0) { 213 if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { 214 *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); 215 Status = EFI_SUCCESS; 216 } 217 OptCnt--; 218 } 219 FreePool (Option); 220 221ON_ERROR: 222 if (Packet != NULL) { 223 FreePool (Packet); 224 } 225 Mtftp6->Configure (Mtftp6, NULL); 226 227 return Status; 228} 229 230 231/** 232 This function is to get data of a file using Tftp. 233 234 @param[in] Private Pointer to PxeBc private data. 235 @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. 236 @param[in] Filename Pointer to boot file name. 237 @param[in] BlockSize Pointer to required block size. 238 @param[in] BufferPtr Pointer to buffer. 239 @param[in, out] BufferSize Pointer to buffer size. 240 @param[in] DontUseBuffer Indicates whether with a receive buffer. 241 242 @retval EFI_SUCCESS Successfully read the data from the special file. 243 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 244 @retval Others Read data from file failed. 245 246**/ 247EFI_STATUS 248PxeBcMtftp6ReadFile ( 249 IN PXEBC_PRIVATE_DATA *Private, 250 IN EFI_MTFTP6_CONFIG_DATA *Config, 251 IN UINT8 *Filename, 252 IN UINTN *BlockSize, 253 IN UINT8 *BufferPtr, 254 IN OUT UINT64 *BufferSize, 255 IN BOOLEAN DontUseBuffer 256 ) 257{ 258 EFI_MTFTP6_PROTOCOL *Mtftp6; 259 EFI_MTFTP6_TOKEN Token; 260 EFI_MTFTP6_OPTION ReqOpt[1]; 261 UINT32 OptCnt; 262 UINT8 OptBuf[128]; 263 EFI_STATUS Status; 264 265 Status = EFI_DEVICE_ERROR; 266 Mtftp6 = Private->Mtftp6; 267 OptCnt = 0; 268 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 269 270 Status = Mtftp6->Configure (Mtftp6, Config); 271 if (EFI_ERROR (Status)) { 272 return Status; 273 } 274 275 if (BlockSize != NULL) { 276 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 277 ReqOpt[0].ValueStr = OptBuf; 278 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 279 OptCnt++; 280 } 281 282 Token.Event = NULL; 283 Token.OverrideData = NULL; 284 Token.Filename = Filename; 285 Token.ModeStr = NULL; 286 Token.OptionCount = OptCnt; 287 Token.OptionList = ReqOpt; 288 Token.Context = Private; 289 290 if (DontUseBuffer) { 291 Token.BufferSize = 0; 292 Token.Buffer = NULL; 293 } else { 294 Token.BufferSize = *BufferSize; 295 Token.Buffer = BufferPtr; 296 } 297 298 Token.CheckPacket = PxeBcMtftp6CheckPacket; 299 Token.TimeoutCallback = NULL; 300 Token.PacketNeeded = NULL; 301 302 Status = Mtftp6->ReadFile (Mtftp6, &Token); 303 // 304 // Get the real size of received buffer. 305 // 306 *BufferSize = Token.BufferSize; 307 308 Mtftp6->Configure (Mtftp6, NULL); 309 310 return Status; 311} 312 313 314/** 315 This function is used to write the data of a file using Tftp. 316 317 @param[in] Private Pointer to PxeBc private data. 318 @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. 319 @param[in] Filename Pointer to boot file name. 320 @param[in] Overwrite Indicate whether with overwrite attribute. 321 @param[in] BlockSize Pointer to required block size. 322 @param[in] BufferPtr Pointer to buffer. 323 @param[in, out] BufferSize Pointer to buffer size. 324 325 @retval EFI_SUCCESS Successfully wrote the data into a special file. 326 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 327 @retval other Write data into file failed. 328 329**/ 330EFI_STATUS 331PxeBcMtftp6WriteFile ( 332 IN PXEBC_PRIVATE_DATA *Private, 333 IN EFI_MTFTP6_CONFIG_DATA *Config, 334 IN UINT8 *Filename, 335 IN BOOLEAN Overwrite, 336 IN UINTN *BlockSize, 337 IN UINT8 *BufferPtr, 338 IN OUT UINT64 *BufferSize 339 ) 340{ 341 EFI_MTFTP6_PROTOCOL *Mtftp6; 342 EFI_MTFTP6_TOKEN Token; 343 EFI_MTFTP6_OPTION ReqOpt[1]; 344 UINT32 OptCnt; 345 UINT8 OptBuf[128]; 346 EFI_STATUS Status; 347 348 Status = EFI_DEVICE_ERROR; 349 Mtftp6 = Private->Mtftp6; 350 OptCnt = 0; 351 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 352 353 Status = Mtftp6->Configure (Mtftp6, Config); 354 if (EFI_ERROR (Status)) { 355 return Status; 356 } 357 358 if (BlockSize != NULL) { 359 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 360 ReqOpt[0].ValueStr = OptBuf; 361 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 362 OptCnt++; 363 } 364 365 Token.Event = NULL; 366 Token.OverrideData = NULL; 367 Token.Filename = Filename; 368 Token.ModeStr = NULL; 369 Token.OptionCount = OptCnt; 370 Token.OptionList = ReqOpt; 371 Token.BufferSize = *BufferSize; 372 Token.Buffer = BufferPtr; 373 Token.CheckPacket = PxeBcMtftp6CheckPacket; 374 Token.TimeoutCallback = NULL; 375 Token.PacketNeeded = NULL; 376 377 Status = Mtftp6->WriteFile (Mtftp6, &Token); 378 // 379 // Get the real size of transmitted buffer. 380 // 381 *BufferSize = Token.BufferSize; 382 383 Mtftp6->Configure (Mtftp6, NULL); 384 385 return Status; 386} 387 388 389/** 390 This function is to read the data (file) from a directory using Tftp. 391 392 @param[in] Private Pointer to PxeBc private data. 393 @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. 394 @param[in] Filename Pointer to boot file name. 395 @param[in] BlockSize Pointer to required block size. 396 @param[in] BufferPtr Pointer to buffer. 397 @param[in, out] BufferSize Pointer to buffer size. 398 @param[in] DontUseBuffer Indicates whether to use a receive buffer. 399 400 @retval EFI_SUCCESS Successfully obtained the data from the file included in directory. 401 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 402 @retval Others Operation failed. 403 404**/ 405EFI_STATUS 406PxeBcMtftp6ReadDirectory ( 407 IN PXEBC_PRIVATE_DATA *Private, 408 IN EFI_MTFTP6_CONFIG_DATA *Config, 409 IN UINT8 *Filename, 410 IN UINTN *BlockSize, 411 IN UINT8 *BufferPtr, 412 IN OUT UINT64 *BufferSize, 413 IN BOOLEAN DontUseBuffer 414 ) 415{ 416 EFI_MTFTP6_PROTOCOL *Mtftp6; 417 EFI_MTFTP6_TOKEN Token; 418 EFI_MTFTP6_OPTION ReqOpt[1]; 419 UINT32 OptCnt; 420 UINT8 OptBuf[128]; 421 EFI_STATUS Status; 422 423 Status = EFI_DEVICE_ERROR; 424 Mtftp6 = Private->Mtftp6; 425 OptCnt = 0; 426 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 427 428 Status = Mtftp6->Configure (Mtftp6, Config); 429 if (EFI_ERROR (Status)) { 430 return Status; 431 } 432 433 if (BlockSize != NULL) { 434 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 435 ReqOpt[0].ValueStr = OptBuf; 436 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 437 OptCnt++; 438 } 439 440 Token.Event = NULL; 441 Token.OverrideData = NULL; 442 Token.Filename = Filename; 443 Token.ModeStr = NULL; 444 Token.OptionCount = OptCnt; 445 Token.OptionList = ReqOpt; 446 Token.Context = Private; 447 448 if (DontUseBuffer) { 449 Token.BufferSize = 0; 450 Token.Buffer = NULL; 451 } else { 452 Token.BufferSize = *BufferSize; 453 Token.Buffer = BufferPtr; 454 } 455 456 Token.CheckPacket = PxeBcMtftp6CheckPacket; 457 Token.TimeoutCallback = NULL; 458 Token.PacketNeeded = NULL; 459 460 Status = Mtftp6->ReadDirectory (Mtftp6, &Token); 461 // 462 // Get the real size of received buffer. 463 // 464 *BufferSize = Token.BufferSize; 465 466 Mtftp6->Configure (Mtftp6, NULL); 467 468 return Status; 469} 470 471 472/** 473 This is a callback function when packets are received or transmitted in Mtftp driver. 474 475 A callback function that is provided by the caller to intercept 476 the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the 477 EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept 478 EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to 479 EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). 480 481 @param[in] This Pointer to EFI_MTFTP4_PROTOCOL. 482 @param[in] Token Pointer to EFI_MTFTP4_TOKEN. 483 @param[in] PacketLen Length of EFI_MTFTP4_PACKET. 484 @param[in] Packet Pointer to EFI_MTFTP4_PACKET to be checked. 485 486 @retval EFI_SUCCESS The current operation succeeeded. 487 @retval EFI_ABORTED Abort the current transfer process. 488 489**/ 490EFI_STATUS 491EFIAPI 492PxeBcMtftp4CheckPacket ( 493 IN EFI_MTFTP4_PROTOCOL *This, 494 IN EFI_MTFTP4_TOKEN *Token, 495 IN UINT16 PacketLen, 496 IN EFI_MTFTP4_PACKET *Packet 497 ) 498{ 499 PXEBC_PRIVATE_DATA *Private; 500 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; 501 EFI_STATUS Status; 502 503 Private = (PXEBC_PRIVATE_DATA *) Token->Context; 504 Callback = Private->PxeBcCallback; 505 Status = EFI_SUCCESS; 506 507 if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) { 508 // 509 // Store the tftp error message into mode data and set the received flag. 510 // 511 Private->Mode.TftpErrorReceived = TRUE; 512 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 513 AsciiStrnCpyS ( 514 Private->Mode.TftpError.ErrorString, 515 PXE_MTFTP_ERROR_STRING_LENGTH, 516 (CHAR8 *) Packet->Error.ErrorMessage, 517 PXE_MTFTP_ERROR_STRING_LENGTH - 1 518 ); 519 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 520 } 521 522 if (Callback != NULL) { 523 // 524 // Callback to user if has when received any tftp packet. 525 // 526 Status = Callback->Callback ( 527 Callback, 528 Private->Function, 529 TRUE, 530 PacketLen, 531 (EFI_PXE_BASE_CODE_PACKET *) Packet 532 ); 533 if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { 534 // 535 // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. 536 // 537 Status = EFI_ABORTED; 538 } else { 539 // 540 // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. 541 // 542 Status = EFI_SUCCESS; 543 } 544 } 545 546 return Status; 547} 548 549 550/** 551 This function is to get size of a file using Tftp. 552 553 @param[in] Private Pointer to PxeBc private data. 554 @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. 555 @param[in] Filename Pointer to boot file name. 556 @param[in] BlockSize Pointer to required block size. 557 @param[in, out] BufferSize Pointer to buffer size. 558 559 @retval EFI_SUCCESS Successfully obtained the size of file. 560 @retval EFI_NOT_FOUND Parse the tftp options failed. 561 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 562 @retval Others Did not obtain the size of the file. 563 564**/ 565EFI_STATUS 566PxeBcMtftp4GetFileSize ( 567 IN PXEBC_PRIVATE_DATA *Private, 568 IN EFI_MTFTP4_CONFIG_DATA *Config, 569 IN UINT8 *Filename, 570 IN UINTN *BlockSize, 571 IN OUT UINT64 *BufferSize 572 ) 573{ 574 EFI_MTFTP4_PROTOCOL *Mtftp4; 575 EFI_MTFTP4_OPTION ReqOpt[2]; 576 EFI_MTFTP4_PACKET *Packet; 577 EFI_MTFTP4_OPTION *Option; 578 UINT32 PktLen; 579 UINT8 OptBuf[128]; 580 UINT32 OptCnt; 581 EFI_STATUS Status; 582 583 *BufferSize = 0; 584 Status = EFI_DEVICE_ERROR; 585 Mtftp4 = Private->Mtftp4; 586 Packet = NULL; 587 Option = NULL; 588 PktLen = 0; 589 OptCnt = 1; 590 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 591 592 Status = Mtftp4->Configure (Mtftp4, Config); 593 if (EFI_ERROR (Status)) { 594 return Status; 595 } 596 597 // 598 // Build the required options for get info. 599 // 600 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; 601 PxeBcUintnToAscDec (0, OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 602 ReqOpt[0].ValueStr = OptBuf; 603 604 if (BlockSize != NULL) { 605 ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 606 ReqOpt[1].ValueStr = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1); 607 PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1)); 608 OptCnt++; 609 } 610 611 Status = Mtftp4->GetInfo ( 612 Mtftp4, 613 NULL, 614 Filename, 615 NULL, 616 (UINT8) OptCnt, 617 ReqOpt, 618 &PktLen, 619 &Packet 620 ); 621 if (EFI_ERROR (Status)) { 622 if (Status == EFI_TFTP_ERROR) { 623 // 624 // Store the tftp error message into mode data and set the received flag. 625 // 626 Private->Mode.TftpErrorReceived = TRUE; 627 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; 628 AsciiStrnCpyS ( 629 Private->Mode.TftpError.ErrorString, 630 PXE_MTFTP_ERROR_STRING_LENGTH, 631 (CHAR8 *) Packet->Error.ErrorMessage, 632 PXE_MTFTP_ERROR_STRING_LENGTH - 1 633 ); 634 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; 635 } 636 goto ON_ERROR; 637 } 638 639 // 640 // Parse the options in the reply packet. 641 // 642 OptCnt = 0; 643 Status = Mtftp4->ParseOptions ( 644 Mtftp4, 645 PktLen, 646 Packet, 647 (UINT32 *) &OptCnt, 648 &Option 649 ); 650 if (EFI_ERROR (Status)) { 651 goto ON_ERROR; 652 } 653 654 // 655 // Parse out the value of "tsize" option. 656 // 657 Status = EFI_NOT_FOUND; 658 while (OptCnt != 0) { 659 if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { 660 *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); 661 Status = EFI_SUCCESS; 662 } 663 OptCnt--; 664 } 665 FreePool (Option); 666 667ON_ERROR: 668 if (Packet != NULL) { 669 FreePool (Packet); 670 } 671 Mtftp4->Configure (Mtftp4, NULL); 672 673 return Status; 674} 675 676 677/** 678 This function is to read the data of a file using Tftp. 679 680 @param[in] Private Pointer to PxeBc private data. 681 @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. 682 @param[in] Filename Pointer to boot file name. 683 @param[in] BlockSize Pointer to required block size. 684 @param[in] BufferPtr Pointer to buffer. 685 @param[in, out] BufferSize Pointer to buffer size. 686 @param[in] DontUseBuffer Indicates whether to use a receive buffer. 687 688 @retval EFI_SUCCESS Successfully read the data from the special file. 689 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 690 @retval Others Read data from file failed. 691 692**/ 693EFI_STATUS 694PxeBcMtftp4ReadFile ( 695 IN PXEBC_PRIVATE_DATA *Private, 696 IN EFI_MTFTP4_CONFIG_DATA *Config, 697 IN UINT8 *Filename, 698 IN UINTN *BlockSize, 699 IN UINT8 *BufferPtr, 700 IN OUT UINT64 *BufferSize, 701 IN BOOLEAN DontUseBuffer 702 ) 703{ 704 EFI_MTFTP4_PROTOCOL *Mtftp4; 705 EFI_MTFTP4_TOKEN Token; 706 EFI_MTFTP4_OPTION ReqOpt[1]; 707 UINT32 OptCnt; 708 UINT8 OptBuf[128]; 709 EFI_STATUS Status; 710 711 Status = EFI_DEVICE_ERROR; 712 Mtftp4 = Private->Mtftp4; 713 OptCnt = 0; 714 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 715 716 Status = Mtftp4->Configure (Mtftp4, Config); 717 if (EFI_ERROR (Status)) { 718 return Status; 719 } 720 721 if (BlockSize != NULL) { 722 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 723 ReqOpt[0].ValueStr = OptBuf; 724 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 725 OptCnt++; 726 } 727 728 Token.Event = NULL; 729 Token.OverrideData = NULL; 730 Token.Filename = Filename; 731 Token.ModeStr = NULL; 732 Token.OptionCount = OptCnt; 733 Token.OptionList = ReqOpt; 734 Token.Context = Private; 735 736 if (DontUseBuffer) { 737 Token.BufferSize = 0; 738 Token.Buffer = NULL; 739 } else { 740 Token.BufferSize = *BufferSize; 741 Token.Buffer = BufferPtr; 742 } 743 744 Token.CheckPacket = PxeBcMtftp4CheckPacket; 745 Token.TimeoutCallback = NULL; 746 Token.PacketNeeded = NULL; 747 748 Status = Mtftp4->ReadFile (Mtftp4, &Token); 749 // 750 // Get the real size of received buffer. 751 // 752 *BufferSize = Token.BufferSize; 753 754 Mtftp4->Configure (Mtftp4, NULL); 755 756 return Status; 757} 758 759 760/** 761 This function is to write the data of a file using Tftp. 762 763 @param[in] Private Pointer to PxeBc private data. 764 @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. 765 @param[in] Filename Pointer to boot file name. 766 @param[in] Overwrite Indicates whether to use the overwrite attribute. 767 @param[in] BlockSize Pointer to required block size. 768 @param[in] BufferPtr Pointer to buffer. 769 @param[in, out] BufferSize Pointer to buffer size. 770 771 @retval EFI_SUCCESS Successfully write the data into the special file. 772 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 773 @retval other Write data into file failed. 774 775**/ 776EFI_STATUS 777PxeBcMtftp4WriteFile ( 778 IN PXEBC_PRIVATE_DATA *Private, 779 IN EFI_MTFTP4_CONFIG_DATA *Config, 780 IN UINT8 *Filename, 781 IN BOOLEAN Overwrite, 782 IN UINTN *BlockSize, 783 IN UINT8 *BufferPtr, 784 IN OUT UINT64 *BufferSize 785 ) 786{ 787 EFI_MTFTP4_PROTOCOL *Mtftp4; 788 EFI_MTFTP4_TOKEN Token; 789 EFI_MTFTP4_OPTION ReqOpt[1]; 790 UINT32 OptCnt; 791 UINT8 OptBuf[128]; 792 EFI_STATUS Status; 793 794 Status = EFI_DEVICE_ERROR; 795 Mtftp4 = Private->Mtftp4; 796 OptCnt = 0; 797 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 798 799 Status = Mtftp4->Configure (Mtftp4, Config); 800 if (EFI_ERROR (Status)) { 801 return Status; 802 } 803 804 if (BlockSize != NULL) { 805 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 806 ReqOpt[0].ValueStr = OptBuf; 807 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 808 OptCnt++; 809 } 810 811 Token.Event = NULL; 812 Token.OverrideData = NULL; 813 Token.Filename = Filename; 814 Token.ModeStr = NULL; 815 Token.OptionCount = OptCnt; 816 Token.OptionList = ReqOpt; 817 Token.BufferSize = *BufferSize; 818 Token.Buffer = BufferPtr; 819 Token.CheckPacket = PxeBcMtftp4CheckPacket; 820 Token.TimeoutCallback = NULL; 821 Token.PacketNeeded = NULL; 822 823 Status = Mtftp4->WriteFile (Mtftp4, &Token); 824 // 825 // Get the real size of transmitted buffer. 826 // 827 *BufferSize = Token.BufferSize; 828 829 Mtftp4->Configure (Mtftp4, NULL); 830 831 return Status; 832} 833 834 835/** 836 This function is to get data (file) from a directory using Tftp. 837 838 @param[in] Private Pointer to PxeBc private data. 839 @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. 840 @param[in] Filename Pointer to boot file name. 841 @param[in] BlockSize Pointer to required block size. 842 @param[in] BufferPtr Pointer to buffer. 843 @param[in, out] BufferSize Pointer to buffer size. 844 @param[in] DontUseBuffer Indicates whether to use a receive buffer. 845 846 @retval EFI_SUCCES Successfully obtained the data from the file included in the directory. 847 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 848 @retval Others Operation failed. 849 850**/ 851EFI_STATUS 852PxeBcMtftp4ReadDirectory ( 853 IN PXEBC_PRIVATE_DATA *Private, 854 IN EFI_MTFTP4_CONFIG_DATA *Config, 855 IN UINT8 *Filename, 856 IN UINTN *BlockSize, 857 IN UINT8 *BufferPtr, 858 IN OUT UINT64 *BufferSize, 859 IN BOOLEAN DontUseBuffer 860 ) 861{ 862 EFI_MTFTP4_PROTOCOL *Mtftp4; 863 EFI_MTFTP4_TOKEN Token; 864 EFI_MTFTP4_OPTION ReqOpt[1]; 865 UINT32 OptCnt; 866 UINT8 OptBuf[128]; 867 EFI_STATUS Status; 868 869 Status = EFI_DEVICE_ERROR; 870 Mtftp4 = Private->Mtftp4; 871 OptCnt = 0; 872 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; 873 874 Status = Mtftp4->Configure (Mtftp4, Config); 875 if (EFI_ERROR (Status)) { 876 return Status; 877 } 878 879 if (BlockSize != NULL) { 880 ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; 881 ReqOpt[0].ValueStr = OptBuf; 882 PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); 883 OptCnt++; 884 } 885 886 Token.Event = NULL; 887 Token.OverrideData = NULL; 888 Token.Filename = Filename; 889 Token.ModeStr = NULL; 890 Token.OptionCount = OptCnt; 891 Token.OptionList = ReqOpt; 892 Token.Context = Private; 893 894 if (DontUseBuffer) { 895 Token.BufferSize = 0; 896 Token.Buffer = NULL; 897 } else { 898 Token.BufferSize = *BufferSize; 899 Token.Buffer = BufferPtr; 900 } 901 902 Token.CheckPacket = PxeBcMtftp4CheckPacket; 903 Token.TimeoutCallback = NULL; 904 Token.PacketNeeded = NULL; 905 906 Status = Mtftp4->ReadDirectory (Mtftp4, &Token); 907 // 908 // Get the real size of received buffer. 909 // 910 *BufferSize = Token.BufferSize; 911 912 Mtftp4->Configure (Mtftp4, NULL); 913 914 return Status; 915} 916 917 918/** 919 This function is wrapper to get the file size using TFTP. 920 921 @param[in] Private Pointer to PxeBc private data. 922 @param[in] Config Pointer to configure data. 923 @param[in] Filename Pointer to boot file name. 924 @param[in] BlockSize Pointer to required block size. 925 @param[in, out] BufferSize Pointer to buffer size. 926 927 @retval EFI_SUCCESS Successfully obtained the size of file. 928 @retval EFI_NOT_FOUND Parse the tftp options failed. 929 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 930 @retval Others Did not obtain the size of the file. 931 932**/ 933EFI_STATUS 934PxeBcTftpGetFileSize ( 935 IN PXEBC_PRIVATE_DATA *Private, 936 IN VOID *Config, 937 IN UINT8 *Filename, 938 IN UINTN *BlockSize, 939 IN OUT UINT64 *BufferSize 940 ) 941{ 942 if (Private->PxeBc.Mode->UsingIpv6) { 943 return PxeBcMtftp6GetFileSize ( 944 Private, 945 (EFI_MTFTP6_CONFIG_DATA *) Config, 946 Filename, 947 BlockSize, 948 BufferSize 949 ); 950 } else { 951 return PxeBcMtftp4GetFileSize ( 952 Private, 953 (EFI_MTFTP4_CONFIG_DATA *) Config, 954 Filename, 955 BlockSize, 956 BufferSize 957 ); 958 } 959} 960 961 962/** 963 This function is a wrapper to get file using TFTP. 964 965 @param[in] Private Pointer to PxeBc private data. 966 @param[in] Config Pointer to config data. 967 @param[in] Filename Pointer to boot file name. 968 @param[in] BlockSize Pointer to required block size. 969 @param[in] BufferPtr Pointer to buffer. 970 @param[in, out] BufferSize Pointer to buffer size. 971 @param[in] DontUseBuffer Indicates whether to use a receive buffer. 972 973 @retval EFI_SUCCESS Sucessfully read the data from the special file. 974 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 975 @retval Others Read data from file failed. 976 977**/ 978EFI_STATUS 979PxeBcTftpReadFile ( 980 IN PXEBC_PRIVATE_DATA *Private, 981 IN VOID *Config, 982 IN UINT8 *Filename, 983 IN UINTN *BlockSize, 984 IN UINT8 *BufferPtr, 985 IN OUT UINT64 *BufferSize, 986 IN BOOLEAN DontUseBuffer 987 ) 988{ 989 if (Private->PxeBc.Mode->UsingIpv6) { 990 return PxeBcMtftp6ReadFile ( 991 Private, 992 (EFI_MTFTP6_CONFIG_DATA *) Config, 993 Filename, 994 BlockSize, 995 BufferPtr, 996 BufferSize, 997 DontUseBuffer 998 ); 999 } else { 1000 return PxeBcMtftp4ReadFile ( 1001 Private, 1002 (EFI_MTFTP4_CONFIG_DATA *) Config, 1003 Filename, 1004 BlockSize, 1005 BufferPtr, 1006 BufferSize, 1007 DontUseBuffer 1008 ); 1009 } 1010} 1011 1012 1013/** 1014 This function is a wrapper to write file using TFTP. 1015 1016 @param[in] Private Pointer to PxeBc private data. 1017 @param[in] Config Pointer to config data. 1018 @param[in] Filename Pointer to boot file name. 1019 @param[in] Overwrite Indicate whether with overwrite attribute. 1020 @param[in] BlockSize Pointer to required block size. 1021 @param[in] BufferPtr Pointer to buffer. 1022 @param[in, out] BufferSize Pointer to buffer size. 1023 1024 @retval EFI_SUCCESS Successfully wrote the data into a special file. 1025 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 1026 @retval other Write data into file failed. 1027 1028**/ 1029EFI_STATUS 1030PxeBcTftpWriteFile ( 1031 IN PXEBC_PRIVATE_DATA *Private, 1032 IN VOID *Config, 1033 IN UINT8 *Filename, 1034 IN BOOLEAN Overwrite, 1035 IN UINTN *BlockSize, 1036 IN UINT8 *BufferPtr, 1037 IN OUT UINT64 *BufferSize 1038 ) 1039{ 1040 if (Private->PxeBc.Mode->UsingIpv6) { 1041 return PxeBcMtftp6WriteFile ( 1042 Private, 1043 (EFI_MTFTP6_CONFIG_DATA *) Config, 1044 Filename, 1045 Overwrite, 1046 BlockSize, 1047 BufferPtr, 1048 BufferSize 1049 ); 1050 } else { 1051 return PxeBcMtftp4WriteFile ( 1052 Private, 1053 (EFI_MTFTP4_CONFIG_DATA *) Config, 1054 Filename, 1055 Overwrite, 1056 BlockSize, 1057 BufferPtr, 1058 BufferSize 1059 ); 1060 } 1061} 1062 1063 1064/** 1065 This function is a wrapper to get the data (file) from a directory using TFTP. 1066 1067 @param[in] Private Pointer to PxeBc private data. 1068 @param[in] Config Pointer to config data. 1069 @param[in] Filename Pointer to boot file name. 1070 @param[in] BlockSize Pointer to required block size. 1071 @param[in] BufferPtr Pointer to buffer. 1072 @param[in, out] BufferSize Pointer to buffer size. 1073 @param[in] DontUseBuffer Indicatse whether to use a receive buffer. 1074 1075 @retval EFI_SUCCES Successfully obtained the data from the file included in the directory. 1076 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. 1077 @retval Others Operation failed. 1078 1079**/ 1080EFI_STATUS 1081PxeBcTftpReadDirectory ( 1082 IN PXEBC_PRIVATE_DATA *Private, 1083 IN VOID *Config, 1084 IN UINT8 *Filename, 1085 IN UINTN *BlockSize, 1086 IN UINT8 *BufferPtr, 1087 IN OUT UINT64 *BufferSize, 1088 IN BOOLEAN DontUseBuffer 1089 ) 1090{ 1091 if (Private->PxeBc.Mode->UsingIpv6) { 1092 return PxeBcMtftp6ReadDirectory ( 1093 Private, 1094 (EFI_MTFTP6_CONFIG_DATA *) Config, 1095 Filename, 1096 BlockSize, 1097 BufferPtr, 1098 BufferSize, 1099 DontUseBuffer 1100 ); 1101 } else { 1102 return PxeBcMtftp4ReadDirectory ( 1103 Private, 1104 (EFI_MTFTP4_CONFIG_DATA *) Config, 1105 Filename, 1106 BlockSize, 1107 BufferPtr, 1108 BufferSize, 1109 DontUseBuffer 1110 ); 1111 } 1112} 1113 1114