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