1 | /** @file
|
---|
2 | This library is used to share code between UEFI network stack modules.
|
---|
3 | It provides the helper routines to access TCP service.
|
---|
4 |
|
---|
5 | Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
|
---|
6 | This program and the accompanying materials
|
---|
7 | are licensed and made available under the terms and conditions of the BSD License
|
---|
8 | which accompanies this distribution. The full text of the license may be found at<BR>
|
---|
9 | http://opensource.org/licenses/bsd-license.php
|
---|
10 |
|
---|
11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
13 |
|
---|
14 | **/
|
---|
15 |
|
---|
16 | #include <Uefi.h>
|
---|
17 |
|
---|
18 | #include <Library/TcpIoLib.h>
|
---|
19 | #include <Library/BaseLib.h>
|
---|
20 | #include <Library/DebugLib.h>
|
---|
21 | #include <Library/UefiBootServicesTableLib.h>
|
---|
22 | #include <Library/MemoryAllocationLib.h>
|
---|
23 | #include <Library/BaseMemoryLib.h>
|
---|
24 |
|
---|
25 | /**
|
---|
26 | The common notify function associated with various TcpIo events.
|
---|
27 |
|
---|
28 | @param[in] Event The event signaled.
|
---|
29 | @param[in] Context The context.
|
---|
30 |
|
---|
31 | **/
|
---|
32 | VOID
|
---|
33 | EFIAPI
|
---|
34 | TcpIoCommonNotify (
|
---|
35 | IN EFI_EVENT Event,
|
---|
36 | IN VOID *Context
|
---|
37 | )
|
---|
38 | {
|
---|
39 | if ((Event == NULL) || (Context == NULL)) {
|
---|
40 | return ;
|
---|
41 | }
|
---|
42 |
|
---|
43 | *((BOOLEAN *) Context) = TRUE;
|
---|
44 | }
|
---|
45 |
|
---|
46 | /**
|
---|
47 | The internal function for delay configuring TCP6 when IP6 driver is still in DAD.
|
---|
48 |
|
---|
49 | @param[in] Tcp6 The EFI_TCP6_PROTOCOL protocol instance.
|
---|
50 | @param[in] Tcp6ConfigData The Tcp6 configuration data.
|
---|
51 |
|
---|
52 | @retval EFI_SUCCESS The operational settings successfully
|
---|
53 | completed.
|
---|
54 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
55 | @retval Others Failed to finish the operation.
|
---|
56 |
|
---|
57 | **/
|
---|
58 | EFI_STATUS
|
---|
59 | TcpIoGetMapping (
|
---|
60 | IN EFI_TCP6_PROTOCOL *Tcp6,
|
---|
61 | IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData
|
---|
62 | )
|
---|
63 | {
|
---|
64 | EFI_STATUS Status;
|
---|
65 | EFI_EVENT Event;
|
---|
66 |
|
---|
67 | if ((Tcp6 == NULL) || (Tcp6ConfigData == NULL)) {
|
---|
68 | return EFI_INVALID_PARAMETER;
|
---|
69 | }
|
---|
70 |
|
---|
71 | Event = NULL;
|
---|
72 | Status = gBS->CreateEvent (
|
---|
73 | EVT_TIMER,
|
---|
74 | TPL_CALLBACK,
|
---|
75 | NULL,
|
---|
76 | NULL,
|
---|
77 | &Event
|
---|
78 | );
|
---|
79 | if (EFI_ERROR (Status)) {
|
---|
80 | goto ON_EXIT;
|
---|
81 | }
|
---|
82 |
|
---|
83 | Status = gBS->SetTimer (
|
---|
84 | Event,
|
---|
85 | TimerRelative,
|
---|
86 | TCP_GET_MAPPING_TIMEOUT
|
---|
87 | );
|
---|
88 |
|
---|
89 | if (EFI_ERROR (Status)) {
|
---|
90 | goto ON_EXIT;
|
---|
91 | }
|
---|
92 |
|
---|
93 | while (EFI_ERROR (gBS->CheckEvent (Event))) {
|
---|
94 |
|
---|
95 | Tcp6->Poll (Tcp6);
|
---|
96 |
|
---|
97 | Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);
|
---|
98 |
|
---|
99 | if (!EFI_ERROR (Status)) {
|
---|
100 | break;
|
---|
101 | }
|
---|
102 | }
|
---|
103 |
|
---|
104 | ON_EXIT:
|
---|
105 |
|
---|
106 | if (Event != NULL) {
|
---|
107 | gBS->CloseEvent (Event);
|
---|
108 | }
|
---|
109 |
|
---|
110 | return Status;
|
---|
111 | }
|
---|
112 |
|
---|
113 | /**
|
---|
114 | Create a TCP socket with the specified configuration data.
|
---|
115 |
|
---|
116 | @param[in] Image The handle of the driver image.
|
---|
117 | @param[in] Controller The handle of the controller.
|
---|
118 | @param[in] TcpVersion The version of Tcp, TCP_VERSION_4 or TCP_VERSION_6.
|
---|
119 | @param[in] ConfigData The Tcp configuration data.
|
---|
120 | @param[out] TcpIo The TcpIo.
|
---|
121 |
|
---|
122 | @retval EFI_SUCCESS The TCP socket is created and configured.
|
---|
123 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
124 | @retval EFI_UNSUPPORTED One or more of the control options are not
|
---|
125 | supported in the implementation.
|
---|
126 | @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
---|
127 | @retval Others Failed to create the TCP socket or configure it.
|
---|
128 |
|
---|
129 | **/
|
---|
130 | EFI_STATUS
|
---|
131 | EFIAPI
|
---|
132 | TcpIoCreateSocket (
|
---|
133 | IN EFI_HANDLE Image,
|
---|
134 | IN EFI_HANDLE Controller,
|
---|
135 | IN UINT8 TcpVersion,
|
---|
136 | IN TCP_IO_CONFIG_DATA *ConfigData,
|
---|
137 | OUT TCP_IO *TcpIo
|
---|
138 | )
|
---|
139 | {
|
---|
140 | EFI_STATUS Status;
|
---|
141 | EFI_EVENT Event;
|
---|
142 | EFI_GUID *ServiceBindingGuid;
|
---|
143 | EFI_GUID *ProtocolGuid;
|
---|
144 | VOID **Interface;
|
---|
145 | EFI_TCP4_OPTION ControlOption;
|
---|
146 | EFI_TCP4_CONFIG_DATA Tcp4ConfigData;
|
---|
147 | EFI_TCP4_ACCESS_POINT *AccessPoint4;
|
---|
148 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
149 | EFI_TCP6_CONFIG_DATA Tcp6ConfigData;
|
---|
150 | EFI_TCP6_ACCESS_POINT *AccessPoint6;
|
---|
151 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
152 | EFI_TCP4_RECEIVE_DATA *RxData;
|
---|
153 |
|
---|
154 | if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (TcpIo == NULL)) {
|
---|
155 | return EFI_INVALID_PARAMETER;
|
---|
156 | }
|
---|
157 |
|
---|
158 | Tcp4 = NULL;
|
---|
159 | Tcp6 = NULL;
|
---|
160 |
|
---|
161 | ZeroMem (TcpIo, sizeof (TCP_IO));
|
---|
162 |
|
---|
163 | if (TcpVersion == TCP_VERSION_4) {
|
---|
164 | ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
|
---|
165 | ProtocolGuid = &gEfiTcp4ProtocolGuid;
|
---|
166 | Interface = (VOID **) (&TcpIo->Tcp.Tcp4);
|
---|
167 | } else if (TcpVersion == TCP_VERSION_6) {
|
---|
168 | ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
|
---|
169 | ProtocolGuid = &gEfiTcp6ProtocolGuid;
|
---|
170 | Interface = (VOID **) (&TcpIo->Tcp.Tcp6);
|
---|
171 | } else {
|
---|
172 | return EFI_UNSUPPORTED;
|
---|
173 | }
|
---|
174 |
|
---|
175 | TcpIo->TcpVersion = TcpVersion;
|
---|
176 |
|
---|
177 | //
|
---|
178 | // Create the TCP child instance and get the TCP protocol.
|
---|
179 | //
|
---|
180 | Status = NetLibCreateServiceChild (
|
---|
181 | Controller,
|
---|
182 | Image,
|
---|
183 | ServiceBindingGuid,
|
---|
184 | &TcpIo->Handle
|
---|
185 | );
|
---|
186 | if (EFI_ERROR (Status)) {
|
---|
187 | return Status;
|
---|
188 | }
|
---|
189 |
|
---|
190 | Status = gBS->OpenProtocol (
|
---|
191 | TcpIo->Handle,
|
---|
192 | ProtocolGuid,
|
---|
193 | Interface,
|
---|
194 | Image,
|
---|
195 | Controller,
|
---|
196 | EFI_OPEN_PROTOCOL_BY_DRIVER
|
---|
197 | );
|
---|
198 | if (EFI_ERROR (Status) || (*Interface == NULL)) {
|
---|
199 | goto ON_ERROR;
|
---|
200 | }
|
---|
201 |
|
---|
202 | if (TcpVersion == TCP_VERSION_4) {
|
---|
203 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
204 | } else {
|
---|
205 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
206 | }
|
---|
207 |
|
---|
208 | TcpIo->Image = Image;
|
---|
209 | TcpIo->Controller = Controller;
|
---|
210 |
|
---|
211 | //
|
---|
212 | // Set the configuration parameters.
|
---|
213 | //
|
---|
214 | ControlOption.ReceiveBufferSize = 0x200000;
|
---|
215 | ControlOption.SendBufferSize = 0x200000;
|
---|
216 | ControlOption.MaxSynBackLog = 0;
|
---|
217 | ControlOption.ConnectionTimeout = 0;
|
---|
218 | ControlOption.DataRetries = 6;
|
---|
219 | ControlOption.FinTimeout = 0;
|
---|
220 | ControlOption.TimeWaitTimeout = 0;
|
---|
221 | ControlOption.KeepAliveProbes = 4;
|
---|
222 | ControlOption.KeepAliveTime = 0;
|
---|
223 | ControlOption.KeepAliveInterval = 0;
|
---|
224 | ControlOption.EnableNagle = FALSE;
|
---|
225 | ControlOption.EnableTimeStamp = FALSE;
|
---|
226 | ControlOption.EnableWindowScaling = TRUE;
|
---|
227 | ControlOption.EnableSelectiveAck = FALSE;
|
---|
228 | ControlOption.EnablePathMtuDiscovery = FALSE;
|
---|
229 |
|
---|
230 | if (TcpVersion == TCP_VERSION_4) {
|
---|
231 | Tcp4ConfigData.TypeOfService = 8;
|
---|
232 | Tcp4ConfigData.TimeToLive = 255;
|
---|
233 | Tcp4ConfigData.ControlOption = &ControlOption;
|
---|
234 |
|
---|
235 | AccessPoint4 = &Tcp4ConfigData.AccessPoint;
|
---|
236 |
|
---|
237 | ZeroMem (AccessPoint4, sizeof (EFI_TCP4_ACCESS_POINT));
|
---|
238 | AccessPoint4->StationPort = ConfigData->Tcp4IoConfigData.StationPort;
|
---|
239 | AccessPoint4->RemotePort = ConfigData->Tcp4IoConfigData.RemotePort;
|
---|
240 | AccessPoint4->ActiveFlag = ConfigData->Tcp4IoConfigData.ActiveFlag;
|
---|
241 |
|
---|
242 | CopyMem (
|
---|
243 | &AccessPoint4->StationAddress,
|
---|
244 | &ConfigData->Tcp4IoConfigData.LocalIp,
|
---|
245 | sizeof (EFI_IPv4_ADDRESS)
|
---|
246 | );
|
---|
247 | CopyMem (
|
---|
248 | &AccessPoint4->SubnetMask,
|
---|
249 | &ConfigData->Tcp4IoConfigData.SubnetMask,
|
---|
250 | sizeof (EFI_IPv4_ADDRESS)
|
---|
251 | );
|
---|
252 | CopyMem (
|
---|
253 | &AccessPoint4->RemoteAddress,
|
---|
254 | &ConfigData->Tcp4IoConfigData.RemoteIp,
|
---|
255 | sizeof (EFI_IPv4_ADDRESS)
|
---|
256 | );
|
---|
257 |
|
---|
258 | ASSERT (Tcp4 != NULL);
|
---|
259 |
|
---|
260 | //
|
---|
261 | // Configure the TCP4 protocol.
|
---|
262 | //
|
---|
263 | Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
|
---|
264 | if (EFI_ERROR (Status)) {
|
---|
265 | goto ON_ERROR;
|
---|
266 | }
|
---|
267 |
|
---|
268 | if (!EFI_IP4_EQUAL (&ConfigData->Tcp4IoConfigData.Gateway, &mZeroIp4Addr)) {
|
---|
269 | //
|
---|
270 | // The gateway is not zero. Add the default route manually.
|
---|
271 | //
|
---|
272 | Status = Tcp4->Routes (
|
---|
273 | Tcp4,
|
---|
274 | FALSE,
|
---|
275 | &mZeroIp4Addr,
|
---|
276 | &mZeroIp4Addr,
|
---|
277 | &ConfigData->Tcp4IoConfigData.Gateway
|
---|
278 | );
|
---|
279 | if (EFI_ERROR (Status)) {
|
---|
280 | goto ON_ERROR;
|
---|
281 | }
|
---|
282 | }
|
---|
283 | } else {
|
---|
284 | Tcp6ConfigData.TrafficClass = 0;
|
---|
285 | Tcp6ConfigData.HopLimit = 255;
|
---|
286 | Tcp6ConfigData.ControlOption = (EFI_TCP6_OPTION *) &ControlOption;
|
---|
287 |
|
---|
288 | AccessPoint6 = &Tcp6ConfigData.AccessPoint;
|
---|
289 |
|
---|
290 | ZeroMem (AccessPoint6, sizeof (EFI_TCP6_ACCESS_POINT));
|
---|
291 | AccessPoint6->StationPort = ConfigData->Tcp6IoConfigData.StationPort;
|
---|
292 | AccessPoint6->RemotePort = ConfigData->Tcp6IoConfigData.RemotePort;
|
---|
293 | AccessPoint6->ActiveFlag = ConfigData->Tcp6IoConfigData.ActiveFlag;
|
---|
294 |
|
---|
295 | IP6_COPY_ADDRESS (&AccessPoint6->RemoteAddress, &ConfigData->Tcp6IoConfigData.RemoteIp);
|
---|
296 |
|
---|
297 |
|
---|
298 | ASSERT (Tcp6 != NULL);
|
---|
299 | //
|
---|
300 | // Configure the TCP6 protocol.
|
---|
301 | //
|
---|
302 | Status = Tcp6->Configure (Tcp6, &Tcp6ConfigData);
|
---|
303 | if (Status == EFI_NO_MAPPING) {
|
---|
304 | Status = TcpIoGetMapping (Tcp6, &Tcp6ConfigData);
|
---|
305 | }
|
---|
306 |
|
---|
307 | if (EFI_ERROR (Status)) {
|
---|
308 | goto ON_ERROR;
|
---|
309 | }
|
---|
310 | }
|
---|
311 |
|
---|
312 | //
|
---|
313 | // Create events for variuos asynchronous operations.
|
---|
314 | //
|
---|
315 | Status = gBS->CreateEvent (
|
---|
316 | EVT_NOTIFY_SIGNAL,
|
---|
317 | TPL_NOTIFY,
|
---|
318 | TcpIoCommonNotify,
|
---|
319 | &TcpIo->IsConnDone,
|
---|
320 | &Event
|
---|
321 | );
|
---|
322 | if (EFI_ERROR (Status)) {
|
---|
323 | goto ON_ERROR;
|
---|
324 | }
|
---|
325 |
|
---|
326 | TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;
|
---|
327 |
|
---|
328 | Status = gBS->CreateEvent (
|
---|
329 | EVT_NOTIFY_SIGNAL,
|
---|
330 | TPL_NOTIFY,
|
---|
331 | TcpIoCommonNotify,
|
---|
332 | &TcpIo->IsListenDone,
|
---|
333 | &Event
|
---|
334 | );
|
---|
335 | if (EFI_ERROR (Status)) {
|
---|
336 | goto ON_ERROR;
|
---|
337 | }
|
---|
338 |
|
---|
339 | TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;
|
---|
340 |
|
---|
341 | Status = gBS->CreateEvent (
|
---|
342 | EVT_NOTIFY_SIGNAL,
|
---|
343 | TPL_NOTIFY,
|
---|
344 | TcpIoCommonNotify,
|
---|
345 | &TcpIo->IsTxDone,
|
---|
346 | &Event
|
---|
347 | );
|
---|
348 | if (EFI_ERROR (Status)) {
|
---|
349 | goto ON_ERROR;
|
---|
350 | }
|
---|
351 |
|
---|
352 | TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;
|
---|
353 |
|
---|
354 |
|
---|
355 | Status = gBS->CreateEvent (
|
---|
356 | EVT_NOTIFY_SIGNAL,
|
---|
357 | TPL_NOTIFY,
|
---|
358 | TcpIoCommonNotify,
|
---|
359 | &TcpIo->IsRxDone,
|
---|
360 | &Event
|
---|
361 | );
|
---|
362 | if (EFI_ERROR (Status)) {
|
---|
363 | goto ON_ERROR;
|
---|
364 | }
|
---|
365 |
|
---|
366 | TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;
|
---|
367 |
|
---|
368 | RxData = (EFI_TCP4_RECEIVE_DATA *) AllocateZeroPool (sizeof (EFI_TCP4_RECEIVE_DATA));
|
---|
369 | if (RxData == NULL) {
|
---|
370 | Status = EFI_OUT_OF_RESOURCES;
|
---|
371 | goto ON_ERROR;
|
---|
372 | }
|
---|
373 |
|
---|
374 | TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;
|
---|
375 |
|
---|
376 | Status = gBS->CreateEvent (
|
---|
377 | EVT_NOTIFY_SIGNAL,
|
---|
378 | TPL_NOTIFY,
|
---|
379 | TcpIoCommonNotify,
|
---|
380 | &TcpIo->IsCloseDone,
|
---|
381 | &Event
|
---|
382 | );
|
---|
383 | if (EFI_ERROR (Status)) {
|
---|
384 | goto ON_ERROR;
|
---|
385 | }
|
---|
386 |
|
---|
387 | TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;
|
---|
388 |
|
---|
389 |
|
---|
390 | return EFI_SUCCESS;
|
---|
391 |
|
---|
392 | ON_ERROR:
|
---|
393 |
|
---|
394 | TcpIoDestroySocket (TcpIo);
|
---|
395 |
|
---|
396 | return Status;
|
---|
397 | }
|
---|
398 |
|
---|
399 | /**
|
---|
400 | Destroy the socket.
|
---|
401 |
|
---|
402 | @param[in] TcpIo The TcpIo which wraps the socket to be destroyed.
|
---|
403 |
|
---|
404 | **/
|
---|
405 | VOID
|
---|
406 | EFIAPI
|
---|
407 | TcpIoDestroySocket (
|
---|
408 | IN TCP_IO *TcpIo
|
---|
409 | )
|
---|
410 | {
|
---|
411 | EFI_EVENT Event;
|
---|
412 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
413 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
414 | UINT8 TcpVersion;
|
---|
415 | EFI_GUID *ServiceBindingGuid;
|
---|
416 | EFI_GUID *ProtocolGuid;
|
---|
417 | EFI_HANDLE ChildHandle;
|
---|
418 |
|
---|
419 | if (TcpIo == NULL) {
|
---|
420 | return ;
|
---|
421 | }
|
---|
422 |
|
---|
423 | TcpVersion = TcpIo->TcpVersion;
|
---|
424 |
|
---|
425 | if ((TcpVersion != TCP_VERSION_4) && (TcpVersion != TCP_VERSION_6)) {
|
---|
426 | return ;
|
---|
427 | }
|
---|
428 |
|
---|
429 | Event = TcpIo->ConnToken.Tcp4Token.CompletionToken.Event;
|
---|
430 |
|
---|
431 | if (Event != NULL) {
|
---|
432 | gBS->CloseEvent (Event);
|
---|
433 | }
|
---|
434 |
|
---|
435 | Event = TcpIo->ListenToken.Tcp4Token.CompletionToken.Event;
|
---|
436 |
|
---|
437 | if (Event != NULL) {
|
---|
438 | gBS->CloseEvent (Event);
|
---|
439 | }
|
---|
440 |
|
---|
441 | Event = TcpIo->TxToken.Tcp4Token.CompletionToken.Event;
|
---|
442 |
|
---|
443 | if (Event != NULL) {
|
---|
444 | gBS->CloseEvent (Event);
|
---|
445 | }
|
---|
446 |
|
---|
447 | Event = TcpIo->RxToken.Tcp4Token.CompletionToken.Event;
|
---|
448 |
|
---|
449 | if (Event != NULL) {
|
---|
450 | gBS->CloseEvent (Event);
|
---|
451 | }
|
---|
452 |
|
---|
453 | Event = TcpIo->CloseToken.Tcp4Token.CompletionToken.Event;
|
---|
454 |
|
---|
455 | if (Event != NULL) {
|
---|
456 | gBS->CloseEvent (Event);
|
---|
457 | }
|
---|
458 |
|
---|
459 | if (TcpIo->RxToken.Tcp4Token.Packet.RxData != NULL) {
|
---|
460 | FreePool (TcpIo->RxToken.Tcp4Token.Packet.RxData);
|
---|
461 | }
|
---|
462 |
|
---|
463 | Tcp4 = NULL;
|
---|
464 | Tcp6 = NULL;
|
---|
465 |
|
---|
466 |
|
---|
467 | if (TcpVersion == TCP_VERSION_4) {
|
---|
468 | ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
|
---|
469 | ProtocolGuid = &gEfiTcp4ProtocolGuid;
|
---|
470 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
471 | if (Tcp4 != NULL) {
|
---|
472 | Tcp4->Configure (Tcp4, NULL);
|
---|
473 | }
|
---|
474 | } else {
|
---|
475 | ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
|
---|
476 | ProtocolGuid = &gEfiTcp6ProtocolGuid;
|
---|
477 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
478 | if (Tcp6 != NULL) {
|
---|
479 | Tcp6->Configure (Tcp6, NULL);
|
---|
480 | }
|
---|
481 | }
|
---|
482 |
|
---|
483 | if ((Tcp4 != NULL) || (Tcp6 != NULL)) {
|
---|
484 |
|
---|
485 | gBS->CloseProtocol (
|
---|
486 | TcpIo->Handle,
|
---|
487 | ProtocolGuid,
|
---|
488 | TcpIo->Image,
|
---|
489 | TcpIo->Controller
|
---|
490 | );
|
---|
491 | }
|
---|
492 |
|
---|
493 | ChildHandle = NULL;
|
---|
494 |
|
---|
495 | if (TcpIo->IsListenDone) {
|
---|
496 | if (TcpVersion == TCP_VERSION_4) {
|
---|
497 | Tcp4 = TcpIo->NewTcp.Tcp4;
|
---|
498 | if (Tcp4 != NULL) {
|
---|
499 | Tcp4->Configure (Tcp4, NULL);
|
---|
500 | ChildHandle = TcpIo->ListenToken.Tcp4Token.NewChildHandle;
|
---|
501 | }
|
---|
502 | } else {
|
---|
503 | Tcp6 = TcpIo->NewTcp.Tcp6;
|
---|
504 | if (Tcp6 != NULL) {
|
---|
505 | Tcp6->Configure (Tcp6, NULL);
|
---|
506 | ChildHandle = TcpIo->ListenToken.Tcp6Token.NewChildHandle;
|
---|
507 | }
|
---|
508 | }
|
---|
509 |
|
---|
510 | if (ChildHandle != NULL) {
|
---|
511 |
|
---|
512 | gBS->CloseProtocol (
|
---|
513 | ChildHandle,
|
---|
514 | ProtocolGuid,
|
---|
515 | TcpIo->Image,
|
---|
516 | TcpIo->Controller
|
---|
517 | );
|
---|
518 | }
|
---|
519 | }
|
---|
520 |
|
---|
521 | NetLibDestroyServiceChild (
|
---|
522 | TcpIo->Controller,
|
---|
523 | TcpIo->Image,
|
---|
524 | ServiceBindingGuid,
|
---|
525 | TcpIo->Handle
|
---|
526 | );
|
---|
527 | }
|
---|
528 |
|
---|
529 | /**
|
---|
530 | Connect to the other endpoint of the TCP socket.
|
---|
531 |
|
---|
532 | @param[in, out] TcpIo The TcpIo wrapping the TCP socket.
|
---|
533 | @param[in] Timeout The time to wait for connection done. Set to NULL for infinite wait.
|
---|
534 |
|
---|
535 | @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket
|
---|
536 | successfully.
|
---|
537 | @retval EFI_TIMEOUT Failed to connect to the other endpoint of the
|
---|
538 | TCP socket in the specified time period.
|
---|
539 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
540 | @retval EFI_UNSUPPORTED One or more of the control options are not
|
---|
541 | supported in the implementation.
|
---|
542 | @retval Others Other errors as indicated.
|
---|
543 |
|
---|
544 | **/
|
---|
545 | EFI_STATUS
|
---|
546 | EFIAPI
|
---|
547 | TcpIoConnect (
|
---|
548 | IN OUT TCP_IO *TcpIo,
|
---|
549 | IN EFI_EVENT Timeout OPTIONAL
|
---|
550 | )
|
---|
551 | {
|
---|
552 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
553 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
554 | EFI_STATUS Status;
|
---|
555 |
|
---|
556 | if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
|
---|
557 | return EFI_INVALID_PARAMETER;
|
---|
558 | }
|
---|
559 |
|
---|
560 | TcpIo->IsConnDone = FALSE;
|
---|
561 |
|
---|
562 | Tcp4 = NULL;
|
---|
563 | Tcp6 = NULL;
|
---|
564 |
|
---|
565 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
566 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
567 | Status = Tcp4->Connect (Tcp4, &TcpIo->ConnToken.Tcp4Token);
|
---|
568 | } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
|
---|
569 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
570 | Status = Tcp6->Connect (Tcp6, &TcpIo->ConnToken.Tcp6Token);
|
---|
571 | } else {
|
---|
572 | return EFI_UNSUPPORTED;
|
---|
573 | }
|
---|
574 |
|
---|
575 | if (EFI_ERROR (Status)) {
|
---|
576 | return Status;
|
---|
577 | }
|
---|
578 |
|
---|
579 | while (!TcpIo->IsConnDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
|
---|
580 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
581 | Tcp4->Poll (Tcp4);
|
---|
582 | } else {
|
---|
583 | Tcp6->Poll (Tcp6);
|
---|
584 | }
|
---|
585 | }
|
---|
586 |
|
---|
587 | if (!TcpIo->IsConnDone) {
|
---|
588 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
589 | Tcp4->Cancel (Tcp4, &TcpIo->ConnToken.Tcp4Token.CompletionToken);
|
---|
590 | } else {
|
---|
591 | Tcp6->Cancel (Tcp6, &TcpIo->ConnToken.Tcp6Token.CompletionToken);
|
---|
592 | }
|
---|
593 | Status = EFI_TIMEOUT;
|
---|
594 | } else {
|
---|
595 | Status = TcpIo->ConnToken.Tcp4Token.CompletionToken.Status;
|
---|
596 | }
|
---|
597 |
|
---|
598 | return Status;
|
---|
599 | }
|
---|
600 |
|
---|
601 | /**
|
---|
602 | Accept the incomding request from the other endpoint of the TCP socket.
|
---|
603 |
|
---|
604 | @param[in, out] TcpIo The TcpIo wrapping the TCP socket.
|
---|
605 | @param[in] Timeout The time to wait for connection done. Set to NULL for infinite wait.
|
---|
606 |
|
---|
607 |
|
---|
608 | @retval EFI_SUCCESS Connect to the other endpoint of the TCP socket
|
---|
609 | successfully.
|
---|
610 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
611 | @retval EFI_UNSUPPORTED One or more of the control options are not
|
---|
612 | supported in the implementation.
|
---|
613 |
|
---|
614 | @retval EFI_TIMEOUT Failed to connect to the other endpoint of the
|
---|
615 | TCP socket in the specified time period.
|
---|
616 | @retval Others Other errors as indicated.
|
---|
617 |
|
---|
618 | **/
|
---|
619 | EFI_STATUS
|
---|
620 | EFIAPI
|
---|
621 | TcpIoAccept (
|
---|
622 | IN OUT TCP_IO *TcpIo,
|
---|
623 | IN EFI_EVENT Timeout OPTIONAL
|
---|
624 | )
|
---|
625 | {
|
---|
626 | EFI_STATUS Status;
|
---|
627 | EFI_GUID *ProtocolGuid;
|
---|
628 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
629 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
630 |
|
---|
631 | if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
|
---|
632 | return EFI_INVALID_PARAMETER;
|
---|
633 | }
|
---|
634 |
|
---|
635 | TcpIo->IsListenDone = FALSE;
|
---|
636 |
|
---|
637 | Tcp4 = NULL;
|
---|
638 | Tcp6 = NULL;
|
---|
639 |
|
---|
640 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
641 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
642 | Status = Tcp4->Accept (Tcp4, &TcpIo->ListenToken.Tcp4Token);
|
---|
643 | } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
|
---|
644 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
645 | Status = Tcp6->Accept (Tcp6, &TcpIo->ListenToken.Tcp6Token);
|
---|
646 | } else {
|
---|
647 | return EFI_UNSUPPORTED;
|
---|
648 | }
|
---|
649 |
|
---|
650 | if (EFI_ERROR (Status)) {
|
---|
651 | return Status;
|
---|
652 | }
|
---|
653 |
|
---|
654 | while (!TcpIo->IsListenDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
|
---|
655 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
656 | Tcp4->Poll (Tcp4);
|
---|
657 | } else {
|
---|
658 | Tcp6->Poll (Tcp6);
|
---|
659 | }
|
---|
660 | }
|
---|
661 |
|
---|
662 | if (!TcpIo->IsListenDone) {
|
---|
663 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
664 | Tcp4->Cancel (Tcp4, &TcpIo->ListenToken.Tcp4Token.CompletionToken);
|
---|
665 | } else {
|
---|
666 | Tcp6->Cancel (Tcp6, &TcpIo->ListenToken.Tcp6Token.CompletionToken);
|
---|
667 | }
|
---|
668 | Status = EFI_TIMEOUT;
|
---|
669 | } else {
|
---|
670 | Status = TcpIo->ListenToken.Tcp4Token.CompletionToken.Status;
|
---|
671 | }
|
---|
672 |
|
---|
673 | //
|
---|
674 | // The new TCP instance handle created for the established connection is
|
---|
675 | // in ListenToken.
|
---|
676 | //
|
---|
677 | if (!EFI_ERROR (Status)) {
|
---|
678 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
679 | ProtocolGuid = &gEfiTcp4ProtocolGuid;
|
---|
680 | } else {
|
---|
681 | ProtocolGuid = &gEfiTcp6ProtocolGuid;
|
---|
682 | }
|
---|
683 |
|
---|
684 | Status = gBS->OpenProtocol (
|
---|
685 | TcpIo->ListenToken.Tcp4Token.NewChildHandle,
|
---|
686 | ProtocolGuid,
|
---|
687 | (VOID **) (&TcpIo->NewTcp.Tcp4),
|
---|
688 | TcpIo->Image,
|
---|
689 | TcpIo->Controller,
|
---|
690 | EFI_OPEN_PROTOCOL_BY_DRIVER
|
---|
691 | );
|
---|
692 |
|
---|
693 | }
|
---|
694 |
|
---|
695 | return Status;
|
---|
696 | }
|
---|
697 |
|
---|
698 | /**
|
---|
699 | Reset the socket.
|
---|
700 |
|
---|
701 | @param[in, out] TcpIo The TcpIo wrapping the TCP socket.
|
---|
702 |
|
---|
703 | **/
|
---|
704 | VOID
|
---|
705 | EFIAPI
|
---|
706 | TcpIoReset (
|
---|
707 | IN OUT TCP_IO *TcpIo
|
---|
708 | )
|
---|
709 | {
|
---|
710 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
711 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
712 | EFI_STATUS Status;
|
---|
713 |
|
---|
714 | if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)) {
|
---|
715 | return ;
|
---|
716 | }
|
---|
717 |
|
---|
718 | TcpIo->IsCloseDone = FALSE;
|
---|
719 | Tcp4 = NULL;
|
---|
720 | Tcp6 = NULL;
|
---|
721 |
|
---|
722 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
723 | TcpIo->CloseToken.Tcp4Token.AbortOnClose = TRUE;
|
---|
724 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
725 | Status = Tcp4->Close (Tcp4, &TcpIo->CloseToken.Tcp4Token);
|
---|
726 | } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
|
---|
727 | TcpIo->CloseToken.Tcp6Token.AbortOnClose = TRUE;
|
---|
728 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
729 | Status = Tcp6->Close (Tcp6, &TcpIo->CloseToken.Tcp6Token);
|
---|
730 | } else {
|
---|
731 | return ;
|
---|
732 | }
|
---|
733 |
|
---|
734 | if (EFI_ERROR (Status)) {
|
---|
735 | return ;
|
---|
736 | }
|
---|
737 |
|
---|
738 | while (!TcpIo->IsCloseDone) {
|
---|
739 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
740 | Tcp4->Poll (Tcp4);
|
---|
741 | } else {
|
---|
742 | Tcp6->Poll (Tcp6);
|
---|
743 | }
|
---|
744 | }
|
---|
745 | }
|
---|
746 |
|
---|
747 |
|
---|
748 | /**
|
---|
749 | Transmit the Packet to the other endpoint of the socket.
|
---|
750 |
|
---|
751 | @param[in] TcpIo The TcpIo wrapping the TCP socket.
|
---|
752 | @param[in] Packet The packet to transmit.
|
---|
753 |
|
---|
754 | @retval EFI_SUCCESS The packet is trasmitted.
|
---|
755 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
756 | @retval EFI_UNSUPPORTED One or more of the control options are not
|
---|
757 | supported in the implementation.
|
---|
758 | @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
---|
759 | @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
|
---|
760 | @retval Others Other errors as indicated.
|
---|
761 |
|
---|
762 | **/
|
---|
763 | EFI_STATUS
|
---|
764 | EFIAPI
|
---|
765 | TcpIoTransmit (
|
---|
766 | IN TCP_IO *TcpIo,
|
---|
767 | IN NET_BUF *Packet
|
---|
768 | )
|
---|
769 | {
|
---|
770 | EFI_STATUS Status;
|
---|
771 | VOID *Data;
|
---|
772 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
773 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
774 | UINTN Size;
|
---|
775 |
|
---|
776 | if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {
|
---|
777 | return EFI_INVALID_PARAMETER;
|
---|
778 | }
|
---|
779 |
|
---|
780 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
781 |
|
---|
782 | Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +
|
---|
783 | (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
|
---|
784 | } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
|
---|
785 | Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
|
---|
786 | (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
|
---|
787 | } else {
|
---|
788 | return EFI_UNSUPPORTED;
|
---|
789 | }
|
---|
790 |
|
---|
791 | Data = AllocatePool (Size);
|
---|
792 | if (Data == NULL) {
|
---|
793 | return EFI_OUT_OF_RESOURCES;
|
---|
794 | }
|
---|
795 |
|
---|
796 | ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE;
|
---|
797 | ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE;
|
---|
798 | ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;
|
---|
799 |
|
---|
800 | //
|
---|
801 | // Build the fragment table.
|
---|
802 | //
|
---|
803 | ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;
|
---|
804 |
|
---|
805 | NetbufBuildExt (
|
---|
806 | Packet,
|
---|
807 | (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0],
|
---|
808 | &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount
|
---|
809 | );
|
---|
810 |
|
---|
811 | Tcp4 = NULL;
|
---|
812 | Tcp6 = NULL;
|
---|
813 | Status = EFI_DEVICE_ERROR;
|
---|
814 |
|
---|
815 | //
|
---|
816 | // Trasnmit the packet.
|
---|
817 | //
|
---|
818 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
819 | TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data;
|
---|
820 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
821 | if (TcpIo->IsListenDone) {
|
---|
822 | Tcp4 = TcpIo->NewTcp.Tcp4;
|
---|
823 | }
|
---|
824 |
|
---|
825 | if (Tcp4 == NULL) {
|
---|
826 | goto ON_EXIT;
|
---|
827 | }
|
---|
828 |
|
---|
829 | Status = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token);
|
---|
830 | } else {
|
---|
831 | TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data;
|
---|
832 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
833 | if (TcpIo->IsListenDone) {
|
---|
834 | Tcp6 = TcpIo->NewTcp.Tcp6;
|
---|
835 | }
|
---|
836 |
|
---|
837 | if (Tcp6 == NULL) {
|
---|
838 | goto ON_EXIT;
|
---|
839 | }
|
---|
840 |
|
---|
841 | Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);
|
---|
842 | }
|
---|
843 |
|
---|
844 | if (EFI_ERROR (Status)) {
|
---|
845 | goto ON_EXIT;
|
---|
846 | }
|
---|
847 |
|
---|
848 | while (!TcpIo->IsTxDone) {
|
---|
849 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
850 | Tcp4->Poll (Tcp4);
|
---|
851 | } else {
|
---|
852 | Tcp6->Poll (Tcp6);
|
---|
853 | }
|
---|
854 | }
|
---|
855 |
|
---|
856 | TcpIo->IsTxDone = FALSE;
|
---|
857 | Status = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;
|
---|
858 |
|
---|
859 | ON_EXIT:
|
---|
860 |
|
---|
861 | FreePool (Data);
|
---|
862 |
|
---|
863 | return Status;
|
---|
864 | }
|
---|
865 |
|
---|
866 | /**
|
---|
867 | Receive data from the socket.
|
---|
868 |
|
---|
869 | @param[in, out] TcpIo The TcpIo which wraps the socket to be destroyed.
|
---|
870 | @param[in] Packet The buffer to hold the data copy from the socket rx buffer.
|
---|
871 | @param[in] AsyncMode Is this receive asyncronous or not.
|
---|
872 | @param[in] Timeout The time to wait for receiving the amount of data the Packet
|
---|
873 | can hold. Set to NULL for infinite wait.
|
---|
874 |
|
---|
875 | @retval EFI_SUCCESS The required amount of data is received from the socket.
|
---|
876 | @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
---|
877 | @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
|
---|
878 | @retval EFI_OUT_OF_RESOURCES Failed to allocate momery.
|
---|
879 | @retval EFI_TIMEOUT Failed to receive the required amount of data in the
|
---|
880 | specified time period.
|
---|
881 | @retval Others Other errors as indicated.
|
---|
882 |
|
---|
883 | **/
|
---|
884 | EFI_STATUS
|
---|
885 | EFIAPI
|
---|
886 | TcpIoReceive (
|
---|
887 | IN OUT TCP_IO *TcpIo,
|
---|
888 | IN NET_BUF *Packet,
|
---|
889 | IN BOOLEAN AsyncMode,
|
---|
890 | IN EFI_EVENT Timeout OPTIONAL
|
---|
891 | )
|
---|
892 | {
|
---|
893 | EFI_TCP4_PROTOCOL *Tcp4;
|
---|
894 | EFI_TCP6_PROTOCOL *Tcp6;
|
---|
895 | EFI_TCP4_RECEIVE_DATA *RxData;
|
---|
896 | EFI_STATUS Status;
|
---|
897 | NET_FRAGMENT *Fragment;
|
---|
898 | UINT32 FragmentCount;
|
---|
899 | UINT32 CurrentFragment;
|
---|
900 |
|
---|
901 | if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) {
|
---|
902 | return EFI_INVALID_PARAMETER;
|
---|
903 | }
|
---|
904 |
|
---|
905 | RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData;
|
---|
906 | if (RxData == NULL) {
|
---|
907 | return EFI_INVALID_PARAMETER;
|
---|
908 | }
|
---|
909 |
|
---|
910 | Tcp4 = NULL;
|
---|
911 | Tcp6 = NULL;
|
---|
912 |
|
---|
913 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
914 | Tcp4 = TcpIo->Tcp.Tcp4;
|
---|
915 |
|
---|
916 | if (TcpIo->IsListenDone) {
|
---|
917 | Tcp4 = TcpIo->NewTcp.Tcp4;
|
---|
918 | }
|
---|
919 |
|
---|
920 | if (Tcp4 == NULL) {
|
---|
921 | return EFI_DEVICE_ERROR;
|
---|
922 | }
|
---|
923 |
|
---|
924 | } else if (TcpIo->TcpVersion == TCP_VERSION_6) {
|
---|
925 | Tcp6 = TcpIo->Tcp.Tcp6;
|
---|
926 |
|
---|
927 | if (TcpIo->IsListenDone) {
|
---|
928 | Tcp6 = TcpIo->NewTcp.Tcp6;
|
---|
929 | }
|
---|
930 |
|
---|
931 | if (Tcp6 == NULL) {
|
---|
932 | return EFI_DEVICE_ERROR;
|
---|
933 | }
|
---|
934 |
|
---|
935 | } else {
|
---|
936 | return EFI_UNSUPPORTED;
|
---|
937 | }
|
---|
938 |
|
---|
939 | FragmentCount = Packet->BlockOpNum;
|
---|
940 | Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
|
---|
941 | if (Fragment == NULL) {
|
---|
942 | Status = EFI_OUT_OF_RESOURCES;
|
---|
943 | goto ON_EXIT;
|
---|
944 | }
|
---|
945 | //
|
---|
946 | // Build the fragment table.
|
---|
947 | //
|
---|
948 | NetbufBuildExt (Packet, Fragment, &FragmentCount);
|
---|
949 |
|
---|
950 | RxData->FragmentCount = 1;
|
---|
951 | CurrentFragment = 0;
|
---|
952 | Status = EFI_SUCCESS;
|
---|
953 |
|
---|
954 | while (CurrentFragment < FragmentCount) {
|
---|
955 | RxData->DataLength = Fragment[CurrentFragment].Len;
|
---|
956 | RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;
|
---|
957 | RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;
|
---|
958 |
|
---|
959 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
960 | Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token);
|
---|
961 | } else {
|
---|
962 | Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);
|
---|
963 | }
|
---|
964 |
|
---|
965 | if (EFI_ERROR (Status)) {
|
---|
966 | goto ON_EXIT;
|
---|
967 | }
|
---|
968 |
|
---|
969 | while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
|
---|
970 | //
|
---|
971 | // Poll until some data is received or an error occurs.
|
---|
972 | //
|
---|
973 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
974 | Tcp4->Poll (Tcp4);
|
---|
975 | } else {
|
---|
976 | Tcp6->Poll (Tcp6);
|
---|
977 | }
|
---|
978 | }
|
---|
979 |
|
---|
980 | if (!TcpIo->IsRxDone) {
|
---|
981 | //
|
---|
982 | // Timeout occurs, cancel the receive request.
|
---|
983 | //
|
---|
984 | if (TcpIo->TcpVersion == TCP_VERSION_4) {
|
---|
985 | Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);
|
---|
986 | } else {
|
---|
987 | Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);
|
---|
988 | }
|
---|
989 |
|
---|
990 | Status = EFI_TIMEOUT;
|
---|
991 | goto ON_EXIT;
|
---|
992 | } else {
|
---|
993 | TcpIo->IsRxDone = FALSE;
|
---|
994 | }
|
---|
995 |
|
---|
996 | Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;
|
---|
997 |
|
---|
998 | if (EFI_ERROR (Status)) {
|
---|
999 | goto ON_EXIT;
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 | Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength;
|
---|
1003 | if (Fragment[CurrentFragment].Len == 0) {
|
---|
1004 | CurrentFragment++;
|
---|
1005 | } else {
|
---|
1006 | Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength;
|
---|
1007 | }
|
---|
1008 | }
|
---|
1009 |
|
---|
1010 | ON_EXIT:
|
---|
1011 |
|
---|
1012 | if (Fragment != NULL) {
|
---|
1013 | FreePool (Fragment);
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | return Status;
|
---|
1017 | }
|
---|