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