BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Impl.c
1 /** @file\r
2   Interface routine for Mtftp4.\r
3 \r
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7 \r
8 **/\r
9 \r
10 \r
11 #include "Mtftp4Impl.h"\r
12 \r
13 \r
14 /**\r
15   Clean up the MTFTP session to get ready for new operation.\r
16 \r
17   @param  Instance               The MTFTP session to clean up\r
18   @param  Result                 The result to return to the caller who initiated\r
19                                  the operation.\r
20 **/\r
21 VOID\r
22 Mtftp4CleanOperation (\r
23   IN OUT MTFTP4_PROTOCOL        *Instance,\r
24   IN     EFI_STATUS             Result\r
25   )\r
26 {\r
27   LIST_ENTRY                *Entry;\r
28   LIST_ENTRY                *Next;\r
29   MTFTP4_BLOCK_RANGE        *Block;\r
30   EFI_MTFTP4_TOKEN          *Token;\r
31 \r
32   //\r
33   // Free various resources.\r
34   //\r
35   Token = Instance->Token;\r
36 \r
37   if (Token != NULL) {\r
38     Token->Status = Result;\r
39 \r
40     if (Token->Event != NULL) {\r
41       gBS->SignalEvent (Token->Event);\r
42     }\r
43 \r
44     Instance->Token = NULL;\r
45   }\r
46 \r
47   ASSERT (Instance->UnicastPort != NULL);\r
48   UdpIoCleanIo (Instance->UnicastPort);\r
49 \r
50   if (Instance->LastPacket != NULL) {\r
51     NetbufFree (Instance->LastPacket);\r
52     Instance->LastPacket = NULL;\r
53   }\r
54 \r
55   if (Instance->McastUdpPort != NULL) {\r
56     gBS->CloseProtocol (\r
57            Instance->McastUdpPort->UdpHandle,\r
58            &gEfiUdp4ProtocolGuid,\r
59            gMtftp4DriverBinding.DriverBindingHandle,\r
60            Instance->Handle\r
61            );\r
62     UdpIoFreeIo (Instance->McastUdpPort);\r
63     Instance->McastUdpPort = NULL;\r
64   }\r
65 \r
66   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {\r
67     Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);\r
68     RemoveEntryList (Entry);\r
69     FreePool (Block);\r
70   }\r
71 \r
72   ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));\r
73 \r
74   Instance->Operation     = 0;\r
75 \r
76   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;\r
77   Instance->WindowSize    = 1;\r
78   Instance->TotalBlock    = 0;\r
79   Instance->AckedBlock    = 0;\r
80   Instance->LastBlock     = 0;\r
81   Instance->ServerIp      = 0;\r
82   Instance->ListeningPort = 0;\r
83   Instance->ConnectedPort = 0;\r
84   Instance->Gateway       = 0;\r
85   Instance->PacketToLive  = 0;\r
86   Instance->MaxRetry      = 0;\r
87   Instance->CurRetry      = 0;\r
88   Instance->Timeout       = 0;\r
89   Instance->McastIp       = 0;\r
90   Instance->McastPort     = 0;\r
91   Instance->Master        = TRUE;\r
92 }\r
93 \r
94 \r
95 /**\r
96   Check packet for GetInfo.\r
97 \r
98   GetInfo is implemented with EfiMtftp4ReadFile. It use Mtftp4GetInfoCheckPacket\r
99   to inspect the first packet from server, then abort the session.\r
100 \r
101   @param  This                   The MTFTP4 protocol instance\r
102   @param  Token                  The user's token\r
103   @param  PacketLen              The length of the packet\r
104   @param  Packet                 The received packet.\r
105 \r
106   @retval EFI_ABORTED            Abort the ReadFile operation and return.\r
107 \r
108 **/\r
109 EFI_STATUS\r
110 EFIAPI\r
111 Mtftp4GetInfoCheckPacket (\r
112   IN EFI_MTFTP4_PROTOCOL    *This,\r
113   IN EFI_MTFTP4_TOKEN       *Token,\r
114   IN UINT16                 PacketLen,\r
115   IN EFI_MTFTP4_PACKET      *Packet\r
116   )\r
117 {\r
118   MTFTP4_GETINFO_STATE      *State;\r
119   EFI_STATUS                Status;\r
120   UINT16                    OpCode;\r
121   EFI_MTFTP4_ERROR_HEADER  *ErrorHeader;\r
122 \r
123   State   = (MTFTP4_GETINFO_STATE *) Token->Context;\r
124   OpCode   = NTOHS (Packet->OpCode);\r
125 \r
126   //\r
127   // Set the GetInfo's return status according to the OpCode.\r
128   //\r
129   switch (OpCode) {\r
130   case EFI_MTFTP4_OPCODE_ERROR:\r
131     ErrorHeader = (EFI_MTFTP4_ERROR_HEADER *) Packet;\r
132     if (ErrorHeader->ErrorCode == EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND) {\r
133       DEBUG ((EFI_D_ERROR, "TFTP error code 1 (File Not Found)\n"));\r
134     } else {\r
135       DEBUG ((EFI_D_ERROR, "TFTP error code %d\n", ErrorHeader->ErrorCode));\r
136     }\r
137     State->Status = EFI_TFTP_ERROR;\r
138     break;\r
139 \r
140   case EFI_MTFTP4_OPCODE_OACK:\r
141     State->Status = EFI_SUCCESS;\r
142     break;\r
143 \r
144   default:\r
145     State->Status = EFI_PROTOCOL_ERROR;\r
146   }\r
147 \r
148   //\r
149   // Allocate buffer then copy the packet over. Use gBS->AllocatePool\r
150   // in case AllocatePool will implements something tricky.\r
151   //\r
152   Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);\r
153 \r
154   if (EFI_ERROR (Status)) {\r
155     State->Status = EFI_OUT_OF_RESOURCES;\r
156     return EFI_ABORTED;\r
157   }\r
158 \r
159   *(State->PacketLen) = PacketLen;\r
160   CopyMem (*(State->Packet), Packet, PacketLen);\r
161 \r
162   return EFI_ABORTED;\r
163 }\r
164 \r
165 \r
166 /**\r
167   Check whether the override data is valid.\r
168 \r
169   It will first validate whether the server is a valid unicast. If a gateway\r
170   is provided in the Override, it also check that it is a unicast on the\r
171   connected network.\r
172 \r
173   @param  Instance               The MTFTP instance\r
174   @param  Override               The override data to validate.\r
175 \r
176   @retval TRUE                   The override data is valid\r
177   @retval FALSE                  The override data is invalid\r
178 \r
179 **/\r
180 BOOLEAN\r
181 Mtftp4OverrideValid (\r
182   IN MTFTP4_PROTOCOL          *Instance,\r
183   IN EFI_MTFTP4_OVERRIDE_DATA *Override\r
184   )\r
185 {\r
186   EFI_MTFTP4_CONFIG_DATA    *Config;\r
187   IP4_ADDR                  Ip;\r
188   IP4_ADDR                  Netmask;\r
189   IP4_ADDR                  Gateway;\r
190 \r
191   CopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));\r
192   if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {\r
193     return FALSE;\r
194   }\r
195 \r
196   Config = &Instance->Config;\r
197 \r
198   CopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
199   Gateway = NTOHL (Gateway);\r
200 \r
201   if (!Config->UseDefaultSetting && (Gateway != 0)) {\r
202     CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
203     CopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));\r
204 \r
205     Netmask = NTOHL (Netmask);\r
206     Ip      = NTOHL (Ip);\r
207 \r
208     if ((Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {\r
209       return FALSE;\r
210     }\r
211   }\r
212 \r
213   return TRUE;\r
214 }\r
215 \r
216 \r
217 /**\r
218   Poll the UDP to get the IP4 default address, which may be retrieved\r
219   by DHCP.\r
220 \r
221   The default time out value is 5 seconds. If IP has retrieved the default address,\r
222   the UDP is reconfigured.\r
223 \r
224   @param  Instance               The Mtftp instance\r
225   @param  UdpIo                  The UDP_IO to poll\r
226   @param  UdpCfgData             The UDP configure data to reconfigure the UDP_IO\r
227 \r
228   @retval TRUE                   The default address is retrieved and UDP is reconfigured.\r
229   @retval FALSE                  Some error occured.\r
230 \r
231 **/\r
232 BOOLEAN\r
233 Mtftp4GetMapping (\r
234   IN MTFTP4_PROTOCOL        *Instance,\r
235   IN UDP_IO                 *UdpIo,\r
236   IN EFI_UDP4_CONFIG_DATA   *UdpCfgData\r
237   )\r
238 {\r
239   MTFTP4_SERVICE            *Service;\r
240   EFI_IP4_MODE_DATA         Ip4Mode;\r
241   EFI_UDP4_PROTOCOL         *Udp;\r
242   EFI_STATUS                Status;\r
243 \r
244   ASSERT (Instance->Config.UseDefaultSetting);\r
245 \r
246   Service = Instance->Service;\r
247   Udp     = UdpIo->Protocol.Udp4;\r
248 \r
249   Status = gBS->SetTimer (\r
250                   Service->TimerToGetMap,\r
251                   TimerRelative,\r
252                   MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND\r
253                   );\r
254   if (EFI_ERROR (Status)) {\r
255     return FALSE;\r
256   }\r
257 \r
258   while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
259     Udp->Poll (Udp);\r
260 \r
261     if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
262         Ip4Mode.IsConfigured) {\r
263 \r
264       Udp->Configure (Udp, NULL);\r
265       return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
266     }\r
267   }\r
268 \r
269   return FALSE;\r
270 }\r
271 \r
272 \r
273 /**\r
274   Configure the UDP port for unicast receiving.\r
275 \r
276   @param  UdpIo                  The UDP_IO instance\r
277   @param  Instance               The MTFTP session\r
278 \r
279   @retval EFI_SUCCESS            The UDP port is successfully configured for the\r
280                                  session to unicast receive.\r
281 \r
282 **/\r
283 EFI_STATUS\r
284 Mtftp4ConfigUnicastPort (\r
285   IN UDP_IO                 *UdpIo,\r
286   IN MTFTP4_PROTOCOL        *Instance\r
287   )\r
288 {\r
289   EFI_MTFTP4_CONFIG_DATA    *Config;\r
290   EFI_UDP4_CONFIG_DATA      UdpConfig;\r
291   EFI_STATUS                Status;\r
292   IP4_ADDR                  Ip;\r
293 \r
294   Config = &Instance->Config;\r
295 \r
296   UdpConfig.AcceptBroadcast    = FALSE;\r
297   UdpConfig.AcceptPromiscuous  = FALSE;\r
298   UdpConfig.AcceptAnyPort      = FALSE;\r
299   UdpConfig.AllowDuplicatePort = FALSE;\r
300   UdpConfig.TypeOfService      = 0;\r
301   UdpConfig.TimeToLive         = 64;\r
302   UdpConfig.DoNotFragment      = FALSE;\r
303   UdpConfig.ReceiveTimeout     = 0;\r
304   UdpConfig.TransmitTimeout    = 0;\r
305   UdpConfig.UseDefaultAddress  = Config->UseDefaultSetting;\r
306   IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);\r
307   IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);\r
308   UdpConfig.StationPort        = Config->LocalPort;\r
309   UdpConfig.RemotePort         = 0;\r
310 \r
311   Ip = HTONL (Instance->ServerIp);\r
312   IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);\r
313 \r
314   Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);\r
315 \r
316   if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {\r
317     return EFI_SUCCESS;\r
318   }\r
319 \r
320   if (!Config->UseDefaultSetting && !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {\r
321     //\r
322     // The station IP address is manually configured and the Gateway IP is not 0.\r
323     // Add the default route for this UDP instance.\r
324     //\r
325     Status = UdpIo->Protocol.Udp4->Routes (\r
326                                      UdpIo->Protocol.Udp4,\r
327                                      FALSE,\r
328                                      &mZeroIp4Addr,\r
329                                      &mZeroIp4Addr,\r
330                                      &Config->GatewayIp\r
331                                      );\r
332     if (EFI_ERROR (Status)) {\r
333       UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);\r
334     }\r
335   }\r
336   return Status;\r
337 }\r
338 \r
339 \r
340 /**\r
341   Start the MTFTP session to do the operation, such as read file,\r
342   write file, and read directory.\r
343 \r
344   @param  This                   The MTFTP session\r
345   @param  Token                  The token than encapsues the user's request.\r
346   @param  Operation              The operation to do\r
347 \r
348   @retval EFI_INVALID_PARAMETER  Some of the parameters are invalid.\r
349   @retval EFI_NOT_STARTED        The MTFTP session hasn't been configured.\r
350   @retval EFI_ALREADY_STARTED    There is pending operation for the session.\r
351   @retval EFI_SUCCESS            The operation is successfully started.\r
352 \r
353 **/\r
354 EFI_STATUS\r
355 Mtftp4Start (\r
356   IN EFI_MTFTP4_PROTOCOL    *This,\r
357   IN EFI_MTFTP4_TOKEN       *Token,\r
358   IN UINT16                 Operation\r
359   )\r
360 {\r
361   MTFTP4_PROTOCOL           *Instance;\r
362   EFI_MTFTP4_OVERRIDE_DATA  *Override;\r
363   EFI_MTFTP4_CONFIG_DATA    *Config;\r
364   EFI_TPL                   OldTpl;\r
365   EFI_STATUS                Status;\r
366   EFI_STATUS                TokenStatus;\r
367 \r
368   //\r
369   // Validate the parameters\r
370   //\r
371   if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||\r
372       ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {\r
373     return EFI_INVALID_PARAMETER;\r
374   }\r
375 \r
376   //\r
377   // User must provide at least one method to collect the data for download.\r
378   //\r
379   if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&\r
380       ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {\r
381     return EFI_INVALID_PARAMETER;\r
382   }\r
383 \r
384   //\r
385   // User must provide at least one method to provide the data for upload.\r
386   //\r
387   if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&\r
388      ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {\r
389     return EFI_INVALID_PARAMETER;\r
390   }\r
391 \r
392   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
393 \r
394   Status      = EFI_SUCCESS;\r
395   TokenStatus = EFI_SUCCESS;\r
396 \r
397   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
398 \r
399   if (Instance->State != MTFTP4_STATE_CONFIGED) {\r
400     Status = EFI_NOT_STARTED;\r
401   }\r
402 \r
403   if (Instance->Operation != 0) {\r
404     Status = EFI_ACCESS_DENIED;\r
405   }\r
406 \r
407   if ((Token->OverrideData != NULL) && !Mtftp4OverrideValid (Instance, Token->OverrideData)) {\r
408     Status = EFI_INVALID_PARAMETER;\r
409   }\r
410 \r
411   if (EFI_ERROR (Status)) {\r
412     gBS->RestoreTPL (OldTpl);\r
413     return Status;\r
414   }\r
415 \r
416   //\r
417   // Set the Operation now to prevent the application start other\r
418   // operations.\r
419   //\r
420   Instance->Operation = Operation;\r
421   Override            = Token->OverrideData;\r
422 \r
423   if (Token->OptionCount != 0) {\r
424     Status = Mtftp4ParseOption (\r
425                Token->OptionList,\r
426                Token->OptionCount,\r
427                TRUE,\r
428                Instance->Operation,\r
429                &Instance->RequestOption\r
430                );\r
431 \r
432     if (EFI_ERROR (Status)) {\r
433       TokenStatus = EFI_DEVICE_ERROR;\r
434       goto ON_ERROR;\r
435     }\r
436   }\r
437 \r
438   //\r
439   // Set the operation parameters from the configuration or override data.\r
440   //\r
441   Config                  = &Instance->Config;\r
442   Instance->Token         = Token;\r
443   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;\r
444   Instance->WindowSize    = MTFTP4_DEFAULT_WINDOWSIZE;\r
445 \r
446   CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));\r
447   Instance->ServerIp      = NTOHL (Instance->ServerIp);\r
448 \r
449   Instance->ListeningPort = Config->InitialServerPort;\r
450   Instance->ConnectedPort = 0;\r
451 \r
452   CopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));\r
453   Instance->Gateway       = NTOHL (Instance->Gateway);\r
454 \r
455   Instance->MaxRetry      = Config->TryCount;\r
456   Instance->Timeout       = Config->TimeoutValue;\r
457   Instance->Master        = TRUE;\r
458 \r
459   if (Override != NULL) {\r
460     CopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));\r
461     CopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
462 \r
463     Instance->ServerIp      = NTOHL (Instance->ServerIp);\r
464     Instance->Gateway       = NTOHL (Instance->Gateway);\r
465 \r
466     Instance->ListeningPort = Override->ServerPort;\r
467     Instance->MaxRetry      = Override->TryCount;\r
468     Instance->Timeout       = Override->TimeoutValue;\r
469   }\r
470 \r
471   if (Instance->ListeningPort == 0) {\r
472     Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;\r
473   }\r
474 \r
475   if (Instance->MaxRetry == 0) {\r
476     Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;\r
477   }\r
478 \r
479   if (Instance->Timeout == 0) {\r
480     Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;\r
481   }\r
482 \r
483   //\r
484   // Config the unicast UDP child to send initial request\r
485   //\r
486   Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);\r
487   if (EFI_ERROR (Status)) {\r
488     TokenStatus = EFI_DEVICE_ERROR;\r
489     goto ON_ERROR;\r
490   }\r
491 \r
492   //\r
493   // Set initial status.\r
494   //\r
495   Token->Status = EFI_NOT_READY;\r
496 \r
497   //\r
498   // Build and send an initial requests\r
499   //\r
500   if (Operation == EFI_MTFTP4_OPCODE_WRQ) {\r
501     Status = Mtftp4WrqStart (Instance, Operation);\r
502   } else {\r
503     Status = Mtftp4RrqStart (Instance, Operation);\r
504   }\r
505 \r
506   if (EFI_ERROR (Status)) {\r
507     TokenStatus = EFI_DEVICE_ERROR;\r
508     goto ON_ERROR;\r
509   }\r
510 \r
511   gBS->RestoreTPL(OldTpl);\r
512 \r
513   if (Token->Event != NULL) {\r
514     return EFI_SUCCESS;\r
515   }\r
516 \r
517   //\r
518   // Return immediately for asynchronous operation or poll the\r
519   // instance for synchronous operation.\r
520   //\r
521   while (Token->Status == EFI_NOT_READY) {\r
522     This->Poll (This);\r
523   }\r
524 \r
525   return Token->Status;\r
526 \r
527 ON_ERROR:\r
528   Mtftp4CleanOperation (Instance, TokenStatus);\r
529   gBS->RestoreTPL (OldTpl);\r
530 \r
531   return Status;\r
532 }\r
533 \r
534 \r
535 /**\r
536   Reads the current operational settings.\r
537 \r
538   The GetModeData()function reads the current operational settings of this\r
539   EFI MTFTPv4 Protocol driver instance.\r
540 \r
541   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
542   @param  ModeData               Pointer to storage for the EFI MTFTPv4 Protocol\r
543                                  driver mode data.\r
544 \r
545   @retval EFI_SUCCESS            The configuration data was successfully returned.\r
546   @retval EFI_OUT_OF_RESOURCES   The required mode data could not be allocated.\r
547   @retval EFI_INVALID_PARAMETER  This is NULL or ModeData is NULL.\r
548 \r
549 **/\r
550 EFI_STATUS\r
551 EFIAPI\r
552 EfiMtftp4GetModeData (\r
553   IN     EFI_MTFTP4_PROTOCOL    *This,\r
554      OUT EFI_MTFTP4_MODE_DATA  *ModeData\r
555   )\r
556 {\r
557   MTFTP4_PROTOCOL  *Instance;\r
558   EFI_TPL          OldTpl;\r
559 \r
560   if ((This == NULL) || (ModeData == NULL)) {\r
561     return EFI_INVALID_PARAMETER;\r
562   }\r
563 \r
564   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
565 \r
566   Instance                         = MTFTP4_PROTOCOL_FROM_THIS (This);\r
567   CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));\r
568   ModeData->SupportedOptionCount   = MTFTP4_SUPPORTED_OPTIONS;\r
569   ModeData->SupportedOptoins       = (UINT8 **) mMtftp4SupportedOptions;\r
570   ModeData->UnsupportedOptionCount = 0;\r
571   ModeData->UnsupportedOptoins     = NULL;\r
572 \r
573   gBS->RestoreTPL (OldTpl);\r
574 \r
575   return EFI_SUCCESS;\r
576 }\r
577 \r
578 \r
579 \r
580 /**\r
581   Initializes, changes, or resets the default operational setting for this\r
582   EFI MTFTPv4 Protocol driver instance.\r
583 \r
584   The Configure() function is used to set and change the configuration data for\r
585   this EFI MTFTPv4 Protocol driver instance. The configuration data can be reset\r
586   to startup defaults by calling Configure() with MtftpConfigData set to NULL.\r
587   Whenever the instance is reset, any pending operation is aborted. By changing\r
588   the EFI MTFTPv4 Protocol driver instance configuration data, the client can\r
589   connect to different MTFTPv4 servers. The configuration parameters in\r
590   MtftpConfigData are used as the default parameters in later MTFTPv4 operations\r
591   and can be overridden in later operations.\r
592 \r
593   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
594   @param  ConfigData             MtftpConfigDataPointer to the configuration data\r
595                                  structure\r
596 \r
597   @retval EFI_SUCCESS            The EFI MTFTPv4 Protocol driver was configured\r
598                                  successfully.\r
599   @retval EFI_INVALID_PARAMETER  One or more following conditions are TRUE:\r
600                                  1.This is NULL.\r
601                                  2.MtftpConfigData.UseDefaultSetting is FALSE and\r
602                                    MtftpConfigData.StationIp is not a valid IPv4\r
603                                    unicast address.\r
604                                  3.MtftpCofigData.UseDefaultSetting is FALSE and\r
605                                    MtftpConfigData.SubnetMask is invalid.\r
606                                  4.MtftpCofigData.ServerIp is not a valid IPv4\r
607                                    unicast address.\r
608                                  5.MtftpConfigData.UseDefaultSetting is FALSE and\r
609                                    MtftpConfigData.GatewayIp is not a valid IPv4\r
610                                    unicast address or is not in the same subnet\r
611                                    with station address.\r
612   @retval EFI_ACCESS_DENIED      The EFI configuration could not be changed at this\r
613                                  time because there is one MTFTP background operation\r
614                                  in progress.\r
615   @retval EFI_NO_MAPPING         When using a default address, configuration\r
616                                  (DHCP, BOOTP, RARP, etc.) has not finished yet.\r
617   @retval EFI_UNSUPPORTED        A configuration protocol (DHCP, BOOTP, RARP, etc.)\r
618                                  could not be located when clients choose to use\r
619                                  the default address settings.\r
620   @retval EFI_OUT_OF_RESOURCES   The EFI MTFTPv4 Protocol driver instance data could\r
621                                  not be allocated.\r
622   @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.\r
623                                  The EFI MTFTPv4 Protocol driver instance is not\r
624                                  configured.\r
625 \r
626 **/\r
627 EFI_STATUS\r
628 EFIAPI\r
629 EfiMtftp4Configure (\r
630   IN EFI_MTFTP4_PROTOCOL    *This,\r
631   IN EFI_MTFTP4_CONFIG_DATA *ConfigData\r
632   )\r
633 {\r
634   MTFTP4_PROTOCOL           *Instance;\r
635   EFI_TPL                   OldTpl;\r
636   IP4_ADDR                  Ip;\r
637   IP4_ADDR                  Netmask;\r
638   IP4_ADDR                  Gateway;\r
639   IP4_ADDR                  ServerIp;\r
640 \r
641   if (This == NULL) {\r
642     return EFI_INVALID_PARAMETER;\r
643   }\r
644 \r
645   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
646 \r
647   if (ConfigData == NULL) {\r
648     //\r
649     // Reset the operation if ConfigData is NULL\r
650     //\r
651     OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
652 \r
653     Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
654     ZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
655     Instance->State = MTFTP4_STATE_UNCONFIGED;\r
656 \r
657     gBS->RestoreTPL (OldTpl);\r
658 \r
659   } else {\r
660     //\r
661     // Configure the parameters for new operation.\r
662     //\r
663     CopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));\r
664     CopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
665     CopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));\r
666     CopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));\r
667 \r
668     Ip       = NTOHL (Ip);\r
669     Netmask  = NTOHL (Netmask);\r
670     Gateway  = NTOHL (Gateway);\r
671     ServerIp = NTOHL (ServerIp);\r
672 \r
673     if (ServerIp == 0 || IP4_IS_LOCAL_BROADCAST (ServerIp)) {\r
674       return EFI_INVALID_PARAMETER;\r
675     }\r
676 \r
677     if (!ConfigData->UseDefaultSetting &&\r
678         ((!IP4_IS_VALID_NETMASK (Netmask) || (Netmask != 0 && !NetIp4IsUnicast (Ip, Netmask))))) {\r
679 \r
680       return EFI_INVALID_PARAMETER;\r
681     }\r
682 \r
683     if ((Gateway != 0) &&\r
684         ((Netmask != 0xFFFFFFFF && !IP4_NET_EQUAL (Gateway, Ip, Netmask)) || (Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)))) {\r
685 \r
686       return EFI_INVALID_PARAMETER;\r
687     }\r
688 \r
689     OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
690 \r
691     if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {\r
692       gBS->RestoreTPL (OldTpl);\r
693       return EFI_ACCESS_DENIED;\r
694     }\r
695 \r
696     CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;\r
697     Instance->State = MTFTP4_STATE_CONFIGED;\r
698 \r
699     gBS->RestoreTPL (OldTpl);\r
700   }\r
701 \r
702   return EFI_SUCCESS;\r
703 }\r
704 \r
705 \r
706 \r
707 /**\r
708   Parses the options in an MTFTPv4 OACK packet.\r
709 \r
710   The ParseOptions() function parses the option fields in an MTFTPv4 OACK packet\r
711   and returns the number of options that were found and optionally a list of\r
712   pointers to the options in the packet.\r
713   If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is\r
714   returned and *OptionCount and *OptionList stop at the last valid option.\r
715   The OptionList is allocated by this function, and caller should free it when used.\r
716 \r
717   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
718   @param  PacketLen              Length of the OACK packet to be parsed.\r
719   @param  Packet                 Pointer to the OACK packet to be parsed.\r
720   @param  OptionCount            Pointer to the number of options in following OptionList.\r
721   @param  OptionList             Pointer to EFI_MTFTP4_OPTION storage. Call the\r
722                                  EFI Boot Service FreePool() to release theOptionList\r
723                                  if the options in this OptionList are not needed\r
724                                  any more\r
725 \r
726   @retval EFI_SUCCESS            The OACK packet was valid and the OptionCount and\r
727                                  OptionList parameters have been updated.\r
728   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
729                                  1.PacketLen is 0.\r
730                                  2.Packet is NULL or Packet is not a valid MTFTPv4 packet.\r
731                                  3.OptionCount is NULL.\r
732   @retval EFI_NOT_FOUND          No options were found in the OACK packet.\r
733   @retval EFI_OUT_OF_RESOURCES   Storage for the OptionList array cannot be allocated.\r
734   @retval EFI_PROTOCOL_ERROR     One or more of the option fields is invalid.\r
735 \r
736 **/\r
737 EFI_STATUS\r
738 EFIAPI\r
739 EfiMtftp4ParseOptions (\r
740   IN     EFI_MTFTP4_PROTOCOL    *This,\r
741   IN     UINT32                 PacketLen,\r
742   IN     EFI_MTFTP4_PACKET      *Packet,\r
743      OUT UINT32                 *OptionCount,\r
744      OUT EFI_MTFTP4_OPTION      **OptionList          OPTIONAL\r
745   )\r
746 {\r
747   EFI_STATUS                Status;\r
748 \r
749   if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||\r
750       (Packet == NULL) || (OptionCount == NULL)) {\r
751 \r
752     return EFI_INVALID_PARAMETER;\r
753   }\r
754 \r
755   Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);\r
756 \r
757   if (EFI_ERROR (Status)) {\r
758     return Status;\r
759   }\r
760 \r
761   if (*OptionCount == 0) {\r
762     return EFI_NOT_FOUND;\r
763   }\r
764 \r
765   return EFI_SUCCESS;\r
766 }\r
767 \r
768 \r
769 /**\r
770   Downloads a file from an MTFTPv4 server.\r
771 \r
772   The ReadFile() function is used to initialize and start an MTFTPv4 download\r
773   process and optionally wait for completion. When the download operation completes,\r
774   whether successfully or not, the Token.Status field is updated by the EFI MTFTPv4\r
775   Protocol driver and then Token.Event is signaled (if it is not NULL).\r
776   Data can be downloaded from the MTFTPv4 server into either of the following locations:\r
777   1.A fixed buffer that is pointed to by Token.Buffer\r
778   2.A download service function that is pointed to by Token.CheckPacket\r
779   If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket\r
780   will be called first. If the call is successful, the packet will be stored in\r
781   Token.Buffer.\r
782 \r
783   @param  This                  Pointer to the EFI_MTFTP4_PROTOCOL instance\r
784   @param  Token                 Pointer to the token structure to provide the\r
785                                 parameters that are used in this operation.\r
786 \r
787   @retval EFI_SUCCESS           The data file has been transferred successfully.\r
788   @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
789   @retval EFI_BUFFER_TOO_SMALL  BufferSize is not large enough to hold the downloaded\r
790                                 data in downloading process.\r
791   @retval EFI_ABORTED           Current operation is aborted by user.\r
792   @retval EFI_ICMP_ERROR        An ICMP ERROR packet was received.\r
793   @retval EFI_TIMEOUT           No responses were received from the MTFTPv4 server.\r
794   @retval EFI_TFTP_ERROR        An MTFTPv4 ERROR packet was received.\r
795   @retval EFI_DEVICE_ERROR      An unexpected network error or system error occurred.\r
796   @retval EFI_NO_MEDIA          There was a media error.\r
797 \r
798 **/\r
799 EFI_STATUS\r
800 EFIAPI\r
801 EfiMtftp4ReadFile (\r
802   IN EFI_MTFTP4_PROTOCOL    *This,\r
803   IN EFI_MTFTP4_TOKEN       *Token\r
804   )\r
805 {\r
806   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);\r
807 }\r
808 \r
809 \r
810 /**\r
811   Sends a data file to an MTFTPv4 server. May be unsupported in some EFI implementations\r
812 \r
813   The WriteFile() function is used to initialize an uploading operation with the\r
814   given option list and optionally wait for completion. If one or more of the\r
815   options is not supported by the server, the unsupported options are ignored and\r
816   a standard TFTP process starts instead. When the upload process completes,\r
817   whether successfully or not, Token.Event is signaled, and the EFI MTFTPv4 Protocol\r
818   driver updates Token.Status.\r
819   The caller can supply the data to be uploaded in the following two modes:\r
820   1.Through the user-provided buffer\r
821   2.Through a callback function\r
822   With the user-provided buffer, the Token.BufferSize field indicates the length\r
823   of the buffer, and the driver will upload the data in the buffer. With an\r
824   EFI_MTFTP4_PACKET_NEEDED callback function, the driver will call this callback\r
825   function to get more data from the user to upload. See the definition of\r
826   EFI_MTFTP4_PACKET_NEEDED for more information. These two modes cannot be used at\r
827   the same time. The callback function will be ignored if the user provides the buffer.\r
828 \r
829   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
830   @param  Token                  Pointer to the token structure to provide the\r
831                                  parameters that are used in this function\r
832 \r
833   @retval EFI_SUCCESS            The upload session has started.\r
834   @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.\r
835   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
836                                  1. This is NULL.\r
837                                  2. Token is NULL.\r
838                                  3. Token.Filename is NULL.\r
839                                  4. Token.OptionCount is not zero and\r
840                                     Token.OptionList is NULL.\r
841                                  5. One or more options in Token.OptionList have wrong\r
842                                     format.\r
843                                  6. Token.Buffer and Token.PacketNeeded are both\r
844                                     NULL.\r
845                                  7. One or more IPv4 addresses in Token.OverrideData\r
846                                     are not valid unicast IPv4 addresses if\r
847                                     Token.OverrideData is not NULL.\r
848   @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the\r
849                                  unsupported list of structure EFI_MTFTP4_MODE_DATA.\r
850   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
851   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
852                                  BOOTP, RARP, etc.) is not finished yet.\r
853   @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4\r
854                                  session.\r
855   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
856   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
857   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
858 \r
859 **/\r
860 EFI_STATUS\r
861 EFIAPI\r
862 EfiMtftp4WriteFile (\r
863   IN EFI_MTFTP4_PROTOCOL    *This,\r
864   IN EFI_MTFTP4_TOKEN       *Token\r
865   )\r
866 {\r
867   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);\r
868 }\r
869 \r
870 \r
871 /**\r
872   Downloads a data file "directory" from an MTFTPv4 server.\r
873   May be unsupported in some EFI implementations\r
874 \r
875   The ReadDirectory() function is used to return a list of files on the MTFTPv4\r
876   server that are logically (or operationally) related to Token.Filename. The\r
877   directory request packet that is sent to the server is built with the option\r
878   list that was provided by caller, if present.\r
879   The file information that the server returns is put into either of the following\r
880   locations:\r
881   1.A fixed buffer that is pointed to by Token.Buffer\r
882   2.A download service function that is pointed to by Token.CheckPacket\r
883   If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket will\r
884   be called first. If the call is successful, the packet will be stored in Token.Buffer.\r
885   The returned directory listing in the Token.Buffer or EFI_MTFTP4_PACKET consists\r
886   of a list of two or three variable-length ASCII strings, each terminated by a\r
887   null character, for each file in the directory. If the multicast option is involved,\r
888   the first field of each directory entry is the static multicast IP address and\r
889   UDP port number that is associated with the file name. The format of the field\r
890   is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its\r
891   terminating null character are not present.\r
892   The next field of each directory entry is the file name and the last field is\r
893   the file information string. The information string contains the file size and\r
894   the create/modify timestamp. The format of the information string is filesize\r
895   yyyy-mm-dd hh:mm:ss:ffff. The timestamp is Coordinated Universal Time\r
896   (UTC; also known as Greenwich Mean Time [GMT]).\r
897   The only difference between ReadFile and ReadDirectory is the opcode used.\r
898 \r
899   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
900   @param  Token                  Pointer to the token structure to provide the\r
901                                  parameters that are used in this function\r
902 \r
903   @retval EFI_SUCCESS            The MTFTPv4 related file "directory" has been downloaded.\r
904   @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.\r
905   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
906                                  1. This is NULL.\r
907                                  2. Token is NULL.\r
908                                  3. Token.Filename is NULL.\r
909                                  4. Token.OptionCount is not zero and\r
910                                     Token.OptionList is NULL.\r
911                                  5. One or more options in Token.OptionList have wrong\r
912                                     format.\r
913                                  6. Token.Buffer and Token.PacketNeeded are both\r
914                                     NULL.\r
915                                  7. One or more IPv4 addresses in Token.OverrideData\r
916                                     are not valid unicast IPv4 addresses if\r
917                                     Token.OverrideData is not NULL.\r
918   @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the\r
919                                  unsupported list of structure EFI_MTFTP4_MODE_DATA.\r
920   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
921   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
922                                  BOOTP, RARP, etc.) is not finished yet.\r
923   @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4\r
924                                  session.\r
925   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
926   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
927   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
928 \r
929 **/\r
930 EFI_STATUS\r
931 EFIAPI\r
932 EfiMtftp4ReadDirectory (\r
933   IN EFI_MTFTP4_PROTOCOL        *This,\r
934   IN EFI_MTFTP4_TOKEN           *Token\r
935   )\r
936 {\r
937   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);\r
938 }\r
939 \r
940 \r
941 /**\r
942   Gets information about a file from an MTFTPv4 server.\r
943 \r
944   The GetInfo() function assembles an MTFTPv4 request packet with options;\r
945   sends it to the MTFTPv4 server; and may return an MTFTPv4 OACK, MTFTPv4 ERROR,\r
946   or ICMP ERROR packet. Retries occur only if no response packets are received\r
947   from the MTFTPv4 server before the timeout expires.\r
948   It is implemented with EfiMtftp4ReadFile: build a token, then pass it to\r
949   EfiMtftp4ReadFile. In its check packet callback abort the opertions.\r
950 \r
951   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
952   @param  OverrideData           Data that is used to override the existing\r
953                                  parameters. If NULL, the default parameters that\r
954                                  were set in the EFI_MTFTP4_PROTOCOL.Configure()\r
955                                  function are used\r
956   @param  Filename               Pointer to null-terminated ASCII file name string\r
957   @param  ModeStr                Pointer to null-terminated ASCII mode string. If NULL, "octet"\r
958                                  will be used\r
959   @param  OptionCount            Number of option/value string pairs in OptionList\r
960   @param  OptionList             Pointer to array of option/value string pairs.\r
961                                  Ignored if OptionCount is zero\r
962   @param  PacketLength           The number of bytes in the returned packet\r
963   @param  Packet                 PacketThe pointer to the received packet. This\r
964                                  buffer must be freed by the caller.\r
965 \r
966   @retval EFI_SUCCESS            An MTFTPv4 OACK packet was received and is in\r
967                                  the Buffer.\r
968   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
969                                  1.This is NULL.\r
970                                  2.Filename is NULL.\r
971                                  3.OptionCount is not zero and OptionList is NULL.\r
972                                  4.One or more options in OptionList have wrong format.\r
973                                  5.PacketLength is NULL.\r
974                                  6.One or more IPv4 addresses in OverrideData are\r
975                                    not valid unicast IPv4 addresses if OverrideData\r
976                                    is not NULL.\r
977   @retval EFI_UNSUPPORTED        One or more options in the OptionList are in the\r
978                                  unsupported list of structure EFI_MTFTP4_MODE_DATA\r
979   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
980   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
981                                  BOOTP, RARP, etc.) has not finished yet.\r
982   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
983   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
984   @retval EFI_TFTP_ERROR         An MTFTPv4 ERROR packet was received and is in\r
985                                  the Buffer.\r
986   @retval EFI_ICMP_ERROR         An ICMP ERROR packet was received and the Packet\r
987                                  is set to NULL.\r
988   @retval EFI_PROTOCOL_ERROR     An unexpected MTFTPv4 packet was received and is\r
989                                  in the Buffer.\r
990   @retval EFI_TIMEOUT            No responses were received from the MTFTPv4 server.\r
991   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
992   @retval EFI_NO_MEDIA           There was a media error.\r
993 \r
994 **/\r
995 EFI_STATUS\r
996 EFIAPI\r
997 EfiMtftp4GetInfo (\r
998   IN     EFI_MTFTP4_PROTOCOL      *This,\r
999   IN     EFI_MTFTP4_OVERRIDE_DATA *OverrideData        OPTIONAL,\r
1000   IN     UINT8                    *Filename,\r
1001   IN     UINT8                    *ModeStr             OPTIONAL,\r
1002   IN     UINT8                    OptionCount,\r
1003   IN     EFI_MTFTP4_OPTION        *OptionList          OPTIONAL,\r
1004      OUT UINT32                   *PacketLength,\r
1005      OUT EFI_MTFTP4_PACKET        **Packet             OPTIONAL\r
1006   )\r
1007 {\r
1008   EFI_MTFTP4_TOKEN          Token;\r
1009   MTFTP4_GETINFO_STATE      State;\r
1010   EFI_STATUS                Status;\r
1011 \r
1012   if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||\r
1013       ((OptionCount != 0) && (OptionList == NULL))) {\r
1014     return EFI_INVALID_PARAMETER;\r
1015   }\r
1016 \r
1017   if (Packet != NULL) {\r
1018     *Packet = NULL;\r
1019   }\r
1020 \r
1021   *PacketLength         = 0;\r
1022   State.Packet          = Packet;\r
1023   State.PacketLen       = PacketLength;\r
1024   State.Status          = EFI_SUCCESS;\r
1025 \r
1026   //\r
1027   // Fill in the Token to issue an synchronous ReadFile operation\r
1028   //\r
1029   Token.Status          = EFI_SUCCESS;\r
1030   Token.Event           = NULL;\r
1031   Token.OverrideData    = OverrideData;\r
1032   Token.Filename        = Filename;\r
1033   Token.ModeStr         = ModeStr;\r
1034   Token.OptionCount     = OptionCount;\r
1035   Token.OptionList      = OptionList;\r
1036   Token.BufferSize      = 0;\r
1037   Token.Buffer          = NULL;\r
1038   Token.Context         = &State;\r
1039   Token.CheckPacket     = Mtftp4GetInfoCheckPacket;\r
1040   Token.TimeoutCallback = NULL;\r
1041   Token.PacketNeeded    = NULL;\r
1042 \r
1043   Status                = EfiMtftp4ReadFile (This, &Token);\r
1044 \r
1045   if (EFI_ABORTED == Status) {\r
1046     return State.Status;\r
1047   }\r
1048 \r
1049   return Status;\r
1050 }\r
1051 \r
1052 /**\r
1053   Polls for incoming data packets and processes outgoing data packets.\r
1054 \r
1055   The Poll() function can be used by network drivers and applications to increase\r
1056   the rate that data packets are moved between the communications device and the\r
1057   transmit and receive queues.\r
1058   In some systems, the periodic timer event in the managed network driver may not\r
1059   poll the underlying communications device fast enough to transmit and/or receive\r
1060   all data packets without missing incoming packets or dropping outgoing packets.\r
1061   Drivers and applications that are experiencing packet loss should try calling\r
1062   the Poll() function more often.\r
1063 \r
1064   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
1065 \r
1066   @retval EFI_SUCCESS            Incoming or outgoing data was processed.\r
1067   @retval EFI_NOT_STARTED        This EFI MTFTPv4 Protocol instance has not been started.\r
1068   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
1069                                  BOOTP, RARP, etc.) is not finished yet.\r
1070   @retval EFI_INVALID_PARAMETER  This is NULL.\r
1071   @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.\r
1072   @retval EFI_TIMEOUT            Data was dropped out of the transmit and/or receive\r
1073                                  queue. Consider increasing the polling rate.\r
1074 \r
1075 **/\r
1076 EFI_STATUS\r
1077 EFIAPI\r
1078 EfiMtftp4Poll (\r
1079   IN EFI_MTFTP4_PROTOCOL    *This\r
1080   )\r
1081 {\r
1082   MTFTP4_PROTOCOL           *Instance;\r
1083   EFI_UDP4_PROTOCOL         *Udp;\r
1084   EFI_STATUS                Status;\r
1085 \r
1086   if (This == NULL) {\r
1087     return EFI_INVALID_PARAMETER;\r
1088   }\r
1089 \r
1090   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
1091 \r
1092   if (Instance->State == MTFTP4_STATE_UNCONFIGED) {\r
1093     return EFI_NOT_STARTED;\r
1094   } else if (Instance->State == MTFTP4_STATE_DESTROY) {\r
1095     return EFI_DEVICE_ERROR;\r
1096   }\r
1097 \r
1098   Udp = Instance->UnicastPort->Protocol.Udp4;\r
1099   Status = Udp->Poll (Udp);\r
1100   Mtftp4OnTimerTick (NULL, Instance->Service);\r
1101   return Status;\r
1102 }\r
1103 \r
1104 EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {\r
1105   EfiMtftp4GetModeData,\r
1106   EfiMtftp4Configure,\r
1107   EfiMtftp4GetInfo,\r
1108   EfiMtftp4ParseOptions,\r
1109   EfiMtftp4ReadFile,\r
1110   EfiMtftp4WriteFile,\r
1111   EfiMtftp4ReadDirectory,\r
1112   EfiMtftp4Poll\r
1113 };\r