]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/SockInterface.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / TcpDxe / SockInterface.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Interface function of the Socket.\r
3\r
f75a7f56 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
7\r
8**/\r
9\r
10#include "SockImpl.h"\r
11\r
12/**\r
13 Check whether the Event is in the List.\r
14\r
15 @param[in] List Pointer to the token list to be searched.\r
16 @param[in] Event The event to be checked.\r
17\r
18 @retval TRUE The specific Event exists in the List.\r
19 @retval FALSE The specific Event is not in the List.\r
20\r
21**/\r
22BOOLEAN\r
23SockTokenExistedInList (\r
d1050b9d
MK
24 IN LIST_ENTRY *List,\r
25 IN EFI_EVENT Event\r
a3bcde70
HT
26 )\r
27{\r
d1050b9d
MK
28 LIST_ENTRY *ListEntry;\r
29 SOCK_TOKEN *SockToken;\r
a3bcde70
HT
30\r
31 NET_LIST_FOR_EACH (ListEntry, List) {\r
32 SockToken = NET_LIST_USER_STRUCT (\r
33 ListEntry,\r
34 SOCK_TOKEN,\r
35 TokenList\r
36 );\r
37\r
38 if (Event == SockToken->Token->Event) {\r
39 return TRUE;\r
40 }\r
41 }\r
42\r
43 return FALSE;\r
44}\r
45\r
46/**\r
47 Call SockTokenExistedInList() to check whether the Event is\r
48 in the related socket's lists.\r
49\r
50 @param[in] Sock Pointer to the instance's socket.\r
51 @param[in] Event The event to be checked.\r
52\r
53 @retval TRUE The Event exists in related socket's lists.\r
54 @retval FALSE The Event is not in related socket's lists.\r
55\r
56**/\r
57BOOLEAN\r
58SockTokenExisted (\r
d1050b9d
MK
59 IN SOCKET *Sock,\r
60 IN EFI_EVENT Event\r
a3bcde70
HT
61 )\r
62{\r
a3bcde70
HT
63 if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||\r
64 SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||\r
65 SockTokenExistedInList (&Sock->RcvTokenList, Event) ||\r
66 SockTokenExistedInList (&Sock->ListenTokenList, Event)\r
d1050b9d
MK
67 )\r
68 {\r
a3bcde70
HT
69 return TRUE;\r
70 }\r
71\r
72 if ((Sock->ConnectionToken != NULL) && (Sock->ConnectionToken->Event == Event)) {\r
a3bcde70
HT
73 return TRUE;\r
74 }\r
75\r
76 if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {\r
77 return TRUE;\r
78 }\r
79\r
80 return FALSE;\r
81}\r
82\r
83/**\r
84 Buffer a token into the specific list of the socket Sock.\r
85\r
86 @param[in] Sock Pointer to the instance's socket.\r
87 @param[in] List Pointer to the list to store the token.\r
88 @param[in] Token Pointer to the token to be buffered.\r
89 @param[in] DataLen The data length of the buffer contained in Token.\r
90\r
91 @return Pointer to the token that wraps Token. If NULL, an error condition occurred.\r
92\r
93**/\r
94SOCK_TOKEN *\r
95SockBufferToken (\r
d1050b9d
MK
96 IN SOCKET *Sock,\r
97 IN LIST_ENTRY *List,\r
98 IN VOID *Token,\r
99 IN UINT32 DataLen\r
a3bcde70
HT
100 )\r
101{\r
102 SOCK_TOKEN *SockToken;\r
103\r
104 SockToken = AllocateZeroPool (sizeof (SOCK_TOKEN));\r
105 if (NULL == SockToken) {\r
a3bcde70 106 DEBUG (\r
c49ca4a2 107 (DEBUG_ERROR,\r
d1050b9d 108 "SockBufferIOToken: No Memory to allocate SockToken\n")\r
a3bcde70
HT
109 );\r
110\r
111 return NULL;\r
112 }\r
113\r
d1050b9d
MK
114 SockToken->Sock = Sock;\r
115 SockToken->Token = (SOCK_COMPLETION_TOKEN *)Token;\r
116 SockToken->RemainDataLen = DataLen;\r
a3bcde70
HT
117 InsertTailList (List, &SockToken->TokenList);\r
118\r
119 return SockToken;\r
120}\r
121\r
122/**\r
75dce340 123 Destroy the socket Sock and its associated protocol control block.\r
a3bcde70
HT
124\r
125 @param[in, out] Sock The socket to be destroyed.\r
126\r
127 @retval EFI_SUCCESS The socket Sock was destroyed successfully.\r
128 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
129\r
130**/\r
131EFI_STATUS\r
132SockDestroyChild (\r
d1050b9d 133 IN OUT SOCKET *Sock\r
a3bcde70
HT
134 )\r
135{\r
d1050b9d
MK
136 EFI_STATUS Status;\r
137 TCP_PROTO_DATA *ProtoData;\r
138 TCP_CB *Tcb;\r
139 EFI_GUID *IpProtocolGuid;\r
140 EFI_GUID *TcpProtocolGuid;\r
141 VOID *SockProtocol;\r
a3bcde70
HT
142\r
143 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
144\r
216f7970 145 if (Sock->InDestroy) {\r
a3bcde70
HT
146 return EFI_SUCCESS;\r
147 }\r
148\r
216f7970 149 Sock->InDestroy = TRUE;\r
a3bcde70 150\r
d555699b 151 if (Sock->IpVersion == IP_VERSION_4) {\r
d1050b9d 152 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
d555699b
ZL
153 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
154 } else {\r
d1050b9d 155 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
d555699b
ZL
156 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
157 }\r
d1050b9d
MK
158\r
159 ProtoData = (TCP_PROTO_DATA *)Sock->ProtoReserved;\r
d555699b
ZL
160 Tcb = ProtoData->TcpPcb;\r
161\r
162 ASSERT (Tcb != NULL);\r
163\r
d555699b
ZL
164 //\r
165 // Close the IP protocol.\r
166 //\r
167 gBS->CloseProtocol (\r
168 Tcb->IpInfo->ChildHandle,\r
169 IpProtocolGuid,\r
170 ProtoData->TcpService->IpIo->Image,\r
171 Sock->SockHandle\r
172 );\r
173\r
174 if (Sock->DestroyCallback != NULL) {\r
175 Sock->DestroyCallback (Sock, Sock->Context);\r
176 }\r
177\r
178 //\r
179 // Retrieve the protocol installed on this sock\r
180 //\r
181 Status = gBS->OpenProtocol (\r
182 Sock->SockHandle,\r
183 TcpProtocolGuid,\r
184 &SockProtocol,\r
185 Sock->DriverBinding,\r
186 Sock->SockHandle,\r
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
188 );\r
189\r
190 if (EFI_ERROR (Status)) {\r
d555699b 191 DEBUG (\r
c49ca4a2 192 (DEBUG_ERROR,\r
d1050b9d
MK
193 "SockDestroyChild: Open protocol installed on socket failed with %r\n",\r
194 Status)\r
d555699b
ZL
195 );\r
196 }\r
197\r
198 //\r
199 // Uninstall the protocol installed on this sock\r
200 //\r
201 gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
202 Sock->SockHandle,\r
203 TcpProtocolGuid,\r
204 SockProtocol,\r
205 NULL\r
206 );\r
597cf8a1 207\r
d1050b9d 208 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
597cf8a1 209 if (EFI_ERROR (Status)) {\r
597cf8a1 210 DEBUG (\r
c49ca4a2 211 (DEBUG_ERROR,\r
d1050b9d
MK
212 "SockDestroyChild: Get the lock to access socket failed with %r\n",\r
213 Status)\r
597cf8a1
ZL
214 );\r
215\r
216 return EFI_ACCESS_DENIED;\r
217 }\r
218\r
a3bcde70
HT
219 //\r
220 // force protocol layer to detach the PCB\r
221 //\r
222 Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);\r
223\r
224 if (EFI_ERROR (Status)) {\r
a3bcde70 225 DEBUG (\r
c49ca4a2 226 (DEBUG_ERROR,\r
d1050b9d
MK
227 "SockDestroyChild: Protocol detach socket failed with %r\n",\r
228 Status)\r
a3bcde70
HT
229 );\r
230\r
216f7970 231 Sock->InDestroy = FALSE;\r
a3bcde70 232 } else if (SOCK_IS_CONFIGURED (Sock)) {\r
a3bcde70
HT
233 SockConnFlush (Sock);\r
234 SockSetState (Sock, SO_CLOSED);\r
235\r
236 Sock->ConfigureState = SO_UNCONFIGURED;\r
237 }\r
238\r
239 EfiReleaseLock (&(Sock->Lock));\r
240\r
241 if (EFI_ERROR (Status)) {\r
242 return Status;\r
243 }\r
244\r
245 SockDestroy (Sock);\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249/**\r
250 Create a socket and its associated protocol control block\r
4cefb5e9 251 with the initial data SockInitData and protocol specific\r
a3bcde70
HT
252 data ProtoData.\r
253\r
4cefb5e9 254 @param[in] SockInitData Initial data to setting the socket.\r
a3bcde70 255\r
4cefb5e9 256 @return Pointer to the newly created socket. If NULL, an error condition occurred.\r
a3bcde70
HT
257\r
258**/\r
259SOCKET *\r
260SockCreateChild (\r
d1050b9d 261 IN SOCK_INIT_DATA *SockInitData\r
a3bcde70
HT
262 )\r
263{\r
264 SOCKET *Sock;\r
265 EFI_STATUS Status;\r
d555699b
ZL
266 VOID *SockProtocol;\r
267 EFI_GUID *TcpProtocolGuid;\r
a3bcde70
HT
268\r
269 //\r
270 // create a new socket\r
271 //\r
272 Sock = SockCreate (SockInitData);\r
273 if (NULL == Sock) {\r
a3bcde70 274 DEBUG (\r
c49ca4a2 275 (DEBUG_ERROR,\r
d1050b9d 276 "SockCreateChild: No resource to create a new socket\n")\r
a3bcde70
HT
277 );\r
278\r
279 return NULL;\r
280 }\r
281\r
282 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
283 if (EFI_ERROR (Status)) {\r
a3bcde70 284 DEBUG (\r
c49ca4a2 285 (DEBUG_ERROR,\r
d1050b9d
MK
286 "SockCreateChild: Get the lock to access socket failed with %r\n",\r
287 Status)\r
a3bcde70 288 );\r
d555699b 289 goto ERROR;\r
a3bcde70 290 }\r
d1050b9d 291\r
a3bcde70
HT
292 //\r
293 // inform the protocol layer to attach the socket\r
294 // with a new protocol control block\r
295 //\r
296 Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);\r
80ae1cc7 297 EfiReleaseLock (&(Sock->Lock));\r
a3bcde70 298 if (EFI_ERROR (Status)) {\r
a3bcde70 299 DEBUG (\r
c49ca4a2 300 (DEBUG_ERROR,\r
d1050b9d
MK
301 "SockCreateChild: Protocol failed to attach a socket with %r\n",\r
302 Status)\r
a3bcde70 303 );\r
d555699b 304 goto ERROR;\r
a3bcde70
HT
305 }\r
306\r
a3bcde70 307 return Sock;\r
d555699b
ZL
308\r
309ERROR:\r
310\r
311 if (Sock->DestroyCallback != NULL) {\r
312 Sock->DestroyCallback (Sock, Sock->Context);\r
313 }\r
314\r
315 if (Sock->IpVersion == IP_VERSION_4) {\r
316 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
317 } else {\r
318 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
319 }\r
320\r
321 gBS->OpenProtocol (\r
322 Sock->SockHandle,\r
323 TcpProtocolGuid,\r
324 &SockProtocol,\r
325 Sock->DriverBinding,\r
326 Sock->SockHandle,\r
327 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
328 );\r
329 //\r
330 // Uninstall the protocol installed on this sock\r
331 //\r
332 gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
333 Sock->SockHandle,\r
334 TcpProtocolGuid,\r
335 SockProtocol,\r
336 NULL\r
337 );\r
338 SockDestroy (Sock);\r
339 return NULL;\r
a3bcde70
HT
340}\r
341\r
342/**\r
343 Configure the specific socket Sock using configuration data ConfigData.\r
344\r
345 @param[in] Sock Pointer to the socket to be configured.\r
346 @param[in] ConfigData Pointer to the configuration data.\r
347\r
348 @retval EFI_SUCCESS The socket configured successfully.\r
349 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
350 socket is already configured.\r
351\r
352**/\r
353EFI_STATUS\r
354SockConfigure (\r
d1050b9d
MK
355 IN SOCKET *Sock,\r
356 IN VOID *ConfigData\r
a3bcde70
HT
357 )\r
358{\r
359 EFI_STATUS Status;\r
360\r
361 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
362 if (EFI_ERROR (Status)) {\r
a3bcde70 363 DEBUG (\r
c49ca4a2 364 (DEBUG_ERROR,\r
d1050b9d
MK
365 "SockConfigure: Get the access for socket failed with %r",\r
366 Status)\r
a3bcde70
HT
367 );\r
368\r
369 return EFI_ACCESS_DENIED;\r
370 }\r
371\r
372 if (SOCK_IS_CONFIGURED (Sock)) {\r
373 Status = EFI_ACCESS_DENIED;\r
374 goto OnExit;\r
375 }\r
376\r
377 ASSERT (Sock->State == SO_CLOSED);\r
378\r
379 Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);\r
380\r
381OnExit:\r
382 EfiReleaseLock (&(Sock->Lock));\r
383\r
384 return Status;\r
385}\r
386\r
387/**\r
388 Initiate a connection establishment process.\r
389\r
4cefb5e9 390 @param[in] Sock Pointer to the socket to initiate the\r
a3bcde70
HT
391 connection.\r
392 @param[in] Token Pointer to the token used for the connection\r
393 operation.\r
394\r
395 @retval EFI_SUCCESS The connection initialized successfully.\r
396 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
397 socket is closed, or the socket is not configured to\r
398 be an active one, or the token is already in one of\r
399 this socket's lists.\r
400 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
401 finished.\r
402 @retval EFI_NOT_STARTED The socket is not configured.\r
403\r
404**/\r
405EFI_STATUS\r
406SockConnect (\r
d1050b9d
MK
407 IN SOCKET *Sock,\r
408 IN VOID *Token\r
a3bcde70
HT
409 )\r
410{\r
411 EFI_STATUS Status;\r
412 EFI_EVENT Event;\r
413\r
414 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
415 if (EFI_ERROR (Status)) {\r
a3bcde70 416 DEBUG (\r
c49ca4a2 417 (DEBUG_ERROR,\r
d1050b9d
MK
418 "SockConnect: Get the access for socket failed with %r",\r
419 Status)\r
a3bcde70
HT
420 );\r
421\r
422 return EFI_ACCESS_DENIED;\r
423 }\r
424\r
425 if (SOCK_IS_NO_MAPPING (Sock)) {\r
426 Status = EFI_NO_MAPPING;\r
427 goto OnExit;\r
428 }\r
429\r
430 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
431 Status = EFI_NOT_STARTED;\r
432 goto OnExit;\r
433 }\r
434\r
435 if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {\r
a3bcde70
HT
436 Status = EFI_ACCESS_DENIED;\r
437 goto OnExit;\r
438 }\r
439\r
d1050b9d 440 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
441\r
442 if (SockTokenExisted (Sock, Event)) {\r
a3bcde70
HT
443 Status = EFI_ACCESS_DENIED;\r
444 goto OnExit;\r
445 }\r
446\r
d1050b9d 447 Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *)Token;\r
a3bcde70
HT
448 SockSetState (Sock, SO_CONNECTING);\r
449 Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);\r
450\r
451OnExit:\r
452 EfiReleaseLock (&(Sock->Lock));\r
453 return Status;\r
454}\r
455\r
456/**\r
457 Issue a listen token to get an existed connected network instance\r
458 or wait for a connection if there is none.\r
459\r
460 @param[in] Sock Pointer to the socket to accept connections.\r
461 @param[in] Token The token to accept a connection.\r
462\r
4cefb5e9 463 @retval EFI_SUCCESS Either a connection is accepted or the Token is\r
a3bcde70
HT
464 buffered for further acception.\r
465 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
466 socket is closed, or the socket is not configured to\r
467 be a passive one, or the token is already in one of\r
468 this socket's lists.\r
469 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
470 finished.\r
471 @retval EFI_NOT_STARTED The socket is not configured.\r
472 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limits.\r
473\r
474**/\r
475EFI_STATUS\r
476SockAccept (\r
d1050b9d
MK
477 IN SOCKET *Sock,\r
478 IN VOID *Token\r
a3bcde70
HT
479 )\r
480{\r
d1050b9d
MK
481 EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
482 LIST_ENTRY *ListEntry;\r
483 EFI_STATUS Status;\r
484 SOCKET *Socket;\r
485 EFI_EVENT Event;\r
a3bcde70
HT
486\r
487 ASSERT (SockStream == Sock->Type);\r
488\r
489 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
490 if (EFI_ERROR (Status)) {\r
a3bcde70 491 DEBUG (\r
c49ca4a2 492 (DEBUG_ERROR,\r
d1050b9d
MK
493 "SockAccept: Get the access for socket failed with %r",\r
494 Status)\r
a3bcde70
HT
495 );\r
496\r
497 return EFI_ACCESS_DENIED;\r
498 }\r
499\r
500 if (SOCK_IS_NO_MAPPING (Sock)) {\r
501 Status = EFI_NO_MAPPING;\r
502 goto Exit;\r
503 }\r
504\r
505 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
506 Status = EFI_NOT_STARTED;\r
507 goto Exit;\r
508 }\r
509\r
510 if (!SOCK_IS_LISTENING (Sock)) {\r
a3bcde70
HT
511 Status = EFI_ACCESS_DENIED;\r
512 goto Exit;\r
513 }\r
514\r
d1050b9d 515 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
516\r
517 if (SockTokenExisted (Sock, Event)) {\r
a3bcde70
HT
518 Status = EFI_ACCESS_DENIED;\r
519 goto Exit;\r
520 }\r
521\r
d1050b9d 522 ListenToken = (EFI_TCP4_LISTEN_TOKEN *)Token;\r
a3bcde70
HT
523\r
524 //\r
525 // Check if a connection has already in this Sock->ConnectionList\r
526 //\r
527 NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {\r
a3bcde70
HT
528 Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);\r
529\r
530 if (SOCK_IS_CONNECTED (Socket)) {\r
531 ListenToken->NewChildHandle = Socket->SockHandle;\r
532 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
533\r
534 RemoveEntryList (ListEntry);\r
535\r
536 ASSERT (Socket->Parent != NULL);\r
537\r
538 Socket->Parent->ConnCnt--;\r
539\r
540 DEBUG (\r
c49ca4a2 541 (DEBUG_NET,\r
d1050b9d
MK
542 "SockAccept: Accept a socket, now conncount is %d",\r
543 Socket->Parent->ConnCnt)\r
a3bcde70
HT
544 );\r
545 Socket->Parent = NULL;\r
546\r
547 goto Exit;\r
548 }\r
549 }\r
550\r
551 //\r
552 // Buffer this token for latter incoming connection request\r
553 //\r
554 if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {\r
a3bcde70
HT
555 Status = EFI_OUT_OF_RESOURCES;\r
556 }\r
557\r
558Exit:\r
559 EfiReleaseLock (&(Sock->Lock));\r
560\r
561 return Status;\r
562}\r
563\r
564/**\r
565 Issue a token with data to the socket to send out.\r
566\r
567 @param[in] Sock Pointer to the socket to process the token with\r
568 data.\r
569 @param[in] Token The token with data that needs to send out.\r
570\r
571 @retval EFI_SUCCESS The token processed successfully.\r
572 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
573 socket is closed, or the socket is not in a\r
574 synchronized state , or the token is already in one\r
575 of this socket's lists.\r
576 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
577 finished.\r
578 @retval EFI_NOT_STARTED The socket is not configured.\r
579 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limits.\r
580\r
581**/\r
582EFI_STATUS\r
583SockSend (\r
d1050b9d
MK
584 IN SOCKET *Sock,\r
585 IN VOID *Token\r
a3bcde70
HT
586 )\r
587{\r
588 SOCK_IO_TOKEN *SndToken;\r
589 EFI_EVENT Event;\r
590 UINT32 FreeSpace;\r
591 EFI_TCP4_TRANSMIT_DATA *TxData;\r
592 EFI_STATUS Status;\r
593 SOCK_TOKEN *SockToken;\r
594 UINT32 DataLen;\r
595\r
596 ASSERT (SockStream == Sock->Type);\r
597\r
598 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
599 if (EFI_ERROR (Status)) {\r
a3bcde70 600 DEBUG (\r
c49ca4a2 601 (DEBUG_ERROR,\r
d1050b9d
MK
602 "SockSend: Get the access for socket failed with %r",\r
603 Status)\r
a3bcde70
HT
604 );\r
605\r
606 return EFI_ACCESS_DENIED;\r
607 }\r
608\r
609 if (SOCK_IS_NO_MAPPING (Sock)) {\r
610 Status = EFI_NO_MAPPING;\r
611 goto Exit;\r
612 }\r
613\r
d1050b9d
MK
614 SndToken = (SOCK_IO_TOKEN *)Token;\r
615 TxData = (EFI_TCP4_TRANSMIT_DATA *)SndToken->Packet.TxData;\r
a3bcde70
HT
616\r
617 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
618 Status = EFI_NOT_STARTED;\r
619 goto Exit;\r
620 }\r
621\r
622 if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {\r
a3bcde70
HT
623 Status = EFI_ACCESS_DENIED;\r
624 goto Exit;\r
625 }\r
626\r
627 //\r
628 // check if a token is already in the token buffer\r
629 //\r
630 Event = SndToken->Token.Event;\r
631\r
632 if (SockTokenExisted (Sock, Event)) {\r
633 Status = EFI_ACCESS_DENIED;\r
634 goto Exit;\r
635 }\r
636\r
637 DataLen = TxData->DataLength;\r
638\r
639 //\r
640 // process this sending token now or buffer it only?\r
641 //\r
642 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
643\r
644 if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {\r
a3bcde70
HT
645 SockToken = SockBufferToken (\r
646 Sock,\r
647 &Sock->SndTokenList,\r
648 SndToken,\r
649 DataLen\r
650 );\r
651\r
652 if (NULL == SockToken) {\r
653 Status = EFI_OUT_OF_RESOURCES;\r
654 }\r
655 } else {\r
a3bcde70
HT
656 SockToken = SockBufferToken (\r
657 Sock,\r
658 &Sock->ProcessingSndTokenList,\r
659 SndToken,\r
660 DataLen\r
661 );\r
662\r
663 if (NULL == SockToken) {\r
8fdb4de6 664 DEBUG ((DEBUG_ERROR, "SockSend: Failed to buffer IO token into socket processing SndToken List\n"));\r
a3bcde70
HT
665\r
666 Status = EFI_OUT_OF_RESOURCES;\r
667 goto Exit;\r
668 }\r
669\r
670 Status = SockProcessTcpSndData (Sock, TxData);\r
671\r
672 if (EFI_ERROR (Status)) {\r
8fdb4de6 673 DEBUG ((DEBUG_ERROR, "SockSend: Failed to process Snd Data\n"));\r
a3bcde70
HT
674\r
675 RemoveEntryList (&(SockToken->TokenList));\r
676 FreePool (SockToken);\r
677 }\r
678 }\r
679\r
680Exit:\r
681 EfiReleaseLock (&(Sock->Lock));\r
682 return Status;\r
683}\r
684\r
685/**\r
686 Issue a token to get data from the socket.\r
687\r
688 @param[in] Sock Pointer to the socket to get data from.\r
689 @param[in] Token The token to store the received data from the\r
690 socket.\r
691\r
692 @retval EFI_SUCCESS The token processed successfully.\r
693 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
694 socket is closed, or the socket is not in a\r
695 synchronized state , or the token is already in one\r
696 of this socket's lists.\r
697 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
698 finished.\r
699 @retval EFI_NOT_STARTED The socket is not configured.\r
700 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
701 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
702\r
703**/\r
704EFI_STATUS\r
705SockRcv (\r
d1050b9d
MK
706 IN SOCKET *Sock,\r
707 IN VOID *Token\r
a3bcde70
HT
708 )\r
709{\r
d1050b9d
MK
710 SOCK_IO_TOKEN *RcvToken;\r
711 UINT32 RcvdBytes;\r
712 EFI_STATUS Status;\r
713 EFI_EVENT Event;\r
a3bcde70
HT
714\r
715 ASSERT (SockStream == Sock->Type);\r
716\r
717 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
718 if (EFI_ERROR (Status)) {\r
a3bcde70 719 DEBUG (\r
c49ca4a2 720 (DEBUG_ERROR,\r
d1050b9d
MK
721 "SockRcv: Get the access for socket failed with %r",\r
722 Status)\r
a3bcde70
HT
723 );\r
724\r
725 return EFI_ACCESS_DENIED;\r
726 }\r
727\r
728 if (SOCK_IS_NO_MAPPING (Sock)) {\r
a3bcde70
HT
729 Status = EFI_NO_MAPPING;\r
730 goto Exit;\r
731 }\r
732\r
733 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
734 Status = EFI_NOT_STARTED;\r
735 goto Exit;\r
736 }\r
737\r
738 if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {\r
a3bcde70
HT
739 Status = EFI_ACCESS_DENIED;\r
740 goto Exit;\r
741 }\r
742\r
d1050b9d 743 RcvToken = (SOCK_IO_TOKEN *)Token;\r
a3bcde70
HT
744\r
745 //\r
746 // check if a token is already in the token buffer of this socket\r
747 //\r
748 Event = RcvToken->Token.Event;\r
749 if (SockTokenExisted (Sock, Event)) {\r
750 Status = EFI_ACCESS_DENIED;\r
751 goto Exit;\r
752 }\r
753\r
d1050b9d 754 RcvToken = (SOCK_IO_TOKEN *)Token;\r
a3bcde70
HT
755 RcvdBytes = GET_RCV_DATASIZE (Sock);\r
756\r
757 //\r
758 // check whether an error has happened before\r
759 //\r
760 if (EFI_ABORTED != Sock->SockError) {\r
a3bcde70
HT
761 SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);\r
762 Sock->SockError = EFI_ABORTED;\r
763 goto Exit;\r
764 }\r
765\r
766 //\r
767 // check whether can not receive and there is no any\r
768 // data buffered in Sock->RcvBuffer\r
769 //\r
770 if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {\r
a3bcde70
HT
771 Status = EFI_CONNECTION_FIN;\r
772 goto Exit;\r
773 }\r
774\r
775 if (RcvdBytes != 0) {\r
72a4f34e 776 SockProcessRcvToken (Sock, RcvToken);\r
a3bcde70
HT
777\r
778 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
779 } else {\r
a3bcde70
HT
780 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
781 Status = EFI_OUT_OF_RESOURCES;\r
782 }\r
783 }\r
784\r
785Exit:\r
786 EfiReleaseLock (&(Sock->Lock));\r
787 return Status;\r
788}\r
789\r
790/**\r
791 Reset the socket and its associated protocol control block.\r
792\r
793 @param[in, out] Sock Pointer to the socket to be flushed.\r
794\r
795 @retval EFI_SUCCESS The socket is flushed successfully.\r
796 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
797\r
798**/\r
799EFI_STATUS\r
800SockFlush (\r
d1050b9d 801 IN OUT SOCKET *Sock\r
a3bcde70
HT
802 )\r
803{\r
804 EFI_STATUS Status;\r
805\r
806 ASSERT (SockStream == Sock->Type);\r
807\r
808 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
809 if (EFI_ERROR (Status)) {\r
a3bcde70 810 DEBUG (\r
c49ca4a2 811 (DEBUG_ERROR,\r
d1050b9d
MK
812 "SockFlush: Get the access for socket failed with %r",\r
813 Status)\r
a3bcde70
HT
814 );\r
815\r
816 return EFI_ACCESS_DENIED;\r
817 }\r
818\r
819 if (!SOCK_IS_CONFIGURED (Sock)) {\r
a3bcde70
HT
820 Status = EFI_ACCESS_DENIED;\r
821 goto Exit;\r
822 }\r
823\r
824 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
825 if (EFI_ERROR (Status)) {\r
a3bcde70 826 DEBUG (\r
c49ca4a2 827 (DEBUG_ERROR,\r
d1050b9d
MK
828 "SockFlush: Protocol failed handling SOCK_FLUSH with %r",\r
829 Status)\r
a3bcde70
HT
830 );\r
831\r
832 goto Exit;\r
833 }\r
834\r
835 SOCK_ERROR (Sock, EFI_ABORTED);\r
836 SockConnFlush (Sock);\r
837 SockSetState (Sock, SO_CLOSED);\r
838\r
839 Sock->ConfigureState = SO_UNCONFIGURED;\r
840\r
841Exit:\r
842 EfiReleaseLock (&(Sock->Lock));\r
843 return Status;\r
844}\r
845\r
846/**\r
847 Close or abort the socket associated connection.\r
848\r
849 @param[in, out] Sock Pointer to the socket of the connection to close\r
850 or abort.\r
851 @param[in] Token The token for a close operation.\r
852 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.\r
853\r
854 @retval EFI_SUCCESS The close or abort operation initialized\r
855 successfully.\r
856 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
857 socket is closed, or the socket is not in a\r
858 synchronized state , or the token is already in one\r
859 of this socket's lists.\r
860 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
861 finished.\r
862 @retval EFI_NOT_STARTED The socket is not configured.\r
863\r
864**/\r
865EFI_STATUS\r
866SockClose (\r
d1050b9d
MK
867 IN OUT SOCKET *Sock,\r
868 IN VOID *Token,\r
869 IN BOOLEAN OnAbort\r
a3bcde70
HT
870 )\r
871{\r
872 EFI_STATUS Status;\r
873 EFI_EVENT Event;\r
874\r
875 ASSERT (SockStream == Sock->Type);\r
876\r
877 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
878 if (EFI_ERROR (Status)) {\r
879 DEBUG (\r
c49ca4a2 880 (DEBUG_ERROR,\r
d1050b9d
MK
881 "SockClose: Get the access for socket failed with %r",\r
882 Status)\r
a3bcde70
HT
883 );\r
884\r
885 return EFI_ACCESS_DENIED;\r
886 }\r
887\r
888 if (SOCK_IS_NO_MAPPING (Sock)) {\r
889 Status = EFI_NO_MAPPING;\r
890 goto Exit;\r
891 }\r
892\r
893 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
894 Status = EFI_NOT_STARTED;\r
895 goto Exit;\r
896 }\r
897\r
898 if (SOCK_IS_DISCONNECTING (Sock)) {\r
899 Status = EFI_ACCESS_DENIED;\r
900 goto Exit;\r
901 }\r
902\r
d1050b9d 903 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
904\r
905 if (SockTokenExisted (Sock, Event)) {\r
906 Status = EFI_ACCESS_DENIED;\r
907 goto Exit;\r
908 }\r
909\r
910 Sock->CloseToken = Token;\r
911 SockSetState (Sock, SO_DISCONNECTING);\r
912\r
913 if (OnAbort) {\r
914 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
915 } else {\r
916 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
917 }\r
918\r
919Exit:\r
920 EfiReleaseLock (&(Sock->Lock));\r
921 return Status;\r
922}\r
923\r
5ffe214a
JW
924/**\r
925 Abort the socket associated connection, listen, transmission or receive request.\r
926\r
927 @param[in, out] Sock Pointer to the socket to abort.\r
928 @param[in] Token Pointer to a token that has been issued by\r
929 Connect(), Accept(), Transmit() or Receive(). If\r
930 NULL, all pending tokens issued by the four\r
931 functions listed above will be aborted.\r
932\r
933 @retval EFI_UNSUPPORTED The operation is not supported in the current\r
934 implementation.\r
935**/\r
936EFI_STATUS\r
937SockCancel (\r
938 IN OUT SOCKET *Sock,\r
939 IN VOID *Token\r
f75a7f56 940 )\r
5ffe214a 941{\r
d1050b9d 942 EFI_STATUS Status;\r
5ffe214a 943\r
d1050b9d 944 Status = EFI_SUCCESS;\r
5ffe214a
JW
945\r
946 ASSERT (SockStream == Sock->Type);\r
947\r
948 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
949 if (EFI_ERROR (Status)) {\r
950 DEBUG (\r
c49ca4a2 951 (DEBUG_ERROR,\r
d1050b9d
MK
952 "SockCancel: Get the access for socket failed with %r",\r
953 Status)\r
5ffe214a
JW
954 );\r
955\r
956 return EFI_ACCESS_DENIED;\r
957 }\r
958\r
959 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
960 Status = EFI_NOT_STARTED;\r
961 goto Exit;\r
962 }\r
f75a7f56 963\r
5ffe214a
JW
964 //\r
965 // 1. Check ConnectionToken.\r
966 //\r
d1050b9d 967 if ((Token == NULL) || ((SOCK_COMPLETION_TOKEN *)Token == Sock->ConnectionToken)) {\r
5ffe214a
JW
968 if (Sock->ConnectionToken != NULL) {\r
969 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);\r
970 Sock->ConnectionToken = NULL;\r
971 }\r
972\r
973 if (Token != NULL) {\r
974 Status = EFI_SUCCESS;\r
975 goto Exit;\r
976 }\r
977 }\r
978\r
979 //\r
980 // 2. Check ListenTokenList.\r
981 //\r
982 Status = SockCancelToken (Token, &Sock->ListenTokenList);\r
d1050b9d 983 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
984 goto Exit;\r
985 }\r
986\r
987 //\r
988 // 3. Check RcvTokenList.\r
989 //\r
990 Status = SockCancelToken (Token, &Sock->RcvTokenList);\r
d1050b9d 991 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
992 goto Exit;\r
993 }\r
f75a7f56 994\r
5ffe214a
JW
995 //\r
996 // 4. Check SndTokenList.\r
997 //\r
998 Status = SockCancelToken (Token, &Sock->SndTokenList);\r
d1050b9d 999 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
1000 goto Exit;\r
1001 }\r
1002\r
1003 //\r
1004 // 5. Check ProcessingSndTokenList.\r
1005 //\r
1006 Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);\r
f75a7f56 1007\r
5ffe214a
JW
1008Exit:\r
1009 EfiReleaseLock (&(Sock->Lock));\r
1010 return Status;\r
1011}\r
1012\r
a3bcde70
HT
1013/**\r
1014 Get the mode data of the low layer protocol.\r
1015\r
1016 @param[in] Sock Pointer to the socket to get mode data from.\r
1017 @param[in, out] Mode Pointer to the data to store the low layer mode\r
1018 information.\r
1019\r
1020 @retval EFI_SUCCESS The mode data was obtained successfully.\r
1021 @retval EFI_NOT_STARTED The socket is not configured.\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025SockGetMode (\r
d1050b9d
MK
1026 IN SOCKET *Sock,\r
1027 IN OUT VOID *Mode\r
a3bcde70
HT
1028 )\r
1029{\r
1030 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
1031}\r
1032\r
a3bcde70
HT
1033/**\r
1034 Add or remove route information in IP route table associated\r
1035 with this socket.\r
1036\r
1037 @param[in] Sock Pointer to the socket associated with the IP route\r
1038 table to operate on.\r
1039 @param[in] RouteInfo Pointer to the route information to be processed.\r
1040\r
1041 @retval EFI_SUCCESS The route table updated successfully.\r
1042 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
1043 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
1044 finished.\r
1045 @retval EFI_NOT_STARTED The socket is not configured.\r
1046\r
1047**/\r
1048EFI_STATUS\r
1049SockRoute (\r
d1050b9d
MK
1050 IN SOCKET *Sock,\r
1051 IN VOID *RouteInfo\r
a3bcde70
HT
1052 )\r
1053{\r
1054 EFI_STATUS Status;\r
1055\r
1056 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
1057 if (EFI_ERROR (Status)) {\r
1058 DEBUG (\r
c49ca4a2 1059 (DEBUG_ERROR,\r
d1050b9d
MK
1060 "SockRoute: Get the access for socket failed with %r",\r
1061 Status)\r
a3bcde70
HT
1062 );\r
1063\r
1064 return EFI_ACCESS_DENIED;\r
1065 }\r
1066\r
1067 if (SOCK_IS_NO_MAPPING (Sock)) {\r
1068 Status = EFI_NO_MAPPING;\r
1069 goto Exit;\r
1070 }\r
1071\r
1072 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
1073 Status = EFI_NOT_STARTED;\r
1074 goto Exit;\r
1075 }\r
1076\r
1077 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
1078\r
1079Exit:\r
1080 EfiReleaseLock (&(Sock->Lock));\r
1081 return Status;\r
1082}\r