Linux-libre 4.9.30-gnu
[librecmc/linux-libre.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 three different files:
9  *
10  * - setup: 8086 machine code, sets up system parm
11  * - system: 80386 code for actual system
12  * - zoffset.h: header with ZO_* defines
13  *
14  * It does some checking that all files are of the correct type, and writes
15  * the result to the specified destination, removing headers and padding to
16  * the right amount. It also writes some system data to stdout.
17  */
18
19 /*
20  * Changes by tytso to allow root device specification
21  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
22  * Cross compiling fixes by Gertjan van Wingerde, July 1996
23  * Rewritten by Martin Mares, April 1997
24  * Substantially overhauled by H. Peter Anvin, April 2007
25  */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36 #include <tools/le_byteshift.h>
37
38 typedef unsigned char  u8;
39 typedef unsigned short u16;
40 typedef unsigned int   u32;
41
42 #define DEFAULT_MAJOR_ROOT 0
43 #define DEFAULT_MINOR_ROOT 0
44 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
45
46 /* Minimal number of setup sectors */
47 #define SETUP_SECT_MIN 5
48 #define SETUP_SECT_MAX 64
49
50 /* This must be large enough to hold the entire setup */
51 u8 buf[SETUP_SECT_MAX*512];
52
53 #define PECOFF_RELOC_RESERVE 0x20
54
55 unsigned long efi32_stub_entry;
56 unsigned long efi64_stub_entry;
57 unsigned long efi_pe_entry;
58 unsigned long startup_64;
59
60 /*----------------------------------------------------------------------*/
61
62 static const u32 crctab32[] = {
63         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
64         0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
65         0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
66         0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
67         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
68         0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
69         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
70         0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
71         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
72         0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
73         0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
74         0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
75         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
76         0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
77         0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
78         0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
79         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
80         0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
81         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
82         0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
83         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
84         0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
85         0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
86         0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
87         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
88         0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
89         0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
90         0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
91         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
92         0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
93         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
94         0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
95         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
96         0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
97         0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
98         0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
99         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
100         0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
101         0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
102         0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
103         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
104         0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
105         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
106         0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
107         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
108         0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
109         0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
110         0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
111         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
112         0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
113         0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
114         0x2d02ef8d
115 };
116
117 static u32 partial_crc32_one(u8 c, u32 crc)
118 {
119         return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
120 }
121
122 static u32 partial_crc32(const u8 *s, int len, u32 crc)
123 {
124         while (len--)
125                 crc = partial_crc32_one(*s++, crc);
126         return crc;
127 }
128
129 static void die(const char * str, ...)
130 {
131         va_list args;
132         va_start(args, str);
133         vfprintf(stderr, str, args);
134         fputc('\n', stderr);
135         exit(1);
136 }
137
138 static void usage(void)
139 {
140         die("Usage: build setup system zoffset.h image");
141 }
142
143 #ifdef CONFIG_EFI_STUB
144
145 static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
146 {
147         unsigned int pe_header;
148         unsigned short num_sections;
149         u8 *section;
150
151         pe_header = get_unaligned_le32(&buf[0x3c]);
152         num_sections = get_unaligned_le16(&buf[pe_header + 6]);
153
154 #ifdef CONFIG_X86_32
155         section = &buf[pe_header + 0xa8];
156 #else
157         section = &buf[pe_header + 0xb8];
158 #endif
159
160         while (num_sections > 0) {
161                 if (strncmp((char*)section, section_name, 8) == 0) {
162                         /* section header size field */
163                         put_unaligned_le32(size, section + 0x8);
164
165                         /* section header vma field */
166                         put_unaligned_le32(vma, section + 0xc);
167
168                         /* section header 'size of initialised data' field */
169                         put_unaligned_le32(datasz, section + 0x10);
170
171                         /* section header 'file offset' field */
172                         put_unaligned_le32(offset, section + 0x14);
173
174                         break;
175                 }
176                 section += 0x28;
177                 num_sections--;
178         }
179 }
180
181 static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
182 {
183         update_pecoff_section_header_fields(section_name, offset, size, size, offset);
184 }
185
186 static void update_pecoff_setup_and_reloc(unsigned int size)
187 {
188         u32 setup_offset = 0x200;
189         u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
190         u32 setup_size = reloc_offset - setup_offset;
191
192         update_pecoff_section_header(".setup", setup_offset, setup_size);
193         update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
194
195         /*
196          * Modify .reloc section contents with a single entry. The
197          * relocation is applied to offset 10 of the relocation section.
198          */
199         put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
200         put_unaligned_le32(10, &buf[reloc_offset + 4]);
201 }
202
203 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
204 {
205         unsigned int pe_header;
206         unsigned int text_sz = file_sz - text_start;
207
208         pe_header = get_unaligned_le32(&buf[0x3c]);
209
210         /*
211          * Size of code: Subtract the size of the first sector (512 bytes)
212          * which includes the header.
213          */
214         put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
215
216         /*
217          * Address of entry point for PE/COFF executable
218          */
219         put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
220
221         update_pecoff_section_header(".text", text_start, text_sz);
222 }
223
224 static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz)
225 {
226         unsigned int pe_header;
227         unsigned int bss_sz = init_sz - file_sz;
228
229         pe_header = get_unaligned_le32(&buf[0x3c]);
230
231         /* Size of uninitialized data */
232         put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]);
233
234         /* Size of image */
235         put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
236
237         update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0);
238 }
239
240 static int reserve_pecoff_reloc_section(int c)
241 {
242         /* Reserve 0x20 bytes for .reloc section */
243         memset(buf+c, 0, PECOFF_RELOC_RESERVE);
244         return PECOFF_RELOC_RESERVE;
245 }
246
247 static void efi_stub_defaults(void)
248 {
249         /* Defaults for old kernel */
250 #ifdef CONFIG_X86_32
251         efi_pe_entry = 0x10;
252 #else
253         efi_pe_entry = 0x210;
254         startup_64 = 0x200;
255 #endif
256 }
257
258 static void efi_stub_entry_update(void)
259 {
260         unsigned long addr = efi32_stub_entry;
261
262 #ifdef CONFIG_X86_64
263         /* Yes, this is really how we defined it :( */
264         addr = efi64_stub_entry - 0x200;
265 #endif
266
267 #ifdef CONFIG_EFI_MIXED
268         if (efi32_stub_entry != addr)
269                 die("32-bit and 64-bit EFI entry points do not match\n");
270 #endif
271         put_unaligned_le32(addr, &buf[0x264]);
272 }
273
274 #else
275
276 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
277 static inline void update_pecoff_text(unsigned int text_start,
278                                       unsigned int file_sz) {}
279 static inline void update_pecoff_bss(unsigned int file_sz,
280                                      unsigned int init_sz) {}
281 static inline void efi_stub_defaults(void) {}
282 static inline void efi_stub_entry_update(void) {}
283
284 static inline int reserve_pecoff_reloc_section(int c)
285 {
286         return 0;
287 }
288 #endif /* CONFIG_EFI_STUB */
289
290
291 /*
292  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
293  * but that would mean tools/build would have to be rebuilt every time. It's
294  * not as if parsing it is hard...
295  */
296 #define PARSE_ZOFS(p, sym) do { \
297         if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))       \
298                 sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);         \
299 } while (0)
300
301 static void parse_zoffset(char *fname)
302 {
303         FILE *file;
304         char *p;
305         int c;
306
307         file = fopen(fname, "r");
308         if (!file)
309                 die("Unable to open `%s': %m", fname);
310         c = fread(buf, 1, sizeof(buf) - 1, file);
311         if (ferror(file))
312                 die("read-error on `zoffset.h'");
313         fclose(file);
314         buf[c] = 0;
315
316         p = (char *)buf;
317
318         while (p && *p) {
319                 PARSE_ZOFS(p, efi32_stub_entry);
320                 PARSE_ZOFS(p, efi64_stub_entry);
321                 PARSE_ZOFS(p, efi_pe_entry);
322                 PARSE_ZOFS(p, startup_64);
323
324                 p = strchr(p, '\n');
325                 while (p && (*p == '\r' || *p == '\n'))
326                         p++;
327         }
328 }
329
330 int main(int argc, char ** argv)
331 {
332         unsigned int i, sz, setup_sectors, init_sz;
333         int c;
334         u32 sys_size;
335         struct stat sb;
336         FILE *file, *dest;
337         int fd;
338         void *kernel;
339         u32 crc = 0xffffffffUL;
340
341         efi_stub_defaults();
342
343         if (argc != 5)
344                 usage();
345         parse_zoffset(argv[3]);
346
347         dest = fopen(argv[4], "w");
348         if (!dest)
349                 die("Unable to write `%s': %m", argv[4]);
350
351         /* Copy the setup code */
352         file = fopen(argv[1], "r");
353         if (!file)
354                 die("Unable to open `%s': %m", argv[1]);
355         c = fread(buf, 1, sizeof(buf), file);
356         if (ferror(file))
357                 die("read-error on `setup'");
358         if (c < 1024)
359                 die("The setup must be at least 1024 bytes");
360         if (get_unaligned_le16(&buf[510]) != 0xAA55)
361                 die("Boot block hasn't got boot flag (0xAA55)");
362         fclose(file);
363
364         c += reserve_pecoff_reloc_section(c);
365
366         /* Pad unused space with zeros */
367         setup_sectors = (c + 511) / 512;
368         if (setup_sectors < SETUP_SECT_MIN)
369                 setup_sectors = SETUP_SECT_MIN;
370         i = setup_sectors*512;
371         memset(buf+c, 0, i-c);
372
373         update_pecoff_setup_and_reloc(i);
374
375         /* Set the default root device */
376         put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
377
378         printf("Setup is %d bytes (padded to %d bytes).\n", c, i);
379
380         /* Open and stat the kernel file */
381         fd = open(argv[2], O_RDONLY);
382         if (fd < 0)
383                 die("Unable to open `%s': %m", argv[2]);
384         if (fstat(fd, &sb))
385                 die("Unable to stat `%s': %m", argv[2]);
386         sz = sb.st_size;
387         printf("System is %d kB\n", (sz+1023)/1024);
388         kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
389         if (kernel == MAP_FAILED)
390                 die("Unable to mmap '%s': %m", argv[2]);
391         /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
392         sys_size = (sz + 15 + 4) / 16;
393
394         /* Patch the setup code with the appropriate size parameters */
395         buf[0x1f1] = setup_sectors-1;
396         put_unaligned_le32(sys_size, &buf[0x1f4]);
397
398         update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
399         init_sz = get_unaligned_le32(&buf[0x260]);
400         update_pecoff_bss(i + (sys_size * 16), init_sz);
401
402         efi_stub_entry_update();
403
404         crc = partial_crc32(buf, i, crc);
405         if (fwrite(buf, 1, i, dest) != i)
406                 die("Writing setup failed");
407
408         /* Copy the kernel code */
409         crc = partial_crc32(kernel, sz, crc);
410         if (fwrite(kernel, 1, sz, dest) != sz)
411                 die("Writing kernel failed");
412
413         /* Add padding leaving 4 bytes for the checksum */
414         while (sz++ < (sys_size*16) - 4) {
415                 crc = partial_crc32_one('\0', crc);
416                 if (fwrite("\0", 1, 1, dest) != 1)
417                         die("Writing padding failed");
418         }
419
420         /* Write the CRC */
421         printf("CRC %x\n", crc);
422         put_unaligned_le32(crc, buf);
423         if (fwrite(buf, 1, 4, dest) != 4)
424                 die("Writing CRC failed");
425
426         /* Catch any delayed write failures */
427         if (fclose(dest))
428                 die("Writing image failed");
429
430         close(fd);
431
432         /* Everything is OK */
433         return 0;
434 }