[Prev][Next][Index][Thread]
Re: some bugs in netboot
Here's the patch relative to oskit-990402
hope it works. more tomorrow.
--
Klaus Espenlaub Email: espenlaub@informatik.uni-ulm.de
Universitaet Ulm Phone: +49 731 50-24178
Abteilung Rechnerstrukturen Fax: +49 731 50-24182
D-89069 Ulm Office: Building O27, Room 316
diff -rNup oskit-990402/boot/net/GNUmakerules oskit-0.97/boot/net/GNUmakerules
--- oskit-990402/boot/net/GNUmakerules Sat Feb 27 13:17:44 1999
+++ oskit-0.97/boot/net/GNUmakerules Thu May 27 13:21:00 1999
@@ -49,7 +49,7 @@ DEPENDLIBS = $(filter %.a, $(foreach DIR
DEPS = $(OBJDIR)/lib/multiboot.o $(OBJFILES) $(DEPENDLIBS) $(OBJDIR)/lib/crtn.o
version.c: $(filter-out version.o,$(DEPS))
- echo >$@ "char version[] = \"NetBoot metakernel v2.6.0\";"
+ echo >$@ "char version[] = \"OSKit NetBoot metakernel v2.7\";"
echo >>$@ "char build_info[] = \"Built `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\nwith options: $(OSKIT_OPTIONS)\";"
CLEAN_FILES += version.c
diff -rNup oskit-990402/boot/net/NEWS oskit-0.97/boot/net/NEWS
--- oskit-990402/boot/net/NEWS Thu Jan 21 00:26:22 1999
+++ oskit-0.97/boot/net/NEWS Tue Jul 13 18:39:36 1999
@@ -63,4 +63,66 @@
- Fixed to not call strlen(0). This is bad. More specifically,
if the program before us stored a bunch of poo at addr 0, then
we can blow our stack in build_cmdline, which allocates
- a dynmaic stack array.
+ a dynamic stack array.
+
+2.5.1 -> 2.6
+ - Added NFS readahead code.
+
+2.6 -> 2.7
+ New code/fixes by Klaus Espenlaub <espenlaub@informatik.uni-ulm.de>
+ - Added code to answer ARP queries sent to us. Previously there was
+ no code to answer ARP queries for our address. This worked, because
+ all serious server systems (that is, *BSD and Linux at least) use
+ the information passed to them on the ARP sent to the server. In
+ the following sequence this doesn't work any more.
+ Test case: Machine C runs netboot kernel, machine S is NFS server.
+ C S
+ S:/this/does/notexist
+ arp -d C
+ S:/this/does/exist
+
+ After this sequence NFS booting stops working - C sends out NFS
+ packets, but S will no longer reply, because it doesn't know where
+ to send the packets. This also happened to me when I let netboot
+ sit there for a whole day and machine S dropped the ARP entry for C.
+ - Pass the multiboot magic number in register %eax. It seems that my
+ kernel (not oskit based) is the only one arund that really checks
+ the magic. I know it's bad to actually read the specs.
+ - Change the ELF loader to load stuff to the load memory address of
+ the section. What else should this value be used for? Again it
+ seems that I'm the first one using different values for VMA and LMA.
+ But don't worry, GNU binutils 2.9.1 (especially objcopy) also have a
+ few annoying bugs in this area.
+ - Change the checks done on the multiboot image. Mostly changes from
+ calling panic() to some sensible error message and then back to the
+ input loop.
+ - Change input handling so that it is more robust. The code is rather
+ inefficient cpu-wise, but it has less buffer overruns and underruns.
+ - Add code to properly number the IP packets sent out. There's just
+ one thing missing in the IP code: checksums.
+
+ The following stuff mostly requires passing at least some of the IP
+ configuration by the kernel command line (using kernel environment
+ variables). The code should be generalized to support bootp
+ configuration. However I'm using etherboot...
+ - Added Linux-style IP/NFS/ethernet card autoconfig. If the
+ environment variables "nfsroot" and "nfsaddrs" are set properly, no
+ bootp request will be sent out. This saves some time and a few log
+ entries. The value of "nfsroot" may contain "%s", which will be
+ replaced by the client IP number.
+ - Added DNS lookup code. Ugly, but working. Currently requires
+ the kernel environment variable "dnsaddrs" to contain an IP address
+ for a working DNS server.
+ - The NFS autoconfig allows just to specify a file name if it is
+ stored on the NFS root filesystem server. You are no longer forced
+ to type 192.168.254.254:/clients/192.168.254.253/crash.mb, just
+ crash.mb, if the NFS autoconfig parameters are set properly. If you
+ need a complete network boot solution for multiboot kernels, have
+ a look at etherboot (version 4.2 and higher). I'm using it with
+ great success. It generates the command line automatically from the
+ bootp request it needs to get its info.
+ - Added code to pass Linux-style boot configuration, if present, to
+ the loaded kernel.
+ - Added a kernel environment variable "bogomips". You'll no longer
+ have to wait for that #$%& loop to finish. But be careful what you
+ pass to the kernel - it's your machine that may crash.
diff -rNup oskit-990402/boot/net/await.c oskit-0.97/boot/net/await.c
--- oskit-990402/boot/net/await.c Thu Feb 18 19:11:09 1999
+++ oskit-0.97/boot/net/await.c Tue May 18 13:41:40 1999
@@ -47,7 +47,7 @@ await_reply(int type, int ival, void *pt
unsigned long time;
struct iphdr *ip;
struct udphdr *udp;
- struct arprequest *arpreply;
+ struct arprequest *arp;
struct rpc_t *rpc;
int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
@@ -56,18 +56,18 @@ await_reply(int type, int ival, void *pt
while(time > currticks()) {
/* pollkbd();*/
if (eth_poll()) { /* We have something! */
+
/* Check for ARP - No IP hdr */
if ((type == AWAIT_ARP) &&
(packetlen >= ETHER_HDR_SIZE +
sizeof(struct arprequest)) &&
(((packet[12] << 8) | packet[13]) == ETHERTYPE_ARP)) {
- arpreply = (struct arprequest *)
+ arp = (struct arprequest *)
&packet[ETHER_HDR_SIZE];
- if ((arpreply->opcode == ntohs(ARPOP_REPLY))
- && memcmp(arpreply->sipaddr, ptr, 4) == 0) {
+ if ((arp->opcode == ntohs(ARPOP_REPLY))
+ && memcmp(arp->sipaddr, ptr, 4) == 0) {
memcpy(arptable[ival].node,
- arpreply->shwaddr,
- ETHER_ADDR_SIZE);
+ arp->shwaddr, ETHER_ADDR_SIZE);
return(1);
}
continue;
@@ -83,6 +83,10 @@ await_reply(int type, int ival, void *pt
(ip->protocol != IP_UDP)) continue;
udp = (struct udphdr *)&packet[ETHER_HDR_SIZE +
sizeof(struct iphdr)];
+
+ /* DNS ? */
+ if ((type == AWAIT_DNS) &&
+ (ntohs(udp->dest) == ival)) return(1);
/* TFTP ? */
if ((type == AWAIT_TFTP) &&
diff -rNup oskit-990402/boot/net/await.h oskit-0.97/boot/net/await.h
--- oskit-990402/boot/net/await.h Sun Jun 1 01:32:03 1997
+++ oskit-0.97/boot/net/await.h Fri May 14 15:11:32 1999
@@ -14,6 +14,7 @@ Author: Martin Renters
#define AWAIT_BOOTP 1
#define AWAIT_TFTP 2
#define AWAIT_RPC 3
+#define AWAIT_DNS 4
int await_reply(int type, int ival, void *ptrv);
diff -rNup oskit-990402/boot/net/base_multiboot_main.c oskit-0.97/boot/net/base_multiboot_main.c
--- oskit-990402/boot/net/base_multiboot_main.c Tue Feb 9 18:05:04 1999
+++ oskit-0.97/boot/net/base_multiboot_main.c Tue Jul 13 18:19:55 1999
@@ -223,7 +223,7 @@ multiboot_main(oskit_addr_t boot_info_pa
char *info_string;
/* Copy the multiboot_info structure into our pre-reserved area.
- This avoids one loose fragment of memory that has to be avoided. */
+ * This avoids one loose fragment of memory that has to be avoided. */
boot_info = *(struct multiboot_info*)phystokv(boot_info_pa);
/*
diff -rNup oskit-990402/boot/net/boot.h oskit-0.97/boot/net/boot.h
--- oskit-990402/boot/net/boot.h Thu Apr 9 00:42:15 1998
+++ oskit-0.97/boot/net/boot.h Tue Jul 13 18:20:19 1999
@@ -27,7 +27,7 @@ struct kerninfo {
struct multiboot_header ki_mbhdr; /* things like load address, entry */
- void *ki_imgaddr; /* where it is in memory */
+ void *ki_imgaddr; /* where it is in memory */
struct multiboot_info *ki_mbinfo; /* stuff we are passing to it */
};
diff -rNup oskit-990402/boot/net/dns.c oskit-0.97/boot/net/dns.c
--- oskit-990402/boot/net/dns.c Thu Jan 1 01:00:00 1970
+++ oskit-0.97/boot/net/dns.c Tue May 18 10:23:50 1999
@@ -0,0 +1,145 @@
+/* "Complete" rewrite of the basic resolver function. */
+/**************************************************************************
+ - BOOTP/TFTP Bootstrap Program
+
+Author: Klaus Espenlaub
+ Date: May/99
+
+**************************************************************************/
+
+#include <oskit/c/arpa/inet.h> /* htonl */
+#include <oskit/c/string.h> /* memcpy */
+#include <oskit/c/stdio.h> /* putchar */
+#include <oskit/c/stdlib.h> /* getenv */
+#include <oskit/c/netinet/in.h> /* INADDR_NONE */
+
+#include "ip.h"
+#include "udp.h"
+#include "await.h"
+#include "ether.h"
+#include "driver.h"
+#include "netboot.h"
+
+#define MAX_DNS_RETRIES 15
+#define DNS_SSOCKET 52
+#define DNS_DSOCKET 53
+#define DNS_RECURSIVE 0x0100
+#define DNS_ATYPE 1
+#define DNS_IN 1
+#define DNS_SREPLYMASK 0xfa8f
+#define DNS_SREPLY 0x8080
+
+struct dns_t {
+ struct iphdr ip;
+ struct udphdr udp;
+
+ unsigned short id;
+ unsigned short qtype;
+ unsigned short qdcount, ancount, nscount, arcount;
+ char data[100];
+};
+
+/*
+ * Host lookup.
+ */
+unsigned long
+hostlookup(const char *host_or_ip)
+{
+ extern char domainname[];
+ int retries = MAX_DNS_RETRIES;
+ static unsigned short idcounter = 7325;
+ unsigned short qtype, qclass;
+ struct dns_t dns;
+ struct dns_t *reply;
+ char name[80];
+ const char *c;
+ char *data;
+ unsigned int ip;
+
+ if (strchr(host_or_ip, '.')) {
+ /* shortcut for dotted decimal notation */
+ for (c = host_or_ip;
+ (*c == '.') || ((*c >= '0') && (*c <= '9'));
+ c++) /* Nothing */;
+ if (*c == '\0') {
+ return ntohl(inet_addr(host_or_ip));
+ }
+ /* Have a name with '.' in it. Assume that it is a FQDN. */
+ strcpy(name, host_or_ip);
+ } else {
+ /* No '.' in the name. Use domainname if properly set. */
+ strcpy(name, host_or_ip);
+ if (strlen(domainname) == 0) {
+ return INADDR_NONE;
+ }
+ strcat(name, ".");
+ strcat(name, domainname);
+ }
+ if (arptable[ARP_NS].ipaddr == 0) {
+ return INADDR_NONE;
+ }
+ /* Now look up the IP for the machine called "name". */
+ dns.id = ntohs(idcounter);
+ idcounter++;
+ dns.qtype = htons(DNS_RECURSIVE);
+ dns.qdcount = htons(1);
+ dns.ancount = htons(0);
+ dns.nscount = htons(0);
+ dns.arcount = htons(0);
+ data = dns.data;
+ while (name[0] != '\0') {
+ c = strchr(name, '.');
+ if (c != NULL) {
+ *data++ = c-name;
+ memcpy(data, name, c-name);
+ data += c-name;
+ memmove(name, c+1, strlen(c+1)+1);
+ } else {
+ *data++ = strlen(name);
+ strcpy(data, name);
+ data += strlen(name);
+ name[0] = '\0';
+ }
+ }
+ *data++ = '\0';
+ qtype = htons(DNS_ATYPE);
+ memcpy(data, &qtype, 2);
+ data += 2;
+ qclass = htons(DNS_IN);
+ memcpy(data, &qclass, 2);
+ data += 2;
+ while (retries--) {
+ udp_transmit(arptable[ARP_NS].ipaddr, DNS_SSOCKET, DNS_DSOCKET,
+ data - (char *)&dns, &dns);
+ if (await_reply(AWAIT_DNS, DNS_SSOCKET, NULL)) {
+ reply = (struct dns_t *)&packet[ETHER_HDR_SIZE];
+ if ((ntohl(*(unsigned int *)reply->ip.src) != arptable[ARP_NS].ipaddr) ||
+ (ntohs(reply->id) != idcounter - 1) ||
+ (ntohs(reply->qdcount) != 1) ||
+ (ntohs(reply->ancount) != 1) ||
+ ((ntohs(reply->qtype) & DNS_SREPLYMASK) != DNS_SREPLY)) {
+ continue;
+ }
+ c = reply->data;
+ /* skip over "query" */
+ while (*c != '\0') {
+ c += 1 + *c;
+ }
+ c += 1 + 4;
+ /* now the answer is read */
+ /* skip over name */
+ while (*c != '\0') {
+ if (((*c) & 0xc0) == 0xc0) {
+ c += 2;
+ break;
+ } else {
+ c += 1 + *c;
+ }
+ }
+ c += 2 + 2 + 4 + 2;
+ memcpy(&ip, c, 4);
+ return ntohl(ip);
+ }
+ }
+ return INADDR_NONE;
+}
diff -rNup oskit-990402/boot/net/dns.h oskit-0.97/boot/net/dns.h
--- oskit-990402/boot/net/dns.h Thu Jan 1 01:00:00 1970
+++ oskit-0.97/boot/net/dns.h Mon May 17 15:12:36 1999
@@ -0,0 +1,16 @@
+/* Resolver function
+ */
+/**************************************************************************
+NETBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Klaus Espenlaub
+ Date: May/99
+
+**************************************************************************/
+
+#ifndef __DNS_H_INCLUDED__
+#define __DNS_H_INCLUDED__
+
+unsigned long hostlookup(const char *host_or_ip);
+
+#endif /* __DNS_H_INCLUDED__ */
diff -rNup oskit-990402/boot/net/do_boot.S oskit-0.97/boot/net/do_boot.S
--- oskit-990402/boot/net/do_boot.S Thu Apr 9 00:42:15 1998
+++ oskit-0.97/boot/net/do_boot.S Fri May 28 16:48:33 1999
@@ -20,6 +20,7 @@
*/
#include <oskit/machine/asm.h>
+#include <oskit/x86/multiboot.h>
.text
@@ -42,6 +43,10 @@ ENTRY(do_boot)
rep
movsb
- jmp *%eax
+ /* copy the entry point to %ecx and put multiboot magic into %eax */
+ movl %eax,%ecx
+ movl $MULTIBOOT_VALID,%eax
+
+ jmp *%ecx
ENTRY(do_boot_end)
diff -rNup oskit-990402/boot/net/dprintf.c oskit-0.97/boot/net/dprintf.c
--- oskit-990402/boot/net/dprintf.c Thu Apr 9 00:42:16 1998
+++ oskit-0.97/boot/net/dprintf.c Tue Jul 13 18:14:27 1999
@@ -25,7 +25,7 @@ void _doprnt(
register const char *fmt,
va_list args,
int radix, /* default radix - for '%r' */
- void (*putc)(), /* character output */
+ void (*putc)(), /* character output */
char *putc_arg); /* argument for putc */
static void
diff -rNup oskit-990402/boot/net/driver.c oskit-0.97/boot/net/driver.c
--- oskit-990402/boot/net/driver.c Wed Mar 31 00:47:13 1999
+++ oskit-0.97/boot/net/driver.c Tue Jul 13 17:51:57 1999
@@ -36,6 +36,7 @@
#include "timer.h"
#include "ether.h"
#include "netboot.h"
+#include "driver.h"
struct etherdev {
oskit_etherdev_t *dev;
@@ -48,6 +49,7 @@ struct etherdev {
unsigned long netmask; /* in host order */
char *hostname;
int hostnamelen; /* word aligned length of hostname */
+char domainname[MAXHOSTNAMELEN];
static struct etherdev ed;
static volatile oskit_queue_t *packq;
#define PACKQ_MAX 32
@@ -65,9 +67,9 @@ static oskit_error_t
net_receive(void *data, oskit_bufio_t *b, oskit_size_t pkt_size)
{
unsigned char bcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- unsigned char dhost[6];
+ unsigned char *frame;
+ struct ether_header *eth;
int err;
- oskit_size_t got;
struct etherdev *dev = (struct etherdev *)data;
unsigned flags;
@@ -79,19 +81,59 @@ net_receive(void *data, oskit_bufio_t *b
/*
* Check the Ethernet header to see if it is addressed to us.
*/
- err = oskit_bufio_read(b, dhost,
- offsetof(struct ether_header, ether_dhost),
- sizeof dhost,
- &got);
+ err = oskit_bufio_map(b, (void **)&frame, 0, pkt_size);
assert(err == 0);
- assert(got == sizeof dhost);
- if (memcmp(dhost, &dev->haddr, sizeof dev->haddr) != 0
- && memcmp(dhost, bcastaddr, sizeof bcastaddr) != 0)
+
+ eth = (struct ether_header *)frame;
+
+ if (memcmp(eth->ether_dhost, &dev->haddr, sizeof dev->haddr) != 0
+ && memcmp(eth->ether_dhost, bcastaddr, sizeof bcastaddr) != 0)
return 0; /* not for us */
+ /* First check for ARP request for our IP */
+ if (ntohs(eth->ether_type) == ETHERTYPE_ARP) {
+ oskit_bufio_t *our_buf;
+ struct arprequest *arp;
+ struct in_addr ip;
+
+ arp = (struct arprequest *)(frame + sizeof(struct ether_header));
+ ip.s_addr = *(unsigned long *)arp->tipaddr;
+ if ((ntohs(arp->hwtype) != ARPHRD_ETHER) ||
+ (ntohs(arp->protocol) != ETHERTYPE_IP) ||
+ (ntohs(arp->opcode) != ARPOP_REQUEST) ||
+ (ntohl(ip.s_addr) != arptable[ARP_CLIENT].ipaddr))
+ goto enqueue; /* not for us - put it into the queue */
+
+ /* Send the reply. */
+ arp->opcode = htons(ARPOP_REPLY);
+ memcpy(arp->tipaddr, arp->sipaddr, sizeof(arp->tipaddr));
+ memcpy(arp->thwaddr, arp->shwaddr, sizeof(arp->thwaddr));
+ memcpy(arp->sipaddr, &(ip.s_addr), sizeof(arp->sipaddr));
+ memcpy(arp->shwaddr, dev->haddr, sizeof(arp->shwaddr));
+
+ /* Fill in the ethernet addresses. */
+ memcpy(eth->ether_dhost, arp->thwaddr, sizeof(arp->shwaddr));
+ memcpy(eth->ether_shost, dev->haddr, sizeof(arp->shwaddr));
+
+ our_buf = oskit_bufio_create(ETHER_HDR_SIZE + sizeof(struct arprequest));
+ if (b != NULL) {
+ oskit_size_t got;
+
+ oskit_bufio_write(our_buf, frame, 0, pkt_size, &got);
+ assert(got == ETHER_HDR_SIZE + sizeof(struct arprequest));
+ oskit_netio_push(dev->send_nio, our_buf,
+ ETHER_HDR_SIZE + sizeof(struct arprequest));
+ oskit_bufio_release(our_buf);
+ } else {
+ printf("couldn't allocate bufio for ARP reply\n");
+ }
+ return 0;
+ }
+
/*
* Try to add it to the queue.
*/
+enqueue:
flags = get_eflags();
cli();
oskit_queue_enqueue(packq, b, 0);
@@ -201,12 +243,16 @@ net_init()
{
#define BUFSIZE 128
static char buf[BUFSIZE];
+ char ipcfgstr[BUFSIZE];
struct bootp_net_info bpi;
oskit_error_t err;
oskit_etherdev_t **alldevs;
int ndev;
int i;
unsigned required_flags;
+ char *dnsaddrs, *nfsaddrs, *ip, *cp, *dot;
+ int num;
+ struct in_addr ic_ns, ic_myaddr, ic_servaddr, ic_netmask, ic_gwaddr;
/* The cast is needed to make it non-volatile. */
/**/ err = oskit_bounded_com_queue_create(PACKQ_MAX, (oskit_queue_t **)&packq);
@@ -221,6 +267,115 @@ net_init()
ndev = osenv_device_lookup(&oskit_etherdev_iid, (void ***)&alldevs);
if (ndev <= 0)
panic("no Ethernet adaptors found!");
+
+ /*
+ * XXX This code currently only handles autoconfiguration of the first
+ * dev from what the bootloader passes to us. On systems with multiple
+ * interfaces this has to be turned off explicitly, unless the first
+ * interface in the autodetect order is what you want. Could be fixed
+ * by using field 5 of the nfsaddrs variable (if existent).
+ */
+ dnsaddrs = getenv("dnsaddrs");
+ if (dnsaddrs != NULL) {
+ strcpy(ipcfgstr, dnsaddrs);
+ cp = strchr(ipcfgstr, ':');
+ if (cp) *cp = '\0';
+ if (inet_aton(ipcfgstr, &ic_ns) == 0) {
+ ic_ns.s_addr = INADDR_NONE;
+ }
+ arptable[ARP_NS].ipaddr = ntohl(ic_ns.s_addr);
+ }
+ nfsaddrs = getenv("nfsaddrs");
+ if ((nfsaddrs != NULL) && (strchr(nfsaddrs, ':') == NULL)) {
+ /* Either "off" or a protocol specification */
+ nfsaddrs = NULL;
+ }
+ if (nfsaddrs != NULL) {
+ /* Parse the whole string */
+ strcpy(ipcfgstr, nfsaddrs); /* don't clobber environment */
+ ip = ipcfgstr;
+ num = 0;
+ while (ip && *ip) {
+ if ((cp = strchr(ip, ':')))
+ *cp++ = '\0';
+ if (strlen(ip) > 0) {
+ switch (num) {
+ case 0:
+ if (inet_aton(ip, &ic_myaddr) == 0)
+ ic_myaddr.s_addr = INADDR_NONE;
+ break;
+ case 1:
+ if (inet_aton(ip, &ic_servaddr) == 0)
+ ic_servaddr.s_addr = INADDR_NONE;
+ break;
+ case 2:
+ if (inet_aton(ip, &ic_gwaddr) == 0)
+ ic_gwaddr.s_addr = INADDR_NONE;
+ break;
+ case 3:
+ if (inet_aton(ip, &ic_netmask) == 0)
+ ic_netmask.s_addr = INADDR_NONE;
+ break;
+ case 4:
+ /* hostnamelen must be word aligned. */
+ if ((dot = strchr(ip, '.'))) {
+ *dot++ = '\0';
+ strcpy(domainname, dot);
+ }
+ hostname = (char *)mustcalloc(strlen(ip) + 3, 1);
+ strcpy(hostname, ip);
+ hostnamelen = (strlen(hostname) + 3) & ~3;
+ break;
+ case 5:
+ /* device name - not implemented */
+ break;
+ case 6:
+ /* protocol to use for getting remaining info */
+ /* XXXX not implemented yet */
+ break;
+ }
+ }
+ ip = cp;
+ num++;
+ }
+ ed.dev = alldevs[0];
+ if ((ic_myaddr.s_addr != INADDR_NONE) &&
+ (ic_servaddr.s_addr != INADDR_NONE) &&
+ (ic_netmask.s_addr != INADDR_NONE) &&
+ (ic_gwaddr.s_addr != INADDR_NONE) &&
+ (ed.dev != NULL)) {
+ ic_myaddr.s_addr = ntohl(ic_myaddr.s_addr);
+ memcpy(&arptable[ARP_CLIENT].ipaddr, &ic_myaddr.s_addr,
+ sizeof ic_myaddr.s_addr);
+ ic_netmask.s_addr = ntohl(ic_netmask.s_addr);
+ memcpy(&netmask, &ic_netmask.s_addr,
+ sizeof ic_netmask.s_addr);
+ ic_gwaddr.s_addr = ntohl(ic_gwaddr.s_addr);
+ memcpy(&arptable[ARP_GATEWAY].ipaddr, &ic_gwaddr.s_addr,
+ sizeof ic_gwaddr.s_addr);
+ /*
+ * Fill in `ed' with info about this dev.
+ */
+/**/ ed.recv_nio = oskit_netio_create(net_receive, &ed);
+ if (ed.recv_nio == NULL)
+ panic("unable to create recv_nio\n");
+ oskit_etherdev_getaddr(ed.dev, ed.haddr);
+ memcpy(arptable[ARP_CLIENT].node, ed.haddr, sizeof(ed.haddr));
+ err = oskit_etherdev_getinfo(ed.dev, &ed.info);
+ if (err)
+ panic("Error(0x%08x) getting info from first autodetected ethercard", err);
+
+ /*
+ * Open it.
+ */
+/**/ err = oskit_etherdev_open(ed.dev, 0, ed.recv_nio, &ed.send_nio);
+ if (err)
+ panic("Error(0x%08x) opening first autodetected ethercard", err);
+
+ return 0;
+ }
+ printf("IP config by kernel env failed - reverting to bootp\n");
+ }
/*
* Try bootp on each dev and use the first one that succeeds.
diff -rNup oskit-990402/boot/net/driver.h oskit-0.97/boot/net/driver.h
--- oskit-990402/boot/net/driver.h Tue Oct 13 08:31:05 1998
+++ oskit-0.97/boot/net/driver.h Fri May 14 15:14:34 1999
@@ -20,8 +20,11 @@
#include <oskit/error.h>
+#define MAXHOSTNAMELEN 80
+
extern char eth_driver[];
extern char packet[];
+extern char domainname[MAXHOSTNAMELEN];
extern oskit_size_t packetlen;
extern unsigned long netmask; /* in host order */
extern char *hostname;
diff -rNup oskit-990402/boot/net/ether.h oskit-0.97/boot/net/ether.h
--- oskit-990402/boot/net/ether.h Thu Apr 9 00:42:17 1998
+++ oskit-0.97/boot/net/ether.h Tue May 18 16:54:42 1999
@@ -53,6 +53,8 @@ struct arprequest {
char tipaddr[4];
};
+#define ARPHRD_ETHER 1
+
#define ARPOP_REQUEST 1
#define ARPOP_REPLY 2
diff -rNup oskit-990402/boot/net/getkernel_net.c oskit-0.97/boot/net/getkernel_net.c
--- oskit-990402/boot/net/getkernel_net.c Wed Mar 31 00:48:41 1999
+++ oskit-0.97/boot/net/getkernel_net.c Thu May 20 15:19:37 1999
@@ -52,6 +52,7 @@ kimg_read(void *handle_notused,
char *bufp = buf;
int chunk_size;
int readahead;
+
#if 0
printf("kimg_read: file_ofs %x, size %x\n", file_ofs, size);
#endif
@@ -86,9 +87,8 @@ kimg_read(void *handle_notused,
* Copies data from the NFS file into ki->ki_imgaddr.
*/
static int
-kimg_load(void *handle,
- oskit_addr_t file_ofs, oskit_size_t file_size,
- oskit_addr_t mem_addr, oskit_size_t mem_size,
+kimg_load(void *handle, oskit_addr_t file_ofs, oskit_size_t file_size,
+ oskit_addr_t load_addr, oskit_addr_t mem_addr, oskit_size_t mem_size,
exec_sectype_t section_type)
{
struct kerninfo *ki = handle;
@@ -97,7 +97,7 @@ kimg_load(void *handle,
#if 0
printf("** load: file_ofs %x, file_size %x\n", file_ofs, file_size);
- printf("-- load: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
+ printf("-- load: phys_mem_addr %x, mem_size %x\n", load_addr, mem_size);
printf("-- load: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
#endif
@@ -105,7 +105,7 @@ kimg_load(void *handle,
return 0;
if ((err = kimg_read(ki, file_ofs,
- ki->ki_imgaddr + mem_addr - ki->ki_mbhdr.load_addr,
+ ki->ki_imgaddr + load_addr - ki->ki_mbhdr.load_addr,
file_size, &got)) != 0)
return err;
if (got != file_size)
@@ -118,16 +118,15 @@ kimg_load(void *handle,
* Callback for the exec library that just tallys up the sizes.
*/
static int
-kimg_tally(void *handle,
- oskit_addr_t file_ofs, oskit_size_t file_size,
- oskit_addr_t mem_addr, oskit_size_t mem_size,
+kimg_tally(void *handle, oskit_addr_t file_ofs, oskit_size_t file_size,
+ oskit_addr_t load_addr, oskit_addr_t mem_addr, oskit_size_t mem_size,
exec_sectype_t section_type)
{
struct multiboot_header *h = handle;
#if 0
printf("** tally: file_ofs %x, file_size %x\n", file_ofs, file_size);
- printf("-- tally: mem_addr %x, mem_size %x\n", mem_addr, mem_size);
+ printf("-- tally: phys_mem_addr %x, mem_size %x\n", load_addr, mem_size);
printf("-- tally: sectype = %b\n", section_type, EXEC_SECTYPE_FORMAT);
#endif
@@ -135,12 +134,12 @@ kimg_tally(void *handle,
return 0;
assert(mem_size > 0);
- if (mem_addr < h->load_addr)
- h->load_addr = mem_addr;
- if (mem_addr+file_size > h->load_end_addr)
- h->load_end_addr = mem_addr+file_size;
- if (mem_addr+mem_size > h->bss_end_addr)
- h->bss_end_addr = mem_addr+mem_size;
+ if (load_addr < h->load_addr)
+ h->load_addr = load_addr;
+ if (load_addr+file_size > h->load_end_addr)
+ h->load_end_addr = load_addr+file_size;
+ if (load_addr+mem_size > h->bss_end_addr)
+ h->bss_end_addr = load_addr+mem_size;
return 0;
}
@@ -284,19 +283,25 @@ getkernel_net(struct kerninfo *ki /* IN/
/*
* Do a bunch of checks on the kernel load ranges.
*/
- assert(ki->ki_mbhdr.load_addr < ki->ki_mbhdr.load_end_addr);
- assert(ki->ki_mbhdr.load_end_addr < ki->ki_mbhdr.bss_end_addr);
printf("Kernel will be at %08x-%08x text+data %d bss %d\n",
ki->ki_mbhdr.load_addr, ki->ki_mbhdr.bss_end_addr,
ki->ki_mbhdr.load_end_addr - ki->ki_mbhdr.load_addr,
ki->ki_mbhdr.bss_end_addr - ki->ki_mbhdr.load_end_addr);
- if (ki->ki_mbhdr.load_addr < 0x1000)
- panic("kernel wants to be loaded too low!");
- if (ki->ki_mbhdr.bss_end_addr > phys_mem_max)
- panic("kernel wants to be loaded beyond available physical memory!");
+ assert(ki->ki_mbhdr.load_addr < ki->ki_mbhdr.load_end_addr);
+ assert(ki->ki_mbhdr.load_end_addr < ki->ki_mbhdr.bss_end_addr);
+ if (ki->ki_mbhdr.load_addr < 0x1000) {
+ printf("kernel wants to be loaded too low!\n");
+ return 1;
+ }
+ if (ki->ki_mbhdr.bss_end_addr > phys_mem_max) {
+ printf("kernel wants to be loaded beyond available physical memory!\n");
+ return 1;
+ }
if ((ki->ki_mbhdr.load_addr < 0x100000)
- && (ki->ki_mbhdr.bss_end_addr > 0xa0000))
- panic("kernel wants to be loaded on top of I/O space!");
+ && (ki->ki_mbhdr.bss_end_addr > 0xa0000)) {
+ printf("kernel wants to be loaded on top of I/O space!\n");
+ return 1;
+ }
/*
* Now, read the whole thing in somewhere.
diff -rNup oskit-990402/boot/net/loadkernel.c oskit-0.97/boot/net/loadkernel.c
--- oskit-990402/boot/net/loadkernel.c Thu Apr 1 23:22:27 1999
+++ oskit-0.97/boot/net/loadkernel.c Wed May 26 17:49:25 1999
@@ -95,6 +95,7 @@ loadkernel(struct kerninfo *ki)
entry = ki->ki_mbhdr.entry;
load_addr = ki->ki_mbhdr.load_addr;
+ dprintf("entry = %p, phys entry = %p\n", entry, kvtophys(entry));
dprintf("ki->ki_mbinfo = %p-%p\n",
kvtophys(ki->ki_mbinfo),
kvtophys(ki->ki_mbinfo) + sizeof(ki->ki_mbinfo));
diff -rNup oskit-990402/boot/net/main.c oskit-0.97/boot/net/main.c
--- oskit-990402/boot/net/main.c Thu Mar 18 22:49:28 1999
+++ oskit-0.97/boot/net/main.c Tue Jul 13 17:53:52 1999
@@ -52,15 +52,28 @@ extern char version[], build_info[];
static void
init_default_args(int bootargc, char *bootargv[], char *default_args[])
{
+ extern char **environ;
+ char **e;
char **p;
int i;
p = &default_args[0];
for (i = 0; i < bootargc; i++)
-#define NDEFAULT_ARGS 2
+#define NDEFAULT_ARGS 10
if (strcmp(bootargv[i], "-h") == 0 ||
strcmp(bootargv[i], "-f") == 0)
*p++ = bootargv[i];
+
+ /* boottype is omitted from the list of environment paramters to
+ pass, because a netboot boot is never automatic. */
+ for (e = environ; *e != NULL; e++) {
+ if ((strncmp(*e, "bogomips=", 9) == 0) ||
+ (strncmp(*e, "dnsaddrs=", 9) == 0) ||
+ (strncmp(*e, "nfsroot=", 8) == 0) ||
+ (strncmp(*e, "nfsaddrs=", 9) == 0)) {
+ *p++ = *e;
+ }
+ }
*p = NULL;
}
@@ -166,15 +179,14 @@ build_cmdline(char *progname, char *defa
return cmdline;
}
-void
+int
main(int argc, char *argv[])
{
- char buf[512];
+ char input[512];
oskit_error_t err;
int done = 0;
struct kerninfo kinfo;
struct multiboot_info *mbi;
- char *input = buf;
char *cmdline = NULL;
int i;
char *default_args[NDEFAULT_ARGS+1] = {0};
@@ -204,7 +216,7 @@ reprompt:
getline(input, 512);
input[strlen(input) - 1] = '\0'; /* chop \n */
while (input[0] && isspace(input[0]))
- input++;
+ memmove(input, input+1, sizeof(input)-1);
if (strcmp(input, "help") == 0) {
printf("\n");
printf("%s\n", version);
@@ -217,8 +229,7 @@ reprompt:
"or\n"
"\tmyhost:/home/foo/kernel -x -y file1 file2\n"
"The directory must be an NFS exported directory.\n"
- "The kernel must be a MultiBoot kernel.\n"
- "Hostnames are currently limited to \"marker\" and \"fast\".\n");
+ "The kernel must be a MultiBoot kernel.\n");
printf("\n");
printf("Type \"quit\" or \"exit\" to %s.\n",
return_address? "return to caller" : "reboot");
@@ -239,7 +250,7 @@ reprompt:
}
if (input[0] == '\0')
goto reprompt;
- if (! parse_cmdline(input,
+ if (! parse_cmdline(input, sizeof(input),
&kinfo.ki_ip.s_addr,
&kinfo.ki_dirname,
&kinfo.ki_filename,
@@ -307,4 +318,5 @@ reprompt:
/* Load it. */
loadkernel(&kinfo);
panic("loadkernel returned");
+ return 0;
}
diff -rNup oskit-990402/boot/net/misc.c oskit-0.97/boot/net/misc.c
--- oskit-990402/boot/net/misc.c Wed Dec 23 13:58:22 1998
+++ oskit-0.97/boot/net/misc.c Mon May 17 15:10:19 1999
@@ -28,8 +28,10 @@ Author: Martin Renters
#include <oskit/c/strings.h> /* strsep */
#include <oskit/c/stdarg.h> /* va_list */
#include <oskit/c/stdio.h> /* putchar */
+#include <oskit/c/stdlib.h> /* getenv */
#include <oskit/c/netinet/in.h> /* INADDR_NONE */
+#include "dns.h"
#include "netboot.h"
/*
@@ -186,39 +188,51 @@ netprintf(char *fmt, ...)
}
/*
- * Host lookup kludge since it is hard to use the oskit's gethostbyname
- * since we don't use the BSD socket stuff.
- * If you fix this, fix the helpstring in main.c too.
- */
-static unsigned long
-hostlookup(char *host_or_ip)
-{
- /* These are padded with NULs so the binary can be patched... */
- if (!strcmp(host_or_ip, "marker") || !strcmp(host_or_ip, "marker.cs"))
- host_or_ip = "155.99.212.61\0\0";
- else if (!strcmp(host_or_ip, "fast") || !strcmp(host_or_ip, "fast.cs"))
- host_or_ip = "155.99.212.1\0\0\0";
- else if (!strcmp(host_or_ip, "golden"))
- host_or_ip = "198.252.55.133\0";
- return ntohl(inet_addr(host_or_ip));
-}
-
-/*
* Take the command line and set the IP, dir, and name components.
* The cmdline is modified and things point into it.
* The cmdline looks like "ip:/dir/file -foo bar", eg "155.99.212.1:/tmp/foo -l"
*/
int
-parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name,
- char **rest)
+parse_cmdline(char *cmdline, int cmdsize, unsigned int *ip, char **dir,
+ char **name, char **rest)
{
- char *p = cmdline;
+ char *p, *op;
char *host_or_ip;
+ char *nfsroot, *nfsaddrs;
+ char *myipstr, *srvipstr;
+ char ipcfg[512], *q;
+ char effroot[512];
+ char cmdprefix[512];
+ int len;
p = strsep(&cmdline, " \t");
*rest = cmdline; /* ok if NULL */
+ nfsroot = getenv("nfsroot");
+ nfsaddrs = getenv("nfsaddrs");
+ op = p;
host_or_ip = strsep(&p, ":");
+ if (!p && nfsroot && nfsaddrs) {
+ strcpy(ipcfg, nfsaddrs); /* don't clobber environment */
+ q = ipcfg;
+ myipstr = q;
+ q = strchr(q, ':');
+ *q++ = '\0';
+ srvipstr = q;
+ q = strchr(q, ':');
+ *q++ = '\0';
+ sprintf(effroot, nfsroot, myipstr);
+ sprintf(cmdprefix, "%s:%s/", srvipstr, effroot);
+ len = strlen(cmdprefix);
+ memmove(op + len, op, cmdsize - len);
+ op[cmdsize-1] = '\0';
+ memmove(op, cmdprefix, len);
+ if (*rest != NULL)
+ *rest += len;
+
+ p = op;
+ host_or_ip = strsep(&p, ":");
+ }
if (! p)
return 0;
diff -rNup oskit-990402/boot/net/netboot.h oskit-0.97/boot/net/netboot.h
--- oskit-990402/boot/net/netboot.h Tue Apr 7 03:27:58 1998
+++ oskit-0.97/boot/net/netboot.h Tue May 11 09:40:39 1999
@@ -36,5 +36,5 @@ Author: Martin Renters
void convert_ipaddr(void *d, void *s);
char *netsprintf(char *buf, char *fmt, ...);
void netprintf(char *fmt, ...);
-int parse_cmdline(char *cmdline, unsigned int *ip, char **dir, char **name,
+int parse_cmdline(char *cmdline, int cmdsize, unsigned int *ip, char **dir, char **name,
char **rest);
diff -rNup oskit-990402/boot/net/rpc.c oskit-0.97/boot/net/rpc.c
--- oskit-990402/boot/net/rpc.c Sun Feb 28 17:43:41 1999
+++ oskit-0.97/boot/net/rpc.c Fri May 14 09:55:25 1999
@@ -35,6 +35,7 @@ void
rpc_init()
{
int i;
+
rpc_id = currticks();
for (i = 0; i < BUFMAX; i++) {
read_cache[i].valid = 0;
@@ -179,9 +180,9 @@ nfs_read(int server, int port, char *fh,
char *rpcptr;
int retries = MAX_RPC_RETRIES;
int rlen;
- int i, curoff, pktcount = 0;
- int saved_rpc_id;
- int rid;
+ int i, curoff, pktcount = 0;
+ int saved_rpc_id;
+ int rid;
struct rpc_buf *cache;
rlen = check_read_cache(offset, len, buffer);
@@ -210,10 +211,10 @@ nfs_read(int server, int port, char *fh,
cache->id = rpc_id;
rpcptr = netsprintf(buf.u.data,
- "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
+ "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
rpc_id, MSG_CALL, 2, PROG_NFS, 2, NFS_READ,
- 1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
- 32, fh, curoff, len, 0);
+ 1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
+ 32, fh, curoff, len, 0);
curoff += len;
readahead--;
pktcount++;
@@ -269,10 +270,10 @@ nfs_read(int server, int port, char *fh,
while(retries--) {
rpcptr = netsprintf(buf.u.data,
- "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
+ "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
rpc_id, MSG_CALL, 2, PROG_NFS, 2, NFS_READ,
- 1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
- 32, fh, offset, len, 0);
+ 1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
+ 32, fh, offset, len, 0);
udp_transmit(arptable[server].ipaddr, RPC_SOCKET,
port, rpcptr - (char *)&buf, &buf);
if (await_reply(AWAIT_RPC, rpc_id, NULL)) {
diff -rNup oskit-990402/boot/net/rpc.h oskit-0.97/boot/net/rpc.h
--- oskit-990402/boot/net/rpc.h Thu Feb 18 19:11:09 1999
+++ oskit-0.97/boot/net/rpc.h Fri May 14 09:58:25 1999
@@ -33,7 +33,7 @@ struct rpc_t {
struct rpc_buf {
int valid;
- int sent; /* Is the request on the wire? */
+ int sent; /* Is the request on the wire? */
unsigned long offset;
unsigned long len;
unsigned long id;
diff -rNup oskit-990402/boot/net/udp.c oskit-0.97/boot/net/udp.c
--- oskit-990402/boot/net/udp.c Tue Apr 7 03:27:59 1998
+++ oskit-0.97/boot/net/udp.c Mon May 17 13:29:47 1999
@@ -24,6 +24,7 @@ udp_transmit(unsigned long destip,
unsigned short srcsock, unsigned short destsock,
int len, void *bufv)
{
+ static unsigned short id_count = 0;
char *buf = bufv;
struct iphdr *ip;
struct udphdr *udp;
@@ -36,7 +37,8 @@ udp_transmit(unsigned long destip,
ip->verhdrlen = 0x45;
ip->service = 0;
ip->len = htons(len);
- ip->ident = 0;
+ ip->ident = htons(id_count);
+ id_count++;
ip->frags = 0;
ip->ttl = 60;
ip->protocol = IP_UDP;
Follow-Ups:
References: