xref: /openbmc/linux/arch/x86/boot/tools/build.c (revision 6e2055a9)
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 int is_big_kernel;
53 
54 #define PECOFF_RELOC_RESERVE 0x20
55 
56 unsigned long efi_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(char *section_name, u32 offset, u32 size)
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(offset, section + 0xc);
167 
168 			/* section header 'size of initialised data' field */
169 			put_unaligned_le32(size, 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_setup_and_reloc(unsigned int size)
182 {
183 	u32 setup_offset = 0x200;
184 	u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
185 	u32 setup_size = reloc_offset - setup_offset;
186 
187 	update_pecoff_section_header(".setup", setup_offset, setup_size);
188 	update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
189 
190 	/*
191 	 * Modify .reloc section contents with a single entry. The
192 	 * relocation is applied to offset 10 of the relocation section.
193 	 */
194 	put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
195 	put_unaligned_le32(10, &buf[reloc_offset + 4]);
196 }
197 
198 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
199 {
200 	unsigned int pe_header;
201 	unsigned int text_sz = file_sz - text_start;
202 
203 	pe_header = get_unaligned_le32(&buf[0x3c]);
204 
205 	/* Size of image */
206 	put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
207 
208 	/*
209 	 * Size of code: Subtract the size of the first sector (512 bytes)
210 	 * which includes the header.
211 	 */
212 	put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
213 
214 	/*
215 	 * Address of entry point for PE/COFF executable
216 	 */
217 	put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
218 
219 	update_pecoff_section_header(".text", text_start, text_sz);
220 }
221 
222 #endif /* CONFIG_EFI_STUB */
223 
224 
225 /*
226  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
227  * but that would mean tools/build would have to be rebuilt every time. It's
228  * not as if parsing it is hard...
229  */
230 #define PARSE_ZOFS(p, sym) do { \
231 	if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))	\
232 		sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);		\
233 } while (0)
234 
235 static void parse_zoffset(char *fname)
236 {
237 	FILE *file;
238 	char *p;
239 	int c;
240 
241 	file = fopen(fname, "r");
242 	if (!file)
243 		die("Unable to open `%s': %m", fname);
244 	c = fread(buf, 1, sizeof(buf) - 1, file);
245 	if (ferror(file))
246 		die("read-error on `zoffset.h'");
247 	fclose(file);
248 	buf[c] = 0;
249 
250 	p = (char *)buf;
251 
252 	while (p && *p) {
253 		PARSE_ZOFS(p, efi_stub_entry);
254 		PARSE_ZOFS(p, efi_pe_entry);
255 		PARSE_ZOFS(p, startup_64);
256 
257 		p = strchr(p, '\n');
258 		while (p && (*p == '\r' || *p == '\n'))
259 			p++;
260 	}
261 }
262 
263 int main(int argc, char ** argv)
264 {
265 	unsigned int i, sz, setup_sectors;
266 	int c;
267 	u32 sys_size;
268 	struct stat sb;
269 	FILE *file, *dest;
270 	int fd;
271 	void *kernel;
272 	u32 crc = 0xffffffffUL;
273 
274 	/* Defaults for old kernel */
275 #ifdef CONFIG_X86_32
276 	efi_pe_entry = 0x10;
277 	efi_stub_entry = 0x30;
278 #else
279 	efi_pe_entry = 0x210;
280 	efi_stub_entry = 0x230;
281 	startup_64 = 0x200;
282 #endif
283 
284 	if (argc != 5)
285 		usage();
286 	parse_zoffset(argv[3]);
287 
288 	dest = fopen(argv[4], "w");
289 	if (!dest)
290 		die("Unable to write `%s': %m", argv[4]);
291 
292 	/* Copy the setup code */
293 	file = fopen(argv[1], "r");
294 	if (!file)
295 		die("Unable to open `%s': %m", argv[1]);
296 	c = fread(buf, 1, sizeof(buf), file);
297 	if (ferror(file))
298 		die("read-error on `setup'");
299 	if (c < 1024)
300 		die("The setup must be at least 1024 bytes");
301 	if (get_unaligned_le16(&buf[510]) != 0xAA55)
302 		die("Boot block hasn't got boot flag (0xAA55)");
303 	fclose(file);
304 
305 #ifdef CONFIG_EFI_STUB
306 	/* Reserve 0x20 bytes for .reloc section */
307 	memset(buf+c, 0, PECOFF_RELOC_RESERVE);
308 	c += PECOFF_RELOC_RESERVE;
309 #endif
310 
311 	/* Pad unused space with zeros */
312 	setup_sectors = (c + 511) / 512;
313 	if (setup_sectors < SETUP_SECT_MIN)
314 		setup_sectors = SETUP_SECT_MIN;
315 	i = setup_sectors*512;
316 	memset(buf+c, 0, i-c);
317 
318 #ifdef CONFIG_EFI_STUB
319 	update_pecoff_setup_and_reloc(i);
320 #endif
321 
322 	/* Set the default root device */
323 	put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
324 
325 	printf("Setup is %d bytes (padded to %d bytes).\n", c, i);
326 
327 	/* Open and stat the kernel file */
328 	fd = open(argv[2], O_RDONLY);
329 	if (fd < 0)
330 		die("Unable to open `%s': %m", argv[2]);
331 	if (fstat(fd, &sb))
332 		die("Unable to stat `%s': %m", argv[2]);
333 	sz = sb.st_size;
334 	printf("System is %d kB\n", (sz+1023)/1024);
335 	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
336 	if (kernel == MAP_FAILED)
337 		die("Unable to mmap '%s': %m", argv[2]);
338 	/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
339 	sys_size = (sz + 15 + 4) / 16;
340 
341 	/* Patch the setup code with the appropriate size parameters */
342 	buf[0x1f1] = setup_sectors-1;
343 	put_unaligned_le32(sys_size, &buf[0x1f4]);
344 
345 #ifdef CONFIG_EFI_STUB
346 	update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
347 
348 #ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */
349 	efi_stub_entry -= 0x200;
350 #endif
351 	put_unaligned_le32(efi_stub_entry, &buf[0x264]);
352 #endif
353 
354 	crc = partial_crc32(buf, i, crc);
355 	if (fwrite(buf, 1, i, dest) != i)
356 		die("Writing setup failed");
357 
358 	/* Copy the kernel code */
359 	crc = partial_crc32(kernel, sz, crc);
360 	if (fwrite(kernel, 1, sz, dest) != sz)
361 		die("Writing kernel failed");
362 
363 	/* Add padding leaving 4 bytes for the checksum */
364 	while (sz++ < (sys_size*16) - 4) {
365 		crc = partial_crc32_one('\0', crc);
366 		if (fwrite("\0", 1, 1, dest) != 1)
367 			die("Writing padding failed");
368 	}
369 
370 	/* Write the CRC */
371 	printf("CRC %x\n", crc);
372 	put_unaligned_le32(crc, buf);
373 	if (fwrite(buf, 1, 4, dest) != 4)
374 		die("Writing CRC failed");
375 
376 	/* Catch any delayed write failures */
377 	if (fclose(dest))
378 		die("Writing image failed");
379 
380 	close(fd);
381 
382 	/* Everything is OK */
383 	return 0;
384 }
385