]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiTcp4Io.c
Fix a minor GUID format issue.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiTcp4Io.c
CommitLineData
12618416 1/** @file\r
2 The wrap of TCP/IP Socket interface\r
6a690e23 3\r
7a444476 4Copyright (c) 2004 - 2007, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
6a690e23 12\r
13Module Name:\r
14\r
15 IScsiTcp4Io.c\r
16\r
17Abstract:\r
12618416 18 The wrap of TCP/IP Socket interface\r
6a690e23 19\r
12618416 20**/\r
6a690e23 21\r
22#include "IScsiImpl.h"\r
23\r
12618416 24/**\r
25 The common notify function associated with various Tcp4Io events. \r
26\r
27 @param Event[in] The event signaled.\r
28\r
29 @param Contect[in] The context.\r
30\r
31 @retval None.\r
32\r
33**/\r
6a690e23 34VOID\r
35EFIAPI\r
36Tcp4IoCommonNotify (\r
37 IN EFI_EVENT Event,\r
38 IN VOID *Context\r
39 )\r
12618416 40{\r
41 *((BOOLEAN *) Context) = TRUE;\r
42}\r
6a690e23 43\r
12618416 44/**\r
45 Create a TCP socket with the specified configuration data. \r
6a690e23 46\r
12618416 47 @param Image[in] The handle of the driver image.\r
6a690e23 48\r
12618416 49 @param Controller[in] The handle of the controller.\r
6a690e23 50\r
12618416 51 @param ConfigData[in] The Tcp4 configuration data.\r
6a690e23 52\r
12618416 53 @param Tcp4Io[in] The Tcp4Io.\r
54 \r
55 @retval EFI_SUCCESS The TCP socket is created and configured.\r
6a690e23 56\r
12618416 57 @retval Other Failed to create the TCP socket or configure it.\r
6a690e23 58\r
12618416 59**/\r
6a690e23 60EFI_STATUS\r
61Tcp4IoCreateSocket (\r
62 IN EFI_HANDLE Image,\r
63 IN EFI_HANDLE Controller,\r
64 IN TCP4_IO_CONFIG_DATA *ConfigData,\r
65 IN TCP4_IO *Tcp4Io\r
66 )\r
6a690e23 67{\r
68 EFI_STATUS Status;\r
69 EFI_TCP4_PROTOCOL *Tcp4;\r
70 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;\r
71 EFI_TCP4_OPTION ControlOption;\r
72 EFI_TCP4_ACCESS_POINT *AccessPoint;\r
73\r
74 Tcp4Io->Handle = NULL;\r
75 Tcp4Io->ConnToken.CompletionToken.Event = NULL;\r
76 Tcp4Io->TxToken.CompletionToken.Event = NULL;\r
77 Tcp4Io->RxToken.CompletionToken.Event = NULL;\r
78 Tcp4Io->CloseToken.CompletionToken.Event = NULL;\r
79 Tcp4 = NULL;\r
80\r
81 //\r
82 // Create the TCP4 child instance and get the TCP4 protocol.\r
83 //\r
84 Status = NetLibCreateServiceChild (\r
85 Controller,\r
86 Image,\r
87 &gEfiTcp4ServiceBindingProtocolGuid,\r
88 &Tcp4Io->Handle\r
89 );\r
90 if (EFI_ERROR (Status)) {\r
91 return Status;\r
92 }\r
93\r
94 Status = gBS->OpenProtocol (\r
95 Tcp4Io->Handle,\r
96 &gEfiTcp4ProtocolGuid,\r
97 (VOID **)&Tcp4Io->Tcp4,\r
98 Image,\r
99 Controller,\r
100 EFI_OPEN_PROTOCOL_BY_DRIVER\r
101 );\r
102 if (EFI_ERROR (Status)) {\r
103 goto ON_ERROR;\r
104 }\r
105\r
106 Tcp4Io->Image = Image;\r
107 Tcp4Io->Controller = Controller;\r
108 Tcp4 = Tcp4Io->Tcp4;\r
109\r
110 //\r
111 // Set the configuration parameters.\r
112 //\r
113 ControlOption.ReceiveBufferSize = 0x200000;\r
114 ControlOption.SendBufferSize = 0x200000;\r
115 ControlOption.MaxSynBackLog = 0;\r
116 ControlOption.ConnectionTimeout = 0;\r
117 ControlOption.DataRetries = 6;\r
118 ControlOption.FinTimeout = 0;\r
119 ControlOption.TimeWaitTimeout = 0;\r
120 ControlOption.KeepAliveProbes = 4;\r
121 ControlOption.KeepAliveTime = 0;\r
122 ControlOption.KeepAliveInterval = 0;\r
123 ControlOption.EnableNagle = FALSE;\r
124 ControlOption.EnableTimeStamp = FALSE;\r
125 ControlOption.EnableWindowScaling = TRUE;\r
126 ControlOption.EnableSelectiveAck = FALSE;\r
127 ControlOption.EnablePathMtuDiscovery = FALSE;\r
128\r
129 Tcp4ConfigData.TypeOfService = 8;\r
130 Tcp4ConfigData.TimeToLive = 255;\r
131 Tcp4ConfigData.ControlOption = &ControlOption;\r
132\r
133 AccessPoint = &Tcp4ConfigData.AccessPoint;\r
134\r
135 AccessPoint->UseDefaultAddress = FALSE;\r
136 AccessPoint->StationPort = 0;\r
137 AccessPoint->RemotePort = ConfigData->RemotePort;\r
138 AccessPoint->ActiveFlag = TRUE;\r
139\r
e48e37fc 140 CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
141 CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
142 CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));\r
6a690e23 143\r
144 //\r
145 // Configure the TCP4 protocol.\r
146 //\r
147 Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);\r
148 if (EFI_ERROR (Status)) {\r
149 goto ON_ERROR;\r
150 }\r
151\r
152 if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {\r
153 //\r
154 // the gateway is not zero, add the default route by hand\r
155 //\r
156 Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);\r
157 if (EFI_ERROR (Status)) {\r
158 goto ON_ERROR;\r
159 }\r
160 }\r
161 //\r
162 // Create events for variuos asynchronous operations.\r
163 //\r
164 Status = gBS->CreateEvent (\r
165 EFI_EVENT_NOTIFY_SIGNAL,\r
e48e37fc 166 TPL_NOTIFY,\r
6a690e23 167 Tcp4IoCommonNotify,\r
168 &Tcp4Io->IsConnDone,\r
169 &Tcp4Io->ConnToken.CompletionToken.Event\r
170 );\r
171 if (EFI_ERROR (Status)) {\r
172 goto ON_ERROR;\r
173 }\r
174\r
175 Status = gBS->CreateEvent (\r
176 EFI_EVENT_NOTIFY_SIGNAL,\r
e48e37fc 177 TPL_NOTIFY,\r
6a690e23 178 Tcp4IoCommonNotify,\r
179 &Tcp4Io->IsTxDone,\r
180 &Tcp4Io->TxToken.CompletionToken.Event\r
181 );\r
182 if (EFI_ERROR (Status)) {\r
183 goto ON_ERROR;\r
184 }\r
185\r
186 Status = gBS->CreateEvent (\r
187 EFI_EVENT_NOTIFY_SIGNAL,\r
e48e37fc 188 TPL_NOTIFY,\r
6a690e23 189 Tcp4IoCommonNotify,\r
190 &Tcp4Io->IsRxDone,\r
191 &Tcp4Io->RxToken.CompletionToken.Event\r
192 );\r
193 if (EFI_ERROR (Status)) {\r
194 goto ON_ERROR;\r
195 }\r
196\r
197 Status = gBS->CreateEvent (\r
198 EFI_EVENT_NOTIFY_SIGNAL,\r
e48e37fc 199 TPL_NOTIFY,\r
6a690e23 200 Tcp4IoCommonNotify,\r
201 &Tcp4Io->IsCloseDone,\r
202 &Tcp4Io->CloseToken.CompletionToken.Event\r
203 );\r
204 if (EFI_ERROR (Status)) {\r
205 goto ON_ERROR;\r
206 }\r
207\r
208 Tcp4Io->IsTxDone = FALSE;\r
209 Tcp4Io->IsRxDone = FALSE;\r
210\r
211 return EFI_SUCCESS;\r
212\r
213ON_ERROR:\r
214\r
215 if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {\r
216 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
217 }\r
218\r
219 if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {\r
220 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
221 }\r
222\r
223 if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {\r
224 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
225 }\r
226\r
227 if (Tcp4 != NULL) {\r
228 Tcp4->Configure (Tcp4, NULL);\r
229\r
230 gBS->CloseProtocol (\r
231 Tcp4Io->Handle,\r
232 &gEfiTcp4ProtocolGuid,\r
233 Image,\r
234 Controller\r
235 );\r
236 }\r
237\r
238 NetLibDestroyServiceChild (\r
239 Controller,\r
240 Image,\r
241 &gEfiTcp4ServiceBindingProtocolGuid,\r
242 Tcp4Io->Handle\r
243 );\r
244\r
245 return Status;\r
246}\r
247\r
12618416 248/**\r
6a690e23 249 Destroy the socket. \r
250\r
12618416 251 @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds.\r
6a690e23 252\r
12618416 253 @retval None.\r
6a690e23 254\r
12618416 255**/\r
256VOID\r
257Tcp4IoDestroySocket (\r
258 IN TCP4_IO *Tcp4Io\r
259 )\r
6a690e23 260{\r
261 EFI_TCP4_PROTOCOL *Tcp4;\r
262\r
263 Tcp4 = Tcp4Io->Tcp4;\r
264\r
265 Tcp4->Configure (Tcp4, NULL);\r
266\r
267 gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);\r
268 gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);\r
269 gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);\r
270\r
271 gBS->CloseProtocol (\r
272 Tcp4Io->Handle,\r
273 &gEfiTcp4ProtocolGuid,\r
274 Tcp4Io->Image,\r
275 Tcp4Io->Controller\r
276 );\r
277\r
278 NetLibDestroyServiceChild (\r
279 Tcp4Io->Controller,\r
280 Tcp4Io->Image,\r
281 &gEfiTcp4ServiceBindingProtocolGuid,\r
282 Tcp4Io->Handle\r
283 );\r
284}\r
285\r
12618416 286/**\r
6a690e23 287 Connect to the other endpoint of the TCP socket.\r
288\r
12618416 289 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.\r
6a690e23 290\r
12618416 291 @param Timeout[in] The time to wait for connection done.\r
6a690e23 292\r
12618416 293 @retval None.\r
6a690e23 294\r
12618416 295**/\r
296EFI_STATUS\r
297Tcp4IoConnect (\r
298 IN TCP4_IO *Tcp4Io,\r
299 IN EFI_EVENT Timeout\r
300 )\r
6a690e23 301{\r
302 EFI_TCP4_PROTOCOL *Tcp4;\r
303 EFI_STATUS Status;\r
304\r
305 Tcp4Io->IsConnDone = FALSE;\r
306 Tcp4 = Tcp4Io->Tcp4;\r
307 Status = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);\r
308 if (EFI_ERROR (Status)) {\r
309 return Status;\r
310 }\r
311\r
312 while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
313 Tcp4->Poll (Tcp4);\r
314 }\r
315\r
316 if (!Tcp4Io->IsConnDone) {\r
317 Status = EFI_TIMEOUT;\r
318 } else {\r
319 Status = Tcp4Io->ConnToken.CompletionToken.Status;\r
320 }\r
321\r
322 return Status;\r
323}\r
324\r
12618416 325/**\r
6a690e23 326 Reset the socket.\r
327\r
12618416 328 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.\r
6a690e23 329\r
12618416 330 @retval None.\r
6a690e23 331\r
12618416 332**/\r
333VOID\r
334Tcp4IoReset (\r
335 IN TCP4_IO *Tcp4Io\r
336 )\r
6a690e23 337{\r
338 EFI_STATUS Status;\r
339 EFI_TCP4_PROTOCOL *Tcp4;\r
340\r
341 Tcp4Io->CloseToken.AbortOnClose = TRUE;\r
342 Tcp4Io->IsCloseDone = FALSE;\r
343\r
344 Tcp4 = Tcp4Io->Tcp4;\r
345 Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);\r
346 if (EFI_ERROR (Status)) {\r
347 return ;\r
348 }\r
349\r
350 while (!Tcp4Io->IsCloseDone) {\r
351 Tcp4->Poll (Tcp4);\r
352 }\r
353}\r
354\r
12618416 355/**\r
6a690e23 356 Transmit the Packet to the other endpoint of the socket.\r
357\r
12618416 358 @param Tcp4Io[in] The Tcp4Io wrapping the TCP socket.\r
6a690e23 359\r
12618416 360 @param Packet[in] The packet to transmit\r
6a690e23 361\r
12618416 362 @retval EFI_SUCCESS The packet is trasmitted.\r
6a690e23 363\r
12618416 364 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 365\r
12618416 366**/\r
367EFI_STATUS\r
368Tcp4IoTransmit (\r
369 IN TCP4_IO *Tcp4Io,\r
370 IN NET_BUF *Packet\r
371 )\r
6a690e23 372{\r
373 EFI_TCP4_TRANSMIT_DATA *TxData;\r
374 EFI_TCP4_PROTOCOL *Tcp4;\r
375 EFI_STATUS Status;\r
376\r
e48e37fc 377 TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));\r
6a690e23 378 if (TxData == NULL) {\r
379 return EFI_OUT_OF_RESOURCES;\r
380 }\r
381\r
382 TxData->Push = TRUE;\r
383 TxData->Urgent = FALSE;\r
384 TxData->DataLength = Packet->TotalSize;\r
385\r
386 //\r
387 // Build the fragment table.\r
388 //\r
389 TxData->FragmentCount = Packet->BlockOpNum;\r
390 NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);\r
391\r
392 Tcp4Io->TxToken.Packet.TxData = TxData;\r
393\r
394 //\r
395 // Trasnmit the packet.\r
396 //\r
397 Tcp4 = Tcp4Io->Tcp4;\r
398 Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);\r
399 if (EFI_ERROR (Status)) {\r
400 goto ON_EXIT;\r
401 }\r
402\r
403 while (!Tcp4Io->IsTxDone) {\r
404 Tcp4->Poll (Tcp4);\r
405 }\r
406\r
407 Tcp4Io->IsTxDone = FALSE;\r
408\r
409 Status = Tcp4Io->TxToken.CompletionToken.Status;\r
410\r
411ON_EXIT:\r
412\r
e48e37fc 413 gBS->FreePool (TxData);\r
6a690e23 414\r
415 return Status;\r
416}\r
417\r
12618416 418/**\r
419 Receive data from the socket.\r
6a690e23 420\r
12618416 421 @param Tcp4Io[in] The Tcp4Io which wraps the socket to be destroyeds.\r
6a690e23 422\r
12618416 423 @param Packet[in] The buffer to hold the data copy from the soket rx buffer.\r
6a690e23 424\r
12618416 425 @param AsyncMode[in] Is this receive asyncronous or not.\r
6a690e23 426\r
12618416 427 @param Timeout[in] The time to wait for receiving the amount of data the Packet\r
428 can hold.\r
6a690e23 429\r
12618416 430 @retval EFI_SUCCESS The required amount of data is received from the socket.\r
6a690e23 431\r
12618416 432 @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.\r
6a690e23 433\r
12618416 434 @retval EFI_TIMEOUT Failed to receive the required amount of data in the\r
435 specified time period.\r
436\r
437**/\r
438EFI_STATUS\r
439Tcp4IoReceive (\r
440 IN TCP4_IO *Tcp4Io,\r
441 IN NET_BUF *Packet,\r
442 IN BOOLEAN AsyncMode,\r
443 IN EFI_EVENT Timeout\r
444 )\r
6a690e23 445{\r
446 EFI_TCP4_PROTOCOL *Tcp4;\r
447 EFI_TCP4_RECEIVE_DATA RxData;\r
448 EFI_STATUS Status;\r
449 NET_FRAGMENT *Fragment;\r
450 UINT32 FragmentCount;\r
451 UINT32 CurrentFragment;\r
452\r
453 FragmentCount = Packet->BlockOpNum;\r
e48e37fc 454 Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
6a690e23 455 if (Fragment == NULL) {\r
456 return EFI_OUT_OF_RESOURCES;\r
457 }\r
458 //\r
459 // Build the fragment table.\r
460 //\r
461 NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
462\r
463 RxData.FragmentCount = 1;\r
464 Tcp4Io->RxToken.Packet.RxData = &RxData;\r
465 CurrentFragment = 0;\r
466 Tcp4 = Tcp4Io->Tcp4;\r
467 Status = EFI_SUCCESS;\r
468\r
469 while (CurrentFragment < FragmentCount) {\r
470 RxData.DataLength = Fragment[CurrentFragment].Len;\r
471 RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
472 RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
473\r
474 Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);\r
475 if (EFI_ERROR (Status)) {\r
476 goto ON_EXIT;\r
477 }\r
478\r
479 while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
480 //\r
481 // Poll until some data is received or something error happens.\r
482 //\r
483 Tcp4->Poll (Tcp4);\r
484 }\r
485\r
486 if (!Tcp4Io->IsRxDone) {\r
487 //\r
488 // Timeout occurs, cancel the receive request.\r
489 //\r
490 Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);\r
491\r
492 Status = EFI_TIMEOUT;\r
493 goto ON_EXIT;\r
494 } else {\r
495 Tcp4Io->IsRxDone = FALSE;\r
496 }\r
497\r
498 if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {\r
499 Status = Tcp4Io->RxToken.CompletionToken.Status;\r
500 goto ON_EXIT;\r
501 }\r
502\r
503 Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;\r
504 if (Fragment[CurrentFragment].Len == 0) {\r
505 CurrentFragment++;\r
506 } else {\r
507 Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;\r
508 }\r
509 }\r
510\r
511ON_EXIT:\r
512\r
e48e37fc 513 gBS->FreePool (Fragment);\r
6a690e23 514\r
515 return Status;\r
516}\r