1/* 2 * $Id: build.c,v 1.1.1.1 2008/10/15 03:26:02 james26_jang Exp $ 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * Copyright (C) 1997 Martin Mares 6 */ 7 8/* 9 * This file builds a disk-image from three different files: 10 * 11 * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest 12 * - setup: 8086 machine code, sets up system parm 13 * - system: 80386 code for actual system 14 * 15 * It does some checking that all files are of the correct type, and 16 * just writes the result to stdout, removing headers and padding to 17 * the right amount. It also writes some system data to stderr. 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 */ 26 27#include <stdio.h> 28#include <string.h> 29#include <stdlib.h> 30#include <stdarg.h> 31#include <sys/types.h> 32#include <sys/stat.h> 33#include <sys/sysmacros.h> 34#include <unistd.h> 35#include <fcntl.h> 36#include <asm/boot.h> 37 38typedef unsigned char byte; 39typedef unsigned short word; 40typedef unsigned long u32; 41 42#define DEFAULT_MAJOR_ROOT 0 43#define DEFAULT_MINOR_ROOT 0 44 45/* Minimal number of setup sectors (see also bootsect.S) */ 46#define SETUP_SECTS 4 47 48byte buf[1024]; 49int fd; 50int is_big_kernel; 51 52void die(const char * str, ...) 53{ 54 va_list args; 55 va_start(args, str); 56 vfprintf(stderr, str, args); 57 fputc('\n', stderr); 58 exit(1); 59} 60 61void file_open(const char *name) 62{ 63 if ((fd = open(name, O_RDONLY, 0)) < 0) 64 die("Unable to open `%s': %m", name); 65} 66 67void usage(void) 68{ 69 die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); 70} 71 72int main(int argc, char ** argv) 73{ 74 unsigned int i, c, sz, setup_sectors; 75 u32 sys_size; 76 byte major_root, minor_root; 77 struct stat sb; 78 79 if (argc > 2 && !strcmp(argv[1], "-b")) 80 { 81 is_big_kernel = 1; 82 argc--, argv++; 83 } 84 if ((argc < 4) || (argc > 5)) 85 usage(); 86 if (argc > 4) { 87 if (!strcmp(argv[4], "CURRENT")) { 88 if (stat("/", &sb)) { 89 perror("/"); 90 die("Couldn't stat /"); 91 } 92 major_root = major(sb.st_dev); 93 minor_root = minor(sb.st_dev); 94 } else if (strcmp(argv[4], "FLOPPY")) { 95 if (stat(argv[4], &sb)) { 96 perror(argv[4]); 97 die("Couldn't stat root device."); 98 } 99 major_root = major(sb.st_rdev); 100 minor_root = minor(sb.st_rdev); 101 } else { 102 major_root = 0; 103 minor_root = 0; 104 } 105 } else { 106 major_root = DEFAULT_MAJOR_ROOT; 107 minor_root = DEFAULT_MINOR_ROOT; 108 } 109 fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); 110 111 file_open(argv[1]); 112 i = read(fd, buf, sizeof(buf)); 113 fprintf(stderr,"Boot sector %d bytes.\n",i); 114 if (i != 512) 115 die("Boot block must be exactly 512 bytes"); 116 if (buf[510] != 0x55 || buf[511] != 0xaa) 117 die("Boot block hasn't got boot flag (0xAA55)"); 118 buf[508] = minor_root; 119 buf[509] = major_root; 120 if (write(1, buf, 512) != 512) 121 die("Write call failed"); 122 close (fd); 123 124 file_open(argv[2]); /* Copy the setup code */ 125 for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) 126 if (write(1, buf, c) != c) 127 die("Write call failed"); 128 if (c != 0) 129 die("read-error on `setup'"); 130 close (fd); 131 132 setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ 133 /* for compatibility with ancient versions of LILO. */ 134 if (setup_sectors < SETUP_SECTS) 135 setup_sectors = SETUP_SECTS; 136 fprintf(stderr, "Setup is %d bytes.\n", i); 137 memset(buf, 0, sizeof(buf)); 138 while (i < setup_sectors * 512) { 139 c = setup_sectors * 512 - i; 140 if (c > sizeof(buf)) 141 c = sizeof(buf); 142 if (write(1, buf, c) != c) 143 die("Write call failed"); 144 i += c; 145 } 146 147 file_open(argv[3]); 148 if (fstat (fd, &sb)) 149 die("Unable to stat `%s': %m", argv[3]); 150 sz = sb.st_size; 151 fprintf (stderr, "System is %d kB\n", sz/1024); 152 sys_size = (sz + 15) / 16; 153 /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */ 154 if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) 155 die("System is too big. Try using %smodules.", 156 is_big_kernel ? "" : "bzImage or "); 157 if (sys_size > 0xefff) 158 fprintf(stderr,"warning: kernel is too big for standalone boot " 159 "from floppy\n"); 160 while (sz > 0) { 161 int l, n; 162 163 l = (sz > sizeof(buf)) ? sizeof(buf) : sz; 164 if ((n=read(fd, buf, l)) != l) { 165 if (n < 0) 166 die("Error reading %s: %m", argv[3]); 167 else 168 die("%s: Unexpected EOF", argv[3]); 169 } 170 if (write(1, buf, l) != l) 171 die("Write failed"); 172 sz -= l; 173 } 174 close(fd); 175 176 if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ 177 die("Output: seek failed"); 178 buf[0] = setup_sectors; 179 if (write(1, buf, 1) != 1) 180 die("Write of setup sector count failed"); 181 if (lseek(1, 500, SEEK_SET) != 500) 182 die("Output: seek failed"); 183 buf[0] = (sys_size & 0xff); 184 buf[1] = ((sys_size >> 8) & 0xff); 185 if (write(1, buf, 2) != 2) 186 die("Write of image length failed"); 187 188 return 0; /* Everything is OK */ 189} 190