0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <stdio.h>
0029 #include <string.h>
0030 #include <stdlib.h>
0031 #include <stdarg.h>
0032 #include <sys/types.h>
0033 #include <sys/stat.h>
0034 #include <unistd.h>
0035 #include <fcntl.h>
0036 #include <sys/mman.h>
0037 #include <tools/le_byteshift.h>
0038
0039 typedef unsigned char u8;
0040 typedef unsigned short u16;
0041 typedef unsigned int u32;
0042
0043 #define DEFAULT_MAJOR_ROOT 0
0044 #define DEFAULT_MINOR_ROOT 0
0045 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
0046
0047
0048 #define SETUP_SECT_MIN 5
0049 #define SETUP_SECT_MAX 64
0050
0051
0052 u8 buf[SETUP_SECT_MAX*512];
0053
0054 #define PECOFF_RELOC_RESERVE 0x20
0055
0056 #ifdef CONFIG_EFI_MIXED
0057 #define PECOFF_COMPAT_RESERVE 0x20
0058 #else
0059 #define PECOFF_COMPAT_RESERVE 0x0
0060 #endif
0061
0062 static unsigned long efi32_stub_entry;
0063 static unsigned long efi64_stub_entry;
0064 static unsigned long efi_pe_entry;
0065 static unsigned long efi32_pe_entry;
0066 static unsigned long kernel_info;
0067 static unsigned long startup_64;
0068 static unsigned long _ehead;
0069 static unsigned long _end;
0070
0071
0072
0073 static const u32 crctab32[] = {
0074 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0075 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0076 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
0077 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0078 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0079 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0080 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
0081 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0082 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0083 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
0084 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
0085 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0086 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
0087 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0088 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
0089 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0090 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
0091 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0092 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
0093 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0094 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0095 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
0096 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
0097 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0098 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
0099 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0100 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0101 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0102 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
0103 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0104 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
0105 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0106 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
0107 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
0108 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
0109 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0110 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0111 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0112 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
0113 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0114 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
0115 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0116 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
0117 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0118 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0119 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
0120 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
0121 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0122 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
0123 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0124 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
0125 0x2d02ef8d
0126 };
0127
0128 static u32 partial_crc32_one(u8 c, u32 crc)
0129 {
0130 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
0131 }
0132
0133 static u32 partial_crc32(const u8 *s, int len, u32 crc)
0134 {
0135 while (len--)
0136 crc = partial_crc32_one(*s++, crc);
0137 return crc;
0138 }
0139
0140 static void die(const char * str, ...)
0141 {
0142 va_list args;
0143 va_start(args, str);
0144 vfprintf(stderr, str, args);
0145 va_end(args);
0146 fputc('\n', stderr);
0147 exit(1);
0148 }
0149
0150 static void usage(void)
0151 {
0152 die("Usage: build setup system zoffset.h image");
0153 }
0154
0155 #ifdef CONFIG_EFI_STUB
0156
0157 static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
0158 {
0159 unsigned int pe_header;
0160 unsigned short num_sections;
0161 u8 *section;
0162
0163 pe_header = get_unaligned_le32(&buf[0x3c]);
0164 num_sections = get_unaligned_le16(&buf[pe_header + 6]);
0165
0166 #ifdef CONFIG_X86_32
0167 section = &buf[pe_header + 0xa8];
0168 #else
0169 section = &buf[pe_header + 0xb8];
0170 #endif
0171
0172 while (num_sections > 0) {
0173 if (strncmp((char*)section, section_name, 8) == 0) {
0174
0175 put_unaligned_le32(size, section + 0x8);
0176
0177
0178 put_unaligned_le32(vma, section + 0xc);
0179
0180
0181 put_unaligned_le32(datasz, section + 0x10);
0182
0183
0184 put_unaligned_le32(offset, section + 0x14);
0185
0186 break;
0187 }
0188 section += 0x28;
0189 num_sections--;
0190 }
0191 }
0192
0193 static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
0194 {
0195 update_pecoff_section_header_fields(section_name, offset, size, size, offset);
0196 }
0197
0198 static void update_pecoff_setup_and_reloc(unsigned int size)
0199 {
0200 u32 setup_offset = 0x200;
0201 u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
0202 #ifdef CONFIG_EFI_MIXED
0203 u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
0204 #endif
0205 u32 setup_size = reloc_offset - setup_offset;
0206
0207 update_pecoff_section_header(".setup", setup_offset, setup_size);
0208 update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
0209
0210
0211
0212
0213
0214 put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
0215 put_unaligned_le32(10, &buf[reloc_offset + 4]);
0216
0217 #ifdef CONFIG_EFI_MIXED
0218 update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
0219
0220
0221
0222
0223
0224
0225 buf[compat_offset] = 0x1;
0226 buf[compat_offset + 1] = 0x8;
0227 put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
0228 put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
0229 #endif
0230 }
0231
0232 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
0233 unsigned int init_sz)
0234 {
0235 unsigned int pe_header;
0236 unsigned int text_sz = file_sz - text_start;
0237 unsigned int bss_sz = init_sz - file_sz;
0238
0239 pe_header = get_unaligned_le32(&buf[0x3c]);
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 bss_sz += CONFIG_PHYSICAL_ALIGN;
0251 init_sz += CONFIG_PHYSICAL_ALIGN;
0252
0253
0254
0255
0256
0257 put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
0258
0259
0260 put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
0261
0262
0263
0264
0265 put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
0266
0267 update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
0268 text_sz, text_start);
0269 }
0270
0271 static int reserve_pecoff_reloc_section(int c)
0272 {
0273
0274 memset(buf+c, 0, PECOFF_RELOC_RESERVE);
0275 return PECOFF_RELOC_RESERVE;
0276 }
0277
0278 static void efi_stub_defaults(void)
0279 {
0280
0281 #ifdef CONFIG_X86_32
0282 efi_pe_entry = 0x10;
0283 #else
0284 efi_pe_entry = 0x210;
0285 startup_64 = 0x200;
0286 #endif
0287 }
0288
0289 static void efi_stub_entry_update(void)
0290 {
0291 unsigned long addr = efi32_stub_entry;
0292
0293 #ifdef CONFIG_X86_64
0294
0295 addr = efi64_stub_entry - 0x200;
0296 #endif
0297
0298 #ifdef CONFIG_EFI_MIXED
0299 if (efi32_stub_entry != addr)
0300 die("32-bit and 64-bit EFI entry points do not match\n");
0301 #endif
0302 put_unaligned_le32(addr, &buf[0x264]);
0303 }
0304
0305 #else
0306
0307 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
0308 static inline void update_pecoff_text(unsigned int text_start,
0309 unsigned int file_sz,
0310 unsigned int init_sz) {}
0311 static inline void efi_stub_defaults(void) {}
0312 static inline void efi_stub_entry_update(void) {}
0313
0314 static inline int reserve_pecoff_reloc_section(int c)
0315 {
0316 return 0;
0317 }
0318 #endif
0319
0320 static int reserve_pecoff_compat_section(int c)
0321 {
0322
0323 memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
0324 return PECOFF_COMPAT_RESERVE;
0325 }
0326
0327
0328
0329
0330
0331
0332 #define PARSE_ZOFS(p, sym) do { \
0333 if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \
0334 sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \
0335 } while (0)
0336
0337 static void parse_zoffset(char *fname)
0338 {
0339 FILE *file;
0340 char *p;
0341 int c;
0342
0343 file = fopen(fname, "r");
0344 if (!file)
0345 die("Unable to open `%s': %m", fname);
0346 c = fread(buf, 1, sizeof(buf) - 1, file);
0347 if (ferror(file))
0348 die("read-error on `zoffset.h'");
0349 fclose(file);
0350 buf[c] = 0;
0351
0352 p = (char *)buf;
0353
0354 while (p && *p) {
0355 PARSE_ZOFS(p, efi32_stub_entry);
0356 PARSE_ZOFS(p, efi64_stub_entry);
0357 PARSE_ZOFS(p, efi_pe_entry);
0358 PARSE_ZOFS(p, efi32_pe_entry);
0359 PARSE_ZOFS(p, kernel_info);
0360 PARSE_ZOFS(p, startup_64);
0361 PARSE_ZOFS(p, _ehead);
0362 PARSE_ZOFS(p, _end);
0363
0364 p = strchr(p, '\n');
0365 while (p && (*p == '\r' || *p == '\n'))
0366 p++;
0367 }
0368 }
0369
0370 int main(int argc, char ** argv)
0371 {
0372 unsigned int i, sz, setup_sectors, init_sz;
0373 int c;
0374 u32 sys_size;
0375 struct stat sb;
0376 FILE *file, *dest;
0377 int fd;
0378 void *kernel;
0379 u32 crc = 0xffffffffUL;
0380
0381 efi_stub_defaults();
0382
0383 if (argc != 5)
0384 usage();
0385 parse_zoffset(argv[3]);
0386
0387 dest = fopen(argv[4], "w");
0388 if (!dest)
0389 die("Unable to write `%s': %m", argv[4]);
0390
0391
0392 file = fopen(argv[1], "r");
0393 if (!file)
0394 die("Unable to open `%s': %m", argv[1]);
0395 c = fread(buf, 1, sizeof(buf), file);
0396 if (ferror(file))
0397 die("read-error on `setup'");
0398 if (c < 1024)
0399 die("The setup must be at least 1024 bytes");
0400 if (get_unaligned_le16(&buf[510]) != 0xAA55)
0401 die("Boot block hasn't got boot flag (0xAA55)");
0402 fclose(file);
0403
0404 c += reserve_pecoff_compat_section(c);
0405 c += reserve_pecoff_reloc_section(c);
0406
0407
0408 setup_sectors = (c + 511) / 512;
0409 if (setup_sectors < SETUP_SECT_MIN)
0410 setup_sectors = SETUP_SECT_MIN;
0411 i = setup_sectors*512;
0412 memset(buf+c, 0, i-c);
0413
0414 update_pecoff_setup_and_reloc(i);
0415
0416
0417 put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
0418
0419
0420 fd = open(argv[2], O_RDONLY);
0421 if (fd < 0)
0422 die("Unable to open `%s': %m", argv[2]);
0423 if (fstat(fd, &sb))
0424 die("Unable to stat `%s': %m", argv[2]);
0425 sz = sb.st_size;
0426 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
0427 if (kernel == MAP_FAILED)
0428 die("Unable to mmap '%s': %m", argv[2]);
0429
0430 sys_size = (sz + 15 + 4) / 16;
0431 #ifdef CONFIG_EFI_STUB
0432
0433
0434
0435
0436 sys_size = (sys_size + 1) & ~1;
0437 #endif
0438
0439
0440 buf[0x1f1] = setup_sectors-1;
0441 put_unaligned_le32(sys_size, &buf[0x1f4]);
0442
0443 init_sz = get_unaligned_le32(&buf[0x260]);
0444 #ifdef CONFIG_EFI_STUB
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 if (init_sz - _end < i + _ehead) {
0460 init_sz = (i + _ehead + _end + 4095) & ~4095;
0461 put_unaligned_le32(init_sz, &buf[0x260]);
0462 }
0463 #endif
0464 update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
0465
0466 efi_stub_entry_update();
0467
0468
0469 put_unaligned_le32(kernel_info, &buf[0x268]);
0470
0471 crc = partial_crc32(buf, i, crc);
0472 if (fwrite(buf, 1, i, dest) != i)
0473 die("Writing setup failed");
0474
0475
0476 crc = partial_crc32(kernel, sz, crc);
0477 if (fwrite(kernel, 1, sz, dest) != sz)
0478 die("Writing kernel failed");
0479
0480
0481 while (sz++ < (sys_size*16) - 4) {
0482 crc = partial_crc32_one('\0', crc);
0483 if (fwrite("\0", 1, 1, dest) != 1)
0484 die("Writing padding failed");
0485 }
0486
0487
0488 put_unaligned_le32(crc, buf);
0489 if (fwrite(buf, 1, 4, dest) != 4)
0490 die("Writing CRC failed");
0491
0492
0493 if (fclose(dest))
0494 die("Writing image failed");
0495
0496 close(fd);
0497
0498
0499 return 0;
0500 }