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 #ifdef GRUB_SETUP_SPARC64
142 grub_uint64_t gpt_offset
;
144 grub_uint16_t last_length
;
145 grub_disk_addr_t first_sector
;
148 /* Helper for setup. */
150 save_blocklists (grub_disk_addr_t sector
, unsigned offset
, unsigned length
,
153 struct blocklists
*bl
= data
;
154 struct grub_boot_blocklist
*prev
= bl
->block
+ 1;
155 grub_uint64_t seclen
;
157 #ifdef GRUB_SETUP_SPARC64
158 sector
-= bl
->gpt_offset
;
161 grub_util_info ("saving <%" GRUB_HOST_PRIuLONG_LONG
",%u,%u>",
162 (unsigned long long) sector
, offset
, length
);
164 if (bl
->first_sector
== (grub_disk_addr_t
) -1)
166 if (offset
!= 0 || length
< GRUB_DISK_SECTOR_SIZE
)
167 grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
169 bl
->first_sector
= sector
;
171 length
-= GRUB_DISK_SECTOR_SIZE
;
176 if (offset
!= 0 || bl
->last_length
!= 0)
177 grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
179 seclen
= (length
+ GRUB_DISK_SECTOR_SIZE
- 1) >> GRUB_DISK_SECTOR_BITS
;
181 if (bl
->block
!= bl
->first_block
182 && (grub_target_to_host64 (prev
->start
)
183 + grub_target_to_host16 (prev
->len
)) == sector
)
185 grub_uint16_t t
= grub_target_to_host16 (prev
->len
);
187 prev
->len
= grub_host_to_target16 (t
);
191 bl
->block
->start
= grub_host_to_target64 (sector
);
192 bl
->block
->len
= grub_host_to_target16 (seclen
);
193 #ifdef GRUB_SETUP_BIOS
194 bl
->block
->segment
= grub_host_to_target16 (bl
->current_segment
);
199 grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
202 bl
->last_length
= length
& (GRUB_DISK_SECTOR_SIZE
- 1);
203 #ifdef GRUB_SETUP_BIOS
204 bl
->current_segment
+= seclen
<< (GRUB_DISK_SECTOR_BITS
- 4);
208 /* Context for setup/identify_partmap. */
209 struct identify_partmap_ctx
211 grub_partition_map_t dest_partmap
;
212 grub_partition_t container
;
213 int multiple_partmaps
;
217 Unlike root_dev, with dest_dev we're interested in the partition map even
218 if dest_dev itself is a whole disk. */
220 identify_partmap (grub_disk_t disk
__attribute__ ((unused
)),
221 const grub_partition_t p
, void *data
)
223 struct identify_partmap_ctx
*ctx
= data
;
225 if (p
->parent
!= ctx
->container
)
227 /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
228 so they are safe to ignore.
230 if (grub_strcmp (p
->partmap
->name
, "netbsd") == 0
231 || grub_strcmp (p
->partmap
->name
, "openbsd") == 0)
233 if (ctx
->dest_partmap
== NULL
)
235 ctx
->dest_partmap
= p
->partmap
;
238 if (ctx
->dest_partmap
== p
->partmap
)
240 ctx
->multiple_partmaps
= 1;
244 #ifdef GRUB_SETUP_BIOS
245 #define SETUP grub_util_bios_setup
246 #elif GRUB_SETUP_SPARC64
247 #define SETUP grub_util_sparc_setup
249 #error "Shouldn't happen"
253 SETUP (const char *dir
,
254 const char *boot_file
, const char *core_file
,
255 const char *dest
, int force
,
256 int fs_probe
, int allow_floppy
,
257 int add_rs_codes
__attribute__ ((unused
))) /* unused on sparc64 */
260 char *boot_img
, *core_img
, *boot_path
;
262 size_t boot_size
, core_size
;
263 grub_uint16_t core_sectors
;
264 grub_device_t root_dev
= 0, dest_dev
, core_dev
;
266 struct blocklists bl
;
268 bl
.first_sector
= (grub_disk_addr_t
) -1;
270 #ifdef GRUB_SETUP_BIOS
272 GRUB_BOOT_I386_PC_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE
>> 4);
276 /* Read the boot image by the OS service. */
277 boot_path
= grub_util_get_path (dir
, boot_file
);
278 boot_size
= grub_util_get_image_size (boot_path
);
279 if (boot_size
!= GRUB_DISK_SECTOR_SIZE
)
280 grub_util_error (_("the size of `%s' is not %u"),
281 boot_path
, GRUB_DISK_SECTOR_SIZE
);
282 boot_img
= grub_util_read_image (boot_path
);
285 core_path
= grub_util_get_path (dir
, core_file
);
286 core_size
= grub_util_get_image_size (core_path
);
287 core_sectors
= ((core_size
+ GRUB_DISK_SECTOR_SIZE
- 1)
288 >> GRUB_DISK_SECTOR_BITS
);
289 if (core_size
< GRUB_DISK_SECTOR_SIZE
)
290 grub_util_error (_("the size of `%s' is too small"), core_path
);
291 #ifdef GRUB_SETUP_BIOS
292 if (core_size
> 0xFFFF * GRUB_DISK_SECTOR_SIZE
)
293 grub_util_error (_("the size of `%s' is too large"), core_path
);
296 core_img
= grub_util_read_image (core_path
);
298 /* Have FIRST_BLOCK to point to the first blocklist. */
299 bl
.first_block
= (struct grub_boot_blocklist
*) (core_img
300 + GRUB_DISK_SECTOR_SIZE
301 - sizeof (*bl
.block
));
303 grub_util_info ("Opening dest `%s'", dest
);
304 dest_dev
= grub_device_open (dest
);
306 grub_util_error ("%s", grub_errmsg
);
311 char **root_devices
= grub_guess_root_devices (dir
);
316 grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), dir
);
318 for (cur
= root_devices
; *cur
; cur
++)
321 grub_device_t try_dev
;
323 drive
= grub_util_get_grub_dev (*cur
);
326 try_dev
= grub_device_open (drive
);
332 if (!found
&& try_dev
->disk
->id
== dest_dev
->disk
->id
333 && try_dev
->disk
->dev
->id
== dest_dev
->disk
->dev
->id
)
336 grub_device_close (root_dev
);
349 grub_device_close (try_dev
);
354 root
= grub_util_get_grub_dev ("/dev/sda");
355 root_dev
= grub_device_open (root
);
357 grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg
);
359 grub_util_error ("guessing the root device failed, because of `%s'", grub_errmsg
);
361 grub_util_info ("guessed root_dev `%s' from "
362 "dir `%s'", root_dev
->disk
->name
, dir
);
364 for (cur
= root_devices
; *cur
; cur
++)
369 grub_util_info ("setting the root device to `%s'", root
);
370 if (grub_env_set ("root", root
) != GRUB_ERR_NONE
)
371 grub_util_error ("%s", grub_errmsg
);
374 #ifdef GRUB_SETUP_BIOS
376 grub_uint8_t
*boot_drive_check
;
378 /* Read the original sector from the disk. */
379 tmp_img
= xmalloc (GRUB_DISK_SECTOR_SIZE
);
380 if (grub_disk_read (dest_dev
->disk
, 0, 0, GRUB_DISK_SECTOR_SIZE
, tmp_img
))
381 grub_util_error ("%s", grub_errmsg
);
383 boot_drive_check
= (grub_uint8_t
*) (boot_img
384 + GRUB_BOOT_MACHINE_DRIVE_CHECK
);
385 /* Copy the possible DOS BPB. */
386 memcpy (boot_img
+ GRUB_BOOT_MACHINE_BPB_START
,
387 tmp_img
+ GRUB_BOOT_MACHINE_BPB_START
,
388 GRUB_BOOT_MACHINE_BPB_END
- GRUB_BOOT_MACHINE_BPB_START
);
390 /* If DEST_DRIVE is a hard disk, enable the workaround, which is
391 for buggy BIOSes which don't pass boot drive correctly. Instead,
392 they pass 0x00 or 0x01 even when booted from 0x80. */
393 if (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
))
395 /* Replace the jmp (2 bytes) with double nop's. */
396 boot_drive_check
[0] = 0x90;
397 boot_drive_check
[1] = 0x90;
401 struct identify_partmap_ctx ctx
= {
402 .dest_partmap
= NULL
,
403 .container
= dest_dev
->disk
->partition
,
404 .multiple_partmaps
= 0
408 grub_disk_addr_t
*sectors
;
411 unsigned int nsec
, maxsec
;
413 grub_partition_iterate (dest_dev
->disk
, identify_partmap
, &ctx
);
415 #ifdef GRUB_SETUP_BIOS
416 /* Copy the partition table. */
417 if (ctx
.dest_partmap
||
418 (!allow_floppy
&& !grub_util_biosdisk_is_floppy (dest_dev
->disk
)))
419 memcpy (boot_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
420 tmp_img
+ GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
,
421 GRUB_BOOT_MACHINE_PART_END
- GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
);
427 && grub_strcmp (ctx
.container
->partmap
->name
, "msdos") == 0
429 && (ctx
.container
->msdostype
== GRUB_PC_PARTITION_TYPE_NETBSD
430 || ctx
.container
->msdostype
== GRUB_PC_PARTITION_TYPE_OPENBSD
))
432 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."));
433 goto unable_to_embed
;
436 fs
= grub_fs_probe (dest_dev
);
438 grub_errno
= GRUB_ERR_NONE
;
440 is_ldm
= grub_util_is_ldm (dest_dev
->disk
);
444 if (!fs
&& !ctx
.dest_partmap
)
445 grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
446 dest_dev
->disk
->name
);
447 if (fs
&& !fs
->reserved_first_sector
)
448 /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */
449 grub_util_error (_("%s appears to contain a %s filesystem which isn't known to "
450 "reserve space for DOS-style boot. Installing GRUB there could "
451 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
452 "by grub-setup (--skip-fs-probe disables this "
453 "check, use at your own risk)"), dest_dev
->disk
->name
, fs
->name
);
455 if (ctx
.dest_partmap
&& strcmp (ctx
.dest_partmap
->name
, "msdos") != 0
456 && strcmp (ctx
.dest_partmap
->name
, "gpt") != 0
457 && strcmp (ctx
.dest_partmap
->name
, "bsd") != 0
458 && strcmp (ctx
.dest_partmap
->name
, "netbsd") != 0
459 && strcmp (ctx
.dest_partmap
->name
, "openbsd") != 0
460 && strcmp (ctx
.dest_partmap
->name
, "sunpc") != 0)
461 /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
462 grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
463 "reserve space for DOS-style boot. Installing GRUB there could "
464 "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
465 "by grub-setup (--skip-fs-probe disables this "
466 "check, use at your own risk)"), dest_dev
->disk
->name
, ctx
.dest_partmap
->name
);
467 if (is_ldm
&& ctx
.dest_partmap
&& strcmp (ctx
.dest_partmap
->name
, "msdos") != 0
468 && strcmp (ctx
.dest_partmap
->name
, "gpt") != 0)
469 grub_util_error (_("%s appears to contain a %s partition map and "
470 "LDM which isn't known to be a safe combination."
471 " Installing GRUB there could "
472 "result in FILESYSTEM DESTRUCTION if valuable data"
474 "by grub-setup (--skip-fs-probe disables this "
475 "check, use at your own risk)"),
476 dest_dev
->disk
->name
, ctx
.dest_partmap
->name
);
480 if (! ctx
.dest_partmap
&& ! fs
&& !is_ldm
)
482 grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
483 goto unable_to_embed
;
485 if (ctx
.multiple_partmaps
|| (ctx
.dest_partmap
&& fs
) || (is_ldm
&& fs
))
487 grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
488 goto unable_to_embed
;
491 if (ctx
.dest_partmap
&& !ctx
.dest_partmap
->embed
)
493 grub_util_warn (_("Partition style `%s' doesn't support embedding"),
494 ctx
.dest_partmap
->name
);
495 goto unable_to_embed
;
498 if (fs
&& !fs
->fs_embed
)
500 grub_util_warn (_("File system `%s' doesn't support embedding"),
502 goto unable_to_embed
;
508 maxsec
= 2 * core_sectors
;
510 maxsec
= core_sectors
;
512 #ifdef GRUB_SETUP_BIOS
513 if (maxsec
> ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
514 >> GRUB_DISK_SECTOR_BITS
))
515 maxsec
= ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR
)
516 >> GRUB_DISK_SECTOR_BITS
);
519 #ifdef GRUB_SETUP_SPARC64
521 * On SPARC we need two extra. One is because we are combining the
522 * core.img with the boot.img. The other is because the boot sector
530 err
= grub_util_ldm_embed (dest_dev
->disk
, &nsec
, maxsec
,
531 GRUB_EMBED_PCBIOS
, §ors
);
532 else if (ctx
.dest_partmap
)
533 err
= ctx
.dest_partmap
->embed (dest_dev
->disk
, &nsec
, maxsec
,
534 GRUB_EMBED_PCBIOS
, §ors
);
536 err
= fs
->fs_embed (dest_dev
, &nsec
, maxsec
,
537 GRUB_EMBED_PCBIOS
, §ors
);
538 if (!err
&& nsec
< core_sectors
)
540 err
= grub_error (GRUB_ERR_OUT_OF_RANGE
,
541 N_("Your embedding area is unusually small. "
542 "core.img won't fit in it."));
547 grub_util_warn ("%s", grub_errmsg
);
548 grub_errno
= GRUB_ERR_NONE
;
549 goto unable_to_embed
;
552 assert (nsec
<= maxsec
);
554 /* Clean out the blocklists. */
555 bl
.block
= bl
.first_block
;
556 while (bl
.block
->len
)
558 grub_memset (bl
.block
, 0, sizeof (*bl
.block
));
562 if ((char *) bl
.block
<= core_img
)
563 grub_util_error ("%s", _("no terminator in the core image"));
566 bl
.block
= bl
.first_block
;
567 for (i
= 0; i
< nsec
; i
++)
568 save_blocklists (sectors
[i
] + grub_partition_get_start (ctx
.container
),
569 0, GRUB_DISK_SECTOR_SIZE
, &bl
);
571 /* Make sure that the last blocklist is a terminator. */
572 if (bl
.block
== bl
.first_block
)
576 #ifdef GRUB_SETUP_BIOS
577 bl
.block
->segment
= 0;
580 #ifdef GRUB_SETUP_SPARC64
583 * On SPARC, the block-list entries need to be based off the beginning
584 * of the parition, not the beginning of the disk.
586 struct grub_boot_blocklist
*block
;
587 block
= bl
.first_block
;
591 block
->start
-= bl
.first_sector
;
597 * Reserve space for the boot block since it can not be in the
598 * Parition table on SPARC.
600 assert (bl
.first_block
->len
> 2);
601 bl
.first_block
->start
+= 2;
602 bl
.first_block
->len
-= 2;
603 write_rootdev (root_dev
, boot_img
, sectors
[BOOT_SECTOR
+ 1] - bl
.first_sector
);
606 #ifdef GRUB_SETUP_BIOS
607 write_rootdev (root_dev
, boot_img
, bl
.first_sector
);
610 /* Round up to the nearest sector boundary, and zero the extra memory */
611 core_img
= xrealloc (core_img
, nsec
* GRUB_DISK_SECTOR_SIZE
);
612 assert (core_img
&& (nsec
* GRUB_DISK_SECTOR_SIZE
>= core_size
));
613 memset (core_img
+ core_size
, 0, nsec
* GRUB_DISK_SECTOR_SIZE
- core_size
);
615 bl
.first_block
= (struct grub_boot_blocklist
*) (core_img
616 + GRUB_DISK_SECTOR_SIZE
617 - sizeof (*bl
.block
));
619 grub_size_t no_rs_length
;
620 no_rs_length
= grub_target_to_host16
621 (grub_get_unaligned16 (core_img
622 + GRUB_DISK_SECTOR_SIZE
623 + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
));
625 if (no_rs_length
== 0xffff)
626 grub_util_error ("%s", _("core.img version mismatch"));
630 grub_set_unaligned32 ((core_img
+ GRUB_DISK_SECTOR_SIZE
631 + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
),
632 grub_host_to_target32 (nsec
* GRUB_DISK_SECTOR_SIZE
- core_size
));
634 void *tmp
= xmalloc (core_size
);
635 grub_memcpy (tmp
, core_img
, core_size
);
636 grub_reed_solomon_add_redundancy (core_img
+ no_rs_length
+ GRUB_DISK_SECTOR_SIZE
,
637 core_size
- no_rs_length
- GRUB_DISK_SECTOR_SIZE
,
638 nsec
* GRUB_DISK_SECTOR_SIZE
640 assert (grub_memcmp (tmp
, core_img
, core_size
) == 0);
644 /* Write the core image onto the disk. */
645 for (i
= 0; i
< nsec
; i
++)
646 grub_disk_write (dest_dev
->disk
, sectors
[i
], 0,
647 GRUB_DISK_SECTOR_SIZE
,
648 core_img
+ i
* GRUB_DISK_SECTOR_SIZE
);
651 #ifdef GRUB_SETUP_SPARC64
653 int isec
= BOOT_SECTOR
;
655 /* Write the boot image onto the disk. */
656 if (grub_disk_write (dest_dev
->disk
, sectors
[isec
++], 0,
657 GRUB_DISK_SECTOR_SIZE
, boot_img
))
658 grub_util_error ("%s", grub_errmsg
);
660 /* Write the core image onto the disk. */
661 for (i
= 0 ; isec
< nsec
; i
++, isec
++)
663 if (grub_disk_write (dest_dev
->disk
, sectors
[isec
], 0,
664 GRUB_DISK_SECTOR_SIZE
,
665 core_img
+ i
* GRUB_DISK_SECTOR_SIZE
))
666 grub_util_error ("%s", grub_errmsg
);
678 if (dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
679 grub_util_error ("%s", _("embedding is not possible, but this is required for "
680 "RAID and LVM install"));
684 fs
= grub_fs_probe (root_dev
);
686 grub_util_error (_("can't determine filesystem on %s"), root
);
688 if (!fs
->blocklist_install
)
689 grub_util_error (_("filesystem `%s' doesn't support blocklists"),
693 #ifdef GRUB_SETUP_BIOS
694 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
695 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
696 /* TRANSLATORS: cross-disk refers to /boot being on one disk
697 but MBR on another. */
698 grub_util_error ("%s", _("embedding is not possible, but this is required for "
699 "cross-disk install"));
704 grub_util_warn ("%s", _("Embedding is not possible. GRUB can only be installed in this "
705 "setup by using blocklists. However, blocklists are UNRELIABLE and "
706 "their use is discouraged."));
708 /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */
709 grub_util_error ("%s", _("will not proceed with blocklists"));
711 /* The core image must be put on a filesystem unfortunately. */
712 grub_util_info ("will leave the core image on the filesystem");
714 grub_util_biosdisk_flush (root_dev
->disk
);
716 /* Clean out the blocklists. */
717 bl
.block
= bl
.first_block
;
718 while (bl
.block
->len
)
722 #ifdef GRUB_SETUP_BIOS
723 bl
.block
->segment
= 0;
728 if ((char *) bl
.block
<= core_img
)
729 grub_util_error ("%s", _("no terminator in the core image"));
732 bl
.block
= bl
.first_block
;
734 #ifdef GRUB_SETUP_SPARC64
736 grub_partition_t container
= root_dev
->disk
->partition
;
739 if (grub_strstr (container
->partmap
->name
, "gpt"))
740 bl
.gpt_offset
= grub_partition_get_start (container
);
744 grub_install_get_blocklist (root_dev
, core_path
, core_img
, core_size
,
745 save_blocklists
, &bl
);
747 if (bl
.first_sector
== (grub_disk_addr_t
)-1)
748 grub_util_error ("%s", _("can't retrieve blocklists"));
750 #ifdef GRUB_SETUP_SPARC64
753 boot_devpath
= (char *) (boot_img
754 + GRUB_BOOT_AOUT_HEADER_SIZE
755 + GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
756 if (dest_dev
->disk
->id
!= root_dev
->disk
->id
757 || dest_dev
->disk
->dev
->id
!= root_dev
->disk
->dev
->id
)
761 = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev
->disk
));
762 /* FIXME handle NULL result */
763 grub_util_info ("dest_ofpath is `%s'", dest_ofpath
);
764 strncpy (boot_devpath
, dest_ofpath
,
765 GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
766 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1);
767 boot_devpath
[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
768 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
- 1] = 0;
773 grub_util_info ("non cross-disk install");
774 memset (boot_devpath
, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
775 - GRUB_BOOT_MACHINE_BOOT_DEVPATH
);
777 grub_util_info ("boot device path %s", boot_devpath
);
781 write_rootdev (root_dev
, boot_img
, bl
.first_sector
);
783 /* Write the first two sectors of the core image onto the disk. */
784 grub_util_info ("opening the core image `%s'", core_path
);
785 fp
= grub_util_fd_open (core_path
, GRUB_UTIL_FD_O_WRONLY
);
786 if (! GRUB_UTIL_FD_IS_VALID (fp
))
787 grub_util_error (_("cannot open `%s': %s"), core_path
,
788 grub_util_fd_strerror ());
790 if (grub_util_fd_write (fp
, core_img
, GRUB_DISK_SECTOR_SIZE
* 2)
791 != GRUB_DISK_SECTOR_SIZE
* 2)
792 grub_util_error (_("cannot write to `%s': %s"),
793 core_path
, strerror (errno
));
794 if (grub_util_fd_sync (fp
) < 0)
795 grub_util_error (_("cannot sync `%s': %s"), core_path
, strerror (errno
));
796 if (grub_util_fd_close (fp
) < 0)
797 grub_util_error (_("cannot close `%s': %s"), core_path
, strerror (errno
));
798 grub_util_biosdisk_flush (root_dev
->disk
);
800 grub_disk_cache_invalidate_all ();
803 char *buf
, *ptr
= core_img
;
804 size_t len
= core_size
;
805 grub_uint64_t blk
, offset
= 0;
806 grub_partition_t container
= core_dev
->disk
->partition
;
809 core_dev
->disk
->partition
= 0;
810 #ifdef GRUB_SETUP_SPARC64
811 offset
= bl
.gpt_offset
;
814 buf
= xmalloc (core_size
);
815 blk
= bl
.first_sector
;
816 err
= grub_disk_read (core_dev
->disk
, blk
+ offset
, 0, GRUB_DISK_SECTOR_SIZE
, buf
);
818 grub_util_error (_("cannot read `%s': %s"), core_dev
->disk
->name
,
820 if (grub_memcmp (buf
, ptr
, GRUB_DISK_SECTOR_SIZE
) != 0)
821 grub_util_error ("%s", _("blocklists are invalid"));
823 ptr
+= GRUB_DISK_SECTOR_SIZE
;
824 len
-= GRUB_DISK_SECTOR_SIZE
;
826 bl
.block
= bl
.first_block
;
827 while (bl
.block
->len
)
829 size_t cur
= grub_target_to_host16 (bl
.block
->len
) << GRUB_DISK_SECTOR_BITS
;
830 blk
= grub_target_to_host64 (bl
.block
->start
);
835 err
= grub_disk_read (core_dev
->disk
, blk
+ offset
, 0, cur
, buf
);
837 grub_util_error (_("cannot read `%s': %s"), core_dev
->disk
->name
,
840 if (grub_memcmp (buf
, ptr
, cur
) != 0)
841 grub_util_error ("%s", _("blocklists are invalid"));
847 if ((char *) bl
.block
<= core_img
)
848 grub_util_error ("%s", _("no terminator in the core image"));
851 grub_util_error ("%s", _("blocklists are incomplete"));
852 core_dev
->disk
->partition
= container
;
856 #ifdef GRUB_SETUP_BIOS
860 /* Write the boot image onto the disk. */
861 if (grub_disk_write (dest_dev
->disk
, BOOT_SECTOR
,
862 0, GRUB_DISK_SECTOR_SIZE
, boot_img
))
863 grub_util_error ("%s", grub_errmsg
);
865 #ifdef GRUB_SETUP_SPARC64
869 grub_util_biosdisk_flush (root_dev
->disk
);
870 grub_util_biosdisk_flush (dest_dev
->disk
);
875 grub_device_close (dest_dev
);
876 grub_device_close (root_dev
);