1. Enable Mtftp4Dxe in MdeModulePkg.dsc
[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
a5867703 263 MTFTP4_PROTOCOL *Instance;\r
772db4bb 264 MTFTP4_GETINFO_STATE *State;\r
265 EFI_STATUS Status;\r
266 UINT16 OpCode;\r
267\r
a5867703 268 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
269 State = &Instance->GetInfoState;\r
270 OpCode = NTOHS (Packet->OpCode);\r
772db4bb 271\r
272 //\r
273 // Set the GetInfo's return status according to the OpCode.\r
274 //\r
275 switch (OpCode) {\r
276 case EFI_MTFTP4_OPCODE_ERROR:\r
277 State->Status = EFI_TFTP_ERROR;\r
278 break;\r
279\r
280 case EFI_MTFTP4_OPCODE_OACK:\r
281 State->Status = EFI_SUCCESS;\r
282 break;\r
283\r
284 default:\r
285 State->Status = EFI_PROTOCOL_ERROR;\r
286 }\r
287\r
288 //\r
289 // Allocate buffer then copy the packet over. Use gBS->AllocatePool\r
290 // in case NetAllocatePool will implements something tricky.\r
291 //\r
292 Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);\r
293\r
294 if (EFI_ERROR (Status)) {\r
295 State->Status = EFI_OUT_OF_RESOURCES;\r
296 return EFI_ABORTED;\r
297 }\r
298\r
299 *(State->PacketLen) = PacketLen;\r
300 NetCopyMem (*(State->Packet), Packet, PacketLen);\r
301\r
302 return EFI_ABORTED;\r
303}\r
304\r
305\r
306/**\r
307 Get the information of the download from the server. It is implemented\r
308 with EfiMtftp4ReadFile: build a token, then pass it to EfiMtftp4ReadFile.\r
309 In its check packet callback abort the opertions.\r
310\r
311 @param This The MTFTP protocol instance\r
312 @param OverrideData The MTFTP override data\r
313 @param Filename The file to get information\r
314 @param ModeStr The mode to use\r
315 @param OptionCount The number of options to append\r
316 @param OptionList The options to append\r
317 @param PacketLength The variable to receive the packet length\r
318 @param Packet The variable to receive the packet.\r
319\r
320 @retval EFI_INVALID_PARAMETER The parameter is invaid\r
321 @retval EFI_SUCCESS The information is got\r
322 @retval Others Failed to get the information.\r
323\r
324**/\r
325STATIC\r
326EFI_STATUS\r
327EFIAPI\r
328EfiMtftp4GetInfo (\r
329 IN EFI_MTFTP4_PROTOCOL *This,\r
330 IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData, OPTIONAL\r
331 IN UINT8 *Filename,\r
332 IN UINT8 *ModeStr, OPTIONAL\r
333 IN UINT8 OptionCount,\r
334 IN EFI_MTFTP4_OPTION *OptionList,\r
335 OUT UINT32 *PacketLength,\r
336 OUT EFI_MTFTP4_PACKET **Packet OPTIONAL\r
337 )\r
338{\r
339 EFI_MTFTP4_TOKEN Token;\r
a5867703 340 MTFTP4_PROTOCOL *Instance;\r
341 MTFTP4_GETINFO_STATE *State;\r
772db4bb 342 EFI_STATUS Status;\r
343\r
344 if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||\r
345 (OptionCount && (OptionList == NULL))) {\r
346 return EFI_INVALID_PARAMETER;\r
347 }\r
348\r
349 if (Packet != NULL) {\r
350 *Packet = NULL;\r
351 }\r
352\r
353 *PacketLength = 0;\r
a5867703 354 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
355 State = &Instance->GetInfoState;\r
356 State->Packet = Packet;\r
357 State->PacketLen = PacketLength;\r
358 State->Status = EFI_SUCCESS;\r
772db4bb 359\r
360 //\r
361 // Fill in the Token to issue an synchronous ReadFile operation\r
362 //\r
363 Token.Status = EFI_SUCCESS;\r
364 Token.Event = NULL;\r
365 Token.OverrideData = OverrideData;\r
366 Token.Filename = Filename;\r
367 Token.ModeStr = ModeStr;\r
368 Token.OptionCount = OptionCount;\r
369 Token.OptionList = OptionList;\r
370 Token.BufferSize = 0;\r
371 Token.Buffer = NULL;\r
772db4bb 372 Token.CheckPacket = Mtftp4GetInfoCheckPacket;\r
373 Token.TimeoutCallback = NULL;\r
374 Token.PacketNeeded = NULL;\r
375\r
376 Status = EfiMtftp4ReadFile (This, &Token);\r
377\r
378 if (EFI_ABORTED == Status) {\r
a5867703 379 return State->Status;\r
772db4bb 380 }\r
381\r
382 return Status;\r
383}\r
384\r
385\r
386/**\r
387 Parse the packet into an array of options. The OptionList is allocated\r
388 by this function, and caller should free it when used.\r
389\r
390 @param This The MTFTP protocol instance\r
391 @param PacketLen The length of the packet\r
392 @param Packet The packet to parse\r
393 @param OptionCount The size of the OptionList array allocated.\r
394 @param OptionList The allocated option array to save the option\r
395 addresses.\r
396\r
397 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
398 @retval EFI_NOT_FOUND There is no valid option in the packet\r
399 @retval EFI_SUCCESS The packet is parsed.\r
400\r
401**/\r
402STATIC\r
403EFI_STATUS\r
404EFIAPI\r
405EfiMtftp4ParseOptions (\r
406 IN EFI_MTFTP4_PROTOCOL *This,\r
407 IN UINT32 PacketLen,\r
408 IN EFI_MTFTP4_PACKET *Packet,\r
409 IN OUT UINT32 *OptionCount,\r
410 OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL\r
411 )\r
412{\r
413 EFI_STATUS Status;\r
414\r
415 if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||\r
416 (Packet == NULL) || (OptionCount == NULL)) {\r
417\r
418 return EFI_INVALID_PARAMETER;\r
419 }\r
420\r
421 Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);\r
422\r
423 if (EFI_ERROR (Status)) {\r
424 return Status;\r
425 }\r
426\r
427 if (*OptionCount == 0) {\r
428 return EFI_NOT_FOUND;\r
429 }\r
430\r
431 return EFI_SUCCESS;\r
432}\r
433\r
434\r
435/**\r
436 Check whether the override data is valid. It will first\r
437 validate whether the server is a valid unicast. If a gateway\r
438 is provided in the Override, it also check that it is a\r
439 unicast on the connected network.\r
440\r
441 @param Instance The MTFTP instance\r
442 @param Override The override data to validate.\r
443\r
444 @return TRUE if the override data is valid, otherwise FALSE.\r
445\r
446**/\r
447STATIC\r
448BOOLEAN\r
449Mtftp4OverrideValid (\r
450 IN MTFTP4_PROTOCOL *Instance,\r
451 IN EFI_MTFTP4_OVERRIDE_DATA *Override\r
452 )\r
453{\r
454 EFI_MTFTP4_CONFIG_DATA *Config;\r
455 IP4_ADDR Ip;\r
456 IP4_ADDR Netmask;\r
457 IP4_ADDR Gateway;\r
458\r
459 NetCopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));\r
460 if (!Ip4IsUnicast (NTOHL (Ip), 0)) {\r
461 return FALSE;\r
462 }\r
463\r
464 Config = &Instance->Config;\r
465\r
466 NetCopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
467 Gateway = NTOHL (Gateway);\r
468\r
469 if (!Config->UseDefaultSetting && (Gateway != 0)) {\r
470 NetCopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
471 NetCopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));\r
472\r
473 Netmask = NTOHL (Netmask);\r
474 Ip = NTOHL (Ip);\r
475\r
476 if (!Ip4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {\r
477 return FALSE;\r
478 }\r
479 }\r
480\r
481 return TRUE;\r
482}\r
483\r
484\r
485/**\r
486 Poll the UDP to get the IP4 default address, which may be retrieved\r
487 by DHCP. The default time out value is 5 seconds. If IP has retrieved\r
488 the default address, the UDP is reconfigured.\r
489\r
490 @param Instance The Mtftp instance\r
491 @param UdpPort The UDP port to poll\r
492 @param UdpCfgData The UDP configure data to reconfigure the UDP\r
493 port.\r
494\r
495 @return TRUE if the default address is retrieved and UDP is reconfigured.\r
496 @return Otherwise FALSE.\r
497\r
498**/\r
499BOOLEAN\r
500Mtftp4GetMapping (\r
501 IN MTFTP4_PROTOCOL *Instance,\r
502 IN UDP_IO_PORT *UdpPort,\r
503 IN EFI_UDP4_CONFIG_DATA *UdpCfgData\r
504 )\r
505{\r
506 MTFTP4_SERVICE *Service;\r
507 EFI_IP4_MODE_DATA Ip4Mode;\r
508 EFI_UDP4_PROTOCOL *Udp;\r
509 EFI_STATUS Status;\r
510\r
511 ASSERT (Instance->Config.UseDefaultSetting);\r
512\r
513 Service = Instance->Service;\r
514 Udp = UdpPort->Udp;\r
515\r
516 Status = gBS->SetTimer (\r
517 Service->TimerToGetMap,\r
518 TimerRelative,\r
519 MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND\r
520 );\r
521 if (EFI_ERROR (Status)) {\r
522 return FALSE;\r
523 }\r
524\r
525 while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
526 Udp->Poll (Udp);\r
527\r
528 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
529 Ip4Mode.IsConfigured) {\r
530\r
531 Udp->Configure (Udp, NULL);\r
532 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);\r
533 }\r
534 }\r
535\r
536 return FALSE;\r
537}\r
538\r
539\r
540/**\r
541 Configure the UDP port for unicast receiving.\r
542\r
543 @param UdpIo The UDP port\r
544 @param Instance The MTFTP session\r
545\r
546 @retval EFI_SUCCESS The UDP port is successfully configured for the\r
547 session to unicast receive.\r
548\r
549**/\r
550STATIC\r
551EFI_STATUS\r
552Mtftp4ConfigUnicastPort (\r
553 IN UDP_IO_PORT *UdpIo,\r
554 IN MTFTP4_PROTOCOL *Instance\r
555 )\r
556{\r
557 EFI_MTFTP4_CONFIG_DATA *Config;\r
558 EFI_UDP4_CONFIG_DATA UdpConfig;\r
559 EFI_STATUS Status;\r
560 IP4_ADDR Ip;\r
561\r
562 Config = &Instance->Config;\r
563\r
564 UdpConfig.AcceptBroadcast = FALSE;\r
565 UdpConfig.AcceptPromiscuous = FALSE;\r
566 UdpConfig.AcceptAnyPort = FALSE;\r
567 UdpConfig.AllowDuplicatePort = FALSE;\r
568 UdpConfig.TypeOfService = 0;\r
569 UdpConfig.TimeToLive = 64;\r
570 UdpConfig.DoNotFragment = FALSE;\r
571 UdpConfig.ReceiveTimeout = 0;\r
572 UdpConfig.TransmitTimeout = 0;\r
573 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;\r
574 UdpConfig.StationAddress = Config->StationIp;\r
575 UdpConfig.SubnetMask = Config->SubnetMask;\r
576 UdpConfig.StationPort = 0;\r
577 UdpConfig.RemotePort = 0;\r
578\r
579 Ip = HTONL (Instance->ServerIp);\r
580 NetCopyMem (&UdpConfig.RemoteAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
581\r
582 Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfig);\r
583\r
584 if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {\r
585 return EFI_SUCCESS;\r
586 }\r
587\r
588 return Status;\r
589}\r
590\r
591\r
592/**\r
593 Start the MTFTP session to do the operation, such as read file,\r
594 write file, and read directory.\r
595\r
596 @param This The MTFTP session\r
597 @param Token The token than encapsues the user's request.\r
598 @param Operation The operation to do\r
599\r
600 @retval EFI_INVALID_PARAMETER Some of the parameters are invalid.\r
601 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.\r
602 @retval EFI_ALREADY_STARTED There is pending operation for the session.\r
603 @retval EFI_SUCCESS The operation is successfully started.\r
604\r
605**/\r
606STATIC\r
607EFI_STATUS\r
608Mtftp4Start (\r
609 IN EFI_MTFTP4_PROTOCOL *This,\r
610 IN EFI_MTFTP4_TOKEN *Token,\r
611 IN UINT16 Operation\r
612 )\r
613{\r
614 MTFTP4_PROTOCOL *Instance;\r
615 EFI_MTFTP4_OVERRIDE_DATA *Override;\r
616 EFI_MTFTP4_CONFIG_DATA *Config;\r
617 EFI_TPL OldTpl;\r
618 EFI_STATUS Status;\r
619\r
620 //\r
621 // Validate the parameters\r
622 //\r
623 if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||\r
624 ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {\r
625 return EFI_INVALID_PARAMETER;\r
626 }\r
627\r
628 //\r
629 // User must provide at least one method to collect the data for download.\r
630 //\r
631 if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&\r
632 ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {\r
633 return EFI_INVALID_PARAMETER;\r
634 }\r
635\r
636 //\r
637 // User must provide at least one method to provide the data for upload.\r
638 //\r
639 if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&\r
640 ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {\r
641 return EFI_INVALID_PARAMETER;\r
642 }\r
643\r
644 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
645\r
646 Status = EFI_SUCCESS;\r
647 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
648\r
649 if (Instance->State != MTFTP4_STATE_CONFIGED) {\r
650 Status = EFI_NOT_STARTED;\r
651 }\r
652\r
653 if (Instance->Operation != 0) {\r
654 Status = EFI_ACCESS_DENIED;\r
655 }\r
656\r
657 if (EFI_ERROR (Status)) {\r
658 NET_RESTORE_TPL (OldTpl);\r
659 return Status;\r
660 }\r
661\r
662 //\r
663 // Set the Operation now to prevent the application start other\r
664 // operations.\r
665 //\r
666 Instance->Operation = Operation;\r
667 Override = Token->OverrideData;\r
668\r
669 if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {\r
670 Status = EFI_INVALID_PARAMETER;\r
671 goto ON_ERROR;\r
672 }\r
673\r
674 if (Token->OptionCount != 0) {\r
675 Status = Mtftp4ParseOption (\r
676 Token->OptionList,\r
677 Token->OptionCount,\r
678 TRUE,\r
679 &Instance->RequestOption\r
680 );\r
681\r
682 if (EFI_ERROR (Status)) {\r
683 goto ON_ERROR;\r
684 }\r
685 }\r
686\r
687 //\r
688 // Set the operation parameters from the configuration or override data.\r
689 //\r
690 Config = &Instance->Config;\r
691 Instance->Token = Token;\r
692 Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;\r
693\r
694 NetCopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));\r
695 Instance->ServerIp = NTOHL (Instance->ServerIp);\r
696\r
697 Instance->ListeningPort = Config->InitialServerPort;\r
698 Instance->ConnectedPort = 0;\r
699\r
700 NetCopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));\r
701 Instance->Gateway = NTOHL (Instance->Gateway);\r
702\r
703 Instance->MaxRetry = Config->TryCount;\r
704 Instance->Timeout = Config->TimeoutValue;\r
705 Instance->Master = TRUE;\r
706\r
707 if (Override != NULL) {\r
708 NetCopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));\r
709 NetCopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
710\r
711 Instance->ServerIp = NTOHL (Instance->ServerIp);\r
712 Instance->Gateway = NTOHL (Instance->Gateway);\r
713\r
714 Instance->ListeningPort = Override->ServerPort;\r
715 Instance->MaxRetry = Override->TryCount;\r
716 Instance->Timeout = Override->TimeoutValue;\r
717 }\r
718\r
719 if (Instance->ListeningPort == 0) {\r
720 Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;\r
721 }\r
722\r
723 if (Instance->MaxRetry == 0) {\r
724 Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;\r
725 }\r
726\r
727 if (Instance->Timeout == 0) {\r
728 Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;\r
729 }\r
730\r
731 //\r
732 // Config the unicast UDP child to send initial request\r
733 //\r
734 Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);\r
735\r
736 if (EFI_ERROR (Status)) {\r
737 goto ON_ERROR;\r
738 }\r
739\r
740 //\r
741 // Build and send an initial requests\r
742 //\r
743 if (Operation == EFI_MTFTP4_OPCODE_WRQ) {\r
744 Status = Mtftp4WrqStart (Instance, Operation);\r
745 } else {\r
746 Status = Mtftp4RrqStart (Instance, Operation);\r
747 }\r
748\r
749 NET_RESTORE_TPL (OldTpl);\r
750\r
751 if (EFI_ERROR (Status)) {\r
752 goto ON_ERROR;\r
753 }\r
754 //\r
755 // Return immediately for asynchronous operation or poll the\r
756 // instance for synchronous operation.\r
757 //\r
758 Token->Status = EFI_NOT_READY;\r
759\r
760 if (Token->Event != NULL) {\r
761 return EFI_SUCCESS;\r
762 }\r
763\r
764 while (Token->Status == EFI_NOT_READY) {\r
765 This->Poll (This);\r
766 }\r
767\r
768 return Token->Status;\r
769\r
770ON_ERROR:\r
771 Mtftp4CleanOperation (Instance, Status);\r
772 NET_RESTORE_TPL (OldTpl);\r
773\r
774 return Status;\r
775}\r
776\r
777\r
778/**\r
779 Read a file from the server.\r
780\r
781 @param This The Mtftp protocol instance.\r
782 @param Token The user's request wrap token.\r
783\r
784 @retval EFI_SUCCESS The ReadFile has finished, the file has been\r
785 downloaded if it is synchronous operation,\r
786 otherwise it has been initated.\r
787 @retval Others Some error happened.\r
788\r
789**/\r
790STATIC\r
791EFI_STATUS\r
792EFIAPI\r
793EfiMtftp4ReadFile (\r
794 IN EFI_MTFTP4_PROTOCOL *This,\r
795 IN EFI_MTFTP4_TOKEN *Token\r
796 )\r
797{\r
798 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);\r
799}\r
800\r
801\r
802/**\r
803 Upload a file to the server.\r
804\r
805 @param This The MTFTP protocol session\r
806 @param Token The user's request wrap token.\r
807\r
808 @retval EFI_SUCCESS The WriteFile has finished, the file has been\r
809 uploaded if it is synchronous operation, otherwise\r
810 it has been initated.\r
811 @retval Others Some error happened.\r
812\r
813**/\r
814STATIC\r
815EFI_STATUS\r
816EFIAPI\r
817EfiMtftp4WriteFile (\r
818 IN EFI_MTFTP4_PROTOCOL *This,\r
819 IN EFI_MTFTP4_TOKEN *Token\r
820 )\r
821{\r
822 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);\r
823}\r
824\r
825\r
826/**\r
827 Read a directory from the server. The only difference\r
828 between ReadFile and ReadDirectory is the opcode used.\r
829\r
830 @param This The MTFTP protocol session\r
831 @param Token The user's request wrap token.\r
832\r
833 @retval EFI_SUCCESS The ReadDirectory has finished, the directory has\r
834 been downloaded as a file if it is synchronous\r
835 operation, otherwise it has been initated.\r
836 @retval Others Some error happened.\r
837\r
838**/\r
839STATIC\r
840EFI_STATUS\r
841EFIAPI\r
842EfiMtftp4ReadDirectory (\r
843 IN EFI_MTFTP4_PROTOCOL *This,\r
844 IN EFI_MTFTP4_TOKEN *Token\r
845 )\r
846{\r
847 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);\r
848}\r
849\r
850\r
851/**\r
852 Poll the network stack to accelerate the packet process.\r
853\r
854 @param This The MTFTP protocol instance.\r
855\r
856 @retval EFI_INVALID_PARAMETER This is NULL.\r
857 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.\r
858 @retval EFI_DEVICE_ERROR The MTFTP session has been destoried.\r
859\r
860**/\r
861STATIC\r
862EFI_STATUS\r
863EFIAPI\r
864EfiMtftp4Poll (\r
865 IN EFI_MTFTP4_PROTOCOL *This\r
866 )\r
867{\r
868 MTFTP4_PROTOCOL *Instance;\r
869 EFI_UDP4_PROTOCOL *Udp;\r
870\r
871 if (This == NULL) {\r
872 return EFI_INVALID_PARAMETER;\r
873 }\r
874\r
875 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
876\r
877 if (Instance->State == MTFTP4_STATE_UNCONFIGED) {\r
878 return EFI_NOT_STARTED;\r
879 } else if (Instance->State == MTFTP4_STATE_DESTORY) {\r
880 return EFI_DEVICE_ERROR;\r
881 }\r
882\r
883 Udp = Instance->UnicastPort->Udp;\r
884 return Udp->Poll (Udp);\r
885}\r
886\r
887EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {\r
888 EfiMtftp4GetModeData,\r
889 EfiMtftp4Configure,\r
890 EfiMtftp4GetInfo,\r
891 EfiMtftp4ParseOptions,\r
892 EfiMtftp4ReadFile,\r
893 EfiMtftp4WriteFile,\r
894 EfiMtftp4ReadDirectory,\r
895 EfiMtftp4Poll\r
896};\r