Subject: port-i386/2928: booting i386 with RB_ASKNAME flag
To: None <gnats-bugs@gnats.netbsd.org>
From: None <martin@rumolt.teuto.de>
List: netbsd-bugs
Date: 11/10/1996 12:10:54
>Number:         2928
>Category:       port-i386
>Synopsis:       port-i386 swapgeneric.c cleanup when booting with RB_ASKNAME
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 10 13:05:00 1996
>Last-Modified:
>Originator:     Martin Husemann
>Organization:
private
>Release:        1.2
>Environment:
System: NetBSD rumolt.teuto.de 1.2 NetBSD 1.2 (RUMOLT) #1: Fri Oct 4 04:57:09 MET DST 1996 root@rumolt.teuto.de:/usr/src/sys/arch/i386/compile/RUMOLT i386
Any generic i386 box.

>Description:
When booting with RB_ASKNAME and entering an invalid name for the root device,
the kernel gives a message similar to this:

use:
	wd%d
	sd%d
	cd%d
	fd%d

This is hardly comprehensible for a normal user. An expert wouldn't have
entered the wrong name in the first place, so I think this should be
much more user friendly.

Looking at the code I found a hard coded limit of two characters per device
name (followed by unit no), but there is at least one device with three
letters in the genericconf array: mcd. I modified the tests a bit and made
it cope with two or three letter names, probably a more general solution
(any number of characters followed by '*' or a digit) should be implemented.
I also added a short description of the device. The message now looks like

use:
	wd0	IDE hard disk
	sd0	SCSI hard disk
	cd0	SCSI CD-ROM
	mcd0	Mitsumi CD-ROM
	fd0	floppy disk
(replace '0' by '1' for second device of the given kind)

The right thing(tm) to do here would be to skip devices in the genericconf
array which didn't configure, so the user is presented his real options
here. We could enumerate all available devices then (i.e.: sd0, sd1, sd2, 
fd0, cd0)

>How-To-Repeat:
Boot with -a and enter an invalid boot device.
Examine sys/arch/i386/i386/swapgeneric.c

>Fix:

*** swapgeneric.c.old	Sun Nov 10 10:56:21 1996
--- swapgeneric.c	Sun Nov 10 11:55:47 1996
***************
*** 92,110 ****
  	char *gc_name;
  	dev_t gc_major;
  } genericconf[] = {
  #if NWDC > 0
! 	{ &wd_cd,  "wd",  0 },
  #endif
  #if NSD > 0
! 	{ &sd_cd,  "sd",  4 },
  #endif
  #if NCD > 0
! 	{ &cd_cd,  "cd",  6 },
  #endif
  #if NMCD > 0
! 	{ &mcd_cd, "mcd", 7 },
  #endif
  #if NFDC > 0
! 	{ &fd_cd,  "fd",  2 },
  #endif
  	{ 0 }
--- 92,111 ----
  	char *gc_name;
  	dev_t gc_major;
+ 	char *gc_desc;
  } genericconf[] = {
  #if NWDC > 0
! 	{ &wd_cd,  "wd",  0, "IDE hard disk" },
  #endif
  #if NSD > 0
! 	{ &sd_cd,  "sd",  4, "SCSI hard disk" },
  #endif
  #if NCD > 0
! 	{ &cd_cd,  "cd",  6, "SCSI CD-ROM" },
  #endif
  #if NMCD > 0
! 	{ &mcd_cd, "mcd", 7, "Mitsumi CD-ROM" },
  #endif
  #if NFDC > 0
! 	{ &fd_cd,  "fd",  2, "floppy disk" },
  #endif
  	{ 0 }
***************
*** 131,134 ****
--- 132,136 ----
  	if (boothowto & RB_ASKNAME) {
  		char name[128];
+ 		int offs;
  retry:
  		printf("root device? ");
***************
*** 136,149 ****
  		for (gc = genericconf; gc->gc_driver; gc++)
  			if (gc->gc_name[0] == name[0] &&
! 			    gc->gc_name[1] == name[1])
  				goto gotit;
  		goto bad;
  gotit:
! 		if (name[3] == '*') {
! 			name[3] = name[4];
  			swaponroot++;
  		}
! 		if (name[2] >= '0' && name[2] <= '7' && name[3] == 0) {
! 			unit = name[2] - '0';
  			goto found;
  		}
--- 138,156 ----
  		for (gc = genericconf; gc->gc_driver; gc++)
  			if (gc->gc_name[0] == name[0] &&
! 			    gc->gc_name[1] == name[1] &&
! 			    (gc->gc_name[2] == '\0' ||
! 			     gc->gc_name[2] == name[2]))
  				goto gotit;
  		goto bad;
  gotit:
! 		offs = 2;
! 		if (gc->gc_name[2] != '\0')
! 			offs++;	/* some devices have 3 char names, eg. "mcd0" */
! 		if (name[offs+1] == '*') {
! 			name[offs+1] = name[offs+2];
  			swaponroot++;
  		}
! 		if (name[offs] >= '0' && name[offs] <= '7' && name[offs+1] == 0) {
! 			unit = name[offs] - '0';
  			goto found;
  		}
***************
*** 152,156 ****
  		printf("use:\n");	
  		for (gc = genericconf; gc->gc_driver; gc++)
! 			printf("\t%s%%d\n", gc->gc_name);
  		goto retry;
  	}
--- 159,164 ----
  		printf("use:\n");	
  		for (gc = genericconf; gc->gc_driver; gc++)
! 			printf("\t%s0\t%s\n", gc->gc_name, gc->gc_desc);
! 		printf("(replace '0' by '1' for second device of the given kind)\n");
  		goto retry;
  	}

>Audit-Trail:
>Unformatted: