/** Flush the tokens in the specific token list. @param Sock Pointer to the socket. @param PendingTokenList Pointer to the token list to be flushed. **/ VOID SockFlushPendingToken ( IN SOCKET *Sock, IN LIST_ENTRY *PendingTokenList ) { SOCK_TOKEN *SockToken; SOCK_COMPLETION_TOKEN *Token; ASSERT ((Sock != NULL) && (PendingTokenList != NULL)); while (!IsListEmpty (PendingTokenList)) { SockToken = NET_LIST_HEAD ( PendingTokenList, SOCK_TOKEN, TokenList ); Token = SockToken->Token; SIGNAL_TOKEN (Token, Sock->SockError); RemoveEntryList (&(SockToken->TokenList)); FreePool (SockToken); } }
INTN Mtftp4GetNextBlockNum ( IN NET_LIST_ENTRY *Head ) /*++ Routine Description: Get the first valid block number on the range list. Arguments: Head - The block range head Returns: -1: if the block range is empty. Otherwise the first valid block number. --*/ { MTFTP4_BLOCK_RANGE *Range; if (NetListIsEmpty (Head)) { return -1; } Range = NET_LIST_HEAD (Head, MTFTP4_BLOCK_RANGE, Link); return Range->Start; }
/** Signal the receive token with the specific error or set socket error code after error is received. @param Sock Pointer to the socket. @param Error The error code received. **/ VOID SockRcvdErr ( IN OUT SOCKET *Sock, IN EFI_STATUS Error ) { SOCK_TOKEN *SockToken; if (!IsListEmpty (&Sock->RcvTokenList)) { SockToken = NET_LIST_HEAD ( &Sock->RcvTokenList, SOCK_TOKEN, TokenList ); RemoveEntryList (&SockToken->TokenList); SIGNAL_TOKEN (SockToken->Token, Error); FreePool (SockToken); } else { SOCK_ERROR (Sock, Error); } }
/** Flush the sndBuffer and rcvBuffer of socket. @param Sock Pointer to the socket. **/ VOID SockConnFlush ( IN OUT SOCKET *Sock ) { SOCKET *Child; ASSERT (Sock != NULL); // // Clear the flag in this socket // Sock->Flag = 0; // // Flush the SndBuffer and RcvBuffer of Sock // NetbufQueFlush (Sock->SndBuffer.DataQueue); NetbufQueFlush (Sock->RcvBuffer.DataQueue); // // Signal the pending token // if (Sock->ConnectionToken != NULL) { SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError); Sock->ConnectionToken = NULL; } if (Sock->CloseToken != NULL) { SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError); Sock->CloseToken = NULL; } SockFlushPendingToken (Sock, &(Sock->ListenTokenList)); SockFlushPendingToken (Sock, &(Sock->RcvTokenList)); SockFlushPendingToken (Sock, &(Sock->SndTokenList)); SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList)); // // Destroy the pending connection, if it is a listening socket // if (SOCK_IS_LISTENING (Sock)) { while (!IsListEmpty (&Sock->ConnectionList)) { Child = NET_LIST_HEAD ( &Sock->ConnectionList, SOCKET, ConnectionList ); SockDestroyChild (Child); } Sock->ConnCnt = 0; } return ; }
/** Get the first valid block number on the range list. @param[in] Head The block range head. @retval ==-1 If the block range is empty. @retval >-1 The first valid block number. **/ INTN Mtftp6GetNextBlockNum ( IN LIST_ENTRY *Head ) { MTFTP6_BLOCK_RANGE *Range; if (IsListEmpty (Head)) { return -1; } Range = NET_LIST_HEAD (Head, MTFTP6_BLOCK_RANGE, Link); return Range->Start; }
/** Get the first buffer block in the specific socket buffer. @param Sockbuf Pointer to the socket buffer. @return Pointer to the first buffer in the queue. NULL if the queue is empty. **/ NET_BUF * SockBufFirst ( IN SOCK_BUFFER *Sockbuf ) { LIST_ENTRY *NetbufList; NetbufList = &(Sockbuf->DataQueue->BufList); if (IsListEmpty (NetbufList)) { return NULL; } return NET_LIST_HEAD (NetbufList, NET_BUF, List); }
/** Called by low layer protocol to indicate that some data is sent or processed. This function trims the sent data in the socket send buffer, signals the data token if proper. @param Sock Pointer to the socket. @param Count The length of the data processed or sent, in bytes. **/ VOID SockDataSent ( IN SOCKET *Sock, IN UINT32 Count ) { SOCK_TOKEN *SockToken; SOCK_COMPLETION_TOKEN *SndToken; ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList)); ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize); NetbufQueTrim (Sock->SndBuffer.DataQueue, Count); // // To check if we can signal some snd token in this socket // while (Count > 0) { SockToken = NET_LIST_HEAD ( &(Sock->ProcessingSndTokenList), SOCK_TOKEN, TokenList ); SndToken = SockToken->Token; if (SockToken->RemainDataLen <= Count) { RemoveEntryList (&(SockToken->TokenList)); SIGNAL_TOKEN (SndToken, EFI_SUCCESS); Count -= SockToken->RemainDataLen; FreePool (SockToken); } else { SockToken->RemainDataLen -= Count; Count = 0; } } // // to judge if we can process some send token in // Sock->SndTokenList, if so process those send token // SockProcessSndToken (Sock); return ; }
/** Wake up the listen token while the connection is established successfully. @param[in, out] Sock Pointer to the socket. **/ VOID SockWakeListenToken ( IN OUT SOCKET *Sock ) { SOCKET *Parent; SOCK_TOKEN *SockToken; EFI_TCP4_LISTEN_TOKEN *ListenToken; Parent = Sock->Parent; ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock)); if (!IsListEmpty (&Parent->ListenTokenList)) { SockToken = NET_LIST_HEAD ( &Parent->ListenTokenList, SOCK_TOKEN, TokenList ); ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token; ListenToken->NewChildHandle = Sock->SockHandle; SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS); RemoveEntryList (&SockToken->TokenList); FreePool (SockToken); RemoveEntryList (&Sock->ConnectionList); Parent->ConnCnt--; DEBUG ( (EFI_D_NET, "SockWakeListenToken: accept a socket, now conncnt is %d", Parent->ConnCnt) ); Sock->Parent = NULL; } }
/** Wake up the receive token while some data is received. @param Sock Pointer to the socket. **/ VOID SockWakeRcvToken ( IN SOCKET *Sock ) { UINT32 RcvdBytes; UINT32 TokenRcvdBytes; SOCK_TOKEN *SockToken; SOCK_IO_TOKEN *RcvToken; ASSERT (Sock->RcvBuffer.DataQueue != NULL); RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize; ASSERT (RcvdBytes > 0); while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) { SockToken = NET_LIST_HEAD ( &Sock->RcvTokenList, SOCK_TOKEN, TokenList ); RcvToken = (SOCK_IO_TOKEN *) SockToken->Token; TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken); if (0 == TokenRcvdBytes) { return ; } RemoveEntryList (&(SockToken->TokenList)); FreePool (SockToken); RcvdBytes -= TokenRcvdBytes; } }
/** Process the send token. @param Sock Pointer to the socket. **/ VOID SockProcessSndToken ( IN OUT SOCKET *Sock ) { UINT32 FreeSpace; SOCK_TOKEN *SockToken; UINT32 DataLen; SOCK_IO_TOKEN *SndToken; EFI_TCP4_TRANSMIT_DATA *TxData; EFI_STATUS Status; ASSERT ((Sock != NULL) && (SockStream == Sock->Type)); FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF); // // to determine if process a send token using // socket layer flow control policy // while ((FreeSpace >= Sock->SndBuffer.LowWater) && !IsListEmpty (&Sock->SndTokenList)) { SockToken = NET_LIST_HEAD ( &(Sock->SndTokenList), SOCK_TOKEN, TokenList ); // // process this token // RemoveEntryList (&(SockToken->TokenList)); InsertTailList ( &(Sock->ProcessingSndTokenList), &(SockToken->TokenList) ); // // Proceess it in the light of SockType // SndToken = (SOCK_IO_TOKEN *) SockToken->Token; TxData = SndToken->Packet.TxData; DataLen = (UINT32) TxData->DataLength; Status = SockProcessTcpSndData (Sock, TxData); if (EFI_ERROR (Status)) { goto OnError; } if (DataLen >= FreeSpace) { FreeSpace = 0; } else { FreeSpace -= DataLen; } } return ; OnError: RemoveEntryList (&SockToken->TokenList); SIGNAL_TOKEN (SockToken->Token, Status); FreePool (SockToken); }
EFI_STATUS Mtftp4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) /*++ Routine Description: Stop the MTFTP driver on controller. The controller is a UDP child handle. Arguments: This - The MTFTP driver binding protocol Controller - The controller to stop NumberOfChildren - The number of children ChildHandleBuffer - The array of the child handle. Returns: EFI_SUCCESS - The driver is stopped on the controller. EFI_DEVICE_ERROR - Failed to stop the driver on the controller. --*/ { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_HANDLE NicHandle; EFI_STATUS Status; EFI_TPL OldTpl; // // MTFTP driver opens UDP child, So, Controller is a UDP // child handle. Locate the Nic handle first. Then get the // MTFTP private data back. // NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid); if (NicHandle == NULL) { return EFI_DEVICE_ERROR; } Status = gBS->OpenProtocol ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, (VOID **) &ServiceBinding, This->DriverBindingHandle, NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding); if (MtftpSb->InDestory) { return EFI_SUCCESS; } OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); if (NumberOfChildren == 0) { MtftpSb->InDestory = TRUE; gBS->UninstallProtocolInterface ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, ServiceBinding ); Mtftp4CleanService (MtftpSb); NetFreePool (MtftpSb); } else { while (!NetListIsEmpty (&MtftpSb->Children)) { Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link); Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle); } if (MtftpSb->ChildrenNum != 0) { Status = EFI_DEVICE_ERROR; } } NET_RESTORE_TPL (OldTpl); return Status; }
/** Stop the MTFTP driver on controller. The controller is a UDP child handle. @param This The MTFTP driver binding protocol @param Controller The controller to stop @param NumberOfChildren The number of children @param ChildHandleBuffer The array of the child handle. @retval EFI_SUCCESS The driver is stopped on the controller. @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller. **/ EFI_STATUS EFIAPI Mtftp4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_HANDLE NicHandle; EFI_STATUS Status; EFI_TPL OldTpl; // // MTFTP driver opens UDP child, So, Controller is a UDP // child handle. Locate the Nic handle first. Then get the // MTFTP private data back. // NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid); if (NicHandle == NULL) { return EFI_DEVICE_ERROR; } Status = gBS->OpenProtocol ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, (VOID **) &ServiceBinding, This->DriverBindingHandle, NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding); if (MtftpSb->InDestory) { return EFI_SUCCESS; } OldTpl = gBS->RaiseTPL (TPL_CALLBACK); if (NumberOfChildren == 0) { MtftpSb->InDestory = TRUE; gBS->UninstallProtocolInterface ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, ServiceBinding ); Mtftp4CleanService (MtftpSb); FreePool (MtftpSb); } else { while (!IsListEmpty (&MtftpSb->Children)) { Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link); Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle); } if (MtftpSb->ChildrenNum != 0) { Status = EFI_DEVICE_ERROR; } } gBS->RestoreTPL (OldTpl); return Status; }