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