Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / arch / x86 / boot / tools / build.c
blob09ce870c0caf12673451407f117f4057b6b181aa
1 /*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 1997 Martin Mares
4 * Copyright (C) 2007 H. Peter Anvin
5 */
7 /*
8 * This file builds a disk-image from two different files:
10 * - setup: 8086 machine code, sets up system parm
11 * - system: 80386 code for actual system
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.
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
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 #include <tools/le_byteshift.h>
39 typedef unsigned char u8;
40 typedef unsigned short u16;
41 typedef unsigned long u32;
43 #define DEFAULT_MAJOR_ROOT 0
44 #define DEFAULT_MINOR_ROOT 0
45 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
47 /* Minimal number of setup sectors */
48 #define SETUP_SECT_MIN 5
49 #define SETUP_SECT_MAX 64
51 /* This must be large enough to hold the entire setup */
52 u8 buf[SETUP_SECT_MAX*512];
53 int is_big_kernel;
55 /*----------------------------------------------------------------------*/
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
112 static u32 partial_crc32_one(u8 c, u32 crc)
114 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
117 static u32 partial_crc32(const u8 *s, int len, u32 crc)
119 while (len--)
120 crc = partial_crc32_one(*s++, crc);
121 return crc;
124 static void die(const char * str, ...)
126 va_list args;
127 va_start(args, str);
128 vfprintf(stderr, str, args);
129 fputc('\n', stderr);
130 exit(1);
133 static void usage(void)
135 die("Usage: build setup system [> image]");
138 int main(int argc, char ** argv)
140 #ifdef CONFIG_EFI_STUB
141 unsigned int file_sz, pe_header;
142 #endif
143 unsigned int i, sz, setup_sectors;
144 int c;
145 u32 sys_size;
146 struct stat sb;
147 FILE *file;
148 int fd;
149 void *kernel;
150 u32 crc = 0xffffffffUL;
152 if (argc != 3)
153 usage();
155 /* Copy the setup code */
156 file = fopen(argv[1], "r");
157 if (!file)
158 die("Unable to open `%s': %m", argv[1]);
159 c = fread(buf, 1, sizeof(buf), file);
160 if (ferror(file))
161 die("read-error on `setup'");
162 if (c < 1024)
163 die("The setup must be at least 1024 bytes");
164 if (get_unaligned_le16(&buf[510]) != 0xAA55)
165 die("Boot block hasn't got boot flag (0xAA55)");
166 fclose(file);
168 /* Pad unused space with zeros */
169 setup_sectors = (c + 511) / 512;
170 if (setup_sectors < SETUP_SECT_MIN)
171 setup_sectors = SETUP_SECT_MIN;
172 i = setup_sectors*512;
173 memset(buf+c, 0, i-c);
175 /* Set the default root device */
176 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
178 fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
180 /* Open and stat the kernel file */
181 fd = open(argv[2], O_RDONLY);
182 if (fd < 0)
183 die("Unable to open `%s': %m", argv[2]);
184 if (fstat(fd, &sb))
185 die("Unable to stat `%s': %m", argv[2]);
186 sz = sb.st_size;
187 fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
188 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
189 if (kernel == MAP_FAILED)
190 die("Unable to mmap '%s': %m", argv[2]);
191 /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
192 sys_size = (sz + 15 + 4) / 16;
194 /* Patch the setup code with the appropriate size parameters */
195 buf[0x1f1] = setup_sectors-1;
196 put_unaligned_le32(sys_size, &buf[0x1f4]);
198 #ifdef CONFIG_EFI_STUB
199 file_sz = sz + i + ((sys_size * 16) - sz);
201 pe_header = get_unaligned_le32(&buf[0x3c]);
203 /* Size of code */
204 put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
206 /* Size of image */
207 put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
209 #ifdef CONFIG_X86_32
211 * Address of entry point.
213 * The EFI stub entry point is +16 bytes from the start of
214 * the .text section.
216 put_unaligned_le32(i + 16, &buf[pe_header + 0x28]);
218 /* .text size */
219 put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
221 /* .text size of initialised data */
222 put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]);
223 #else
225 * Address of entry point. startup_32 is at the beginning and
226 * the 64-bit entry point (startup_64) is always 512 bytes
227 * after. The EFI stub entry point is 16 bytes after that, as
228 * the first instruction allows legacy loaders to jump over
229 * the EFI stub initialisation
231 put_unaligned_le32(i + 528, &buf[pe_header + 0x28]);
233 /* .text size */
234 put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
236 /* .text size of initialised data */
237 put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]);
239 #endif /* CONFIG_X86_32 */
240 #endif /* CONFIG_EFI_STUB */
242 crc = partial_crc32(buf, i, crc);
243 if (fwrite(buf, 1, i, stdout) != i)
244 die("Writing setup failed");
246 /* Copy the kernel code */
247 crc = partial_crc32(kernel, sz, crc);
248 if (fwrite(kernel, 1, sz, stdout) != sz)
249 die("Writing kernel failed");
251 /* Add padding leaving 4 bytes for the checksum */
252 while (sz++ < (sys_size*16) - 4) {
253 crc = partial_crc32_one('\0', crc);
254 if (fwrite("\0", 1, 1, stdout) != 1)
255 die("Writing padding failed");
258 /* Write the CRC */
259 fprintf(stderr, "CRC %lx\n", crc);
260 if (fwrite(&crc, 1, 4, stdout) != 4)
261 die("Writing CRC failed");
263 close(fd);
265 /* Everything is OK */
266 return 0;