2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 1997 Martin Mares
4 * Copyright (C) 2007 H. Peter Anvin
8 * This file builds a disk-image from two different files:
10 * - setup: 8086 machine code, sets up system parm
11 * - system: 80386 code for actual system
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.
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
30 #include <sys/types.h>
32 #include <sys/sysmacros.h>
38 typedef unsigned char u8
;
39 typedef unsigned short u16
;
40 typedef unsigned long u32
;
42 #define DEFAULT_MAJOR_ROOT 0
43 #define DEFAULT_MINOR_ROOT 0
45 /* Minimal number of setup sectors */
46 #define SETUP_SECT_MIN 5
47 #define SETUP_SECT_MAX 64
49 /* This must be large enough to hold the entire setup */
50 u8 buf
[SETUP_SECT_MAX
*512];
53 static void die(const char * str
, ...)
57 vfprintf(stderr
, str
, args
);
62 static void usage(void)
64 die("Usage: build [-b] setup system [rootdev] [> image]");
67 int main(int argc
, char ** argv
)
69 unsigned int i
, sz
, setup_sectors
;
72 u8 major_root
, minor_root
;
78 if (argc
> 2 && !strcmp(argv
[1], "-b"))
83 if ((argc
< 3) || (argc
> 4))
86 if (!strcmp(argv
[3], "CURRENT")) {
89 die("Couldn't stat /");
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
)) {
96 die("Couldn't stat root device.");
98 major_root
= major(sb
.st_rdev
);
99 minor_root
= minor(sb
.st_rdev
);
105 major_root
= DEFAULT_MAJOR_ROOT
;
106 minor_root
= DEFAULT_MINOR_ROOT
;
108 fprintf(stderr
, "Root device is (%d, %d)\n", major_root
, minor_root
);
110 /* Copy the setup code */
111 file
= fopen(argv
[1], "r");
113 die("Unable to open `%s': %m", argv
[1]);
114 c
= fread(buf
, 1, sizeof(buf
), file
);
116 die("read-error on `setup'");
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)");
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
);
130 /* Set the default root device */
131 buf
[508] = minor_root
;
132 buf
[509] = major_root
;
134 fprintf(stderr
, "Setup is %d bytes (padded to %d bytes).\n", c
, i
);
136 /* Open and stat the kernel file */
137 fd
= open(argv
[2], O_RDONLY
);
139 die("Unable to open `%s': %m", argv
[2]);
141 die("Unable to stat `%s': %m", argv
[2]);
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.");
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;
158 if (fwrite(buf
, 1, i
, stdout
) != i
)
159 die("Writing setup failed");
161 /* Copy the kernel code */
162 if (fwrite(kernel
, 1, sz
, stdout
) != sz
)
163 die("Writing kernel failed");
166 /* Everything is OK */