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