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