Fix bug in function EfiFvbEraseBlock()
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Main.c
1 /** @file\r
2 \r
3 Copyright (c) 2005 - 2006, 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   Tcp4Main.c\r
15 \r
16 Abstract:\r
17 \r
18   Implementation of TCP4 protocol services.\r
19 \r
20 \r
21 **/\r
22 \r
23 #include "Tcp4Main.h"\r
24 \r
25 \r
26 /**\r
27   Check the integrity of the data buffer.\r
28 \r
29   @param  DataLen                  The total length of the data buffer.\r
30   @param  FragmentCount            The fragment count of the fragment table.\r
31   @param  FragmentTable            Pointer to the fragment table of the data\r
32                                    buffer.\r
33 \r
34   @retval EFI_SUCCESS              The integrity check is passed.\r
35   @retval EFI_INVALID_PARAMETER    The integrity check is failed.\r
36 \r
37 **/\r
38 STATIC\r
39 EFI_STATUS\r
40 Tcp4ChkDataBuf (\r
41   IN UINT32                 DataLen,\r
42   IN UINT32                 FragmentCount,\r
43   IN EFI_TCP4_FRAGMENT_DATA *FragmentTable\r
44   )\r
45 {\r
46   UINT32 Index;\r
47 \r
48   UINT32 Len;\r
49 \r
50   for (Index = 0, Len = 0; Index < FragmentCount; Index++) {\r
51     Len = Len + (UINT32) FragmentTable[Index].FragmentLength;\r
52   }\r
53 \r
54   if (DataLen != Len) {\r
55     return EFI_INVALID_PARAMETER;\r
56   }\r
57 \r
58   return EFI_SUCCESS;\r
59 }\r
60 \r
61 \r
62 /**\r
63   Get the current operational status.\r
64 \r
65   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
66   @param  Tcp4State                Pointer to the buffer to receive the current TCP\r
67                                    state.\r
68   @param  Tcp4ConfigData           Pointer to the buffer to receive the current TCP\r
69                                    configuration.\r
70   @param  Ip4ModeData              Pointer to the buffer to receive the current\r
71                                    IPv4 configuration.\r
72   @param  MnpConfigData            Pointer to the buffer to receive the current MNP\r
73                                    configuration data indirectly used by the TCPv4\r
74                                    Instance.\r
75   @param  SnpModeData              Pointer to the buffer to receive the current SNP\r
76                                    configuration data indirectly used by the TCPv4\r
77                                    Instance.\r
78 \r
79   @retval EFI_SUCCESS              The mode data was read.\r
80   @retval EFI_NOT_STARTED          No configuration data is available because this\r
81                                    instance hasn't been started.\r
82   @retval EFI_INVALID_PARAMETER    This is NULL.\r
83 \r
84 **/\r
85 EFI_STATUS\r
86 EFIAPI\r
87 Tcp4GetModeData (\r
88   IN  CONST EFI_TCP4_PROTOCOL                  * This,\r
89   OUT       EFI_TCP4_CONNECTION_STATE          * Tcp4State OPTIONAL,\r
90   OUT       EFI_TCP4_CONFIG_DATA               * Tcp4ConfigData OPTIONAL,\r
91   OUT       EFI_IP4_MODE_DATA                  * Ip4ModeData OPTIONAL,\r
92   OUT       EFI_MANAGED_NETWORK_CONFIG_DATA    * MnpConfigData OPTIONAL,\r
93   OUT       EFI_SIMPLE_NETWORK_MODE            * SnpModeData OPTIONAL\r
94   )\r
95 {\r
96   TCP4_MODE_DATA  TcpMode;\r
97   SOCKET          *Sock;\r
98 \r
99   if (NULL == This) {\r
100     return EFI_INVALID_PARAMETER;\r
101   }\r
102 \r
103   Sock                    = SOCK_FROM_THIS (This);\r
104 \r
105   TcpMode.Tcp4State       = Tcp4State;\r
106   TcpMode.Tcp4ConfigData  = Tcp4ConfigData;\r
107   TcpMode.Ip4ModeData     = Ip4ModeData;\r
108   TcpMode.MnpConfigData   = MnpConfigData;\r
109   TcpMode.SnpModeData     = SnpModeData;\r
110 \r
111   return SockGetMode (Sock, &TcpMode);\r
112 }\r
113 \r
114 \r
115 /**\r
116   Initialize or brutally reset the operational parameters for\r
117   this EFI TCPv4 instance.\r
118 \r
119   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
120   @param  TcpConfigData            Pointer to the configure data to configure the\r
121                                    instance.\r
122 \r
123   @retval EFI_SUCCESS              The operational settings are set, changed, or\r
124                                    reset successfully.\r
125   @retval EFI_NO_MAPPING           When using a default address, configuration\r
126                                    (through DHCP, BOOTP, RARP, etc.) is not\r
127                                    finished.\r
128   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid.\r
129   @retval EFI_ACCESS_DENIED        Configuring TCP instance when it is already\r
130                                    configured.\r
131   @retval EFI_DEVICE_ERROR         An unexpected network or system error occurred.\r
132   @retval EFI_UNSUPPORTED          One or more of the control options are not\r
133                                    supported in the implementation.\r
134   @retval EFI_OUT_OF_RESOURCES     Could not allocate enough system resources.\r
135 \r
136 **/\r
137 EFI_STATUS\r
138 EFIAPI\r
139 Tcp4Configure (\r
140   IN EFI_TCP4_PROTOCOL        * This,\r
141   IN EFI_TCP4_CONFIG_DATA     * TcpConfigData OPTIONAL\r
142   )\r
143 {\r
144   EFI_TCP4_OPTION  *Option;\r
145   SOCKET           *Sock;\r
146   EFI_STATUS       Status;\r
147   IP4_ADDR         Ip;\r
148   IP4_ADDR         SubnetMask;\r
149 \r
150 //  CpuBreakpoint ();\r
151   if (NULL == This) {\r
152     return EFI_INVALID_PARAMETER;\r
153   }\r
154 \r
155   //\r
156   // Tcp protocol related parameter check will be conducted here\r
157   //\r
158   if (NULL != TcpConfigData) {\r
159 \r
160     NetCopyMem (&Ip, &TcpConfigData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
161     if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
162       return EFI_INVALID_PARAMETER;\r
163     }\r
164 \r
165     if (TcpConfigData->AccessPoint.ActiveFlag &&\r
166       (0 == TcpConfigData->AccessPoint.RemotePort || (Ip == 0))) {\r
167       return EFI_INVALID_PARAMETER;\r
168     }\r
169 \r
170     if (!TcpConfigData->AccessPoint.UseDefaultAddress) {\r
171 \r
172       NetCopyMem (&Ip, &TcpConfigData->AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
173       NetCopyMem (&SubnetMask, &TcpConfigData->AccessPoint.SubnetMask, sizeof (IP4_ADDR));\r
174       if (!Ip4IsUnicast (NTOHL (Ip), 0) || !IP4_IS_VALID_NETMASK (NTOHL (SubnetMask))) {\r
175         return EFI_INVALID_PARAMETER;\r
176       }\r
177     }\r
178 \r
179     Option = TcpConfigData->ControlOption;\r
180     if ((NULL != Option) &&\r
181         (Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {\r
182       return EFI_UNSUPPORTED;\r
183     }\r
184   }\r
185 \r
186   Sock = SOCK_FROM_THIS (This);\r
187 \r
188   if (NULL == TcpConfigData) {\r
189     return SockFlush (Sock);\r
190   }\r
191 \r
192   Status = SockConfigure (Sock, TcpConfigData);\r
193 \r
194   if (EFI_NO_MAPPING == Status) {\r
195     Sock->ConfigureState = SO_NO_MAPPING;\r
196   }\r
197 \r
198   return Status;\r
199 }\r
200 \r
201 \r
202 /**\r
203   Add or delete routing entries.\r
204 \r
205   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
206   @param  DeleteRoute              If TRUE, delete the specified route from routing\r
207                                    table; if FALSE, add the specified route to\r
208                                    routing table.\r
209   @param  SubnetAddress            The destination network.\r
210   @param  SubnetMask               The subnet mask for the destination network.\r
211   @param  GatewayAddress           The gateway address for this route.\r
212 \r
213   @retval EFI_SUCCESS              The operation completed successfully.\r
214   @retval EFI_NOT_STARTED          The EFI_TCP4_PROTOCOL instance has not been\r
215                                    configured.\r
216   @retval EFI_NO_MAPPING           When using a default address, configuration\r
217                                    (through DHCP, BOOTP, RARP, etc.) is not\r
218                                    finished.\r
219   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid.\r
220   @retval EFI_OUT_OF_RESOURCES     Could not allocate enough resources to add the\r
221                                    entry to the routing table.\r
222   @retval EFI_NOT_FOUND            This route is not in the routing table.\r
223   @retval EFI_ACCESS_DENIED        This route is already in the routing table.\r
224   @retval EFI_UNSUPPORTED          The TCP driver does not support this operation.\r
225 \r
226 **/\r
227 EFI_STATUS\r
228 EFIAPI\r
229 Tcp4Routes (\r
230   IN EFI_TCP4_PROTOCOL           *This,\r
231   IN BOOLEAN                     DeleteRoute,\r
232   IN EFI_IPv4_ADDRESS            *SubnetAddress,\r
233   IN EFI_IPv4_ADDRESS            *SubnetMask,\r
234   IN EFI_IPv4_ADDRESS            *GatewayAddress\r
235   )\r
236 {\r
237   SOCKET          *Sock;\r
238   TCP4_ROUTE_INFO RouteInfo;\r
239 \r
240   if (NULL == This) {\r
241     return EFI_INVALID_PARAMETER;\r
242   }\r
243 \r
244   Sock                      = SOCK_FROM_THIS (This);\r
245 \r
246   RouteInfo.DeleteRoute     = DeleteRoute;\r
247   RouteInfo.SubnetAddress   = SubnetAddress;\r
248   RouteInfo.SubnetMask      = SubnetMask;\r
249   RouteInfo.GatewayAddress  = GatewayAddress;\r
250 \r
251   return SockRoute (Sock, &RouteInfo);\r
252 }\r
253 \r
254 \r
255 /**\r
256   Initiate a nonblocking TCP connection request for an active TCP instance.\r
257 \r
258   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance\r
259   @param  ConnectionToken          Pointer to the connection token to return when\r
260                                    the TCP three way handshake finishes.\r
261 \r
262   @retval EFI_SUCCESS              The connection request is successfully\r
263                                    initiated.\r
264   @retval EFI_NOT_STARTED          This EFI_TCP4_PROTOCOL instance hasn't been\r
265                                    configured.\r
266   @retval EFI_ACCESS_DENIED        The instance is not configured as an active one\r
267                                    or it is not in Tcp4StateClosed state.\r
268   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid.\r
269   @retval EFI_OUT_OF_RESOURCES     The driver can't allocate enough resource to\r
270                                    initiate the active open.\r
271   @retval EFI_DEVICE_ERROR         An unexpected system or network error occurred.\r
272 \r
273 **/\r
274 EFI_STATUS\r
275 EFIAPI\r
276 Tcp4Connect (\r
277   IN EFI_TCP4_PROTOCOL           *This,\r
278   IN EFI_TCP4_CONNECTION_TOKEN   *ConnectionToken\r
279   )\r
280 {\r
281   SOCKET  *Sock;\r
282 \r
283   if (NULL == This ||\r
284       NULL == ConnectionToken ||\r
285       NULL == ConnectionToken->CompletionToken.Event) {\r
286     return EFI_INVALID_PARAMETER;\r
287   }\r
288 \r
289   Sock = SOCK_FROM_THIS (This);\r
290 \r
291   return SockConnect (Sock, ConnectionToken);\r
292 }\r
293 \r
294 \r
295 /**\r
296   Listen on the passive instance to accept an incoming connection request.\r
297 \r
298   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance\r
299   @param  ListenToken              Pointer to the listen token to return when\r
300                                    operation finishes.\r
301 \r
302   @retval EFI_SUCCESS              The listen token has been queued successfully.\r
303   @retval EFI_NOT_STARTED          The EFI_TCP4_PROTOCOL instance hasn't been\r
304                                    configured.\r
305   @retval EFI_ACCESS_DENIED        The instatnce is not a passive one or it is not\r
306                                    in Tcp4StateListen state or a same listen token\r
307                                    has already existed in the listen token queue of\r
308                                    this TCP instance.\r
309   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid.\r
310   @retval EFI_OUT_OF_RESOURCES     Could not allocate enough resources to finish\r
311                                    the operation.\r
312   @retval EFI_DEVICE_ERROR         An unexpected system or network error occurred.\r
313 \r
314 **/\r
315 EFI_STATUS\r
316 EFIAPI\r
317 Tcp4Accept (\r
318   IN EFI_TCP4_PROTOCOL             *This,\r
319   IN EFI_TCP4_LISTEN_TOKEN         *ListenToken\r
320   )\r
321 {\r
322   SOCKET  *Sock;\r
323 \r
324   if (NULL == This ||\r
325       NULL == ListenToken ||\r
326       NULL == ListenToken->CompletionToken.Event) {\r
327     return EFI_INVALID_PARAMETER;\r
328   }\r
329 \r
330   Sock = SOCK_FROM_THIS (This);\r
331 \r
332   return SockAccept (Sock, ListenToken);\r
333 }\r
334 \r
335 \r
336 /**\r
337   Queues outgoing data into the transmit queue\r
338 \r
339   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance\r
340   @param  Token                    Pointer to the completion token to queue to the\r
341                                    transmit queue\r
342 \r
343   @retval EFI_SUCCESS              The data has been queued for transmission\r
344   @retval EFI_NOT_STARTED          The EFI_TCP4_PROTOCOL instance hasn't been\r
345                                    configured.\r
346   @retval EFI_NO_MAPPING           When using a default address, configuration\r
347                                    (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
348   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid\r
349   @retval EFI_ACCESS_DENIED        One or more of the following conditions is TRUE:\r
350                                    * A transmit completion token with the same\r
351                                    Token-> CompletionToken.Event was already in the\r
352                                    transmission queue. * The current instance is in\r
353                                    Tcp4StateClosed state * The current instance is\r
354                                    a passive one and it is in Tcp4StateListen\r
355                                    state. * User has called Close() to disconnect\r
356                                    this connection.\r
357   @retval EFI_NOT_READY            The completion token could not be queued because\r
358                                    the transmit queue is full.\r
359   @retval EFI_OUT_OF_RESOURCES     Could not queue the transmit data because of\r
360                                    resource shortage.\r
361   @retval EFI_NETWORK_UNREACHABLE  There is no route to the destination network or\r
362                                    address.\r
363 \r
364 **/\r
365 EFI_STATUS\r
366 EFIAPI\r
367 Tcp4Transmit (\r
368   IN EFI_TCP4_PROTOCOL            *This,\r
369   IN EFI_TCP4_IO_TOKEN            *Token\r
370   )\r
371 {\r
372   SOCKET      *Sock;\r
373   EFI_STATUS  Status;\r
374 \r
375   if (NULL == This ||\r
376       NULL == Token ||\r
377       NULL == Token->CompletionToken.Event ||\r
378       NULL == Token->Packet.TxData ||\r
379       0 == Token->Packet.TxData->FragmentCount ||\r
380       0 == Token->Packet.TxData->DataLength\r
381       ) {\r
382     return EFI_INVALID_PARAMETER;\r
383   }\r
384 \r
385   Status = Tcp4ChkDataBuf (\r
386             (UINT32) Token->Packet.TxData->DataLength,\r
387             (UINT32) Token->Packet.TxData->FragmentCount,\r
388             Token->Packet.TxData->FragmentTable\r
389             );\r
390   if (EFI_ERROR (Status)) {\r
391     return Status;\r
392   }\r
393 \r
394   Sock = SOCK_FROM_THIS (This);\r
395 \r
396   return SockSend (Sock, Token);\r
397 \r
398 }\r
399 \r
400 \r
401 /**\r
402   Place an asynchronous receive request into the receiving queue.\r
403 \r
404   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
405   @param  Token                    Pointer to a token that is associated with the\r
406                                    receive data descriptor.\r
407 \r
408   @retval EFI_SUCCESS              The receive completion token was cached\r
409   @retval EFI_NOT_STARTED          The EFI_TCP4_PROTOCOL instance hasn't been\r
410                                    configured.\r
411   @retval EFI_NO_MAPPING           When using a default address, configuration\r
412                                    (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
413   @retval EFI_INVALID_PARAMETER    One or more parameters are invalid.\r
414   @retval EFI_OUT_OF_RESOURCES     The receive completion token could not be queued\r
415                                    due to a lack of system resources.\r
416   @retval EFI_DEVICE_ERROR         An unexpected system or network error occurred.\r
417   @retval EFI_ACCESS_DENIED        One or more of the following conditions is TRUE:\r
418                                    * A receive completion token with the same\r
419                                    Token->CompletionToken.Event was already in the\r
420                                    receive queue. * The current instance is in\r
421                                    Tcp4StateClosed state. * The current instance is\r
422                                    a passive one and it is in Tcp4StateListen\r
423                                    state. * User has called Close() to disconnect\r
424                                    this connection.\r
425   @retval EFI_CONNECTION_FIN       The communication peer has closed the connection\r
426                                    and there is no any buffered data in the receive\r
427                                    buffer of this instance.\r
428   @retval EFI_NOT_READY            The receive request could not be queued because\r
429                                    the receive queue is full.\r
430 \r
431 **/\r
432 EFI_STATUS\r
433 EFIAPI\r
434 Tcp4Receive (\r
435   IN EFI_TCP4_PROTOCOL           *This,\r
436   IN EFI_TCP4_IO_TOKEN           *Token\r
437   )\r
438 {\r
439   SOCKET      *Sock;\r
440   EFI_STATUS  Status;\r
441 \r
442   if (NULL == This ||\r
443       NULL == Token ||\r
444       NULL == Token->CompletionToken.Event ||\r
445       NULL == Token->Packet.RxData ||\r
446       0 == Token->Packet.RxData->FragmentCount ||\r
447       0 == Token->Packet.RxData->DataLength\r
448       ) {\r
449     return EFI_INVALID_PARAMETER;\r
450   }\r
451 \r
452   Status = Tcp4ChkDataBuf (\r
453             (UINT32) Token->Packet.RxData->DataLength,\r
454             (UINT32) Token->Packet.RxData->FragmentCount,\r
455             Token->Packet.RxData->FragmentTable\r
456             );\r
457   if (EFI_ERROR (Status)) {\r
458     return Status;\r
459   }\r
460 \r
461   Sock = SOCK_FROM_THIS (This);\r
462 \r
463   return SockRcv (Sock, Token);\r
464 \r
465 }\r
466 \r
467 \r
468 /**\r
469   Disconnecting a TCP connection gracefully or reset a TCP connection.\r
470 \r
471   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance\r
472   @param  CloseToken               Pointer to the close token to return when\r
473                                    operation finishes.\r
474 \r
475   @retval EFI_SUCCESS              The operation completed successfully\r
476   @retval EFI_NOT_STARTED          The EFI_TCP4_PROTOCOL instance hasn't been\r
477                                    configured.\r
478   @retval EFI_ACCESS_DENIED        One or more of the following are TRUE: *\r
479                                    Configure() has been called with TcpConfigData\r
480                                    set to NULL and this function has not returned.\r
481                                    * Previous Close() call on this instance has not\r
482                                    finished.\r
483   @retval EFI_INVALID_PARAMETER    One ore more parameters are invalid\r
484   @retval EFI_OUT_OF_RESOURCES     Could not allocate enough resource to finish the\r
485                                    operation\r
486   @retval EFI_DEVICE_ERROR         Any unexpected and not belonged to above\r
487                                    category error.\r
488 \r
489 **/\r
490 EFI_STATUS\r
491 EFIAPI\r
492 Tcp4Close (\r
493   IN EFI_TCP4_PROTOCOL           *This,\r
494   IN EFI_TCP4_CLOSE_TOKEN        *CloseToken\r
495   )\r
496 {\r
497   SOCKET  *Sock;\r
498 \r
499   if (NULL == This ||\r
500       NULL == CloseToken ||\r
501       NULL == CloseToken->CompletionToken.Event) {\r
502     return EFI_INVALID_PARAMETER;\r
503   }\r
504 \r
505   Sock = SOCK_FROM_THIS (This);\r
506 \r
507   return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);\r
508 }\r
509 \r
510 \r
511 /**\r
512   Abort an asynchronous connection, listen, transmission or receive request.\r
513 \r
514   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
515   @param  Token                    Pointer to a token that has been issued by\r
516                                    Connect(), Accept(), Transmit() or Receive(). If\r
517                                    NULL, all pending tokens issued by above four\r
518                                    functions will be aborted.\r
519 \r
520   @retval EFI_UNSUPPORTED          The operation is not supported in current\r
521                                    implementation.\r
522 \r
523 **/\r
524 EFI_STATUS\r
525 EFIAPI\r
526 Tcp4Cancel (\r
527   IN EFI_TCP4_PROTOCOL           * This,\r
528   IN EFI_TCP4_COMPLETION_TOKEN   * Token OPTIONAL\r
529   )\r
530 {\r
531   return EFI_UNSUPPORTED;\r
532 }\r
533 \r
534 \r
535 /**\r
536   Poll to receive incoming data and transmit outgoing segments.\r
537 \r
538   @param  This                     Pointer to the EFI_TCP4_PROTOCOL instance.\r
539 \r
540   @retval EFI_SUCCESS              Incoming or outgoing data was processed.\r
541   @retval EFI_INVALID_PARAMETER    This is NULL.\r
542   @retval EFI_DEVICE_ERROR         An unexpected system or network error occurred.\r
543   @retval EFI_NOT_READY            No incoming or outgoing data was processed.\r
544   @retval EFI_TIMEOUT              Data was dropped out of the transmission or\r
545                                    receive queue. Consider increasing the polling\r
546                                    rate.\r
547 \r
548 **/\r
549 EFI_STATUS\r
550 EFIAPI\r
551 Tcp4Poll (\r
552   IN EFI_TCP4_PROTOCOL        *This\r
553   )\r
554 {\r
555   SOCKET      *Sock;\r
556   EFI_STATUS  Status;\r
557 \r
558   if (NULL == This) {\r
559     return EFI_INVALID_PARAMETER;\r
560   }\r
561 \r
562   Sock    = SOCK_FROM_THIS (This);\r
563 \r
564   Status  = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);\r
565 \r
566   return Status;\r
567 }\r