1 /* grub-mkimage.c - make a bootable image */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/machine/boot.h>
23 #include <grub/machine/kernel.h>
24 #include <grub/machine/memory.h>
25 #include <grub/kernel.h>
26 #include <grub/disk.h>
27 #include <grub/util/misc.h>
28 #include <grub/util/resolve.h>
29 #include <grub/misc.h>
39 #if defined(HAVE_LZO_LZO1X_H)
40 # include <lzo/lzo1x.h>
41 #elif defined(HAVE_LZO1X_H)
46 compress_kernel (char *kernel_img
, size_t kernel_size
,
47 char **core_img
, size_t *core_size
)
52 grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img
, kernel_size
);
53 if (kernel_size
< GRUB_KERNEL_MACHINE_RAW_SIZE
)
54 grub_util_error ("the core image is too small");
56 if (lzo_init () != LZO_E_OK
)
57 grub_util_error ("cannot initialize LZO");
59 *core_img
= xmalloc (kernel_size
+ kernel_size
/ 64 + 16 + 3);
60 wrkmem
= xmalloc (LZO1X_999_MEM_COMPRESS
);
62 memcpy (*core_img
, kernel_img
, GRUB_KERNEL_MACHINE_RAW_SIZE
);
64 grub_util_info ("compressing the core image");
65 if (lzo1x_999_compress ((const lzo_byte
*) (kernel_img
66 + GRUB_KERNEL_MACHINE_RAW_SIZE
),
67 kernel_size
- GRUB_KERNEL_MACHINE_RAW_SIZE
,
68 (lzo_byte
*) (*core_img
69 + GRUB_KERNEL_MACHINE_RAW_SIZE
),
72 grub_util_error ("cannot compress the kernel image");
76 *core_size
= (size_t) size
+ GRUB_KERNEL_MACHINE_RAW_SIZE
;
80 generate_image (const char *dir
, char *prefix
, FILE *out
, char *mods
[], char *memdisk_path
)
82 grub_addr_t module_addr
= 0;
83 char *kernel_img
, *boot_img
, *core_img
;
84 size_t kernel_size
, boot_size
, total_module_size
, core_size
, memdisk_size
= 0;
85 char *kernel_path
, *boot_path
;
88 struct grub_util_path_list
*path_list
, *p
, *next
;
89 struct grub_module_info
*modinfo
;
91 path_list
= grub_util_resolve_dependencies (dir
, "moddep.lst", mods
);
93 kernel_path
= grub_util_get_path (dir
, "kernel.img");
94 kernel_size
= grub_util_get_image_size (kernel_path
);
96 total_module_size
= sizeof (struct grub_module_info
);
97 for (p
= path_list
; p
; p
= p
->next
)
98 total_module_size
+= (grub_util_get_image_size (p
->name
)
99 + sizeof (struct grub_module_header
));
101 grub_util_info ("the total module size is 0x%x", total_module_size
);
105 memdisk_size
= ALIGN_UP(grub_util_get_image_size (memdisk_path
), 512);
106 grub_util_info ("the size of memory disk is 0x%x", memdisk_size
);
109 kernel_img
= xmalloc (kernel_size
+ total_module_size
+ memdisk_size
);
110 grub_util_load_image (kernel_path
, kernel_img
);
112 if (GRUB_KERNEL_MACHINE_PREFIX
+ strlen (prefix
) + 1 > GRUB_KERNEL_MACHINE_DATA_END
)
113 grub_util_error ("prefix too long");
114 strcpy (kernel_img
+ GRUB_KERNEL_MACHINE_PREFIX
, prefix
);
116 /* Fill in the grub_module_info structure. */
117 modinfo
= (struct grub_module_info
*) (kernel_img
+ kernel_size
);
118 modinfo
->magic
= GRUB_MODULE_MAGIC
;
119 modinfo
->offset
= sizeof (struct grub_module_info
);
120 modinfo
->size
= total_module_size
;
122 offset
= kernel_size
+ sizeof (struct grub_module_info
);
123 for (p
= path_list
; p
; p
= p
->next
)
125 struct grub_module_header
*header
;
128 mod_size
= grub_util_get_image_size (p
->name
);
130 header
= (struct grub_module_header
*) (kernel_img
+ offset
);
131 header
->offset
= grub_cpu_to_le32 (sizeof (*header
));
132 header
->size
= grub_cpu_to_le32 (mod_size
+ sizeof (*header
));
133 offset
+= sizeof (*header
);
135 grub_util_load_image (p
->name
, kernel_img
+ offset
);
141 grub_util_load_image (memdisk_path
, kernel_img
+ offset
);
142 offset
+= memdisk_size
;
145 compress_kernel (kernel_img
, kernel_size
+ total_module_size
+ memdisk_size
,
146 &core_img
, &core_size
);
148 grub_util_info ("the core size is 0x%x", core_size
);
150 num
= ((core_size
+ GRUB_DISK_SECTOR_SIZE
- 1) >> GRUB_DISK_SECTOR_BITS
);
152 grub_util_error ("the core image is too big");
154 boot_path
= grub_util_get_path (dir
, "diskboot.img");
155 boot_size
= grub_util_get_image_size (boot_path
);
156 if (boot_size
!= GRUB_DISK_SECTOR_SIZE
)
157 grub_util_error ("diskboot.img is not one sector size");
159 boot_img
= grub_util_read_image (boot_path
);
161 /* i386 is a little endian architecture. */
162 *((grub_uint16_t
*) (boot_img
+ GRUB_DISK_SECTOR_SIZE
163 - GRUB_BOOT_MACHINE_LIST_SIZE
+ 8))
164 = grub_cpu_to_le16 (num
);
166 grub_util_write_image (boot_img
, boot_size
, out
);
170 module_addr
= (path_list
171 ? (GRUB_BOOT_MACHINE_KERNEL_ADDR
+ GRUB_DISK_SECTOR_SIZE
175 grub_util_info ("the first module address is 0x%x", module_addr
);
176 *((grub_uint32_t
*) (core_img
+ GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
))
177 = grub_cpu_to_le32 (total_module_size
);
178 *((grub_uint32_t
*) (core_img
+ GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE
))
179 = grub_cpu_to_le32 (kernel_size
);
180 *((grub_uint32_t
*) (core_img
+ GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE
))
181 = grub_cpu_to_le32 (memdisk_size
);
182 *((grub_uint32_t
*) (core_img
+ GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
))
183 = grub_cpu_to_le32 (core_size
- GRUB_KERNEL_MACHINE_RAW_SIZE
);
185 if (core_size
> GRUB_MEMORY_MACHINE_UPPER
- GRUB_MEMORY_MACHINE_LINK_ADDR
)
186 grub_util_error ("Core image is too big (%p > %p)\n", core_size
,
187 GRUB_MEMORY_MACHINE_UPPER
- GRUB_MEMORY_MACHINE_LINK_ADDR
);
189 grub_util_write_image (core_img
, core_size
, out
);
196 next
= path_list
->next
;
197 free ((void *) path_list
->name
);
205 static struct option options
[] =
207 {"directory", required_argument
, 0, 'd'},
208 {"prefix", required_argument
, 0, 'p'},
209 {"memdisk", required_argument
, 0, 'm'},
210 {"output", required_argument
, 0, 'o'},
211 {"help", no_argument
, 0, 'h'},
212 {"version", no_argument
, 0, 'V'},
213 {"verbose", no_argument
, 0, 'v'},
221 fprintf (stderr
, "Try ``grub-mkimage --help'' for more information.\n");
224 Usage: grub-mkimage [OPTION]... [MODULES]\n\
226 Make a bootable image of GRUB.\n\
228 -d, --directory=DIR use images and modules under DIR [default=%s]\n\
229 -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
230 -m, --memdisk=FILE embed FILE as a memdisk image\n\
231 -o, --output=FILE output a generated image to FILE [default=stdout]\n\
232 -h, --help display this message and exit\n\
233 -V, --version print version information and exit\n\
234 -v, --verbose print verbose messages\n\
236 Report bugs to <%s>.\n\
237 ", GRUB_LIBDIR
, DEFAULT_DIRECTORY
, PACKAGE_BUGREPORT
);
243 main (int argc
, char *argv
[])
248 char *memdisk
= NULL
;
251 progname
= "grub-mkimage";
255 int c
= getopt_long (argc
, argv
, "d:p:m:o:hVv", options
, 0);
266 output
= xstrdup (optarg
);
273 dir
= xstrdup (optarg
);
280 memdisk
= xstrdup (optarg
);
291 prefix
= xstrdup (optarg
);
295 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME
, PACKAGE_VERSION
);
310 fp
= fopen (output
, "wb");
312 grub_util_error ("cannot open %s", output
);
315 generate_image (dir
? : GRUB_LIBDIR
, prefix
? : DEFAULT_DIRECTORY
, fp
, argv
+ optind
, memdisk
);