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