1 /** @file 2 Routines to process Rrq (download). 3 4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 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<BR> 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 17 #include "Mtftp4Impl.h" 18 19 20 /** 21 The packet process callback for MTFTP download. 22 23 @param UdpPacket The packet received 24 @param EndPoint The local/remote access point of the packet 25 @param IoStatus The status of the receiving 26 @param Context Opaque parameter, which is the MTFTP session 27 28 **/ 29 VOID 30 EFIAPI 31 Mtftp4RrqInput ( 32 IN NET_BUF *UdpPacket, 33 IN UDP_END_POINT *EndPoint, 34 IN EFI_STATUS IoStatus, 35 IN VOID *Context 36 ); 37 38 39 /** 40 Start the MTFTP session to download. 41 42 It will first initialize some of the internal states then build and send a RRQ 43 reqeuest packet, at last, it will start receive for the downloading. 44 45 @param Instance The Mtftp session 46 @param Operation The MTFTP opcode, it may be a EFI_MTFTP4_OPCODE_RRQ 47 or EFI_MTFTP4_OPCODE_DIR. 48 49 @retval EFI_SUCCESS The mtftp download session is started. 50 @retval Others Failed to start downloading. 51 52 **/ 53 EFI_STATUS 54 Mtftp4RrqStart ( 55 IN MTFTP4_PROTOCOL *Instance, 56 IN UINT16 Operation 57 ) 58 { 59 EFI_STATUS Status; 60 61 // 62 // The valid block number range are [1, 0xffff]. For example: 63 // the client sends an RRQ request to the server, the server 64 // transfers the DATA1 block. If option negoitation is ongoing, 65 // the server will send back an OACK, then client will send ACK0. 66 // 67 Status = Mtftp4InitBlockRange (&Instance->Blocks, 1, 0xffff); 68 69 if (EFI_ERROR (Status)) { 70 return Status; 71 } 72 73 Status = Mtftp4SendRequest (Instance); 74 75 if (EFI_ERROR (Status)) { 76 return Status; 77 } 78 79 return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0); 80 } 81 82 83 /** 84 Build and send a ACK packet for the download session. 85 86 @param Instance The Mtftp session 87 @param BlkNo The BlkNo to ack. 88 89 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet 90 @retval EFI_SUCCESS The ACK has been sent 91 @retval Others Failed to send the ACK. 92 93 **/ 94 EFI_STATUS 95 Mtftp4RrqSendAck ( 96 IN MTFTP4_PROTOCOL *Instance, 97 IN UINT16 BlkNo 98 ) 99 { 100 EFI_MTFTP4_PACKET *Ack; 101 NET_BUF *Packet; 102 103 Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER)); 104 if (Packet == NULL) { 105 return EFI_OUT_OF_RESOURCES; 106 } 107 108 Ack = (EFI_MTFTP4_PACKET *) NetbufAllocSpace ( 109 Packet, 110 sizeof (EFI_MTFTP4_ACK_HEADER), 111 FALSE 112 ); 113 ASSERT (Ack != NULL); 114 115 Ack->Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK); 116 Ack->Ack.Block[0] = HTONS (BlkNo); 117 118 return Mtftp4SendPacket (Instance, Packet); 119 } 120 121 122 /** 123 Deliver the received data block to the user, which can be saved 124 in the user provide buffer or through the CheckPacket callback. 125 126 @param Instance The Mtftp session 127 @param Packet The received data packet 128 @param Len The packet length 129 130 @retval EFI_SUCCESS The data is saved successfully 131 @retval EFI_ABORTED The user tells to abort by return an error through 132 CheckPacket 133 @retval EFI_BUFFER_TOO_SMALL The user's buffer is too small and buffer length is 134 updated to the actual buffer size needed. 135 136 **/ 137 EFI_STATUS 138 Mtftp4RrqSaveBlock ( 139 IN OUT MTFTP4_PROTOCOL *Instance, 140 IN EFI_MTFTP4_PACKET *Packet, 141 IN UINT32 Len 142 ) 143 { 144 EFI_MTFTP4_TOKEN *Token; 145 EFI_STATUS Status; 146 UINT16 Block; 147 UINT64 Start; 148 UINT32 DataLen; 149 UINT64 TotalBlock; 150 BOOLEAN Completed; 151 152 Completed = FALSE; 153 Token = Instance->Token; 154 Block = NTOHS (Packet->Data.Block); 155 DataLen = Len - MTFTP4_DATA_HEAD_LEN; 156 157 // 158 // This is the last block, save the block no 159 // 160 if (DataLen < Instance->BlkSize) { 161 Completed = TRUE; 162 Instance->LastBlock = Block; 163 Mtftp4SetLastBlockNum (&Instance->Blocks, Block); 164 } 165 166 // 167 // Remove this block number from the file hole. If Mtftp4RemoveBlockNum 168 // returns EFI_NOT_FOUND, the block has been saved, don't save it again. 169 // Note that : For bigger files, allowing the block counter to roll over 170 // to accept transfers of unlimited size. So TotalBlock is memorised as 171 // continuous block counter. 172 // 173 Status = Mtftp4RemoveBlockNum (&Instance->Blocks, Block, Completed, &TotalBlock); 174 175 if (Status == EFI_NOT_FOUND) { 176 return EFI_SUCCESS; 177 } else if (EFI_ERROR (Status)) { 178 return Status; 179 } 180 181 if (Token->CheckPacket != NULL) { 182 Status = Token->CheckPacket (&Instance->Mtftp4, Token, (UINT16) Len, Packet); 183 184 if (EFI_ERROR (Status)) { 185 Mtftp4SendError ( 186 Instance, 187 EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, 188 (UINT8 *) "User aborted download" 189 ); 190 191 return EFI_ABORTED; 192 } 193 } 194 195 if (Token->Buffer != NULL) { 196 Start = MultU64x32 (TotalBlock - 1, Instance->BlkSize); 197 198 if (Start + DataLen <= Token->BufferSize) { 199 CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen); 200 201 // 202 // Update the file size when received the last block 203 // 204 if ((Instance->LastBlock == Block) && Completed) { 205 Token->BufferSize = Start + DataLen; 206 } 207 208 } else if (Instance->LastBlock != 0) { 209 // 210 // Don't save the data if the buffer is too small, return 211 // EFI_BUFFER_TOO_SMALL if received the last packet. This 212 // will give a accurate file length. 213 // 214 Token->BufferSize = Start + DataLen; 215 216 Mtftp4SendError ( 217 Instance, 218 EFI_MTFTP4_ERRORCODE_DISK_FULL, 219 (UINT8 *) "User provided memory block is too small" 220 ); 221 222 return EFI_BUFFER_TOO_SMALL; 223 } 224 } 225 226 return EFI_SUCCESS; 227 } 228 229 230 /** 231 Function to process the received data packets. 232 233 It will save the block then send back an ACK if it is active. 234 235 @param Instance The downloading MTFTP session 236 @param Packet The packet received 237 @param Len The length of the packet 238 @param Multicast Whether this packet is multicast or unicast 239 @param Completed Return whether the download has completed 240 241 @retval EFI_SUCCESS The data packet is successfully processed 242 @retval EFI_ABORTED The download is aborted by the user 243 @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small 244 245 **/ 246 EFI_STATUS 247 Mtftp4RrqHandleData ( 248 IN MTFTP4_PROTOCOL *Instance, 249 IN EFI_MTFTP4_PACKET *Packet, 250 IN UINT32 Len, 251 IN BOOLEAN Multicast, 252 OUT BOOLEAN *Completed 253 ) 254 { 255 EFI_STATUS Status; 256 UINT16 BlockNum; 257 INTN Expected; 258 259 *Completed = FALSE; 260 BlockNum = NTOHS (Packet->Data.Block); 261 Expected = Mtftp4GetNextBlockNum (&Instance->Blocks); 262 263 ASSERT (Expected >= 0); 264 265 // 266 // If we are active and received an unexpected packet, retransmit 267 // the last ACK then restart receiving. If we are passive, save 268 // the block. 269 // 270 if (Instance->Master && (Expected != BlockNum)) { 271 Mtftp4Retransmit (Instance); 272 return EFI_SUCCESS; 273 } 274 275 Status = Mtftp4RrqSaveBlock (Instance, Packet, Len); 276 277 if (EFI_ERROR (Status)) { 278 return Status; 279 } 280 281 // 282 // Reset the passive client's timer whenever it received a 283 // valid data packet. 284 // 285 if (!Instance->Master) { 286 Mtftp4SetTimeout (Instance); 287 } 288 289 // 290 // Check whether we have received all the blocks. Send the ACK if we 291 // are active (unicast client or master client for multicast download). 292 // If we have received all the blocks, send an ACK even if we are passive 293 // to tell the server that we are done. 294 // 295 Expected = Mtftp4GetNextBlockNum (&Instance->Blocks); 296 297 if (Instance->Master || (Expected < 0)) { 298 if (Expected < 0) { 299 // 300 // If we are passive client, then the just received Block maybe 301 // isn't the last block. We need to send an ACK to the last block 302 // to inform the server that we are done. If we are active client, 303 // the Block == Instance->LastBlock. 304 // 305 BlockNum = Instance->LastBlock; 306 *Completed = TRUE; 307 308 } else { 309 BlockNum = (UINT16) (Expected - 1); 310 } 311 312 Mtftp4RrqSendAck (Instance, BlockNum); 313 } 314 315 return EFI_SUCCESS; 316 } 317 318 319 /** 320 Validate whether the options received in the server's OACK packet is valid. 321 322 The options are valid only if: 323 1. The server doesn't include options not requested by us 324 2. The server can only use smaller blksize than that is requested 325 3. The server can only use the same timeout as requested 326 4. The server doesn't change its multicast channel. 327 328 @param This The downloading Mtftp session 329 @param Reply The options in the OACK packet 330 @param Request The requested options 331 332 @retval TRUE The options in the OACK is OK. 333 @retval FALSE The options in the OACK is invalid. 334 335 **/ 336 BOOLEAN 337 Mtftp4RrqOackValid ( 338 IN MTFTP4_PROTOCOL *This, 339 IN MTFTP4_OPTION *Reply, 340 IN MTFTP4_OPTION *Request 341 ) 342 { 343 344 // 345 // It is invalid for server to return options we don't request 346 // 347 if ((Reply->Exist &~Request->Exist) != 0) { 348 return FALSE; 349 } 350 351 // 352 // Server can only specify a smaller block size to be used and 353 // return the timeout matches that requested. 354 // 355 if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0)&& (Reply->BlkSize > Request->BlkSize)) || 356 (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) { 357 return FALSE; 358 } 359 360 // 361 // The server can send ",,master" to client to change its master 362 // setting. But if it use the specific multicast channel, it can't 363 // change the setting. 364 // 365 if (((Reply->Exist & MTFTP4_MCAST_EXIST) != 0) && (This->McastIp != 0)) { 366 if ((Reply->McastIp != 0) && (Reply->McastIp != This->McastIp)) { 367 return FALSE; 368 } 369 370 if ((Reply->McastPort != 0) && (Reply->McastPort != This->McastPort)) { 371 return FALSE; 372 } 373 } 374 375 return TRUE; 376 } 377 378 379 /** 380 Configure a UDP IO port to receive the multicast. 381 382 @param McastIo The UDP IO to configure 383 @param Context The opaque parameter to the function which is the 384 MTFTP session. 385 386 @retval EFI_SUCCESS The UDP child is successfully configured. 387 @retval Others Failed to configure the UDP child. 388 389 **/ 390 EFI_STATUS 391 EFIAPI 392 Mtftp4RrqConfigMcastPort ( 393 IN UDP_IO *McastIo, 394 IN VOID *Context 395 ) 396 { 397 MTFTP4_PROTOCOL *Instance; 398 EFI_MTFTP4_CONFIG_DATA *Config; 399 EFI_UDP4_CONFIG_DATA UdpConfig; 400 EFI_IPv4_ADDRESS Group; 401 EFI_STATUS Status; 402 IP4_ADDR Ip; 403 404 Instance = (MTFTP4_PROTOCOL *) Context; 405 Config = &Instance->Config; 406 407 UdpConfig.AcceptBroadcast = FALSE; 408 UdpConfig.AcceptPromiscuous = FALSE; 409 UdpConfig.AcceptAnyPort = FALSE; 410 UdpConfig.AllowDuplicatePort = FALSE; 411 UdpConfig.TypeOfService = 0; 412 UdpConfig.TimeToLive = 64; 413 UdpConfig.DoNotFragment = FALSE; 414 UdpConfig.ReceiveTimeout = 0; 415 UdpConfig.TransmitTimeout = 0; 416 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting; 417 IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp); 418 IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask); 419 UdpConfig.StationPort = Instance->McastPort; 420 UdpConfig.RemotePort = 0; 421 422 Ip = HTONL (Instance->ServerIp); 423 IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip); 424 425 Status = McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, &UdpConfig); 426 427 if (EFI_ERROR (Status)) { 428 return Status; 429 } 430 431 if (!Config->UseDefaultSetting && 432 !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) { 433 // 434 // The station IP address is manually configured and the Gateway IP is not 0. 435 // Add the default route for this UDP instance. 436 // 437 Status = McastIo->Protocol.Udp4->Routes ( 438 McastIo->Protocol.Udp4, 439 FALSE, 440 &mZeroIp4Addr, 441 &mZeroIp4Addr, 442 &Config->GatewayIp 443 ); 444 445 if (EFI_ERROR (Status)) { 446 McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, NULL); 447 return Status; 448 } 449 } 450 451 // 452 // join the multicast group 453 // 454 Ip = HTONL (Instance->McastIp); 455 IP4_COPY_ADDRESS (&Group, &Ip); 456 457 return McastIo->Protocol.Udp4->Groups (McastIo->Protocol.Udp4, TRUE, &Group); 458 } 459 460 461 /** 462 Function to process the OACK. 463 464 It will first validate the OACK packet, then update the various negotiated parameters. 465 466 @param Instance The download MTFTP session 467 @param Packet The packet received 468 @param Len The packet length 469 @param Multicast Whether this packet is received as a multicast 470 @param Completed Returns whether the download has completed. NOT 471 used by this function. 472 473 @retval EFI_DEVICE_ERROR Failed to create/start a multicast UDP child 474 @retval EFI_TFTP_ERROR Some error happened during the process 475 @retval EFI_SUCCESS The OACK is successfully processed. 476 477 **/ 478 EFI_STATUS 479 Mtftp4RrqHandleOack ( 480 IN OUT MTFTP4_PROTOCOL *Instance, 481 IN EFI_MTFTP4_PACKET *Packet, 482 IN UINT32 Len, 483 IN BOOLEAN Multicast, 484 OUT BOOLEAN *Completed 485 ) 486 { 487 MTFTP4_OPTION Reply; 488 EFI_STATUS Status; 489 INTN Expected; 490 EFI_UDP4_PROTOCOL *Udp4; 491 492 *Completed = FALSE; 493 494 // 495 // If already started the master download, don't change the 496 // setting. Master download always succeeds. 497 // 498 Expected = Mtftp4GetNextBlockNum (&Instance->Blocks); 499 ASSERT (Expected != -1); 500 501 if (Instance->Master && (Expected != 1)) { 502 return EFI_SUCCESS; 503 } 504 505 // 506 // Parse and validate the options from server 507 // 508 ZeroMem (&Reply, sizeof (MTFTP4_OPTION)); 509 510 Status = Mtftp4ParseOptionOack (Packet, Len, &Reply); 511 512 if (EFI_ERROR (Status) || 513 !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) { 514 // 515 // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES. 516 // 517 if (Status != EFI_OUT_OF_RESOURCES) { 518 Mtftp4SendError ( 519 Instance, 520 EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, 521 (UINT8 *) "Mal-formated OACK packet" 522 ); 523 } 524 525 return EFI_TFTP_ERROR; 526 } 527 528 if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) { 529 530 // 531 // Save the multicast info. Always update the Master, only update the 532 // multicast IP address, block size, timeoute at the first time. If IP 533 // address is updated, create a UDP child to receive the multicast. 534 // 535 Instance->Master = Reply.Master; 536 537 if (Instance->McastIp == 0) { 538 if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) { 539 Mtftp4SendError ( 540 Instance, 541 EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, 542 (UINT8 *) "Illegal multicast setting" 543 ); 544 545 return EFI_TFTP_ERROR; 546 } 547 548 // 549 // Create a UDP child then start receive the multicast from it. 550 // 551 Instance->McastIp = Reply.McastIp; 552 Instance->McastPort = Reply.McastPort; 553 if (Instance->McastUdpPort == NULL) { 554 Instance->McastUdpPort = UdpIoCreateIo ( 555 Instance->Service->Controller, 556 Instance->Service->Image, 557 Mtftp4RrqConfigMcastPort, 558 UDP_IO_UDP4_VERSION, 559 Instance 560 ); 561 if (Instance->McastUdpPort != NULL) { 562 Status = gBS->OpenProtocol ( 563 Instance->McastUdpPort->UdpHandle, 564 &gEfiUdp4ProtocolGuid, 565 (VOID **) &Udp4, 566 Instance->Service->Image, 567 Instance->Handle, 568 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 569 ); 570 if (EFI_ERROR (Status)) { 571 UdpIoFreeIo (Instance->McastUdpPort); 572 Instance->McastUdpPort = NULL; 573 return EFI_DEVICE_ERROR; 574 } 575 } 576 } 577 578 579 if (Instance->McastUdpPort == NULL) { 580 return EFI_DEVICE_ERROR; 581 } 582 583 Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0); 584 585 if (EFI_ERROR (Status)) { 586 Mtftp4SendError ( 587 Instance, 588 EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION, 589 (UINT8 *) "Failed to create socket to receive multicast packet" 590 ); 591 592 return Status; 593 } 594 595 // 596 // Update the parameters used. 597 // 598 if (Reply.BlkSize != 0) { 599 Instance->BlkSize = Reply.BlkSize; 600 } 601 602 if (Reply.Timeout != 0) { 603 Instance->Timeout = Reply.Timeout; 604 } 605 } 606 607 } else { 608 Instance->Master = TRUE; 609 610 if (Reply.BlkSize != 0) { 611 Instance->BlkSize = Reply.BlkSize; 612 } 613 614 if (Reply.Timeout != 0) { 615 Instance->Timeout = Reply.Timeout; 616 } 617 } 618 619 // 620 // Send an ACK to (Expected - 1) which is 0 for unicast download, 621 // or tell the server we want to receive the Expected block. 622 // 623 return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1)); 624 } 625 626 627 /** 628 The packet process callback for MTFTP download. 629 630 @param UdpPacket The packet received 631 @param EndPoint The local/remote access point of the packet 632 @param IoStatus The status of the receiving 633 @param Context Opaque parameter, which is the MTFTP session 634 635 **/ 636 VOID 637 EFIAPI 638 Mtftp4RrqInput ( 639 IN NET_BUF *UdpPacket, 640 IN UDP_END_POINT *EndPoint, 641 IN EFI_STATUS IoStatus, 642 IN VOID *Context 643 ) 644 { 645 MTFTP4_PROTOCOL *Instance; 646 EFI_MTFTP4_PACKET *Packet; 647 BOOLEAN Completed; 648 BOOLEAN Multicast; 649 EFI_STATUS Status; 650 UINT16 Opcode; 651 UINT32 Len; 652 653 Instance = (MTFTP4_PROTOCOL *) Context; 654 NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE); 655 656 Status = EFI_SUCCESS; 657 Packet = NULL; 658 Completed = FALSE; 659 Multicast = FALSE; 660 661 if (EFI_ERROR (IoStatus)) { 662 Status = IoStatus; 663 goto ON_EXIT; 664 } 665 666 ASSERT (UdpPacket != NULL); 667 668 // 669 // Find the port this packet is from to restart receive correctly. 670 // 671 Multicast = (BOOLEAN) (EndPoint->LocalAddr.Addr[0] == Instance->McastIp); 672 673 if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) { 674 goto ON_EXIT; 675 } 676 677 // 678 // Client send initial request to server's listening port. Server 679 // will select a UDP port to communicate with the client. The server 680 // is required to use the same port as RemotePort to multicast the 681 // data. 682 // 683 if (EndPoint->RemotePort != Instance->ConnectedPort) { 684 if (Instance->ConnectedPort != 0) { 685 goto ON_EXIT; 686 } else { 687 Instance->ConnectedPort = EndPoint->RemotePort; 688 } 689 } 690 691 // 692 // Copy the MTFTP packet to a continuous buffer if it isn't already so. 693 // 694 Len = UdpPacket->TotalSize; 695 696 if (UdpPacket->BlockOpNum > 1) { 697 Packet = AllocatePool (Len); 698 699 if (Packet == NULL) { 700 Status = EFI_OUT_OF_RESOURCES; 701 goto ON_EXIT; 702 } 703 704 NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet); 705 706 } else { 707 Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL); 708 ASSERT (Packet != NULL); 709 } 710 711 Opcode = NTOHS (Packet->OpCode); 712 713 // 714 // Call the user's CheckPacket if provided. Abort the transmission 715 // if CheckPacket returns an EFI_ERROR code. 716 // 717 if ((Instance->Token->CheckPacket != NULL) && 718 ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) { 719 720 Status = Instance->Token->CheckPacket ( 721 &Instance->Mtftp4, 722 Instance->Token, 723 (UINT16) Len, 724 Packet 725 ); 726 727 if (EFI_ERROR (Status)) { 728 // 729 // Send an error message to the server to inform it 730 // 731 if (Opcode != EFI_MTFTP4_OPCODE_ERROR) { 732 Mtftp4SendError ( 733 Instance, 734 EFI_MTFTP4_ERRORCODE_REQUEST_DENIED, 735 (UINT8 *) "User aborted the transfer" 736 ); 737 } 738 739 Status = EFI_ABORTED; 740 goto ON_EXIT; 741 } 742 } 743 744 switch (Opcode) { 745 case EFI_MTFTP4_OPCODE_DATA: 746 if ((Len > (UINT32) (MTFTP4_DATA_HEAD_LEN + Instance->BlkSize)) || 747 (Len < (UINT32) MTFTP4_DATA_HEAD_LEN)) { 748 goto ON_EXIT; 749 } 750 751 Status = Mtftp4RrqHandleData (Instance, Packet, Len, Multicast, &Completed); 752 break; 753 754 case EFI_MTFTP4_OPCODE_OACK: 755 if (Multicast || (Len <= MTFTP4_OPCODE_LEN)) { 756 goto ON_EXIT; 757 } 758 759 Status = Mtftp4RrqHandleOack (Instance, Packet, Len, Multicast, &Completed); 760 break; 761 762 case EFI_MTFTP4_OPCODE_ERROR: 763 Status = EFI_TFTP_ERROR; 764 break; 765 766 default: 767 break; 768 } 769 770 ON_EXIT: 771 772 // 773 // Free the resources, then if !EFI_ERROR (Status), restart the 774 // receive, otherwise end the session. 775 // 776 if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) { 777 FreePool (Packet); 778 } 779 780 if (UdpPacket != NULL) { 781 NetbufFree (UdpPacket); 782 } 783 784 if (!EFI_ERROR (Status) && !Completed) { 785 if (Multicast) { 786 Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0); 787 } else { 788 Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0); 789 } 790 } 791 792 if (EFI_ERROR (Status) || Completed) { 793 Mtftp4CleanOperation (Instance, Status); 794 } 795 } 796