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