/** Creates a child handle and installs gEfiSocketProtocolGuid. This routine creates a child handle for the socket driver and installs the ::gEfiSocketProtocolGuid on that handle with a pointer to the ::EFI_SOCKET_PROTOCOL structure address. This routine is called by ::EslServiceGetProtocol in UseSocketDxe when the socket application is linked with UseSocketDxe. @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure. @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL, then a new handle is created. If it is a pointer to an existing UEFI handle, then the protocol is added to the existing UEFI handle. @retval EFI_SUCCESS The protocol was added to ChildHandle. @retval EFI_INVALID_PARAMETER ChildHandle is NULL. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create the child @retval other The child handle was not created **/ EFI_STATUS EFIAPI EslDxeCreateChild ( IN EFI_SERVICE_BINDING_PROTOCOL * pThis, IN OUT EFI_HANDLE * pChildHandle ) { ESL_SOCKET * pSocket; EFI_STATUS Status; DBG_ENTER ( ); // // Create a socket structure // Status = EslSocketAllocate ( pChildHandle, DEBUG_SOCKET, &pSocket ); // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Set the remote address This routine sets the remote address in the port. This routine is called by ::EslSocketConnect to specify the remote network address. @param [in] pPort Address of an ::ESL_PORT structure. @param [in] pSockAddr Network address of the remote system. @param [in] SockAddrLength Length in bytes of the network address. @retval EFI_SUCCESS The operation was successful **/ EFI_STATUS EslUdp6RemoteAddressSet ( IN ESL_PORT * pPort, IN CONST struct sockaddr * pSockAddr, IN socklen_t SockAddrLength ) { CONST struct sockaddr_in6 * pRemoteAddress; ESL_UDP6_CONTEXT * pUdp6; EFI_STATUS Status; DBG_ENTER ( ); // // Set the remote address // pUdp6 = &pPort->Context.Udp6; pRemoteAddress = (struct sockaddr_in6 *)pSockAddr; CopyMem ( &pUdp6->ConfigData.RemoteAddress, &pRemoteAddress->sin6_addr, sizeof ( pUdp6->ConfigData.RemoteAddress )); pUdp6->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin6_port ); Status = EFI_SUCCESS; // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Initialize the network specific portions of an ::ESL_PORT structure. This routine initializes the network specific portions of an ::ESL_PORT structure for use by the socket. This support routine is called by ::EslSocketPortAllocate to connect the socket with the underlying network adapter running the UDPv4 protocol. @param [in] pPort Address of an ESL_PORT structure @param [in] DebugFlags Flags for debug messages @retval EFI_SUCCESS - Socket successfully created **/ EFI_STATUS EslUdp6PortAllocate ( IN ESL_PORT * pPort, IN UINTN DebugFlags ) { EFI_UDP6_CONFIG_DATA * pConfig; ESL_SOCKET * pSocket; EFI_STATUS Status; DBG_ENTER ( ); // // Initialize the port // pSocket = pPort->pSocket; pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp6Tx.TxData ); pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp6Tx.Event ); pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP6_COMPLETION_TOKEN, Packet.TxData ); // // Save the cancel, receive and transmit addresses // pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.UDPv6->Configure; pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Cancel; pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.UDPv6->Poll; pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Receive; pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv6->Transmit; // // Do not drop packets // pConfig = &pPort->Context.Udp6.ConfigData; pConfig->ReceiveTimeout = 0; pConfig->ReceiveTimeout = pConfig->ReceiveTimeout; // // Set the configuration flags // pConfig->AllowDuplicatePort = TRUE; pConfig->AcceptAnyPort = FALSE; pConfig->AcceptPromiscuous = FALSE; pConfig->HopLimit = 255; pConfig->TrafficClass = 0; Status = EFI_SUCCESS; // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Removes gEfiSocketProtocolGuid and destroys the child handle. This routine uninstalls ::gEfiSocketProtocolGuid from the child handle and destroys the child handle if necessary. This routine is called from ???. @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure. @param [in] ChildHandle Handle of the child to destroy @retval EFI_SUCCESS The protocol was removed from ChildHandle. @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle. @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle because its services are being used. @retval other The child handle was not destroyed **/ EFI_STATUS EFIAPI EslDxeDestroyChild ( IN EFI_SERVICE_BINDING_PROTOCOL * pThis, IN EFI_HANDLE ChildHandle ) { ESL_LAYER * pLayer; EFI_SOCKET_PROTOCOL * pSocketProtocol; EFI_STATUS Status; DBG_ENTER ( ); // // Locate the socket control structure // pLayer = &mEslLayer; Status = gBS->OpenProtocol ( ChildHandle, &gEfiSocketProtocolGuid, (VOID **)&pSocketProtocol, pLayer->ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( !EFI_ERROR ( Status )) { // // Free the socket resources // Status = EslSocketFree ( pSocketProtocol, NULL ); } else { DEBUG (( DEBUG_ERROR, "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n", ChildHandle, Status )); } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Ax88772 driver entry point. @param [in] ImageHandle Handle for the image. @param [in] pSystemTable Address of the system table. @retval EFI_SUCCESS Image successfully loaded. **/ EFI_STATUS EFIAPI EntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE * pSystemTable ) { EFI_STATUS Status; DBG_ENTER ( ); // // Add the driver to the list of drivers // Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, pSystemTable, &gDriverBinding, ImageHandle, &gComponentName, &gComponentName2 ); ASSERT_EFI_ERROR (Status); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n", ImageHandle )); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n", ImageHandle )); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n", ImageHandle )); } DBG_EXIT_STATUS ( Status ); return Status; }
/** Respond with the list of known pages @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS IndexPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { CONST DT_PAGE * pPage; CONST DT_PAGE * pPageEnd; EFI_STATUS Status; DBG_ENTER ( ); // // Send the index page // for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Index" ); if ( EFI_ERROR ( Status )) { break; } // // Build the table header // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>UEFI Web Server</h1>\r\n" "<table border=\"1\">\r\n" " <tr bgcolor=\"c0c0ff\"><th>Page</th><th>Description</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Walk the list of pages // Skip the first page // pPage = &mPageList[0]; pPageEnd = &pPage[mPageCount]; pPage += 1; while ( pPageEnd > pPage ) { // // Build the table entry for this page // Status = HttpSendAnsiString ( SocketFD, pPort, "<tr><td><a target=\"_blank\" href=\"" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendUnicodeString ( SocketFD, pPort, &pPage->pPageName[1]); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "\">" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendUnicodeString ( SocketFD, pPort, &pPage->pPageName[1]); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "</a></td><td>" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendUnicodeString ( SocketFD, pPort, pPage->pDescription ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "</td></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Set the next page // pPage += 1; } if ( EFI_ERROR ( Status )) { break; } // // Build the table trailer // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Start this driver on Controller by opening UsbIo and DevicePath protocols. Initialize PXE structures, create a copy of the Controller Device Path with the NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol on the newly created Device Path. @param [in] pThis Protocol instance pointer. @param [in] Controller Handle of device to work with. @param [in] pRemainingDevicePath Not used, always produce all possible children. @retval EFI_SUCCESS This driver is added to Controller. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI DriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL * pThis, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath ) { EFI_STATUS Status; NIC_DEVICE * pNicDevice; UINTN LengthInBytes; DBG_ENTER ( ); // // Allocate the device structure // LengthInBytes = sizeof ( *pNicDevice ); Status = gBS->AllocatePool ( EfiRuntimeServicesData, LengthInBytes, (VOID **) &pNicDevice ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT, "0x%08x: Allocate pNicDevice, %d bytes\r\n", pNicDevice, sizeof ( *pNicDevice ))); // // Set the structure signature // ZeroMem ( pNicDevice, LengthInBytes ); pNicDevice->Signature = DEV_SIGNATURE; // // Connect to the USB I/O protocol // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &pNicDevice->pUsbIo, pThis->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if ( !EFI_ERROR ( Status )) { // // Allocate the necessary events // Status = gBS->CreateEvent ( EVT_TIMER, TPL_AX88772, (EFI_EVENT_NOTIFY)Ax88772Timer, pNicDevice, (VOID **)&pNicDevice->Timer ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "0x%08x: Allocated timer\r\n", pNicDevice->Timer )); // // Initialize the simple network protocol // pNicDevice->Controller = Controller; SN_Setup ( pNicDevice ); // // Start the timer // Status = gBS->SetTimer ( pNicDevice->Timer, TimerPeriodic, TIMER_MSEC ); if ( !EFI_ERROR ( Status )) { // // Install both the simple network and device path protocols. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiCallerIdGuid, pNicDevice, &gEfiSimpleNetworkProtocolGuid, &pNicDevice->SimpleNetwork, NULL ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiCallerIdGuid on 0x%08x\r\n", Controller )); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiSimpleNetworkProtocolGuid on 0x%08x\r\n", Controller )); DBG_EXIT_STATUS ( Status ); return Status; } DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, "ERROR - Failed to install gEfiSimpleNetworkProtocol on 0x%08x\r\n", Controller )); } else { DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, "ERROR - Failed to start the timer, Status: %r\r\n", Status )); } } else { DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO, "ERROR - Failed to create timer event, Status: %r\r\n", Status )); } // // Done with the USB stack // gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, pThis->DriverBindingHandle, Controller ); } // // Done with the device // gBS->FreePool ( pNicDevice ); } // // Display the driver start status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Connect to the network service bindings Walk the network service protocols on the controller handle and locate any that are not in use. Create ::ESL_SERVICE structures to manage the network layer interfaces for the socket driver. Tag each of the network interfaces that are being used. Finally, this routine calls ESL_SOCKET_BINDING::pfnInitialize to prepare the network interface for use by the socket layer. @param [in] BindingHandle Handle for protocol binding. @param [in] Controller Handle of device to work with. @retval EFI_SUCCESS This driver is added to Controller. @retval EFI_OUT_OF_RESOURCES No more memory available. @retval EFI_UNSUPPORTED This driver does not support this device. **/ EFI_STATUS EFIAPI EslServiceConnect ( IN EFI_HANDLE BindingHandle, IN EFI_HANDLE Controller ) { BOOLEAN bInUse; EFI_STATUS ExitStatus; UINTN LengthInBytes; UINT8 * pBuffer; CONST ESL_SOCKET_BINDING * pEnd; VOID * pJunk; ESL_SERVICE ** ppServiceListHead; ESL_SERVICE * pService; CONST ESL_SOCKET_BINDING * pSocketBinding; EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding; EFI_STATUS Status; EFI_TPL TplPrevious; DBG_ENTER ( ); // // Assume the list is empty // ExitStatus = EFI_UNSUPPORTED; bInUse = FALSE; // // Walk the list of network connection points // pSocketBinding = &cEslSocketBinding[0]; pEnd = &pSocketBinding[ cEslSocketBindingEntries ]; while ( pEnd > pSocketBinding ) { // // Determine if the controller supports the network protocol // Status = gBS->OpenProtocol ( Controller, pSocketBinding->pNetworkBinding, (VOID**)&pServiceBinding, BindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( !EFI_ERROR ( Status )) { // // Determine if the socket layer is already connected // Status = gBS->OpenProtocol ( Controller, (EFI_GUID *)pSocketBinding->pTagGuid, &pJunk, BindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( EFI_UNSUPPORTED == Status ) { // // Allocate a service structure since the tag is not present // LengthInBytes = sizeof ( *pService ); Status = gBS->AllocatePool ( EfiRuntimeServicesData, LengthInBytes, (VOID **) &pService ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT, "0x%08x: Allocate pService, %d bytes\r\n", pService, LengthInBytes )); // // Set the structure signature and service binding // ZeroMem ( pService, LengthInBytes ); pService->Signature = SERVICE_SIGNATURE; pService->pSocketBinding = pSocketBinding; pService->Controller = Controller; pService->pServiceBinding = pServiceBinding; // // Mark the controller in use // if ( !bInUse ) { Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiCallerIdGuid, NULL, NULL ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: gEfiCallerIdGuid on 0x%08x\r\n", Controller )); bInUse = TRUE; } else { if ( EFI_INVALID_PARAMETER == Status ) { Status = EFI_SUCCESS; } } } if ( !EFI_ERROR ( Status )) { // // Mark the network service protocol in use // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, pSocketBinding->pTagGuid, pService, NULL ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Installed: %s TagGuid on 0x%08x\r\n", pSocketBinding->pName, Controller )); // // Synchronize with the socket layer // RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // // Connect the service to the list // pBuffer = (UINT8 *)&mEslLayer; pBuffer = &pBuffer[ pSocketBinding->ServiceListOffset ]; ppServiceListHead = (ESL_SERVICE **)pBuffer; pService->pNext = *ppServiceListHead; *ppServiceListHead = pService; // // Release the socket layer synchronization // RESTORE_TPL ( TplPrevious ); // // At least one service was made available // ExitStatus = EFI_SUCCESS; } else { DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, "ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n", pSocketBinding->pName, Controller, Status )); } if ( EFI_ERROR ( Status )) { // // The controller is no longer in use // if ( bInUse ) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiCallerIdGuid, NULL, NULL ); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Removed: gEfiCallerIdGuid from 0x%08x\r\n", Controller )); } } } else { DEBUG (( DEBUG_ERROR | DEBUG_INIT, "ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n", Controller, Status )); } // // Release the service if necessary // if ( EFI_ERROR ( Status )) { gBS->FreePool ( pService ); DEBUG (( DEBUG_POOL | DEBUG_INIT, "0x%08x: Free pService, %d bytes\r\n", pService, sizeof ( *pService ))); pService = NULL; } } else { DEBUG (( DEBUG_ERROR | DEBUG_INIT, "ERROR - Failed service allocation, Status: %r\r\n", Status )); ExitStatus = EFI_OUT_OF_RESOURCES; break; } } } // // Set the next network protocol // pSocketBinding += 1; } // // Display the driver start status // DBG_EXIT_STATUS ( ExitStatus ); return ExitStatus; }
/** Shutdown the connections to the network layer by locating the tags on the network interfaces established by ::EslServiceConnect. This routine shutdowns any activity on the network interface and then frees the ::ESL_SERVICE structures. @param [in] BindingHandle Handle for protocol binding. @param [in] Controller Handle of device to stop driver on. @retval EFI_SUCCESS This driver is removed Controller. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. @retval other This driver was not removed from this device. **/ EFI_STATUS EFIAPI EslServiceDisconnect ( IN EFI_HANDLE BindingHandle, IN EFI_HANDLE Controller ) { UINT8 * pBuffer; CONST ESL_SOCKET_BINDING * pEnd; ESL_PORT * pPort; ESL_SERVICE * pPreviousService; ESL_SERVICE * pService; ESL_SERVICE ** ppServiceListHead; CONST ESL_SOCKET_BINDING * pSocketBinding; EFI_STATUS Status; EFI_TPL TplPrevious; DBG_ENTER ( ); // // Walk the list of network connection points in reverse order // pEnd = &cEslSocketBinding[0]; pSocketBinding = &pEnd[ cEslSocketBindingEntries ]; while ( pEnd < pSocketBinding ) { // // Set the next network protocol // pSocketBinding -= 1; // // Determine if the driver connected // Status = gBS->OpenProtocol ( Controller, (EFI_GUID *)pSocketBinding->pTagGuid, (VOID **)&pService, BindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( !EFI_ERROR ( Status )) { // // Synchronize with the socket layer // RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // // Walk the list of ports // pPort = pService->pPortList; while ( NULL != pPort ) { // // Remove the port from the port list // pPort->pService = NULL; pService->pPortList = pPort->pLinkService; // // Close the port // EslSocketPortCloseStart ( pPort, TRUE, DEBUG_POOL | DEBUG_INIT ); // // Set the next port // pPort = pService->pPortList; } // // Remove the service from the service list // pBuffer = (UINT8 *)&mEslLayer; pBuffer = &pBuffer[ pService->pSocketBinding->ServiceListOffset ]; ppServiceListHead = (ESL_SERVICE **)pBuffer; pPreviousService = *ppServiceListHead; if ( pService == pPreviousService ) { // // Remove the service from the beginning of the list // *ppServiceListHead = pService->pNext; } else { // // Remove the service from the middle of the list // while ( NULL != pPreviousService ) { if ( pService == pPreviousService->pNext ) { pPreviousService->pNext = pService->pNext; break; } pPreviousService = pPreviousService->pNext; } } // // Release the socket layer synchronization // RESTORE_TPL ( TplPrevious ); // // Break the driver connection // Status = gBS->UninstallMultipleProtocolInterfaces ( Controller, pSocketBinding->pTagGuid, pService, NULL ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT, "Removed: %s TagGuid from 0x%08x\r\n", pSocketBinding->pName, Controller )); } else { DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT, "ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n", pSocketBinding->pName, Controller, Status )); } // // Free the service structure // Status = gBS->FreePool ( pService ); if ( !EFI_ERROR ( Status )) { DEBUG (( DEBUG_POOL | DEBUG_INIT, "0x%08x: Free pService, %d bytes\r\n", pService, sizeof ( *pService ))); } else { DEBUG (( DEBUG_POOL | DEBUG_INIT, "ERROR - Failed to free pService 0x%08x, Status: %r\r\n", pService, Status )); } pService = NULL; } } // // The controller is no longer in use // gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiCallerIdGuid, NULL, NULL ); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "Removed: gEfiCallerIdGuid from 0x%08x\r\n", Controller )); // // The driver is disconnected from the network controller // Status = EFI_SUCCESS; // // Display the driver start status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Buffer data for transmission over a network connection. This routine buffers data for the transmit engine in the normal data queue. When the \ref TransmitEngine has resources, this routine will start the transmission of the next buffer on the network connection. This routine is called by ::EslSocketTransmit to buffer data for transmission. The data is copied into a local buffer freeing the application buffer for reuse upon return. When necessary, this routine starts the transmit engine that performs the data transmission on the network connection. The transmit engine transmits the data a packet at a time over the network connection. Transmission errors are returned during the next transmission or during the close operation. Only buffering errors are returned during the current transmission attempt. @param [in] pSocket Address of an ::ESL_SOCKET structure @param [in] Flags Message control flags @param [in] BufferLength Length of the the buffer @param [in] pBuffer Address of a buffer to receive the data. @param [in] pDataLength Number of received data bytes in the buffer. @param [in] pAddress Network address of the remote system address @param [in] AddressLength Length of the remote network address structure @retval EFI_SUCCESS - Socket data successfully buffered **/ EFI_STATUS EslUdp6TxBuffer ( IN ESL_SOCKET * pSocket, IN int Flags, IN size_t BufferLength, IN CONST UINT8 * pBuffer, OUT size_t * pDataLength, IN const struct sockaddr * pAddress, IN socklen_t AddressLength ) { ESL_PACKET * pPacket; ESL_PACKET * pPreviousPacket; ESL_PORT * pPort; const struct sockaddr_in6 * pRemoteAddress; ESL_UDP6_CONTEXT * pUdp6; size_t * pTxBytes; ESL_UDP6_TX_DATA * pTxData; EFI_STATUS Status; EFI_TPL TplPrevious; DBG_ENTER ( ); // // Assume failure // Status = EFI_UNSUPPORTED; pSocket->errno = ENOTCONN; *pDataLength = 0; // // Verify that the socket is connected // if ( SOCKET_STATE_CONNECTED == pSocket->State ) { // // Verify that there is enough room to buffer another // transmit operation // pTxBytes = &pSocket->TxBytes; if ( pSocket->MaxTxBuf > *pTxBytes ) { // // Locate the port // pPort = pSocket->pPortList; while ( NULL != pPort ) { // // Determine the queue head // pUdp6 = &pPort->Context.Udp6; // // Attempt to allocate the packet // Status = EslSocketPacketAllocate ( &pPacket, sizeof ( pPacket->Op.Udp6Tx ) - sizeof ( pPacket->Op.Udp6Tx.Buffer ) + BufferLength, 0, DEBUG_TX ); if ( !EFI_ERROR ( Status )) { // // Initialize the transmit operation // pTxData = &pPacket->Op.Udp6Tx; pTxData->TxData.UdpSessionData = NULL; pTxData->TxData.DataLength = (UINT32) BufferLength; pTxData->TxData.FragmentCount = 1; pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength; pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp6Tx.Buffer[0]; // // Set the remote system address if necessary // pTxData->TxData.UdpSessionData = NULL; if ( NULL != pAddress ) { pRemoteAddress = (const struct sockaddr_in6 *)pAddress; CopyMem ( &pTxData->Session.SourceAddress, &pUdp6->ConfigData.StationAddress, sizeof ( pTxData->Session.SourceAddress )); pTxData->Session.SourcePort = 0; CopyMem ( &pTxData->Session.DestinationAddress, &pRemoteAddress->sin6_addr, sizeof ( pTxData->Session.DestinationAddress )); pTxData->Session.DestinationPort = SwapBytes16 ( pRemoteAddress->sin6_port ); // // Use the remote system address when sending this packet // pTxData->TxData.UdpSessionData = &pTxData->Session; } // // Copy the data into the buffer // CopyMem ( &pPacket->Op.Udp6Tx.Buffer[0], pBuffer, BufferLength ); // // Synchronize with the socket layer // RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // // Display the request // DEBUG (( DEBUG_TX, "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", BufferLength, pBuffer, pTxData->Session.DestinationAddress.Addr[0], pTxData->Session.DestinationAddress.Addr[1], pTxData->Session.DestinationAddress.Addr[2], pTxData->Session.DestinationAddress.Addr[3], pTxData->Session.DestinationAddress.Addr[4], pTxData->Session.DestinationAddress.Addr[5], pTxData->Session.DestinationAddress.Addr[6], pTxData->Session.DestinationAddress.Addr[7], pTxData->Session.DestinationAddress.Addr[8], pTxData->Session.DestinationAddress.Addr[9], pTxData->Session.DestinationAddress.Addr[10], pTxData->Session.DestinationAddress.Addr[11], pTxData->Session.DestinationAddress.Addr[12], pTxData->Session.DestinationAddress.Addr[13], pTxData->Session.DestinationAddress.Addr[14], pTxData->Session.DestinationAddress.Addr[15], pTxData->Session.DestinationPort )); // // Queue the data for transmission // pPacket->pNext = NULL; pPreviousPacket = pSocket->pTxPacketListTail; if ( NULL == pPreviousPacket ) { pSocket->pTxPacketListHead = pPacket; } else { pPreviousPacket->pNext = pPacket; } pSocket->pTxPacketListTail = pPacket; DEBUG (( DEBUG_TX, "0x%08x: Packet on transmit list\r\n", pPacket )); // // Account for the buffered data // *pTxBytes += BufferLength; *pDataLength = BufferLength; // // Start the transmit engine if it is idle // if ( NULL != pPort->pTxFree ) { EslSocketTxStart ( pPort, &pSocket->pTxPacketListHead, &pSocket->pTxPacketListTail, &pPort->pTxActive, &pPort->pTxFree ); // // Ignore any transmit error // if ( EFI_ERROR ( pSocket->TxError )) { DEBUG (( DEBUG_TX, "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", pPort, pPacket, pSocket->TxError )); } pSocket->TxError = EFI_SUCCESS; } // // Release the socket layer synchronization // RESTORE_TPL ( TplPrevious ); } else { // // Packet allocation failed // pSocket->errno = ENOMEM; break; } // // Set the next port // pPort = pPort->pLinkSocket; } } else { // // Not enough buffer space available // pSocket->errno = EAGAIN; Status = EFI_NOT_READY; } } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Set the local port address. This routine sets the local port address. This support routine is called by ::EslSocketPortAllocate. @param [in] pPort Address of an ESL_PORT structure @param [in] pSockAddr Address of a sockaddr structure that contains the connection point on the local machine. An IPv4 address of INADDR_ANY specifies that the connection is made to all of the network stacks on the platform. Specifying a specific IPv4 address restricts the connection to the network stack supporting that address. Specifying zero for the port causes the network layer to assign a port number from the dynamic range. Specifying a specific port number causes the network layer to use that port. @param [in] bBindTest TRUE = run bind testing @retval EFI_SUCCESS The operation was successful **/ EFI_STATUS EslIp4LocalAddressSet ( IN ESL_PORT * pPort, IN CONST struct sockaddr * pSockAddr, IN BOOLEAN bBindTest ) { EFI_IP4_CONFIG_DATA * pConfig; CONST struct sockaddr_in * pIpAddress; CONST UINT8 * pIpv4Address; EFI_STATUS Status; DBG_ENTER ( ); // // Validate the address // pIpAddress = (struct sockaddr_in *)pSockAddr; if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) { // // The local address must not be the broadcast address // Status = EFI_INVALID_PARAMETER; pPort->pSocket->errno = EADDRNOTAVAIL; } else { Status = EFI_SUCCESS; // // Set the local address // pIpAddress = (struct sockaddr_in *)pSockAddr; pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr; pConfig = &pPort->Context.Ip4.ModeData.ConfigData; pConfig->StationAddress.Addr[0] = pIpv4Address[0]; pConfig->StationAddress.Addr[1] = pIpv4Address[1]; pConfig->StationAddress.Addr[2] = pIpv4Address[2]; pConfig->StationAddress.Addr[3] = pIpv4Address[3]; // // Determine if the default address is used // pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr ); // // Display the local address // DEBUG (( DEBUG_BIND, "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n", pPort, pConfig->StationAddress.Addr[0], pConfig->StationAddress.Addr[1], pConfig->StationAddress.Addr[2], pConfig->StationAddress.Addr[3])); // // Set the subnet mask // if ( pConfig->UseDefaultAddress ) { pConfig->SubnetMask.Addr[0] = 0; pConfig->SubnetMask.Addr[1] = 0; pConfig->SubnetMask.Addr[2] = 0; pConfig->SubnetMask.Addr[3] = 0; } else { pConfig->SubnetMask.Addr[0] = 0xff; pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0; } } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Add a port to the list of ports to be polled. @param [in] pWebServer The web server control structure address. @param [in] SocketFD The socket's file descriptor to add to the list. @retval EFI_SUCCESS The port was successfully added @retval EFI_NO_RESOURCES Insufficient memory to add the port **/ EFI_STATUS PortAdd ( IN DT_WEB_SERVER * pWebServer, IN int SocketFD ) { nfds_t Index; size_t LengthInBytes; nfds_t MaxEntries; nfds_t MaxEntriesNew; struct pollfd * pFdList; struct pollfd * pFdListNew; WSDT_PORT ** ppPortListNew; WSDT_PORT * pPort; EFI_STATUS Status; DBG_ENTER ( ); // // Use for/break instead of goto // for ( ; ; ) { // // Assume success // Status = EFI_SUCCESS; // // Create a new list if necessary // pFdList = pWebServer->pFdList; MaxEntries = pWebServer->MaxEntries; if ( pWebServer->Entries >= MaxEntries ) { MaxEntriesNew = 16 + MaxEntries; // // The current FD list is full // Allocate a new FD list // LengthInBytes = sizeof ( *pFdList ) * MaxEntriesNew; Status = gBS->AllocatePool ( EfiRuntimeServicesData, LengthInBytes, (VOID **)&pFdListNew ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR | DEBUG_POOL, "ERROR - Failed to allocate the FD list, Status: %r\r\n", Status )); break; } // // Allocate a new port list // LengthInBytes = sizeof ( *ppPortListNew ) * MaxEntriesNew; Status = gBS->AllocatePool ( EfiRuntimeServicesData, LengthInBytes, (VOID **) &ppPortListNew ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR | DEBUG_POOL, "ERROR - Failed to allocate the port list, Status: %r\r\n", Status )); // // Free the new FD list // gBS->FreePool ( pFdListNew ); break; } // // Duplicate the FD list // Index = MaxEntries; if ( NULL != pFdList ) { CopyMem ( pFdListNew, pFdList, Index * sizeof ( *pFdList )); } // // Initialize the new entries in the FD list // for ( ; MaxEntriesNew > Index; Index++ ) { pFdListNew[ Index ].fd = -1; pFdListNew[ Index ].events = 0; pFdListNew[ Index ].revents = 0; } // // Free the old FD list // if ( NULL != pFdList ) { gBS->FreePool ( pFdList ); } // // Switch to the new FD list // pWebServer->pFdList = pFdListNew; pFdList = pWebServer->pFdList; // // Duplicate the port list // Index = MaxEntries; if ( NULL != pWebServer->ppPortList ) { CopyMem ( ppPortListNew, pWebServer->ppPortList, Index * sizeof ( *ppPortListNew )); } // // Initialize the new entries in the port list // for ( ; MaxEntriesNew > Index; Index++ ) { ppPortListNew[ Index ] = NULL; } // // Free the old port list // if ( NULL != pWebServer->ppPortList ) { gBS->FreePool ( pWebServer->ppPortList ); } // // Switch to the new port list // pWebServer->ppPortList = ppPortListNew; // // Update the list size // pWebServer->MaxEntries = MaxEntriesNew; } // // Allocate a new port // LengthInBytes = sizeof ( *pPort ); Status = gBS->AllocatePool ( EfiRuntimeServicesData, LengthInBytes, (VOID **)&pPort ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR | DEBUG_POOL, "ERROR - Failed to allocate the port, Status: %r\r\n", Status )); break; } // // Initialize the port // pPort->RequestLength = 0; pPort->TxBytes = 0; // // Add the socket to the FD list // pFdList[ pWebServer->Entries ].fd = SocketFD; pFdList[ pWebServer->Entries ].events = POLLRDNORM | POLLHUP; pFdList[ pWebServer->Entries ].revents = 0; // // Add the port to the port list // pWebServer->ppPortList[ pWebServer->Entries ] = pPort; // // Account for the new entry // pWebServer->Entries += 1; DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO, "WebServer handling %d ports\r\n", pWebServer->Entries )); // // All done // break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Respond with the firmware status @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS FirmwarePage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { EFI_STATUS Status; DBG_ENTER ( ); // // Send the system table page // for ( ; ; ) { // // Send the page and table header // Status = TableHeader ( SocketFD, pPort, L"Firmware", NULL ); if ( EFI_ERROR ( Status )) { break; } // // Display the firmware vendor and revision // Status = RowUnicodeString ( SocketFD, pPort, "Vendor", gST->FirmwareVendor ); if ( EFI_ERROR ( Status )) { break; } Status = RowRevision ( SocketFD, pPort, "Revision", gST->FirmwareRevision ); if ( EFI_ERROR ( Status )) { break; } // // Display the UEFI version // Status = RowRevision ( SocketFD, pPort, "UEFI", gST->Hdr.Revision ); if ( EFI_ERROR ( Status )) { break; } // // Build the table trailer // Status = TableTrailer ( SocketFD, pPort, pbDone ); break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and closing the DevicePath and PciIo protocols on Controller. @param [in] pThis Protocol instance pointer. @param [in] Controller Handle of device to stop driver on. @param [in] NumberOfChildren How many children need to be stopped. @param [in] pChildHandleBuffer Not used. @retval EFI_SUCCESS This driver is removed Controller. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. @retval other This driver was not removed from this device. **/ EFI_STATUS EFIAPI DriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL * pThis, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE * pChildHandleBuffer ) { NIC_DEVICE * pNicDevice; EFI_STATUS Status; DBG_ENTER ( ); // // Determine if this driver is already attached // Status = gBS->OpenProtocol ( Controller, &gEfiCallerIdGuid, (VOID **) &pNicDevice, pThis->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( !EFI_ERROR ( Status )) { // // AX88772 driver is no longer running on this device // gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleNetworkProtocolGuid, &pNicDevice->SimpleNetwork, &gEfiCallerIdGuid, pNicDevice, NULL ); DEBUG (( DEBUG_POOL | DEBUG_INIT, "Removed: gEfiSimpleNetworkProtocolGuid from 0x%08x\r\n", Controller )); DEBUG (( DEBUG_POOL | DEBUG_INIT, "Removed: gEfiCallerIdGuid from 0x%08x\r\n", Controller )); // // Stop the timer // if ( NULL != pNicDevice->Timer ) { gBS->SetTimer ( pNicDevice->Timer, TimerCancel, 0 ); gBS->CloseEvent ( pNicDevice->Timer ); DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO, "0x%08x: Released timer\r\n", pNicDevice->Timer )); } // // Done with the device context // DEBUG (( DEBUG_POOL | DEBUG_INIT, "0x%08x: Free pNicDevice, %d bytes\r\n", pNicDevice, sizeof ( *pNicDevice ))); gBS->FreePool ( pNicDevice ); } // // Return the shutdown status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Respond with the Ports page @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS PortsPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { socklen_t AddressLength; struct sockaddr_in6 LocalAddress; DT_WEB_SERVER * pWebServer; EFI_STATUS Status; DBG_ENTER ( ); // // Send the Hello World page // pWebServer = &mWebServer; for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Ports" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page body // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>Web-Server Ports</h1>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Check for TCP v4 // if ( -1 != pWebServer->HttpListenPort ) { AddressLength = sizeof ( LocalAddress ); if ( 0 == getsockname ( pWebServer->HttpListenPort, (struct sockaddr *)&LocalAddress, &AddressLength )) { Status = HttpSendAnsiString ( SocketFD, pPort, "<a href=\"http://" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "\">Tcp4</a><br>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } } // // Check for TCP v6 // if ( -1 != pWebServer->HttpListenPort6 ) { AddressLength = sizeof ( LocalAddress ); if ( 0 == getsockname ( pWebServer->HttpListenPort6, (struct sockaddr *)&LocalAddress, &AddressLength )) { Status = HttpSendAnsiString ( SocketFD, pPort, "<a href=\"http://" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "\">Tcp6</a><br>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Verify the adapter's IP address This support routine is called by EslSocketBindTest. @param [in] pPort Address of an ::ESL_PORT structure. @param [in] pConfigData Address of the configuration data @retval EFI_SUCCESS - The IP address is valid @retval EFI_NOT_STARTED - The IP address is invalid **/ EFI_STATUS EslUdp6VerifyLocalIpAddress ( IN ESL_PORT * pPort, IN EFI_UDP6_CONFIG_DATA * pConfigData ) { UINTN AddressCount; EFI_IP6_ADDRESS_INFO * pAddressInfo; UINTN DataSize; EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData; EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol; ESL_SERVICE * pService; EFI_STATUS Status; DBG_ENTER ( ); // // Use break instead of goto // pIpConfigData = NULL; for ( ; ; ) { // // Determine if the IP address is specified // DEBUG (( DEBUG_BIND, "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", pConfigData->StationAddress.Addr[0], pConfigData->StationAddress.Addr[1], pConfigData->StationAddress.Addr[2], pConfigData->StationAddress.Addr[3], pConfigData->StationAddress.Addr[4], pConfigData->StationAddress.Addr[5], pConfigData->StationAddress.Addr[6], pConfigData->StationAddress.Addr[7], pConfigData->StationAddress.Addr[8], pConfigData->StationAddress.Addr[9], pConfigData->StationAddress.Addr[10], pConfigData->StationAddress.Addr[11], pConfigData->StationAddress.Addr[12], pConfigData->StationAddress.Addr[13], pConfigData->StationAddress.Addr[14], pConfigData->StationAddress.Addr[15])); if (( 0 == pConfigData->StationAddress.Addr [ 0 ]) && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) && ( 0 == pConfigData->StationAddress.Addr [ 3 ]) && ( 0 == pConfigData->StationAddress.Addr [ 4 ]) && ( 0 == pConfigData->StationAddress.Addr [ 5 ]) && ( 0 == pConfigData->StationAddress.Addr [ 6 ]) && ( 0 == pConfigData->StationAddress.Addr [ 7 ]) && ( 0 == pConfigData->StationAddress.Addr [ 8 ]) && ( 0 == pConfigData->StationAddress.Addr [ 9 ]) && ( 0 == pConfigData->StationAddress.Addr [ 10 ]) && ( 0 == pConfigData->StationAddress.Addr [ 11 ]) && ( 0 == pConfigData->StationAddress.Addr [ 12 ]) && ( 0 == pConfigData->StationAddress.Addr [ 13 ]) && ( 0 == pConfigData->StationAddress.Addr [ 14 ]) && ( 0 == pConfigData->StationAddress.Addr [ 15 ])) { Status = EFI_SUCCESS; break; } // // Open the configuration protocol // pService = pPort->pService; Status = gBS->OpenProtocol ( pService->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **)&pIpConfigProtocol, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR, "ERROR - IP Configuration Protocol not available, Status: %r\r\n", Status )); break; } // // Get the IP configuration data size // DataSize = 0; Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, Ip6ConfigDataTypeInterfaceInfo, &DataSize, NULL ); if ( EFI_BUFFER_TOO_SMALL != Status ) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to get IP Configuration data size, Status: %r\r\n", Status )); break; } // // Allocate the configuration data buffer // pIpConfigData = AllocatePool ( DataSize ); if ( NULL == pIpConfigData ) { DEBUG (( DEBUG_ERROR, "ERROR - Not enough memory to allocate IP Configuration data!\r\n" )); Status = EFI_OUT_OF_RESOURCES; break; } // // Get the IP configuration // Status = pIpConfigProtocol->GetData ( pIpConfigProtocol, Ip6ConfigDataTypeInterfaceInfo, &DataSize, pIpConfigData ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to return IP Configuration data, Status: %r\r\n", Status )); break; } // // Display the current configuration // DEBUG (( DEBUG_BIND, "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", pIpConfigData->HwAddress.Addr [ 0 ], pIpConfigData->HwAddress.Addr [ 1 ], pIpConfigData->HwAddress.Addr [ 2 ], pIpConfigData->HwAddress.Addr [ 3 ], pIpConfigData->HwAddress.Addr [ 4 ], pIpConfigData->HwAddress.Addr [ 5 ], pIpConfigData->HwAddress.Addr [ 6 ], pIpConfigData->HwAddress.Addr [ 7 ], pIpConfigData->HwAddress.Addr [ 8 ], pIpConfigData->HwAddress.Addr [ 9 ], pIpConfigData->HwAddress.Addr [ 10 ], pIpConfigData->HwAddress.Addr [ 11 ], pIpConfigData->HwAddress.Addr [ 12 ], pIpConfigData->HwAddress.Addr [ 13 ], pIpConfigData->HwAddress.Addr [ 14 ], pIpConfigData->HwAddress.Addr [ 15 ])); // // Validate the hardware address // Status = EFI_SUCCESS; if (( 16 == pIpConfigData->HwAddressSize ) && ( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ]) && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ]) && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ]) && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ]) && ( pConfigData->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ]) && ( pConfigData->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ]) && ( pConfigData->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ]) && ( pConfigData->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ]) && ( pConfigData->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ]) && ( pConfigData->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ]) && ( pConfigData->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ]) && ( pConfigData->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ]) && ( pConfigData->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ]) && ( pConfigData->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ]) && ( pConfigData->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ]) && ( pConfigData->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) { break; } // // Walk the list of other IP addresses assigned to this adapter // for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) { pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ]; // // Display the IP address // DEBUG (( DEBUG_BIND, "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", pAddressInfo->Address.Addr [ 0 ], pAddressInfo->Address.Addr [ 1 ], pAddressInfo->Address.Addr [ 2 ], pAddressInfo->Address.Addr [ 3 ], pAddressInfo->Address.Addr [ 4 ], pAddressInfo->Address.Addr [ 5 ], pAddressInfo->Address.Addr [ 6 ], pAddressInfo->Address.Addr [ 7 ], pAddressInfo->Address.Addr [ 8 ], pAddressInfo->Address.Addr [ 9 ], pAddressInfo->Address.Addr [ 10 ], pAddressInfo->Address.Addr [ 11 ], pAddressInfo->Address.Addr [ 12 ], pAddressInfo->Address.Addr [ 13 ], pAddressInfo->Address.Addr [ 14 ], pAddressInfo->Address.Addr [ 15 ])); // // Validate the IP address // if (( pConfigData->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ]) && ( pConfigData->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ]) && ( pConfigData->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ]) && ( pConfigData->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ]) && ( pConfigData->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ]) && ( pConfigData->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ]) && ( pConfigData->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ]) && ( pConfigData->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ]) && ( pConfigData->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ]) && ( pConfigData->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ]) && ( pConfigData->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ]) && ( pConfigData->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ]) && ( pConfigData->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ]) && ( pConfigData->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ]) && ( pConfigData->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ]) && ( pConfigData->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) { break; } } if ( pIpConfigData->AddressInfoCount > AddressCount ) { break; } // // The IP address did not match // Status = EFI_NOT_STARTED; break; } // // Free the buffer if necessary // if ( NULL != pIpConfigData ) { FreePool ( pIpConfigData ); } // // Return the IP address status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Respond with the DHCP options @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS DhcpOptionsPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { // EFI_HANDLE Dhcp4Handle; EFI_DHCP4_MODE_DATA Dhcp4Mode; UINTN HandleCount; EFI_DHCP4_PROTOCOL * pDhcp4; EFI_DHCP4_PACKET * pDhcp4Packet; EFI_HANDLE * pEnd; EFI_HANDLE * pHandle; // EFI_SERVICE_BINDING_PROTOCOL * pService; EFI_STATUS Status; DBG_ENTER ( ); // // Send the DHCP options // for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"DHCP Options" ); if ( EFI_ERROR ( Status )) { break; } // // Build the header // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendUnicodeString ( SocketFD, pPort, L"DHCP Options" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "</h1>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Attempt to locate DHCP clients // Status = gBS->LocateHandleBuffer ( ByProtocol, // &gEfiDhcp4ServiceBindingProtocolGuid, &gEfiDhcp4ProtocolGuid, NULL, &HandleCount, &pHandle ); if ( EFI_ERROR ( Status )) { Status = HttpSendAnsiString ( SocketFD, pPort, "DHCP not in use" ); if ( EFI_ERROR ( Status )) { break; } } else { // // Walk the list of handles // pEnd = &pHandle [ HandleCount ]; while ( pEnd > pHandle ) { /* // // Get the DHCP service binding // Status = gBS->OpenProtocol ( *pHandle, &gEfiDhcp4ServiceBindingProtocolGuid, &pService, NULL, gImageHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( EFI_ERROR ( Status )) { Status = HttpSendAnsiString ( SocketFD, pPort, "Failed to open gEfiDhcp4ServiceBindingProtocolGuid" ); break; } // // Get the DHCP handle // Status = pService->CreateChild ( pService, &Dhcp4Handle ); if ( EFI_ERROR ( Status )) { Status = HttpSendAnsiString ( SocketFD, pPort, "Failed to create DHCP4 child" ); } else { */ // // Get the DHCP protocol // Status = gBS->OpenProtocol ( *pHandle, // Dhcp4Handle, &gEfiDhcp4ProtocolGuid, &pDhcp4, NULL, gImageHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( EFI_ERROR ( Status )) { Status = HttpSendAnsiString ( SocketFD, pPort, "Failed to open gEfiDhcp4ProtocolGuid" ); } else { // // Get the DHCP packet // Status = pDhcp4->GetModeData ( pDhcp4, &Dhcp4Mode ); if ( EFI_ERROR ( Status )) { Status = HttpSendAnsiString ( SocketFD, pPort, "Failed to get DHCP4 mode" ); } else { // // Get the last packet // pDhcp4Packet = Dhcp4Mode.ReplyPacket; if ( NULL == pDhcp4Packet ) { Status = HttpSendAnsiString ( SocketFD, pPort, "No DHCP reply received!<br/>DHCP Mode:<br/>" ); if ( EFI_ERROR ( Status )) { break; } // // Display the DHCP mode data // Status = HttpSendDump ( SocketFD, pPort, sizeof ( Dhcp4Mode ), (UINT8 *)&Dhcp4Mode ); } else { // // Display the DHCP packet // Status = HttpSendDump ( SocketFD, pPort, pDhcp4Packet->Length, (UINT8 *)&pDhcp4Packet->Dhcp4 ); } } /* } // // Done with the DHCP protocol // pService->DestroyChild ( pService, Dhcp4Handle ); */ } // // Set the next service binding // pHandle += 1; } } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Page to display the memory map @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS MemoryMapPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { UINT64 Attributes; BOOLEAN bSomethingDisplayed; UINTN Count; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryEnd; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryDescriptor; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryDescriptorStart; EFI_STATUS Status; DBG_ENTER ( ); // // Send the memory map page // pMemoryDescriptorStart = NULL; for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Memory Map" ); if ( EFI_ERROR ( Status )) { break; } // // Start the table // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>Memory Map</h1>\r\n" "<table>\r\n" " <tr><th align=\"right\">Type</th><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"right\">Attributes</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Get the memory map // Status = gDS->GetMemorySpaceMap ( &Count, &pMemoryDescriptor ); if ( !EFI_ERROR ( Status )) { pMemoryDescriptorStart = pMemoryDescriptor; pMemoryEnd = &pMemoryDescriptor[ Count ]; while ( pMemoryEnd > pMemoryDescriptor ) { // // Display the type // Status = HttpSendAnsiString ( SocketFD, pPort, "<tr><td align=\"right\"><code>" ); if ( EFI_ERROR ( Status )) { break; } if ( DIM ( mpMemoryType ) > pMemoryDescriptor->GcdMemoryType ) { Status = HttpSendAnsiString ( SocketFD, pPort, mpMemoryType[ pMemoryDescriptor->GcdMemoryType ]); } else { Status = HttpSendValue ( SocketFD, pPort, pMemoryDescriptor->GcdMemoryType ); } if ( EFI_ERROR ( Status )) { break; } // // Display the start address // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->BaseAddress ); if ( EFI_ERROR ( Status )) { break; } // // Display the end address // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->BaseAddress + pMemoryDescriptor->Length - 1 ); if ( EFI_ERROR ( Status )) { break; } // // Display the attributes // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->Attributes ); if ( EFI_ERROR ( Status )) { break; } // // Decode the attributes // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td>" ); if ( EFI_ERROR ( Status )) { break; } bSomethingDisplayed = FALSE; Attributes = pMemoryDescriptor->Attributes; if ( 0 != ( Attributes & EFI_MEMORY_RUNTIME )) { bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Runtime" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_XP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Execute" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_RP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Read" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Write" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_UCE )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "UCE" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WB )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Back" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WT )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Through" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WC )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Combining" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_UC )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Uncached" ); if ( EFI_ERROR ( Status )) { break; } } // // Finish the row // Status = HttpSendAnsiString ( SocketFD, pPort, "</td></tr>" ); if ( EFI_ERROR ( Status )) { break; } // // Set the next memory descriptor // pMemoryDescriptor += 1; } } // // Finish the table // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; } // // Release the memory descriptors // if ( NULL != pMemoryDescriptorStart ) { FreePool ( pMemoryDescriptorStart ); } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Determine if the socket is configured. This routine uses the flag ESL_SOCKET::bConfigured to determine if the network layer's configuration routine has been called. This routine calls the bind and configuration routines if they were not already called. After the port is configured, the \ref ReceiveEngine is started. This routine is called by EslSocketIsConfigured to verify that the socket is configured. @param [in] pSocket Address of an ::ESL_SOCKET structure @retval EFI_SUCCESS - The port is connected @retval EFI_NOT_STARTED - The port is not connected **/ EFI_STATUS EslUdp6SocketIsConfigured ( IN ESL_SOCKET * pSocket ) { EFI_UDP6_CONFIG_DATA * pConfigData; ESL_PORT * pPort; ESL_PORT * pNextPort; ESL_UDP6_CONTEXT * pUdp6; EFI_UDP6_PROTOCOL * pUdp6Protocol; EFI_STATUS Status; struct sockaddr_in6 LocalAddress; DBG_ENTER ( ); // // Assume success // Status = EFI_SUCCESS; // // Configure the port if necessary // if ( !pSocket->bConfigured ) { // // Fill in the port list if necessary // pSocket->errno = ENETDOWN; if ( NULL == pSocket->pPortList ) { ZeroMem ( &LocalAddress, sizeof ( LocalAddress )); LocalAddress.sin6_len = sizeof ( LocalAddress ); LocalAddress.sin6_family = AF_INET6; Status = EslSocketBind ( &pSocket->SocketProtocol, (struct sockaddr *)&LocalAddress, LocalAddress.sin6_len, &pSocket->errno ); } // // Walk the port list // pPort = pSocket->pPortList; while ( NULL != pPort ) { // // Attempt to configure the port // pNextPort = pPort->pLinkSocket; pUdp6 = &pPort->Context.Udp6; pUdp6Protocol = pPort->pProtocol.UDPv6; pConfigData = &pUdp6->ConfigData; DEBUG (( DEBUG_TX, "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", pPort, pConfigData->StationAddress.Addr[0], pConfigData->StationAddress.Addr[1], pConfigData->StationAddress.Addr[2], pConfigData->StationAddress.Addr[3], pConfigData->StationAddress.Addr[4], pConfigData->StationAddress.Addr[5], pConfigData->StationAddress.Addr[6], pConfigData->StationAddress.Addr[7], pConfigData->StationAddress.Addr[8], pConfigData->StationAddress.Addr[9], pConfigData->StationAddress.Addr[10], pConfigData->StationAddress.Addr[11], pConfigData->StationAddress.Addr[12], pConfigData->StationAddress.Addr[13], pConfigData->StationAddress.Addr[14], pConfigData->StationAddress.Addr[15], pConfigData->StationPort )); DEBUG (( DEBUG_TX, "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", pConfigData->RemoteAddress.Addr[0], pConfigData->RemoteAddress.Addr[1], pConfigData->RemoteAddress.Addr[2], pConfigData->RemoteAddress.Addr[3], pConfigData->RemoteAddress.Addr[4], pConfigData->RemoteAddress.Addr[5], pConfigData->RemoteAddress.Addr[6], pConfigData->RemoteAddress.Addr[7], pConfigData->RemoteAddress.Addr[8], pConfigData->RemoteAddress.Addr[9], pConfigData->RemoteAddress.Addr[10], pConfigData->RemoteAddress.Addr[11], pConfigData->RemoteAddress.Addr[12], pConfigData->RemoteAddress.Addr[13], pConfigData->RemoteAddress.Addr[14], pConfigData->RemoteAddress.Addr[15], pConfigData->RemotePort )); Status = pUdp6Protocol->Configure ( pUdp6Protocol, pConfigData ); if ( !EFI_ERROR ( Status )) { // // Update the configuration data // Status = pUdp6Protocol->GetModeData ( pUdp6Protocol, pConfigData, NULL, NULL, NULL ); } if ( EFI_ERROR ( Status )) { if ( !pSocket->bConfigured ) { DEBUG (( DEBUG_LISTEN, "ERROR - Failed to configure the Udp6 port, Status: %r\r\n", Status )); switch ( Status ) { case EFI_ACCESS_DENIED: pSocket->errno = EACCES; break; default: case EFI_DEVICE_ERROR: pSocket->errno = EIO; break; case EFI_INVALID_PARAMETER: pSocket->errno = EADDRNOTAVAIL; break; case EFI_NO_MAPPING: pSocket->errno = EAFNOSUPPORT; break; case EFI_OUT_OF_RESOURCES: pSocket->errno = ENOBUFS; break; case EFI_UNSUPPORTED: pSocket->errno = EOPNOTSUPP; break; } } } else { DEBUG (( DEBUG_TX, "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", pPort, pConfigData->StationAddress.Addr[0], pConfigData->StationAddress.Addr[1], pConfigData->StationAddress.Addr[2], pConfigData->StationAddress.Addr[3], pConfigData->StationAddress.Addr[4], pConfigData->StationAddress.Addr[5], pConfigData->StationAddress.Addr[6], pConfigData->StationAddress.Addr[7], pConfigData->StationAddress.Addr[8], pConfigData->StationAddress.Addr[9], pConfigData->StationAddress.Addr[10], pConfigData->StationAddress.Addr[11], pConfigData->StationAddress.Addr[12], pConfigData->StationAddress.Addr[13], pConfigData->StationAddress.Addr[14], pConfigData->StationAddress.Addr[15], pConfigData->StationPort )); DEBUG (( DEBUG_TX, "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", pConfigData->RemoteAddress.Addr[0], pConfigData->RemoteAddress.Addr[1], pConfigData->RemoteAddress.Addr[2], pConfigData->RemoteAddress.Addr[3], pConfigData->RemoteAddress.Addr[4], pConfigData->RemoteAddress.Addr[5], pConfigData->RemoteAddress.Addr[6], pConfigData->RemoteAddress.Addr[7], pConfigData->RemoteAddress.Addr[8], pConfigData->RemoteAddress.Addr[9], pConfigData->RemoteAddress.Addr[10], pConfigData->RemoteAddress.Addr[11], pConfigData->RemoteAddress.Addr[12], pConfigData->RemoteAddress.Addr[13], pConfigData->RemoteAddress.Addr[14], pConfigData->RemoteAddress.Addr[15], pConfigData->RemotePort )); pPort->bConfigured = TRUE; pSocket->bConfigured = TRUE; // // Start the first read on the port // EslSocketRxStart ( pPort ); // // The socket is connected // pSocket->State = SOCKET_STATE_CONNECTED; pSocket->errno = 0; } // // Set the next port // pPort = pNextPort; } } // // Determine the socket configuration status // Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED; // // Return the port connected state. // DBG_EXIT_STATUS ( Status ); return Status; }
/** Set the local port address. This routine sets the local port address. This support routine is called by ::EslSocketPortAllocate. @param [in] pPort Address of an ESL_PORT structure @param [in] pSockAddr Address of a sockaddr structure that contains the connection point on the local machine. An IPv6 address of INADDR_ANY specifies that the connection is made to all of the network stacks on the platform. Specifying a specific IPv6 address restricts the connection to the network stack supporting that address. Specifying zero for the port causes the network layer to assign a port number from the dynamic range. Specifying a specific port number causes the network layer to use that port. @param [in] bBindTest TRUE = run bind testing @retval EFI_SUCCESS The operation was successful **/ EFI_STATUS EslUdp6LocalAddressSet ( IN ESL_PORT * pPort, IN CONST struct sockaddr * pSockAddr, IN BOOLEAN bBindTest ) { EFI_UDP6_CONFIG_DATA * pConfig; CONST struct sockaddr_in6 * pIpAddress; CONST UINT8 * pIPv6Address; EFI_STATUS Status; DBG_ENTER ( ); // // Set the local address // pIpAddress = (struct sockaddr_in6 *)pSockAddr; pIPv6Address = (UINT8 *)&pIpAddress->sin6_addr; pConfig = &pPort->Context.Udp6.ConfigData; CopyMem ( &pConfig->StationAddress, pIPv6Address, sizeof ( pConfig->StationAddress )); // // Validate the IP address // pConfig->StationPort = 0; Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL ) : EFI_SUCCESS; if ( !EFI_ERROR ( Status )) { // // Set the port number // pConfig->StationPort = SwapBytes16 ( pIpAddress->sin6_port ); pPort->pSocket->bAddressSet = TRUE; // // Display the local address // DEBUG (( DEBUG_BIND, "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", pPort, pConfig->StationAddress.Addr[0], pConfig->StationAddress.Addr[1], pConfig->StationAddress.Addr[2], pConfig->StationAddress.Addr[3], pConfig->StationAddress.Addr[4], pConfig->StationAddress.Addr[5], pConfig->StationAddress.Addr[6], pConfig->StationAddress.Addr[7], pConfig->StationAddress.Addr[8], pConfig->StationAddress.Addr[9], pConfig->StationAddress.Addr[10], pConfig->StationAddress.Addr[11], pConfig->StationAddress.Addr[12], pConfig->StationAddress.Addr[13], pConfig->StationAddress.Addr[14], pConfig->StationAddress.Addr[15], pConfig->StationPort )); } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Entry point for the web server application. @param [in] Argc The number of arguments @param [in] Argv The argument value array @retval 0 The application exited normally. @retval Other An error occurred. **/ int main ( IN int Argc, IN char **Argv ) { UINT16 HttpPort; UINTN Index; DT_WEB_SERVER * pWebServer; EFI_STATUS Status; UINT64 TriggerTime; // // Get the HTTP port // HttpPort = PcdGet16 ( WebServer_HttpPort ); DEBUG (( DEBUG_HTTP_PORT, "HTTP Port: %d\r\n", HttpPort )); // // Create a timer event to start HTTP port // pWebServer = &mWebServer; Status = gBS->CreateEvent ( EVT_TIMER, TPL_WEB_SERVER, NULL, NULL, &pWebServer->TimerEvent ); if ( !EFI_ERROR ( Status )) { TriggerTime = HTTP_PORT_POLL_DELAY * ( 1000 * 10 ); Status = gBS->SetTimer ( pWebServer->TimerEvent, TimerPeriodic, TriggerTime ); if ( !EFI_ERROR ( Status )) { // // Run the web server forever // pWebServer->HttpListenPort = -1; pWebServer->HttpListenPort6 = -1; pWebServer->bRunning = TRUE; do { // // Poll the network layer to create the HTTP port // for the web server. More than one attempt may // be necessary since it may take some time to get // the IP address and initialize the upper layers // of the network stack. // if (( -1 == pWebServer->HttpListenPort ) || ( -1 == pWebServer->HttpListenPort6 )) { do { // // Wait a while before polling for a connection // if ( EFI_SUCCESS != gBS->CheckEvent ( pWebServer->TimerEvent )) { if ( 0 != pWebServer->Entries ) { break; } gBS->WaitForEvent ( 1, &pWebServer->TimerEvent, &Index ); } // // Poll for a network connection // if ( -1 == pWebServer->HttpListenPort ) { WebServerListen ( pWebServer, AF_INET, IPPROTO_TCP, HttpPort, &pWebServer->HttpListenPort ); } if ( -1 == pWebServer->HttpListenPort6 ) { WebServerListen ( pWebServer, AF_INET6, IPPROTO_TCP, HttpPort, &pWebServer->HttpListenPort6 ); } // // Continue polling while both network connections are // not present // } while ( 0 == pWebServer->Entries ); } // // Poll the sockets for activity while both network // connections are connected // do { SocketPoll ( pWebServer ); } while ( pWebServer->bRunning && ( -1 != pWebServer->HttpListenPort ) && ( -1 != pWebServer->HttpListenPort6 )); // // Continue polling the network connections until both // TCP4 and TCP6 are connected // } while ( pWebServer->bRunning ); // // Stop the timer // gBS->SetTimer ( pWebServer->TimerEvent, TimerCancel, 0 ); } // // Done with the timer event // gBS->CloseEvent ( pWebServer->TimerEvent ); } // // Return the final status // DBG_EXIT_STATUS ( Status ); return Status; }
/** Page to reboot the system @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS RebootPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { EFI_STATUS Status; DBG_ENTER ( ); // // Send the Reboot page // for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Reboot" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page body // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>Reboot</h1>\r\n" "<p>\r\n" " Ouch! The system is rebooting!\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); if ( EFI_ERROR ( Status )) { break; } // // Deliver the data to the remote system by // closing the socket // close ( SocketFD ); // // Attempt to reboot the system // DEBUG (( DEBUG_REQUEST, "Reseting System\r\n" )); gRT->ResetSystem ( EfiResetCold, EFI_SUCCESS, 0, NULL ); break; } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }