1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
37typedef unsigned char u8;
38typedef unsigned short u16;
39typedef 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
46#define SETUP_SECT_MIN 5
47#define SETUP_SECT_MAX 64
48
49
50u8 buf[SETUP_SECT_MAX*512];
51int is_big_kernel;
52
53#define PECOFF_RELOC_RESERVE 0x20
54
55unsigned long efi_stub_entry;
56unsigned long efi_pe_entry;
57unsigned long startup_64;
58
59
60
61static const u32 crctab32[] = {
62 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
63 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
64 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
65 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
66 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
67 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
68 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
69 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
70 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
71 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
72 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
73 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
74 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
75 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
76 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
77 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
78 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
79 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
80 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
81 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
82 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
83 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
84 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
85 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
86 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
87 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
88 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
89 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
90 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
91 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
92 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
93 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
94 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
95 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
96 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
97 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
98 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
99 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
100 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
101 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
102 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
103 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
104 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
105 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
106 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
107 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
108 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
109 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
110 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
111 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
112 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
113 0x2d02ef8d
114};
115
116static u32 partial_crc32_one(u8 c, u32 crc)
117{
118 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
119}
120
121static u32 partial_crc32(const u8 *s, int len, u32 crc)
122{
123 while (len--)
124 crc = partial_crc32_one(*s++, crc);
125 return crc;
126}
127
128static void die(const char * str, ...)
129{
130 va_list args;
131 va_start(args, str);
132 vfprintf(stderr, str, args);
133 fputc('\n', stderr);
134 exit(1);
135}
136
137static void usage(void)
138{
139 die("Usage: build setup system [zoffset.h] [> image]");
140}
141
142#ifdef CONFIG_EFI_STUB
143
144static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
145{
146 unsigned int pe_header;
147 unsigned short num_sections;
148 u8 *section;
149
150 pe_header = get_unaligned_le32(&buf[0x3c]);
151 num_sections = get_unaligned_le16(&buf[pe_header + 6]);
152
153#ifdef CONFIG_X86_32
154 section = &buf[pe_header + 0xa8];
155#else
156 section = &buf[pe_header + 0xb8];
157#endif
158
159 while (num_sections > 0) {
160 if (strncmp((char*)section, section_name, 8) == 0) {
161
162 put_unaligned_le32(size, section + 0x8);
163
164
165 put_unaligned_le32(offset, section + 0xc);
166
167
168 put_unaligned_le32(size, section + 0x10);
169
170
171 put_unaligned_le32(offset, section + 0x14);
172
173 break;
174 }
175 section += 0x28;
176 num_sections--;
177 }
178}
179
180static void update_pecoff_setup_and_reloc(unsigned int size)
181{
182 u32 setup_offset = 0x200;
183 u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
184 u32 setup_size = reloc_offset - setup_offset;
185
186 update_pecoff_section_header(".setup", setup_offset, setup_size);
187 update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
188
189
190
191
192
193 put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
194 put_unaligned_le32(10, &buf[reloc_offset + 4]);
195}
196
197static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
198{
199 unsigned int pe_header;
200 unsigned int text_sz = file_sz - text_start;
201
202 pe_header = get_unaligned_le32(&buf[0x3c]);
203
204
205 put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
206
207
208
209
210
211 put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
212
213
214
215
216 put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
217
218 update_pecoff_section_header(".text", text_start, text_sz);
219}
220
221#endif
222
223
224
225
226
227
228
229#define PARSE_ZOFS(p, sym) do { \
230 if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \
231 sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \
232} while (0)
233
234static void parse_zoffset(char *fname)
235{
236 FILE *file;
237 char *p;
238 int c;
239
240 file = fopen(fname, "r");
241 if (!file)
242 die("Unable to open `%s': %m", fname);
243 c = fread(buf, 1, sizeof(buf) - 1, file);
244 if (ferror(file))
245 die("read-error on `zoffset.h'");
246 fclose(file);
247 buf[c] = 0;
248
249 p = (char *)buf;
250
251 while (p && *p) {
252 PARSE_ZOFS(p, efi_stub_entry);
253 PARSE_ZOFS(p, efi_pe_entry);
254 PARSE_ZOFS(p, startup_64);
255
256 p = strchr(p, '\n');
257 while (p && (*p == '\r' || *p == '\n'))
258 p++;
259 }
260}
261
262int main(int argc, char ** argv)
263{
264 unsigned int i, sz, setup_sectors;
265 int c;
266 u32 sys_size;
267 struct stat sb;
268 FILE *file;
269 int fd;
270 void *kernel;
271 u32 crc = 0xffffffffUL;
272
273
274#ifdef CONFIG_X86_32
275 efi_pe_entry = 0x10;
276 efi_stub_entry = 0x30;
277#else
278 efi_pe_entry = 0x210;
279 efi_stub_entry = 0x230;
280 startup_64 = 0x200;
281#endif
282
283 if (argc == 4)
284 parse_zoffset(argv[3]);
285 else if (argc != 3)
286 usage();
287
288
289 file = fopen(argv[1], "r");
290 if (!file)
291 die("Unable to open `%s': %m", argv[1]);
292 c = fread(buf, 1, sizeof(buf), file);
293 if (ferror(file))
294 die("read-error on `setup'");
295 if (c < 1024)
296 die("The setup must be at least 1024 bytes");
297 if (get_unaligned_le16(&buf[510]) != 0xAA55)
298 die("Boot block hasn't got boot flag (0xAA55)");
299 fclose(file);
300
301#ifdef CONFIG_EFI_STUB
302
303 memset(buf+c, 0, PECOFF_RELOC_RESERVE);
304 c += PECOFF_RELOC_RESERVE;
305#endif
306
307
308 setup_sectors = (c + 511) / 512;
309 if (setup_sectors < SETUP_SECT_MIN)
310 setup_sectors = SETUP_SECT_MIN;
311 i = setup_sectors*512;
312 memset(buf+c, 0, i-c);
313
314#ifdef CONFIG_EFI_STUB
315 update_pecoff_setup_and_reloc(i);
316#endif
317
318
319 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
320
321 fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
322
323
324 fd = open(argv[2], O_RDONLY);
325 if (fd < 0)
326 die("Unable to open `%s': %m", argv[2]);
327 if (fstat(fd, &sb))
328 die("Unable to stat `%s': %m", argv[2]);
329 sz = sb.st_size;
330 fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
331 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
332 if (kernel == MAP_FAILED)
333 die("Unable to mmap '%s': %m", argv[2]);
334
335 sys_size = (sz + 15 + 4) / 16;
336
337
338 buf[0x1f1] = setup_sectors-1;
339 put_unaligned_le32(sys_size, &buf[0x1f4]);
340
341#ifdef CONFIG_EFI_STUB
342 update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
343
344#ifdef CONFIG_X86_64
345 efi_stub_entry -= 0x200;
346#endif
347 put_unaligned_le32(efi_stub_entry, &buf[0x264]);
348#endif
349
350 crc = partial_crc32(buf, i, crc);
351 if (fwrite(buf, 1, i, stdout) != i)
352 die("Writing setup failed");
353
354
355 crc = partial_crc32(kernel, sz, crc);
356 if (fwrite(kernel, 1, sz, stdout) != sz)
357 die("Writing kernel failed");
358
359
360 while (sz++ < (sys_size*16) - 4) {
361 crc = partial_crc32_one('\0', crc);
362 if (fwrite("\0", 1, 1, stdout) != 1)
363 die("Writing padding failed");
364 }
365
366
367 fprintf(stderr, "CRC %x\n", crc);
368 put_unaligned_le32(crc, buf);
369 if (fwrite(buf, 1, 4, stdout) != 4)
370 die("Writing CRC failed");
371
372 close(fd);
373
374
375 return 0;
376}
377