EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c

Go to the documentation of this file.
00001 
00016 #include "Mtftp6Impl.h"
00017 
00018 
00030 EFI_STATUS
00031 Mtftp6RrqSendAck (
00032   IN MTFTP6_INSTANCE        *Instance,
00033   IN UINT16                 BlockNum
00034   )
00035 {
00036   EFI_MTFTP6_PACKET         *Ack;
00037   NET_BUF                   *Packet;
00038 
00039   //
00040   // Allocate net buffer to create ack packet.
00041   //
00042   Packet = NetbufAlloc (sizeof (EFI_MTFTP6_ACK_HEADER));
00043 
00044   if (Packet == NULL) {
00045     return EFI_OUT_OF_RESOURCES;
00046   }
00047 
00048   Ack = (EFI_MTFTP6_PACKET *) NetbufAllocSpace (
00049                                 Packet,
00050                                 sizeof (EFI_MTFTP6_ACK_HEADER),
00051                                 FALSE
00052                                 );
00053   ASSERT (Ack != NULL);
00054 
00055   Ack->Ack.OpCode    = HTONS (EFI_MTFTP6_OPCODE_ACK);
00056   Ack->Ack.Block[0]  = HTONS (BlockNum);
00057 
00058   //
00059   // Reset current retry count of the instance.
00060   //
00061   Instance->CurRetry = 0;
00062 
00063   return Mtftp6TransmitPacket (Instance, Packet);
00064 }
00065 
00066 
00083 EFI_STATUS
00084 Mtftp6RrqSaveBlock (
00085   IN  MTFTP6_INSTANCE       *Instance,
00086   IN  EFI_MTFTP6_PACKET     *Packet,
00087   IN  UINT32                Len,
00088   OUT NET_BUF               **UdpPacket
00089   )
00090 {
00091   EFI_MTFTP6_TOKEN          *Token;
00092   EFI_STATUS                Status;
00093   UINT16                    Block;
00094   UINT64                    Start;
00095   UINT32                    DataLen;
00096   UINT64                    TotalBlock;
00097   BOOLEAN                   Completed;
00098 
00099   Completed = FALSE;
00100   Token     = Instance->Token;
00101   Block     = NTOHS (Packet->Data.Block);
00102   DataLen   = Len - MTFTP6_DATA_HEAD_LEN;
00103 
00104   //
00105   // This is the last block, save the block num
00106   //
00107   if (DataLen < Instance->BlkSize) {
00108     Completed = TRUE;
00109     Instance->LastBlk = Block;
00110     Mtftp6SetLastBlockNum (&Instance->BlkList, Block);
00111   }
00112 
00113   //
00114   // Remove this block number from the file hole. If Mtftp6RemoveBlockNum
00115   // returns EFI_NOT_FOUND, the block has been saved, don't save it again.
00116   // Note that : For bigger files, allowing the block counter to roll over
00117   // to accept transfers of unlimited size. So TotalBlock is memorised as
00118   // continuous block counter.
00119   //
00120   Status = Mtftp6RemoveBlockNum (&Instance->BlkList, Block, Completed, &TotalBlock);
00121 
00122   if (Status == EFI_NOT_FOUND) {
00123     return EFI_SUCCESS;
00124   } else if (EFI_ERROR (Status)) {
00125     return Status;
00126   }
00127 
00128   if (Token->CheckPacket != NULL) {
00129     //
00130     // Callback to the check packet routine with the received packet.
00131     //
00132     Status = Token->CheckPacket (&Instance->Mtftp6, Token, (UINT16) Len, Packet);
00133 
00134     if (EFI_ERROR (Status)) {
00135       //
00136       // Free the received packet before send new packet in ReceiveNotify,
00137       // since the Udp6Io might need to be reconfigured.
00138       //
00139       NetbufFree (*UdpPacket);
00140       *UdpPacket = NULL;
00141       //
00142       // Send the Mtftp6 error message if user aborted the current session.
00143       //
00144       Mtftp6SendError (
00145         Instance,
00146         EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
00147         (UINT8 *) "User aborted download"
00148         );
00149 
00150       return EFI_ABORTED;
00151     }
00152   }
00153 
00154   if (Token->Buffer != NULL) {
00155 
00156     Start = MultU64x32 (TotalBlock - 1, Instance->BlkSize);
00157     if (Start + DataLen <= Token->BufferSize) {
00158       CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen);
00159       //
00160       // Update the file size when received the last block
00161       //
00162       if ((Instance->LastBlk == Block) && Completed) {
00163         Token->BufferSize = Start + DataLen;
00164       }
00165     } else if (Instance->LastBlk != 0) {
00166       //
00167       // Don't save the data if the buffer is too small, return
00168       // EFI_BUFFER_TOO_SMALL if received the last packet. This
00169       // will give a accurate file length.
00170       //
00171       Token->BufferSize = Start + DataLen;
00172 
00173       //
00174       // Free the received packet before send new packet in ReceiveNotify,
00175       // since the udpio might need to be reconfigured.
00176       //
00177       NetbufFree (*UdpPacket);
00178       *UdpPacket = NULL;
00179       //
00180       // Send the Mtftp6 error message if no enough buffer.
00181       //
00182       Mtftp6SendError (
00183         Instance,
00184         EFI_MTFTP6_ERRORCODE_DISK_FULL,
00185         (UINT8 *) "User provided memory block is too small"
00186         );
00187 
00188       return EFI_BUFFER_TOO_SMALL;
00189     }
00190   }
00191 
00192   return EFI_SUCCESS;
00193 }
00194 
00195 
00212 EFI_STATUS
00213 Mtftp6RrqHandleData (
00214   IN  MTFTP6_INSTANCE       *Instance,
00215   IN  EFI_MTFTP6_PACKET     *Packet,
00216   IN  UINT32                Len,
00217   OUT NET_BUF               **UdpPacket,
00218   OUT BOOLEAN               *IsCompleted
00219   )
00220 {
00221   EFI_STATUS                Status;
00222   UINT16                    BlockNum;
00223   INTN                      Expected;
00224 
00225   *IsCompleted = FALSE;
00226   BlockNum     = NTOHS (Packet->Data.Block);
00227   Expected     = Mtftp6GetNextBlockNum (&Instance->BlkList);
00228 
00229   ASSERT (Expected >= 0);
00230 
00231   //
00232   // If we are active and received an unexpected packet, retransmit
00233   // the last ACK then restart receiving. If we are passive, save
00234   // the block.
00235   //
00236   if (Instance->IsMaster && (Expected != BlockNum)) {
00237     //
00238     // Free the received packet before send new packet in ReceiveNotify,
00239     // since the udpio might need to be reconfigured.
00240     //
00241     NetbufFree (*UdpPacket);
00242     *UdpPacket = NULL;
00243 
00244     Mtftp6TransmitPacket (Instance, Instance->LastPacket);
00245     return EFI_SUCCESS;
00246   }
00247 
00248   Status = Mtftp6RrqSaveBlock (Instance, Packet, Len, UdpPacket);
00249 
00250   if (EFI_ERROR (Status)) {
00251     return Status;
00252   }
00253 
00254   //
00255   // Reset the passive client's timer whenever it received a valid data packet.
00256   //
00257   if (!Instance->IsMaster) {
00258     Instance->PacketToLive = Instance->Timeout * 2;
00259   }
00260 
00261   //
00262   // Check whether we have received all the blocks. Send the ACK if we
00263   // are active (unicast client or master client for multicast download).
00264   // If we have received all the blocks, send an ACK even if we are passive
00265   // to tell the server that we are done.
00266   //
00267   Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
00268 
00269   if (Instance->IsMaster || Expected < 0) {
00270     if (Expected < 0) {
00271       //
00272       // If we are passive client, then the just received Block maybe
00273       // isn't the last block. We need to send an ACK to the last block
00274       // to inform the server that we are done. If we are active client,
00275       // the Block == Instance->LastBlock.
00276       //
00277       BlockNum     = Instance->LastBlk;
00278       *IsCompleted = TRUE;
00279 
00280     } else {
00281       BlockNum     = (UINT16) (Expected - 1);
00282     }
00283     //
00284     // Free the received packet before send new packet in ReceiveNotify,
00285     // since the udpio might need to be reconfigured.
00286     //
00287     NetbufFree (*UdpPacket);
00288     *UdpPacket = NULL;
00289 
00290     Mtftp6RrqSendAck (Instance, BlockNum);
00291   }
00292 
00293   return EFI_SUCCESS;
00294 }
00295 
00296 
00313 BOOLEAN
00314 Mtftp6RrqOackValid (
00315   IN MTFTP6_INSTANCE           *Instance,
00316   IN MTFTP6_EXT_OPTION_INFO    *ReplyInfo,
00317   IN MTFTP6_EXT_OPTION_INFO    *RequestInfo
00318   )
00319 {
00320   //
00321   // It is invalid for server to return options we don't request
00322   //
00323   if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
00324     return FALSE;
00325   }
00326 
00327   //
00328   // Server can only specify a smaller block size to be used and
00329   // return the timeout matches that requested.
00330   //
00331   if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
00332       (((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
00333       ) {
00334     return FALSE;
00335   }
00336 
00337   //
00338   // The server can send ",,master" to client to change its master
00339   // setting. But if it use the specific multicast channel, it can't
00340   // change the setting.
00341   //
00342   if (((ReplyInfo->BitMap & MTFTP6_OPT_MCAST_BIT) != 0) && !NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
00343 
00344     if (!NetIp6IsUnspecifiedAddr (&ReplyInfo->McastIp) && CompareMem (
00345                                                             &ReplyInfo->McastIp,
00346                                                             &Instance->McastIp,
00347                                                             sizeof (EFI_IPv6_ADDRESS)
00348                                                             ) != 0) {
00349       return FALSE;
00350     }
00351 
00352     if ((ReplyInfo->McastPort != 0) && (ReplyInfo->McastPort != Instance->McastPort)) {
00353       return FALSE;
00354     }
00355   }
00356 
00357   return TRUE;
00358 }
00359 
00360 
00371 EFI_STATUS
00372 EFIAPI
00373 Mtftp6RrqConfigMcastUdpIo (
00374   IN UDP_IO                 *McastIo,
00375   IN VOID                   *Context
00376   )
00377 {
00378   EFI_STATUS                Status;
00379   EFI_UDP6_PROTOCOL         *Udp6;
00380   EFI_UDP6_CONFIG_DATA      *Udp6Cfg;
00381   EFI_IPv6_ADDRESS          Group;
00382   MTFTP6_INSTANCE           *Instance;
00383 
00384   Udp6     = McastIo->Protocol.Udp6;
00385   Udp6Cfg  = &(McastIo->Config.Udp6);
00386   Instance = (MTFTP6_INSTANCE *) Context;
00387 
00388   //
00389   // Set the configure data for the mcast Udp6Io.
00390   //
00391   ZeroMem (Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
00392 
00393   Udp6Cfg->AcceptPromiscuous  = FALSE;
00394   Udp6Cfg->AcceptAnyPort      = FALSE;
00395   Udp6Cfg->AllowDuplicatePort = FALSE;
00396   Udp6Cfg->TrafficClass       = 0;
00397   Udp6Cfg->HopLimit           = 128;
00398   Udp6Cfg->ReceiveTimeout     = 0;
00399   Udp6Cfg->TransmitTimeout    = 0;
00400   Udp6Cfg->StationPort        = Instance->McastPort;
00401   Udp6Cfg->RemotePort         = 0;
00402 
00403   CopyMem (
00404     &Udp6Cfg->RemoteAddress,
00405     &Instance->ServerIp,
00406     sizeof (EFI_IPv6_ADDRESS)
00407     );
00408 
00409   //
00410   // Configure the mcast Udp6Io.
00411   //
00412   Status = Udp6->Configure (Udp6, Udp6Cfg);
00413 
00414   if (EFI_ERROR (Status)) {
00415     return Status;
00416   }
00417 
00418   //
00419   // Join the multicast group
00420   //
00421   CopyMem (&Group, &Instance->McastIp, sizeof (EFI_IPv6_ADDRESS));
00422 
00423   return Udp6->Groups (Udp6, TRUE, &Group);
00424 }
00425 
00426 
00442 EFI_STATUS
00443 Mtftp6RrqHandleOack (
00444   IN  MTFTP6_INSTANCE       *Instance,
00445   IN  EFI_MTFTP6_PACKET     *Packet,
00446   IN  UINT32                Len,
00447   OUT NET_BUF               **UdpPacket,
00448   OUT BOOLEAN               *IsCompleted
00449   )
00450 {
00451   EFI_MTFTP6_OPTION         *Options;
00452   UINT32                    Count;
00453   MTFTP6_EXT_OPTION_INFO    ExtInfo;
00454   EFI_STATUS                Status;
00455   INTN                      Expected;
00456 
00457   *IsCompleted = FALSE;
00458 
00459   //
00460   // If already started the master download, don't change the
00461   // setting. Master download always succeeds.
00462   //
00463   Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
00464   ASSERT (Expected != -1);
00465 
00466   if (Instance->IsMaster && Expected != 1) {
00467     return EFI_SUCCESS;
00468   }
00469 
00470   ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
00471 
00472   //
00473   // Parse the options in the packet.
00474   //
00475   Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);
00476 
00477   if (EFI_ERROR (Status)) {
00478     return Status;
00479   }
00480 
00481   //
00482   // Parse the extensive options in the packet.
00483   //
00484   Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);
00485 
00486   if (EFI_ERROR (Status) || !Mtftp6RrqOackValid (Instance, &ExtInfo, &Instance->ExtInfo)) {
00487     //
00488     // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
00489     //
00490     if (Status != EFI_OUT_OF_RESOURCES) {
00491       //
00492       // Free the received packet before send new packet in ReceiveNotify,
00493       // since the udpio might need to be reconfigured.
00494       //
00495       NetbufFree (*UdpPacket);
00496       *UdpPacket = NULL;
00497       //
00498       // Send the Mtftp6 error message if invalid packet.
00499       //
00500       Mtftp6SendError (
00501         Instance,
00502         EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
00503         (UINT8 *) "Mal-formated OACK packet"
00504         );
00505     }
00506 
00507     return EFI_TFTP_ERROR;
00508   }
00509 
00510   if ((ExtInfo.BitMap & MTFTP6_OPT_MCAST_BIT) != 0) {
00511 
00512     //
00513     // Save the multicast info. Always update the Master, only update the
00514     // multicast IP address, block size, timeoute at the first time. If IP
00515     // address is updated, create a UDP child to receive the multicast.
00516     //
00517     Instance->IsMaster = ExtInfo.IsMaster;
00518 
00519     if (NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
00520       if (NetIp6IsUnspecifiedAddr (&ExtInfo.McastIp) || ExtInfo.McastPort == 0) {
00521         //
00522         // Free the received packet before send new packet in ReceiveNotify,
00523         // since the udpio might need to be reconfigured.
00524         //
00525         NetbufFree (*UdpPacket);
00526         *UdpPacket = NULL;
00527         //
00528         // Send the Mtftp6 error message if invalid multi-cast setting.
00529         //
00530         Mtftp6SendError (
00531           Instance,
00532           EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
00533           (UINT8 *) "Illegal multicast setting"
00534           );
00535 
00536         return EFI_TFTP_ERROR;
00537       }
00538 
00539       //
00540       // Create a UDP child then start receive the multicast from it.
00541       //
00542       CopyMem (
00543         &Instance->McastIp,
00544         &ExtInfo.McastIp,
00545         sizeof (EFI_IP_ADDRESS)
00546         );
00547 
00548       Instance->McastPort  = ExtInfo.McastPort;
00549       Instance->McastUdpIo = UdpIoCreateIo (
00550                                Instance->Service->Controller,
00551                                Instance->Service->Image,
00552                                Mtftp6RrqConfigMcastUdpIo,
00553                                UDP_IO_UDP6_VERSION,
00554                                Instance
00555                                );
00556 
00557       if (Instance->McastUdpIo == NULL) {
00558         return EFI_DEVICE_ERROR;
00559       }
00560 
00561       Status = UdpIoRecvDatagram (
00562                  Instance->McastUdpIo,
00563                  Mtftp6RrqInput,
00564                  Instance,
00565                  0
00566                  );
00567 
00568       if (EFI_ERROR (Status)) {
00569         //
00570         // Free the received packet before send new packet in ReceiveNotify,
00571         // since the udpio might need to be reconfigured.
00572         //
00573         NetbufFree (*UdpPacket);
00574         *UdpPacket = NULL;
00575         //
00576         // Send the Mtftp6 error message if failed to create Udp6Io to receive.
00577         //
00578         Mtftp6SendError (
00579           Instance,
00580           EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION,
00581           (UINT8 *) "Failed to create socket to receive multicast packet"
00582           );
00583 
00584         return Status;
00585       }
00586 
00587       //
00588       // Update the parameters used.
00589       //
00590       if (ExtInfo.BlkSize != 0) {
00591         Instance->BlkSize = ExtInfo.BlkSize;
00592       }
00593 
00594       if (ExtInfo.Timeout != 0) {
00595         Instance->Timeout = ExtInfo.Timeout;
00596       }
00597     }
00598 
00599   } else {
00600 
00601     Instance->IsMaster = TRUE;
00602 
00603     if (ExtInfo.BlkSize != 0) {
00604       Instance->BlkSize = ExtInfo.BlkSize;
00605     }
00606 
00607     if (ExtInfo.Timeout != 0) {
00608       Instance->Timeout = ExtInfo.Timeout;
00609     }
00610   }
00611 
00612   //
00613   // Free the received packet before send new packet in ReceiveNotify,
00614   // since the udpio might need to be reconfigured.
00615   //
00616   NetbufFree (*UdpPacket);
00617   *UdpPacket = NULL;
00618   //
00619   // Send an ACK to (Expected - 1) which is 0 for unicast download,
00620   // or tell the server we want to receive the Expected block.
00621   //
00622   return Mtftp6RrqSendAck (Instance, (UINT16) (Expected - 1));
00623 }
00624 
00625 
00635 VOID
00636 EFIAPI
00637 Mtftp6RrqInput (
00638   IN NET_BUF                *UdpPacket,
00639   IN UDP_END_POINT          *UdpEpt,
00640   IN EFI_STATUS             IoStatus,
00641   IN VOID                   *Context
00642   )
00643 {
00644   MTFTP6_INSTANCE           *Instance;
00645   EFI_MTFTP6_PACKET         *Packet;
00646   BOOLEAN                   IsCompleted;
00647   BOOLEAN                   IsMcast;
00648   EFI_STATUS                Status;
00649   UINT16                    Opcode;
00650   UINT32                    TotalNum;
00651   UINT32                    Len;
00652 
00653   Instance = (MTFTP6_INSTANCE *) Context;
00654 
00655   NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);
00656 
00657   Status      = EFI_SUCCESS;
00658   Packet      = NULL;
00659   IsCompleted = FALSE;
00660   IsMcast     = FALSE;
00661   TotalNum    = 0;
00662 
00663   //
00664   // Return error status if Udp6 instance failed to receive.
00665   //
00666   if (EFI_ERROR (IoStatus)) {
00667     Status = IoStatus;
00668     goto ON_EXIT;
00669   }
00670 
00671   ASSERT (UdpPacket != NULL);
00672 
00673   if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
00674     goto ON_EXIT;
00675   }
00676 
00677   //
00678   // Find the port this packet is from to restart receive correctly.
00679   //
00680   if (CompareMem (
00681         Ip6Swap128 (&UdpEpt->LocalAddr.v6),
00682         &Instance->McastIp,
00683         sizeof (EFI_IPv6_ADDRESS)
00684         ) == 0) {
00685     IsMcast = TRUE;
00686   } else {
00687     IsMcast = FALSE;
00688   }
00689 
00690   //
00691   // Client send initial request to server's listening port. Server
00692   // will select a UDP port to communicate with the client. The server
00693   // is required to use the same port as RemotePort to multicast the
00694   // data.
00695   //
00696   if (UdpEpt->RemotePort != Instance->ServerDataPort) {
00697     if (Instance->ServerDataPort != 0) {
00698       goto ON_EXIT;
00699     } else {
00700       //
00701       // For the subsequent exchange of requests, reconfigure the udpio as
00702       // (serverip, serverport, localip, localport).
00703       // Ususally, the client set serverport as 0 to receive and reset it
00704       // once the first packet arrives to send ack.
00705       //
00706       Instance->ServerDataPort = UdpEpt->RemotePort;
00707     }
00708   }
00709 
00710   //
00711   // Copy the MTFTP packet to a continuous buffer if it isn't already so.
00712   //
00713   Len      = UdpPacket->TotalSize;
00714   TotalNum = UdpPacket->BlockOpNum;
00715 
00716   if (TotalNum > 1) {
00717     Packet = AllocateZeroPool (Len);
00718 
00719     if (Packet == NULL) {
00720       Status = EFI_OUT_OF_RESOURCES;
00721       goto ON_EXIT;
00722     }
00723 
00724     NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
00725 
00726   } else {
00727     Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
00728     ASSERT (Packet != NULL);
00729   }
00730 
00731   Opcode = NTOHS (Packet->OpCode);
00732 
00733   //
00734   // Callback to the user's CheckPacket if provided. Abort the transmission
00735   // if CheckPacket returns an EFI_ERROR code.
00736   //
00737   if ((Instance->Token->CheckPacket != NULL) &&
00738       (Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
00739       ) {
00740 
00741     Status = Instance->Token->CheckPacket (
00742                                 &Instance->Mtftp6,
00743                                 Instance->Token,
00744                                 (UINT16) Len,
00745                                 Packet
00746                                 );
00747 
00748     if (EFI_ERROR (Status)) {
00749       //
00750       // Send an error message to the server to inform it
00751       //
00752       if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
00753         //
00754         // Free the received packet before send new packet in ReceiveNotify,
00755         // since the udpio might need to be reconfigured.
00756         //
00757         NetbufFree (UdpPacket);
00758         UdpPacket = NULL;
00759         //
00760         // Send the Mtftp6 error message if user aborted the current session.
00761         //
00762         Mtftp6SendError (
00763           Instance,
00764           EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
00765           (UINT8 *) "User aborted the transfer"
00766           );
00767       }
00768 
00769       Status = EFI_ABORTED;
00770       goto ON_EXIT;
00771     }
00772   }
00773 
00774   //
00775   // Switch the process routines by the operation code.
00776   //
00777   switch (Opcode) {
00778   case EFI_MTFTP6_OPCODE_DATA:
00779     if ((Len > (UINT32) (MTFTP6_DATA_HEAD_LEN + Instance->BlkSize)) || (Len < (UINT32) MTFTP6_DATA_HEAD_LEN)) {
00780       goto ON_EXIT;
00781     }
00782     //
00783     // Handle the data packet of Rrq.
00784     //
00785     Status = Mtftp6RrqHandleData (
00786                Instance,
00787                Packet,
00788                Len,
00789                &UdpPacket,
00790                &IsCompleted
00791                );
00792     break;
00793 
00794   case EFI_MTFTP6_OPCODE_OACK:
00795     if (IsMcast || Len <= MTFTP6_OPCODE_LEN) {
00796       goto ON_EXIT;
00797     }
00798     //
00799     // Handle the Oack packet of Rrq.
00800     //
00801     Status = Mtftp6RrqHandleOack (
00802                Instance,
00803                Packet,
00804                Len,
00805                &UdpPacket,
00806                &IsCompleted
00807                );
00808     break;
00809 
00810   default:
00811     //
00812     // Drop and return eror if received error message.
00813     //
00814     Status = EFI_TFTP_ERROR;
00815     break;
00816   }
00817 
00818 ON_EXIT:
00819   //
00820   // Free the resources, then if !EFI_ERROR (Status), restart the
00821   // receive, otherwise end the session.
00822   //
00823   if (Packet != NULL && TotalNum > 1) {
00824     FreePool (Packet);
00825   }
00826   if (UdpPacket != NULL) {
00827     NetbufFree (UdpPacket);
00828   }
00829   if (!EFI_ERROR (Status) && !IsCompleted) {
00830     if (IsMcast) {
00831       Status = UdpIoRecvDatagram (
00832                  Instance->McastUdpIo,
00833                  Mtftp6RrqInput,
00834                  Instance,
00835                  0
00836                  );
00837     } else {
00838       Status = UdpIoRecvDatagram (
00839                  Instance->UdpIo,
00840                  Mtftp6RrqInput,
00841                  Instance,
00842                  0
00843                  );
00844     }
00845   }
00846   //
00847   // Clean up the current session if failed to continue.
00848   //
00849   if (EFI_ERROR (Status) || IsCompleted) {
00850     Mtftp6OperationClean (Instance, Status);
00851   }
00852 }
00853 
00854 
00867 EFI_STATUS
00868 Mtftp6RrqStart (
00869   IN MTFTP6_INSTANCE        *Instance,
00870   IN UINT16                 Operation
00871   )
00872 {
00873   EFI_STATUS                Status;
00874 
00875   //
00876   // The valid block number range are [1, 0xffff]. For example:
00877   // the client sends an RRQ request to the server, the server
00878   // transfers the DATA1 block. If option negoitation is ongoing,
00879   // the server will send back an OACK, then client will send ACK0.
00880   //
00881   Status = Mtftp6InitBlockRange (&Instance->BlkList, 1, 0xffff);
00882 
00883   if (EFI_ERROR (Status)) {
00884     return Status;
00885   }
00886 
00887   Status = Mtftp6SendRequest (Instance, Operation);
00888 
00889   if (EFI_ERROR (Status)) {
00890     return Status;
00891   }
00892 
00893   return UdpIoRecvDatagram (
00894            Instance->UdpIo,
00895            Mtftp6RrqInput,
00896            Instance,
00897            0
00898            );
00899 }
00900 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines