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