mirror of https://github.com/ipxe/ipxe.git
struct nic is now part of struct dev, rather than the other way around.
Tie into new boot device framework.pull/1/head
parent
31410b1b5d
commit
1434e8d68d
198
src/core/nic.c
198
src/core/nic.c
|
@ -15,6 +15,8 @@ Literature dealing with the network protocols:
|
||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
#include "etherboot.h"
|
#include "etherboot.h"
|
||||||
|
#include "console.h"
|
||||||
|
#include "dev.h"
|
||||||
#include "nic.h"
|
#include "nic.h"
|
||||||
#include "elf.h" /* FOR EM_CURRENT */
|
#include "elf.h" /* FOR EM_CURRENT */
|
||||||
|
|
||||||
|
@ -221,52 +223,6 @@ int vci_etherboot;
|
||||||
#endif
|
#endif
|
||||||
#endif /* NO_DHCP_SUPPORT */
|
#endif /* NO_DHCP_SUPPORT */
|
||||||
|
|
||||||
static int dummy(void *unused __unused)
|
|
||||||
{
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Careful. We need an aligned buffer to avoid problems on machines
|
|
||||||
* that care about alignment. To trivally align the ethernet data
|
|
||||||
* (the ip hdr and arp requests) we offset the packet by 2 bytes.
|
|
||||||
* leaving the ethernet data 16 byte aligned. Beyond this
|
|
||||||
* we use memmove but this makes the common cast simple and fast.
|
|
||||||
*/
|
|
||||||
static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
|
|
||||||
|
|
||||||
struct nic nic =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0, /* dev.disable */
|
|
||||||
{
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
PCI_BUS_TYPE,
|
|
||||||
}, /* dev.devid */
|
|
||||||
0, /* index */
|
|
||||||
0, /* type */
|
|
||||||
PROBE_FIRST, /* how_pobe */
|
|
||||||
PROBE_NONE, /* to_probe */
|
|
||||||
0, /* failsafe */
|
|
||||||
0, /* type_index */
|
|
||||||
{}, /* state */
|
|
||||||
},
|
|
||||||
(int (*)(struct nic *, int))dummy, /* poll */
|
|
||||||
(void (*)(struct nic *, const char *,
|
|
||||||
unsigned int, unsigned int,
|
|
||||||
const char *))dummy, /* transmit */
|
|
||||||
(void (*)(struct nic *,
|
|
||||||
irq_action_t))dummy, /* irq */
|
|
||||||
0, /* flags */
|
|
||||||
&rom, /* rom_info */
|
|
||||||
arptable[ARP_CLIENT].node, /* node_addr */
|
|
||||||
packet + ETH_DATA_ALIGN, /* packet */
|
|
||||||
0, /* packetlen */
|
|
||||||
0, /* ioaddr */
|
|
||||||
0, /* irqno */
|
|
||||||
0, /* priv_data */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef RARP_NOT_BOOTP
|
#ifdef RARP_NOT_BOOTP
|
||||||
static int rarp(void);
|
static int rarp(void);
|
||||||
#else
|
#else
|
||||||
|
@ -275,42 +231,12 @@ static int bootp(void);
|
||||||
static unsigned short tcpudpchksum(struct iphdr *ip);
|
static unsigned short tcpudpchksum(struct iphdr *ip);
|
||||||
|
|
||||||
|
|
||||||
int eth_probe(struct dev *dev)
|
struct nic *nic = &dev.nic;
|
||||||
{
|
|
||||||
return probe(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
int eth_poll(int retrieve)
|
|
||||||
{
|
|
||||||
return ((*nic.poll)(&nic, retrieve));
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p)
|
|
||||||
{
|
|
||||||
(*nic.transmit)(&nic, d, t, s, p);
|
|
||||||
if (t == ETH_P_IP) twiddle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_disable(void)
|
|
||||||
{
|
|
||||||
#ifdef MULTICAST_LEVEL2
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < MAX_IGMP; i++) {
|
|
||||||
leave_group(i);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
disable(&nic.dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_irq (irq_action_t action)
|
|
||||||
{
|
|
||||||
(*nic.irq)(&nic,action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out what our boot parameters are
|
* Find out what our boot parameters are
|
||||||
*/
|
*/
|
||||||
int eth_load_configuration(struct dev *dev __unused)
|
static int nic_load_configuration(struct dev *dev __unused)
|
||||||
{
|
{
|
||||||
int server_found;
|
int server_found;
|
||||||
/* Find a server to get BOOTP reply from */
|
/* Find a server to get BOOTP reply from */
|
||||||
|
@ -340,7 +266,7 @@ int eth_load_configuration(struct dev *dev __unused)
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
LOAD - Try to get booted
|
LOAD - Try to get booted
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
int eth_load(struct dev *dev __unused)
|
static int nic_load(struct dev *dev __unused)
|
||||||
{
|
{
|
||||||
const char *kernel;
|
const char *kernel;
|
||||||
printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
|
printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
|
||||||
|
@ -390,6 +316,56 @@ int eth_load(struct dev *dev __unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void nic_disable ( struct dev *dev ) {
|
||||||
|
struct nic *nic = &dev->nic;
|
||||||
|
|
||||||
|
#ifdef MULTICAST_LEVEL2
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < MAX_IGMP; i++) {
|
||||||
|
leave_group(i);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nic->nic_op->disable ( nic );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device operations tables
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct dev_operations nic_operations = {
|
||||||
|
.disable = nic_disable,
|
||||||
|
.load_configuration = nic_load_configuration,
|
||||||
|
.load = nic_load,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Careful. We need an aligned buffer to avoid problems on machines
|
||||||
|
* that care about alignment. To trivally align the ethernet data
|
||||||
|
* (the ip hdr and arp requests) we offset the packet by 2 bytes.
|
||||||
|
* leaving the ethernet data 16 byte aligned. Beyond this
|
||||||
|
* we use memmove but this makes the common cast simple and fast.
|
||||||
|
*/
|
||||||
|
static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a struct dev to operate as a NIC, return the struct nic *
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct nic * nic_device ( struct dev *dev ) {
|
||||||
|
struct nic *nic = &dev->nic;
|
||||||
|
|
||||||
|
memset ( nic, 0, sizeof ( *nic ) );
|
||||||
|
nic->node_addr = arptable[ARP_CLIENT].node;
|
||||||
|
nic->packet = packet + ETH_DATA_ALIGN;
|
||||||
|
dev->dev_op = &nic_operations;
|
||||||
|
return nic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
DEFAULT_NETMASK - Return default netmask for IP address
|
DEFAULT_NETMASK - Return default netmask for IP address
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -414,9 +390,9 @@ static int await_arp(int ival, void *ptr,
|
||||||
struct arprequest *arpreply;
|
struct arprequest *arpreply;
|
||||||
if (ptype != ETH_P_ARP)
|
if (ptype != ETH_P_ARP)
|
||||||
return 0;
|
return 0;
|
||||||
if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
|
if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
|
||||||
return 0;
|
return 0;
|
||||||
arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
||||||
|
|
||||||
if (arpreply->opcode != htons(ARP_REPLY))
|
if (arpreply->opcode != htons(ARP_REPLY))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -703,7 +679,7 @@ int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
|
||||||
continue; /* Back to waiting for packet */
|
continue; /* Back to waiting for packet */
|
||||||
}
|
}
|
||||||
/* Packet has been received */
|
/* Packet has been received */
|
||||||
rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
|
rcvd = (struct tftp_t *)&nic->packet[ETH_HLEN];
|
||||||
recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
|
recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
|
||||||
- sizeof(rcvd->opcode);
|
- sizeof(rcvd->opcode);
|
||||||
rport = ntohs(rcvd->udp.src);
|
rport = ntohs(rcvd->udp.src);
|
||||||
|
@ -783,9 +759,9 @@ static int await_rarp(int ival, void *ptr,
|
||||||
struct arprequest *arpreply;
|
struct arprequest *arpreply;
|
||||||
if (ptype != ETH_P_RARP)
|
if (ptype != ETH_P_RARP)
|
||||||
return 0;
|
return 0;
|
||||||
if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
|
if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
|
||||||
return 0;
|
return 0;
|
||||||
arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
||||||
if (arpreply->opcode != htons(RARP_REPLY))
|
if (arpreply->opcode != htons(RARP_REPLY))
|
||||||
return 0;
|
return 0;
|
||||||
if ((arpreply->opcode == htons(RARP_REPLY)) &&
|
if ((arpreply->opcode == htons(RARP_REPLY)) &&
|
||||||
|
@ -847,9 +823,9 @@ static int await_bootp(int ival __unused, void *ptr __unused,
|
||||||
if (!udp) {
|
if (!udp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
|
bootpreply = (struct bootp_t *)&nic->packet[ETH_HLEN +
|
||||||
sizeof(struct iphdr) + sizeof(struct udphdr)];
|
sizeof(struct iphdr) + sizeof(struct udphdr)];
|
||||||
if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
|
if (nic->packetlen < ETH_HLEN + sizeof(struct iphdr) +
|
||||||
sizeof(struct udphdr) +
|
sizeof(struct udphdr) +
|
||||||
#ifdef NO_DHCP_SUPPORT
|
#ifdef NO_DHCP_SUPPORT
|
||||||
sizeof(struct bootp_t)
|
sizeof(struct bootp_t)
|
||||||
|
@ -922,11 +898,11 @@ static int bootp(void)
|
||||||
unsigned char *bp_vend;
|
unsigned char *bp_vend;
|
||||||
|
|
||||||
#ifndef NO_DHCP_SUPPORT
|
#ifndef NO_DHCP_SUPPORT
|
||||||
dhcp_machine_info[4] = nic.dev.devid.bus_type;
|
dhcp_machine_info[4] = dev.devid.bus_type;
|
||||||
dhcp_machine_info[5] = nic.dev.devid.vendor_id & 0xff;
|
dhcp_machine_info[5] = dev.devid.vendor_id & 0xff;
|
||||||
dhcp_machine_info[6] = ((nic.dev.devid.vendor_id) >> 8) & 0xff;
|
dhcp_machine_info[6] = ((dev.devid.vendor_id) >> 8) & 0xff;
|
||||||
dhcp_machine_info[7] = nic.dev.devid.device_id & 0xff;
|
dhcp_machine_info[7] = dev.devid.device_id & 0xff;
|
||||||
dhcp_machine_info[8] = ((nic.dev.devid.device_id) >> 8) & 0xff;
|
dhcp_machine_info[8] = ((dev.devid.device_id) >> 8) & 0xff;
|
||||||
#endif /* NO_DHCP_SUPPORT */
|
#endif /* NO_DHCP_SUPPORT */
|
||||||
memset(&ip, 0, sizeof(struct bootpip_t));
|
memset(&ip, 0, sizeof(struct bootpip_t));
|
||||||
ip.bp.bp_op = BOOTP_REQUEST;
|
ip.bp.bp_op = BOOTP_REQUEST;
|
||||||
|
@ -1092,11 +1068,11 @@ static void process_igmp(struct iphdr *ip, unsigned long now)
|
||||||
int i;
|
int i;
|
||||||
unsigned iplen;
|
unsigned iplen;
|
||||||
if (!ip || (ip->protocol == IP_IGMP) ||
|
if (!ip || (ip->protocol == IP_IGMP) ||
|
||||||
(nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
|
(nic->packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iplen = (ip->verhdrlen & 0xf)*4;
|
iplen = (ip->verhdrlen & 0xf)*4;
|
||||||
igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)];
|
igmp = (struct igmp *)&nic->packet[sizeof(struct iphdr)];
|
||||||
if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
|
if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
|
||||||
return;
|
return;
|
||||||
if ((igmp->type == IGMP_QUERY) &&
|
if ((igmp->type == IGMP_QUERY) &&
|
||||||
|
@ -1303,7 +1279,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
||||||
syn_ack = state == CLOSED || state == SYN_RCVD;
|
syn_ack = state == CLOSED || state == SYN_RCVD;
|
||||||
consumed = ntohl(tcp->ack) - send_seq - syn_ack;
|
consumed = ntohl(tcp->ack) - send_seq - syn_ack;
|
||||||
if (consumed < 0 || consumed > can_send) {
|
if (consumed < 0 || consumed > can_send) {
|
||||||
tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
|
tcp_reset((struct iphdr *)&nic->packet[ETH_HLEN]);
|
||||||
goto recv_data;
|
goto recv_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,7 +1321,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
consume_data:
|
consume_data:
|
||||||
ip = (struct iphdr *)&nic.packet[ETH_HLEN];
|
ip = (struct iphdr *)&nic->packet[ETH_HLEN];
|
||||||
header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
|
header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
|
||||||
payload = ntohs(ip->len) - header_size;
|
payload = ntohs(ip->len) - header_size;
|
||||||
if (payload > 0 && state == ESTABLISHED) {
|
if (payload > 0 && state == ESTABLISHED) {
|
||||||
|
@ -1354,7 +1330,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
||||||
recv_seq += payload - old_bytes;
|
recv_seq += payload - old_bytes;
|
||||||
if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
|
if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
|
||||||
!recv(payload - old_bytes,
|
!recv(payload - old_bytes,
|
||||||
&nic.packet[ETH_HLEN+header_size+old_bytes],
|
&nic->packet[ETH_HLEN+header_size+old_bytes],
|
||||||
ptr)) {
|
ptr)) {
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
|
@ -1466,15 +1442,15 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
||||||
/* We have something! */
|
/* We have something! */
|
||||||
|
|
||||||
/* Find the Ethernet packet type */
|
/* Find the Ethernet packet type */
|
||||||
if (nic.packetlen >= ETH_HLEN) {
|
if (nic->packetlen >= ETH_HLEN) {
|
||||||
ptype = ((unsigned short) nic.packet[12]) << 8
|
ptype = ((unsigned short) nic->packet[12]) << 8
|
||||||
| ((unsigned short) nic.packet[13]);
|
| ((unsigned short) nic->packet[13]);
|
||||||
} else continue; /* what else could we do with it? */
|
} else continue; /* what else could we do with it? */
|
||||||
/* Verify an IP header */
|
/* Verify an IP header */
|
||||||
ip = 0;
|
ip = 0;
|
||||||
if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
|
if ((ptype == ETH_P_IP) && (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
|
||||||
unsigned ipoptlen;
|
unsigned ipoptlen;
|
||||||
ip = (struct iphdr *)&nic.packet[ETH_HLEN];
|
ip = (struct iphdr *)&nic->packet[ETH_HLEN];
|
||||||
if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
|
if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
|
||||||
continue;
|
continue;
|
||||||
iplen = (ip->verhdrlen & 0xf) * 4;
|
iplen = (ip->verhdrlen & 0xf) * 4;
|
||||||
|
@ -1496,17 +1472,17 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
||||||
/* Delete the ip options, to guarantee
|
/* Delete the ip options, to guarantee
|
||||||
* good alignment, and make etherboot simpler.
|
* good alignment, and make etherboot simpler.
|
||||||
*/
|
*/
|
||||||
memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
|
memmove(&nic->packet[ETH_HLEN + sizeof(struct iphdr)],
|
||||||
&nic.packet[ETH_HLEN + iplen],
|
&nic->packet[ETH_HLEN + iplen],
|
||||||
nic.packetlen - ipoptlen);
|
nic->packetlen - ipoptlen);
|
||||||
nic.packetlen -= ipoptlen;
|
nic->packetlen -= ipoptlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
udp = 0;
|
udp = 0;
|
||||||
if (ip && (ip->protocol == IP_UDP) &&
|
if (ip && (ip->protocol == IP_UDP) &&
|
||||||
(nic.packetlen >=
|
(nic->packetlen >=
|
||||||
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
||||||
udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
|
udp = (struct udphdr *)&nic->packet[ETH_HLEN + sizeof(struct iphdr)];
|
||||||
|
|
||||||
/* Make certain we have a reasonable packet length */
|
/* Make certain we have a reasonable packet length */
|
||||||
if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
|
if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
|
||||||
|
@ -1520,9 +1496,9 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
||||||
tcp = 0;
|
tcp = 0;
|
||||||
#ifdef DOWNLOAD_PROTO_HTTP
|
#ifdef DOWNLOAD_PROTO_HTTP
|
||||||
if (ip && (ip->protocol == IP_TCP) &&
|
if (ip && (ip->protocol == IP_TCP) &&
|
||||||
(nic.packetlen >=
|
(nic->packetlen >=
|
||||||
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
|
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
|
||||||
tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
|
tcp = (struct tcphdr *)&nic->packet[ETH_HLEN +
|
||||||
sizeof(struct iphdr)];
|
sizeof(struct iphdr)];
|
||||||
/* Make certain we have a reasonable packet length */
|
/* Make certain we have a reasonable packet length */
|
||||||
if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
|
if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
|
||||||
|
@ -1544,11 +1520,11 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
||||||
* action. This allows us reply to arp, igmp, and lacp queries.
|
* action. This allows us reply to arp, igmp, and lacp queries.
|
||||||
*/
|
*/
|
||||||
if ((ptype == ETH_P_ARP) &&
|
if ((ptype == ETH_P_ARP) &&
|
||||||
(nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
|
(nic->packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
|
||||||
struct arprequest *arpreply;
|
struct arprequest *arpreply;
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
|
|
||||||
arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
||||||
memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
|
memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
|
||||||
if ((arpreply->opcode == htons(ARP_REQUEST)) &&
|
if ((arpreply->opcode == htons(ARP_REQUEST)) &&
|
||||||
(tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
|
(tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
|
||||||
|
|
Loading…
Reference in New Issue