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 38 typedef unsigned char u8; 39 typedef unsigned short u16; 40 typedef 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 */ 50 u8 buf[SETUP_SECT_MAX*512]; 51 int is_big_kernel; 52 53 static void die(const char * str, ...) 54 { 55 va_list args; 56 va_start(args, str); 57 vfprintf(stderr, str, args); 58 fputc('\n', stderr); 59 exit(1); 60 } 61 62 static void usage(void) 63 { 64 die("Usage: build [-b] setup system [rootdev] [> image]"); 65 } 66 67 int main(int argc, char ** argv) 68 { 69 unsigned int i, sz, setup_sectors; 70 int c; 71 u32 sys_size; 72 u8 major_root, minor_root; 73 struct stat sb; 74 FILE *file; 75 int fd; 76 void *kernel; 77 78 if (argc > 2 && !strcmp(argv[1], "-b")) 79 { 80 is_big_kernel = 1; 81 argc--, argv++; 82 } 83 if ((argc < 3) || (argc > 4)) 84 usage(); 85 if (argc > 3) { 86 if (!strcmp(argv[3], "CURRENT")) { 87 if (stat("/", &sb)) { 88 perror("/"); 89 die("Couldn't stat /"); 90 } 91 major_root = major(sb.st_dev); 92 minor_root = minor(sb.st_dev); 93 } else if (strcmp(argv[3], "FLOPPY")) { 94 if (stat(argv[3], &sb)) { 95 perror(argv[3]); 96 die("Couldn't stat root device."); 97 } 98 major_root = major(sb.st_rdev); 99 minor_root = minor(sb.st_rdev); 100 } else { 101 major_root = 0; 102 minor_root = 0; 103 } 104 } else { 105 major_root = DEFAULT_MAJOR_ROOT; 106 minor_root = DEFAULT_MINOR_ROOT; 107 } 108 fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); 109 110 /* Copy the setup code */ 111 file = fopen(argv[1], "r"); 112 if (!file) 113 die("Unable to open `%s': %m", argv[1]); 114 c = fread(buf, 1, sizeof(buf), file); 115 if (ferror(file)) 116 die("read-error on `setup'"); 117 if (c < 1024) 118 die("The setup must be at least 1024 bytes"); 119 if (buf[510] != 0x55 || buf[511] != 0xaa) 120 die("Boot block hasn't got boot flag (0xAA55)"); 121 fclose(file); 122 123 /* Pad unused space with zeros */ 124 setup_sectors = (c + 511) / 512; 125 if (setup_sectors < SETUP_SECT_MIN) 126 setup_sectors = SETUP_SECT_MIN; 127 i = setup_sectors*512; 128 memset(buf+c, 0, i-c); 129 130 /* Set the default root device */ 131 buf[508] = minor_root; 132 buf[509] = major_root; 133 134 fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); 135 136 /* Open and stat the kernel file */ 137 fd = open(argv[2], O_RDONLY); 138 if (fd < 0) 139 die("Unable to open `%s': %m", argv[2]); 140 if (fstat(fd, &sb)) 141 die("Unable to stat `%s': %m", argv[2]); 142 sz = sb.st_size; 143 fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); 144 kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 145 if (kernel == MAP_FAILED) 146 die("Unable to mmap '%s': %m", argv[2]); 147 sys_size = (sz + 15) / 16; 148 if (!is_big_kernel && sys_size > DEF_SYSSIZE) 149 die("System is too big. Try using bzImage or modules."); 150 151 /* Patch the setup code with the appropriate size parameters */ 152 buf[0x1f1] = setup_sectors-1; 153 buf[0x1f4] = sys_size; 154 buf[0x1f5] = sys_size >> 8; 155 buf[0x1f6] = sys_size >> 16; 156 buf[0x1f7] = sys_size >> 24; 157 158 if (fwrite(buf, 1, i, stdout) != i) 159 die("Writing setup failed"); 160 161 /* Copy the kernel code */ 162 if (fwrite(kernel, 1, sz, stdout) != sz) 163 die("Writing kernel failed"); 164 close(fd); 165 166 /* Everything is OK */ 167 return 0; 168 } 169