From 6afeabc6cb433ddb8839be05056fb9b2c5985bc9 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 9 Jul 1996 02:04:32 +0000 Subject: Obtained from: Whistle Communications control program to control the facility of the bootblocks to fetch a default bootstring from a fixed location on the disk. See the manpage for more info. --- sbin/i386/nextboot/Makefile | 9 ++ sbin/i386/nextboot/nextboot.8 | 87 ++++++++++++++++ sbin/i386/nextboot/nextboot.c | 232 ++++++++++++++++++++++++++++++++++++++++++ sbin/nextboot/Makefile | 9 ++ sbin/nextboot/nextboot.8 | 87 ++++++++++++++++ sbin/nextboot/nextboot.c | 232 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 656 insertions(+) create mode 100644 sbin/i386/nextboot/Makefile create mode 100644 sbin/i386/nextboot/nextboot.8 create mode 100644 sbin/i386/nextboot/nextboot.c create mode 100644 sbin/nextboot/Makefile create mode 100644 sbin/nextboot/nextboot.8 create mode 100644 sbin/nextboot/nextboot.c (limited to 'sbin') diff --git a/sbin/i386/nextboot/Makefile b/sbin/i386/nextboot/Makefile new file mode 100644 index 0000000..7ac235f --- /dev/null +++ b/sbin/i386/nextboot/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 1.1 (Julian Elischer) 3/28/93 +# +# + +PROG= nextboot +SRCS= nextboot.c +MAN8= nextboot.8 + +.include diff --git a/sbin/i386/nextboot/nextboot.8 b/sbin/i386/nextboot/nextboot.8 new file mode 100644 index 0000000..b301fba --- /dev/null +++ b/sbin/i386/nextboot/nextboot.8 @@ -0,0 +1,87 @@ +.Dd July 9, 1996 +.Dt NEXTBOOT 8 +.\".Os BSD 4 +.Sh NAME +.Nm nextboot +.Nd Install a default bootstring block on the boot disk +.Sh SYNOPSIS +.Nm +.Op Fl b +.Ar filename bootstring ... +.Pp +.Nm +.Op Fl e +.Op Fl d +.Ar filename +.Bl -tag -width time +.It Fl b +Is used for bootstrapping (initially configuring) the nameblock. Without +this, +.Nm +will refuse to write to a block that does not already contain the magic +number. +.It Fl d +temporarily disables an existing name block by changing a bit +in the magic number. +.It Fl e +restores the good magic number on a block disabled by -d. +.El +.Sh PROLOGUE +The FreeBSD program +.Nm +controls the actions of the boot blocks at the time of the next boot. +If compiled with the correct option, +the boot blocks will check the nameblock for a magic number and a +default name to use for booting. If compiled to do so they will also +delete the name from the block, ensuring that if the boot should fail, +then it will not be tried again. It is the job of /etc/rc to use +.Nm +to re-install the string if that boot is found to have succeeded. +This allows a one-time only boot string to be used for such applications +as remote debugging, and installation of new, untrusted kernels. +The nameblock is defined at compile time to be the second physical block +on the disk. +.Pp +.Sh DESCRIPTION +.Nm +first checks that the disk has an fdisk table and checks that none of the +partitions defined in that table include the nameblock. If the name block is +shown to be unused, it will install the bootstrings given as arguments, +one after the other, each preceded by a small magic number, and NULL +terminated. The end of the list of strings is delimited by a sequence of +0xff bytes. If the boot blocks are compiled to write back the nameblock +after each boot, it will zero out the supplied names as it uses them, +one per boot, +until it reaches the 0xff, at which time it will revert to the compiled in +boot string. At this time the nameblock will contain only zeroed out names. +.Pp +An example of usage might be: +.Bd -literal + nextboot -b /dev/rwd0 1:sd(0,a)/kernel.experimental wd(0,a)/kernel.old +.Ed +.Pp +Which would instruct the boot blocks at the next boot, +to try boot the experimental kernel off the scsi disk. +If for any reason this failed, the next boot attempt would +boot the kernel +.Em /kernel.old +off the IDE drive. (assuming the write-back option were enabled) If this +in turn failed. the compiled in default would be used. +.Pp +If the write-back feature is disabled, the nextboot program is a convenient way +to change the default boot string. Note, that should the file specified in +the nameblock be non-existant, then the name compiled into the boot blocks +will be used for the boot rather than the next name in the nameblock. The +nameblock is only consulted ONCE per boot. + + +.Sh SEE ALSO +.Xr boot 8 +.Xr disklabel 8 +.Xr fdisk 8 +.Sh BUGS +The entire program should be made more user-friendly. +.Pp +Whether to write back or not should be specified at run-time in the nameblock +so that the boot blocks need not be altered to get this feature. +.Pp diff --git a/sbin/i386/nextboot/nextboot.c b/sbin/i386/nextboot/nextboot.c new file mode 100644 index 0000000..bbf8b79 --- /dev/null +++ b/sbin/i386/nextboot/nextboot.c @@ -0,0 +1,232 @@ + +/* + * Copyright (c) 1996 Whistle Communications + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * Whistle Communications allows free use of this software in its "as is" + * condition. Whistle Communications disclaims any liability of any kind for + * any damages whatsoever resulting from the use of this software. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mboot +{ + unsigned char padding[2]; /* force the longs to be long alligned */ + unsigned char bootinst[DOSPARTOFF]; + struct dos_partition parts[4]; + unsigned short int signature; +}; +struct mboot mboot; + +#define NAMEBLOCK 1 /* 2nd block */ +#define BLOCKSIZE 512 +#define ENABLE_MAGIC 0xdeafc0de +#define DISABLE_MAGIC 0xdeadc0de +static int bflag; +static int eflag; +static int dflag; +static int nameblock = NAMEBLOCK; + +char * myname; +#define BOOT_MAGIC 0xAA55 + +static void usage(void) { + printf (" usage: %s [-b] device bootstring [bootstring] ...\n" + ,myname); + printf (" or: %s {-e,-d} device \n" + ,myname); + printf (" flags are mutually exclusive\n"); + exit(1); +} + +main (int argc, char** argv) +{ + int fd = -1; + char namebuf[1024], *cp = namebuf; + int i,j; + int ch; + int part; + + bflag = 0; + myname = argv[0]; + while ((ch = getopt(argc, argv, "bde")) != EOF) { + switch(ch) { + case 'b': + bflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + eflag = 1; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if ( (dflag + eflag + bflag) > 1 ) { + usage(); + } + if (dflag + eflag){ + if(argc != 1 ) { + usage(); + } + } else { + if (argc <2) { + usage(); + } + } + if ((fd = open(argv[0], O_RDWR, 0)) < 0) { + perror("open"); + printf ("file: %s\n",argv[0]); + usage(); + } + + argc--; + argv++; + + /******************************************* + * Check that we have an MBR + */ + if (lseek(fd,0,0) == -1) { + perror("lseek"); + exit(1); + } + if (read (fd,&mboot.bootinst[0],BLOCKSIZE ) != BLOCKSIZE) { + perror("read0"); + exit(1); + } + if(mboot.signature != (unsigned short)BOOT_MAGIC) { + printf(" no fdisk part.. not touching block 1\n"); + exit(1); + } + + /******************************************* + * And check that none of the partitions in it cover the name block; + */ + for ( part = 0; part < 4; part++) { + if( mboot.parts[part].dp_size + && (mboot.parts[part].dp_start <= NAMEBLOCK) + && (mboot.parts[part].dp_start + + mboot.parts[part].dp_size > NAMEBLOCK)) { + printf(" Name sector lies within a Bios partition.\n"); + printf(" Aborting write.\n"); + exit(1); + } + } + + + /******************************************* + * Now check the name sector itself to see if it's been initialised. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek"); + exit(1); + } + if ( read (fd,namebuf,BLOCKSIZE ) != BLOCKSIZE) { + perror("read1"); + exit(1); + } + /******************************************* + * check if we are just enabling or disabling + * Remember the flags are exlusive.. + */ + if(!bflag) { /* don't care what's there if bflag is set */ + switch(*(unsigned long *)cp) + { + case DISABLE_MAGIC: + case ENABLE_MAGIC: + break; + default: + fprintf(stderr, + "namesector not initialised.." + "use the -b flag..\n"); + exit(1); + } + } + + + /******************************************* + * If the z or r flag is set, damage or restore the magic number.. + * to disable/enable the feature + */ + if(dflag) { + *(unsigned long *)cp = DISABLE_MAGIC; + } else { + *(unsigned long *)cp = ENABLE_MAGIC; + } + if ((!dflag) && (!eflag)) { + /******************************************* + * Create a new namesector in ram + */ + cp += 4; + for ( i = 0 ; i < argc ; i++ ) { + *cp++ = 'D'; + *cp++ = 'N'; + j = strlen(argv[i]); + strncpy(cp,argv[i],j); + cp += j; + *cp++ = 0; + } + *cp++ = 0xff; + *cp++ = 0xff; + *cp++ = 0xff; + namebuf[BLOCKSIZE-1] = 0; /* paranoid */ + namebuf[BLOCKSIZE] = 0xff; + } + + /******************************************* + * write it to disk. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek"); + exit(1); + } + if(write (fd,namebuf,BLOCKSIZE ) != BLOCKSIZE) { + perror("write"); + exit(1); + } + +#if 0 + /******************************************* + * just to be safe/paranoid.. read it back.. + * and print it.. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek (second) "); + exit(1); + } + read (fd,namebuf,512); + for (i = 0;i< 16;i++) { + for ( j = 0; j < 16; j++) { + printf("%02x ",(unsigned char )namebuf[(i*16) + j ]); + } + printf("\n"); + } +#endif + exit(0); +} + + diff --git a/sbin/nextboot/Makefile b/sbin/nextboot/Makefile new file mode 100644 index 0000000..7ac235f --- /dev/null +++ b/sbin/nextboot/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 1.1 (Julian Elischer) 3/28/93 +# +# + +PROG= nextboot +SRCS= nextboot.c +MAN8= nextboot.8 + +.include diff --git a/sbin/nextboot/nextboot.8 b/sbin/nextboot/nextboot.8 new file mode 100644 index 0000000..b301fba --- /dev/null +++ b/sbin/nextboot/nextboot.8 @@ -0,0 +1,87 @@ +.Dd July 9, 1996 +.Dt NEXTBOOT 8 +.\".Os BSD 4 +.Sh NAME +.Nm nextboot +.Nd Install a default bootstring block on the boot disk +.Sh SYNOPSIS +.Nm +.Op Fl b +.Ar filename bootstring ... +.Pp +.Nm +.Op Fl e +.Op Fl d +.Ar filename +.Bl -tag -width time +.It Fl b +Is used for bootstrapping (initially configuring) the nameblock. Without +this, +.Nm +will refuse to write to a block that does not already contain the magic +number. +.It Fl d +temporarily disables an existing name block by changing a bit +in the magic number. +.It Fl e +restores the good magic number on a block disabled by -d. +.El +.Sh PROLOGUE +The FreeBSD program +.Nm +controls the actions of the boot blocks at the time of the next boot. +If compiled with the correct option, +the boot blocks will check the nameblock for a magic number and a +default name to use for booting. If compiled to do so they will also +delete the name from the block, ensuring that if the boot should fail, +then it will not be tried again. It is the job of /etc/rc to use +.Nm +to re-install the string if that boot is found to have succeeded. +This allows a one-time only boot string to be used for such applications +as remote debugging, and installation of new, untrusted kernels. +The nameblock is defined at compile time to be the second physical block +on the disk. +.Pp +.Sh DESCRIPTION +.Nm +first checks that the disk has an fdisk table and checks that none of the +partitions defined in that table include the nameblock. If the name block is +shown to be unused, it will install the bootstrings given as arguments, +one after the other, each preceded by a small magic number, and NULL +terminated. The end of the list of strings is delimited by a sequence of +0xff bytes. If the boot blocks are compiled to write back the nameblock +after each boot, it will zero out the supplied names as it uses them, +one per boot, +until it reaches the 0xff, at which time it will revert to the compiled in +boot string. At this time the nameblock will contain only zeroed out names. +.Pp +An example of usage might be: +.Bd -literal + nextboot -b /dev/rwd0 1:sd(0,a)/kernel.experimental wd(0,a)/kernel.old +.Ed +.Pp +Which would instruct the boot blocks at the next boot, +to try boot the experimental kernel off the scsi disk. +If for any reason this failed, the next boot attempt would +boot the kernel +.Em /kernel.old +off the IDE drive. (assuming the write-back option were enabled) If this +in turn failed. the compiled in default would be used. +.Pp +If the write-back feature is disabled, the nextboot program is a convenient way +to change the default boot string. Note, that should the file specified in +the nameblock be non-existant, then the name compiled into the boot blocks +will be used for the boot rather than the next name in the nameblock. The +nameblock is only consulted ONCE per boot. + + +.Sh SEE ALSO +.Xr boot 8 +.Xr disklabel 8 +.Xr fdisk 8 +.Sh BUGS +The entire program should be made more user-friendly. +.Pp +Whether to write back or not should be specified at run-time in the nameblock +so that the boot blocks need not be altered to get this feature. +.Pp diff --git a/sbin/nextboot/nextboot.c b/sbin/nextboot/nextboot.c new file mode 100644 index 0000000..bbf8b79 --- /dev/null +++ b/sbin/nextboot/nextboot.c @@ -0,0 +1,232 @@ + +/* + * Copyright (c) 1996 Whistle Communications + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * Whistle Communications allows free use of this software in its "as is" + * condition. Whistle Communications disclaims any liability of any kind for + * any damages whatsoever resulting from the use of this software. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mboot +{ + unsigned char padding[2]; /* force the longs to be long alligned */ + unsigned char bootinst[DOSPARTOFF]; + struct dos_partition parts[4]; + unsigned short int signature; +}; +struct mboot mboot; + +#define NAMEBLOCK 1 /* 2nd block */ +#define BLOCKSIZE 512 +#define ENABLE_MAGIC 0xdeafc0de +#define DISABLE_MAGIC 0xdeadc0de +static int bflag; +static int eflag; +static int dflag; +static int nameblock = NAMEBLOCK; + +char * myname; +#define BOOT_MAGIC 0xAA55 + +static void usage(void) { + printf (" usage: %s [-b] device bootstring [bootstring] ...\n" + ,myname); + printf (" or: %s {-e,-d} device \n" + ,myname); + printf (" flags are mutually exclusive\n"); + exit(1); +} + +main (int argc, char** argv) +{ + int fd = -1; + char namebuf[1024], *cp = namebuf; + int i,j; + int ch; + int part; + + bflag = 0; + myname = argv[0]; + while ((ch = getopt(argc, argv, "bde")) != EOF) { + switch(ch) { + case 'b': + bflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + eflag = 1; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if ( (dflag + eflag + bflag) > 1 ) { + usage(); + } + if (dflag + eflag){ + if(argc != 1 ) { + usage(); + } + } else { + if (argc <2) { + usage(); + } + } + if ((fd = open(argv[0], O_RDWR, 0)) < 0) { + perror("open"); + printf ("file: %s\n",argv[0]); + usage(); + } + + argc--; + argv++; + + /******************************************* + * Check that we have an MBR + */ + if (lseek(fd,0,0) == -1) { + perror("lseek"); + exit(1); + } + if (read (fd,&mboot.bootinst[0],BLOCKSIZE ) != BLOCKSIZE) { + perror("read0"); + exit(1); + } + if(mboot.signature != (unsigned short)BOOT_MAGIC) { + printf(" no fdisk part.. not touching block 1\n"); + exit(1); + } + + /******************************************* + * And check that none of the partitions in it cover the name block; + */ + for ( part = 0; part < 4; part++) { + if( mboot.parts[part].dp_size + && (mboot.parts[part].dp_start <= NAMEBLOCK) + && (mboot.parts[part].dp_start + + mboot.parts[part].dp_size > NAMEBLOCK)) { + printf(" Name sector lies within a Bios partition.\n"); + printf(" Aborting write.\n"); + exit(1); + } + } + + + /******************************************* + * Now check the name sector itself to see if it's been initialised. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek"); + exit(1); + } + if ( read (fd,namebuf,BLOCKSIZE ) != BLOCKSIZE) { + perror("read1"); + exit(1); + } + /******************************************* + * check if we are just enabling or disabling + * Remember the flags are exlusive.. + */ + if(!bflag) { /* don't care what's there if bflag is set */ + switch(*(unsigned long *)cp) + { + case DISABLE_MAGIC: + case ENABLE_MAGIC: + break; + default: + fprintf(stderr, + "namesector not initialised.." + "use the -b flag..\n"); + exit(1); + } + } + + + /******************************************* + * If the z or r flag is set, damage or restore the magic number.. + * to disable/enable the feature + */ + if(dflag) { + *(unsigned long *)cp = DISABLE_MAGIC; + } else { + *(unsigned long *)cp = ENABLE_MAGIC; + } + if ((!dflag) && (!eflag)) { + /******************************************* + * Create a new namesector in ram + */ + cp += 4; + for ( i = 0 ; i < argc ; i++ ) { + *cp++ = 'D'; + *cp++ = 'N'; + j = strlen(argv[i]); + strncpy(cp,argv[i],j); + cp += j; + *cp++ = 0; + } + *cp++ = 0xff; + *cp++ = 0xff; + *cp++ = 0xff; + namebuf[BLOCKSIZE-1] = 0; /* paranoid */ + namebuf[BLOCKSIZE] = 0xff; + } + + /******************************************* + * write it to disk. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek"); + exit(1); + } + if(write (fd,namebuf,BLOCKSIZE ) != BLOCKSIZE) { + perror("write"); + exit(1); + } + +#if 0 + /******************************************* + * just to be safe/paranoid.. read it back.. + * and print it.. + */ + if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1) { + perror("lseek (second) "); + exit(1); + } + read (fd,namebuf,512); + for (i = 0;i< 16;i++) { + for ( j = 0; j < 16; j++) { + printf("%02x ",(unsigned char )namebuf[(i*16) + j ]); + } + printf("\n"); + } +#endif + exit(0); +} + + -- cgit v1.1