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