Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Jun 98 17:28:25 +0100 (BST)
From:      iedowse@maths.tcd.ie
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   i386/7098: Various netboot fixes 
Message-ID:  <9806281728.aa09864@walton.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help

>Number:         7098
>Category:       i386
>Synopsis:       Various netboot fixes
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 28 09:30:01 PDT 1998
>Last-Modified:
>Originator:     Ian Dowse
>Organization:
		School of Mathematics,
		Trinity College Dublin
>Release:        FreeBSD 2.2.6-STABLE i386
>Environment:

	FreeBSD stable and current, using
	netboot for diskless booting.

>Description:

 These are a selection of small problems and annoyances with the netboot
 code. Apart from the first one, none really affect typical configurations
 but are nevertheless unnecessary limitations. We use netbooted PCs as
 student X-terminals and all of the below fixes have been useful. Apologies
 for including them all in one PR, but some are just too silly or trivial
 to send on their own!

 If anyone is interested, I also have a version of netboot which works
 on the Intel Etherexpress Pro/100 cards. I haven't used it with a
 flash rom on the card yet though.

 a)	Newer SMC cards have hardware addresses starting with 00:E0.
	Netboot compares the MAC address with 00:00:C0 to determine
	if it is a WD/SMC card, so it fails to detect these.

 b)	Netboot is unable to boot kzipped kernels, as it assumes that
	the kernel load address is 0x100000.

 c)	Users can abort the booting process and enter arbitrary network
	addresses, or boot from a floppy disk. This can be a problem when
	netbooted machines are used in a student environment.

 d)	It is not possible to set all options via bootp. For example there
	is no way to remotely force a client to boot from disk. With both
	SECURE_BOOT(patch below) and NO_TFTP defined, short of unplugging
	the eprom there is no way at all to get the client to boot locally.
	A generic solution is to allow complete netboot commands to be sent
	using bootp lines such as:
		:T132="diskboot":

 e)	The last character of netboot command names is not checked. You
	can type 'iz 10.0.0.1' and it will be interpreted as 'ip'. This
	is only important if you try to add a new command which is the
	same as an existing one except for the last character.

 f)	We have a configuration where multiple servers are willing to serve
	a diskless client. The tftp config file, or the bootptab entry on
	each server must specify the root and swap filesystems as 'ip:/fs'
	even though 'ip' will usually be the responding server's IP address.
	It would be nice if netboot could automatically prepend the server's
	IP address to an entry specified as just '/fs', so that multiple
	servers can use the same tftp or bootp configuration files. Admittedly
	this is hardly a major problem!

>How-To-Repeat:

 a)	Try to use netboot with a new SMC card.
 b)	Try to netboot a kzip'd kernel
 c)	Install netboot clients in a student computer lab and watch what
	happens :)
 d)	Try to send a 'diskboot' command via bootp.
 e)	Add a new command 'd' to the bootcmds array, and when typed,
	it will be treated as '?', the first 1-character command.
 f)	Set up a multiple-server configuration; bootp or tftp config files
	from one server cannot copied directly to others.


>Fix:

a)

diff -c ../netboot.old/ns8390.c ./ns8390.c
*** ../netboot.old/ns8390.c	Sun Aug 24 00:38:12 1997
--- ./ns8390.c	Sun Jun 28 02:44:59 1998
***************
*** 82,89 ****
  		chksum = 0;
  		/* Check for WD/SMC card by checking ethernet address */
  		if (inb(eth_asic_base+8) != 0) continue;
! 		if (inb(eth_asic_base+9) != 0) continue;
! 		if (inb(eth_asic_base+10) != 0xC0) continue;
  		for (i=8; i<16; i++)
  			chksum += inb(i+eth_asic_base);
  		if ((chksum & 0x00FF) == 0x00FF)
--- 82,91 ----
  		chksum = 0;
  		/* Check for WD/SMC card by checking ethernet address */
  		if (inb(eth_asic_base+8) != 0) continue;
! 		if (inb(eth_asic_base+9) != 0xE0) {
! 			if (inb(eth_asic_base+9) != 0) continue;
! 			if (inb(eth_asic_base+10) != 0xC0) continue;
! 		}
  		for (i=8; i<16; i++)
  			chksum += inb(i+eth_asic_base);
  		if ((chksum & 0x00FF) == 0x00FF)


b)

diff -c ../netboot.old/main.c ./main.c
*** ../netboot.old/main.c	Sun Jan 18 23:16:27 1998
--- ./main.c	Sun Jun 28 02:59:50 1998
***************
*** 292,298 ****
  		printf("Bad executable format!\r\n");
  		longjmp(jmp_bootmenu, 1);
  	}
! 	loadpoint = (char *)0x100000;
  	offset = N_TXTOFF(head);
  	printf("text=0x%X, ",head.a_text);
  	nfsload(head.a_text);
--- 292,298 ----
  		printf("Bad executable format!\r\n");
  		longjmp(jmp_bootmenu, 1);
  	}
! 	loadpoint = (char *)(head.a_entry & 0x00FFFFFF);
  	offset = N_TXTOFF(head);
  	printf("text=0x%X, ",head.a_text);
  	nfsload(head.a_text);


c)

diff -c ../netboot.old/Makefile ./Makefile
*** ../netboot.old/Makefile	Sat Mar  7 11:20:13 1998
--- ./Makefile	Sun Jun 28 15:46:19 1998
***************
*** 3,8 ****
--- 3,9 ----
  # Makefile for NETBOOT
  #
  # Basic Options:
+ #	-DSECURE_BOOT	- Disable 'boot>' prompt completely
  #	-DASK_BOOT	- Ask "Boot from Network (Y/N) ?" at startup
  #	-DROMSIZE	- Size of EPROM - Must be set (even for .COM files)
  #	-DRELOC		- Relocation address (usually 0x90000)
diff -c ../netboot.old/bootmenu.c ./bootmenu.c
*** ../netboot.old/bootmenu.c	Wed May 14 03:44:26 1997
--- ./bootmenu.c	Sun Jun 28 03:41:20 1998
***************
*** 327,332 ****
--- 338,355 ----
  {
  	char cmd[80];
  	int ptr, c;
+ #ifdef SECURE_BOOT
+ 	char *p;
+ 
+ 	printf("\r\n");
+ 
+ 	printf("Press any key to retry:");
+ 	while (iskey())
+ 		getchar();
+ 	getchar();
+ 	printf("\r\n");
+ 	eth_probe();
+ #else
  	printf("\r\n");
  	while (1) {
  		ptr = 0;
***************
*** 349,353 ****
--- 372,377 ----
  		printf("\r\n");
  		if (execute(cmd)) break;
  	}
+ #endif
  	eth_reset();
  }
diff -c ../netboot.old/main.c ./main.c
*** ../netboot.old/main.c	Sun Jan 18 23:16:27 1998
--- ./main.c	Sun Jun 28 02:59:50 1998
***************
*** 343,349 ****
--- 343,351 ----
  **************************************************************************/
  pollkbd()
  {
+ #ifndef SECURE_BOOT
  	if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1);
+ #endif
  }
  
  /**************************************************************************


d)

diff -c ../netboot.old/main.c ./main.c
*** ../netboot.old/main.c	Sun Jan 18 23:16:27 1998
--- ./main.c	Sun Jun 28 02:59:50 1998
***************
*** 657,662 ****
--- 659,676 ----
  				break;
  			case 131:       /* swap mount options */
  				bootp_string("swapopts", p);
+ 				break;
+ 			case 132:       /* any other options */
+ 			case 133:
+ 			case 134:
+ 			case 135:
+ 			case 136:
+ 			case 137:
+ 			case 138:
+ 			case 139:
+ 			case 140:
+ 			case 141:
+ 				bootp_string("", p);
  				break;
  			default:
  				printf("Unknown RFC1048-tag ");

e)

diff -c ../netboot.old/bootmenu.c ./bootmenu.c
*** ../netboot.old/bootmenu.c	Wed May 14 03:44:26 1997
--- ./bootmenu.c	Sun Jun 28 03:41:20 1998
***************
*** 305,311 ****
  	while(cmd->name) {
  		p = buf;
  		q = cmd->name;
! 		while (*q && (*(q++) == *(p++))) ;
  		if ((!(*q)) && ((*p == ' ') || (*p == '\t') || (!(*p)))) {
  			if (!cmd->func) 
  				return(1);
--- 315,322 ----
  	while(cmd->name) {
  		p = buf;
  		q = cmd->name;
! 		while (*q && *q == *p++)
! 			q++;
  		if ((!(*q)) && ((*p == ' ') || (*p == '\t') || (!(*p)))) {
  			if (!cmd->func) 
  				return(1);


f)

diff -c ../netboot.old/bootmenu.c ./bootmenu.c
*** ../netboot.old/bootmenu.c	Wed May 14 03:44:26 1997
--- ./bootmenu.c	Sun Jun 28 02:58:42 1998
***************
*** 32,39 ****
  	{"netmask",	cmd_netmask,	"<addr>     set network mask"},
  	{"hostname",	cmd_hostname,	"<name>    set hostname"},
  	{"kernel",	cmd_kernel,	"<file>      set boot filename"},
! 	{"rootfs",	cmd_rootfs,	"ip:/fs      set root filesystem"},
! 	{"swapfs",	cmd_swapfs,	"ip:/fs      set swap filesystem"},
  	{"swapsize",	cmd_swapsize,	"<nblks>   set swap size"},
  	{"swapopts",	cmd_swapopts,	"<options> swap mount options"},
  	{"rootopts",	cmd_rootopts,	"<options> root mount options"},
--- 32,39 ----
  	{"netmask",	cmd_netmask,	"<addr>     set network mask"},
  	{"hostname",	cmd_hostname,	"<name>    set hostname"},
  	{"kernel",	cmd_kernel,	"<file>      set boot filename"},
! 	{"rootfs",	cmd_rootfs,	"[ip:]/fs    set root filesystem"},
! 	{"swapfs",	cmd_swapfs,	"[ip:]/fs    set swap filesystem"},
  	{"swapsize",	cmd_swapsize,	"<nblks>   set swap size"},
  	{"swapopts",	cmd_swapopts,	"<options> swap mount options"},
  	{"rootopts",	cmd_rootopts,	"<options> root mount options"},
***************
*** 160,176 ****
  cmd_rootfs(p)
  	char *p;
  {
! 	if (!setip(p, &arptable[ARP_ROOTSERVER].ipaddr)) {
  		printf("Root filesystem is %I:%s\r\n",
  			nfsdiskless.root_saddr.sin_addr,
  			nfsdiskless.root_hostnam);
  	} else {
- 		bcopy(&arptable[ARP_ROOTSERVER].ipaddr,
- 			&nfsdiskless.root_saddr.sin_addr, 4);
  		while (*p && (*p != ':')) p++;
  		if (*p == ':') p++;
- 		sprintf(&nfsdiskless.root_hostnam, "%s", p);
  	}
  }
  
  /**************************************************************************
--- 160,181 ----
  cmd_rootfs(p)
  	char *p;
  {
! 	if (*p == '/') {
! 		bcopy(&arptable[ARP_SERVER].ipaddr,
! 		    &arptable[ARP_ROOTSERVER].ipaddr, 4);
! 	} else if (!setip(p, &arptable[ARP_ROOTSERVER].ipaddr)) {
  		printf("Root filesystem is %I:%s\r\n",
  			nfsdiskless.root_saddr.sin_addr,
  			nfsdiskless.root_hostnam);
+ 		return;
  	} else {
  		while (*p && (*p != ':')) p++;
  		if (*p == ':') p++;
  	}
+ 
+ 	bcopy(&arptable[ARP_ROOTSERVER].ipaddr,
+ 	    &nfsdiskless.root_saddr.sin_addr, 4);
+ 	sprintf(&nfsdiskless.root_hostnam, "%s", p);
  }
  
  /**************************************************************************
***************
*** 179,195 ****
  cmd_swapfs(p)
  	char *p;
  {
! 	if (!setip(p, &arptable[ARP_SWAPSERVER].ipaddr)) {
  		printf("Swap filesystem is %I:%s\r\n",
  			nfsdiskless.swap_saddr.sin_addr,
  			nfsdiskless.swap_hostnam);
  	} else {
- 		bcopy(&arptable[ARP_SWAPSERVER].ipaddr,
- 			&nfsdiskless.swap_saddr.sin_addr, 4);
  		while (*p && (*p != ':')) p++;
  		if (*p == ':') p++;
- 		sprintf(&nfsdiskless.swap_hostnam, "%s", p);
  	}
  }
  
  /**************************************************************************
--- 184,205 ----
  cmd_swapfs(p)
  	char *p;
  {
! 	if (*p == '/') {
! 		bcopy(&arptable[ARP_SERVER].ipaddr,
! 		    &arptable[ARP_SWAPSERVER].ipaddr, 4);
! 	} else if (!setip(p, &arptable[ARP_SWAPSERVER].ipaddr)) {
  		printf("Swap filesystem is %I:%s\r\n",
  			nfsdiskless.swap_saddr.sin_addr,
  			nfsdiskless.swap_hostnam);
+ 		return;
  	} else {
  		while (*p && (*p != ':')) p++;
  		if (*p == ':') p++;
  	}
+ 
+ 	bcopy(&arptable[ARP_SWAPSERVER].ipaddr,
+ 	    &nfsdiskless.swap_saddr.sin_addr, 4);
+ 	sprintf(&nfsdiskless.swap_hostnam, "%s", p);
  }
  
  /**************************************************************************
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9806281728.aa09864>