summaryrefslogtreecommitdiffstats
path: root/sbin/i386/nextboot
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1996-07-09 02:04:32 +0000
committerjulian <julian@FreeBSD.org>1996-07-09 02:04:32 +0000
commit6afeabc6cb433ddb8839be05056fb9b2c5985bc9 (patch)
treeaa2dea08b76aa7ed2a1064862574dbebf2da4d79 /sbin/i386/nextboot
parent7dbcea9d7a235d9bdfe0a5925903b3d65c4ee84d (diff)
downloadFreeBSD-src-6afeabc6cb433ddb8839be05056fb9b2c5985bc9.zip
FreeBSD-src-6afeabc6cb433ddb8839be05056fb9b2c5985bc9.tar.gz
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.
Diffstat (limited to 'sbin/i386/nextboot')
-rw-r--r--sbin/i386/nextboot/Makefile9
-rw-r--r--sbin/i386/nextboot/nextboot.887
-rw-r--r--sbin/i386/nextboot/nextboot.c232
3 files changed, 328 insertions, 0 deletions
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 <bsd.prog.mk>
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 <sys/types.h>
+#include <sys/disklabel.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+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);
+}
+
+
OpenPOWER on IntegriCloud