xref: /linux/arch/x86/boot/tools/build.c (revision f2ee442115c9b6219083c019939a9cc0c9abb2f8)
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 	unsigned int i, sz, setup_sectors;
139 	int c;
140 	u32 sys_size;
141 	struct stat sb;
142 	FILE *file;
143 	int fd;
144 	void *kernel;
145 	u32 crc = 0xffffffffUL;
146 
147 	if (argc != 3)
148 		usage();
149 
150 	/* Copy the setup code */
151 	file = fopen(argv[1], "r");
152 	if (!file)
153 		die("Unable to open `%s': %m", argv[1]);
154 	c = fread(buf, 1, sizeof(buf), file);
155 	if (ferror(file))
156 		die("read-error on `setup'");
157 	if (c < 1024)
158 		die("The setup must be at least 1024 bytes");
159 	if (buf[510] != 0x55 || buf[511] != 0xaa)
160 		die("Boot block hasn't got boot flag (0xAA55)");
161 	fclose(file);
162 
163 	/* Pad unused space with zeros */
164 	setup_sectors = (c + 511) / 512;
165 	if (setup_sectors < SETUP_SECT_MIN)
166 		setup_sectors = SETUP_SECT_MIN;
167 	i = setup_sectors*512;
168 	memset(buf+c, 0, i-c);
169 
170 	/* Set the default root device */
171 	buf[508] = DEFAULT_MINOR_ROOT;
172 	buf[509] = DEFAULT_MAJOR_ROOT;
173 
174 	fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
175 
176 	/* Open and stat the kernel file */
177 	fd = open(argv[2], O_RDONLY);
178 	if (fd < 0)
179 		die("Unable to open `%s': %m", argv[2]);
180 	if (fstat(fd, &sb))
181 		die("Unable to stat `%s': %m", argv[2]);
182 	sz = sb.st_size;
183 	fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
184 	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
185 	if (kernel == MAP_FAILED)
186 		die("Unable to mmap '%s': %m", argv[2]);
187 	/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
188 	sys_size = (sz + 15 + 4) / 16;
189 
190 	/* Patch the setup code with the appropriate size parameters */
191 	buf[0x1f1] = setup_sectors-1;
192 	buf[0x1f4] = sys_size;
193 	buf[0x1f5] = sys_size >> 8;
194 	buf[0x1f6] = sys_size >> 16;
195 	buf[0x1f7] = sys_size >> 24;
196 
197 	crc = partial_crc32(buf, i, crc);
198 	if (fwrite(buf, 1, i, stdout) != i)
199 		die("Writing setup failed");
200 
201 	/* Copy the kernel code */
202 	crc = partial_crc32(kernel, sz, crc);
203 	if (fwrite(kernel, 1, sz, stdout) != sz)
204 		die("Writing kernel failed");
205 
206 	/* Add padding leaving 4 bytes for the checksum */
207 	while (sz++ < (sys_size*16) - 4) {
208 		crc = partial_crc32_one('\0', crc);
209 		if (fwrite("\0", 1, 1, stdout) != 1)
210 			die("Writing padding failed");
211 	}
212 
213 	/* Write the CRC */
214 	fprintf(stderr, "CRC %lx\n", crc);
215 	if (fwrite(&crc, 1, 4, stdout) != 4)
216 		die("Writing CRC failed");
217 
218 	close(fd);
219 
220 	/* Everything is OK */
221 	return 0;
222 }
223