]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
remove member context from _EFI_MTFTP4_TOKEN structure.
[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 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 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 CopyMem(&Instance->Config, ConfigData, sizeof (*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_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 NetAllocatePool 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 NetCopyMem (*(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 NetCopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));
460 if (!Ip4IsUnicast (NTOHL (Ip), 0)) {
461 return FALSE;
462 }
463
464 Config = &Instance->Config;
465
466 NetCopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
467 Gateway = NTOHL (Gateway);
468
469 if (!Config->UseDefaultSetting && (Gateway != 0)) {
470 NetCopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));
471 NetCopyMem (&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 NetCopyMem (&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 return Status;
589 }
590
591
592 /**
593 Start the MTFTP session to do the operation, such as read file,
594 write file, and read directory.
595
596 @param This The MTFTP session
597 @param Token The token than encapsues the user's request.
598 @param Operation The operation to do
599
600 @retval EFI_INVALID_PARAMETER Some of the parameters are invalid.
601 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
602 @retval EFI_ALREADY_STARTED There is pending operation for the session.
603 @retval EFI_SUCCESS The operation is successfully started.
604
605 **/
606 STATIC
607 EFI_STATUS
608 Mtftp4Start (
609 IN EFI_MTFTP4_PROTOCOL *This,
610 IN EFI_MTFTP4_TOKEN *Token,
611 IN UINT16 Operation
612 )
613 {
614 MTFTP4_PROTOCOL *Instance;
615 EFI_MTFTP4_OVERRIDE_DATA *Override;
616 EFI_MTFTP4_CONFIG_DATA *Config;
617 EFI_TPL OldTpl;
618 EFI_STATUS Status;
619
620 //
621 // Validate the parameters
622 //
623 if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||
624 ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {
625 return EFI_INVALID_PARAMETER;
626 }
627
628 //
629 // User must provide at least one method to collect the data for download.
630 //
631 if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&
632 ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {
633 return EFI_INVALID_PARAMETER;
634 }
635
636 //
637 // User must provide at least one method to provide the data for upload.
638 //
639 if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&
640 ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {
641 return EFI_INVALID_PARAMETER;
642 }
643
644 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
645
646 Status = EFI_SUCCESS;
647 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
648
649 if (Instance->State != MTFTP4_STATE_CONFIGED) {
650 Status = EFI_NOT_STARTED;
651 }
652
653 if (Instance->Operation != 0) {
654 Status = EFI_ACCESS_DENIED;
655 }
656
657 if (EFI_ERROR (Status)) {
658 NET_RESTORE_TPL (OldTpl);
659 return Status;
660 }
661
662 //
663 // Set the Operation now to prevent the application start other
664 // operations.
665 //
666 Instance->Operation = Operation;
667 Override = Token->OverrideData;
668
669 if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {
670 Status = EFI_INVALID_PARAMETER;
671 goto ON_ERROR;
672 }
673
674 if (Token->OptionCount != 0) {
675 Status = Mtftp4ParseOption (
676 Token->OptionList,
677 Token->OptionCount,
678 TRUE,
679 &Instance->RequestOption
680 );
681
682 if (EFI_ERROR (Status)) {
683 goto ON_ERROR;
684 }
685 }
686
687 //
688 // Set the operation parameters from the configuration or override data.
689 //
690 Config = &Instance->Config;
691 Instance->Token = Token;
692 Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
693
694 NetCopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));
695 Instance->ServerIp = NTOHL (Instance->ServerIp);
696
697 Instance->ListeningPort = Config->InitialServerPort;
698 Instance->ConnectedPort = 0;
699
700 NetCopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));
701 Instance->Gateway = NTOHL (Instance->Gateway);
702
703 Instance->MaxRetry = Config->TryCount;
704 Instance->Timeout = Config->TimeoutValue;
705 Instance->Master = TRUE;
706
707 if (Override != NULL) {
708 NetCopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));
709 NetCopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
710
711 Instance->ServerIp = NTOHL (Instance->ServerIp);
712 Instance->Gateway = NTOHL (Instance->Gateway);
713
714 Instance->ListeningPort = Override->ServerPort;
715 Instance->MaxRetry = Override->TryCount;
716 Instance->Timeout = Override->TimeoutValue;
717 }
718
719 if (Instance->ListeningPort == 0) {
720 Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;
721 }
722
723 if (Instance->MaxRetry == 0) {
724 Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;
725 }
726
727 if (Instance->Timeout == 0) {
728 Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;
729 }
730
731 //
732 // Config the unicast UDP child to send initial request
733 //
734 Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);
735
736 if (EFI_ERROR (Status)) {
737 goto ON_ERROR;
738 }
739
740 //
741 // Build and send an initial requests
742 //
743 if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
744 Status = Mtftp4WrqStart (Instance, Operation);
745 } else {
746 Status = Mtftp4RrqStart (Instance, Operation);
747 }
748
749 NET_RESTORE_TPL (OldTpl);
750
751 if (EFI_ERROR (Status)) {
752 goto ON_ERROR;
753 }
754 //
755 // Return immediately for asynchronous operation or poll the
756 // instance for synchronous operation.
757 //
758 Token->Status = EFI_NOT_READY;
759
760 if (Token->Event != NULL) {
761 return EFI_SUCCESS;
762 }
763
764 while (Token->Status == EFI_NOT_READY) {
765 This->Poll (This);
766 }
767
768 return Token->Status;
769
770 ON_ERROR:
771 Mtftp4CleanOperation (Instance, Status);
772 NET_RESTORE_TPL (OldTpl);
773
774 return Status;
775 }
776
777
778 /**
779 Read a file from the server.
780
781 @param This The Mtftp protocol instance.
782 @param Token The user's request wrap token.
783
784 @retval EFI_SUCCESS The ReadFile has finished, the file has been
785 downloaded if it is synchronous operation,
786 otherwise it has been initated.
787 @retval Others Some error happened.
788
789 **/
790 STATIC
791 EFI_STATUS
792 EFIAPI
793 EfiMtftp4ReadFile (
794 IN EFI_MTFTP4_PROTOCOL *This,
795 IN EFI_MTFTP4_TOKEN *Token
796 )
797 {
798 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);
799 }
800
801
802 /**
803 Upload a file to the server.
804
805 @param This The MTFTP protocol session
806 @param Token The user's request wrap token.
807
808 @retval EFI_SUCCESS The WriteFile has finished, the file has been
809 uploaded if it is synchronous operation, otherwise
810 it has been initated.
811 @retval Others Some error happened.
812
813 **/
814 STATIC
815 EFI_STATUS
816 EFIAPI
817 EfiMtftp4WriteFile (
818 IN EFI_MTFTP4_PROTOCOL *This,
819 IN EFI_MTFTP4_TOKEN *Token
820 )
821 {
822 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);
823 }
824
825
826 /**
827 Read a directory from the server. The only difference
828 between ReadFile and ReadDirectory is the opcode used.
829
830 @param This The MTFTP protocol session
831 @param Token The user's request wrap token.
832
833 @retval EFI_SUCCESS The ReadDirectory has finished, the directory has
834 been downloaded as a file if it is synchronous
835 operation, otherwise it has been initated.
836 @retval Others Some error happened.
837
838 **/
839 STATIC
840 EFI_STATUS
841 EFIAPI
842 EfiMtftp4ReadDirectory (
843 IN EFI_MTFTP4_PROTOCOL *This,
844 IN EFI_MTFTP4_TOKEN *Token
845 )
846 {
847 return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);
848 }
849
850
851 /**
852 Poll the network stack to accelerate the packet process.
853
854 @param This The MTFTP protocol instance.
855
856 @retval EFI_INVALID_PARAMETER This is NULL.
857 @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
858 @retval EFI_DEVICE_ERROR The MTFTP session has been destoried.
859
860 **/
861 STATIC
862 EFI_STATUS
863 EFIAPI
864 EfiMtftp4Poll (
865 IN EFI_MTFTP4_PROTOCOL *This
866 )
867 {
868 MTFTP4_PROTOCOL *Instance;
869 EFI_UDP4_PROTOCOL *Udp;
870
871 if (This == NULL) {
872 return EFI_INVALID_PARAMETER;
873 }
874
875 Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
876
877 if (Instance->State == MTFTP4_STATE_UNCONFIGED) {
878 return EFI_NOT_STARTED;
879 } else if (Instance->State == MTFTP4_STATE_DESTORY) {
880 return EFI_DEVICE_ERROR;
881 }
882
883 Udp = Instance->UnicastPort->Udp;
884 return Udp->Poll (Udp);
885 }
886
887 EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {
888 EfiMtftp4GetModeData,
889 EfiMtftp4Configure,
890 EfiMtftp4GetInfo,
891 EfiMtftp4ParseOptions,
892 EfiMtftp4ReadFile,
893 EfiMtftp4WriteFile,
894 EfiMtftp4ReadDirectory,
895 EfiMtftp4Poll
896 };