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