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