Merge branches 'at91', 'dyntick', 'ep93xx', 'iop', 'ixp', 'misc', 'orion', 'omap...
[linux-2.6] / arch / x86 / boot / tools / build.c
1 /*
2  *  Copyright (C) 1991, 1992  Linus Torvalds
3  *  Copyright (C) 1997 Martin Mares
4  *  Copyright (C) 2007 H. Peter Anvin
5  */
6
7 /*
8  * This file builds a disk-image from two different files:
9  *
10  * - setup: 8086 machine code, sets up system parm
11  * - system: 80386 code for actual system
12  *
13  * It does some checking that all files are of the correct type, and
14  * just writes the result to stdout, removing headers and padding to
15  * the right amount. It also writes some system data to stderr.
16  */
17
18 /*
19  * Changes by tytso to allow root device specification
20  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
21  * Cross compiling fixes by Gertjan van Wingerde, July 1996
22  * Rewritten by Martin Mares, April 1997
23  * Substantially overhauled by H. Peter Anvin, April 2007
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/sysmacros.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36 #include <asm/boot.h>
37
38 typedef unsigned char  u8;
39 typedef unsigned short u16;
40 typedef unsigned long  u32;
41
42 #define DEFAULT_MAJOR_ROOT 0
43 #define DEFAULT_MINOR_ROOT 0
44
45 /* Minimal number of setup sectors */
46 #define SETUP_SECT_MIN 5
47 #define SETUP_SECT_MAX 64
48
49 /* This must be large enough to hold the entire setup */
50 u8 buf[SETUP_SECT_MAX*512];
51 int is_big_kernel;
52
53 /*----------------------------------------------------------------------*/
54
55 static const u32 crctab32[] = {
56         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
57         0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
58         0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
59         0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
60         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
61         0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
62         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
63         0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
64         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
65         0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
66         0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
67         0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
68         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
69         0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
70         0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
71         0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
72         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
73         0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
74         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
75         0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
76         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
77         0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
78         0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
79         0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
80         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
81         0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
82         0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
83         0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
84         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
85         0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
86         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
87         0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
88         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
89         0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
90         0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
91         0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
92         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
93         0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
94         0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
95         0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
96         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
97         0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
98         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
99         0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
100         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
101         0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
102         0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
103         0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
104         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
105         0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
106         0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
107         0x2d02ef8d
108 };
109
110 static u32 partial_crc32_one(u8 c, u32 crc)
111 {
112         return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
113 }
114
115 static u32 partial_crc32(const u8 *s, int len, u32 crc)
116 {
117         while (len--)
118                 crc = partial_crc32_one(*s++, crc);
119         return crc;
120 }
121
122 static void die(const char * str, ...)
123 {
124         va_list args;
125         va_start(args, str);
126         vfprintf(stderr, str, args);
127         fputc('\n', stderr);
128         exit(1);
129 }
130
131 static void usage(void)
132 {
133         die("Usage: build [-b] setup system [rootdev] [> image]");
134 }
135
136 int main(int argc, char ** argv)
137 {
138         unsigned int i, sz, setup_sectors;
139         int c;
140         u32 sys_size;
141         u8 major_root, minor_root;
142         struct stat sb;
143         FILE *file;
144         int fd;
145         void *kernel;
146         u32 crc = 0xffffffffUL;
147
148         if (argc > 2 && !strcmp(argv[1], "-b"))
149           {
150             is_big_kernel = 1;
151             argc--, argv++;
152           }
153         if ((argc < 3) || (argc > 4))
154                 usage();
155         if (argc > 3) {
156                 if (!strcmp(argv[3], "CURRENT")) {
157                         if (stat("/", &sb)) {
158                                 perror("/");
159                                 die("Couldn't stat /");
160                         }
161                         major_root = major(sb.st_dev);
162                         minor_root = minor(sb.st_dev);
163                 } else if (strcmp(argv[3], "FLOPPY")) {
164                         if (stat(argv[3], &sb)) {
165                                 perror(argv[3]);
166                                 die("Couldn't stat root device.");
167                         }
168                         major_root = major(sb.st_rdev);
169                         minor_root = minor(sb.st_rdev);
170                 } else {
171                         major_root = 0;
172                         minor_root = 0;
173                 }
174         } else {
175                 major_root = DEFAULT_MAJOR_ROOT;
176                 minor_root = DEFAULT_MINOR_ROOT;
177         }
178         fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
179
180         /* Copy the setup code */
181         file = fopen(argv[1], "r");
182         if (!file)
183                 die("Unable to open `%s': %m", argv[1]);
184         c = fread(buf, 1, sizeof(buf), file);
185         if (ferror(file))
186                 die("read-error on `setup'");
187         if (c < 1024)
188                 die("The setup must be at least 1024 bytes");
189         if (buf[510] != 0x55 || buf[511] != 0xaa)
190                 die("Boot block hasn't got boot flag (0xAA55)");
191         fclose(file);
192
193         /* Pad unused space with zeros */
194         setup_sectors = (c + 511) / 512;
195         if (setup_sectors < SETUP_SECT_MIN)
196                 setup_sectors = SETUP_SECT_MIN;
197         i = setup_sectors*512;
198         memset(buf+c, 0, i-c);
199
200         /* Set the default root device */
201         buf[508] = minor_root;
202         buf[509] = major_root;
203
204         fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
205
206         /* Open and stat the kernel file */
207         fd = open(argv[2], O_RDONLY);
208         if (fd < 0)
209                 die("Unable to open `%s': %m", argv[2]);
210         if (fstat(fd, &sb))
211                 die("Unable to stat `%s': %m", argv[2]);
212         sz = sb.st_size;
213         fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
214         kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
215         if (kernel == MAP_FAILED)
216                 die("Unable to mmap '%s': %m", argv[2]);
217         /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
218         sys_size = (sz + 15 + 4) / 16;
219         if (!is_big_kernel && sys_size > DEF_SYSSIZE)
220                 die("System is too big. Try using bzImage or modules.");
221
222         /* Patch the setup code with the appropriate size parameters */
223         buf[0x1f1] = setup_sectors-1;
224         buf[0x1f4] = sys_size;
225         buf[0x1f5] = sys_size >> 8;
226         buf[0x1f6] = sys_size >> 16;
227         buf[0x1f7] = sys_size >> 24;
228
229         crc = partial_crc32(buf, i, crc);
230         if (fwrite(buf, 1, i, stdout) != i)
231                 die("Writing setup failed");
232
233         /* Copy the kernel code */
234         crc = partial_crc32(kernel, sz, crc);
235         if (fwrite(kernel, 1, sz, stdout) != sz)
236                 die("Writing kernel failed");
237
238         /* Add padding leaving 4 bytes for the checksum */
239         while (sz++ < (sys_size*16) - 4) {
240                 crc = partial_crc32_one('\0', crc);
241                 if (fwrite("\0", 1, 1, stdout) != 1)
242                         die("Writing padding failed");
243         }
244
245         /* Write the CRC */
246         fprintf(stderr, "CRC %lx\n", crc);
247         if (fwrite(&crc, 1, 4, stdout) != 4)
248                 die("Writing CRC failed");
249
250         close(fd);
251
252         /* Everything is OK */
253         return 0;
254 }