linux/arch/x86/boot/tools/build.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Copyright (C) 1991, 1992  Linus Torvalds
   4 *  Copyright (C) 1997 Martin Mares
   5 *  Copyright (C) 2007 H. Peter Anvin
   6 */
   7
   8/*
   9 * This file builds a disk-image from three different files:
  10 *
  11 * - setup: 8086 machine code, sets up system parm
  12 * - system: 80386 code for actual system
  13 * - zoffset.h: header with ZO_* defines
  14 *
  15 * It does some checking that all files are of the correct type, and writes
  16 * the result to the specified destination, removing headers and padding to
  17 * the right amount. It also writes some system data to stdout.
  18 */
  19
  20/*
  21 * Changes by tytso to allow root device specification
  22 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  23 * Cross compiling fixes by Gertjan van Wingerde, July 1996
  24 * Rewritten by Martin Mares, April 1997
  25 * Substantially overhauled by H. Peter Anvin, April 2007
  26 */
  27
  28#include <stdio.h>
  29#include <string.h>
  30#include <stdlib.h>
  31#include <stdarg.h>
  32#include <sys/types.h>
  33#include <sys/stat.h>
  34#include <unistd.h>
  35#include <fcntl.h>
  36#include <sys/mman.h>
  37#include <tools/le_byteshift.h>
  38
  39typedef unsigned char  u8;
  40typedef unsigned short u16;
  41typedef unsigned int   u32;
  42
  43#define DEFAULT_MAJOR_ROOT 0
  44#define DEFAULT_MINOR_ROOT 0
  45#define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
  46
  47/* Minimal number of setup sectors */
  48#define SETUP_SECT_MIN 5
  49#define SETUP_SECT_MAX 64
  50
  51/* This must be large enough to hold the entire setup */
  52u8 buf[SETUP_SECT_MAX*512];
  53
  54#define PECOFF_RELOC_RESERVE 0x20
  55
  56#ifdef CONFIG_EFI_MIXED
  57#define PECOFF_COMPAT_RESERVE 0x20
  58#else
  59#define PECOFF_COMPAT_RESERVE 0x0
  60#endif
  61
  62static unsigned long efi32_stub_entry;
  63static unsigned long efi64_stub_entry;
  64static unsigned long efi_pe_entry;
  65static unsigned long efi32_pe_entry;
  66static unsigned long kernel_info;
  67static unsigned long startup_64;
  68static unsigned long _ehead;
  69static unsigned long _end;
  70
  71/*----------------------------------------------------------------------*/
  72
  73static const u32 crctab32[] = {
  74        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
  75        0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
  76        0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
  77        0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
  78        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
  79        0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  80        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
  81        0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
  82        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
  83        0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
  84        0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
  85        0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
  86        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
  87        0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
  88        0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
  89        0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
  90        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
  91        0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
  92        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
  93        0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
  94        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
  95        0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
  96        0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
  97        0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  98        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
  99        0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
 100        0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
 101        0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 102        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
 103        0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
 104        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
 105        0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 106        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
 107        0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
 108        0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
 109        0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 110        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
 111        0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
 112        0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
 113        0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
 114        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
 115        0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
 116        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
 117        0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
 118        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
 119        0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
 120        0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
 121        0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
 122        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
 123        0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
 124        0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
 125        0x2d02ef8d
 126};
 127
 128static u32 partial_crc32_one(u8 c, u32 crc)
 129{
 130        return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
 131}
 132
 133static u32 partial_crc32(const u8 *s, int len, u32 crc)
 134{
 135        while (len--)
 136                crc = partial_crc32_one(*s++, crc);
 137        return crc;
 138}
 139
 140static void die(const char * str, ...)
 141{
 142        va_list args;
 143        va_start(args, str);
 144        vfprintf(stderr, str, args);
 145        va_end(args);
 146        fputc('\n', stderr);
 147        exit(1);
 148}
 149
 150static void usage(void)
 151{
 152        die("Usage: build setup system zoffset.h image");
 153}
 154
 155#ifdef CONFIG_EFI_STUB
 156
 157static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
 158{
 159        unsigned int pe_header;
 160        unsigned short num_sections;
 161        u8 *section;
 162
 163        pe_header = get_unaligned_le32(&buf[0x3c]);
 164        num_sections = get_unaligned_le16(&buf[pe_header + 6]);
 165
 166#ifdef CONFIG_X86_32
 167        section = &buf[pe_header + 0xa8];
 168#else
 169        section = &buf[pe_header + 0xb8];
 170#endif
 171
 172        while (num_sections > 0) {
 173                if (strncmp((char*)section, section_name, 8) == 0) {
 174                        /* section header size field */
 175                        put_unaligned_le32(size, section + 0x8);
 176
 177                        /* section header vma field */
 178                        put_unaligned_le32(vma, section + 0xc);
 179
 180                        /* section header 'size of initialised data' field */
 181                        put_unaligned_le32(datasz, section + 0x10);
 182
 183                        /* section header 'file offset' field */
 184                        put_unaligned_le32(offset, section + 0x14);
 185
 186                        break;
 187                }
 188                section += 0x28;
 189                num_sections--;
 190        }
 191}
 192
 193static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
 194{
 195        update_pecoff_section_header_fields(section_name, offset, size, size, offset);
 196}
 197
 198static void update_pecoff_setup_and_reloc(unsigned int size)
 199{
 200        u32 setup_offset = 0x200;
 201        u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
 202#ifdef CONFIG_EFI_MIXED
 203        u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
 204#endif
 205        u32 setup_size = reloc_offset - setup_offset;
 206
 207        update_pecoff_section_header(".setup", setup_offset, setup_size);
 208        update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
 209
 210        /*
 211         * Modify .reloc section contents with a single entry. The
 212         * relocation is applied to offset 10 of the relocation section.
 213         */
 214        put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
 215        put_unaligned_le32(10, &buf[reloc_offset + 4]);
 216
 217#ifdef CONFIG_EFI_MIXED
 218        update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
 219
 220        /*
 221         * Put the IA-32 machine type (0x14c) and the associated entry point
 222         * address in the .compat section, so loaders can figure out which other
 223         * execution modes this image supports.
 224         */
 225        buf[compat_offset] = 0x1;
 226        buf[compat_offset + 1] = 0x8;
 227        put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
 228        put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
 229#endif
 230}
 231
 232static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
 233                               unsigned int init_sz)
 234{
 235        unsigned int pe_header;
 236        unsigned int text_sz = file_sz - text_start;
 237        unsigned int bss_sz = init_sz - file_sz;
 238
 239        pe_header = get_unaligned_le32(&buf[0x3c]);
 240
 241        /*
 242         * The PE/COFF loader may load the image at an address which is
 243         * misaligned with respect to the kernel_alignment field in the setup
 244         * header.
 245         *
 246         * In order to avoid relocating the kernel to correct the misalignment,
 247         * add slack to allow the buffer to be aligned within the declared size
 248         * of the image.
 249         */
 250        bss_sz  += CONFIG_PHYSICAL_ALIGN;
 251        init_sz += CONFIG_PHYSICAL_ALIGN;
 252
 253        /*
 254         * Size of code: Subtract the size of the first sector (512 bytes)
 255         * which includes the header.
 256         */
 257        put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
 258
 259        /* Size of image */
 260        put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
 261
 262        /*
 263         * Address of entry point for PE/COFF executable
 264         */
 265        put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
 266
 267        update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
 268                                            text_sz, text_start);
 269}
 270
 271static int reserve_pecoff_reloc_section(int c)
 272{
 273        /* Reserve 0x20 bytes for .reloc section */
 274        memset(buf+c, 0, PECOFF_RELOC_RESERVE);
 275        return PECOFF_RELOC_RESERVE;
 276}
 277
 278static void efi_stub_defaults(void)
 279{
 280        /* Defaults for old kernel */
 281#ifdef CONFIG_X86_32
 282        efi_pe_entry = 0x10;
 283#else
 284        efi_pe_entry = 0x210;
 285        startup_64 = 0x200;
 286#endif
 287}
 288
 289static void efi_stub_entry_update(void)
 290{
 291        unsigned long addr = efi32_stub_entry;
 292
 293#ifdef CONFIG_X86_64
 294        /* Yes, this is really how we defined it :( */
 295        addr = efi64_stub_entry - 0x200;
 296#endif
 297
 298#ifdef CONFIG_EFI_MIXED
 299        if (efi32_stub_entry != addr)
 300                die("32-bit and 64-bit EFI entry points do not match\n");
 301#endif
 302        put_unaligned_le32(addr, &buf[0x264]);
 303}
 304
 305#else
 306
 307static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
 308static inline void update_pecoff_text(unsigned int text_start,
 309                                      unsigned int file_sz,
 310                                      unsigned int init_sz) {}
 311static inline void efi_stub_defaults(void) {}
 312static inline void efi_stub_entry_update(void) {}
 313
 314static inline int reserve_pecoff_reloc_section(int c)
 315{
 316        return 0;
 317}
 318#endif /* CONFIG_EFI_STUB */
 319
 320static int reserve_pecoff_compat_section(int c)
 321{
 322        /* Reserve 0x20 bytes for .compat section */
 323        memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
 324        return PECOFF_COMPAT_RESERVE;
 325}
 326
 327/*
 328 * Parse zoffset.h and find the entry points. We could just #include zoffset.h
 329 * but that would mean tools/build would have to be rebuilt every time. It's
 330 * not as if parsing it is hard...
 331 */
 332#define PARSE_ZOFS(p, sym) do { \
 333        if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))       \
 334                sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);         \
 335} while (0)
 336
 337static void parse_zoffset(char *fname)
 338{
 339        FILE *file;
 340        char *p;
 341        int c;
 342
 343        file = fopen(fname, "r");
 344        if (!file)
 345                die("Unable to open `%s': %m", fname);
 346        c = fread(buf, 1, sizeof(buf) - 1, file);
 347        if (ferror(file))
 348                die("read-error on `zoffset.h'");
 349        fclose(file);
 350        buf[c] = 0;
 351
 352        p = (char *)buf;
 353
 354        while (p && *p) {
 355                PARSE_ZOFS(p, efi32_stub_entry);
 356                PARSE_ZOFS(p, efi64_stub_entry);
 357                PARSE_ZOFS(p, efi_pe_entry);
 358                PARSE_ZOFS(p, efi32_pe_entry);
 359                PARSE_ZOFS(p, kernel_info);
 360                PARSE_ZOFS(p, startup_64);
 361                PARSE_ZOFS(p, _ehead);
 362                PARSE_ZOFS(p, _end);
 363
 364                p = strchr(p, '\n');
 365                while (p && (*p == '\r' || *p == '\n'))
 366                        p++;
 367        }
 368}
 369
 370int main(int argc, char ** argv)
 371{
 372        unsigned int i, sz, setup_sectors, init_sz;
 373        int c;
 374        u32 sys_size;
 375        struct stat sb;
 376        FILE *file, *dest;
 377        int fd;
 378        void *kernel;
 379        u32 crc = 0xffffffffUL;
 380
 381        efi_stub_defaults();
 382
 383        if (argc != 5)
 384                usage();
 385        parse_zoffset(argv[3]);
 386
 387        dest = fopen(argv[4], "w");
 388        if (!dest)
 389                die("Unable to write `%s': %m", argv[4]);
 390
 391        /* Copy the setup code */
 392        file = fopen(argv[1], "r");
 393        if (!file)
 394                die("Unable to open `%s': %m", argv[1]);
 395        c = fread(buf, 1, sizeof(buf), file);
 396        if (ferror(file))
 397                die("read-error on `setup'");
 398        if (c < 1024)
 399                die("The setup must be at least 1024 bytes");
 400        if (get_unaligned_le16(&buf[510]) != 0xAA55)
 401                die("Boot block hasn't got boot flag (0xAA55)");
 402        fclose(file);
 403
 404        c += reserve_pecoff_compat_section(c);
 405        c += reserve_pecoff_reloc_section(c);
 406
 407        /* Pad unused space with zeros */
 408        setup_sectors = (c + 511) / 512;
 409        if (setup_sectors < SETUP_SECT_MIN)
 410                setup_sectors = SETUP_SECT_MIN;
 411        i = setup_sectors*512;
 412        memset(buf+c, 0, i-c);
 413
 414        update_pecoff_setup_and_reloc(i);
 415
 416        /* Set the default root device */
 417        put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
 418
 419        /* Open and stat the kernel file */
 420        fd = open(argv[2], O_RDONLY);
 421        if (fd < 0)
 422                die("Unable to open `%s': %m", argv[2]);
 423        if (fstat(fd, &sb))
 424                die("Unable to stat `%s': %m", argv[2]);
 425        sz = sb.st_size;
 426        kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
 427        if (kernel == MAP_FAILED)
 428                die("Unable to mmap '%s': %m", argv[2]);
 429        /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
 430        sys_size = (sz + 15 + 4) / 16;
 431#ifdef CONFIG_EFI_STUB
 432        /*
 433         * COFF requires minimum 32-byte alignment of sections, and
 434         * adding a signature is problematic without that alignment.
 435         */
 436        sys_size = (sys_size + 1) & ~1;
 437#endif
 438
 439        /* Patch the setup code with the appropriate size parameters */
 440        buf[0x1f1] = setup_sectors-1;
 441        put_unaligned_le32(sys_size, &buf[0x1f4]);
 442
 443        init_sz = get_unaligned_le32(&buf[0x260]);
 444#ifdef CONFIG_EFI_STUB
 445        /*
 446         * The decompression buffer will start at ImageBase. When relocating
 447         * the compressed kernel to its end, we must ensure that the head
 448         * section does not get overwritten.  The head section occupies
 449         * [i, i + _ehead), and the destination is [init_sz - _end, init_sz).
 450         *
 451         * At present these should never overlap, because 'i' is at most 32k
 452         * because of SETUP_SECT_MAX, '_ehead' is less than 1k, and the
 453         * calculation of INIT_SIZE in boot/header.S ensures that
 454         * 'init_sz - _end' is at least 64k.
 455         *
 456         * For future-proofing, increase init_sz if necessary.
 457         */
 458
 459        if (init_sz - _end < i + _ehead) {
 460                init_sz = (i + _ehead + _end + 4095) & ~4095;
 461                put_unaligned_le32(init_sz, &buf[0x260]);
 462        }
 463#endif
 464        update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
 465
 466        efi_stub_entry_update();
 467
 468        /* Update kernel_info offset. */
 469        put_unaligned_le32(kernel_info, &buf[0x268]);
 470
 471        crc = partial_crc32(buf, i, crc);
 472        if (fwrite(buf, 1, i, dest) != i)
 473                die("Writing setup failed");
 474
 475        /* Copy the kernel code */
 476        crc = partial_crc32(kernel, sz, crc);
 477        if (fwrite(kernel, 1, sz, dest) != sz)
 478                die("Writing kernel failed");
 479
 480        /* Add padding leaving 4 bytes for the checksum */
 481        while (sz++ < (sys_size*16) - 4) {
 482                crc = partial_crc32_one('\0', crc);
 483                if (fwrite("\0", 1, 1, dest) != 1)
 484                        die("Writing padding failed");
 485        }
 486
 487        /* Write the CRC */
 488        put_unaligned_le32(crc, buf);
 489        if (fwrite(buf, 1, 4, dest) != 4)
 490                die("Writing CRC failed");
 491
 492        /* Catch any delayed write failures */
 493        if (fclose(dest))
 494                die("Writing image failed");
 495
 496        close(fd);
 497
 498        /* Everything is OK */
 499        return 0;
 500}
 501