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