Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sbin / i386 / nextboot / nextboot.c
1 /*
2  * Copyright (c) 1996 Whistle Communications
3  * All Rights Reserved.
4  *
5  * Permission to use, copy, modify and distribute this software and its
6  * documentation is hereby granted, provided that both the copyright
7  * notice and this permission notice appear in all copies of the
8  * software, derivative works or modified versions, and any portions
9  * thereof, and that both notices appear in supporting documentation.
10  *
11  * Whistle Communications allows free use of this software in its "as is"
12  * condition.  Whistle Communications disclaims any liability of any kind for
13  * any damages whatsoever resulting from the use of this software.
14  *
15  * $FreeBSD: src/sbin/i386/nextboot/nextboot.c,v 1.6 1999/08/28 00:13:06 peter Exp $
16  * $DragonFly: src/sbin/i386/nextboot/nextboot.c,v 1.2 2003/06/17 04:27:33 dillon Exp $
17  */
18
19 #include <sys/types.h>
20 #include <sys/disklabel.h>
21 #include <fcntl.h>
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 struct mboot
28 {
29         unsigned char padding[2]; /* force the longs to be long aligned */
30         unsigned char bootinst[DOSPARTOFF];
31         struct  dos_partition parts[4];
32         unsigned short int      signature;
33 };
34 struct mboot mboot;
35
36 #define NAMEBLOCK 1 /* 2nd block */
37 #define BLOCKSIZE 512
38 #define ENABLE_MAGIC 0xfadefeed
39 #define DISABLE_MAGIC 0xfadefade
40 static int      bflag;
41 static int      eflag;
42 static int      dflag;
43
44 #define BOOT_MAGIC 0xAA55
45
46 static void
47 usage(void) {
48         fprintf (stderr, "%s\n%s\n",
49         "usage: nextboot [-b] device bootstring [bootstring] ...",
50         "       nextboot {-e,-d} device");
51         exit(1);
52 }
53
54 int
55 main (int argc, char** argv)
56 {
57         int     fd = -1;
58         char namebuf[1024], *cp = namebuf;
59         int     i,j;
60         int     ch;
61         int     part;
62
63         bflag = 0;
64         while ((ch = getopt(argc, argv, "bde")) != -1) {
65                 switch(ch) {
66                 case 'b':
67                         bflag = 1;
68                         break;
69                 case 'd':
70                         dflag = 1;
71                         break;
72                 case 'e':
73                         eflag = 1;
74                         break;
75                 case '?':
76                 default:
77                         usage();
78                 }
79         }
80         argc -= optind;
81         argv += optind;
82
83         if ( (dflag + eflag + bflag) > 1 ) {
84                 usage();
85         }
86         if (dflag + eflag){
87                 if(argc != 1 ) {
88                         usage();
89                 }
90         } else {
91                 if (argc <2) {
92                         usage();
93                 }
94         }
95         if ((fd = open(argv[0], O_RDWR, 0)) < 0)
96                 errx(1, "can't open %s", argv[0]);
97
98         argc--;
99         argv++;
100
101         /*******************************************
102          * Check that we have an MBR
103          */
104         if (lseek(fd,0,0) == -1)
105                 err(1, "lseek");
106         if (read (fd,&mboot.bootinst[0],BLOCKSIZE ) != BLOCKSIZE)
107                 err(1, "read0");
108         if (mboot.signature != (unsigned short)BOOT_MAGIC)
109                 errx(1, "no fdisk part.. not touching block 1");
110
111         /*******************************************
112          * And check that none of the partitions in it cover the name block;
113          */
114         for ( part = 0; part < 4; part++) {
115                 if( mboot.parts[part].dp_size
116                  && (mboot.parts[part].dp_start <= NAMEBLOCK)
117                  && (mboot.parts[part].dp_start
118                         + mboot.parts[part].dp_size > NAMEBLOCK))
119                         errx(1,
120                 "name sector lies within a Bios partition: aborting write");
121         }
122
123
124         /*******************************************
125          *  Now check the  name sector itself to see if it's been initialized.
126          */
127         if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1)
128                 err(1, "lseek");
129         if (read(fd,namebuf,BLOCKSIZE) != BLOCKSIZE)
130                 err(1, "read1");
131         /*******************************************
132          * check if we are just enabling or disabling
133          * Remember the flags are exclusive..
134          */
135         if(!bflag) { /* don't care what's there if bflag is set */
136                 switch(*(unsigned long *)cp)
137                 {
138                 case    DISABLE_MAGIC:
139                 case    ENABLE_MAGIC:
140                         break;
141                 default:
142                         errx(1, "namesector not initialized, use the -b flag");
143                 }
144         }
145
146
147         /*******************************************
148          *  If the z or r flag is set, damage or restore the magic number..
149          * to disable/enable the feature
150          */
151         if(dflag) {
152                 *(unsigned long *)cp = DISABLE_MAGIC;
153         } else {
154                 *(unsigned long *)cp = ENABLE_MAGIC;
155         }
156         if ((!dflag) && (!eflag)) {
157                 /*******************************************
158                 *  Create a new namesector in ram 
159                 */
160                 cp += 4;
161                 for ( i = 0 ; i < argc ; i++ ) {
162                         *cp++ = 'D';
163                         *cp++ = 'N';
164                         j = strlen(argv[i]);
165                         strncpy(cp,argv[i],j);
166                         cp += j;
167                         *cp++ = 0;
168                 }
169                 *cp++ = 0xff;
170                 *cp++ = 0xff;
171                 *cp++ = 0xff;
172                 namebuf[BLOCKSIZE-1] = 0; /* paranoid */
173                 namebuf[BLOCKSIZE] = 0xff;
174         }
175
176         /*******************************************
177          *  write it to disk.
178          */
179         if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1)
180                 err(1, "lseek");
181         if(write (fd,namebuf,BLOCKSIZE ) != BLOCKSIZE)
182                 err(1, "write");
183
184 #if 0
185         /*******************************************
186          * just to be safe/paranoid.. read it back..
187          * and print it..
188          */
189         if (lseek(fd,NAMEBLOCK * BLOCKSIZE,0) == -1)
190                 err(1, "lseek (second)");
191         read (fd,namebuf,512);
192         for (i = 0;i< 16;i++) {
193                 for ( j = 0; j < 16; j++) {
194                         printf("%02x ",(unsigned char )namebuf[(i*16) + j ]);
195                 }
196                 printf("\n");
197         }
198 #endif
199         exit(0);
200 }