linux/arch/x86/boot/tools/build.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1991, 1992  Linus Torvalds
   3 *  Copyright (C) 1997 Martin Mares
   4 *  Copyright (C) 2007 H. Peter Anvin
   5 */
   6
   7/*
   8 * This file builds a disk-image from two different files:
   9 *
  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
  23 * Substantially overhauled by H. Peter Anvin, April 2007
  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>
  35#include <sys/mman.h>
  36#include <asm/boot.h>
  37
  38typedef unsigned char  u8;
  39typedef unsigned short u16;
  40typedef unsigned long  u32;
  41
  42#define DEFAULT_MAJOR_ROOT 0
  43#define DEFAULT_MINOR_ROOT 0
  44
  45/* Minimal number of setup sectors */
  46#define SETUP_SECT_MIN 5
  47#define SETUP_SECT_MAX 64
  48
  49/* This must be large enough to hold the entire setup */
  50u8 buf[SETUP_SECT_MAX*512];
  51int is_big_kernel;
  52
  53/*----------------------------------------------------------------------*/
  54
  55static const u32 crctab32[] = {
  56        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
  57        0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
  58        0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
  59        0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
  60        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
  61        0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  62        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
  63        0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
  64        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
  65        0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
  66        0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
  67        0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
  68        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
  69        0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
  70        0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
  71        0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
  72        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
  73        0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
  74        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
  75        0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
  76        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
  77        0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
  78        0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
  79        0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  80        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
  81        0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
  82        0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
  83        0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
  84        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
  85        0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  86        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
  87        0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
  88        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
  89        0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
  90        0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
  91        0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
  92        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
  93        0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
  94        0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
  95        0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
  96        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
  97        0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
  98        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
  99        0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
 100        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
 101        0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
 102        0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
 103        0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
 104        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
 105        0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
 106        0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
 107        0x2d02ef8d
 108};
 109
 110static u32 partial_crc32_one(u8 c, u32 crc)
 111{
 112        return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
 113}
 114
 115static u32 partial_crc32(const u8 *s, int len, u32 crc)
 116{
 117        while (len--)
 118                crc = partial_crc32_one(*s++, crc);
 119        return crc;
 120}
 121
 122static void die(const char * str, ...)
 123{
 124        va_list args;
 125        va_start(args, str);
 126        vfprintf(stderr, str, args);
 127        fputc('\n', stderr);
 128        exit(1);
 129}
 130
 131static void usage(void)
 132{
 133        die("Usage: build [-b] setup system [rootdev] [> image]");
 134}
 135
 136int main(int argc, char ** argv)
 137{
 138        unsigned int i, sz, setup_sectors;
 139        int c;
 140        u32 sys_size;
 141        u8 major_root, minor_root;
 142        struct stat sb;
 143        FILE *file;
 144        int fd;
 145        void *kernel;
 146        u32 crc = 0xffffffffUL;
 147
 148        if (argc > 2 && !strcmp(argv[1], "-b"))
 149          {
 150            is_big_kernel = 1;
 151            argc--, argv++;
 152          }
 153        if ((argc < 3) || (argc > 4))
 154                usage();
 155        if (argc > 3) {
 156                if (!strcmp(argv[3], "CURRENT")) {
 157                        if (stat("/", &sb)) {
 158                                perror("/");
 159                                die("Couldn't stat /");
 160                        }
 161                        major_root = major(sb.st_dev);
 162                        minor_root = minor(sb.st_dev);
 163                } else if (strcmp(argv[3], "FLOPPY")) {
 164                        if (stat(argv[3], &sb)) {
 165                                perror(argv[3]);
 166                                die("Couldn't stat root device.");
 167                        }
 168                        major_root = major(sb.st_rdev);
 169                        minor_root = minor(sb.st_rdev);
 170                } else {
 171                        major_root = 0;
 172                        minor_root = 0;
 173                }
 174        } else {
 175                major_root = DEFAULT_MAJOR_ROOT;
 176                minor_root = DEFAULT_MINOR_ROOT;
 177        }
 178        fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
 179
 180        /* Copy the setup code */
 181        file = fopen(argv[1], "r");
 182        if (!file)
 183                die("Unable to open `%s': %m", argv[1]);
 184        c = fread(buf, 1, sizeof(buf), file);
 185        if (ferror(file))
 186                die("read-error on `setup'");
 187        if (c < 1024)
 188                die("The setup must be at least 1024 bytes");
 189        if (buf[510] != 0x55 || buf[511] != 0xaa)
 190                die("Boot block hasn't got boot flag (0xAA55)");
 191        fclose(file);
 192
 193        /* Pad unused space with zeros */
 194        setup_sectors = (c + 511) / 512;
 195        if (setup_sectors < SETUP_SECT_MIN)
 196                setup_sectors = SETUP_SECT_MIN;
 197        i = setup_sectors*512;
 198        memset(buf+c, 0, i-c);
 199
 200        /* Set the default root device */
 201        buf[508] = minor_root;
 202        buf[509] = major_root;
 203
 204        fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
 205
 206        /* Open and stat the kernel file */
 207        fd = open(argv[2], O_RDONLY);
 208        if (fd < 0)
 209                die("Unable to open `%s': %m", argv[2]);
 210        if (fstat(fd, &sb))
 211                die("Unable to stat `%s': %m", argv[2]);
 212        sz = sb.st_size;
 213        fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
 214        kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
 215        if (kernel == MAP_FAILED)
 216                die("Unable to mmap '%s': %m", argv[2]);
 217        /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
 218        sys_size = (sz + 15 + 4) / 16;
 219        if (!is_big_kernel && sys_size > DEF_SYSSIZE)
 220                die("System is too big. Try using bzImage or modules.");
 221
 222        /* Patch the setup code with the appropriate size parameters */
 223        buf[0x1f1] = setup_sectors-1;
 224        buf[0x1f4] = sys_size;
 225        buf[0x1f5] = sys_size >> 8;
 226        buf[0x1f6] = sys_size >> 16;
 227        buf[0x1f7] = sys_size >> 24;
 228
 229        crc = partial_crc32(buf, i, crc);
 230        if (fwrite(buf, 1, i, stdout) != i)
 231                die("Writing setup failed");
 232
 233        /* Copy the kernel code */
 234        crc = partial_crc32(kernel, sz, crc);
 235        if (fwrite(kernel, 1, sz, stdout) != sz)
 236                die("Writing kernel failed");
 237
 238        /* Add padding leaving 4 bytes for the checksum */
 239        while (sz++ < (sys_size*16) - 4) {
 240                crc = partial_crc32_one('\0', crc);
 241                if (fwrite("\0", 1, 1, stdout) != 1)
 242                        die("Writing padding failed");
 243        }
 244
 245        /* Write the CRC */
 246        fprintf(stderr, "CRC %lx\n", crc);
 247        if (fwrite(&crc, 1, 4, stdout) != 4)
 248                die("Writing CRC failed");
 249
 250        close(fd);
 251
 252        /* Everything is OK */
 253        return 0;
 254}
 255