~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/boot/tools/build.c

Version: ~ [ linux-5.5-rc1 ] ~ [ linux-5.4.2 ] ~ [ linux-5.3.15 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.88 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.158 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.206 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.206 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 three different files:
  9  *
 10  * - setup: 8086 machine code, sets up system parm
 11  * - system: 80386 code for actual system
 12  * - zoffset.h: header with ZO_* defines
 13  *
 14  * It does some checking that all files are of the correct type, and writes
 15  * the result to the specified destination, removing headers and padding to
 16  * the right amount. It also writes some system data to stdout.
 17  */
 18 
 19 /*
 20  * Changes by tytso to allow root device specification
 21  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
 22  * Cross compiling fixes by Gertjan van Wingerde, July 1996
 23  * Rewritten by Martin Mares, April 1997
 24  * Substantially overhauled by H. Peter Anvin, April 2007
 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 <unistd.h>
 34 #include <fcntl.h>
 35 #include <sys/mman.h>
 36 #include <tools/le_byteshift.h>
 37 
 38 typedef unsigned char  u8;
 39 typedef unsigned short u16;
 40 typedef unsigned int   u32;
 41 
 42 #define DEFAULT_MAJOR_ROOT 0
 43 #define DEFAULT_MINOR_ROOT 0
 44 #define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
 45 
 46 /* Minimal number of setup sectors */
 47 #define SETUP_SECT_MIN 5
 48 #define SETUP_SECT_MAX 64
 49 
 50 /* This must be large enough to hold the entire setup */
 51 u8 buf[SETUP_SECT_MAX*512];
 52 
 53 #define PECOFF_RELOC_RESERVE 0x20
 54 
 55 unsigned long efi32_stub_entry;
 56 unsigned long efi64_stub_entry;
 57 unsigned long efi_pe_entry;
 58 unsigned long startup_64;
 59 
 60 /*----------------------------------------------------------------------*/
 61 
 62 static const u32 crctab32[] = {
 63         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
 64         0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
 65         0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
 66         0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 67         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
 68         0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
 69         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
 70         0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 71         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
 72         0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
 73         0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
 74         0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 75         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
 76         0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
 77         0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
 78         0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 79         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
 80         0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
 81         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
 82         0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 83         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
 84         0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
 85         0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
 86         0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
 87         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
 88         0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
 89         0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
 90         0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 91         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
 92         0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
 93         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
 94         0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 95         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
 96         0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
 97         0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
 98         0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 99         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
100         0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
101         0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
102         0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
103         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
104         0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
105         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
106         0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
107         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
108         0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
109         0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
110         0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
111         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
112         0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
113         0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
114         0x2d02ef8d
115 };
116 
117 static u32 partial_crc32_one(u8 c, u32 crc)
118 {
119         return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
120 }
121 
122 static u32 partial_crc32(const u8 *s, int len, u32 crc)
123 {
124         while (len--)
125                 crc = partial_crc32_one(*s++, crc);
126         return crc;
127 }
128 
129 static void die(const char * str, ...)
130 {
131         va_list args;
132         va_start(args, str);
133         vfprintf(stderr, str, args);
134         fputc('\n', stderr);
135         exit(1);
136 }
137 
138 static void usage(void)
139 {
140         die("Usage: build setup system zoffset.h image");
141 }
142 
143 #ifdef CONFIG_EFI_STUB
144 
145 static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
146 {
147         unsigned int pe_header;
148         unsigned short num_sections;
149         u8 *section;
150 
151         pe_header = get_unaligned_le32(&buf[0x3c]);
152         num_sections = get_unaligned_le16(&buf[pe_header + 6]);
153 
154 #ifdef CONFIG_X86_32
155         section = &buf[pe_header + 0xa8];
156 #else
157         section = &buf[pe_header + 0xb8];
158 #endif
159 
160         while (num_sections > 0) {
161                 if (strncmp((char*)section, section_name, 8) == 0) {
162                         /* section header size field */
163                         put_unaligned_le32(size, section + 0x8);
164 
165                         /* section header vma field */
166                         put_unaligned_le32(vma, section + 0xc);
167 
168                         /* section header 'size of initialised data' field */
169                         put_unaligned_le32(datasz, section + 0x10);
170 
171                         /* section header 'file offset' field */
172                         put_unaligned_le32(offset, section + 0x14);
173 
174                         break;
175                 }
176                 section += 0x28;
177                 num_sections--;
178         }
179 }
180 
181 static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
182 {
183         update_pecoff_section_header_fields(section_name, offset, size, size, offset);
184 }
185 
186 static void update_pecoff_setup_and_reloc(unsigned int size)
187 {
188         u32 setup_offset = 0x200;
189         u32 reloc_offset = size - PECOFF_RELOC_RESERVE;
190         u32 setup_size = reloc_offset - setup_offset;
191 
192         update_pecoff_section_header(".setup", setup_offset, setup_size);
193         update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
194 
195         /*
196          * Modify .reloc section contents with a single entry. The
197          * relocation is applied to offset 10 of the relocation section.
198          */
199         put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
200         put_unaligned_le32(10, &buf[reloc_offset + 4]);
201 }
202 
203 static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
204 {
205         unsigned int pe_header;
206         unsigned int text_sz = file_sz - text_start;
207 
208         pe_header = get_unaligned_le32(&buf[0x3c]);
209 
210         /*
211          * Size of code: Subtract the size of the first sector (512 bytes)
212          * which includes the header.
213          */
214         put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
215 
216         /*
217          * Address of entry point for PE/COFF executable
218          */
219         put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
220 
221         update_pecoff_section_header(".text", text_start, text_sz);
222 }
223 
224 static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz)
225 {
226         unsigned int pe_header;
227         unsigned int bss_sz = init_sz - file_sz;
228 
229         pe_header = get_unaligned_le32(&buf[0x3c]);
230 
231         /* Size of uninitialized data */
232         put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]);
233 
234         /* Size of image */
235         put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
236 
237         update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0);
238 }
239 
240 static int reserve_pecoff_reloc_section(int c)
241 {
242         /* Reserve 0x20 bytes for .reloc section */
243         memset(buf+c, 0, PECOFF_RELOC_RESERVE);
244         return PECOFF_RELOC_RESERVE;
245 }
246 
247 static void efi_stub_defaults(void)
248 {
249         /* Defaults for old kernel */
250 #ifdef CONFIG_X86_32
251         efi_pe_entry = 0x10;
252 #else
253         efi_pe_entry = 0x210;
254         startup_64 = 0x200;
255 #endif
256 }
257 
258 static void efi_stub_entry_update(void)
259 {
260         unsigned long addr = efi32_stub_entry;
261 
262 #ifdef CONFIG_X86_64
263         /* Yes, this is really how we defined it :( */
264         addr = efi64_stub_entry - 0x200;
265 #endif
266 
267 #ifdef CONFIG_EFI_MIXED
268         if (efi32_stub_entry != addr)
269                 die("32-bit and 64-bit EFI entry points do not match\n");
270 #endif
271         put_unaligned_le32(addr, &buf[0x264]);
272 }
273 
274 #else
275 
276 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
277 static inline void update_pecoff_text(unsigned int text_start,
278                                       unsigned int file_sz) {}
279 static inline void update_pecoff_bss(unsigned int file_sz,
280                                      unsigned int init_sz) {}
281 static inline void efi_stub_defaults(void) {}
282 static inline void efi_stub_entry_update(void) {}
283 
284 static inline int reserve_pecoff_reloc_section(int c)
285 {
286         return 0;
287 }
288 #endif /* CONFIG_EFI_STUB */
289 
290 
291 /*
292  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
293  * but that would mean tools/build would have to be rebuilt every time. It's
294  * not as if parsing it is hard...
295  */
296 #define PARSE_ZOFS(p, sym) do { \
297         if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))       \
298                 sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);         \
299 } while (0)
300 
301 static void parse_zoffset(char *fname)
302 {
303         FILE *file;
304         char *p;
305         int c;
306 
307         file = fopen(fname, "r");
308         if (!file)
309                 die("Unable to open `%s': %m", fname);
310         c = fread(buf, 1, sizeof(buf) - 1, file);
311         if (ferror(file))
312                 die("read-error on `zoffset.h'");
313         fclose(file);
314         buf[c] = 0;
315 
316         p = (char *)buf;
317 
318         while (p && *p) {
319                 PARSE_ZOFS(p, efi32_stub_entry);
320                 PARSE_ZOFS(p, efi64_stub_entry);
321                 PARSE_ZOFS(p, efi_pe_entry);
322                 PARSE_ZOFS(p, startup_64);
323 
324                 p = strchr(p, '\n');
325                 while (p && (*p == '\r' || *p == '\n'))
326                         p++;
327         }
328 }
329 
330 int main(int argc, char ** argv)
331 {
332         unsigned int i, sz, setup_sectors, init_sz;
333         int c;
334         u32 sys_size;
335         struct stat sb;
336         FILE *file, *dest;
337         int fd;
338         void *kernel;
339         u32 crc = 0xffffffffUL;
340 
341         efi_stub_defaults();
342 
343         if (argc != 5)
344                 usage();
345         parse_zoffset(argv[3]);
346 
347         dest = fopen(argv[4], "w");
348         if (!dest)
349                 die("Unable to write `%s': %m", argv[4]);
350 
351         /* Copy the setup code */
352         file = fopen(argv[1], "r");
353         if (!file)
354                 die("Unable to open `%s': %m", argv[1]);
355         c = fread(buf, 1, sizeof(buf), file);
356         if (ferror(file))
357                 die("read-error on `setup'");
358         if (c < 1024)
359                 die("The setup must be at least 1024 bytes");
360         if (get_unaligned_le16(&buf[510]) != 0xAA55)
361                 die("Boot block hasn't got boot flag (0xAA55)");
362         fclose(file);
363 
364         c += reserve_pecoff_reloc_section(c);
365 
366         /* Pad unused space with zeros */
367         setup_sectors = (c + 511) / 512;
368         if (setup_sectors < SETUP_SECT_MIN)
369                 setup_sectors = SETUP_SECT_MIN;
370         i = setup_sectors*512;
371         memset(buf+c, 0, i-c);
372 
373         update_pecoff_setup_and_reloc(i);
374 
375         /* Set the default root device */
376         put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
377 
378         printf("Setup is %d bytes (padded to %d bytes).\n", c, i);
379 
380         /* Open and stat the kernel file */
381         fd = open(argv[2], O_RDONLY);
382         if (fd < 0)
383                 die("Unable to open `%s': %m", argv[2]);
384         if (fstat(fd, &sb))
385                 die("Unable to stat `%s': %m", argv[2]);
386         sz = sb.st_size;
387         printf("System is %d kB\n", (sz+1023)/1024);
388         kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
389         if (kernel == MAP_FAILED)
390                 die("Unable to mmap '%s': %m", argv[2]);
391         /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
392         sys_size = (sz + 15 + 4) / 16;
393 
394         /* Patch the setup code with the appropriate size parameters */
395         buf[0x1f1] = setup_sectors-1;
396         put_unaligned_le32(sys_size, &buf[0x1f4]);
397 
398         update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
399         init_sz = get_unaligned_le32(&buf[0x260]);
400         update_pecoff_bss(i + (sys_size * 16), init_sz);
401 
402         efi_stub_entry_update();
403 
404         crc = partial_crc32(buf, i, crc);
405         if (fwrite(buf, 1, i, dest) != i)
406                 die("Writing setup failed");
407 
408         /* Copy the kernel code */
409         crc = partial_crc32(kernel, sz, crc);
410         if (fwrite(kernel, 1, sz, dest) != sz)
411                 die("Writing kernel failed");
412 
413         /* Add padding leaving 4 bytes for the checksum */
414         while (sz++ < (sys_size*16) - 4) {
415                 crc = partial_crc32_one('\0', crc);
416                 if (fwrite("\0", 1, 1, dest) != 1)
417                         die("Writing padding failed");
418         }
419 
420         /* Write the CRC */
421         printf("CRC %x\n", crc);
422         put_unaligned_le32(crc, buf);
423         if (fwrite(buf, 1, 4, dest) != 4)
424                 die("Writing CRC failed");
425 
426         /* Catch any delayed write failures */
427         if (fclose(dest))
428                 die("Writing image failed");
429 
430         close(fd);
431 
432         /* Everything is OK */
433         return 0;
434 }
435 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp