119d8d79cSThomas Gleixner /* 219d8d79cSThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 319d8d79cSThomas Gleixner * Copyright (C) 1997 Martin Mares 419d8d79cSThomas Gleixner * Copyright (C) 2007 H. Peter Anvin 519d8d79cSThomas Gleixner */ 619d8d79cSThomas Gleixner 719d8d79cSThomas Gleixner /* 819d8d79cSThomas Gleixner * This file builds a disk-image from two different files: 919d8d79cSThomas Gleixner * 1019d8d79cSThomas Gleixner * - setup: 8086 machine code, sets up system parm 1119d8d79cSThomas Gleixner * - system: 80386 code for actual system 1219d8d79cSThomas Gleixner * 1319d8d79cSThomas Gleixner * It does some checking that all files are of the correct type, and 1419d8d79cSThomas Gleixner * just writes the result to stdout, removing headers and padding to 1519d8d79cSThomas Gleixner * the right amount. It also writes some system data to stderr. 1619d8d79cSThomas Gleixner */ 1719d8d79cSThomas Gleixner 1819d8d79cSThomas Gleixner /* 1919d8d79cSThomas Gleixner * Changes by tytso to allow root device specification 2019d8d79cSThomas Gleixner * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 2119d8d79cSThomas Gleixner * Cross compiling fixes by Gertjan van Wingerde, July 1996 2219d8d79cSThomas Gleixner * Rewritten by Martin Mares, April 1997 2319d8d79cSThomas Gleixner * Substantially overhauled by H. Peter Anvin, April 2007 2419d8d79cSThomas Gleixner */ 2519d8d79cSThomas Gleixner 2619d8d79cSThomas Gleixner #include <stdio.h> 2719d8d79cSThomas Gleixner #include <string.h> 2819d8d79cSThomas Gleixner #include <stdlib.h> 2919d8d79cSThomas Gleixner #include <stdarg.h> 3019d8d79cSThomas Gleixner #include <sys/types.h> 3119d8d79cSThomas Gleixner #include <sys/stat.h> 3219d8d79cSThomas Gleixner #include <sys/sysmacros.h> 3319d8d79cSThomas Gleixner #include <unistd.h> 3419d8d79cSThomas Gleixner #include <fcntl.h> 3519d8d79cSThomas Gleixner #include <sys/mman.h> 3619d8d79cSThomas Gleixner #include <asm/boot.h> 3719d8d79cSThomas Gleixner 3819d8d79cSThomas Gleixner typedef unsigned char u8; 3919d8d79cSThomas Gleixner typedef unsigned short u16; 4019d8d79cSThomas Gleixner typedef unsigned long u32; 4119d8d79cSThomas Gleixner 4219d8d79cSThomas Gleixner #define DEFAULT_MAJOR_ROOT 0 4319d8d79cSThomas Gleixner #define DEFAULT_MINOR_ROOT 0 4419d8d79cSThomas Gleixner 4519d8d79cSThomas Gleixner /* Minimal number of setup sectors */ 4619d8d79cSThomas Gleixner #define SETUP_SECT_MIN 5 4719d8d79cSThomas Gleixner #define SETUP_SECT_MAX 64 4819d8d79cSThomas Gleixner 4919d8d79cSThomas Gleixner /* This must be large enough to hold the entire setup */ 5019d8d79cSThomas Gleixner u8 buf[SETUP_SECT_MAX*512]; 5119d8d79cSThomas Gleixner int is_big_kernel; 5219d8d79cSThomas Gleixner 537d6e737cSIan Campbell /*----------------------------------------------------------------------*/ 547d6e737cSIan Campbell 557d6e737cSIan Campbell static const u32 crctab32[] = { 567d6e737cSIan Campbell 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 577d6e737cSIan Campbell 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 587d6e737cSIan Campbell 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 597d6e737cSIan Campbell 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 607d6e737cSIan Campbell 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 617d6e737cSIan Campbell 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 627d6e737cSIan Campbell 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 637d6e737cSIan Campbell 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 647d6e737cSIan Campbell 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 657d6e737cSIan Campbell 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 667d6e737cSIan Campbell 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 677d6e737cSIan Campbell 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 687d6e737cSIan Campbell 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 697d6e737cSIan Campbell 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 707d6e737cSIan Campbell 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 717d6e737cSIan Campbell 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 727d6e737cSIan Campbell 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 737d6e737cSIan Campbell 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 747d6e737cSIan Campbell 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 757d6e737cSIan Campbell 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 767d6e737cSIan Campbell 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 777d6e737cSIan Campbell 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 787d6e737cSIan Campbell 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 797d6e737cSIan Campbell 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 807d6e737cSIan Campbell 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 817d6e737cSIan Campbell 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 827d6e737cSIan Campbell 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 837d6e737cSIan Campbell 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 847d6e737cSIan Campbell 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 857d6e737cSIan Campbell 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 867d6e737cSIan Campbell 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 877d6e737cSIan Campbell 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 887d6e737cSIan Campbell 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 897d6e737cSIan Campbell 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 907d6e737cSIan Campbell 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 917d6e737cSIan Campbell 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 927d6e737cSIan Campbell 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 937d6e737cSIan Campbell 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 947d6e737cSIan Campbell 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 957d6e737cSIan Campbell 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 967d6e737cSIan Campbell 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 977d6e737cSIan Campbell 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 987d6e737cSIan Campbell 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 997d6e737cSIan Campbell 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 1007d6e737cSIan Campbell 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 1017d6e737cSIan Campbell 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 1027d6e737cSIan Campbell 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 1037d6e737cSIan Campbell 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 1047d6e737cSIan Campbell 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 1057d6e737cSIan Campbell 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 1067d6e737cSIan Campbell 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 1077d6e737cSIan Campbell 0x2d02ef8d 1087d6e737cSIan Campbell }; 1097d6e737cSIan Campbell 1107d6e737cSIan Campbell static u32 partial_crc32_one(u8 c, u32 crc) 1117d6e737cSIan Campbell { 1127d6e737cSIan Campbell return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); 1137d6e737cSIan Campbell } 1147d6e737cSIan Campbell 1157d6e737cSIan Campbell static u32 partial_crc32(const u8 *s, int len, u32 crc) 1167d6e737cSIan Campbell { 1177d6e737cSIan Campbell while (len--) 1187d6e737cSIan Campbell crc = partial_crc32_one(*s++, crc); 1197d6e737cSIan Campbell return crc; 1207d6e737cSIan Campbell } 1217d6e737cSIan Campbell 12219d8d79cSThomas Gleixner static void die(const char * str, ...) 12319d8d79cSThomas Gleixner { 12419d8d79cSThomas Gleixner va_list args; 12519d8d79cSThomas Gleixner va_start(args, str); 12619d8d79cSThomas Gleixner vfprintf(stderr, str, args); 12719d8d79cSThomas Gleixner fputc('\n', stderr); 12819d8d79cSThomas Gleixner exit(1); 12919d8d79cSThomas Gleixner } 13019d8d79cSThomas Gleixner 13119d8d79cSThomas Gleixner static void usage(void) 13219d8d79cSThomas Gleixner { 133*079f85e6SMichal Marek die("Usage: build setup system [> image]"); 13419d8d79cSThomas Gleixner } 13519d8d79cSThomas Gleixner 13619d8d79cSThomas Gleixner int main(int argc, char ** argv) 13719d8d79cSThomas Gleixner { 13819d8d79cSThomas Gleixner unsigned int i, sz, setup_sectors; 13919d8d79cSThomas Gleixner int c; 14019d8d79cSThomas Gleixner u32 sys_size; 14119d8d79cSThomas Gleixner struct stat sb; 14219d8d79cSThomas Gleixner FILE *file; 14319d8d79cSThomas Gleixner int fd; 14419d8d79cSThomas Gleixner void *kernel; 1457d6e737cSIan Campbell u32 crc = 0xffffffffUL; 14619d8d79cSThomas Gleixner 147*079f85e6SMichal Marek if (argc != 3) 14819d8d79cSThomas Gleixner usage(); 14919d8d79cSThomas Gleixner 15019d8d79cSThomas Gleixner /* Copy the setup code */ 15119d8d79cSThomas Gleixner file = fopen(argv[1], "r"); 15219d8d79cSThomas Gleixner if (!file) 15319d8d79cSThomas Gleixner die("Unable to open `%s': %m", argv[1]); 15419d8d79cSThomas Gleixner c = fread(buf, 1, sizeof(buf), file); 15519d8d79cSThomas Gleixner if (ferror(file)) 15619d8d79cSThomas Gleixner die("read-error on `setup'"); 15719d8d79cSThomas Gleixner if (c < 1024) 15819d8d79cSThomas Gleixner die("The setup must be at least 1024 bytes"); 15919d8d79cSThomas Gleixner if (buf[510] != 0x55 || buf[511] != 0xaa) 16019d8d79cSThomas Gleixner die("Boot block hasn't got boot flag (0xAA55)"); 16119d8d79cSThomas Gleixner fclose(file); 16219d8d79cSThomas Gleixner 16319d8d79cSThomas Gleixner /* Pad unused space with zeros */ 16419d8d79cSThomas Gleixner setup_sectors = (c + 511) / 512; 16519d8d79cSThomas Gleixner if (setup_sectors < SETUP_SECT_MIN) 16619d8d79cSThomas Gleixner setup_sectors = SETUP_SECT_MIN; 16719d8d79cSThomas Gleixner i = setup_sectors*512; 16819d8d79cSThomas Gleixner memset(buf+c, 0, i-c); 16919d8d79cSThomas Gleixner 17019d8d79cSThomas Gleixner /* Set the default root device */ 171*079f85e6SMichal Marek buf[508] = DEFAULT_MINOR_ROOT; 172*079f85e6SMichal Marek buf[509] = DEFAULT_MAJOR_ROOT; 17319d8d79cSThomas Gleixner 17419d8d79cSThomas Gleixner fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); 17519d8d79cSThomas Gleixner 17619d8d79cSThomas Gleixner /* Open and stat the kernel file */ 17719d8d79cSThomas Gleixner fd = open(argv[2], O_RDONLY); 17819d8d79cSThomas Gleixner if (fd < 0) 17919d8d79cSThomas Gleixner die("Unable to open `%s': %m", argv[2]); 18019d8d79cSThomas Gleixner if (fstat(fd, &sb)) 18119d8d79cSThomas Gleixner die("Unable to stat `%s': %m", argv[2]); 18219d8d79cSThomas Gleixner sz = sb.st_size; 18319d8d79cSThomas Gleixner fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); 18419d8d79cSThomas Gleixner kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 18519d8d79cSThomas Gleixner if (kernel == MAP_FAILED) 18619d8d79cSThomas Gleixner die("Unable to mmap '%s': %m", argv[2]); 1877d6e737cSIan Campbell /* Number of 16-byte paragraphs, including space for a 4-byte CRC */ 1887d6e737cSIan Campbell sys_size = (sz + 15 + 4) / 16; 18919d8d79cSThomas Gleixner 19019d8d79cSThomas Gleixner /* Patch the setup code with the appropriate size parameters */ 19119d8d79cSThomas Gleixner buf[0x1f1] = setup_sectors-1; 19219d8d79cSThomas Gleixner buf[0x1f4] = sys_size; 19319d8d79cSThomas Gleixner buf[0x1f5] = sys_size >> 8; 19419d8d79cSThomas Gleixner buf[0x1f6] = sys_size >> 16; 19519d8d79cSThomas Gleixner buf[0x1f7] = sys_size >> 24; 19619d8d79cSThomas Gleixner 1977d6e737cSIan Campbell crc = partial_crc32(buf, i, crc); 19819d8d79cSThomas Gleixner if (fwrite(buf, 1, i, stdout) != i) 19919d8d79cSThomas Gleixner die("Writing setup failed"); 20019d8d79cSThomas Gleixner 20119d8d79cSThomas Gleixner /* Copy the kernel code */ 2027d6e737cSIan Campbell crc = partial_crc32(kernel, sz, crc); 20319d8d79cSThomas Gleixner if (fwrite(kernel, 1, sz, stdout) != sz) 20419d8d79cSThomas Gleixner die("Writing kernel failed"); 2057d6e737cSIan Campbell 2067d6e737cSIan Campbell /* Add padding leaving 4 bytes for the checksum */ 2077d6e737cSIan Campbell while (sz++ < (sys_size*16) - 4) { 2087d6e737cSIan Campbell crc = partial_crc32_one('\0', crc); 2097d6e737cSIan Campbell if (fwrite("\0", 1, 1, stdout) != 1) 2107d6e737cSIan Campbell die("Writing padding failed"); 2117d6e737cSIan Campbell } 2127d6e737cSIan Campbell 2137d6e737cSIan Campbell /* Write the CRC */ 2147d6e737cSIan Campbell fprintf(stderr, "CRC %lx\n", crc); 2157d6e737cSIan Campbell if (fwrite(&crc, 1, 4, stdout) != 4) 2167d6e737cSIan Campbell die("Writing CRC failed"); 2177d6e737cSIan Campbell 21819d8d79cSThomas Gleixner close(fd); 21919d8d79cSThomas Gleixner 22019d8d79cSThomas Gleixner /* Everything is OK */ 22119d8d79cSThomas Gleixner return 0; 22219d8d79cSThomas Gleixner } 223