Beispiel #1
0
/**
 * Reset the network device
 *
 * @v snp		SNP interface
 * @v ext_verify	Extended verification required
 * @ret efirc		EFI status code
 */
static EFI_STATUS EFIAPI
efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
	struct efi_snp_device *snpdev =
		container_of ( snp, struct efi_snp_device, snp );
	int rc;

	DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
		snpdev, ( ext_verify ? "with" : "without" ) );

	netdev_close ( snpdev->netdev );
	snpdev->mode.State = EfiSimpleNetworkStarted;

	if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
		DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
		       snpdev, snpdev->netdev->name, strerror ( rc ) );
		return RC_TO_EFIRC ( rc );
	}

	snpdev->mode.State = EfiSimpleNetworkInitialized;
	return 0;
}
Beispiel #2
0
/**
 * Parse stored options
 *
 * @v nvo		Non-volatile options block
 *
 * Verifies that the options data is valid, and configures the DHCP
 * options block.  If the data is not valid, it is replaced with an
 * empty options block.
 */
static void nvo_init_dhcpopts ( struct nvo_block *nvo ) {
	uint8_t *options_data;
	size_t options_len;

	/* Steal one byte for the checksum */
	options_data = ( nvo->data + 1 );
	options_len = ( nvo->total_len - 1 );

	/* If checksum fails, or options data starts with a zero,
	 * assume the whole block is invalid.  This should capture the
	 * case of random initial contents.
	 */
	if ( ( nvo_checksum ( nvo ) != 0 ) || ( options_data[0] == 0 ) ) {
		DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
		       "assuming empty\n", nvo, nvo_checksum ( nvo ),
		       options_data[0] );
		memset ( nvo->data, 0, nvo->total_len );
	}

	dhcpopt_init ( &nvo->dhcpopts, options_data, options_len );
}
Beispiel #3
0
/**
 * Wait for admin event queue to be torn down
 *
 * @v intelxl		Intel device
 * @ret rc		Return status code
 */
static int intelxlvf_reset_wait_teardown ( struct intelxl_nic *intelxl ) {
	uint32_t admin_evt_len;
	unsigned int i;

	/* Wait for admin event queue to be torn down */
	for ( i = 0 ; i < INTELXLVF_RESET_MAX_WAIT_MS ; i++ ) {

		/* Check admin event queue length register */
		admin_evt_len = readl ( intelxl->regs + INTELXLVF_ADMIN +
					INTELXLVF_ADMIN_EVT_LEN );
		if ( ! ( admin_evt_len & INTELXL_ADMIN_LEN_ENABLE ) )
			return 0;

		/* Delay */
		mdelay ( 1 );
	}

	DBGC ( intelxl, "INTELXL %p timed out waiting for teardown (%#08x)\n",
	       intelxl, admin_evt_len );
	return -ETIMEDOUT;
}
Beispiel #4
0
Datei: nii.c Projekt: baloo/ipxe
/**
 * Set receive filters
 *
 * @v nii		NII NIC
 * @ret rc		Return status code
 */
static int nii_set_rx_filters ( struct nii_nic *nii ) {
	unsigned int op;
	int stat;
	int rc;

	/* Issue command */
	op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS,
		      ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
			PXE_OPFLAGS_RECEIVE_FILTER_UNICAST |
			PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST |
			PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS |
			PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST ) );
	if ( ( stat = nii_issue ( nii, op ) ) < 0 ) {
		rc = -EIO_STAT ( stat );
		DBGC ( nii, "NII %s could not set receive filters: %s\n",
		       nii->dev.name, strerror ( rc ) );
		return rc;
	}

	return 0;
}
Beispiel #5
0
/**
 * Wait for transmit and receive to become idle
 *
 * @v myson		Myson device
 * @ret rc		Return status code
 */
static int myson_wait_idle ( struct myson_nic *myson ) {
	uint32_t tcr_rcr;
	unsigned int i;

	/* Wait for both transmit and receive to be idle */
	for ( i = 0 ; i < MYSON_IDLE_MAX_WAIT_MS ; i++ ) {

		/* If either process is running, delay 1ms and retry */
		tcr_rcr = readl ( myson->regs + MYSON_TCR_RCR );
		if ( tcr_rcr & ( MYSON_TCR_TXS | MYSON_RCR_RXS ) ) {
			mdelay ( 1 );
			continue;
		}

		return 0;
	}

	DBGC ( myson, "MYSON %p timed out waiting for idle state (status "
	       "%08x)\n", myson, tcr_rcr );
	return -ETIMEDOUT;
}
Beispiel #6
0
Datei: nii.c Projekt: baloo/ipxe
/**
 * Initialise UNDI
 *
 * @v nii		NII NIC
 * @ret rc		Return status code
 */
static int nii_initialise ( struct nii_nic *nii ) {
	PXE_CPB_INITIALIZE cpb;
	PXE_DB_INITIALIZE db;
	unsigned int op;
	int stat;
	int rc;

	/* Allocate memory buffer */
	nii->buffer = umalloc ( nii->buffer_len );
	if ( ! nii->buffer ) {
		rc = -ENOMEM;
		goto err_alloc;
	}

	/* Construct parameter block */
	memset ( &cpb, 0, sizeof ( cpb ) );
	cpb.MemoryAddr = ( ( intptr_t ) nii->buffer );
	cpb.MemoryLength = nii->buffer_len;

	/* Construct data block */
	memset ( &db, 0, sizeof ( db ) );

	/* Issue command */
	op = NII_OP ( PXE_OPCODE_INITIALIZE,
		      PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE );
	if ( ( stat = nii_issue_cpb_db ( nii, op, &cpb, sizeof ( cpb ),
					 &db, sizeof ( db ) ) ) < 0 ) {
		rc = -EIO_STAT ( stat );
		DBGC ( nii, "NII %s could not initialise: %s\n",
		       nii->dev.name, strerror ( rc ) );
		goto err_initialize;
	}

	return 0;

 err_initialize:
	ufree ( nii->buffer );
 err_alloc:
	return rc;
}
Beispiel #7
0
/**
 * Open all PeerDist discovery sockets
 *
 * @ret rc		Return status code
 */
static int peerdisc_socket_open ( void ) {
	struct peerdisc_socket *socket;
	int rc;

	/* Open each socket */
	for_each_table_entry ( socket, PEERDISC_SOCKETS ) {
		if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM,
					       &socket->address.sa,
					       NULL ) ) != 0 ) {
			DBGC ( socket, "PEERDISC %s could not open socket: "
			       "%s\n", socket->name, strerror ( rc ) );
			goto err;
		}
	}

	return 0;

 err:
	for_each_table_entry_continue_reverse ( socket, PEERDISC_SOCKETS )
		intf_restart ( &socket->xfer, rc );
	return rc;
}
Beispiel #8
0
/**
 * Probe EFI image
 *
 * @v image		EFI file
 * @ret rc		Return status code
 */
static int efi_image_probe ( struct image *image ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_HANDLE handle;
	EFI_STATUS efirc;

	/* Attempt loading image */
	if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
				       user_to_virt ( image->data, 0 ),
				       image->len, &handle ) ) != 0 ) {
		/* Not an EFI image */
		DBGC ( image, "EFIIMAGE %p could not load: %s\n",
		       image, efi_strerror ( efirc ) );
		return -ENOEXEC;
	}

	/* Unload the image.  We can't leave it loaded, because we
	 * have no "unload" operation.
	 */
	bs->UnloadImage ( handle );

	return 0;
}
Beispiel #9
0
/**
 * Enable auto-polling
 *
 * @v rhn		Rhine device
 * @ret rc		Return status code
 *
 * This is voodoo.  There seems to be no documentation on exactly what
 * we are waiting for, or why we have to do anything other than simply
 * turn the feature on.
 */
static int rhine_mii_autopoll ( struct rhine_nic *rhn ) {
	unsigned int timeout = RHINE_TIMEOUT_US;
	uint8_t addr;

	/* Initiate auto-polling */
	writeb ( MII_BMSR, rhn->regs + RHINE_MII_ADDR );
	writeb ( RHINE_MII_CR_AUTOPOLL, rhn->regs + RHINE_MII_CR );

	/* Wait for auto-polling to complete */
	while ( timeout-- ) {
		udelay ( 1 );
		addr = readb ( rhn->regs + RHINE_MII_ADDR );
		if ( ! ( addr & RHINE_MII_ADDR_MDONE ) ) {
			writeb ( ( MII_BMSR | RHINE_MII_ADDR_MSRCEN ),
				 rhn->regs + RHINE_MII_ADDR );
			return 0;
		}
	}

	DBGC ( rhn, "RHINE %p MII auto-poll timeout\n", rhn );
	return -ETIMEDOUT;
}
Beispiel #10
0
/**
 * Probe PXE image (with rejection of potential EFI images)
 *
 * @v image		PXE file
 * @ret rc		Return status code
 */
int pxe_probe_no_mz ( struct image *image ) {
	uint16_t magic;
	int rc;

	/* Probe PXE image */
	if ( ( rc = pxe_probe ( image ) ) != 0 )
		return rc;

	/* Reject image with an "MZ" signature which may indicate an
	 * EFI image incorrectly handed out to a BIOS system.
	 */
	if ( image->len >= sizeof ( magic ) ) {
		copy_from_user ( &magic, image->data, 0, sizeof ( magic ) );
		if ( magic == cpu_to_le16 ( EFI_IMAGE_DOS_SIGNATURE ) ) {
			DBGC ( image, "IMAGE %p may be an EFI image\n",
			       image );
			return -ENOTTY;
		}
	}

	return 0;
}
Beispiel #11
0
/**
 * Poll for received packets
 *
 * @v netdev		Network device
 */
static void rhine_poll_rx ( struct net_device *netdev ) {
	struct rhine_nic *rhn = netdev->priv;
	struct rhine_descriptor *desc;
	struct io_buffer *iobuf;
	unsigned int rx_idx;
	uint32_t des0;
	size_t len;

	/* Check for received packets */
	while ( rhn->rx.cons != rhn->rx.prod ) {

		/* Get next receive descriptor */
		rx_idx = ( rhn->rx.cons % RHINE_RXDESC_NUM );
		desc = &rhn->rx.desc[rx_idx];

		/* Stop if descriptor is still in use */
		if ( desc->des0 & cpu_to_le32 ( RHINE_DES0_OWN ) )
			return;

		/* Populate I/O buffer */
		iobuf = rhn->rx_iobuf[rx_idx];
		rhn->rx_iobuf[rx_idx] = NULL;
		des0 = le32_to_cpu ( desc->des0 );
		len = ( RHINE_DES0_GETSIZE ( des0 ) - 4 /* strip CRC */ );
		iob_put ( iobuf, len );

		/* Hand off to network stack */
		if ( des0 & RHINE_RDES0_RXOK ) {
			DBGC2 ( rhn, "RHINE %p RX %d complete (length %zd)\n",
				rhn, rx_idx, len );
			netdev_rx ( netdev, iobuf );
		} else {
			DBGC ( rhn, "RHINE %p RX %d error (length %zd, DES0 "
			       "%08x)\n", rhn, rx_idx, len, des0 );
			netdev_rx_err ( netdev, iobuf, -EIO );
		}
		rhn->rx.cons++;
	}
}
Beispiel #12
0
/**
 * Get resources
 *
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int intelxlvf_admin_get_resources ( struct net_device *netdev ) {
	struct intelxl_nic *intelxl = netdev->priv;
	struct intelxl_admin_descriptor *cmd;
	struct intelxl_admin_vf_get_resources_buffer *res;
	int rc;

	/* Populate descriptor */
	cmd = intelxl_admin_command_descriptor ( intelxl );
	cmd->vopcode = cpu_to_le32 ( INTELXL_ADMIN_VF_GET_RESOURCES );

	/* Issue command */
	if ( ( rc = intelxlvf_admin_command ( netdev ) ) != 0 )
		return rc;

	/* Parse response */
	res = &intelxl->vbuf.res;
	intelxl->vsi = le16_to_cpu ( res->vsi );
	memcpy ( netdev->hw_addr, res->mac, ETH_ALEN );
	DBGC ( intelxl, "INTELXL %p VSI %#04x\n", intelxl, intelxl->vsi );

	return 0;
}
Beispiel #13
0
/**
 * Wait for virtual function to be marked as active
 *
 * @v intelxl		Intel device
 * @ret rc		Return status code
 */
static int intelxlvf_reset_wait_active ( struct intelxl_nic *intelxl ) {
	uint32_t vfgen_rstat;
	unsigned int vfr_state;
	unsigned int i;

	/* Wait for virtual function to be marked as active */
	for ( i = 0 ; i < INTELXLVF_RESET_MAX_WAIT_MS ; i++ ) {

		/* Check status as written by physical function driver */
		vfgen_rstat = readl ( intelxl->regs + INTELXLVF_VFGEN_RSTAT );
		vfr_state = INTELXLVF_VFGEN_RSTAT_VFR_STATE ( vfgen_rstat );
		if ( vfr_state == INTELXLVF_VFGEN_RSTAT_VFR_STATE_ACTIVE )
			return 0;

		/* Delay */
		mdelay ( 1 );
	}

	DBGC ( intelxl, "INTELXL %p timed out waiting for activation "
	       "(%#08x)\n", intelxl, vfgen_rstat );
	return -ETIMEDOUT;
}
/**
 * Hold off watchdog timer
 *
 * @v retry		Retry timer
 * @v over		Failure indicator
 */
static void efi_watchdog_expired ( struct retry_timer *timer,
				   int over __unused ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	static CHAR16 data[] = WATCHDOG_DATA;
	EFI_STATUS efirc;
	int rc;

	DBGC2 ( timer, "EFI holding off watchdog timer\n" );

	/* Restart this holdoff timer */
	start_timer_fixed ( timer, ( WATCHDOG_HOLDOFF_SECS * TICKS_PER_SEC ) );

	/* Reset watchdog timer */
	if ( ( efirc = bs->SetWatchdogTimer ( WATCHDOG_TIMEOUT_SECS,
					      WATCHDOG_CODE, sizeof ( data ),
					      data ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( timer, "EFI could not set watchdog timer: %s\n",
		       strerror ( rc ) );
		return;
	}
}
Beispiel #15
0
Datei: nii.c Projekt: baloo/ipxe
/**
 * Set station address
 *
 * @v nii		NII NIC
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int nii_set_station_address ( struct nii_nic *nii,
				     struct net_device *netdev ) {
	PXE_CPB_STATION_ADDRESS cpb;
	int stat;
	int rc;

	/* Construct parameter block */
	memset ( &cpb, 0, sizeof ( cpb ) );
	memcpy ( cpb.StationAddr, netdev->ll_addr,
		 netdev->ll_protocol->ll_addr_len );

	/* Issue command */
	if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_STATION_ADDRESS,
				      &cpb, sizeof ( cpb ) ) ) < 0 ) {
		rc = -EIO_STAT ( stat );
		DBGC ( nii, "NII %s could not set station address: %s\n",
		       nii->dev.name, strerror ( rc ) );
		return rc;
	}

	return 0;
}
Beispiel #16
0
/**
 * Transmit packet
 *
 * @v netdev		Network device
 * @v iobuf		I/O buffer
 * @ret rc		Return status code
 */
static int netfront_transmit ( struct net_device *netdev,
			       struct io_buffer *iobuf ) {
	struct netfront_nic *netfront = netdev->priv;
	struct xen_device *xendev = netfront->xendev;
	struct netif_tx_request *request;
	int notify;
	int rc;

	/* Check that we have space in the ring */
	if ( netfront_ring_is_full ( &netfront->tx ) ) {
		DBGC ( netfront, "NETFRONT %s out of transmit descriptors\n",
		       xendev->key );
		return -ENOBUFS;
	}

	/* Add to descriptor ring */
	request = RING_GET_REQUEST ( &netfront->tx_fring,
				     netfront->tx_fring.req_prod_pvt );
	if ( ( rc = netfront_push ( netfront, &netfront->tx, iobuf,
				    &request->id, &request->gref ) ) != 0 ) {
		return rc;
	}
	request->offset = ( virt_to_phys ( iobuf->data ) & ( PAGE_SIZE - 1 ) );
	request->flags = NETTXF_data_validated;
	request->size = iob_len ( iobuf );
	DBGC2 ( netfront, "NETFRONT %s TX id %d ref %d is %#08lx+%zx\n",
		xendev->key, request->id, request->gref,
		virt_to_phys ( iobuf->data ), iob_len ( iobuf ) );

	/* Consume descriptor */
	netfront->tx_fring.req_prod_pvt++;

	/* Push new descriptor and notify backend if applicable */
	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY ( &netfront->tx_fring, notify );
	if ( notify )
		netfront_send_event ( netfront );

	return 0;
}
Beispiel #17
0
/**
 * Reload configuration from EEPROM
 *
 * @v myson		Myson device
 * @ret rc		Return status code
 */
static int myson_reload_config ( struct myson_nic *myson ) {
	unsigned int i;

	/* Initiate reload */
	writel ( MYSON_ROM_AUTOLD, myson->regs + MYSON_ROM_MII );

	/* Wait for reload to complete */
	for ( i = 0 ; i < MYSON_AUTOLD_MAX_WAIT_MS ; i++ ) {

		/* If reload is not complete, delay 1ms and retry */
		if ( readl ( myson->regs + MYSON_ROM_MII ) & MYSON_ROM_AUTOLD ){
			mdelay ( 1 );
			continue;
		}

		return 0;
	}

	DBGC ( myson, "MYSON %p timed out waiting for configuration "
	       "reload\n", myson );
	return -ETIMEDOUT;
}
Beispiel #18
0
/**
 * Poll for received packets
 *
 * @v netdev		Network device
 */
static void myson_poll_rx ( struct net_device *netdev ) {
	struct myson_nic *myson = netdev->priv;
	struct myson_descriptor *rx;
	struct io_buffer *iobuf;
	unsigned int rx_idx;
	size_t len;

	/* Check for received packets */
	while ( myson->rx.cons != myson->rx.prod ) {

		/* Get next receive descriptor */
		rx_idx = ( myson->rx.cons % MYSON_NUM_RX_DESC );
		rx = &myson->rx.desc[rx_idx];

		/* Stop if descriptor is still in use */
		if ( rx->status & MYSON_RX_STAT_OWN )
			return;

		/* Populate I/O buffer */
		iobuf = myson->rx_iobuf[rx_idx];
		myson->rx_iobuf[rx_idx] = NULL;
		len = MYSON_RX_STAT_FLNG ( le32_to_cpu ( rx->status ) );
		iob_put ( iobuf, len - 4 /* strip CRC */ );

		/* Hand off to network stack */
		if ( rx->status & cpu_to_le32 ( MYSON_RX_STAT_ES ) ) {
			DBGC ( myson, "MYSON %p RX %d error (length %zd, "
			       "status %08x)\n", myson, rx_idx, len,
			       le32_to_cpu ( rx->status ) );
			netdev_rx_err ( netdev, iobuf, -EIO );
		} else {
			DBGC2 ( myson, "MYSON %p RX %d complete (length "
				"%zd)\n", myson, rx_idx, len );
			netdev_rx ( netdev, iobuf );
		}
		myson->rx.cons++;
	}
}
Beispiel #19
0
Datei: nii.c Projekt: baloo/ipxe
/**
 * Start UNDI
 *
 * @v nii		NII NIC
 * @ret rc		Return status code
 */
static int nii_start_undi ( struct nii_nic *nii ) {
	PXE_CPB_START_31 cpb;
	int stat;
	int rc;

	/* Construct parameter block */
	memset ( &cpb, 0, sizeof ( cpb ) );
	cpb.Delay = ( ( intptr_t ) nii_delay );
	cpb.Block = ( ( intptr_t ) nii_block );
	cpb.Mem_IO = ( ( intptr_t ) nii_io );
	cpb.Unique_ID = ( ( intptr_t ) nii );

	/* Issue command */
	if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_START, &cpb,
				      sizeof ( cpb ) ) ) < 0 ) {
		rc = -EIO_STAT ( stat );
		DBGC ( nii, "NII %s could not start: %s\n",
		       nii->dev.name, strerror ( rc ) );
		return rc;
	}

	return 0;
}
Beispiel #20
0
Datei: open.c Projekt: 42wim/ipxe
/**
 * Open location
 *
 * @v intf		Data transfer interface
 * @v type		Location type
 * @v args		Remaining arguments depend upon location type
 * @ret rc		Return status code
 */
int xfer_vopen ( struct interface *intf, int type, va_list args ) {
	switch ( type ) {
	case LOCATION_URI_STRING: {
		const char *uri_string = va_arg ( args, const char * );

		return xfer_open_uri_string ( intf, uri_string ); }
	case LOCATION_URI: {
		struct uri *uri = va_arg ( args, struct uri * );

		return xfer_open_uri ( intf, uri ); }
	case LOCATION_SOCKET: {
		int semantics = va_arg ( args, int );
		struct sockaddr *peer = va_arg ( args, struct sockaddr * );
		struct sockaddr *local = va_arg ( args, struct sockaddr * );

		return xfer_open_socket ( intf, semantics, peer, local ); }
	default:
		DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to "
		       "open unsupported location type %d\n",
		       INTF_DBG ( intf ), type );
		return -ENOTSUP;
	}
}
Beispiel #21
0
/**
 * Read from MII register
 *
 * @v mii		MII interface
 * @v reg		Register address
 * @ret value		Data read, or negative error
 */
static int rhine_mii_read ( struct mii_interface *mii, unsigned int reg ) {
	struct rhine_nic *rhn = container_of ( mii, struct rhine_nic, mii );
	unsigned int timeout = RHINE_TIMEOUT_US;
	uint8_t cr;

	DBGC2 ( rhn, "RHINE %p MII read reg %d\n", rhn, reg );

	/* Initiate read */
	writeb ( reg, rhn->regs + RHINE_MII_ADDR );
	cr = readb ( rhn->regs + RHINE_MII_CR );
	writeb ( ( cr | RHINE_MII_CR_RDEN ), rhn->regs + RHINE_MII_CR );

	/* Wait for read to complete */
	while ( timeout-- ) {
		udelay ( 1 );
		cr = readb ( rhn->regs + RHINE_MII_CR );
		if ( ! ( cr & RHINE_MII_CR_RDEN ) )
			return readw ( rhn->regs + RHINE_MII_RDWR );
	}

	DBGC ( rhn, "RHINE %p MII read timeout\n", rhn );
	return -ETIMEDOUT;
}
Beispiel #22
0
/**
 * Wait for MII to become idle
 *
 * @v smsc95xx		SMSC95xx device
 * @ret rc		Return status code
 */
static int smsc95xx_mii_wait ( struct smsc95xx_device *smsc95xx ) {
	uint32_t mii_access;
	unsigned int i;
	int rc;

	/* Wait for MIIBZY to become clear */
	for ( i = 0 ; i < SMSC95XX_MII_MAX_WAIT_MS ; i++ ) {

		/* Read MII_ACCESS and check MIIBZY */
		if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_MII_ACCESS,
					     &mii_access ) ) != 0 )
			return rc;
		if ( ! ( mii_access & SMSC95XX_MII_ACCESS_MIIBZY ) )
			return 0;

		/* Delay */
		mdelay ( 1 );
	}

	DBGC ( smsc95xx, "SMSC95XX %p timed out waiting for MII\n",
	       smsc95xx );
	return -ETIMEDOUT;
}
/**
 * Read block device capacity
 *
 * @v control		Control interface
 * @v data		Data interface
 * @ret rc		Return status code
 */
int http_block_read_capacity ( struct http_transaction *http,
			       struct interface *data ) {
	int rc;

	/* Start a HEAD request to retrieve the capacity */
	if ( ( rc = http_open ( data, &http_head, http->uri, NULL,
				NULL ) ) != 0 )
		goto err_open;

	/* Insert block device translator */
	if ( ( rc = block_translate ( data, UNULL, HTTP_BLKSIZE ) ) != 0 ) {
		DBGC ( http, "HTTP %p could not insert block translator: %s\n",
		       http, strerror ( rc ) );
		goto err_translate;
	}

	return 0;

 err_translate:
	intf_restart ( data, rc );
 err_open:
	return rc;
}
Beispiel #24
0
/**
 * Wait for EEPROM to become idle
 *
 * @v smsc95xx		SMSC95xx device
 * @ret rc		Return status code
 */
static int smsc95xx_eeprom_wait ( struct smsc95xx_device *smsc95xx ) {
	uint32_t e2p_cmd;
	unsigned int i;
	int rc;

	/* Wait for EPC_BSY to become clear */
	for ( i = 0 ; i < SMSC95XX_EEPROM_MAX_WAIT_MS ; i++ ) {

		/* Read E2P_CMD and check EPC_BSY */
		if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_E2P_CMD,
					     &e2p_cmd ) ) != 0 )
			return rc;
		if ( ! ( e2p_cmd & SMSC95XX_E2P_CMD_EPC_BSY ) )
			return 0;

		/* Delay */
		mdelay ( 1 );
	}

	DBGC ( smsc95xx, "SMSC95XX %p timed out waiting for EEPROM\n",
	       smsc95xx );
	return -ETIMEDOUT;
}
Beispiel #25
0
/**
 * Load PXE image into memory
 *
 * @v image		PXE file
 * @ret rc		Return status code
 */
int pxe_load ( struct image *image ) {
	userptr_t buffer = real_to_user ( 0, 0x7c00 );
	size_t filesz = image->len;
	size_t memsz = image->len;
	int rc;

	/* Images too large to fit in base memory cannot be PXE
	 * images.  We include this check to help prevent unrecognised
	 * images from being marked as PXE images, since PXE images
	 * have no signature we can check against.
	 */
	if ( filesz > ( 0xa0000 - 0x7c00 ) )
		return -ENOEXEC;

	/* Rejecting zero-length images is also useful, since these
	 * end up looking to the user like bugs in gPXE.
	 */
	if ( ! filesz )
		return -ENOEXEC;

	/* There are no signature checks for PXE; we will accept anything */
	if ( ! image->type )
		image->type = &pxe_image_type;

	/* Verify and prepare segment */
	if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
		DBGC ( image, "IMAGE %p could not prepare segment: %s\n",
		       image, strerror ( rc ) );
		return rc;
	}

	/* Copy image to segment */
	memcpy_user ( buffer, 0, image->data, 0, filesz );

	return 0;
}
Beispiel #26
0
/**
 * Open the network device
 *
 * @v snp		SNP interface
 * @v extra_rx_bufsize	Extra RX buffer size, in bytes
 * @v extra_tx_bufsize	Extra TX buffer size, in bytes
 * @ret efirc		EFI status code
 */
static EFI_STATUS EFIAPI
efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
		     UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
	struct efi_snp_device *snpdev =
		container_of ( snp, struct efi_snp_device, snp );
	int rc;

	DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
		snpdev, ( ( unsigned long ) extra_rx_bufsize ),
		( ( unsigned long ) extra_tx_bufsize ) );

	/* Fail if net device is currently claimed for use by iPXE */
	if ( efi_snp_claimed )
		return EFI_NOT_READY;

	if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
		DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
		       snpdev, snpdev->netdev->name, strerror ( rc ) );
		return EFIRC ( rc );
	}
	efi_snp_set_state ( snpdev );

	return 0;
}
Beispiel #27
0
/**
 * Open network device
 *
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int nii_open ( struct net_device *netdev ) {
	struct nii_nic *nii = netdev->priv;
	int rc;

	/* Initialise NIC
	 *
	 * Some Emulex NII drivers have a bug which prevents packets
	 * from being sent or received unless we specifically ask it
	 * to detect cable presence during initialisation.  Work
	 * around these buggy drivers by requesting cable detection at
	 * this point, even though we don't care about link state here
	 * (and would prefer to have the NIC initialise even if no
	 * cable is present, to match the behaviour of all other iPXE
	 * drivers).
	 */
	if ( ( rc = nii_initialise_and_detect ( nii ) ) != 0 )
		goto err_initialise;

	/* Attempt to set station address */
	if ( ( rc = nii_set_station_address ( nii, netdev ) ) != 0 ) {
		DBGC ( nii, "NII %s could not set station address: %s\n",
		       nii->dev.name, strerror ( rc ) );
		/* Treat as non-fatal */
	}

	/* Set receive filters */
	if ( ( rc = nii_set_rx_filters ( nii ) ) != 0 )
		goto err_set_rx_filters;

	return 0;

 err_set_rx_filters:
	nii_shutdown ( nii );
 err_initialise:
	return rc;
}
Beispiel #28
0
/**
 * Transmit Fibre Channel ELS frame
 *
 * @v els		Fibre Channel ELS transaction
 * @v data		Data to transmit
 * @v len		Length of data
 * @ret rc		Return status code
 */
int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) {
    struct xfer_metadata meta;
    struct sockaddr_fc dest;
    int rc;

    DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) );
    DBGC2_HDA ( els, 0, data, len );

    /* Construct metadata */
    memset ( &meta, 0, sizeof ( meta ) );
    meta.flags = ( fc_els_is_request ( els ) ?
                   XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) );
    meta.dest = fc_fill_sockaddr ( &dest, &els->peer_port_id );

    /* Transmit frame */
    if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len,
                                        &meta ) ) != 0 ) {
        DBGC ( els, FCELS_FMT " could not deliver frame: %s\n",
               FCELS_ARGS ( els ), strerror ( rc ) );
        return rc;
    }

    return 0;
}
Beispiel #29
0
/**
 * Start name resolution
 *
 * @v resolv		Name resolution interface
 * @v name		Name to resolve
 * @v sa		Socket address to complete
 * @ret rc		Return status code
 */
int resolv ( struct interface *resolv, const char *name,
	     struct sockaddr *sa ) {
	struct resolv_mux *mux;
	size_t name_len = ( strlen ( name ) + 1 );
	int rc;

	/* Allocate and initialise structure */
	mux = zalloc ( sizeof ( *mux ) + name_len );
	if ( ! mux )
		return -ENOMEM;
	ref_init ( &mux->refcnt, NULL );
	intf_init ( &mux->parent, &null_intf_desc, &mux->refcnt );
	intf_init ( &mux->child, &resmux_child_desc, &mux->refcnt );
	mux->resolver = table_start ( RESOLVERS );
	if ( sa )
		memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
	memcpy ( mux->name, name, name_len );

	DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );

	/* Start first resolver in chain.  There will always be at
	 * least one resolver (the numeric resolver), so no need to
	 * check for the zero-resolvers-available case.
	 */
	if ( ( rc = resmux_try ( mux ) ) != 0 )
		goto err;

	/* Attach parent interface, mortalise self, and return */
	intf_plug_plug ( &mux->parent, resolv );
	ref_put ( &mux->refcnt );
	return 0;

 err:
	ref_put ( &mux->refcnt );
	return rc;	
}
Beispiel #30
0
Datei: nii.c Projekt: baloo/ipxe
/**
 * I/O callback
 *
 * @v unique_id		NII NIC
 * @v op		Operations
 * @v len		Length of data
 * @v addr		Address
 * @v data		Data buffer
 */
static EFIAPI VOID nii_io ( UINT64 unique_id, UINT8 op, UINT8 len, UINT64 addr,
			    UINT64 data ) {
	struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
	EFI_PCI_IO_PROTOCOL_ACCESS *access;
	EFI_PCI_IO_PROTOCOL_IO_MEM io;
	EFI_PCI_IO_PROTOCOL_WIDTH width;
	unsigned int bar;
	EFI_STATUS efirc;
	int rc;

	/* Determine accessor and BAR */
	if ( op & ( PXE_MEM_READ | PXE_MEM_WRITE ) ) {
		access = &nii->pci_io->Mem;
		bar = nii->mem_bar;
	} else {
		access = &nii->pci_io->Io;
		bar = nii->io_bar;
	}

	/* Determine operaton */
	io = ( ( op & ( PXE_IO_WRITE | PXE_MEM_WRITE ) ) ?
	       access->Write : access->Read );

	/* Determine width */
	width = ( fls ( len ) - 1 );

	/* Issue operation */
	if ( ( efirc = io ( nii->pci_io, width, bar, addr, 1,
			    ( ( void * ) ( intptr_t ) data ) ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( nii, "NII %s I/O operation %#x failed: %s\n",
		       nii->dev.name, op, strerror ( rc ) );
		/* No way to report failure */
		return;
	}
}