1 /* grub-setup.c - make GRUB usable */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 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/emu/misc.h>
23 #include <grub/util/misc.h>
24 #include <grub/device.h>
25 #include <grub/disk.h>
26 #include <grub/file.h>
28 #include <grub/partition.h>
30 #include <grub/emu/hostdisk.h>
31 #include <grub/machine/boot.h>
32 #include <grub/machine/kernel.h>
33 #include <grub/term.h>
34 #include <grub/i18n.h>
35 #include <grub/util/lvm.h>
36 #ifdef GRUB_MACHINE_IEEE1275
37 #include <grub/util/ofpath.h>
44 #include <sys/types.h>
48 #include <grub/emu/getroot.h>
50 #include <grub/reed_solomon.h>
51 #include <grub/msdos_partition.h>
52 #include <include/grub/crypto.h>
57 /* On SPARC this program fills in various fields inside of the 'boot' and 'core'
60 * The 'boot' image needs to know the OBP path name of the root
61 * device. It also needs to know the initial block number of
62 * 'core' (which is 'diskboot' concatenated with 'kernel' and
63 * all the modules, this is created by grub-mkimage). This resulting
64 * 'boot' image is 512 bytes in size and is placed in the second block
67 * The initial 'diskboot' block acts as a loader for the actual GRUB
68 * kernel. It contains the loading code and then a block list.
70 * The block list of 'core' starts at the end of the 'diskboot' image
71 * and works it's way backwards towards the end of the code of 'diskboot'.
73 * We patch up the images with the necessary values and write out the
77 #define DEFAULT_BOOT_FILE "boot.img"
78 #define DEFAULT_CORE_FILE "core.img"
80 #ifdef GRUB_MACHINE_SPARC64
81 #define grub_target_to_host16(x) grub_be_to_cpu16(x)
82 #define grub_target_to_host32(x) grub_be_to_cpu32(x)
83 #define grub_target_to_host64(x) grub_be_to_cpu64(x)
84 #define grub_host_to_target16(x) grub_cpu_to_be16(x)
85 #define grub_host_to_target32(x) grub_cpu_to_be32(x)
86 #define grub_host_to_target64(x) grub_cpu_to_be64(x)
87 #elif defined (GRUB_MACHINE_PCBIOS)
88 #define grub_target_to_host16(x) grub_le_to_cpu16(x)
89 #define grub_target_to_host32(x) grub_le_to_cpu32(x)
90 #define grub_target_to_host64(x) grub_le_to_cpu64(x)
91 #define grub_host_to_target16(x) grub_cpu_to_le16(x)
92 #define grub_host_to_target32(x) grub_cpu_to_le32(x)
93 #define grub_host_to_target64(x) grub_cpu_to_le64(x)
99 write_rootdev (char *core_img
, grub_device_t root_dev
,
100 char *boot_img
, grub_uint64_t first_sector
)
102 #ifdef GRUB_MACHINE_PCBIOS
104 grub_uint8_t
*boot_drive
;
105 grub_disk_addr_t
*kernel_sector
;
106 boot_drive
= (grub_uint8_t
*) (boot_img
+ GRUB_BOOT_MACHINE_BOOT_DRIVE
);
107 kernel_sector
= (grub_disk_addr_t
*) (boot_img
108 + GRUB_BOOT_MACHINE_KERNEL_SECTOR
);
110 /* FIXME: can this be skipped? */
113 *kernel_sector
= grub_cpu_to_le64 (first_sector
);
116 #ifdef GRUB_MACHINE_IEEE1275
118 grub_disk_addr_t
*kernel_byte
;
119 kernel_byte
= (grub_disk_addr_t
*) (boot_img
120 + GRUB_BOOT_AOUT_HEADER_SIZE
121 + GRUB_BOOT_MACHINE_KERNEL_BYTE
);
122 *kernel_byte
= grub_cpu_to_be64 (first_sector
<< GRUB_DISK_SECTOR_BITS
);
127 #ifdef GRUB_MACHINE_IEEE1275
128 #define BOOT_SECTOR 1
130 #define BOOT_SECTOR 0
134 setup (const char *dir
,
135 const char *boot_file
, const char *core_file
,
136 const char *dest
, int force
,
137 int fs_probe
, int allow_floppy
)
139 char *boot_path
, *core_path
, *core_path_dev
, *core_path_dev_full
;
140 char *boot_img
, *core_img
;
142 size_t boot_size
, core_size
;
143 grub_uint16_t core_sectors
;
144 grub_device_t root_dev
= 0, dest_dev
;
145 struct grub_boot_blocklist
*first_block
, *block
, *last_block
;
148 grub_disk_addr_t first_sector
;
149 #ifdef GRUB_MACHINE_PCBIOS
150 grub_uint16_t current_segment
151 = GRUB_BOOT_MACHINE_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE
>> 4);
153 grub_uint16_t last_length
= GRUB_DISK_SECTOR_SIZE
;
157 auto void NESTED_FUNC_ATTR
save_first_sector (grub_disk_addr_t sector
,
160 auto void NESTED_FUNC_ATTR
save_blocklists (grub_disk_addr_t sector
,
164 void NESTED_FUNC_ATTR
save_first_sector (grub_disk_addr_t sector
,
168 grub_util_info ("the first sector is <%llu,%u,%u>",
169 sector
, offset
, length
);
171 if (offset
!= 0 || length
!= GRUB_DISK_SECTOR_SIZE
)
172 grub_util_error (_("the first sector of the core file is not sector-aligned"));
174 first_sector
= sector
;
177 void NESTED_FUNC_ATTR
save_blocklists (grub_disk_addr_t sector
,
181 struct grub_boot_blocklist
*prev
= block
+ 1;
183 grub_util_info ("saving <%llu,%u,%u>", sector
, offset
, length
);
185 if (offset
!= 0 || last_length
!= GRUB_DISK_SECTOR_SIZE
)
186 grub_util_error (_("non-sector-aligned data is found in the core file"));
188 if (block
!= first_block
189 && (grub_target_to_host64 (prev
->start
)
190 + grub_target_to_host16 (prev
->len
)) == sector
)
191 prev
->len
= grub_host_to_target16 (grub_target_to_host16 (prev
->len
) + 1);
194 block
->start
= grub_host_to_target64 (sector
);
195 block
->len
= grub_host_to_target16 (1);
196 #ifdef GRUB_MACHINE_PCBIOS
197 block
->segment
= grub_host_to_target16 (current_segment
);
202 grub_util_error (_("the sectors of the core file are too fragmented"));
205 last_length
= length
;
206 #ifdef GRUB_MACHINE_PCBIOS
207 current_segment
+= GRUB_DISK_SECTOR_SIZE
>> 4;
211 /* Read the boot image by the OS service. */
212 boot_path
= grub_util_get_path (dir
, boot_file
);
213 boot_size
= grub_util_get_image_size (boot_path
);
214 if (boot_size
!= GRUB_DISK_SECTOR_SIZE
)
215 grub_util_error (_("the size of `%s' is not %u"),
216 boot_path
, GRUB_DISK_SECTOR_SIZE
);
217 boot_img
= grub_util_read_image (boot_path
);
220 core_path
= grub_util_get_path (dir
, core_file
);
221 core_size
= grub_util_get_image_size (core_path
);
222 core_sectors
= ((core_size
+ GRUB_DISK_SECTOR_SIZE
- 1)
223 >> GRUB_DISK_SECTOR_BITS
);
224 if (core_size
< GRUB_DISK_SECTOR_SIZE
)
225 grub_util_error (_("the size of `%s' is too small"), core_path
);
226 #ifdef GRUB_MACHINE_PCBIOS
227 if (core_size
> 0xFFFF * GRUB_DISK_SECTOR_SIZE
)
228 grub_util_error (_("the size of `%s' is too large"), core_path
);
231 core_img
= grub_util_read_image (core_path
);
233 /* Have FIRST_BLOCK to point to the first blocklist. */
234 first_block
= (struct grub_boot_blocklist
*) (core_img
235 + GRUB_DISK_SECTOR_SIZE
237 grub_util_info ("root is `%s', dest is `%s'", root
, dest
);
239 grub_util_info ("Opening dest");
240 dest_dev
= grub_device_open (dest
);
242 grub_util_error ("%s", _(grub_errmsg
));
245 char **root_devices
= grub_guess_root_devices (dir
);
249 for (cur
= root_devices
; *cur
; cur
++)
252 grub_device_t try_dev
;
254 drive
= grub_util_get_grub_dev (*cur
);
257 try_dev
= grub_device_open (drive
);
260 if (!found
&& try_dev
->disk
->id
== dest_dev
->disk
->id
261 && try_dev
->disk
->dev
->id
== dest_dev
->disk
->dev
->id
)
264 grub_device_close (root_dev
);
277 grub_device_close (try_dev
);
282 grub_util_error ("guessing the root device failed, because of `%s'",
285 grub_util_info ("guessed root_dev `%s' from "
286 "dir `%s'", root_dev
->disk
->name
, dir
);
289 grub_util_info ("setting the root device to `%s'", root
);
290 if (grub_env_set ("root", root
) != GRUB_ERR_NONE
)
291 grub_util_error ("%s", _(grub_errmsg
));
293 #ifdef GRUB_MACHINE_PCBIOS
294 /* Read the original sector from the disk. */
295 tmp_img
= xmalloc (GRUB_DISK_SECTOR_SIZE
);
296 if (grub_disk_read (dest_dev
->disk
, 0, 0, GRUB_DISK_SECTOR_SIZE
, tmp_img
))
297 grub_util_error ("%s", _(grub_errmsg
));
300 #ifdef GRUB_MACHINE_PCBIOS
302 grub_uint16_t
*boot_drive_check
;
303 boot_drive_check
= (grub_uint16_t
*) (boot_img
304 + GRUB_BOOT_MACHINE_DRIVE_CHECK
);
305 /* Copy the possible DOS BPB. */
306 memcpy (boot_img
+ GRUB_BOOT_MACHINE_BPB_START
,
307 tmp_img
+ GRUB_BOOT_MACHINE_BPB_START
,
308 GRUB_BOOT_MACHINE_BPB_END
- GRUB_BOOT_MACHINE_BPB_START
);
310 /* If DEST_DRIVE is a hard disk, enable the workaround, which is
311 for buggy BIOSes which don't pass boot drive correctly. Instead,
312 they pass 0x00 or 0x01 even when booted from 0x80. */
313 if (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
))
314 /* Replace the jmp (2 bytes) with double nop's. */
315 *boot_drive_check
= 0x9090;
319 #ifdef GRUB_MACHINE_PCBIOS
321 grub_partition_map_t dest_partmap
= NULL
;
322 grub_partition_t container
= dest_dev
->disk
->partition
;
323 int multiple_partmaps
= 0;
326 grub_disk_addr_t
*sectors
;
331 /* Unlike root_dev, with dest_dev we're interested in the partition map even
332 if dest_dev itself is a whole disk. */
333 auto int NESTED_FUNC_ATTR
identify_partmap (grub_disk_t disk
,
334 const grub_partition_t p
);
335 int NESTED_FUNC_ATTR
identify_partmap (grub_disk_t disk
__attribute__ ((unused
)),
336 const grub_partition_t p
)
338 if (p
->parent
!= container
)
340 /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
341 so they are safe to ignore.
343 if (grub_strcmp (p
->partmap
->name
, "netbsd") == 0
344 || grub_strcmp (p
->partmap
->name
, "openbsd") == 0)
346 if (dest_partmap
== NULL
)
348 dest_partmap
= p
->partmap
;
351 if (dest_partmap
== p
->partmap
)
353 multiple_partmaps
= 1;
357 grub_partition_iterate (dest_dev
->disk
, identify_partmap
);
359 if (container
&& grub_strcmp (container
->partmap
->name
, "msdos") == 0
361 && (container
->msdostype
== GRUB_PC_PARTITION_TYPE_NETBSD
362 || container
->msdostype
== GRUB_PC_PARTITION_TYPE_OPENBSD
))
364 grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
365 goto unable_to_embed
;
368 fs
= grub_fs_probe (dest_dev
);
370 grub_errno
= GRUB_ERR_NONE
;
372 is_ldm
= grub_util_is_ldm (dest_dev
->disk
);
374 #ifdef GRUB_MACHINE_PCBIOS
377 if (!fs
&& !dest_partmap
)
378 grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
379 dest_dev
->disk
->name
);
380 if (fs
&& !fs
->reserved_first_sector
)
381 grub_util_error (_("%s appears to contain a %s filesystem which isn't known to "
382 "reserve space for DOS-style boot. Installing GRUB there could "
383 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
384 "by grub-setup (--skip-fs-probe disables this "
385 "check, use at your own risk)"), dest_dev
->disk
->name
, fs
->name
);
387 if (dest_partmap
&& strcmp (dest_partmap
->name
, "msdos") != 0
388 && strcmp (dest_partmap
->name
, "gpt") != 0
389 && strcmp (dest_partmap
->name
, "bsd") != 0
390 && strcmp (dest_partmap
->name
, "netbsd") != 0
391 && strcmp (dest_partmap
->name
, "openbsd") != 0
392 && strcmp (dest_partmap
->name
, "sunpc") != 0)
393 grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
394 "reserve space for DOS-style boot. Installing GRUB there could "
395 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
396 "by grub-setup (--skip-fs-probe disables this "
397 "check, use at your own risk)"), dest_dev
->disk
->name
, dest_partmap
->name
);
398 if (is_ldm
&& dest_partmap
&& strcmp (dest_partmap
->name
, "msdos") != 0
399 && strcmp (dest_partmap
->name
, "gpt") != 0)
400 grub_util_error (_("%s appears to contain a %s partition map and "
401 "LDM which isn't known to be a safe combination."
402 " Installing GRUB there could "
403 "result in FILESYSTEM DESTRUCTION if valuable data"
405 "by grub-setup (--skip-fs-probe disables this "
406 "check, use at your own risk)"),
407 dest_dev
->disk
->name
, dest_partmap
->name
);
412 /* Copy the partition table. */
414 (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
)))
415 memcpy (boot_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
416 tmp_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
417 GRUB_BOOT_MACHINE_PART_END
- GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
);
421 if (! dest_partmap
&& ! fs
&& !is_ldm
)
423 grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
424 goto unable_to_embed
;
426 if (multiple_partmaps
|| (dest_partmap
&& fs
) || (is_ldm
&& fs
))
428 grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
429 goto unable_to_embed
;
432 if (dest_partmap
&& !dest_partmap
->embed
)
434 grub_util_warn (_("Partition style '%s' doesn't support embeding"),
436 goto unable_to_embed
;
439 if (fs
&& !fs
->embed
)
441 grub_util_warn (_("File system '%s' doesn't support embeding"),
443 goto unable_to_embed
;
448 err
= grub_util_ldm_embed (dest_dev
->disk
, &nsec
,
449 GRUB_EMBED_PCBIOS
, §ors
);
450 else if (dest_partmap
)
451 err
= dest_partmap
->embed (dest_dev
->disk
, &nsec
,
452 GRUB_EMBED_PCBIOS
, §ors
);
454 err
= fs
->embed (dest_dev
, &nsec
,
455 GRUB_EMBED_PCBIOS
, §ors
);
456 if (!err
&& nsec
< core_sectors
)
458 err
= grub_error (GRUB_ERR_OUT_OF_RANGE
,
459 N_("Your embedding area is unusually small. "
460 "core.img won't fit in it."));
465 grub_util_warn ("%s", _(grub_errmsg
));
466 grub_errno
= GRUB_ERR_NONE
;
467 goto unable_to_embed
;
470 if (nsec
> 2 * core_sectors
)
471 nsec
= 2 * core_sectors
;
472 if (nsec
> ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
473 >> GRUB_DISK_SECTOR_BITS
))
474 nsec
= ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
475 >> GRUB_DISK_SECTOR_BITS
);
477 /* Clean out the blocklists. */
481 grub_memset (block
, 0, sizeof (block
));
485 if ((char *) block
<= core_img
)
486 grub_util_error (_("no terminator in the core image"));
489 save_first_sector (sectors
[0] + grub_partition_get_start (container
),
490 0, GRUB_DISK_SECTOR_SIZE
);
493 for (i
= 1; i
< nsec
; i
++)
494 save_blocklists (sectors
[i
] + grub_partition_get_start (container
),
495 0, GRUB_DISK_SECTOR_SIZE
);
497 write_rootdev (core_img
, root_dev
, boot_img
, first_sector
);
499 core_img
= realloc (core_img
, nsec
* GRUB_DISK_SECTOR_SIZE
);
500 first_block
= (struct grub_boot_blocklist
*) (core_img
501 + GRUB_DISK_SECTOR_SIZE
504 grub_size_t no_rs_length
;
505 *(grub_uint32_t
*) (core_img
+ GRUB_DISK_SECTOR_SIZE
506 + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
)
507 = grub_host_to_target32 (nsec
* GRUB_DISK_SECTOR_SIZE
- core_size
);
508 no_rs_length
= grub_target_to_host16
509 (*(grub_uint16_t
*) (core_img
510 + GRUB_DISK_SECTOR_SIZE
511 + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
));
513 if (no_rs_length
== 0xffff)
514 grub_util_error (_("core.img version mismatch"));
516 void *tmp
= xmalloc (core_size
);
517 grub_memcpy (tmp
, core_img
, core_size
);
518 grub_reed_solomon_add_redundancy (core_img
+ no_rs_length
+ GRUB_DISK_SECTOR_SIZE
,
519 core_size
- no_rs_length
- GRUB_DISK_SECTOR_SIZE
,
520 nsec
* GRUB_DISK_SECTOR_SIZE
522 assert (grub_memcmp (tmp
, core_img
, core_size
) == 0);
525 /* Make sure that the second blocklist is a terminator. */
526 block
= first_block
- 1;
531 /* Write the core image onto the disk. */
532 for (i
= 0; i
< nsec
; i
++)
533 grub_disk_write (dest_dev
->disk
, sectors
[i
], 0,
534 GRUB_DISK_SECTOR_SIZE
,
535 core_img
+ i
* GRUB_DISK_SECTOR_SIZE
);
545 #ifdef GRUB_MACHINE_PCBIOS
546 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
547 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
548 grub_util_error (_("embedding is not possible, but this is required for "
549 "cross-disk, RAID and LVM install"));
551 if (dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
552 grub_util_error (_("embedding is not possible, but this is required for "
553 "RAID and LVM install"));
557 grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this "
558 "setup by using blocklists. However, blocklists are UNRELIABLE and "
559 "their use is discouraged."));
561 grub_util_error (_("will not proceed with blocklists"));
563 /* The core image must be put on a filesystem unfortunately. */
564 grub_util_info ("will leave the core image on the filesystem");
566 /* Make sure that GRUB reads the identical image as the OS. */
567 tmp_img
= xmalloc (core_size
);
568 core_path_dev_full
= grub_util_get_path (dir
, core_file
);
569 core_path_dev
= grub_make_system_path_relative_to_its_root (core_path_dev_full
);
570 free (core_path_dev_full
);
572 grub_util_biosdisk_flush (root_dev
->disk
);
576 for (i
= 0; i
< MAX_TRIES
; i
++)
578 grub_util_info ((i
== 0) ? _("attempting to read the core image `%s' from GRUB")
579 : _("attempting to read the core image `%s' from GRUB again"),
582 grub_disk_cache_invalidate_all ();
584 grub_file_filter_disable_compression ();
585 file
= grub_file_open (core_path_dev
);
588 if (grub_file_size (file
) != core_size
)
589 grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
590 (int) grub_file_size (file
), (int) core_size
);
591 else if (grub_file_read (file
, tmp_img
, core_size
)
592 != (grub_ssize_t
) core_size
)
593 grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
595 else if (memcmp (core_img
, tmp_img
, core_size
) != 0)
601 dump
= fopen ("dump.img", "wb");
604 fwrite (tmp_img
, 1, core_size
, dump
);
608 dump2
= fopen ("dump2.img", "wb");
611 fwrite (core_img
, 1, core_size
, dump2
);
616 grub_util_info ("succeeded in opening the core image but the data is different");
620 grub_file_close (file
);
624 grub_file_close (file
);
627 grub_util_info ("couldn't open the core image");
630 grub_util_info ("error message = %s", grub_errmsg
);
632 grub_errno
= GRUB_ERR_NONE
;
633 grub_util_biosdisk_flush (root_dev
->disk
);
638 grub_util_error (_("cannot read `%s' correctly"), core_path_dev
);
640 /* Clean out the blocklists. */
646 #ifdef GRUB_MACHINE_PCBIOS
652 if ((char *) block
<= core_img
)
653 grub_util_error (_("no terminator in the core image"));
656 /* Now read the core image to determine where the sectors are. */
657 grub_file_filter_disable_compression ();
658 file
= grub_file_open (core_path_dev
);
660 grub_util_error ("%s", _(grub_errmsg
));
662 file
->read_hook
= save_first_sector
;
663 if (grub_file_read (file
, tmp_img
, GRUB_DISK_SECTOR_SIZE
)
664 != GRUB_DISK_SECTOR_SIZE
)
665 grub_util_error (_("failed to read the first sector of the core image"));
668 file
->read_hook
= save_blocklists
;
669 if (grub_file_read (file
, tmp_img
, core_size
- GRUB_DISK_SECTOR_SIZE
)
670 != (grub_ssize_t
) core_size
- GRUB_DISK_SECTOR_SIZE
)
671 grub_util_error (_("failed to read the rest sectors of the core image"));
673 #ifdef GRUB_MACHINE_IEEE1275
676 boot_devpath
= (char *) (boot_img
677 + GRUB_BOOT_AOUT_HEADER_SIZE
678 + GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
679 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
680 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
682 const char *dest_ofpath
;
684 = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev
->disk
));
685 grub_util_info ("dest_ofpath is `%s'", dest_ofpath
);
686 strncpy (boot_devpath
, dest_ofpath
, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
687 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1);
688 boot_devpath
[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
689 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1] = 0;
693 grub_util_info ("non cross-disk install");
694 memset (boot_devpath
, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
695 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
697 grub_util_info ("boot device path %s", boot_devpath
);
701 grub_file_close (file
);
703 free (core_path_dev
);
706 write_rootdev (core_img
, root_dev
, boot_img
, first_sector
);
708 /* Write the first two sectors of the core image onto the disk. */
709 grub_util_info ("opening the core image `%s'", core_path
);
710 fp
= fopen (core_path
, "r+b");
712 grub_util_error (_("cannot open `%s': %s"), core_path
,
715 grub_util_write_image (core_img
, GRUB_DISK_SECTOR_SIZE
* 2, fp
, core_path
);
720 /* Write the boot image onto the disk. */
721 if (grub_disk_write (dest_dev
->disk
, BOOT_SECTOR
,
722 0, GRUB_DISK_SECTOR_SIZE
, boot_img
))
723 grub_util_error ("%s", _(grub_errmsg
));
725 grub_util_biosdisk_flush (root_dev
->disk
);
726 grub_util_biosdisk_flush (dest_dev
->disk
);
731 grub_device_close (dest_dev
);
732 grub_device_close (root_dev
);
735 static struct argp_option options
[] = {
736 {"boot-image", 'b', N_("FILE"), 0,
737 N_("Use FILE as the boot image [default=%s]"), 0},
738 {"core-image", 'c', N_("FILE"), 0,
739 N_("Use FILE as the core image [default=%s]"), 0},
740 {"directory", 'd', N_("DIR"), 0,
741 N_("Use GRUB files in the directory DIR [default=%s]"), 0},
742 {"device-map", 'm', N_("FILE"), 0,
743 N_("Use FILE as the device map [default=%s]"), 0},
744 {"root-device", 'r', N_("DEVICE"), 0,
745 N_("Use DEV as the root device [default=guessed]"), 0},
747 N_("Install even if problems are detected"), 0},
748 {"skip-fs-probe",'s',0, 0,
749 N_("Do not probe for filesystems in DEVICE"), 0},
750 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
751 {"allow-floppy", 'a', 0, 0,
752 N_("Make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0},
758 help_filter (int key
, const char *text
, void *input
__attribute__ ((unused
)))
763 return xasprintf (text
, DEFAULT_BOOT_FILE
);
766 return xasprintf (text
, DEFAULT_CORE_FILE
);
769 return xasprintf (text
, DEFAULT_DIRECTORY
);
772 return xasprintf (text
, DEFAULT_DEVICE_MAP
);
775 return (char *) text
;
792 argp_parser (int key
, char *arg
, struct argp_state
*state
)
794 /* Get the input argument from argp_parse, which we
795 know is a pointer to our arguments structure. */
796 struct arguments
*arguments
= state
->input
;
803 arguments
->allow_floppy
= 1;
807 if (arguments
->boot_file
)
808 free (arguments
->boot_file
);
810 arguments
->boot_file
= xstrdup (arg
);
814 if (arguments
->core_file
)
815 free (arguments
->core_file
);
817 arguments
->core_file
= xstrdup (arg
);
822 free (arguments
->dir
);
824 arguments
->dir
= xstrdup (arg
);
828 if (arguments
->dev_map
)
829 free (arguments
->dev_map
);
831 arguments
->dev_map
= xstrdup (arg
);
835 arguments
->force
= 1;
839 arguments
->fs_probe
= 0;
847 if (state
->arg_num
== 0)
848 arguments
->device
= xstrdup(arg
);
851 /* Too many arguments. */
852 fprintf (stderr
, _("Unknown extra argument `%s'.\n"), arg
);
857 case ARGP_KEY_NO_ARGS
:
858 fprintf (stderr
, "%s", _("No device is specified.\n"));
864 return ARGP_ERR_UNKNOWN
;
870 static struct argp argp
= {
871 options
, argp_parser
, N_("DEVICE"),
873 Set up images to boot from DEVICE.\n\
875 You should not normally run this program directly. Use grub-install instead.")
877 DEVICE must be an OS device (e.g. /dev/sda)."),
878 NULL
, help_filter
, NULL
882 get_device_name (char *dev
)
884 size_t len
= strlen (dev
);
886 if (dev
[0] != '(' || dev
[len
- 1] != ')')
894 main (int argc
, char *argv
[])
896 char *root_dev
= NULL
;
897 char *dest_dev
= NULL
;
898 struct arguments arguments
;
900 set_program_name (argv
[0]);
902 grub_util_init_nls ();
904 /* Default option values. */
905 memset (&arguments
, 0, sizeof (struct arguments
));
906 arguments
.fs_probe
= 1;
908 /* Parse our arguments */
909 if (argp_parse (&argp
, argc
, argv
, 0, 0, &arguments
) != 0)
911 fprintf (stderr
, "%s", _("Error in parsing command line arguments\n"));
915 #ifdef GRUB_MACHINE_IEEE1275
920 grub_env_set ("debug", "all");
922 /* Initialize the emulated biosdisk driver. */
923 grub_util_biosdisk_init (arguments
.dev_map
? : DEFAULT_DEVICE_MAP
);
925 /* Initialize all modules. */
927 grub_gcry_init_all ();
930 grub_mdraid09_fini ();
931 grub_mdraid1x_fini ();
932 grub_diskfilter_fini ();
933 grub_diskfilter_init ();
934 grub_mdraid09_init ();
935 grub_mdraid1x_init ();
938 dest_dev
= get_device_name (arguments
.device
);
941 /* Possibly, the user specified an OS device file. */
942 dest_dev
= grub_util_get_grub_dev (arguments
.device
);
945 char *program
= xstrdup(program_name
);
946 fprintf (stderr
, _("Invalid device `%s'.\n"), arguments
.device
);
947 argp_help (&argp
, stderr
, ARGP_HELP_STD_USAGE
, program
);
951 grub_util_info ("transformed OS device `%s' into GRUB device `%s'",
952 arguments
.device
, dest_dev
);
956 /* For simplicity. */
957 dest_dev
= xstrdup (dest_dev
);
958 grub_util_info ("Using `%s' as GRUB device", dest_dev
);
961 /* Do the real work. */
962 setup (arguments
.dir
? : DEFAULT_DIRECTORY
,
963 arguments
.boot_file
? : DEFAULT_BOOT_FILE
,
964 arguments
.core_file
? : DEFAULT_CORE_FILE
,
965 dest_dev
, arguments
.force
,
966 arguments
.fs_probe
, arguments
.allow_floppy
);
968 /* Free resources. */
970 grub_util_biosdisk_fini ();
972 free (arguments
.boot_file
);
973 free (arguments
.core_file
);
974 free (arguments
.dir
);
975 free (arguments
.dev_map
);
976 free (arguments
.device
);