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