4b8e165ee5723643dcd89619a341c7559eafe2bd
[~shefty/rdma-dev.git] / 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 <unistd.h>
33 #include <fcntl.h>
34 #include <sys/mman.h>
35 #include <tools/le_byteshift.h>
36
37 typedef unsigned char  u8;
38 typedef unsigned short u16;
39 typedef unsigned int   u32;
40
41 #define DEFAULT_MAJOR_ROOT 0
42 #define DEFAULT_MINOR_ROOT 0
43 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
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 #define PECOFF_RELOC_RESERVE 0x20
54
55 /*----------------------------------------------------------------------*/
56
57 static const u32 crctab32[] = {
58         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
59         0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
60         0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
61         0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
62         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
63         0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
64         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
65         0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
66         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
67         0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
68         0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
69         0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
70         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
71         0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
72         0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
73         0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
74         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
75         0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
76         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
77         0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
78         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
79         0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
80         0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
81         0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
82         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
83         0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
84         0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
85         0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
86         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
87         0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
88         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
89         0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
90         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
91         0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
92         0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
93         0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
94         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
95         0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
96         0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
97         0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
98         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
99         0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
100         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
101         0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
102         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
103         0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
104         0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
105         0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
106         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
107         0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
108         0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
109         0x2d02ef8d
110 };
111
112 static u32 partial_crc32_one(u8 c, u32 crc)
113 {
114         return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
115 }
116
117 static u32 partial_crc32(const u8 *s, int len, u32 crc)
118 {
119         while (len--)
120                 crc = partial_crc32_one(*s++, crc);
121         return crc;
122 }
123
124 static void die(const char * str, ...)
125 {
126         va_list args;
127         va_start(args, str);
128         vfprintf(stderr, str, args);
129         fputc('\n', stderr);
130         exit(1);
131 }
132
133 static void usage(void)
134 {
135         die("Usage: build setup system [> image]");
136 }
137
138 #ifdef CONFIG_EFI_STUB
139
140 static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
141 {
142         unsigned int pe_header;
143         unsigned short num_sections;
144         u8 *section;
145
146         pe_header = get_unaligned_le32(&buf[0x3c]);
147         num_sections = get_unaligned_le16(&buf[pe_header + 6]);
148
149 #ifdef CONFIG_X86_32
150         section = &buf[pe_header + 0xa8];
151 #else
152         section = &buf[pe_header + 0xb8];
153 #endif
154
155         while (num_sections > 0) {
156                 if (strncmp((char*)section, section_name, 8) == 0) {
157                         /* section header size field */
158                         put_unaligned_le32(size, section + 0x8);
159
160                         /* section header vma field */
161                         put_unaligned_le32(offset, section + 0xc);
162
163                         /* section header 'size of initialised data' field */
164                         put_unaligned_le32(size, section + 0x10);
165
166                         /* section header 'file offset' field */
167                         put_unaligned_le32(offset, section + 0x14);
168
169                         break;
170                 }
171                 section += 0x28;
172                 num_sections--;
173         }
174 }
175
176 static void update_pecoff_setup_and_reloc(unsigned int size)
177 {
178         u32 setup_offset = 0x200;
179         u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
180         u32 setup_size = reloc_offset - setup_offset;
181
182         update_pecoff_section_header(".setup", setup_offset, setup_size);
183         update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
184
185         /*
186          * Modify .reloc section contents with a single entry. The
187          * relocation is applied to offset 10 of the relocation section.
188          */
189         put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
190         put_unaligned_le32(10, &buf[reloc_offset + 4]);
191 }
192
193 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
194 {
195         unsigned int pe_header;
196         unsigned int text_sz = file_sz - text_start;
197
198         pe_header = get_unaligned_le32(&buf[0x3c]);
199
200         /* Size of image */
201         put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
202
203         /*
204          * Size of code: Subtract the size of the first sector (512 bytes)
205          * which includes the header.
206          */
207         put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
208
209 #ifdef CONFIG_X86_32
210         /*
211          * Address of entry point.
212          *
213          * The EFI stub entry point is +16 bytes from the start of
214          * the .text section.
215          */
216         put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
217 #else
218         /*
219          * Address of entry point. startup_32 is at the beginning and
220          * the 64-bit entry point (startup_64) is always 512 bytes
221          * after. The EFI stub entry point is 16 bytes after that, as
222          * the first instruction allows legacy loaders to jump over
223          * the EFI stub initialisation
224          */
225         put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
226 #endif /* CONFIG_X86_32 */
227
228         update_pecoff_section_header(".text", text_start, text_sz);
229 }
230
231 #endif /* CONFIG_EFI_STUB */
232
233 int main(int argc, char ** argv)
234 {
235         unsigned int i, sz, setup_sectors;
236         int c;
237         u32 sys_size;
238         struct stat sb;
239         FILE *file;
240         int fd;
241         void *kernel;
242         u32 crc = 0xffffffffUL;
243
244         if (argc != 3)
245                 usage();
246
247         /* Copy the setup code */
248         file = fopen(argv[1], "r");
249         if (!file)
250                 die("Unable to open `%s': %m", argv[1]);
251         c = fread(buf, 1, sizeof(buf), file);
252         if (ferror(file))
253                 die("read-error on `setup'");
254         if (c < 1024)
255                 die("The setup must be at least 1024 bytes");
256         if (get_unaligned_le16(&buf[510]) != 0xAA55)
257                 die("Boot block hasn't got boot flag (0xAA55)");
258         fclose(file);
259
260 #ifdef CONFIG_EFI_STUB
261         /* Reserve 0x20 bytes for .reloc section */
262         memset(buf+c, 0, PECOFF_RELOC_RESERVE);
263         c += PECOFF_RELOC_RESERVE;
264 #endif
265
266         /* Pad unused space with zeros */
267         setup_sectors = (c + 511) / 512;
268         if (setup_sectors < SETUP_SECT_MIN)
269                 setup_sectors = SETUP_SECT_MIN;
270         i = setup_sectors*512;
271         memset(buf+c, 0, i-c);
272
273 #ifdef CONFIG_EFI_STUB
274         update_pecoff_setup_and_reloc(i);
275 #endif
276
277         /* Set the default root device */
278         put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
279
280         fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
281
282         /* Open and stat the kernel file */
283         fd = open(argv[2], O_RDONLY);
284         if (fd < 0)
285                 die("Unable to open `%s': %m", argv[2]);
286         if (fstat(fd, &sb))
287                 die("Unable to stat `%s': %m", argv[2]);
288         sz = sb.st_size;
289         fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
290         kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
291         if (kernel == MAP_FAILED)
292                 die("Unable to mmap '%s': %m", argv[2]);
293         /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
294         sys_size = (sz + 15 + 4) / 16;
295
296         /* Patch the setup code with the appropriate size parameters */
297         buf[0x1f1] = setup_sectors-1;
298         put_unaligned_le32(sys_size, &buf[0x1f4]);
299
300 #ifdef CONFIG_EFI_STUB
301         update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
302 #endif
303
304         crc = partial_crc32(buf, i, crc);
305         if (fwrite(buf, 1, i, stdout) != i)
306                 die("Writing setup failed");
307
308         /* Copy the kernel code */
309         crc = partial_crc32(kernel, sz, crc);
310         if (fwrite(kernel, 1, sz, stdout) != sz)
311                 die("Writing kernel failed");
312
313         /* Add padding leaving 4 bytes for the checksum */
314         while (sz++ < (sys_size*16) - 4) {
315                 crc = partial_crc32_one('\0', crc);
316                 if (fwrite("\0", 1, 1, stdout) != 1)
317                         die("Writing padding failed");
318         }
319
320         /* Write the CRC */
321         fprintf(stderr, "CRC %x\n", crc);
322         put_unaligned_le32(crc, buf);
323         if (fwrite(buf, 1, 4, stdout) != 4)
324                 die("Writing CRC failed");
325
326         close(fd);
327
328         /* Everything is OK */
329         return 0;
330 }