Home | History | Annotate | Download | only in Mtftp4Dxe
      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