x86, efi: Fix endian issues and unaligned accesses
[deliverable/linux.git] / arch / x86 / boot / tools / build.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 1997 Martin Mares
4fd06960 4 * Copyright (C) 2007 H. Peter Anvin
1da177e4
LT
5 */
6
7/*
9aa3909c 8 * This file builds a disk-image from two different files:
1da177e4 9 *
1da177e4
LT
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
4fd06960 23 * Substantially overhauled by H. Peter Anvin, April 2007
1da177e4
LT
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>
4fd06960 35#include <sys/mman.h>
1da177e4 36#include <asm/boot.h>
92f42c50 37#include <tools/le_byteshift.h>
1da177e4 38
4fd06960
PA
39typedef unsigned char u8;
40typedef unsigned short u16;
41typedef unsigned long u32;
1da177e4
LT
42
43#define DEFAULT_MAJOR_ROOT 0
44#define DEFAULT_MINOR_ROOT 0
92f42c50 45#define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
1da177e4 46
4fd06960
PA
47/* Minimal number of setup sectors */
48#define SETUP_SECT_MIN 5
49#define SETUP_SECT_MAX 64
1da177e4 50
4fd06960
PA
51/* This must be large enough to hold the entire setup */
52u8 buf[SETUP_SECT_MAX*512];
1da177e4
LT
53int is_big_kernel;
54
7d6e737c
IC
55/*----------------------------------------------------------------------*/
56
57static 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
112static u32 partial_crc32_one(u8 c, u32 crc)
113{
114 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
115}
116
117static 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
4fd06960 124static void die(const char * str, ...)
1da177e4
LT
125{
126 va_list args;
127 va_start(args, str);
128 vfprintf(stderr, str, args);
129 fputc('\n', stderr);
130 exit(1);
131}
132
4fd06960 133static void usage(void)
1da177e4 134{
079f85e6 135 die("Usage: build setup system [> image]");
1da177e4
LT
136}
137
138int main(int argc, char ** argv)
139{
291f3632
MF
140#ifdef CONFIG_EFI_STUB
141 unsigned int file_sz, pe_header;
142#endif
a8f50345
KZ
143 unsigned int i, sz, setup_sectors;
144 int c;
1da177e4 145 u32 sys_size;
1da177e4 146 struct stat sb;
4fd06960
PA
147 FILE *file;
148 int fd;
149 void *kernel;
7d6e737c 150 u32 crc = 0xffffffffUL;
1da177e4 151
079f85e6 152 if (argc != 3)
1da177e4 153 usage();
1da177e4 154
4fd06960
PA
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");
92f42c50 164 if (get_unaligned_le16(&buf[510]) != 0xAA55)
1da177e4 165 die("Boot block hasn't got boot flag (0xAA55)");
4fd06960
PA
166 fclose(file);
167
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);
174
175 /* Set the default root device */
92f42c50 176 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
1da177e4 177
4fd06960
PA
178 fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
179
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]);
1da177e4 186 sz = sb.st_size;
4fd06960
PA
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]);
7d6e737c
IC
191 /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
192 sys_size = (sz + 15 + 4) / 16;
4fd06960
PA
193
194 /* Patch the setup code with the appropriate size parameters */
195 buf[0x1f1] = setup_sectors-1;
92f42c50 196 put_unaligned_le32(sys_size, &buf[0x1f4]);
4fd06960 197
291f3632
MF
198#ifdef CONFIG_EFI_STUB
199 file_sz = sz + i + ((sys_size * 16) - sz);
200
92f42c50 201 pe_header = get_unaligned_le32(&buf[0x3c]);
291f3632
MF
202
203 /* Size of code */
92f42c50 204 put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]);
291f3632
MF
205
206 /* Size of image */
92f42c50 207 put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
291f3632
MF
208
209#ifdef CONFIG_X86_32
210 /* Address of entry point */
92f42c50 211 put_unaligned_le32(i, &buf[pe_header + 0x28]);
291f3632
MF
212
213 /* .text size */
92f42c50 214 put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
291f3632
MF
215
216 /* .text size of initialised data */
92f42c50 217 put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]);
291f3632
MF
218#else
219 /*
220 * Address of entry point. startup_32 is at the beginning and
221 * the 64-bit entry point (startup_64) is always 512 bytes
222 * after.
223 */
92f42c50 224 put_unaligned_le32(i + 512, &buf[pe_header + 0x28]);
291f3632
MF
225
226 /* .text size */
92f42c50 227 put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
291f3632
MF
228
229 /* .text size of initialised data */
92f42c50
MF
230 put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]);
231
291f3632
MF
232#endif /* CONFIG_X86_32 */
233#endif /* CONFIG_EFI_STUB */
234
7d6e737c 235 crc = partial_crc32(buf, i, crc);
4fd06960
PA
236 if (fwrite(buf, 1, i, stdout) != i)
237 die("Writing setup failed");
238
239 /* Copy the kernel code */
7d6e737c 240 crc = partial_crc32(kernel, sz, crc);
4fd06960
PA
241 if (fwrite(kernel, 1, sz, stdout) != sz)
242 die("Writing kernel failed");
7d6e737c
IC
243
244 /* Add padding leaving 4 bytes for the checksum */
245 while (sz++ < (sys_size*16) - 4) {
246 crc = partial_crc32_one('\0', crc);
247 if (fwrite("\0", 1, 1, stdout) != 1)
248 die("Writing padding failed");
249 }
250
251 /* Write the CRC */
252 fprintf(stderr, "CRC %lx\n", crc);
253 if (fwrite(&crc, 1, 4, stdout) != 4)
254 die("Writing CRC failed");
255
1da177e4
LT
256 close(fd);
257
4fd06960
PA
258 /* Everything is OK */
259 return 0;
1da177e4 260}
This page took 0.520402 seconds and 5 git commands to generate.