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/term.h>
32 #include <grub/i18n.h>
34 #ifdef GRUB_SETUP_SPARC64
35 #include <grub/util/ofpath.h>
36 #include <grub/sparc64/ieee1275/boot.h>
37 #include <grub/sparc64/ieee1275/kernel.h>
39 #include <grub/i386/pc/boot.h>
40 #include <grub/i386/pc/kernel.h>
47 #include <sys/types.h>
51 #include <grub/emu/getroot.h>
53 #include <grub/reed_solomon.h>
54 #include <grub/msdos_partition.h>
55 #include <grub/crypto.h>
56 #include <grub/util/install.h>
57 #include <grub/emu/hostfile.h>
61 /* On SPARC this program fills in various fields inside of the 'boot' and 'core'
64 * The 'boot' image needs to know the OBP path name of the root
65 * device. It also needs to know the initial block number of
66 * 'core' (which is 'diskboot' concatenated with 'kernel' and
67 * all the modules, this is created by grub-mkimage). This resulting
68 * 'boot' image is 512 bytes in size and is placed in the second block
71 * The initial 'diskboot' block acts as a loader for the actual GRUB
72 * kernel. It contains the loading code and then a block list.
74 * The block list of 'core' starts at the end of the 'diskboot' image
75 * and works it's way backwards towards the end of the code of 'diskboot'.
77 * We patch up the images with the necessary values and write out the
81 #ifdef GRUB_SETUP_SPARC64
82 #define grub_target_to_host16(x) grub_be_to_cpu16(x)
83 #define grub_target_to_host32(x) grub_be_to_cpu32(x)
84 #define grub_target_to_host64(x) grub_be_to_cpu64(x)
85 #define grub_host_to_target16(x) grub_cpu_to_be16(x)
86 #define grub_host_to_target32(x) grub_cpu_to_be32(x)
87 #define grub_host_to_target64(x) grub_cpu_to_be64(x)
88 #elif defined (GRUB_SETUP_BIOS)
89 #define grub_target_to_host16(x) grub_le_to_cpu16(x)
90 #define grub_target_to_host32(x) grub_le_to_cpu32(x)
91 #define grub_target_to_host64(x) grub_le_to_cpu64(x)
92 #define grub_host_to_target16(x) grub_cpu_to_le16(x)
93 #define grub_host_to_target32(x) grub_cpu_to_le32(x)
94 #define grub_host_to_target64(x) grub_cpu_to_le64(x)
100 write_rootdev (grub_device_t root_dev
,
101 char *boot_img
, grub_uint64_t first_sector
)
103 #ifdef GRUB_SETUP_BIOS
105 grub_uint8_t
*boot_drive
;
107 boot_drive
= (grub_uint8_t
*) (boot_img
+ GRUB_BOOT_MACHINE_BOOT_DRIVE
);
108 kernel_sector
= (boot_img
+ GRUB_BOOT_MACHINE_KERNEL_SECTOR
);
110 /* FIXME: can this be skipped? */
113 grub_set_unaligned64 (kernel_sector
, grub_cpu_to_le64 (first_sector
));
116 #ifdef GRUB_SETUP_SPARC64
119 kernel_byte
= (boot_img
+ GRUB_BOOT_AOUT_HEADER_SIZE
120 + GRUB_BOOT_MACHINE_KERNEL_BYTE
);
121 grub_set_unaligned64 (kernel_byte
,
122 grub_cpu_to_be64 (first_sector
<< GRUB_DISK_SECTOR_BITS
));
127 #ifdef GRUB_SETUP_SPARC64
128 #define BOOT_SECTOR 1
130 #define BOOT_SECTOR 0
133 /* Helper for setup. */
137 struct grub_boot_blocklist
*first_block
, *block
;
138 #ifdef GRUB_SETUP_BIOS
139 grub_uint16_t current_segment
;
141 grub_uint16_t last_length
;
142 grub_disk_addr_t first_sector
;
145 /* Helper for setup. */
147 save_blocklists (grub_disk_addr_t sector
, unsigned offset
, unsigned length
,
150 struct blocklists
*bl
= data
;
151 struct grub_boot_blocklist
*prev
= bl
->block
+ 1;
152 grub_uint64_t seclen
;
154 grub_util_info ("saving <%" GRUB_HOST_PRIuLONG_LONG
",%u,%u>",
155 (unsigned long long) sector
, offset
, length
);
157 if (bl
->first_sector
== (grub_disk_addr_t
) -1)
159 if (offset
!= 0 || length
< GRUB_DISK_SECTOR_SIZE
)
160 grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
162 bl
->first_sector
= sector
;
164 length
-= GRUB_DISK_SECTOR_SIZE
;
169 if (offset
!= 0 || bl
->last_length
!= 0)
170 grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
172 seclen
= (length
+ GRUB_DISK_SECTOR_SIZE
- 1) >> GRUB_DISK_SECTOR_BITS
;
174 if (bl
->block
!= bl
->first_block
175 && (grub_target_to_host64 (prev
->start
)
176 + grub_target_to_host16 (prev
->len
)) == sector
)
178 grub_uint16_t t
= grub_target_to_host16 (prev
->len
);
180 prev
->len
= grub_host_to_target16 (t
);
184 bl
->block
->start
= grub_host_to_target64 (sector
);
185 bl
->block
->len
= grub_host_to_target16 (seclen
);
186 #ifdef GRUB_SETUP_BIOS
187 bl
->block
->segment
= grub_host_to_target16 (bl
->current_segment
);
192 grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
195 bl
->last_length
= length
& (GRUB_DISK_SECTOR_SIZE
- 1);
196 #ifdef GRUB_SETUP_BIOS
197 bl
->current_segment
+= seclen
<< (GRUB_DISK_SECTOR_BITS
- 4);
201 #ifdef GRUB_SETUP_BIOS
202 /* Context for setup/identify_partmap. */
203 struct identify_partmap_ctx
205 grub_partition_map_t dest_partmap
;
206 grub_partition_t container
;
207 int multiple_partmaps
;
211 Unlike root_dev, with dest_dev we're interested in the partition map even
212 if dest_dev itself is a whole disk. */
214 identify_partmap (grub_disk_t disk
__attribute__ ((unused
)),
215 const grub_partition_t p
, void *data
)
217 struct identify_partmap_ctx
*ctx
= data
;
219 if (p
->parent
!= ctx
->container
)
221 /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
222 so they are safe to ignore.
224 if (grub_strcmp (p
->partmap
->name
, "netbsd") == 0
225 || grub_strcmp (p
->partmap
->name
, "openbsd") == 0)
227 if (ctx
->dest_partmap
== NULL
)
229 ctx
->dest_partmap
= p
->partmap
;
232 if (ctx
->dest_partmap
== p
->partmap
)
234 ctx
->multiple_partmaps
= 1;
239 #ifdef GRUB_SETUP_BIOS
240 #define SETUP grub_util_bios_setup
241 #elif GRUB_SETUP_SPARC64
242 #define SETUP grub_util_sparc_setup
244 #error "Shouldn't happen"
248 SETUP (const char *dir
,
249 const char *boot_file
, const char *core_file
,
250 const char *dest
, int force
,
251 int fs_probe
, int allow_floppy
,
252 int add_rs_codes
__attribute__ ((unused
))) /* unused on sparc64 */
255 char *boot_img
, *core_img
, *boot_path
;
257 size_t boot_size
, core_size
;
258 #ifdef GRUB_SETUP_BIOS
259 grub_uint16_t core_sectors
;
261 grub_device_t root_dev
= 0, dest_dev
, core_dev
;
263 struct blocklists bl
;
265 bl
.first_sector
= (grub_disk_addr_t
) -1;
267 #ifdef GRUB_SETUP_BIOS
269 GRUB_BOOT_I386_PC_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE
>> 4);
273 /* Read the boot image by the OS service. */
274 boot_path
= grub_util_get_path (dir
, boot_file
);
275 boot_size
= grub_util_get_image_size (boot_path
);
276 if (boot_size
!= GRUB_DISK_SECTOR_SIZE
)
277 grub_util_error (_("the size of `%s' is not %u"),
278 boot_path
, GRUB_DISK_SECTOR_SIZE
);
279 boot_img
= grub_util_read_image (boot_path
);
282 core_path
= grub_util_get_path (dir
, core_file
);
283 core_size
= grub_util_get_image_size (core_path
);
284 #ifdef GRUB_SETUP_BIOS
285 core_sectors
= ((core_size
+ GRUB_DISK_SECTOR_SIZE
- 1)
286 >> GRUB_DISK_SECTOR_BITS
);
288 if (core_size
< GRUB_DISK_SECTOR_SIZE
)
289 grub_util_error (_("the size of `%s' is too small"), core_path
);
290 #ifdef GRUB_SETUP_BIOS
291 if (core_size
> 0xFFFF * GRUB_DISK_SECTOR_SIZE
)
292 grub_util_error (_("the size of `%s' is too large"), core_path
);
295 core_img
= grub_util_read_image (core_path
);
297 /* Have FIRST_BLOCK to point to the first blocklist. */
298 bl
.first_block
= (struct grub_boot_blocklist
*) (core_img
299 + GRUB_DISK_SECTOR_SIZE
300 - sizeof (*bl
.block
));
301 grub_util_info ("root is `%s', dest is `%s'", root
, dest
);
303 grub_util_info ("Opening dest");
304 dest_dev
= grub_device_open (dest
);
306 grub_util_error ("%s", grub_errmsg
);
311 char **root_devices
= grub_guess_root_devices (dir
);
315 for (cur
= root_devices
; *cur
; cur
++)
318 grub_device_t try_dev
;
320 drive
= grub_util_get_grub_dev (*cur
);
323 try_dev
= grub_device_open (drive
);
329 if (!found
&& try_dev
->disk
->id
== dest_dev
->disk
->id
330 && try_dev
->disk
->dev
->id
== dest_dev
->disk
->dev
->id
)
333 grub_device_close (root_dev
);
346 grub_device_close (try_dev
);
351 grub_util_error ("guessing the root device failed, because of `%s'",
354 grub_util_info ("guessed root_dev `%s' from "
355 "dir `%s'", root_dev
->disk
->name
, dir
);
358 grub_util_info ("setting the root device to `%s'", root
);
359 if (grub_env_set ("root", root
) != GRUB_ERR_NONE
)
360 grub_util_error ("%s", grub_errmsg
);
362 #ifdef GRUB_SETUP_BIOS
365 grub_uint8_t
*boot_drive_check
;
367 /* Read the original sector from the disk. */
368 tmp_img
= xmalloc (GRUB_DISK_SECTOR_SIZE
);
369 if (grub_disk_read (dest_dev
->disk
, 0, 0, GRUB_DISK_SECTOR_SIZE
, tmp_img
))
370 grub_util_error ("%s", grub_errmsg
);
372 boot_drive_check
= (grub_uint8_t
*) (boot_img
373 + GRUB_BOOT_MACHINE_DRIVE_CHECK
);
374 /* Copy the possible DOS BPB. */
375 memcpy (boot_img
+ GRUB_BOOT_MACHINE_BPB_START
,
376 tmp_img
+ GRUB_BOOT_MACHINE_BPB_START
,
377 GRUB_BOOT_MACHINE_BPB_END
- GRUB_BOOT_MACHINE_BPB_START
);
379 /* If DEST_DRIVE is a hard disk, enable the workaround, which is
380 for buggy BIOSes which don't pass boot drive correctly. Instead,
381 they pass 0x00 or 0x01 even when booted from 0x80. */
382 if (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
))
384 /* Replace the jmp (2 bytes) with double nop's. */
385 boot_drive_check
[0] = 0x90;
386 boot_drive_check
[1] = 0x90;
389 struct identify_partmap_ctx ctx
= {
390 .dest_partmap
= NULL
,
391 .container
= dest_dev
->disk
->partition
,
392 .multiple_partmaps
= 0
396 grub_disk_addr_t
*sectors
;
399 unsigned int nsec
, maxsec
;
401 grub_partition_iterate (dest_dev
->disk
, identify_partmap
, &ctx
);
403 /* Copy the partition table. */
404 if (ctx
.dest_partmap
||
405 (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
)))
406 memcpy (boot_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
407 tmp_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
408 GRUB_BOOT_MACHINE_PART_END
- GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
);
413 && grub_strcmp (ctx
.container
->partmap
->name
, "msdos") == 0
415 && (ctx
.container
->msdostype
== GRUB_PC_PARTITION_TYPE_NETBSD
416 || ctx
.container
->msdostype
== GRUB_PC_PARTITION_TYPE_OPENBSD
))
418 grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
419 goto unable_to_embed
;
422 fs
= grub_fs_probe (dest_dev
);
424 grub_errno
= GRUB_ERR_NONE
;
426 is_ldm
= grub_util_is_ldm (dest_dev
->disk
);
430 if (!fs
&& !ctx
.dest_partmap
)
431 grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
432 dest_dev
->disk
->name
);
433 if (fs
&& !fs
->reserved_first_sector
)
434 /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */
435 grub_util_error (_("%s appears to contain a %s filesystem which isn't known to "
436 "reserve space for DOS-style boot. Installing GRUB there could "
437 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
438 "by grub-setup (--skip-fs-probe disables this "
439 "check, use at your own risk)"), dest_dev
->disk
->name
, fs
->name
);
441 if (ctx
.dest_partmap
&& strcmp (ctx
.dest_partmap
->name
, "msdos") != 0
442 && strcmp (ctx
.dest_partmap
->name
, "gpt") != 0
443 && strcmp (ctx
.dest_partmap
->name
, "bsd") != 0
444 && strcmp (ctx
.dest_partmap
->name
, "netbsd") != 0
445 && strcmp (ctx
.dest_partmap
->name
, "openbsd") != 0
446 && strcmp (ctx
.dest_partmap
->name
, "sunpc") != 0)
447 /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
448 grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
449 "reserve space for DOS-style boot. Installing GRUB there could "
450 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
451 "by grub-setup (--skip-fs-probe disables this "
452 "check, use at your own risk)"), dest_dev
->disk
->name
, ctx
.dest_partmap
->name
);
453 if (is_ldm
&& ctx
.dest_partmap
&& strcmp (ctx
.dest_partmap
->name
, "msdos") != 0
454 && strcmp (ctx
.dest_partmap
->name
, "gpt") != 0)
455 grub_util_error (_("%s appears to contain a %s partition map and "
456 "LDM which isn't known to be a safe combination."
457 " Installing GRUB there could "
458 "result in FILESYSTEM DESTRUCTION if valuable data"
460 "by grub-setup (--skip-fs-probe disables this "
461 "check, use at your own risk)"),
462 dest_dev
->disk
->name
, ctx
.dest_partmap
->name
);
466 if (! ctx
.dest_partmap
&& ! fs
&& !is_ldm
)
468 grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
469 goto unable_to_embed
;
471 if (ctx
.multiple_partmaps
|| (ctx
.dest_partmap
&& fs
) || (is_ldm
&& fs
))
473 grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
474 goto unable_to_embed
;
477 if (ctx
.dest_partmap
&& !ctx
.dest_partmap
->embed
)
479 grub_util_warn (_("Partition style `%s' doesn't support embedding"),
480 ctx
.dest_partmap
->name
);
481 goto unable_to_embed
;
484 if (fs
&& !fs
->embed
)
486 grub_util_warn (_("File system `%s' doesn't support embedding"),
488 goto unable_to_embed
;
494 maxsec
= 2 * core_sectors
;
496 maxsec
= core_sectors
;
498 if (maxsec
> ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
499 >> GRUB_DISK_SECTOR_BITS
))
500 maxsec
= ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
501 >> GRUB_DISK_SECTOR_BITS
);
504 err
= grub_util_ldm_embed (dest_dev
->disk
, &nsec
, maxsec
,
505 GRUB_EMBED_PCBIOS
, §ors
);
506 else if (ctx
.dest_partmap
)
507 err
= ctx
.dest_partmap
->embed (dest_dev
->disk
, &nsec
, maxsec
,
508 GRUB_EMBED_PCBIOS
, §ors
);
510 err
= fs
->embed (dest_dev
, &nsec
, maxsec
,
511 GRUB_EMBED_PCBIOS
, §ors
);
512 if (!err
&& nsec
< core_sectors
)
514 err
= grub_error (GRUB_ERR_OUT_OF_RANGE
,
515 N_("Your embedding area is unusually small. "
516 "core.img won't fit in it."));
521 grub_util_warn ("%s", grub_errmsg
);
522 grub_errno
= GRUB_ERR_NONE
;
523 goto unable_to_embed
;
526 assert (nsec
<= maxsec
);
528 /* Clean out the blocklists. */
529 bl
.block
= bl
.first_block
;
530 while (bl
.block
->len
)
532 grub_memset (bl
.block
, 0, sizeof (*bl
.block
));
536 if ((char *) bl
.block
<= core_img
)
537 grub_util_error ("%s", _("no terminator in the core image"));
540 bl
.block
= bl
.first_block
;
541 for (i
= 0; i
< nsec
; i
++)
542 save_blocklists (sectors
[i
] + grub_partition_get_start (ctx
.container
),
543 0, GRUB_DISK_SECTOR_SIZE
, &bl
);
545 /* Make sure that the last blocklist is a terminator. */
546 if (bl
.block
== bl
.first_block
)
550 bl
.block
->segment
= 0;
552 write_rootdev (root_dev
, boot_img
, bl
.first_sector
);
554 /* Round up to the nearest sector boundary, and zero the extra memory */
555 core_img
= xrealloc (core_img
, nsec
* GRUB_DISK_SECTOR_SIZE
);
556 assert (core_img
&& (nsec
* GRUB_DISK_SECTOR_SIZE
>= core_size
));
557 memset (core_img
+ core_size
, 0, nsec
* GRUB_DISK_SECTOR_SIZE
- core_size
);
559 bl
.first_block
= (struct grub_boot_blocklist
*) (core_img
560 + GRUB_DISK_SECTOR_SIZE
561 - sizeof (*bl
.block
));
563 grub_size_t no_rs_length
;
564 no_rs_length
= grub_target_to_host16
565 (grub_get_unaligned16 (core_img
566 + GRUB_DISK_SECTOR_SIZE
567 + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
));
569 if (no_rs_length
== 0xffff)
570 grub_util_error ("%s", _("core.img version mismatch"));
574 grub_set_unaligned32 ((core_img
+ GRUB_DISK_SECTOR_SIZE
575 + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
),
576 grub_host_to_target32 (nsec
* GRUB_DISK_SECTOR_SIZE
- core_size
));
578 void *tmp
= xmalloc (core_size
);
579 grub_memcpy (tmp
, core_img
, core_size
);
580 grub_reed_solomon_add_redundancy (core_img
+ no_rs_length
+ GRUB_DISK_SECTOR_SIZE
,
581 core_size
- no_rs_length
- GRUB_DISK_SECTOR_SIZE
,
582 nsec
* GRUB_DISK_SECTOR_SIZE
584 assert (grub_memcmp (tmp
, core_img
, core_size
) == 0);
588 /* Write the core image onto the disk. */
589 for (i
= 0; i
< nsec
; i
++)
590 grub_disk_write (dest_dev
->disk
, sectors
[i
], 0,
591 GRUB_DISK_SECTOR_SIZE
,
592 core_img
+ i
* GRUB_DISK_SECTOR_SIZE
);
602 if (dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
603 grub_util_error ("%s", _("embedding is not possible, but this is required for "
604 "RAID and LVM install"));
608 fs
= grub_fs_probe (root_dev
);
610 grub_util_error (_("can't determine filesystem on %s"), root
);
612 if (!fs
->blocklist_install
)
613 grub_util_error (_("filesystem `%s' doesn't support blocklists"),
617 #ifdef GRUB_SETUP_BIOS
618 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
619 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
620 /* TRANSLATORS: cross-disk refers to /boot being on one disk
621 but MBR on another. */
622 grub_util_error ("%s", _("embedding is not possible, but this is required for "
623 "cross-disk install"));
628 grub_util_warn ("%s", _("Embedding is not possible. GRUB can only be installed in this "
629 "setup by using blocklists. However, blocklists are UNRELIABLE and "
630 "their use is discouraged."));
632 /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */
633 grub_util_error ("%s", _("will not proceed with blocklists"));
635 /* The core image must be put on a filesystem unfortunately. */
636 grub_util_info ("will leave the core image on the filesystem");
638 grub_util_biosdisk_flush (root_dev
->disk
);
640 /* Clean out the blocklists. */
641 bl
.block
= bl
.first_block
;
642 while (bl
.block
->len
)
646 #ifdef GRUB_SETUP_BIOS
647 bl
.block
->segment
= 0;
652 if ((char *) bl
.block
<= core_img
)
653 grub_util_error ("%s", _("no terminator in the core image"));
656 bl
.block
= bl
.first_block
;
658 grub_install_get_blocklist (root_dev
, core_path
, core_img
, core_size
,
659 save_blocklists
, &bl
);
661 if (bl
.first_sector
== (grub_disk_addr_t
)-1)
662 grub_util_error ("%s", _("can't retrieve blocklists"));
664 #ifdef GRUB_SETUP_SPARC64
667 boot_devpath
= (char *) (boot_img
668 + GRUB_BOOT_AOUT_HEADER_SIZE
669 + GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
670 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
671 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
675 = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev
->disk
));
676 /* FIXME handle NULL result */
677 grub_util_info ("dest_ofpath is `%s'", dest_ofpath
);
678 strncpy (boot_devpath
, dest_ofpath
,
679 GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
680 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1);
681 boot_devpath
[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
682 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1] = 0;
687 grub_util_info ("non cross-disk install");
688 memset (boot_devpath
, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
689 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
691 grub_util_info ("boot device path %s", boot_devpath
);
695 write_rootdev (root_dev
, boot_img
, bl
.first_sector
);
697 /* Write the first two sectors of the core image onto the disk. */
698 grub_util_info ("opening the core image `%s'", core_path
);
699 fp
= grub_util_fd_open (core_path
, GRUB_UTIL_FD_O_WRONLY
);
700 if (! GRUB_UTIL_FD_IS_VALID (fp
))
701 grub_util_error (_("cannot open `%s': %s"), core_path
,
702 grub_util_fd_strerror ());
704 if (grub_util_fd_write (fp
, core_img
, GRUB_DISK_SECTOR_SIZE
* 2)
705 != GRUB_DISK_SECTOR_SIZE
* 2)
706 grub_util_error (_("cannot write to `%s': %s"),
707 core_path
, strerror (errno
));
708 grub_util_fd_sync (fp
);
709 grub_util_fd_close (fp
);
710 grub_util_biosdisk_flush (root_dev
->disk
);
712 grub_disk_cache_invalidate_all ();
715 char *buf
, *ptr
= core_img
;
716 size_t len
= core_size
;
718 grub_partition_t container
= core_dev
->disk
->partition
;
721 core_dev
->disk
->partition
= 0;
723 buf
= xmalloc (core_size
);
724 blk
= bl
.first_sector
;
725 err
= grub_disk_read (core_dev
->disk
, blk
, 0, GRUB_DISK_SECTOR_SIZE
, buf
);
727 grub_util_error (_("cannot read `%s': %s"), core_dev
->disk
->name
,
729 if (grub_memcmp (buf
, ptr
, GRUB_DISK_SECTOR_SIZE
) != 0)
730 grub_util_error ("%s", _("blocklists are invalid"));
732 ptr
+= GRUB_DISK_SECTOR_SIZE
;
733 len
-= GRUB_DISK_SECTOR_SIZE
;
735 bl
.block
= bl
.first_block
;
736 while (bl
.block
->len
)
738 size_t cur
= grub_target_to_host16 (bl
.block
->len
) << GRUB_DISK_SECTOR_BITS
;
739 blk
= grub_target_to_host64 (bl
.block
->start
);
744 err
= grub_disk_read (core_dev
->disk
, blk
, 0, cur
, buf
);
746 grub_util_error (_("cannot read `%s': %s"), core_dev
->disk
->name
,
749 if (grub_memcmp (buf
, ptr
, cur
) != 0)
750 grub_util_error ("%s", _("blocklists are invalid"));
756 if ((char *) bl
.block
<= core_img
)
757 grub_util_error ("%s", _("no terminator in the core image"));
760 grub_util_error ("%s", _("blocklists are incomplete"));
761 core_dev
->disk
->partition
= container
;
765 #ifdef GRUB_SETUP_BIOS
769 /* Write the boot image onto the disk. */
770 if (grub_disk_write (dest_dev
->disk
, BOOT_SECTOR
,
771 0, GRUB_DISK_SECTOR_SIZE
, boot_img
))
772 grub_util_error ("%s", grub_errmsg
);
774 grub_util_biosdisk_flush (root_dev
->disk
);
775 grub_util_biosdisk_flush (dest_dev
->disk
);
780 grub_device_close (dest_dev
);
781 grub_device_close (root_dev
);