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
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
124static void die(const char * str, ...)
125{
126 va_list args;
127 va_start(args, str);
128 vfprintf(stderr, str, args);
129 fputc('\n', stderr);
130 exit(1);
131}
132
133static void usage(void)
134{
135 die("Usage: build setup system [> image]");
136}
137
138#ifdef CONFIG_EFI_STUB
139
140static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
141{
142 unsigned int pe_header;
143 unsigned short num_sections;
144 u8 *section;
145
146 pe_header = get_unaligned_le32(&buf[0x3c]);
147 num_sections = get_unaligned_le16(&buf[pe_header + 6]);
148
149#ifdef CONFIG_X86_32
150 section = &buf[pe_header + 0xa8];
151#else
152 section = &buf[pe_header + 0xb8];
153#endif
154
155 while (num_sections > 0) {
156 if (strncmp((char*)section, section_name, 8) == 0) {
157
158 put_unaligned_le32(size, section + 0x8);
159
160
161 put_unaligned_le32(offset, section + 0xc);
162
163
164 put_unaligned_le32(size, section + 0x10);
165
166
167 put_unaligned_le32(offset, section + 0x14);
168
169 break;
170 }
171 section += 0x28;
172 num_sections--;
173 }
174}
175
176static void update_pecoff_setup_and_reloc(unsigned int size)
177{
178 u32 setup_offset = 0x200;
179 u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
180 u32 setup_size = reloc_offset - setup_offset;
181
182 update_pecoff_section_header(".setup", setup_offset, setup_size);
183 update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
184
185
186
187
188
189 put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
190 put_unaligned_le32(10, &buf[reloc_offset + 4]);
191}
192
193static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
194{
195 unsigned int pe_header;
196 unsigned int text_sz = file_sz - text_start;
197
198 pe_header = get_unaligned_le32(&buf[0x3c]);
199
200
201 put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
202
203
204
205
206
207 put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
208
209#ifdef CONFIG_X86_32
210
211
212
213
214
215
216 put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
217#else
218
219
220
221
222
223
224
225 put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
226#endif
227
228 update_pecoff_section_header(".text", text_start, text_sz);
229}
230
231#endif
232
233int main(int argc, char ** argv)
234{
235 unsigned int i, sz, setup_sectors;
236 int c;
237 u32 sys_size;
238 struct stat sb;
239 FILE *file;
240 int fd;
241 void *kernel;
242 u32 crc = 0xffffffffUL;
243
244 if (argc != 3)
245 usage();
246
247
248 file = fopen(argv[1], "r");
249 if (!file)
250 die("Unable to open `%s': %m", argv[1]);
251 c = fread(buf, 1, sizeof(buf), file);
252 if (ferror(file))
253 die("read-error on `setup'");
254 if (c < 1024)
255 die("The setup must be at least 1024 bytes");
256 if (get_unaligned_le16(&buf[510]) != 0xAA55)
257 die("Boot block hasn't got boot flag (0xAA55)");
258 fclose(file);
259
260#ifdef CONFIG_EFI_STUB
261
262 memset(buf+c, 0, PECOFF_RELOC_RESERVE);
263 c += PECOFF_RELOC_RESERVE;
264#endif
265
266
267 setup_sectors = (c + 511) / 512;
268 if (setup_sectors < SETUP_SECT_MIN)
269 setup_sectors = SETUP_SECT_MIN;
270 i = setup_sectors*512;
271 memset(buf+c, 0, i-c);
272
273#ifdef CONFIG_EFI_STUB
274 update_pecoff_setup_and_reloc(i);
275#endif
276
277
278 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
279
280 fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
281
282
283 fd = open(argv[2], O_RDONLY);
284 if (fd < 0)
285 die("Unable to open `%s': %m", argv[2]);
286 if (fstat(fd, &sb))
287 die("Unable to stat `%s': %m", argv[2]);
288 sz = sb.st_size;
289 fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
290 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
291 if (kernel == MAP_FAILED)
292 die("Unable to mmap '%s': %m", argv[2]);
293
294 sys_size = (sz + 15 + 4) / 16;
295
296
297 buf[0x1f1] = setup_sectors-1;
298 put_unaligned_le32(sys_size, &buf[0x1f4]);
299
300#ifdef CONFIG_EFI_STUB
301 update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
302#endif
303
304 crc = partial_crc32(buf, i, crc);
305 if (fwrite(buf, 1, i, stdout) != i)
306 die("Writing setup failed");
307
308
309 crc = partial_crc32(kernel, sz, crc);
310 if (fwrite(kernel, 1, sz, stdout) != sz)
311 die("Writing kernel failed");
312
313
314 while (sz++ < (sys_size*16) - 4) {
315 crc = partial_crc32_one('\0', crc);
316 if (fwrite("\0", 1, 1, stdout) != 1)
317 die("Writing padding failed");
318 }
319
320
321 fprintf(stderr, "CRC %x\n", crc);
322 put_unaligned_le32(crc, buf);
323 if (fwrite(buf, 1, 4, stdout) != 4)
324 die("Writing CRC failed");
325
326 close(fd);
327
328
329 return 0;
330}
331