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