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