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