]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
sync function header to avoid ecc
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Impl.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Mtftp4Impl.c\r
15\r
16Abstract:\r
17\r
18 Interface routine for Mtftp4\r
19\r
20\r
21**/\r
22\r
23#include "Mtftp4Impl.h"\r
24\r
772db4bb 25EFI_STATUS\r
26EFIAPI\r
27EfiMtftp4ReadFile (\r
28 IN EFI_MTFTP4_PROTOCOL *This,\r
29 IN EFI_MTFTP4_TOKEN *Token\r
30 );\r
31\r
32\r
33/**\r
34 Get the current operation parameter for the MTFTP session\r
35\r
36 @param This The MTFTP protocol instance\r
37 @param ModeData The MTFTP mode data\r
38\r
39 @retval EFI_INVALID_PARAMETER This or ModeData is NULL\r
40 @retval EFI_SUCCESS The operation parameter is saved in ModeData\r
41\r
42**/\r
772db4bb 43EFI_STATUS\r
44EFIAPI\r
45EfiMtftp4GetModeData (\r
46 IN EFI_MTFTP4_PROTOCOL *This,\r
47 OUT EFI_MTFTP4_MODE_DATA *ModeData\r
48 )\r
49{\r
50 MTFTP4_PROTOCOL *Instance;\r
51 EFI_TPL OldTpl;\r
52\r
53 if ((This == NULL) || (ModeData == NULL)) {\r
54 return EFI_INVALID_PARAMETER;\r
55 }\r
56\r
e48e37fc 57 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 58\r
59 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
84b5c78e 60 CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));\r
772db4bb 61 ModeData->SupportedOptionCount = MTFTP4_SUPPORTED_OPTIONS;\r
67a58d0f 62 ModeData->SupportedOptoins = (UINT8 **) mMtftp4SupportedOptions;\r
772db4bb 63 ModeData->UnsupportedOptionCount = 0;\r
64 ModeData->UnsupportedOptoins = NULL;\r
65\r
e48e37fc 66 gBS->RestoreTPL (OldTpl);\r
772db4bb 67\r
68 return EFI_SUCCESS;\r
69}\r
70\r
71\r
72/**\r
73 Clean up the MTFTP session to get ready for new operation.\r
74\r
75 @param Instance The MTFTP session to clean up\r
76 @param Result The result to return to the caller who initiated\r
77 the operation.\r
78\r
79 @return None\r
80\r
81**/\r
82VOID\r
83Mtftp4CleanOperation (\r
84 IN MTFTP4_PROTOCOL *Instance,\r
85 IN EFI_STATUS Result\r
86 )\r
87{\r
e48e37fc 88 LIST_ENTRY *Entry;\r
89 LIST_ENTRY *Next;\r
772db4bb 90 MTFTP4_BLOCK_RANGE *Block;\r
91 EFI_MTFTP4_TOKEN *Token;\r
92\r
93 //\r
94 // Free various resources.\r
95 //\r
96 Token = Instance->Token;\r
97\r
98 if (Token != NULL) {\r
99 Token->Status = Result;\r
100\r
101 if (Token->Event != NULL) {\r
102 gBS->SignalEvent (Token->Event);\r
103 }\r
104\r
105 Instance->Token = NULL;\r
106 }\r
107\r
108 ASSERT (Instance->UnicastPort != NULL);\r
109 UdpIoCleanPort (Instance->UnicastPort);\r
110\r
111 if (Instance->LastPacket != NULL) {\r
112 NetbufFree (Instance->LastPacket);\r
113 Instance->LastPacket = NULL;\r
114 }\r
115\r
116 if (Instance->McastUdpPort != NULL) {\r
117 UdpIoFreePort (Instance->McastUdpPort);\r
118 Instance->McastUdpPort = NULL;\r
119 }\r
120\r
121 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {\r
122 Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);\r
e48e37fc 123 RemoveEntryList (Entry);\r
124 gBS->FreePool (Block);\r
772db4bb 125 }\r
126\r
e48e37fc 127 ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));\r
772db4bb 128\r
129 Instance->Operation = 0;\r
130\r
131 Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;\r
132 Instance->LastBlock = 0;\r
133 Instance->ServerIp = 0;\r
134 Instance->ListeningPort = 0;\r
135 Instance->ConnectedPort = 0;\r
136 Instance->Gateway = 0;\r
137 Instance->PacketToLive = 0;\r
138 Instance->MaxRetry = 0;\r
139 Instance->CurRetry = 0;\r
140 Instance->Timeout = 0;\r
141 Instance->McastIp = 0;\r
142 Instance->McastPort = 0;\r
143 Instance->Master = TRUE;\r
144}\r
145\r
146\r
147/**\r
148 Configure the MTFTP session for new operation or reset the current\r
149 operation if ConfigData is NULL.\r
150\r
151 @param This The MTFTP session to configure\r
152 @param ConfigData The configure parameters\r
153\r
154 @retval EFI_INVALID_PARAMETER Some of the parameter is invalid.\r
155 @retval EFI_ACCESS_DENIED There is pending operation\r
156 @retval EFI_SUCCESS The instance is configured for operation.\r
157\r
158**/\r
772db4bb 159EFI_STATUS\r
160EFIAPI\r
161EfiMtftp4Configure (\r
162 IN EFI_MTFTP4_PROTOCOL *This,\r
163 IN EFI_MTFTP4_CONFIG_DATA *ConfigData\r
164 )\r
165{\r
166 MTFTP4_PROTOCOL *Instance;\r
167 EFI_TPL OldTpl;\r
168 IP4_ADDR Ip;\r
169 IP4_ADDR Netmask;\r
170 IP4_ADDR Gateway;\r
171 IP4_ADDR ServerIp;\r
172\r
173 if (This == NULL) {\r
174 return EFI_INVALID_PARAMETER;\r
175 }\r
176\r
177 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
178\r
179 if (ConfigData == NULL) {\r
180 //\r
181 // Reset the operation if ConfigData is NULL\r
182 //\r
e48e37fc 183 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 184\r
185 Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
e48e37fc 186 ZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
772db4bb 187 Instance->State = MTFTP4_STATE_UNCONFIGED;\r
188\r
e48e37fc 189 gBS->RestoreTPL (OldTpl);\r
772db4bb 190\r
191 } else {\r
192 //\r
193 // Configure the parameters for new operation.\r
194 //\r
e48e37fc 195 CopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));\r
196 CopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
197 CopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));\r
198 CopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));\r
772db4bb 199\r
200 Ip = NTOHL (Ip);\r
201 Netmask = NTOHL (Netmask);\r
202 Gateway = NTOHL (Gateway);\r
203 ServerIp = NTOHL (ServerIp);\r
204\r
205 if (!Ip4IsUnicast (ServerIp, 0)) {\r
206 return EFI_INVALID_PARAMETER;\r
207 }\r
208\r
209 if (!ConfigData->UseDefaultSetting &&\r
210 ((!IP4_IS_VALID_NETMASK (Netmask) || !Ip4IsUnicast (Ip, Netmask)))) {\r
211\r
212 return EFI_INVALID_PARAMETER;\r
213 }\r
214\r
215 if ((Gateway != 0) &&\r
216 (!IP4_NET_EQUAL (Gateway, Ip, Netmask) || !Ip4IsUnicast (Gateway, Netmask))) {\r
217\r
218 return EFI_INVALID_PARAMETER;\r
219 }\r
220\r
e48e37fc 221 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 222\r
223 if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {\r
e48e37fc 224 gBS->RestoreTPL (OldTpl);\r
772db4bb 225 return EFI_ACCESS_DENIED;\r
226 }\r
227\r
84b5c78e 228 CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;\r
772db4bb 229 Instance->State = MTFTP4_STATE_CONFIGED;\r
230\r
e48e37fc 231 gBS->RestoreTPL (OldTpl);\r
772db4bb 232 }\r
233\r
234 return EFI_SUCCESS;\r
235}\r
236\r
237\r
238/**\r
239 Check packet for GetInfo. GetInfo is implemented with EfiMtftp4ReadFile.\r
240 It use Mtftp4GetInfoCheckPacket to inspect the first packet from server,\r
241 then abort the session.\r
242\r
243 @param This The MTFTP4 protocol instance\r
244 @param Token The user's token\r
245 @param PacketLen The length of the packet\r
246 @param Packet The received packet.\r
247\r
248 @retval EFI_ABORTED Abort the ReadFile operation and return.\r
249\r
250**/\r
772db4bb 251EFI_STATUS\r
252Mtftp4GetInfoCheckPacket (\r
253 IN EFI_MTFTP4_PROTOCOL *This,\r
254 IN EFI_MTFTP4_TOKEN *Token,\r
255 IN UINT16 PacketLen,\r
256 IN EFI_MTFTP4_PACKET *Packet\r
257 )\r
258{\r
61066b8d 259 MTFTP4_PROTOCOL *Instance;\r
772db4bb 260 MTFTP4_GETINFO_STATE *State;\r
261 EFI_STATUS Status;\r
262 UINT16 OpCode;\r
263\r
61066b8d 264 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
265 State = &Instance->GetInfoState;\r
a5867703 266 OpCode = NTOHS (Packet->OpCode);\r
772db4bb 267\r
268 //\r
269 // Set the GetInfo's return status according to the OpCode.\r
270 //\r
271 switch (OpCode) {\r
272 case EFI_MTFTP4_OPCODE_ERROR:\r
273 State->Status = EFI_TFTP_ERROR;\r
274 break;\r
275\r
276 case EFI_MTFTP4_OPCODE_OACK:\r
277 State->Status = EFI_SUCCESS;\r
278 break;\r
279\r
280 default:\r
281 State->Status = EFI_PROTOCOL_ERROR;\r
282 }\r
283\r
284 //\r
285 // Allocate buffer then copy the packet over. Use gBS->AllocatePool\r
e48e37fc 286 // in case AllocatePool will implements something tricky.\r
772db4bb 287 //\r
288 Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);\r
289\r
290 if (EFI_ERROR (Status)) {\r
291 State->Status = EFI_OUT_OF_RESOURCES;\r
292 return EFI_ABORTED;\r
293 }\r
294\r
295 *(State->PacketLen) = PacketLen;\r
e48e37fc 296 CopyMem (*(State->Packet), Packet, PacketLen);\r
772db4bb 297\r
298 return EFI_ABORTED;\r
299}\r
300\r
301\r
302/**\r
303 Get the information of the download from the server. It is implemented\r
304 with EfiMtftp4ReadFile: build a token, then pass it to EfiMtftp4ReadFile.\r
305 In its check packet callback abort the opertions.\r
306\r
307 @param This The MTFTP protocol instance\r
308 @param OverrideData The MTFTP override data\r
309 @param Filename The file to get information\r
310 @param ModeStr The mode to use\r
311 @param OptionCount The number of options to append\r
312 @param OptionList The options to append\r
313 @param PacketLength The variable to receive the packet length\r
314 @param Packet The variable to receive the packet.\r
315\r
316 @retval EFI_INVALID_PARAMETER The parameter is invaid\r
317 @retval EFI_SUCCESS The information is got\r
318 @retval Others Failed to get the information.\r
319\r
320**/\r
772db4bb 321EFI_STATUS\r
322EFIAPI\r
323EfiMtftp4GetInfo (\r
324 IN EFI_MTFTP4_PROTOCOL *This,\r
325 IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData, OPTIONAL\r
326 IN UINT8 *Filename,\r
327 IN UINT8 *ModeStr, OPTIONAL\r
328 IN UINT8 OptionCount,\r
329 IN EFI_MTFTP4_OPTION *OptionList,\r
330 OUT UINT32 *PacketLength,\r
331 OUT EFI_MTFTP4_PACKET **Packet OPTIONAL\r
332 )\r
333{\r
334 EFI_MTFTP4_TOKEN Token;\r
61066b8d 335 MTFTP4_PROTOCOL *Instance;\r
336 MTFTP4_GETINFO_STATE *State;\r
772db4bb 337 EFI_STATUS Status;\r
338\r
339 if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||\r
340 (OptionCount && (OptionList == NULL))) {\r
341 return EFI_INVALID_PARAMETER;\r
342 }\r
343\r
344 if (Packet != NULL) {\r
345 *Packet = NULL;\r
346 }\r
347\r
348 *PacketLength = 0;\r
61066b8d 349 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
350 State = &Instance->GetInfoState;\r
351 State->Packet = Packet;\r
352 State->PacketLen = PacketLength;\r
353 State->Status = EFI_SUCCESS;\r
772db4bb 354\r
355 //\r
356 // Fill in the Token to issue an synchronous ReadFile operation\r
357 //\r
358 Token.Status = EFI_SUCCESS;\r
359 Token.Event = NULL;\r
360 Token.OverrideData = OverrideData;\r
361 Token.Filename = Filename;\r
362 Token.ModeStr = ModeStr;\r
363 Token.OptionCount = OptionCount;\r
364 Token.OptionList = OptionList;\r
365 Token.BufferSize = 0;\r
366 Token.Buffer = NULL;\r
772db4bb 367 Token.CheckPacket = Mtftp4GetInfoCheckPacket;\r
368 Token.TimeoutCallback = NULL;\r
369 Token.PacketNeeded = NULL;\r
370\r
371 Status = EfiMtftp4ReadFile (This, &Token);\r
372\r
373 if (EFI_ABORTED == Status) {\r
61066b8d 374 return State->Status;\r
772db4bb 375 }\r
376\r
377 return Status;\r
378}\r
379\r
380\r
381/**\r
382 Parse the packet into an array of options. The OptionList is allocated\r
383 by this function, and caller should free it when used.\r
384\r
385 @param This The MTFTP protocol instance\r
386 @param PacketLen The length of the packet\r
387 @param Packet The packet to parse\r
388 @param OptionCount The size of the OptionList array allocated.\r
389 @param OptionList The allocated option array to save the option\r
390 addresses.\r
391\r
392 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
393 @retval EFI_NOT_FOUND There is no valid option in the packet\r
394 @retval EFI_SUCCESS The packet is parsed.\r
395\r
396**/\r
772db4bb 397EFI_STATUS\r
398EFIAPI\r
399EfiMtftp4ParseOptions (\r
400 IN EFI_MTFTP4_PROTOCOL *This,\r
401 IN UINT32 PacketLen,\r
402 IN EFI_MTFTP4_PACKET *Packet,\r
403 IN OUT UINT32 *OptionCount,\r
404 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL\r
405 )\r
406{\r
407 EFI_STATUS Status;\r
408\r
409 if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||\r
410 (Packet == NULL) || (OptionCount == NULL)) {\r
411\r
412 return EFI_INVALID_PARAMETER;\r
413 }\r
414\r
415 Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);\r
416\r
417 if (EFI_ERROR (Status)) {\r
418 return Status;\r
419 }\r
420\r
421 if (*OptionCount == 0) {\r
422 return EFI_NOT_FOUND;\r
423 }\r
424\r
425 return EFI_SUCCESS;\r
426}\r
427\r
428\r
429/**\r
430 Check whether the override data is valid. It will first\r
431 validate whether the server is a valid unicast. If a gateway\r
432 is provided in the Override, it also check that it is a\r
433 unicast on the connected network.\r
434\r
435 @param Instance The MTFTP instance\r
436 @param Override The override data to validate.\r
437\r
438 @return TRUE if the override data is valid, otherwise FALSE.\r
439\r
440**/\r
772db4bb 441BOOLEAN\r
442Mtftp4OverrideValid (\r
443 IN MTFTP4_PROTOCOL *Instance,\r
444 IN EFI_MTFTP4_OVERRIDE_DATA *Override\r
445 )\r
446{\r
447 EFI_MTFTP4_CONFIG_DATA *Config;\r
448 IP4_ADDR Ip;\r
449 IP4_ADDR Netmask;\r
450 IP4_ADDR Gateway;\r
451\r
e48e37fc 452 CopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));\r
772db4bb 453 if (!Ip4IsUnicast (NTOHL (Ip), 0)) {\r
454 return FALSE;\r
455 }\r
456\r
457 Config = &Instance->Config;\r
458\r
e48e37fc 459 CopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
772db4bb 460 Gateway = NTOHL (Gateway);\r
461\r
462 if (!Config->UseDefaultSetting && (Gateway != 0)) {\r
e48e37fc 463 CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
464 CopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));\r
772db4bb 465\r
466 Netmask = NTOHL (Netmask);\r
467 Ip = NTOHL (Ip);\r
468\r
469 if (!Ip4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {\r
470 return FALSE;\r
471 }\r
472 }\r
473\r
474 return TRUE;\r
475}\r
476\r
477\r
478/**\r
479 Poll the UDP to get the IP4 default address, which may be retrieved\r
480 by DHCP. The default time out value is 5 seconds. If IP has retrieved\r
481 the default address, the UDP is reconfigured.\r
482\r
483 @param Instance The Mtftp instance\r
484 @param UdpPort The UDP port to poll\r
485 @param UdpCfgData The UDP configure data to reconfigure the UDP\r
486 port.\r
487\r
488 @return TRUE if the default address is retrieved and UDP is reconfigured.\r
489 @return Otherwise FALSE.\r
490\r
491**/\r
492BOOLEAN\r
493Mtftp4GetMapping (\r
494 IN MTFTP4_PROTOCOL *Instance,\r
495 IN UDP_IO_PORT *UdpPort,\r
496 IN EFI_UDP4_CONFIG_DATA *UdpCfgData\r
497 )\r
498{\r
499 MTFTP4_SERVICE *Service;\r
500 EFI_IP4_MODE_DATA Ip4Mode;\r
501 EFI_UDP4_PROTOCOL *Udp;\r
502 EFI_STATUS Status;\r
503\r
504 ASSERT (Instance->Config.UseDefaultSetting);\r
505\r
506 Service = Instance->Service;\r
507 Udp = UdpPort->Udp;\r
508\r
509 Status = gBS->SetTimer (\r
510 Service->TimerToGetMap,\r
511 TimerRelative,\r
512 MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND\r
513 );\r
514 if (EFI_ERROR (Status)) {\r
515 return FALSE;\r
516 }\r
517\r
518 while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
519 Udp->Poll (Udp);\r
520\r
521 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
522 Ip4Mode.IsConfigured) {\r
523\r
524 Udp->Configure (Udp, NULL);\r
525 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
526 }\r
527 }\r
528\r
529 return FALSE;\r
530}\r
531\r
532\r
533/**\r
534 Configure the UDP port for unicast receiving.\r
535\r
536 @param UdpIo The UDP port\r
537 @param Instance The MTFTP session\r
538\r
539 @retval EFI_SUCCESS The UDP port is successfully configured for the\r
540 session to unicast receive.\r
541\r
542**/\r
772db4bb 543EFI_STATUS\r
544Mtftp4ConfigUnicastPort (\r
545 IN UDP_IO_PORT *UdpIo,\r
546 IN MTFTP4_PROTOCOL *Instance\r
547 )\r
548{\r
549 EFI_MTFTP4_CONFIG_DATA *Config;\r
550 EFI_UDP4_CONFIG_DATA UdpConfig;\r
551 EFI_STATUS Status;\r
552 IP4_ADDR Ip;\r
553\r
554 Config = &Instance->Config;\r
555\r
556 UdpConfig.AcceptBroadcast = FALSE;\r
557 UdpConfig.AcceptPromiscuous = FALSE;\r
558 UdpConfig.AcceptAnyPort = FALSE;\r
559 UdpConfig.AllowDuplicatePort = FALSE;\r
560 UdpConfig.TypeOfService = 0;\r
561 UdpConfig.TimeToLive = 64;\r
562 UdpConfig.DoNotFragment = FALSE;\r
563 UdpConfig.ReceiveTimeout = 0;\r
564 UdpConfig.TransmitTimeout = 0;\r
565 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;\r
566 UdpConfig.StationAddress = Config->StationIp;\r
567 UdpConfig.SubnetMask = Config->SubnetMask;\r
568 UdpConfig.StationPort = 0;\r
569 UdpConfig.RemotePort = 0;\r
570\r
571 Ip = HTONL (Instance->ServerIp);\r
e48e37fc 572 CopyMem (&UdpConfig.RemoteAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 573\r
574 Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfig);\r
575\r
576 if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {\r
577 return EFI_SUCCESS;\r
578 }\r
579\r
c4a62a12 580 if (!Config->UseDefaultSetting && !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {\r
581 //\r
582 // The station IP address is manually configured and the Gateway IP is not 0.\r
583 // Add the default route for this UDP instance.\r
584 //\r
585 Status = UdpIo->Udp->Routes (UdpIo->Udp, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &Config->GatewayIp);\r
586 if (EFI_ERROR (Status)) {\r
587 UdpIo->Udp->Configure (UdpIo->Udp, NULL);\r
588 }\r
589 }\r
772db4bb 590 return Status;\r
591}\r
592\r
593\r
594/**\r
595 Start the MTFTP session to do the operation, such as read file,\r
596 write file, and read directory.\r
597\r
598 @param This The MTFTP session\r
599 @param Token The token than encapsues the user's request.\r
600 @param Operation The operation to do\r
601\r
602 @retval EFI_INVALID_PARAMETER Some of the parameters are invalid.\r
603 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.\r
604 @retval EFI_ALREADY_STARTED There is pending operation for the session.\r
605 @retval EFI_SUCCESS The operation is successfully started.\r
606\r
607**/\r
772db4bb 608EFI_STATUS\r
609Mtftp4Start (\r
610 IN EFI_MTFTP4_PROTOCOL *This,\r
611 IN EFI_MTFTP4_TOKEN *Token,\r
612 IN UINT16 Operation\r
613 )\r
614{\r
615 MTFTP4_PROTOCOL *Instance;\r
616 EFI_MTFTP4_OVERRIDE_DATA *Override;\r
617 EFI_MTFTP4_CONFIG_DATA *Config;\r
618 EFI_TPL OldTpl;\r
619 EFI_STATUS Status;\r
620\r
621 //\r
622 // Validate the parameters\r
623 //\r
624 if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||\r
625 ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {\r
626 return EFI_INVALID_PARAMETER;\r
627 }\r
628\r
629 //\r
630 // User must provide at least one method to collect the data for download.\r
631 //\r
632 if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&\r
633 ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {\r
634 return EFI_INVALID_PARAMETER;\r
635 }\r
636\r
637 //\r
638 // User must provide at least one method to provide the data for upload.\r
639 //\r
640 if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&\r
641 ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {\r
642 return EFI_INVALID_PARAMETER;\r
643 }\r
644\r
645 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
646\r
647 Status = EFI_SUCCESS;\r
e48e37fc 648 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 649\r
650 if (Instance->State != MTFTP4_STATE_CONFIGED) {\r
651 Status = EFI_NOT_STARTED;\r
652 }\r
653\r
654 if (Instance->Operation != 0) {\r
655 Status = EFI_ACCESS_DENIED;\r
656 }\r
657\r
658 if (EFI_ERROR (Status)) {\r
e48e37fc 659 gBS->RestoreTPL (OldTpl);\r
772db4bb 660 return Status;\r
661 }\r
662\r
663 //\r
664 // Set the Operation now to prevent the application start other\r
665 // operations.\r
666 //\r
667 Instance->Operation = Operation;\r
668 Override = Token->OverrideData;\r
669\r
670 if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {\r
671 Status = EFI_INVALID_PARAMETER;\r
672 goto ON_ERROR;\r
673 }\r
674\r
675 if (Token->OptionCount != 0) {\r
676 Status = Mtftp4ParseOption (\r
677 Token->OptionList,\r
678 Token->OptionCount,\r
679 TRUE,\r
680 &Instance->RequestOption\r
681 );\r
682\r
683 if (EFI_ERROR (Status)) {\r
684 goto ON_ERROR;\r
685 }\r
686 }\r
687\r
688 //\r
689 // Set the operation parameters from the configuration or override data.\r
690 //\r
691 Config = &Instance->Config;\r
692 Instance->Token = Token;\r
693 Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;\r
694\r
e48e37fc 695 CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));\r
772db4bb 696 Instance->ServerIp = NTOHL (Instance->ServerIp);\r
697\r
698 Instance->ListeningPort = Config->InitialServerPort;\r
699 Instance->ConnectedPort = 0;\r
700\r
e48e37fc 701 CopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));\r
772db4bb 702 Instance->Gateway = NTOHL (Instance->Gateway);\r
703\r
704 Instance->MaxRetry = Config->TryCount;\r
705 Instance->Timeout = Config->TimeoutValue;\r
706 Instance->Master = TRUE;\r
707\r
708 if (Override != NULL) {\r
e48e37fc 709 CopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));\r
710 CopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
772db4bb 711\r
712 Instance->ServerIp = NTOHL (Instance->ServerIp);\r
713 Instance->Gateway = NTOHL (Instance->Gateway);\r
714\r
715 Instance->ListeningPort = Override->ServerPort;\r
716 Instance->MaxRetry = Override->TryCount;\r
717 Instance->Timeout = Override->TimeoutValue;\r
718 }\r
719\r
720 if (Instance->ListeningPort == 0) {\r
721 Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;\r
722 }\r
723\r
724 if (Instance->MaxRetry == 0) {\r
725 Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;\r
726 }\r
727\r
728 if (Instance->Timeout == 0) {\r
729 Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;\r
730 }\r
731\r
732 //\r
733 // Config the unicast UDP child to send initial request\r
734 //\r
735 Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);\r
736\r
737 if (EFI_ERROR (Status)) {\r
738 goto ON_ERROR;\r
739 }\r
740\r
174f03d2 741 //\r
742 // Set initial status.\r
743 //\r
744 Token->Status = EFI_NOT_READY;\r
745\r
772db4bb 746 //\r
747 // Build and send an initial requests\r
748 //\r
749 if (Operation == EFI_MTFTP4_OPCODE_WRQ) {\r
750 Status = Mtftp4WrqStart (Instance, Operation);\r
751 } else {\r
752 Status = Mtftp4RrqStart (Instance, Operation);\r
753 }\r
754\r
e48e37fc 755 gBS->RestoreTPL (OldTpl);\r
772db4bb 756\r
757 if (EFI_ERROR (Status)) {\r
758 goto ON_ERROR;\r
759 }\r
772db4bb 760\r
761 if (Token->Event != NULL) {\r
762 return EFI_SUCCESS;\r
763 }\r
764\r
174f03d2 765 //\r
766 // Return immediately for asynchronous operation or poll the\r
767 // instance for synchronous operation.\r
768 //\r
772db4bb 769 while (Token->Status == EFI_NOT_READY) {\r
770 This->Poll (This);\r
771 }\r
772\r
773 return Token->Status;\r
774\r
775ON_ERROR:\r
776 Mtftp4CleanOperation (Instance, Status);\r
e48e37fc 777 gBS->RestoreTPL (OldTpl);\r
772db4bb 778\r
779 return Status;\r
780}\r
781\r
782\r
783/**\r
784 Read a file from the server.\r
785\r
786 @param This The Mtftp protocol instance.\r
787 @param Token The user's request wrap token.\r
788\r
789 @retval EFI_SUCCESS The ReadFile has finished, the file has been\r
790 downloaded if it is synchronous operation,\r
791 otherwise it has been initated.\r
792 @retval Others Some error happened.\r
793\r
794**/\r
772db4bb 795EFI_STATUS\r
796EFIAPI\r
797EfiMtftp4ReadFile (\r
798 IN EFI_MTFTP4_PROTOCOL *This,\r
799 IN EFI_MTFTP4_TOKEN *Token\r
800 )\r
801{\r
802 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);\r
803}\r
804\r
805\r
806/**\r
807 Upload a file to the server.\r
808\r
809 @param This The MTFTP protocol session\r
810 @param Token The user's request wrap token.\r
811\r
812 @retval EFI_SUCCESS The WriteFile has finished, the file has been\r
813 uploaded if it is synchronous operation, otherwise\r
814 it has been initated.\r
815 @retval Others Some error happened.\r
816\r
817**/\r
772db4bb 818EFI_STATUS\r
819EFIAPI\r
820EfiMtftp4WriteFile (\r
821 IN EFI_MTFTP4_PROTOCOL *This,\r
822 IN EFI_MTFTP4_TOKEN *Token\r
823 )\r
824{\r
825 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);\r
826}\r
827\r
828\r
829/**\r
830 Read a directory from the server. The only difference\r
831 between ReadFile and ReadDirectory is the opcode used.\r
832\r
833 @param This The MTFTP protocol session\r
834 @param Token The user's request wrap token.\r
835\r
836 @retval EFI_SUCCESS The ReadDirectory has finished, the directory has\r
837 been downloaded as a file if it is synchronous\r
838 operation, otherwise it has been initated.\r
839 @retval Others Some error happened.\r
840\r
841**/\r
772db4bb 842EFI_STATUS\r
843EFIAPI\r
844EfiMtftp4ReadDirectory (\r
845 IN EFI_MTFTP4_PROTOCOL *This,\r
846 IN EFI_MTFTP4_TOKEN *Token\r
847 )\r
848{\r
849 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);\r
850}\r
851\r
852\r
853/**\r
854 Poll the network stack to accelerate the packet process.\r
855\r
856 @param This The MTFTP protocol instance.\r
857\r
858 @retval EFI_INVALID_PARAMETER This is NULL.\r
859 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.\r
860 @retval EFI_DEVICE_ERROR The MTFTP session has been destoried.\r
861\r
862**/\r
772db4bb 863EFI_STATUS\r
864EFIAPI\r
865EfiMtftp4Poll (\r
866 IN EFI_MTFTP4_PROTOCOL *This\r
867 )\r
868{\r
869 MTFTP4_PROTOCOL *Instance;\r
870 EFI_UDP4_PROTOCOL *Udp;\r
871\r
872 if (This == NULL) {\r
873 return EFI_INVALID_PARAMETER;\r
874 }\r
875\r
876 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
877\r
878 if (Instance->State == MTFTP4_STATE_UNCONFIGED) {\r
879 return EFI_NOT_STARTED;\r
880 } else if (Instance->State == MTFTP4_STATE_DESTORY) {\r
881 return EFI_DEVICE_ERROR;\r
882 }\r
883\r
884 Udp = Instance->UnicastPort->Udp;\r
885 return Udp->Poll (Udp);\r
886}\r
887\r
888EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {\r
889 EfiMtftp4GetModeData,\r
890 EfiMtftp4Configure,\r
891 EfiMtftp4GetInfo,\r
892 EfiMtftp4ParseOptions,\r
893 EfiMtftp4ReadFile,\r
894 EfiMtftp4WriteFile,\r
895 EfiMtftp4ReadDirectory,\r
896 EfiMtftp4Poll\r
897};\r