Home | History | Annotate | Download | only in EfiSocketLib
      1 /** @file
      2   Implement the IP4 driver support for the socket layer.
      3 
      4   Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials are licensed and made available
      6   under the terms and conditions of the BSD License which accompanies this
      7   distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 **/
     13 #include "Socket.h"
     14 
     15 
     16 /** Get the local socket address.
     17 
     18   This routine returns the IPv4 address associated with the local
     19   socket.
     20 
     21   This routine is called by ::EslSocketGetLocalAddress to determine the
     22   network address for the SOCK_RAW socket.
     23 
     24   @param [in] pPort       Address of an ::ESL_PORT structure.
     25   @param [out] pAddress   Network address to receive the local system address
     26 **/
     27 VOID
     28 EslIp4LocalAddressGet (
     29   IN ESL_PORT * pPort,
     30   OUT struct sockaddr * pAddress
     31   )
     32 {
     33   struct sockaddr_in * pLocalAddress;
     34   ESL_IP4_CONTEXT * pIp4;
     35 
     36   DBG_ENTER ( );
     37 
     38   //  Return the local address
     39   pIp4 = &pPort->Context.Ip4;
     40   pLocalAddress = (struct sockaddr_in *)pAddress;
     41   pLocalAddress->sin_family = AF_INET;
     42   CopyMem ( &pLocalAddress->sin_addr,
     43             &pIp4->ModeData.ConfigData.StationAddress.Addr[0],
     44             sizeof ( pLocalAddress->sin_addr ));
     45 
     46   DBG_EXIT ( );
     47 }
     48 
     49 
     50 /** Set the local port address.
     51 
     52   This routine sets the local port address.
     53 
     54   This support routine is called by ::EslSocketPortAllocate.
     55 
     56   @param [in] pPort       Address of an ESL_PORT structure
     57   @param [in] pSockAddr   Address of a sockaddr structure that contains the
     58                           connection point on the local machine.  An IPv4 address
     59                           of INADDR_ANY specifies that the connection is made to
     60                           all of the network stacks on the platform.  Specifying a
     61                           specific IPv4 address restricts the connection to the
     62                           network stack supporting that address.  Specifying zero
     63                           for the port causes the network layer to assign a port
     64                           number from the dynamic range.  Specifying a specific
     65                           port number causes the network layer to use that port.
     66 
     67   @param [in] bBindTest   TRUE = run bind testing
     68 
     69   @retval EFI_SUCCESS     The operation was successful
     70  **/
     71 EFI_STATUS
     72 EslIp4LocalAddressSet (
     73   IN ESL_PORT * pPort,
     74   IN CONST struct sockaddr * pSockAddr,
     75   IN BOOLEAN bBindTest
     76   )
     77 {
     78   EFI_IP4_CONFIG_DATA * pConfig;
     79   CONST struct sockaddr_in * pIpAddress;
     80   CONST UINT8 * pIpv4Address;
     81   EFI_STATUS Status;
     82 
     83   DBG_ENTER ( );
     84 
     85   //  Validate the address
     86   pIpAddress = (struct sockaddr_in *)pSockAddr;
     87   if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
     88     //  The local address must not be the broadcast address
     89     Status = EFI_INVALID_PARAMETER;
     90     pPort->pSocket->errno = EADDRNOTAVAIL;
     91   }
     92   else {
     93     Status = EFI_SUCCESS;
     94 
     95     //  Set the local address
     96     pIpAddress = (struct sockaddr_in *)pSockAddr;
     97     pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
     98     pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
     99     pConfig->StationAddress.Addr[0] = pIpv4Address[0];
    100     pConfig->StationAddress.Addr[1] = pIpv4Address[1];
    101     pConfig->StationAddress.Addr[2] = pIpv4Address[2];
    102     pConfig->StationAddress.Addr[3] = pIpv4Address[3];
    103 
    104     //  Determine if the default address is used
    105     pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
    106 
    107     //  Display the local address
    108     DEBUG (( DEBUG_BIND,
    109               "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",
    110               pPort,
    111               pConfig->StationAddress.Addr[0],
    112               pConfig->StationAddress.Addr[1],
    113               pConfig->StationAddress.Addr[2],
    114               pConfig->StationAddress.Addr[3]));
    115 
    116     //  Set the subnet mask
    117     if ( pConfig->UseDefaultAddress ) {
    118       pConfig->SubnetMask.Addr[0] = 0;
    119       pConfig->SubnetMask.Addr[1] = 0;
    120       pConfig->SubnetMask.Addr[2] = 0;
    121       pConfig->SubnetMask.Addr[3] = 0;
    122     }
    123     else {
    124       pConfig->SubnetMask.Addr[0] = 0xff;
    125       pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
    126       pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
    127       pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;
    128     }
    129   }
    130   //  Return the operation status
    131   DBG_EXIT_STATUS ( Status );
    132   return Status;
    133 }
    134 
    135 
    136 /** Get the option value.
    137 
    138   This routine handles the IPv4 level options.
    139 
    140   The ::EslSocketOptionGet routine calls this routine to retrieve
    141   the IPv4 options one at a time by name.
    142 
    143   @param [in] pSocket           Address of an ::ESL_SOCKET structure
    144   @param [in] OptionName        Name of the option
    145   @param [out] ppOptionData     Buffer to receive address of option value
    146   @param [out] pOptionLength    Buffer to receive the option length
    147 
    148   @retval EFI_SUCCESS - Socket data successfully received
    149  **/
    150 EFI_STATUS
    151 EslIp4OptionGet (
    152   IN ESL_SOCKET * pSocket,
    153   IN int OptionName,
    154   OUT CONST void ** __restrict ppOptionData,
    155   OUT socklen_t * __restrict pOptionLength
    156   )
    157 {
    158   EFI_STATUS Status;
    159 
    160   DBG_ENTER ( );
    161 
    162   //  Assume success
    163   pSocket->errno = 0;
    164   Status = EFI_SUCCESS;
    165 
    166   //  Attempt to get the option
    167   switch ( OptionName ) {
    168   default:
    169     //  Option not supported
    170     pSocket->errno = ENOPROTOOPT;
    171     Status = EFI_INVALID_PARAMETER;
    172     break;
    173 
    174   case IP_HDRINCL:
    175     *ppOptionData = (void *)&pSocket->bIncludeHeader;
    176     *pOptionLength = sizeof ( pSocket->bIncludeHeader );
    177     break;
    178   }
    179   //  Return the operation status
    180   DBG_EXIT_STATUS ( Status );
    181   return Status;
    182 }
    183 
    184 
    185 /** Set the option value.
    186 
    187   This routine handles the IPv4 level options.
    188 
    189   The ::EslSocketOptionSet routine calls this routine to adjust
    190   the IPv4 options one at a time by name.
    191 
    192   @param [in] pSocket         Address of an ::ESL_SOCKET structure
    193   @param [in] OptionName      Name of the option
    194   @param [in] pOptionValue    Buffer containing the option value
    195   @param [in] OptionLength    Length of the buffer in bytes
    196 
    197   @retval EFI_SUCCESS - Option successfully set
    198  **/
    199 EFI_STATUS
    200 EslIp4OptionSet (
    201   IN ESL_SOCKET * pSocket,
    202   IN int OptionName,
    203   IN CONST void * pOptionValue,
    204   IN socklen_t OptionLength
    205   )
    206 {
    207   BOOLEAN bTrueFalse;
    208   //socklen_t LengthInBytes;
    209   //UINT8 * pOptionData;
    210   EFI_STATUS Status;
    211 
    212   DBG_ENTER ( );
    213 
    214   //  Assume success
    215   pSocket->errno = 0;
    216   Status = EFI_SUCCESS;
    217 
    218   //  Determine if the option protocol matches
    219   //LengthInBytes = 0;
    220   //pOptionData = NULL;
    221   switch ( OptionName ) {
    222   default:
    223     //  Protocol level not supported
    224     DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));
    225     pSocket->errno = ENOTSUP;
    226     Status = EFI_UNSUPPORTED;
    227     break;
    228 
    229   case IP_HDRINCL:
    230 
    231     //  Validate the option length
    232     if ( sizeof ( UINT32 ) == OptionLength ) {
    233       //  Restrict the input to TRUE or FALSE
    234       bTrueFalse = TRUE;
    235       if ( 0 == *(UINT32 *)pOptionValue ) {
    236         bTrueFalse = FALSE;
    237       }
    238       pOptionValue = &bTrueFalse;
    239 
    240       //  Set the option value
    241       //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;
    242       //LengthInBytes = sizeof ( pSocket->bIncludeHeader );
    243     }
    244     break;
    245   }
    246   //  Return the operation status
    247   DBG_EXIT_STATUS ( Status );
    248   return Status;
    249 }
    250 
    251 
    252 /**
    253   Free a receive packet
    254 
    255   This routine performs the network specific operations necessary
    256   to free a receive packet.
    257 
    258   This routine is called by ::EslSocketPortCloseTxDone to free a
    259   receive packet.
    260 
    261   @param [in] pPacket         Address of an ::ESL_PACKET structure.
    262   @param [in, out] pRxBytes   Address of the count of RX bytes
    263 
    264 **/
    265 VOID
    266 EslIp4PacketFree (
    267   IN ESL_PACKET * pPacket,
    268   IN OUT size_t * pRxBytes
    269   )
    270 {
    271   EFI_IP4_RECEIVE_DATA * pRxData;
    272   DBG_ENTER ( );
    273 
    274   //
    275   //  Account for the receive bytes
    276   //
    277   pRxData = pPacket->Op.Ip4Rx.pRxData;
    278   *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;
    279 
    280   //
    281   //  Disconnect the buffer from the packet
    282   //
    283   pPacket->Op.Ip4Rx.pRxData = NULL;
    284 
    285   //
    286   //  Return the buffer to the IP4 driver
    287   //
    288   gBS->SignalEvent ( pRxData->RecycleSignal );
    289   DBG_EXIT ( );
    290 }
    291 
    292 
    293 /**
    294   Initialize the network specific portions of an ::ESL_PORT structure.
    295 
    296   This routine initializes the network specific portions of an
    297   ::ESL_PORT structure for use by the socket.
    298 
    299   This support routine is called by ::EslSocketPortAllocate
    300   to connect the socket with the underlying network adapter
    301   running the IPv4 protocol.
    302 
    303   @param [in] pPort       Address of an ESL_PORT structure
    304   @param [in] DebugFlags  Flags for debug messages
    305 
    306   @retval EFI_SUCCESS - Socket successfully created
    307 
    308  **/
    309 EFI_STATUS
    310 EslIp4PortAllocate (
    311   IN ESL_PORT * pPort,
    312   IN UINTN DebugFlags
    313   )
    314 {
    315   EFI_IP4_CONFIG_DATA * pConfig;
    316   ESL_SOCKET * pSocket;
    317   EFI_STATUS Status;
    318 
    319   DBG_ENTER ( );
    320 
    321   //
    322   //  Initialize the port
    323   //
    324   pSocket = pPort->pSocket;
    325   pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );
    326   pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );
    327   pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );
    328 
    329   //
    330   //  Save the cancel, receive and transmit addresses
    331   //
    332   pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure;
    333   pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;
    334   pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll;
    335   pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;
    336   pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;
    337 
    338   //
    339   //  Set the configuration flags
    340   //
    341   pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
    342   pConfig->AcceptIcmpErrors = FALSE;
    343   pConfig->AcceptBroadcast = FALSE;
    344   pConfig->AcceptPromiscuous = FALSE;
    345   pConfig->TypeOfService = 0;
    346   pConfig->TimeToLive = 255;
    347   pConfig->DoNotFragment = FALSE;
    348   pConfig->RawData = FALSE;
    349   pConfig->ReceiveTimeout = 0;
    350   pConfig->TransmitTimeout = 0;
    351 
    352   //
    353   //  Set the default protocol
    354   //
    355   pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;
    356   pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );
    357   Status = EFI_SUCCESS;
    358 
    359   //
    360   //  Return the operation status
    361   //
    362   DBG_EXIT_STATUS ( Status );
    363   return Status;
    364 }
    365 
    366 
    367 /**
    368   Receive data from a network connection.
    369 
    370   This routine attempts to return buffered data to the caller.  The
    371   data is removed from the urgent queue if the message flag MSG_OOB
    372   is specified, otherwise data is removed from the normal queue.
    373   See the \ref ReceiveEngine section.
    374 
    375   This routine is called by ::EslSocketReceive to handle the network
    376   specific receive operation to support SOCK_RAW sockets.
    377 
    378   @param [in] pPort           Address of an ::ESL_PORT structure.
    379 
    380   @param [in] pPacket         Address of an ::ESL_PACKET structure.
    381 
    382   @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
    383 
    384   @param [in] BufferLength    Length of the the buffer
    385 
    386   @param [in] pBuffer         Address of a buffer to receive the data.
    387 
    388   @param [in] pDataLength     Number of received data bytes in the buffer.
    389 
    390   @param [out] pAddress       Network address to receive the remote system address
    391 
    392   @param [out] pSkipBytes     Address to receive the number of bytes skipped
    393 
    394   @return   Returns the address of the next free byte in the buffer.
    395 
    396  **/
    397 UINT8 *
    398 EslIp4Receive (
    399   IN ESL_PORT * pPort,
    400   IN ESL_PACKET * pPacket,
    401   IN BOOLEAN * pbConsumePacket,
    402   IN size_t BufferLength,
    403   IN UINT8 * pBuffer,
    404   OUT size_t * pDataLength,
    405   OUT struct sockaddr * pAddress,
    406   OUT size_t * pSkipBytes
    407   )
    408 {
    409   size_t DataBytes;
    410   size_t HeaderBytes;
    411   size_t LengthInBytes;
    412   struct sockaddr_in * pRemoteAddress;
    413   EFI_IP4_RECEIVE_DATA * pRxData;
    414 
    415   DBG_ENTER ( );
    416 
    417   //
    418   //  Return the remote system address if requested
    419   //
    420   pRxData = pPacket->Op.Ip4Rx.pRxData;
    421   if ( NULL != pAddress ) {
    422     //
    423     //  Build the remote address
    424     //
    425     DEBUG (( DEBUG_RX,
    426               "Getting packet remote address: %d.%d.%d.%d\r\n",
    427               pRxData->Header->SourceAddress.Addr[0],
    428               pRxData->Header->SourceAddress.Addr[1],
    429               pRxData->Header->SourceAddress.Addr[2],
    430               pRxData->Header->SourceAddress.Addr[3]));
    431     pRemoteAddress = (struct sockaddr_in *)pAddress;
    432     CopyMem ( &pRemoteAddress->sin_addr,
    433               &pRxData->Header->SourceAddress.Addr[0],
    434               sizeof ( pRemoteAddress->sin_addr ));
    435   }
    436 
    437   //
    438   //  Copy the IP header
    439   //
    440   HeaderBytes = pRxData->HeaderLength;
    441   if ( HeaderBytes > BufferLength ) {
    442     HeaderBytes = BufferLength;
    443   }
    444   DEBUG (( DEBUG_RX,
    445             "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
    446             pRxData->Header,
    447             pBuffer,
    448             HeaderBytes ));
    449   CopyMem ( pBuffer, pRxData->Header, HeaderBytes );
    450   pBuffer += HeaderBytes;
    451   LengthInBytes = HeaderBytes;
    452 
    453   //
    454   //  Copy the received data
    455   //
    456   if ( 0 < ( BufferLength - LengthInBytes )) {
    457     pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,
    458                                               &pRxData->FragmentTable[0],
    459                                               BufferLength - LengthInBytes,
    460                                               pBuffer,
    461                                               &DataBytes );
    462     LengthInBytes += DataBytes;
    463   }
    464 
    465   //
    466   //  Determine if the data is being read
    467   //
    468   if ( *pbConsumePacket ) {
    469     //
    470     //  Display for the bytes consumed
    471     //
    472     DEBUG (( DEBUG_RX,
    473               "0x%08x: Port account for 0x%08x bytes\r\n",
    474               pPort,
    475               LengthInBytes ));
    476 
    477     //
    478     //  Account for any discarded data
    479     //
    480     *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;
    481   }
    482 
    483   //
    484   //  Return the data length and the buffer address
    485   //
    486   *pDataLength = LengthInBytes;
    487   DBG_EXIT_HEX ( pBuffer );
    488   return pBuffer;
    489 }
    490 
    491 
    492 /**
    493   Get the remote socket address
    494 
    495   This routine returns the address of the remote connection point
    496   associated with the SOCK_RAW socket.
    497 
    498   This routine is called by ::EslSocketGetPeerAddress to detemine
    499   the IPv4 address associated with the network adapter.
    500 
    501   @param [in] pPort       Address of an ::ESL_PORT structure.
    502 
    503   @param [out] pAddress   Network address to receive the remote system address
    504 
    505 **/
    506 VOID
    507 EslIp4RemoteAddressGet (
    508   IN ESL_PORT * pPort,
    509   OUT struct sockaddr * pAddress
    510   )
    511 {
    512   struct sockaddr_in * pRemoteAddress;
    513   ESL_IP4_CONTEXT * pIp4;
    514 
    515   DBG_ENTER ( );
    516 
    517   //
    518   //  Return the remote address
    519   //
    520   pIp4 = &pPort->Context.Ip4;
    521   pRemoteAddress = (struct sockaddr_in *)pAddress;
    522   pRemoteAddress->sin_family = AF_INET;
    523   CopyMem ( &pRemoteAddress->sin_addr,
    524             &pIp4->DestinationAddress.Addr[0],
    525             sizeof ( pRemoteAddress->sin_addr ));
    526 
    527   DBG_EXIT ( );
    528 }
    529 
    530 
    531 /**
    532   Set the remote address
    533 
    534   This routine sets the remote address in the port.
    535 
    536   This routine is called by ::EslSocketConnect to specify the
    537   remote network address.
    538 
    539   @param [in] pPort           Address of an ::ESL_PORT structure.
    540 
    541   @param [in] pSockAddr       Network address of the remote system.
    542 
    543   @param [in] SockAddrLength  Length in bytes of the network address.
    544 
    545   @retval EFI_SUCCESS     The operation was successful
    546 
    547  **/
    548 EFI_STATUS
    549 EslIp4RemoteAddressSet (
    550   IN ESL_PORT * pPort,
    551   IN CONST struct sockaddr * pSockAddr,
    552   IN socklen_t SockAddrLength
    553   )
    554 {
    555   ESL_IP4_CONTEXT * pIp4;
    556   CONST struct sockaddr_in * pRemoteAddress;
    557   EFI_STATUS Status;
    558 
    559   DBG_ENTER ( );
    560 
    561   //
    562   //  Set the remote address
    563   //
    564   pIp4 = &pPort->Context.Ip4;
    565   pRemoteAddress = (struct sockaddr_in *)pSockAddr;
    566   pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
    567   pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
    568   pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
    569   pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
    570   pPort->pSocket->bAddressSet = TRUE;
    571   Status = EFI_SUCCESS;
    572 
    573   //
    574   //  Return the operation status
    575   //
    576   DBG_EXIT_STATUS ( Status );
    577   return Status;
    578 }
    579 
    580 
    581 /**
    582   Process the receive completion
    583 
    584   This routine keeps the IPv4 driver's buffer and queues it in
    585   in FIFO order to the data queue.  The IP4 driver's buffer will
    586   be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
    587   See the \ref ReceiveEngine section.
    588 
    589   This routine is called by the IPv4 driver when data is
    590   received.
    591 
    592   @param [in] Event     The receive completion event
    593 
    594   @param [in] pIo       The address of an ::ESL_IO_MGMT structure
    595 
    596 **/
    597 VOID
    598 EslIp4RxComplete (
    599   IN EFI_EVENT Event,
    600   IN ESL_IO_MGMT * pIo
    601   )
    602 {
    603   size_t LengthInBytes;
    604   ESL_PACKET * pPacket;
    605   EFI_IP4_RECEIVE_DATA * pRxData;
    606   EFI_STATUS Status;
    607 
    608   DBG_ENTER ( );
    609 
    610   //
    611   //  Get the operation status.
    612   //
    613   Status = pIo->Token.Ip4Rx.Status;
    614 
    615   //
    616   //  Get the packet length
    617   //
    618   pRxData = pIo->Token.Ip4Rx.Packet.RxData;
    619   LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;
    620 
    621   //{{
    622   //      +--------------------+   +----------------------+
    623   //      | ESL_IO_MGMT        |   |      Data Buffer     |
    624   //      |                    |   |     (Driver owned)   |
    625   //      |    +---------------+   +----------------------+
    626   //      |    | Token         |               ^
    627   //      |    |      Rx Event |               |
    628   //      |    |               |   +----------------------+
    629   //      |    |        RxData --> | EFI_IP4_RECEIVE_DATA |
    630   //      +----+---------------+   |    (Driver owned)    |
    631   //                               +----------------------+
    632   //      +--------------------+               ^
    633   //      | ESL_PACKET         |               .
    634   //      |                    |               .
    635   //      |    +---------------+               .
    636   //      |    |       pRxData --> NULL  .......
    637   //      +----+---------------+
    638   //
    639   //
    640   //  Save the data in the packet
    641   //}}
    642   pPacket = pIo->pPacket;
    643   pPacket->Op.Ip4Rx.pRxData = pRxData;
    644 
    645   //
    646   //  Complete this request
    647   //
    648   EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
    649   DBG_EXIT ( );
    650 }
    651 
    652 
    653 /**
    654   Determine if the socket is configured.
    655 
    656   This routine uses the flag ESL_SOCKET::bConfigured to determine
    657   if the network layer's configuration routine has been called.
    658   This routine calls the ::EslSocketBind and configuration routines
    659   if they were not already called.  After the port is configured,
    660   the \ref ReceiveEngine is started.
    661 
    662   This routine is called by EslSocketIsConfigured to verify
    663   that the socket is configured.
    664 
    665   @param [in] pSocket         Address of an ::ESL_SOCKET structure
    666 
    667   @retval EFI_SUCCESS - The port is connected
    668   @retval EFI_NOT_STARTED - The port is not connected
    669 
    670  **/
    671  EFI_STATUS
    672  EslIp4SocketIsConfigured (
    673   IN ESL_SOCKET * pSocket
    674   )
    675 {
    676   UINTN Index;
    677   ESL_PORT * pPort;
    678   ESL_PORT * pNextPort;
    679   ESL_IP4_CONTEXT * pIp4;
    680   EFI_IP4_PROTOCOL * pIp4Protocol;
    681   EFI_STATUS Status;
    682   struct sockaddr_in LocalAddress;
    683 
    684   DBG_ENTER ( );
    685 
    686   //
    687   //  Assume success
    688   //
    689   Status = EFI_SUCCESS;
    690 
    691   //
    692   //  Configure the port if necessary
    693   //
    694   if ( !pSocket->bConfigured ) {
    695     //
    696     //  Fill in the port list if necessary
    697     //
    698     pSocket->errno = ENETDOWN;
    699     if ( NULL == pSocket->pPortList ) {
    700       LocalAddress.sin_len = sizeof ( LocalAddress );
    701       LocalAddress.sin_family = AF_INET;
    702       LocalAddress.sin_addr.s_addr = 0;
    703       LocalAddress.sin_port = 0;
    704       Status = EslSocketBind ( &pSocket->SocketProtocol,
    705                                (struct sockaddr *)&LocalAddress,
    706                                LocalAddress.sin_len,
    707                                &pSocket->errno );
    708     }
    709 
    710     //
    711     //  Walk the port list
    712     //
    713     pPort = pSocket->pPortList;
    714     while ( NULL != pPort ) {
    715       //
    716       //  Update the raw setting
    717       //
    718       pIp4 = &pPort->Context.Ip4;
    719       if ( pSocket->bIncludeHeader ) {
    720         //
    721         //  IP header will be included with the data on transmit
    722         //
    723         pIp4->ModeData.ConfigData.RawData = TRUE;
    724       }
    725 
    726       //
    727       //  Attempt to configure the port
    728       //
    729       pNextPort = pPort->pLinkSocket;
    730       pIp4Protocol = pPort->pProtocol.IPv4;
    731       DEBUG (( DEBUG_TX,
    732                 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
    733                           pPort,
    734                           pIp4->ModeData.ConfigData.StationAddress.Addr[0],
    735                           pIp4->ModeData.ConfigData.StationAddress.Addr[1],
    736                           pIp4->ModeData.ConfigData.StationAddress.Addr[2],
    737                           pIp4->ModeData.ConfigData.StationAddress.Addr[3],
    738                           pIp4->DestinationAddress.Addr[0],
    739                           pIp4->DestinationAddress.Addr[1],
    740                           pIp4->DestinationAddress.Addr[2],
    741                           pIp4->DestinationAddress.Addr[3]));
    742       Status = pIp4Protocol->Configure ( pIp4Protocol,
    743                                           &pIp4->ModeData.ConfigData );
    744       if ( !EFI_ERROR ( Status )) {
    745         //
    746         //  Update the configuration data
    747         //
    748         Status = pIp4Protocol->GetModeData ( pIp4Protocol,
    749                                              &pIp4->ModeData,
    750                                              NULL,
    751                                              NULL );
    752       }
    753       if ( EFI_ERROR ( Status )) {
    754         if ( !pSocket->bConfigured ) {
    755           DEBUG (( DEBUG_LISTEN,
    756                     "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
    757                     Status ));
    758           switch ( Status ) {
    759           case EFI_ACCESS_DENIED:
    760             pSocket->errno = EACCES;
    761             break;
    762 
    763           default:
    764           case EFI_DEVICE_ERROR:
    765             pSocket->errno = EIO;
    766             break;
    767 
    768           case EFI_INVALID_PARAMETER:
    769             pSocket->errno = EADDRNOTAVAIL;
    770             break;
    771 
    772           case EFI_NO_MAPPING:
    773             pSocket->errno = EAFNOSUPPORT;
    774             break;
    775 
    776           case EFI_OUT_OF_RESOURCES:
    777             pSocket->errno = ENOBUFS;
    778             break;
    779 
    780           case EFI_UNSUPPORTED:
    781             pSocket->errno = EOPNOTSUPP;
    782             break;
    783           }
    784         }
    785       }
    786       else {
    787         DEBUG (( DEBUG_TX,
    788                   "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
    789                   pPort,
    790                   pIp4->ModeData.ConfigData.StationAddress.Addr[0],
    791                   pIp4->ModeData.ConfigData.StationAddress.Addr[1],
    792                   pIp4->ModeData.ConfigData.StationAddress.Addr[2],
    793                   pIp4->ModeData.ConfigData.StationAddress.Addr[3],
    794                   pIp4->DestinationAddress.Addr[0],
    795                   pIp4->DestinationAddress.Addr[1],
    796                   pIp4->DestinationAddress.Addr[2],
    797                   pIp4->DestinationAddress.Addr[3]));
    798         DEBUG (( DEBUG_TX,
    799                   "Subnet Mask: %d.%d.%d.%d\r\n",
    800                   pIp4->ModeData.ConfigData.SubnetMask.Addr[0],
    801                   pIp4->ModeData.ConfigData.SubnetMask.Addr[1],
    802                   pIp4->ModeData.ConfigData.SubnetMask.Addr[2],
    803                   pIp4->ModeData.ConfigData.SubnetMask.Addr[3]));
    804         DEBUG (( DEBUG_TX,
    805                   "Route Count: %d\r\n",
    806                   pIp4->ModeData.RouteCount ));
    807         for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) {
    808           if ( 0 == Index ) {
    809             DEBUG (( DEBUG_TX, "Route Table:\r\n" ));
    810           }
    811           DEBUG (( DEBUG_TX,
    812                     "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
    813                     Index,
    814                     pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0],
    815                     pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1],
    816                     pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2],
    817                     pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3],
    818                     pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0],
    819                     pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1],
    820                     pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2],
    821                     pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3],
    822                     pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0],
    823                     pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1],
    824                     pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2],
    825                     pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3]));
    826         }
    827         pPort->bConfigured = TRUE;
    828         pSocket->bConfigured = TRUE;
    829 
    830         //
    831         //  Start the first read on the port
    832         //
    833         EslSocketRxStart ( pPort );
    834 
    835         //
    836         //  The socket is connected
    837         //
    838         pSocket->State = SOCKET_STATE_CONNECTED;
    839         pSocket->errno = 0;
    840       }
    841 
    842       //
    843       //  Set the next port
    844       //
    845       pPort = pNextPort;
    846     }
    847   }
    848 
    849   //
    850   //  Determine the socket configuration status
    851   //
    852   Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
    853 
    854   //
    855   //  Return the port connected state.
    856   //
    857   DBG_EXIT_STATUS ( Status );
    858   return Status;
    859 }
    860 
    861 
    862 /**
    863   Buffer data for transmission over a network connection.
    864 
    865   This routine buffers data for the transmit engine in the normal
    866   data queue.  When the \ref TransmitEngine has resources, this
    867   routine will start the transmission of the next buffer on the
    868   network connection.
    869 
    870   This routine is called by ::EslSocketTransmit to buffer
    871   data for transmission.  The data is copied into a local buffer
    872   freeing the application buffer for reuse upon return.  When
    873   necessary, this routine starts the transmit engine that
    874   performs the data transmission on the network connection.  The
    875   transmit engine transmits the data a packet at a time over the
    876   network connection.
    877 
    878   Transmission errors are returned during the next transmission or
    879   during the close operation.  Only buffering errors are returned
    880   during the current transmission attempt.
    881 
    882   @param [in] pSocket         Address of an ::ESL_SOCKET structure
    883 
    884   @param [in] Flags           Message control flags
    885 
    886   @param [in] BufferLength    Length of the the buffer
    887 
    888   @param [in] pBuffer         Address of a buffer to receive the data.
    889 
    890   @param [in] pDataLength     Number of received data bytes in the buffer.
    891 
    892   @param [in] pAddress        Network address of the remote system address
    893 
    894   @param [in] AddressLength   Length of the remote network address structure
    895 
    896   @retval EFI_SUCCESS - Socket data successfully buffered
    897 
    898 **/
    899 EFI_STATUS
    900 EslIp4TxBuffer (
    901   IN ESL_SOCKET * pSocket,
    902   IN int Flags,
    903   IN size_t BufferLength,
    904   IN CONST UINT8 * pBuffer,
    905   OUT size_t * pDataLength,
    906   IN const struct sockaddr * pAddress,
    907   IN socklen_t AddressLength
    908   )
    909 {
    910   ESL_PACKET * pPacket;
    911   ESL_PACKET * pPreviousPacket;
    912   ESL_PORT * pPort;
    913   const struct sockaddr_in * pRemoteAddress;
    914   ESL_IP4_CONTEXT * pIp4;
    915   size_t * pTxBytes;
    916   ESL_IP4_TX_DATA * pTxData;
    917   EFI_STATUS Status;
    918   EFI_TPL TplPrevious;
    919 
    920   DBG_ENTER ( );
    921 
    922   //
    923   //  Assume failure
    924   //
    925   Status = EFI_UNSUPPORTED;
    926   pSocket->errno = ENOTCONN;
    927   *pDataLength = 0;
    928 
    929   //
    930   //  Verify that the socket is connected
    931   //
    932   if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
    933     //
    934     //  Verify that there is enough room to buffer another
    935     //  transmit operation
    936     //
    937     pTxBytes = &pSocket->TxBytes;
    938     if ( pSocket->MaxTxBuf > *pTxBytes ) {
    939       //
    940       //  Locate the port
    941       //
    942       pPort = pSocket->pPortList;
    943       while ( NULL != pPort ) {
    944         //
    945         //  Determine the queue head
    946         //
    947         pIp4 = &pPort->Context.Ip4;
    948 
    949         //
    950         //  Attempt to allocate the packet
    951         //
    952         Status = EslSocketPacketAllocate ( &pPacket,
    953                                            sizeof ( pPacket->Op.Ip4Tx )
    954                                            - sizeof ( pPacket->Op.Ip4Tx.Buffer )
    955                                            + BufferLength,
    956                                            0,
    957                                            DEBUG_TX );
    958         if ( !EFI_ERROR ( Status )) {
    959           //
    960           //  Initialize the transmit operation
    961           //
    962           pTxData = &pPacket->Op.Ip4Tx;
    963           pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0];
    964           pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1];
    965           pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2];
    966           pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3];
    967           pTxData->TxData.OverrideData = NULL;
    968           pTxData->TxData.OptionsLength = 0;
    969           pTxData->TxData.OptionsBuffer = NULL;
    970           pTxData->TxData.TotalDataLength = (UINT32) BufferLength;
    971           pTxData->TxData.FragmentCount = 1;
    972           pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;
    973           pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0];
    974 
    975           //
    976           //  Set the remote system address if necessary
    977           //
    978           if ( NULL != pAddress ) {
    979             pRemoteAddress = (const struct sockaddr_in *)pAddress;
    980             pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0];
    981             pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1];
    982             pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2];
    983             pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3];
    984             pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;
    985             pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
    986             pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
    987             pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
    988             pTxData->Override.GatewayAddress.Addr[0] = 0;
    989             pTxData->Override.GatewayAddress.Addr[1] = 0;
    990             pTxData->Override.GatewayAddress.Addr[2] = 0;
    991             pTxData->Override.GatewayAddress.Addr[3] = 0;
    992             pTxData->Override.Protocol = (UINT8)pSocket->Protocol;
    993             pTxData->Override.TypeOfService = 0;
    994             pTxData->Override.TimeToLive = 255;
    995             pTxData->Override.DoNotFragment = FALSE;
    996 
    997             //
    998             //  Use the remote system address when sending this packet
    999             //
   1000             pTxData->TxData.OverrideData = &pTxData->Override;
   1001           }
   1002 
   1003           //
   1004           //  Copy the data into the buffer
   1005           //
   1006           CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0],
   1007                     pBuffer,
   1008                     BufferLength );
   1009 
   1010           //
   1011           //  Synchronize with the socket layer
   1012           //
   1013           RAISE_TPL ( TplPrevious, TPL_SOCKETS );
   1014 
   1015           //
   1016           //  Display the request
   1017           //
   1018           DEBUG (( DEBUG_TX,
   1019                     "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
   1020                     BufferLength,
   1021                     pBuffer,
   1022                     pIp4->ModeData.ConfigData.StationAddress.Addr[0],
   1023                     pIp4->ModeData.ConfigData.StationAddress.Addr[1],
   1024                     pIp4->ModeData.ConfigData.StationAddress.Addr[2],
   1025                     pIp4->ModeData.ConfigData.StationAddress.Addr[3],
   1026                     pTxData->TxData.DestinationAddress.Addr[0],
   1027                     pTxData->TxData.DestinationAddress.Addr[1],
   1028                     pTxData->TxData.DestinationAddress.Addr[2],
   1029                     pTxData->TxData.DestinationAddress.Addr[3]));
   1030 
   1031           //
   1032           //  Queue the data for transmission
   1033           //
   1034           pPacket->pNext = NULL;
   1035           pPreviousPacket = pSocket->pTxPacketListTail;
   1036           if ( NULL == pPreviousPacket ) {
   1037             pSocket->pTxPacketListHead = pPacket;
   1038           }
   1039           else {
   1040             pPreviousPacket->pNext = pPacket;
   1041           }
   1042           pSocket->pTxPacketListTail = pPacket;
   1043           DEBUG (( DEBUG_TX,
   1044                     "0x%08x: Packet on transmit list\r\n",
   1045                     pPacket ));
   1046 
   1047           //
   1048           //  Account for the buffered data
   1049           //
   1050           *pTxBytes += BufferLength;
   1051           *pDataLength = BufferLength;
   1052 
   1053           //
   1054           //  Start the transmit engine if it is idle
   1055           //
   1056           if ( NULL != pPort->pTxFree ) {
   1057             EslSocketTxStart ( pPort,
   1058                                &pSocket->pTxPacketListHead,
   1059                                &pSocket->pTxPacketListTail,
   1060                                &pPort->pTxActive,
   1061                                &pPort->pTxFree );
   1062 
   1063             //
   1064             //  Ignore any transmit error
   1065             //
   1066             if ( EFI_ERROR ( pSocket->TxError )) {
   1067               DEBUG (( DEBUG_TX,
   1068                        "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
   1069                        pPort,
   1070                        pPacket,
   1071                        pSocket->TxError ));
   1072             }
   1073             pSocket->TxError = EFI_SUCCESS;
   1074           }
   1075 
   1076           //
   1077           //  Release the socket layer synchronization
   1078           //
   1079           RESTORE_TPL ( TplPrevious );
   1080         }
   1081         else {
   1082           //
   1083           //  Packet allocation failed
   1084           //
   1085           pSocket->errno = ENOMEM;
   1086           break;
   1087         }
   1088 
   1089         //
   1090         //  Set the next port
   1091         //
   1092         pPort = pPort->pLinkSocket;
   1093       }
   1094     }
   1095     else {
   1096       //
   1097       //  Not enough buffer space available
   1098       //
   1099       pSocket->errno = EAGAIN;
   1100       Status = EFI_NOT_READY;
   1101     }
   1102   }
   1103 
   1104   //
   1105   //  Return the operation status
   1106   //
   1107   DBG_EXIT_STATUS ( Status );
   1108   return Status;
   1109 }
   1110 
   1111 
   1112 /**
   1113   Process the transmit completion
   1114 
   1115   This routine use ::EslSocketTxComplete to perform the transmit
   1116   completion processing for data packets.
   1117 
   1118   This routine is called by the IPv4 network layer when a data
   1119   transmit request completes.
   1120 
   1121   @param [in] Event     The normal transmit completion event
   1122 
   1123   @param [in] pIo       The address of an ::ESL_IO_MGMT structure
   1124 
   1125 **/
   1126 VOID
   1127 EslIp4TxComplete (
   1128   IN EFI_EVENT Event,
   1129   IN ESL_IO_MGMT * pIo
   1130   )
   1131 {
   1132   UINT32 LengthInBytes;
   1133   ESL_PORT * pPort;
   1134   ESL_PACKET * pPacket;
   1135   ESL_SOCKET * pSocket;
   1136   EFI_STATUS Status;
   1137 
   1138   DBG_ENTER ( );
   1139 
   1140   //
   1141   //  Locate the active transmit packet
   1142   //
   1143   pPacket = pIo->pPacket;
   1144   pPort = pIo->pPort;
   1145   pSocket = pPort->pSocket;
   1146 
   1147   //
   1148   //  Get the transmit length and status
   1149   //
   1150   LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength;
   1151   pSocket->TxBytes -= LengthInBytes;
   1152   Status = pIo->Token.Ip4Tx.Status;
   1153 
   1154   //
   1155   //  Ignore the transmit error
   1156   //
   1157   if ( EFI_ERROR ( Status )) {
   1158     DEBUG (( DEBUG_TX,
   1159              "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
   1160              pPort,
   1161              pPacket,
   1162              Status ));
   1163     Status = EFI_SUCCESS;
   1164   }
   1165 
   1166   //
   1167   //  Complete the transmit operation
   1168   //
   1169   EslSocketTxComplete ( pIo,
   1170                         LengthInBytes,
   1171                         Status,
   1172                         "Raw ",
   1173                         &pSocket->pTxPacketListHead,
   1174                         &pSocket->pTxPacketListTail,
   1175                         &pPort->pTxActive,
   1176                         &pPort->pTxFree );
   1177   DBG_EXIT ( );
   1178 }
   1179 
   1180 
   1181 /**
   1182   Verify the adapter's IP address
   1183 
   1184   This support routine is called by EslSocketBindTest.
   1185 
   1186   @param [in] pPort       Address of an ::ESL_PORT structure.
   1187   @param [in] pConfigData Address of the configuration data
   1188 
   1189   @retval EFI_SUCCESS - The IP address is valid
   1190   @retval EFI_NOT_STARTED - The IP address is invalid
   1191 
   1192  **/
   1193 EFI_STATUS
   1194 EslIp4VerifyLocalIpAddress (
   1195   IN ESL_PORT * pPort,
   1196   IN EFI_IP4_CONFIG_DATA * pConfigData
   1197   )
   1198 {
   1199   UINTN DataSize;
   1200   EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;
   1201   EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;
   1202   ESL_SERVICE * pService;
   1203   EFI_STATUS Status;
   1204 
   1205   DBG_ENTER ( );
   1206 
   1207   //
   1208   //  Use break instead of goto
   1209   //
   1210   pIfInfo = NULL;
   1211   for ( ; ; ) {
   1212     //
   1213     //  Determine if the IP address is specified
   1214     //
   1215     DEBUG (( DEBUG_BIND,
   1216               "UseDefaultAddress: %s\r\n",
   1217               pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));
   1218     DEBUG (( DEBUG_BIND,
   1219               "Requested IP address: %d.%d.%d.%d\r\n",
   1220               pConfigData->StationAddress.Addr [ 0 ],
   1221               pConfigData->StationAddress.Addr [ 1 ],
   1222               pConfigData->StationAddress.Addr [ 2 ],
   1223               pConfigData->StationAddress.Addr [ 3 ]));
   1224     if ( pConfigData->UseDefaultAddress
   1225       || (( 0 == pConfigData->StationAddress.Addr [ 0 ])
   1226       && ( 0 == pConfigData->StationAddress.Addr [ 1 ])
   1227       && ( 0 == pConfigData->StationAddress.Addr [ 2 ])
   1228       && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))
   1229     {
   1230       Status = EFI_SUCCESS;
   1231       break;
   1232     }
   1233 
   1234     //
   1235     //  Open the configuration protocol
   1236     //
   1237     pService = pPort->pService;
   1238     Status = gBS->OpenProtocol (
   1239                     pService->Controller,
   1240                     &gEfiIp4Config2ProtocolGuid,
   1241                     (VOID **)&pIpConfig2Protocol,
   1242                     NULL,
   1243                     NULL,
   1244                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1245                     );
   1246     if ( EFI_ERROR ( Status )) {
   1247       DEBUG (( DEBUG_ERROR,
   1248                 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
   1249                 Status ));
   1250       break;
   1251     }
   1252 
   1253     //
   1254     // Get the interface information size.
   1255     //
   1256     DataSize = 0;
   1257     Status = pIpConfig2Protocol->GetData (
   1258                                    pIpConfig2Protocol,
   1259                                    Ip4Config2DataTypeInterfaceInfo,
   1260                                    &DataSize,
   1261                                    NULL
   1262                                    );
   1263     if ( EFI_BUFFER_TOO_SMALL != Status ) {
   1264       DEBUG (( DEBUG_ERROR,
   1265                 "ERROR - Failed to get the interface information size, Status: %r\r\n",
   1266                 Status ));
   1267       break;
   1268     }
   1269 
   1270     //
   1271     //  Allocate the interface information buffer
   1272     //
   1273     pIfInfo = AllocatePool ( DataSize );
   1274     if ( NULL == pIfInfo ) {
   1275       DEBUG (( DEBUG_ERROR,
   1276                 "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
   1277       Status = EFI_OUT_OF_RESOURCES;
   1278       break;
   1279     }
   1280 
   1281     //
   1282     // Get the interface info.
   1283     //
   1284     Status = pIpConfig2Protocol->GetData (
   1285                                   pIpConfig2Protocol,
   1286                                   Ip4Config2DataTypeInterfaceInfo,
   1287                                   &DataSize,
   1288                                   pIfInfo
   1289                                   );
   1290     if ( EFI_ERROR ( Status )) {
   1291       DEBUG (( DEBUG_ERROR,
   1292                 "ERROR - Failed to return the interface info, Status: %r\r\n",
   1293                 Status ));
   1294       break;
   1295     }
   1296 
   1297     //
   1298     //  Display the current configuration
   1299     //
   1300     DEBUG (( DEBUG_BIND,
   1301               "Actual adapter IP address: %d.%d.%d.%d\r\n",
   1302               pIfInfo->StationAddress.Addr [ 0 ],
   1303               pIfInfo->StationAddress.Addr [ 1 ],
   1304               pIfInfo->StationAddress.Addr [ 2 ],
   1305               pIfInfo->StationAddress.Addr [ 3 ]));
   1306 
   1307     //
   1308     //  Assume the port is not configured
   1309     //
   1310     Status = EFI_SUCCESS;
   1311     if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])
   1312       && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])
   1313       && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])
   1314       && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {
   1315       break;
   1316     }
   1317 
   1318     //
   1319     //  The IP address did not match
   1320     //
   1321     Status = EFI_NOT_STARTED;
   1322     break;
   1323   }
   1324 
   1325   //
   1326   //  Free the buffer if necessary
   1327   //
   1328   if ( NULL != pIfInfo ) {
   1329     FreePool ( pIfInfo );
   1330   }
   1331 
   1332   //
   1333   //  Return the IP address status
   1334   //
   1335   DBG_EXIT_STATUS ( Status );
   1336   return Status;
   1337 }
   1338 
   1339 
   1340 /**
   1341   Interface between the socket layer and the network specific
   1342   code that supports SOCK_RAW sockets over IPv4.
   1343 **/
   1344 CONST ESL_PROTOCOL_API cEslIp4Api = {
   1345   "IPv4",
   1346     IPPROTO_IP,
   1347   OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ),
   1348   OFFSET_OF ( ESL_LAYER, pIp4List ),
   1349   OFFSET_OF ( struct sockaddr_in, sin_zero ),
   1350   sizeof ( struct sockaddr_in ),
   1351   AF_INET,
   1352   sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
   1353   sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
   1354   OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),
   1355   FALSE,
   1356   EADDRNOTAVAIL,
   1357   NULL,   //  Accept
   1358   NULL,   //  ConnectPoll
   1359   NULL,   //  ConnectStart
   1360   EslIp4SocketIsConfigured,
   1361   EslIp4LocalAddressGet,
   1362   EslIp4LocalAddressSet,
   1363   NULL,   //  Listen
   1364   EslIp4OptionGet,
   1365   EslIp4OptionSet,
   1366   EslIp4PacketFree,
   1367   EslIp4PortAllocate,
   1368   NULL,   //  PortClose
   1369   NULL,   //  PortCloseOp
   1370   TRUE,
   1371   EslIp4Receive,
   1372   EslIp4RemoteAddressGet,
   1373   EslIp4RemoteAddressSet,
   1374   EslIp4RxComplete,
   1375   NULL,   //  RxStart
   1376   EslIp4TxBuffer,
   1377   EslIp4TxComplete,
   1378   NULL,   //  TxOobComplete
   1379   (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress
   1380 };
   1381