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 /*----------------------------------------------------------------------*/
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 
partial_crc32_one(u8 c,u32 crc)110 static u32 partial_crc32_one(u8 c, u32 crc)
111 {
112 	return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
113 }
114 
partial_crc32(const u8 * s,int len,u32 crc)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 
die(const char * str,...)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 
usage(void)131 static void usage(void)
132 {
133 	die("Usage: build setup system [> image]");
134 }
135 
main(int argc,char ** argv)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 (get_unaligned_le16(&buf[510]) != 0xAA55)
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 	put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
175 
176 	fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
177 
178 	/* Open and stat the kernel file */
179 	fd = open(argv[2], O_RDONLY);
180 	if (fd < 0)
181 		die("Unable to open `%s': %m", argv[2]);
182 	if (fstat(fd, &sb))
183 		die("Unable to stat `%s': %m", argv[2]);
184 	sz = sb.st_size;
185 	fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
186 	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
187 	if (kernel == MAP_FAILED)
188 		die("Unable to mmap '%s': %m", argv[2]);
189 	/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
190 	sys_size = (sz + 15 + 4) / 16;
191 
192 	/* Patch the setup code with the appropriate size parameters */
193 	buf[0x1f1] = setup_sectors-1;
194 	put_unaligned_le32(sys_size, &buf[0x1f4]);
195 
196 #ifdef CONFIG_EFI_STUB
197 	file_sz = sz + i + ((sys_size * 16) - sz);
198 
199 	pe_header = get_unaligned_le32(&buf[0x3c]);
200 
201 	/* Size of code */
202 	put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
203 
204 	/* Size of image */
205 	put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
206 
207 #ifdef CONFIG_X86_32
208 	/*
209 	 * Address of entry point.
210 	 *
211 	 * The EFI stub entry point is +16 bytes from the start of
212 	 * the .text section.
213 	 */
214 	put_unaligned_le32(i + 16, &buf[pe_header + 0x28]);
215 
216 	/* .text size */
217 	put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
218 
219 	/* .text size of initialised data */
220 	put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]);
221 #else
222 	/*
223 	 * Address of entry point. startup_32 is at the beginning and
224 	 * the 64-bit entry point (startup_64) is always 512 bytes
225 	 * after. The EFI stub entry point is 16 bytes after that, as
226 	 * the first instruction allows legacy loaders to jump over
227 	 * the EFI stub initialisation
228 	 */
229 	put_unaligned_le32(i + 528, &buf[pe_header + 0x28]);
230 
231 	/* .text size */
232 	put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
233 
234 	/* .text size of initialised data */
235 	put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]);
236 
237 #endif /* CONFIG_X86_32 */
238 #endif /* CONFIG_EFI_STUB */
239 
240 	crc = partial_crc32(buf, i, crc);
241 	if (fwrite(buf, 1, i, stdout) != i)
242 		die("Writing setup failed");
243 
244 	/* Copy the kernel code */
245 	crc = partial_crc32(kernel, sz, crc);
246 	if (fwrite(kernel, 1, sz, stdout) != sz)
247 		die("Writing kernel failed");
248 
249 	/* Add padding leaving 4 bytes for the checksum */
250 	while (sz++ < (sys_size*16) - 4) {
251 		crc = partial_crc32_one('\0', crc);
252 		if (fwrite("\0", 1, 1, stdout) != 1)
253 			die("Writing padding failed");
254 	}
255 
256 	/* Write the CRC */
257 	fprintf(stderr, "CRC %x\n", crc);
258 	put_unaligned_le32(crc, buf);
259 	if (fwrite(buf, 1, 4, stdout) != 4)
260 		die("Writing CRC failed");
261 
262 	close(fd);
263 
264 	/* Everything is OK */
265 	return 0;
266 }
267