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>
37 #include <tools/le_byteshift.h>
39 typedef unsigned char u8
;
40 typedef unsigned short u16
;
41 typedef unsigned long u32
;
43 #define DEFAULT_MAJOR_ROOT 0
44 #define DEFAULT_MINOR_ROOT 0
45 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
47 /* Minimal number of setup sectors */
48 #define SETUP_SECT_MIN 5
49 #define SETUP_SECT_MAX 64
51 /* This must be large enough to hold the entire setup */
52 u8 buf
[SETUP_SECT_MAX
*512];
55 /*----------------------------------------------------------------------*/
57 static const u32 crctab32
[] = {
58 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
59 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
60 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
61 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
62 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
63 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
64 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
65 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
66 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
67 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
68 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
69 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
70 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
71 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
72 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
73 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
74 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
75 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
76 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
77 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
78 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
79 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
80 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
81 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
82 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
83 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
84 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
85 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
86 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
87 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
88 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
89 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
90 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
91 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
92 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
93 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
94 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
95 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
96 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
97 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
98 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
99 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
100 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
101 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
102 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
103 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
104 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
105 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
106 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
107 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
108 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
112 static u32
partial_crc32_one(u8 c
, u32 crc
)
114 return crctab32
[(crc
^ c
) & 0xff] ^ (crc
>> 8);
117 static u32
partial_crc32(const u8
*s
, int len
, u32 crc
)
120 crc
= partial_crc32_one(*s
++, crc
);
124 static void die(const char * str
, ...)
128 vfprintf(stderr
, str
, args
);
133 static void usage(void)
135 die("Usage: build setup system [> image]");
138 int main(int argc
, char ** argv
)
140 #ifdef CONFIG_EFI_STUB
141 unsigned int file_sz
, pe_header
;
143 unsigned int i
, sz
, setup_sectors
;
150 u32 crc
= 0xffffffffUL
;
155 /* Copy the setup code */
156 file
= fopen(argv
[1], "r");
158 die("Unable to open `%s': %m", argv
[1]);
159 c
= fread(buf
, 1, sizeof(buf
), file
);
161 die("read-error on `setup'");
163 die("The setup must be at least 1024 bytes");
164 if (get_unaligned_le16(&buf
[510]) != 0xAA55)
165 die("Boot block hasn't got boot flag (0xAA55)");
168 /* Pad unused space with zeros */
169 setup_sectors
= (c
+ 511) / 512;
170 if (setup_sectors
< SETUP_SECT_MIN
)
171 setup_sectors
= SETUP_SECT_MIN
;
172 i
= setup_sectors
*512;
173 memset(buf
+c
, 0, i
-c
);
175 /* Set the default root device */
176 put_unaligned_le16(DEFAULT_ROOT_DEV
, &buf
[508]);
178 fprintf(stderr
, "Setup is %d bytes (padded to %d bytes).\n", c
, i
);
180 /* Open and stat the kernel file */
181 fd
= open(argv
[2], O_RDONLY
);
183 die("Unable to open `%s': %m", argv
[2]);
185 die("Unable to stat `%s': %m", argv
[2]);
187 fprintf (stderr
, "System is %d kB\n", (sz
+1023)/1024);
188 kernel
= mmap(NULL
, sz
, PROT_READ
, MAP_SHARED
, fd
, 0);
189 if (kernel
== MAP_FAILED
)
190 die("Unable to mmap '%s': %m", argv
[2]);
191 /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
192 sys_size
= (sz
+ 15 + 4) / 16;
194 /* Patch the setup code with the appropriate size parameters */
195 buf
[0x1f1] = setup_sectors
-1;
196 put_unaligned_le32(sys_size
, &buf
[0x1f4]);
198 #ifdef CONFIG_EFI_STUB
199 file_sz
= sz
+ i
+ ((sys_size
* 16) - sz
);
201 pe_header
= get_unaligned_le32(&buf
[0x3c]);
204 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0x1c]);
207 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0x50]);
211 * Address of entry point.
213 * The EFI stub entry point is +16 bytes from the start of
216 put_unaligned_le32(i
+ 16, &buf
[pe_header
+ 0x28]);
219 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0xb0]);
221 /* .text size of initialised data */
222 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0xb8]);
225 * Address of entry point. startup_32 is at the beginning and
226 * the 64-bit entry point (startup_64) is always 512 bytes
227 * after. The EFI stub entry point is 16 bytes after that, as
228 * the first instruction allows legacy loaders to jump over
229 * the EFI stub initialisation
231 put_unaligned_le32(i
+ 528, &buf
[pe_header
+ 0x28]);
234 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0xc0]);
236 /* .text size of initialised data */
237 put_unaligned_le32(file_sz
, &buf
[pe_header
+ 0xc8]);
239 #endif /* CONFIG_X86_32 */
240 #endif /* CONFIG_EFI_STUB */
242 crc
= partial_crc32(buf
, i
, crc
);
243 if (fwrite(buf
, 1, i
, stdout
) != i
)
244 die("Writing setup failed");
246 /* Copy the kernel code */
247 crc
= partial_crc32(kernel
, sz
, crc
);
248 if (fwrite(kernel
, 1, sz
, stdout
) != sz
)
249 die("Writing kernel failed");
251 /* Add padding leaving 4 bytes for the checksum */
252 while (sz
++ < (sys_size
*16) - 4) {
253 crc
= partial_crc32_one('\0', crc
);
254 if (fwrite("\0", 1, 1, stdout
) != 1)
255 die("Writing padding failed");
259 fprintf(stderr
, "CRC %lx\n", crc
);
260 if (fwrite(&crc
, 1, 4, stdout
) != 4)
261 die("Writing CRC failed");
265 /* Everything is OK */