[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
OpenBSD+GRUB+PXE patches
From: |
Cedric Berger |
Subject: |
OpenBSD+GRUB+PXE patches |
Date: |
Wed, 14 Mar 2001 14:36:20 -0800 |
To fulfill my GPL obligations and to the benefit of OpenBSD/GRUB hackers,
Here is a set of patch to boot a diskless OpenBSD using GRUB and a PXE
compatible Ethernet Card (tested with Intel EtherExpress 10/100 pro). The
GRUB patch is *not* a general purpose fix for booting OpenBSD with GRUB.
The GRUP patch is made of two files: a diff from the 0.5.95 cvs version and a
new openbsd.c file that must be put inside the stage2 directory.
With this patch, GRUB will try to load the kernel from one of the following
files
on the server default tftp directory "bsd", "obsd", "bsd.old".
The OpenBSD patch is optional. Its purpose is to pass some additional
information from GRUB to the OpenBSD kernel, in order to:
1) remove the RARP step, which is a pain to setup on the server, and which
is redundant since PXE/GRUB use DHCP anyway
2) support multi-homed hosts
3) better support for subnetting
Notes:
1) GRUB *requires* a recent Redhat Linux to compile. OpenBSD 2.8,
FreeBSD 4.2 will refuse to compile it.
2) use "--enable-diskless --enable-eepro100" to configure GRUB.
2) I've been unable to compile with the latest GRUB 0.5.96.1, but "porting"
the patch is straitforward.
3) I'm *not* on the bug-grub mailing list.
Cedric
Index: netboot/main.c
===================================================================
RCS file: /cvsroot/grub/grub/netboot/main.c,v
retrieving revision 1.10
diff -u -r1.10 main.c
--- netboot/main.c 2000/06/07 15:35:18 1.10
+++ netboot/main.c 2001/03/14 22:07:36
@@ -52,7 +52,8 @@
struct rom_info rom;
static int vendorext_isvalid;
-static unsigned long netmask;
+unsigned long netmask = 0;
+unsigned long mybcast = 0;
static struct bootpd_t bootp_data;
static unsigned long xid;
static unsigned char *end_of_rfc1533 = NULL;
@@ -164,15 +165,16 @@
grub_printf ("Not initialized yet.\n");
else
{
- char me[16], my_mask[16], server[16], gw[16];
+ char me[16], my_mask[16], my_bcast[16], server[16], gw[16];
sprint_ip_addr (me, arptable[ARP_CLIENT].ipaddr.s_addr);
sprint_ip_addr (my_mask, netmask);
+ sprint_ip_addr (my_bcast, mybcast);
sprint_ip_addr (server, arptable[ARP_SERVER].ipaddr.s_addr);
sprint_ip_addr (gw, arptable[ARP_GATEWAY].ipaddr.s_addr);
- grub_printf ("Address: %s Netmask: %s\nServer: %s Gateway: %s\n",
- me, my_mask, server, gw);
+ grub_printf ("Address: %s Netmask: %s Broadcast: %s"
+ "\nServer: %s Gateway: %s\n", me, my_mask, my_bcast, server,
gw);
}
}
@@ -321,6 +323,10 @@
struct tftp_t tp;
int rc;
int packetsize = TFTP_DEFAULTSIZE_PACKET;
+
+ /* don't send absolute TFTP requeses */
+ if(*name == '/')
+ name++;
/* Clear out the Rx queue first. It contains nothing of interest,
* except possibly ARP requests from the DHCP/TFTP server. We use
@@ -935,6 +941,10 @@
{
end_of_rfc1533 = endp = p;
continue;
+ }
+ else if (c == RFC1533_INTBROADCAST)
+ {
+ grub_memmove ((char *) &mybcast, p + 2, sizeof (in_addr));
}
else if (c == RFC1533_NETMASK)
{
Index: stage2/boot.c
===================================================================
RCS file: /cvsroot/grub/grub/stage2/boot.c,v
retrieving revision 1.21
diff -u -r1.21 boot.c
--- stage2/boot.c 2000/05/04 22:15:20 1.21
+++ stage2/boot.c 2001/03/14 22:07:38
@@ -609,6 +609,11 @@
*/
+#if SUPPORT_DISKLESS // replace this code by OpenBSD hack
+#define obsd_diskless_boot bsd_boot
+#include "openbsd.c"
+#else
+
void
bsd_boot (kernel_t type, int bootdev, char *arg)
{
@@ -748,3 +753,4 @@
extended_memory, mbi.mem_lower);
}
}
+#endif
Index: stage2/common.c
===================================================================
RCS file: /cvsroot/grub/grub/stage2/common.c,v
retrieving revision 1.12
diff -u -r1.12 common.c
--- stage2/common.c 2000/05/29 16:11:08 1.12
+++ stage2/common.c 2001/03/14 22:07:38
@@ -273,6 +273,11 @@
saved_drive = boot_drive;
saved_partition = install_partition;
+#ifdef SUPPORT_DISKLESS
+ //@@@ Direct OpenBSD start if possible
+ obsd_main();
+#endif
+
/* Start main routine here. */
cmain ();
}
openbsd.c
Description: application/unknown-content-type-c_file
Index: sys/arch/i386/i386/bios.c
===================================================================
RCS file: /export/CVSroot/openbsd/sys/arch/i386/i386/bios.c,v
retrieving revision 1.42
diff -u -r1.42 bios.c
--- bios.c 2001/02/28 19:16:06 1.42
+++ bios.c 2001/03/14 22:25:41
@@ -65,6 +65,7 @@
#include "apm.h"
#include "pcibios.h"
#include "pci.h"
+#include "ether.h"
struct bios_softc {
struct device sc_dev;
@@ -95,6 +96,12 @@
u_int32_t bios_cksumlen;
struct bios32_entry bios32_entry;
+#if defined(NFSCLIENT) && (NETHER > 0 || NFDDI > 0)
+bios_ip4info_t *bios_ip4info;
+u_int32_t bios_ip4info_nvec;
+bios_linkaddr_t *bios_linkaddr;
+#endif // NFSCLIENT
+
bios_diskinfo_t *bios_getdiskinfo __P((dev_t));
int
@@ -338,6 +345,47 @@
cnset(cdp->consdev);
}
break;
+
+#if defined(NFSCLIENT) && (NETHER > 0 || NFDDI > 0)
+ case BOOTARG_IP4INFO:
+ bios_ip4info = (bios_ip4info_t*)q->ba_arg;
+ bios_ip4info_nvec = (q->ba_size - sizeof(bootarg_t) +
+ sizeof(q->ba_arg)) / sizeof(u_int32_t);
+#ifdef BIOS_DEBUG
+ if(bios_ip4info_nvec >= 1 && bios_ip4info->ip4_myaddr)
+ printf(" myip4addr %08X", bios_ip4info->ip4_myaddr);
+ if(bios_ip4info_nvec >= 2 && bios_ip4info->ip4_mymask)
+ printf(" myip4mask %08X", bios_ip4info->ip4_mymask);
+ if(bios_ip4info_nvec >= 3 && bios_ip4info->ip4_mybcast)
+ printf(" myip4bcast %08X", bios_ip4info->ip4_mybcast);
+#endif
+ break;
+ case BOOTARG_LINKADDR:
+ if (q->ba_size >= sizeof(bios_linkaddr_t))
+ {
+#ifdef BIOS_DEBUG
+ int i;
+#endif
+ bios_linkaddr = (bios_linkaddr_t*)q->ba_arg;
+#ifdef BIOS_DEBUG
+ printf(" linkaddr");
+#endif
+ if (bios_linkaddr->la_alen > q->ba_size - 2) {
+#ifdef BIOS_DEBUG
+ printf(" INVALID");
+#endif
+ bios_linkaddr = NULL;
+ break;
+ }
+#ifdef BIOS_DEBUG
+ printf(" %d", bios_linkaddr->la_alen);
+ for (i = 0; i < bios_linkaddr->la_alen; i++)
+
printf("%c%02X",(i?':':'/'),bios_linkaddr->la_addr[i]);
+#endif
+ }
+ break;
+#endif //NFSCLIENT
+
default:
#ifdef BIOS_DEBUG
Index: sys/arch/i386/include/biosvar.h
===================================================================
RCS file: /export/CVSroot/openbsd/sys/arch/i386/include/biosvar.h,v
retrieving revision 1.38
diff -u -r1.38 biosvar.h
--- biosvar.h 2001/02/28 16:45:25 1.38
+++ biosvar.h 2001/03/14 22:25:41
@@ -197,6 +197,43 @@
int conspeed;
} bios_consdev_t;
+/*
+ * our IP address as discovered by the bootstrap NIC
+ */
+#define BOOTARG_IP4INFO 6
+typedef struct _bios_ip4info {
+ u_int32_t ip4_myaddr; /* if != 0, my IP address, as used by boot */
+ u_int32_t ip4_mymask; /* if != 0, my IP netmask, as used by boot */
+ u_int32_t ip4_mybcast; /* if != 0, my IP broadcast address */
+} bios_ip4info_t;
+extern bios_ip4info_t *bios_ip4info;
+extern u_int32_t bios_ip4info_nvec;
+
+/*
+ * this macro is called by the NFS diskless code in nfs/nfs_boot.c
+ */
+#define BOOT_GETIP4INFO(addr, mask, bcast) do { \
+ (addr) = (bios_ip4info && bios_ip4info_nvec >=1) ? \
+ bios_ip4info->ip4_myaddr : 0; \
+ (mask) = (bios_ip4info && bios_ip4info_nvec >=2) ? \
+ bios_ip4info->ip4_mymask : 0; \
+ (bcast) = (bios_ip4info && bios_ip4info_nvec >=3) ? \
+ bios_ip4info->ip4_mybcast : 0; \
+} while(0)
+
+/*
+ * the link address of the bootstrap NIC
+ */
+#define BOOTARG_LINKADDR 7
+typedef struct _bios_linkaddr {
+ u_int8_t la_type;
+ u_int8_t la_alen;
+ u_int8_t la_addr[6];
+} bios_linkaddr_t;
+extern bios_linkaddr_t *bios_linkaddr;
+#define BOOT_LINKADDR bios_linkaddr
+
+
#if defined(_KERNEL) || defined (_STANDALONE)
#ifdef _LOCORE
Index: sys/nfs/nfs_boot.c
===================================================================
RCS file: /export/CVSroot/openbsd/sys/nfs/nfs_boot.c,v
retrieving revision 1.11
diff -u -r1.11 nfs_boot.c
--- nfs_boot.c 1999/01/03 10:07:19 1.11
+++ nfs_boot.c 2001/03/14 22:25:46
@@ -41,6 +41,7 @@
#include <sys/socketvar.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -56,6 +57,11 @@
#include "ether.h"
+#ifdef i386
+#include <machine/biosvar.h>
+#endif
+
+
#if !defined(NFSCLIENT) || (NETHER == 0 && NFDDI == 0)
int
@@ -86,7 +92,7 @@
* so we might as well take advantage of it for bootparam too.
*
* The diskless boot sequence goes as follows:
- * (1) Use RARP to get our interface address
+ * (1) Get BOOT parameters or Use RARP to get our interface address
* (2) Use RPC/bootparam/whoami to get our hostname,
* our IP address, and the server's IP address.
* (3) Use RPC/bootparam/getfile to get the root path
@@ -119,6 +125,7 @@
{
struct ifreq ireq;
struct in_addr my_ip, gw_ip;
+ struct in_addr my_mask, my_bcast;
struct sockaddr_in bp_sin;
struct sockaddr_in *sin;
struct ifnet *ifp;
@@ -139,6 +146,29 @@
*/
if (nfsbootdevname)
ifp = ifunit(nfsbootdevname);
+#ifdef BOOT_LINKADDR
+ else if(BOOT_LINKADDR) {
+ for (ifp = ifnet.tqh_first; ifp != 0; ifp =
ifp->if_list.tqe_next)
+ if ((ifp->if_flags &
+ (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
+ {
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
+ for(ifa = ifp->if_addrlist.tqh_first; ifa != 0;
+ ifa = ifa->ifa_list.tqe_next)
+ if ((sdl = (struct sockaddr_dl
*)ifa->ifa_addr)
+ && sdl->sdl_family == AF_LINK
+ && sdl->sdl_type ==
BOOT_LINKADDR->la_type
+ && sdl->sdl_alen ==
BOOT_LINKADDR->la_alen
+ && !bcmp(LLADDR(sdl),
BOOT_LINKADDR->la_addr,
+ BOOT_LINKADDR->la_alen))
+ break;
+ if(ifa != 0)
+ break;
+ }
+ }
+
+#endif
else
for (ifp = ifnet.tqh_first; ifp != 0; ifp =
ifp->if_list.tqe_next)
if ((ifp->if_flags &
@@ -167,25 +197,67 @@
panic("nfs_boot: SIFFLAGS, error=%d", error);
/*
- * Do RARP for the interface address.
+ * If we're lucky, the boot already know who we are
+ * and we can get rid of the RARP step
*/
- if ((error = revarpwhoami(&my_ip, ifp)) != 0)
+ #ifdef BOOT_GETIP4INFO
+ BOOT_GETIP4INFO(my_ip.s_addr, my_mask.s_addr, my_bcast.s_addr);
+ #else
+ my_ip.s_addr = my_mask.s_addr = my_bcast.s_addr = 0;
+ #endif
+
+ if(my_ip.s_addr) {
+ printf("nfs_boot: client_addr=%s (boot)\n", inet_ntoa(my_ip));
+ } else {
+ /*
+ * Do RARP for the interface address.
+ */
+ if ((error = revarpwhoami(&my_ip, ifp)) != 0)
panic("revarp failed, error=%d", error);
- printf("nfs_boot: client_addr=%s\n", inet_ntoa(my_ip));
+ printf("nfs_boot: client_addr=%s (rarp)\n", inet_ntoa(my_ip));
+ }
/*
* Do enough of ifconfig(8) so that the chosen interface
- * can talk to the servers. (just set the address)
+ * can talk to the servers.
+ */
+ sin = (struct sockaddr_in *)&ireq.ifr_addr;
+ bzero((caddr_t)sin, sizeof(*sin));
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+
+ /*
+ * if we know our netmask, it's better to set it up before the
+ * IP address to prevent creating a bogus routing table entry when
+ * subnetting
+ */
+ if(my_mask.s_addr) {
+ printf("nfs_boot: client_mask=%s (boot)\n", inet_ntoa(my_mask));
+ sin->sin_addr.s_addr = my_mask.s_addr;
+ error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)&ireq, procp);
+ if (error)
+ panic("nfs_boot: set if mask, error=%d", error);
+ }
+
+ /*
+ * setup my IP address
*/
- sin = (struct sockaddr_in *)&ireq.ifr_addr;
- bzero((caddr_t)sin, sizeof(*sin));
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
sin->sin_addr.s_addr = my_ip.s_addr;
error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp);
if (error)
panic("nfs_boot: set if addr, error=%d", error);
+ /*
+ * if we know our broadcast address, we can also set it up
+ */
+ if(my_bcast.s_addr) {
+ printf("nfs_boot: client_broadcast=%s (boot)\n",
inet_ntoa(my_bcast));
+ sin->sin_addr.s_addr = my_bcast.s_addr;
+ error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)&ireq, procp);
+ if (error)
+ panic("nfs_boot: set if broadcast, error=%d", error);
+ }
+
soclose(so);
/*
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- OpenBSD+GRUB+PXE patches,
Cedric Berger <=