]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Mtftp4Dxe/Mtftp4Support.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Mtftp4Dxe / Mtftp4Support.c
CommitLineData
772db4bb 1/** @file\r
dab714aa 2 Support routines for Mtftp.\r
d1102dba 3\r
0e2a5749 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
772db4bb 6\r
772db4bb 7**/\r
8\r
9#include "Mtftp4Impl.h"\r
10\r
772db4bb 11/**\r
dab714aa 12 Allocate a MTFTP4 block range, then init it to the range of [Start, End]\r
772db4bb 13\r
14 @param Start The start block number\r
15 @param End The last block number in the range\r
16\r
dab714aa 17 @return Pointer to the created block range, NULL if failed to allocate memory.\r
772db4bb 18\r
19**/\r
772db4bb 20MTFTP4_BLOCK_RANGE *\r
21Mtftp4AllocateRange (\r
d1050b9d
MK
22 IN UINT16 Start,\r
23 IN UINT16 End\r
772db4bb 24 )\r
25{\r
d1050b9d 26 MTFTP4_BLOCK_RANGE *Range;\r
772db4bb 27\r
f1f11ea2 28 Range = AllocateZeroPool (sizeof (MTFTP4_BLOCK_RANGE));\r
772db4bb 29\r
30 if (Range == NULL) {\r
31 return NULL;\r
32 }\r
33\r
e48e37fc 34 InitializeListHead (&Range->Link);\r
d1050b9d
MK
35 Range->Start = Start;\r
36 Range->End = End;\r
37 Range->Bound = End;\r
772db4bb 38\r
39 return Range;\r
40}\r
41\r
772db4bb 42/**\r
d1102dba
LG
43 Initialize the block range for either RRQ or WRQ.\r
44\r
45 RRQ and WRQ have different requirements for Start and End.\r
46 For example, during start up, WRQ initializes its whole valid block range\r
68ddad3f 47 to [0, 0xffff]. This is because the server will send us a ACK0 to inform us\r
d1102dba 48 to start the upload. When the client received ACK0, it will remove 0 from the\r
dab714aa 49 range, get the next block number, which is 1, then upload the BLOCK1. For RRQ\r
d1102dba
LG
50 without option negotiation, the server will directly send us the BLOCK1 in\r
51 response to the client's RRQ. When received BLOCK1, the client will remove\r
52 it from the block range and send an ACK. It also works if there is option\r
dab714aa 53 negotiation.\r
772db4bb 54\r
55 @param Head The block range head to initialize\r
56 @param Start The Start block number.\r
57 @param End The last block number.\r
58\r
59 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for initial block range\r
60 @retval EFI_SUCCESS The initial block range is created.\r
61\r
62**/\r
63EFI_STATUS\r
64Mtftp4InitBlockRange (\r
d1050b9d
MK
65 IN LIST_ENTRY *Head,\r
66 IN UINT16 Start,\r
67 IN UINT16 End\r
772db4bb 68 )\r
69{\r
d1050b9d 70 MTFTP4_BLOCK_RANGE *Range;\r
772db4bb 71\r
72 Range = Mtftp4AllocateRange (Start, End);\r
73\r
74 if (Range == NULL) {\r
75 return EFI_OUT_OF_RESOURCES;\r
76 }\r
77\r
e48e37fc 78 InsertTailList (Head, &Range->Link);\r
772db4bb 79 return EFI_SUCCESS;\r
80}\r
81\r
772db4bb 82/**\r
83 Get the first valid block number on the range list.\r
84\r
85 @param Head The block range head\r
86\r
d1102dba 87 @return The first valid block number, -1 if the block range is empty.\r
772db4bb 88\r
89**/\r
90INTN\r
91Mtftp4GetNextBlockNum (\r
d1050b9d 92 IN LIST_ENTRY *Head\r
772db4bb 93 )\r
94{\r
95 MTFTP4_BLOCK_RANGE *Range;\r
96\r
e48e37fc 97 if (IsListEmpty (Head)) {\r
772db4bb 98 return -1;\r
99 }\r
100\r
101 Range = NET_LIST_HEAD (Head, MTFTP4_BLOCK_RANGE, Link);\r
102 return Range->Start;\r
103}\r
104\r
772db4bb 105/**\r
d1102dba
LG
106 Set the last block number of the block range list.\r
107\r
dab714aa 108 It will remove all the blocks after the Last. MTFTP initialize the block range\r
d1102dba 109 to the maximum possible range, such as [0, 0xffff] for WRQ. When it gets the\r
dab714aa 110 last block number, it will call this function to set the last block number.\r
772db4bb 111\r
112 @param Head The block range list\r
113 @param Last The last block number\r
114\r
772db4bb 115**/\r
116VOID\r
117Mtftp4SetLastBlockNum (\r
d1050b9d
MK
118 IN LIST_ENTRY *Head,\r
119 IN UINT16 Last\r
772db4bb 120 )\r
121{\r
d1050b9d 122 MTFTP4_BLOCK_RANGE *Range;\r
772db4bb 123\r
124 //\r
125 // Iterate from the tail to head to remove the block number\r
126 // after the last.\r
127 //\r
e48e37fc 128 while (!IsListEmpty (Head)) {\r
772db4bb 129 Range = NET_LIST_TAIL (Head, MTFTP4_BLOCK_RANGE, Link);\r
130\r
131 if (Range->Start > Last) {\r
e48e37fc 132 RemoveEntryList (&Range->Link);\r
766c7483 133 FreePool (Range);\r
772db4bb 134 continue;\r
135 }\r
136\r
137 if (Range->End > Last) {\r
138 Range->End = Last;\r
139 }\r
140\r
d1050b9d 141 return;\r
772db4bb 142 }\r
143}\r
144\r
772db4bb 145/**\r
146 Remove the block number from the block range list.\r
147\r
148 @param Head The block range list to remove from\r
149 @param Num The block number to remove\r
9202304c
JW
150 @param Completed Whether Num is the last block number.\r
151 @param BlockCounter The continuous block counter instead of the value after roll-over.\r
772db4bb 152\r
153 @retval EFI_NOT_FOUND The block number isn't in the block range list\r
154 @retval EFI_SUCCESS The block number has been removed from the list\r
155 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource\r
156\r
157**/\r
158EFI_STATUS\r
159Mtftp4RemoveBlockNum (\r
d1050b9d
MK
160 IN LIST_ENTRY *Head,\r
161 IN UINT16 Num,\r
162 IN BOOLEAN Completed,\r
163 OUT UINT64 *BlockCounter\r
772db4bb 164 )\r
165{\r
d1050b9d
MK
166 MTFTP4_BLOCK_RANGE *Range;\r
167 MTFTP4_BLOCK_RANGE *NewRange;\r
168 LIST_ENTRY *Entry;\r
772db4bb 169\r
170 NET_LIST_FOR_EACH (Entry, Head) {\r
772db4bb 171 //\r
172 // Each block represents a hole [Start, End] in the file,\r
173 // skip to the first range with End >= Num\r
174 //\r
175 Range = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);\r
176\r
177 if (Range->End < Num) {\r
178 continue;\r
179 }\r
180\r
181 //\r
182 // There are three different cases for Start\r
183 // 1. (Start > Num) && (End >= Num):\r
184 // because all the holes before this one has the condition of\r
185 // End < Num, so this block number has been removed.\r
186 //\r
187 // 2. (Start == Num) && (End >= Num):\r
188 // Need to increase the Start by one, and if End == Num, this\r
189 // hole has been removed completely, remove it.\r
190 //\r
191 // 3. (Start < Num) && (End >= Num):\r
192 // if End == Num, only need to decrease the End by one because\r
193 // we have (Start < Num) && (Num == End), so (Start <= End - 1).\r
68ddad3f 194 // if (End > Num), the hold is split into two holes, with\r
772db4bb 195 // [Start, Num - 1] and [Num + 1, End].\r
196 //\r
197 if (Range->Start > Num) {\r
198 return EFI_NOT_FOUND;\r
772db4bb 199 } else if (Range->Start == Num) {\r
200 Range->Start++;\r
201\r
f1f11ea2 202 //\r
d1102dba
LG
203 // Note that: RFC 1350 does not mention block counter roll-over,\r
204 // but several TFTP hosts implement the roll-over be able to accept\r
205 // transfers of unlimited size. There is no consensus, however, whether\r
206 // the counter should wrap around to zero or to one. Many implementations\r
207 // wrap to zero, because this is the simplest to implement. Here we choose\r
f1f11ea2 208 // this solution.\r
209 //\r
d1050b9d 210 *BlockCounter = Num;\r
d1102dba 211\r
f1f11ea2 212 if (Range->Round > 0) {\r
d1050b9d 213 *BlockCounter += Range->Bound + MultU64x32 ((UINTN)(Range->Round -1), (UINT32)(Range->Bound + 1)) + 1;\r
6c047cfa 214 }\r
f1f11ea2 215\r
216 if (Range->Start > Range->Bound) {\r
d1102dba 217 Range->Start = 0;\r
d1050b9d 218 Range->Round++;\r
f1f11ea2 219 }\r
220\r
49fd66cb 221 if ((Range->Start > Range->End) || Completed) {\r
e48e37fc 222 RemoveEntryList (&Range->Link);\r
766c7483 223 FreePool (Range);\r
772db4bb 224 }\r
225\r
226 return EFI_SUCCESS;\r
772db4bb 227 } else {\r
228 if (Range->End == Num) {\r
229 Range->End--;\r
230 } else {\r
d1050b9d 231 NewRange = Mtftp4AllocateRange ((UINT16)(Num + 1), (UINT16)Range->End);\r
772db4bb 232\r
233 if (NewRange == NULL) {\r
234 return EFI_OUT_OF_RESOURCES;\r
235 }\r
236\r
237 Range->End = Num - 1;\r
238 NetListInsertAfter (&Range->Link, &NewRange->Link);\r
239 }\r
240\r
241 return EFI_SUCCESS;\r
242 }\r
243 }\r
244\r
245 return EFI_NOT_FOUND;\r
246}\r
247\r
772db4bb 248/**\r
249 Build then transmit the request packet for the MTFTP session.\r
250\r
251 @param Instance The Mtftp session\r
252\r
253 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the request\r
254 @retval EFI_SUCCESS The request is built and sent\r
255 @retval Others Failed to transmit the packet.\r
256\r
257**/\r
258EFI_STATUS\r
259Mtftp4SendRequest (\r
d1050b9d 260 IN MTFTP4_PROTOCOL *Instance\r
772db4bb 261 )\r
262{\r
d1050b9d
MK
263 EFI_MTFTP4_PACKET *Packet;\r
264 EFI_MTFTP4_OPTION *Options;\r
265 EFI_MTFTP4_TOKEN *Token;\r
266 RETURN_STATUS Status;\r
267 NET_BUF *Nbuf;\r
268 UINT8 *Mode;\r
269 UINT8 *Cur;\r
270 UINTN Index;\r
271 UINT32 BufferLength;\r
272 UINTN FileNameLength;\r
273 UINTN ModeLength;\r
274 UINTN OptionStrLength;\r
275 UINTN ValueStrLength;\r
772db4bb 276\r
277 Token = Instance->Token;\r
278 Options = Token->OptionList;\r
279 Mode = Instance->Token->ModeStr;\r
280\r
281 if (Mode == NULL) {\r
d1050b9d 282 Mode = (UINT8 *)"octet";\r
772db4bb 283 }\r
284\r
285 //\r
286 // Compute the packet length\r
287 //\r
d1050b9d
MK
288 FileNameLength = AsciiStrLen ((CHAR8 *)Token->Filename);\r
289 ModeLength = AsciiStrLen ((CHAR8 *)Mode);\r
290 BufferLength = (UINT32)FileNameLength + (UINT32)ModeLength + 4;\r
772db4bb 291\r
292 for (Index = 0; Index < Token->OptionCount; Index++) {\r
d1050b9d
MK
293 OptionStrLength = AsciiStrLen ((CHAR8 *)Options[Index].OptionStr);\r
294 ValueStrLength = AsciiStrLen ((CHAR8 *)Options[Index].ValueStr);\r
295 BufferLength += (UINT32)OptionStrLength + (UINT32)ValueStrLength + 2;\r
772db4bb 296 }\r
d1050b9d 297\r
772db4bb 298 //\r
299 // Allocate a packet then copy the data over\r
300 //\r
6b6fe3e9 301 if ((Nbuf = NetbufAlloc (BufferLength)) == NULL) {\r
772db4bb 302 return EFI_OUT_OF_RESOURCES;\r
303 }\r
304\r
d1050b9d 305 Packet = (EFI_MTFTP4_PACKET *)NetbufAllocSpace (Nbuf, BufferLength, FALSE);\r
894d038a 306 ASSERT (Packet != NULL);\r
307\r
772db4bb 308 Packet->OpCode = HTONS (Instance->Operation);\r
6b6fe3e9 309 BufferLength -= sizeof (Packet->OpCode);\r
d1102dba 310\r
d1050b9d
MK
311 Cur = Packet->Rrq.Filename;\r
312 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Token->Filename);\r
6b6fe3e9 313 ASSERT_EFI_ERROR (Status);\r
d1050b9d
MK
314 BufferLength -= (UINT32)(FileNameLength + 1);\r
315 Cur += FileNameLength + 1;\r
316 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Mode);\r
6b6fe3e9 317 ASSERT_EFI_ERROR (Status);\r
d1050b9d
MK
318 BufferLength -= (UINT32)(ModeLength + 1);\r
319 Cur += ModeLength + 1;\r
772db4bb 320\r
321 for (Index = 0; Index < Token->OptionCount; ++Index) {\r
d1050b9d
MK
322 OptionStrLength = AsciiStrLen ((CHAR8 *)Options[Index].OptionStr);\r
323 ValueStrLength = AsciiStrLen ((CHAR8 *)Options[Index].ValueStr);\r
d1102dba 324\r
d1050b9d 325 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Options[Index].OptionStr);\r
6b6fe3e9 326 ASSERT_EFI_ERROR (Status);\r
d1050b9d
MK
327 BufferLength -= (UINT32)(OptionStrLength + 1);\r
328 Cur += OptionStrLength + 1;\r
d1102dba 329\r
d1050b9d 330 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Options[Index].ValueStr);\r
6b6fe3e9 331 ASSERT_EFI_ERROR (Status);\r
d1050b9d
MK
332 BufferLength -= (UINT32)(ValueStrLength + 1);\r
333 Cur += ValueStrLength + 1;\r
772db4bb 334 }\r
335\r
336 return Mtftp4SendPacket (Instance, Nbuf);\r
337}\r
338\r
772db4bb 339/**\r
dab714aa 340 Build then send an error message.\r
772db4bb 341\r
342 @param Instance The MTFTP session\r
d1102dba 343 @param ErrCode The error code\r
dab714aa 344 @param ErrInfo The error message\r
772db4bb 345\r
346 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the error packet\r
347 @retval EFI_SUCCESS The error packet is transmitted.\r
348 @retval Others Failed to transmit the packet.\r
349\r
350**/\r
351EFI_STATUS\r
352Mtftp4SendError (\r
d1050b9d
MK
353 IN MTFTP4_PROTOCOL *Instance,\r
354 IN UINT16 ErrCode,\r
355 IN UINT8 *ErrInfo\r
772db4bb 356 )\r
357{\r
d1050b9d
MK
358 NET_BUF *Packet;\r
359 EFI_MTFTP4_PACKET *TftpError;\r
360 UINT32 Len;\r
772db4bb 361\r
d1050b9d
MK
362 Len = (UINT32)(AsciiStrLen ((CHAR8 *)ErrInfo) + sizeof (EFI_MTFTP4_ERROR_HEADER));\r
363 Packet = NetbufAlloc (Len);\r
772db4bb 364 if (Packet == NULL) {\r
365 return EFI_OUT_OF_RESOURCES;\r
366 }\r
367\r
d1050b9d 368 TftpError = (EFI_MTFTP4_PACKET *)NetbufAllocSpace (Packet, Len, FALSE);\r
894d038a 369 ASSERT (TftpError != NULL);\r
370\r
d1050b9d 371 TftpError->OpCode = HTONS (EFI_MTFTP4_OPCODE_ERROR);\r
772db4bb 372 TftpError->Error.ErrorCode = HTONS (ErrCode);\r
373\r
d1050b9d 374 AsciiStrCpyS ((CHAR8 *)TftpError->Error.ErrorMessage, Len, (CHAR8 *)ErrInfo);\r
772db4bb 375\r
376 return Mtftp4SendPacket (Instance, Packet);\r
377}\r
378\r
772db4bb 379/**\r
380 The callback function called when the packet is transmitted.\r
d1102dba 381\r
772db4bb 382 It simply frees the packet.\r
383\r
384 @param Packet The transmitted (or failed to) packet\r
b45b45b2 385 @param EndPoint The local and remote UDP access point\r
772db4bb 386 @param IoStatus The result of the transmission\r
387 @param Context Opaque parameter to the callback\r
388\r
772db4bb 389**/\r
772db4bb 390VOID\r
e798cd87 391EFIAPI\r
772db4bb 392Mtftp4OnPacketSent (\r
d1050b9d
MK
393 IN NET_BUF *Packet,\r
394 IN UDP_END_POINT *EndPoint,\r
395 IN EFI_STATUS IoStatus,\r
396 IN VOID *Context\r
772db4bb 397 )\r
398{\r
399 NetbufFree (Packet);\r
400}\r
401\r
772db4bb 402/**\r
dab714aa 403 Set the timeout for the instance. User a longer time for passive instances.\r
772db4bb 404\r
405 @param Instance The Mtftp session to set time out\r
406\r
772db4bb 407**/\r
408VOID\r
409Mtftp4SetTimeout (\r
d1050b9d 410 IN OUT MTFTP4_PROTOCOL *Instance\r
772db4bb 411 )\r
412{\r
413 if (Instance->Master) {\r
414 Instance->PacketToLive = Instance->Timeout;\r
415 } else {\r
416 Instance->PacketToLive = Instance->Timeout * 2;\r
417 }\r
418}\r
419\r
772db4bb 420/**\r
d1102dba
LG
421 Send the packet for the instance.\r
422\r
423 It will first save a reference to the packet for later retransmission.\r
424 Then determine the destination port, listen port for requests, and connected\r
dab714aa 425 port for others. At last, send the packet out.\r
772db4bb 426\r
427 @param Instance The Mtftp instance\r
428 @param Packet The packet to send\r
429\r
430 @retval EFI_SUCCESS The packet is sent out\r
431 @retval Others Failed to transmit the packet.\r
432\r
433**/\r
434EFI_STATUS\r
435Mtftp4SendPacket (\r
d1050b9d
MK
436 IN OUT MTFTP4_PROTOCOL *Instance,\r
437 IN OUT NET_BUF *Packet\r
772db4bb 438 )\r
439{\r
d1050b9d
MK
440 UDP_END_POINT UdpPoint;\r
441 EFI_STATUS Status;\r
442 UINT16 OpCode;\r
443 UINT8 *Buffer;\r
772db4bb 444\r
445 //\r
446 // Save the packet for retransmission\r
447 //\r
448 if (Instance->LastPacket != NULL) {\r
449 NetbufFree (Instance->LastPacket);\r
450 }\r
451\r
d1050b9d 452 Instance->LastPacket = Packet;\r
772db4bb 453\r
d1050b9d 454 Instance->CurRetry = 0;\r
772db4bb 455 Mtftp4SetTimeout (Instance);\r
456\r
b45b45b2 457 ZeroMem (&UdpPoint, sizeof (UdpPoint));\r
458 UdpPoint.RemoteAddr.Addr[0] = Instance->ServerIp;\r
772db4bb 459\r
460 //\r
461 // Send the requests to the listening port, other packets\r
462 // to the connected port\r
463 //\r
16cd325f
ED
464 Buffer = NetbufGetByte (Packet, 0, NULL);\r
465 ASSERT (Buffer != NULL);\r
466 OpCode = NTOHS (*(UINT16 *)Buffer);\r
772db4bb 467\r
d1102dba 468 if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) ||\r
dab714aa 469 (OpCode == EFI_MTFTP4_OPCODE_DIR) ||\r
d1050b9d
MK
470 (OpCode == EFI_MTFTP4_OPCODE_WRQ))\r
471 {\r
772db4bb 472 UdpPoint.RemotePort = Instance->ListeningPort;\r
473 } else {\r
474 UdpPoint.RemotePort = Instance->ConnectedPort;\r
475 }\r
476\r
477 NET_GET_REF (Packet);\r
478\r
479 Status = UdpIoSendDatagram (\r
480 Instance->UnicastPort,\r
481 Packet,\r
482 &UdpPoint,\r
b45b45b2 483 NULL,\r
772db4bb 484 Mtftp4OnPacketSent,\r
485 Instance\r
486 );\r
487\r
488 if (EFI_ERROR (Status)) {\r
489 NET_PUT_REF (Packet);\r
490 }\r
491\r
492 return Status;\r
493}\r
494\r
772db4bb 495/**\r
dab714aa 496 Retransmit the last packet for the instance.\r
772db4bb 497\r
498 @param Instance The Mtftp instance\r
499\r
500 @retval EFI_SUCCESS The last packet is retransmitted.\r
501 @retval Others Failed to retransmit.\r
502\r
503**/\r
504EFI_STATUS\r
505Mtftp4Retransmit (\r
d1050b9d 506 IN MTFTP4_PROTOCOL *Instance\r
772db4bb 507 )\r
508{\r
d1050b9d
MK
509 UDP_END_POINT UdpPoint;\r
510 EFI_STATUS Status;\r
511 UINT16 OpCode;\r
512 UINT8 *Buffer;\r
772db4bb 513\r
514 ASSERT (Instance->LastPacket != NULL);\r
515\r
b45b45b2 516 ZeroMem (&UdpPoint, sizeof (UdpPoint));\r
517 UdpPoint.RemoteAddr.Addr[0] = Instance->ServerIp;\r
772db4bb 518\r
519 //\r
520 // Set the requests to the listening port, other packets to the connected port\r
521 //\r
16cd325f
ED
522 Buffer = NetbufGetByte (Instance->LastPacket, 0, NULL);\r
523 ASSERT (Buffer != NULL);\r
d1050b9d 524 OpCode = NTOHS (*(UINT16 *)Buffer);\r
772db4bb 525\r
526 if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || (OpCode == EFI_MTFTP4_OPCODE_DIR) ||\r
d1050b9d
MK
527 (OpCode == EFI_MTFTP4_OPCODE_WRQ))\r
528 {\r
772db4bb 529 UdpPoint.RemotePort = Instance->ListeningPort;\r
530 } else {\r
531 UdpPoint.RemotePort = Instance->ConnectedPort;\r
532 }\r
533\r
534 NET_GET_REF (Instance->LastPacket);\r
535\r
536 Status = UdpIoSendDatagram (\r
537 Instance->UnicastPort,\r
538 Instance->LastPacket,\r
539 &UdpPoint,\r
b45b45b2 540 NULL,\r
772db4bb 541 Mtftp4OnPacketSent,\r
542 Instance\r
543 );\r
544\r
545 if (EFI_ERROR (Status)) {\r
546 NET_PUT_REF (Instance->LastPacket);\r
547 }\r
548\r
549 return Status;\r
550}\r
551\r
0e2a5749
FS
552/**\r
553 The timer ticking function in TPL_NOTIFY level for the Mtftp service instance.\r
554\r
555 @param Event The ticking event\r
556 @param Context The Mtftp service instance\r
557\r
558**/\r
559VOID\r
560EFIAPI\r
561Mtftp4OnTimerTickNotifyLevel (\r
d1050b9d
MK
562 IN EFI_EVENT Event,\r
563 IN VOID *Context\r
0e2a5749
FS
564 )\r
565{\r
d1050b9d
MK
566 MTFTP4_SERVICE *MtftpSb;\r
567 LIST_ENTRY *Entry;\r
568 LIST_ENTRY *Next;\r
569 MTFTP4_PROTOCOL *Instance;\r
0e2a5749 570\r
d1050b9d 571 MtftpSb = (MTFTP4_SERVICE *)Context;\r
0e2a5749
FS
572\r
573 //\r
574 // Iterate through all the children of the Mtftp service instance. Time\r
575 // out the current packet transmit.\r
576 //\r
577 NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {\r
578 Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);\r
579 if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {\r
580 Instance->HasTimeout = FALSE;\r
581 } else {\r
582 Instance->HasTimeout = TRUE;\r
583 }\r
584 }\r
585}\r
586\r
772db4bb 587/**\r
588 The timer ticking function for the Mtftp service instance.\r
589\r
590 @param Event The ticking event\r
591 @param Context The Mtftp service instance\r
592\r
772db4bb 593**/\r
594VOID\r
595EFIAPI\r
596Mtftp4OnTimerTick (\r
d1050b9d
MK
597 IN EFI_EVENT Event,\r
598 IN VOID *Context\r
772db4bb 599 )\r
600{\r
d1050b9d
MK
601 MTFTP4_SERVICE *MtftpSb;\r
602 LIST_ENTRY *Entry;\r
603 LIST_ENTRY *Next;\r
604 MTFTP4_PROTOCOL *Instance;\r
605 EFI_MTFTP4_TOKEN *Token;\r
772db4bb 606\r
d1050b9d 607 MtftpSb = (MTFTP4_SERVICE *)Context;\r
772db4bb 608\r
609 //\r
0e2a5749 610 // Iterate through all the children of the Mtftp service instance.\r
772db4bb 611 //\r
612 NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {\r
613 Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);\r
0e2a5749 614 if (!Instance->HasTimeout) {\r
772db4bb 615 continue;\r
616 }\r
d1102dba 617\r
0e2a5749 618 Instance->HasTimeout = FALSE;\r
772db4bb 619\r
620 //\r
621 // Call the user's time out handler\r
622 //\r
623 Token = Instance->Token;\r
624\r
d1050b9d
MK
625 if ((Token != NULL) && (Token->TimeoutCallback != NULL) &&\r
626 EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token)))\r
627 {\r
772db4bb 628 Mtftp4SendError (\r
0e2a5749
FS
629 Instance,\r
630 EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,\r
d1050b9d 631 (UINT8 *)"User aborted the transfer in time out"\r
0e2a5749 632 );\r
772db4bb 633\r
634 Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
635 continue;\r
636 }\r
637\r
638 //\r
68ddad3f 639 // Retransmit the packet if haven't reach the maximum retry count,\r
772db4bb 640 // otherwise exit the transfer.\r
641 //\r
642 if (++Instance->CurRetry < Instance->MaxRetry) {\r
643 Mtftp4Retransmit (Instance);\r
644 Mtftp4SetTimeout (Instance);\r
645 } else {\r
646 Mtftp4CleanOperation (Instance, EFI_TIMEOUT);\r
647 continue;\r
648 }\r
649 }\r
650}\r