* util/sparc64/ieee1275/misc.c: New file.

* util/sparc64/ieee1275/grub-setup.c: New file.
	* util/sparc64/ieee1275/grub-ofpathname.c: New file.
	* util/sparc64/ieee1275/grub-mkimage.c: New file.
	* util/sparc64/ieee1275/grub-install.in: New file.
	* util/ieee1275/ofpath.c: New file.
	* util/ieee1275/devicemap.c: New file.
	* util/devicemap.c: New file.
	* util/deviceiter.c: New file.
	* kern/sparc64/ieee1275/init.c: New file.
	* include/grub/util/ofpath.h: New file.
	* include/grub/util/deviceiter.h: New file.
	* util/grub-mkdevicemap.c: Include deviceiter.h.
	Implement using grub_util_emit_devicemap_entry and
	grub_util_iterate_devices.
	* conf/i386-corebook.rmk: Build util/deviceiter.c and
	util/devicemap.c into grub-mkdevicemap
	* conf/i386-efi.rmk: Likewise.
	* conf/i386-ieee1275.rmk: Likewise.
	* conf/i386-pc.rmk: Likewise.
	* conf/powerpc-ieee1275.rmk: Likewise.
	* conf/sparc64-ieee1275.rmk: Add rules to build boot block
	images and installation utilities.  Build kernel as image
	instead of as elf binary.  Use common rules as much as possible.
This commit is contained in:
davem 2009-04-22 09:57:39 +00:00
parent 4e8269dad2
commit a1447506fe
20 changed files with 2689 additions and 817 deletions

View file

@ -0,0 +1,276 @@
#! /bin/sh
# Install GRUB on your drive.
# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GRUB is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
# Initialize some variables.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
sbindir=@sbindir@
bindir=@bindir@
libdir=@libdir@
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
target_cpu=@target_cpu@
platform=@platform@
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
grub_setup=${sbindir}/`echo grub-setup | sed ${transform}`
grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
rootdir=
grub_prefix=`echo /boot/grub | sed ${transform}`
modules=
install_device=
no_floppy=
force_lba=
recheck=no
debug=no
# Usage: usage
# Print the usage.
usage () {
cat <<EOF
Usage: grub-install [OPTION] install_device
Install GRUB on your drive.
-h, --help print this message and exit
-v, --version print the version information and exit
--modules=MODULES pre-load specified modules MODULES
--root-directory=DIR install GRUB images under the directory DIR
instead of the root directory
--grub-setup=FILE use FILE as grub-setup
--grub-mkimage=FILE use FILE as grub-mkimage
--grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
--grub-probe=FILE use FILE as grub-probe
--no-floppy do not probe any floppy drive
--recheck probe a device map even if it already exists
INSTALL_DEVICE can be a GRUB device name or a system device filename.
grub-install copies GRUB images into the DIR/boot directory specified by
--root-directory, and uses grub-setup to install grub into the boot
sector.
Report bugs to <bug-grub@gnu.org>.
EOF
}
# Check the arguments.
for option in "$@"; do
case "$option" in
-h | --help)
usage
exit 0 ;;
-v | --version)
echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
exit 0 ;;
--modules=*)
modules=`echo "$option" | sed 's/--modules=//'` ;;
--root-directory=*)
rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
--grub-setup=*)
grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;;
--grub-mkimage=*)
grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
--grub-mkdevicemap=*)
grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
--grub-probe=*)
grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;;
--no-floppy)
no_floppy="--no-floppy" ;;
--recheck)
recheck=yes ;;
# This is an undocumented feature...
--debug)
debug=yes ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
exit 1
;;
*)
if test "x$install_device" != x; then
echo "More than one install_devices?" 1>&2
usage
exit 1
fi
install_device="${option}" ;;
esac
done
# for make_system_path_relative_to_its_root()
. ${libdir}/grub/grub-mkconfig_lib
if test "x$install_device" = x; then
echo "install_device not specified." 1>&2
usage
exit 1
fi
# If the debugging feature is enabled, print commands.
setup_verbose=
if test $debug = yes; then
set -x
setup_verbose="--verbose"
fi
# Initialize these directories here, since ROOTDIR was initialized.
bootdir=${rootdir}/boot
grubdir=${bootdir}/`echo grub | sed ${transform}`
device_map=${grubdir}/device.map
grub_probe="${grub_probe} --device-map=${device_map}"
# Check if GRUB is installed.
set $grub_setup dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
set $grub_mkimage dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
set $grub_mkdevicemap dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
# Create the GRUB directory if it is not present.
test -d "$bootdir" || mkdir "$bootdir" || exit 1
test -d "$grubdir" || mkdir "$grubdir" || exit 1
# If --recheck is specified, remove the device map, if present.
if test $recheck = yes; then
rm -f $device_map
fi
# Create the device map file if it is not present.
if test -f "$device_map"; then
:
else
# Create a safe temporary file.
test -n "$mklog" && log_file=`$mklog`
$grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1
fi
# Make sure that there is no duplicated entry.
tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
| sort | uniq -d | sed -n 1p`
if test -n "$tmp"; then
echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
exit 1
fi
# Copy the GRUB images to the GRUB directory.
for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img; do
if test -f $file && [ "`basename $file`" != menu.lst ]; then
rm -f $file || exit 1
fi
done
for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
cp -f $file ${grubdir} || exit 1
done
for file in ${pkglibdir}/*.img; do
cp -f $file ${grubdir} || exit 1
done
# Write device to a variable so we don't have to traverse /dev every time.
grub_device=`$grub_probe --target=device ${grubdir}`
# Create the core image. First, auto-detect the filesystem module.
fs_module=`$grub_probe --target=fs --device ${grub_device}`
if test "x$fs_module" = x -a "x$modules" = x; then
echo "Auto-detection of a filesystem module failed." 1>&2
echo "Please specify the module with the option \`--modules' explicitly." 1>&2
exit 1
fi
# Then the partition map module. In order to support partition-less media,
# this command is allowed to fail (--target=fs already grants us that the
# filesystem will be accessible).
partmap_module=`$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`
# Device abstraction module, if any (lvm, raid).
devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}`
modules="$modules $fs_module $partmap_module $devabstraction_module"
prefix_drive=
if [ "x${devabstraction_module}" = "x" ] ; then
if echo "${install_device}" | grep -qx "(.*)" ; then
install_drive="${install_device}"
else
install_drive="`$grub_probe --target=drive --device ${install_device}`"
fi
grub_drive="`$grub_probe --target=drive --device ${grub_device}`"
# Strip partition number
install_drive="`echo ${install_drive} | sed -e s/,[0-9]*//g`"
grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*//g`"
if [ "x${grub_drive}" != "x${install_drive}" ] ; then
uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`"
if [ "x${uuid}" = "x" ] ; then
echo "You attempted a cross-disk install, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
exit 1
fi
prefix_drive="(UUID=${uuid})"
modules="$modules fs_uuid"
fi
else
prefix_drive=`$grub_probe --target=drive --device ${grub_device}`
fi
relative_grubdir=`make_system_path_relative_to_its_root ${grubdir}` || exit 1
if [ "x${relative_grubdir}" = "x" ] ; then
relative_grubdir=/
fi
$grub_mkimage --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
# Now perform the installation.
$grub_setup ${setup_verbose} --directory=${grubdir} --device-map=${device_map} \
${install_device} || exit 1
# Prompt the user to check if the device map is correct.
echo "Installation finished. No error reported."
echo "This is the contents of the device map $device_map."
echo "Check if this is correct or not. If any of the lines is incorrect,"
echo "fix it and re-run the script \`grub-install'."
echo
cat $device_map
# Bye.
exit 0

View file

@ -0,0 +1,294 @@
/* grub-mkimage.c - make a bootable image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/types.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <grub/kernel.h>
#include <grub/disk.h>
#include <grub/util/misc.h>
#include <grub/util/resolve.h>
#include <grub/misc.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define _GNU_SOURCE 1
#include <getopt.h>
static void
compress_kernel (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size)
{
/* No compression support yet. */
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
*core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size);
*core_size = kernel_size;
}
static void
generate_image (const char *dir, const char *prefix, FILE *out, char *mods[], char *memdisk_path)
{
size_t kernel_size, total_module_size, memdisk_size, core_size, boot_size, offset;
char *kernel_path, *kernel_img, *core_img, *boot_path, *boot_img;
struct grub_util_path_list *path_list, *p;
struct grub_module_info *modinfo;
grub_addr_t module_addr;
unsigned int num;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
kernel_path = grub_util_get_path (dir, "kernel.img");
kernel_size = grub_util_get_image_size (kernel_path);
total_module_size = sizeof (struct grub_module_info);
for (p = path_list; p; p = p->next)
total_module_size += (grub_util_get_image_size (p->name)
+ sizeof (struct grub_module_header));
memdisk_size = 0;
if (memdisk_path)
{
memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
total_module_size += memdisk_size + sizeof (struct grub_module_header);
}
grub_util_info ("the total module size is 0x%x", total_module_size);
kernel_img = xmalloc (kernel_size + total_module_size);
grub_util_load_image (kernel_path, kernel_img);
if ((GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1)
> GRUB_KERNEL_MACHINE_DATA_END)
grub_util_error ("prefix too long");
strcpy (kernel_img + GRUB_KERNEL_MACHINE_PREFIX, prefix);
/* Fill in the grub_module_info structure. */
modinfo = (struct grub_module_info *) (kernel_img + kernel_size);
modinfo->magic = GRUB_MODULE_MAGIC;
modinfo->offset = sizeof (struct grub_module_info);
modinfo->size = total_module_size;
offset = kernel_size + sizeof (struct grub_module_info);
for (p = path_list; p; p = p->next)
{
struct grub_module_header *header;
size_t mod_size;
mod_size = grub_util_get_image_size (p->name);
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_cpu_to_be32 (OBJ_TYPE_ELF);
header->size = grub_cpu_to_be32 (mod_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (p->name, kernel_img + offset);
offset += mod_size;
}
if (memdisk_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_cpu_to_be32 (OBJ_TYPE_MEMDISK);
header->size = grub_cpu_to_be32 (memdisk_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (memdisk_path, kernel_img + offset);
offset += memdisk_size;
}
compress_kernel (kernel_img, kernel_size + total_module_size,
&core_img, &core_size);
grub_util_info ("the core size is 0x%x", core_size);
num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
num <<= GRUB_DISK_SECTOR_BITS;
boot_path = grub_util_get_path (dir, "diskboot.img");
boot_size = grub_util_get_image_size (boot_path);
if (boot_size != GRUB_DISK_SECTOR_SIZE)
grub_util_error ("diskboot.img is not one sector size");
boot_img = grub_util_read_image (boot_path);
/* sparc is a big endian architecture. */
*((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
- GRUB_BOOT_MACHINE_LIST_SIZE + 8))
= grub_cpu_to_be32 (num);
grub_util_write_image (boot_img, boot_size, out);
free (boot_img);
free (boot_path);
module_addr = (path_list
? (GRUB_BOOT_MACHINE_IMAGE_ADDRESS + kernel_size)
: 0);
grub_util_info ("the first module address is 0x%x", module_addr);
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE))
= grub_cpu_to_be32 (total_module_size);
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
= grub_cpu_to_be32 (kernel_size);
/* No compression support yet. */
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
= grub_cpu_to_be32 (0);
grub_util_write_image (core_img, core_size, out);
free (kernel_img);
free (core_img);
free (kernel_path);
while (path_list)
{
struct grub_util_path_list *next = path_list->next;
free ((void *) path_list->name);
free (path_list);
path_list = next;
}
}
static struct option options[] =
{
{"directory", required_argument, 0, 'd'},
{"prefix", required_argument, 0, 'p'},
{"memdisk", required_argument, 0, 'm'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
else
printf ("\
Usage: grub-mkimage [OPTION]... [MODULES]\n\
\n\
Make a bootable image of GRUB.\n\
\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-p, --prefix=DIR set grub_prefix directory [default=%s]\n\
-m, --memdisk=FILE embed FILE as a memdisk image\n\
-o, --output=FILE output a generated image to FILE [default=stdout]\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\
Report bugs to <%s>.\n\
", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
exit (status);
}
int
main (int argc, char *argv[])
{
char *output = NULL;
char *dir = NULL;
char *prefix = NULL;
char *memdisk = NULL;
FILE *fp = stdout;
progname = "grub-mkimage";
while (1)
{
int c = getopt_long (argc, argv, "d:p:m:o:hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'o':
if (output)
free (output);
output = xstrdup (optarg);
break;
case 'd':
if (dir)
free (dir);
dir = xstrdup (optarg);
break;
case 'm':
if (memdisk)
free (memdisk);
memdisk = xstrdup (optarg);
if (prefix)
free (prefix);
prefix = xstrdup ("(memdisk)/boot/grub");
break;
case 'h':
usage (0);
break;
case 'p':
if (prefix)
free (prefix);
prefix = xstrdup (optarg);
break;
case 'V':
printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
if (output)
{
fp = fopen (output, "wb");
if (! fp)
grub_util_error ("cannot open %s", output);
}
generate_image (dir ? : GRUB_LIBDIR,
prefix ? : DEFAULT_DIRECTORY, fp,
argv + optind, memdisk);
fclose (fp);
if (dir)
free (dir);
return 0;
}

View file

@ -0,0 +1,39 @@
/* grub-ofpathname.c - Find OpenBOOT path for a given device */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/util/misc.h>
#include <grub/util/ofpath.h>
int main(int argc, char **argv)
{
char *of_path;
if (argc != 2)
{
printf("Usage: grub-ofpathname DEVICE\n");
return 1;
}
of_path = grub_util_devname_to_ofpath (argv[1]);
printf("%s\n", of_path);
free (of_path);
return 0;
}

View file

@ -0,0 +1,625 @@
/* grub-setup.c - make GRUB usable */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/types.h>
#include <grub/util/misc.h>
#include <grub/device.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/fs.h>
#include <grub/partition.h>
#include <grub/pc_partition.h>
#include <grub/gpt_partition.h>
#include <grub/env.h>
#include <grub/util/hostdisk.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <grub/term.h>
#include <grub/util/raid.h>
#include <grub/util/lvm.h>
#include <grub_setup_init.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <grub/util/getroot.h>
#define _GNU_SOURCE 1
#include <getopt.h>
/* This program fills in various fields inside of the 'boot' and 'core'
* image files.
*
* The 'boot' image needs to know the OBP path name of the root
* device. It also needs to know the initial block number of
* 'core' (which is 'diskboot' concatenated with 'kernel' and
* all the modules, this is created by grub-mkimage). This resulting
* 'boot' image is 512 bytes in size and is placed in the first block
* of a partition.
*
* The initial 'diskboot' block acts as a loader for the actual GRUB
* kernel. It contains the loading code and then a block list.
*
* The block list of 'core' starts at the end of the 'diskboot' image
* and works it's way backwards towards the end of the code of 'diskboot'.
*
* We patch up the images with the necessary values and write out the
* result.
*/
#define DEFAULT_BOOT_FILE "boot.img"
#define DEFAULT_CORE_FILE "core.img"
/* This is the blocklist used in the diskboot image. */
struct boot_blocklist
{
grub_uint64_t start;
grub_uint32_t len;
} __attribute__ ((packed));
void
grub_putchar (int c)
{
putchar (c);
}
int
grub_getkey (void)
{
return -1;
}
struct grub_handler_class grub_term_input_class;
struct grub_handler_class grub_term_output_class;
void
grub_refresh (void)
{
fflush (stdout);
}
static void
setup (const char *prefix, const char *dir,
const char *boot_file, const char *core_file,
const char *root, const char *dest)
{
char *boot_path, *core_path;
char *boot_img, *core_img;
size_t boot_size, core_size;
grub_uint16_t core_sectors;
grub_device_t root_dev, dest_dev;
char *boot_devpath;
grub_disk_addr_t *kernel_sector;
struct boot_blocklist *first_block, *block;
char *tmp_img;
int i;
grub_disk_addr_t first_sector;
grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
grub_file_t file;
FILE *fp;
struct { grub_uint64_t start; grub_uint64_t end; } embed_region;
embed_region.start = embed_region.end = ~0UL;
auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
unsigned int offset,
unsigned int length);
auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
unsigned int offset,
unsigned int length);
void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
unsigned int offset,
unsigned int length)
{
grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length);
if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
grub_util_error ("The first sector of the core file "
"is not sector-aligned");
first_sector = sector;
}
void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
unsigned int offset,
unsigned int length)
{
struct boot_blocklist *prev = block + 1;
grub_util_info ("saving <%llu,%u,%u>", sector, offset, length);
if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
grub_util_error ("Non-sector-aligned data is found in the core file");
if (block != first_block
&& (grub_be_to_cpu64 (prev->start)
+ grub_be_to_cpu16 (prev->len)) == sector)
prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1);
else
{
block->start = grub_cpu_to_be64 (sector);
block->len = grub_cpu_to_be16 (1);
block--;
if (block->len)
grub_util_error ("The sectors of the core file are too fragmented");
}
last_length = length;
}
/* Read the boot image by the OS service. */
boot_path = grub_util_get_path (dir, boot_file);
boot_size = grub_util_get_image_size (boot_path);
if (boot_size != GRUB_DISK_SECTOR_SIZE)
grub_util_error ("The size of `%s' is not %d",
boot_path, GRUB_DISK_SECTOR_SIZE);
boot_img = grub_util_read_image (boot_path);
free (boot_path);
/* Set the addresses of variables in the boot image. */
boot_devpath = (char *) (boot_img
+ GRUB_BOOT_AOUT_HEADER_SIZE
+ GRUB_BOOT_MACHINE_BOOT_DEVPATH);
kernel_sector = (grub_disk_addr_t *) (boot_img
+ GRUB_BOOT_AOUT_HEADER_SIZE
+ GRUB_BOOT_MACHINE_KERNEL_SECTOR);
core_path = grub_util_get_path (dir, core_file);
core_size = grub_util_get_image_size (core_path);
core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS);
if (core_size < GRUB_DISK_SECTOR_SIZE)
grub_util_error ("The size of `%s' is too small", core_path);
core_img = grub_util_read_image (core_path);
free (core_path);
/* Have FIRST_BLOCK to point to the first blocklist. */
first_block = (struct boot_blocklist *) (core_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof (*block));
grub_util_info ("root is '%s' and dest is '%s'", root, dest);
/* Open the root device and the destination device. */
grub_util_info ("Opening root");
root_dev = grub_device_open (root);
if (! root_dev)
grub_util_error ("%s", grub_errmsg);
grub_util_info ("Opening dest");
dest_dev = grub_device_open (dest);
if (! dest_dev)
grub_util_error ("%s", grub_errmsg);
grub_util_info ("setting the root device to `%s'", root);
if (grub_env_set ("root", root) != GRUB_ERR_NONE)
grub_util_error ("%s", grub_errmsg);
/* The core image must be put on a filesystem unfortunately. */
grub_util_info ("will leave the core image on the filesystem");
/* Make sure that GRUB reads the identical image as the OS. */
tmp_img = xmalloc (core_size);
core_path = grub_util_get_path (prefix, core_file);
/* It is a Good Thing to sync two times. */
sync ();
sync ();
#define MAX_TRIES 5
for (i = 0; i < MAX_TRIES; i++)
{
grub_util_info ("attempting to read the core image `%s' from GRUB%s",
core_path, (i == 0) ? "" : " again");
grub_disk_cache_invalidate_all ();
file = grub_file_open (core_path);
if (file)
{
if (grub_file_size (file) != core_size)
grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
(int) grub_file_size (file), (int) core_size);
else if (grub_file_read (file, tmp_img, core_size)
!= (grub_ssize_t) core_size)
grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
(int) core_size);
else if (memcmp (core_img, tmp_img, core_size) != 0)
{
#if 0
FILE *dump;
FILE *dump2;
dump = fopen ("dump.img", "wb");
if (dump)
{
fwrite (tmp_img, 1, core_size, dump);
fclose (dump);
}
dump2 = fopen ("dump2.img", "wb");
if (dump2)
{
fwrite (core_img, 1, core_size, dump2);
fclose (dump2);
}
#endif
grub_util_info ("succeeded in opening the core image but the data is different");
}
else
{
grub_file_close (file);
break;
}
grub_file_close (file);
}
else
grub_util_info ("couldn't open the core image");
if (grub_errno)
grub_util_info ("error message = %s", grub_errmsg);
grub_errno = GRUB_ERR_NONE;
sync ();
sleep (1);
}
if (i == MAX_TRIES)
grub_util_error ("Cannot read `%s' correctly", core_path);
/* Clean out the blocklists. */
block = first_block;
while (block->len)
{
block->start = 0;
block->len = 0;
block--;
if ((char *) block <= core_img)
grub_util_error ("No terminator in the core image");
}
/* Now read the core image to determine where the sectors are. */
file = grub_file_open (core_path);
if (! file)
grub_util_error ("%s", grub_errmsg);
file->read_hook = save_first_sector;
if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
grub_util_error ("Failed to read the first sector of the core image");
block = first_block;
file->read_hook = save_blocklists;
if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
!= (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
grub_util_error ("Failed to read the rest sectors of the core image");
grub_file_close (file);
free (core_path);
free (tmp_img);
*kernel_sector = grub_cpu_to_be64 (first_sector);
strcpy(boot_devpath, dest);
grub_util_info ("boot device path %s, prefix is %s, dest is %s",
boot_devpath, prefix, dest);
/* Write the first two sectors of the core image onto the disk. */
core_path = grub_util_get_path (dir, core_file);
grub_util_info ("opening the core image `%s'", core_path);
fp = fopen (core_path, "r+b");
if (! fp)
grub_util_error ("Cannot open `%s'", core_path);
grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp);
fclose (fp);
free (core_path);
/* Write the boot image onto the disk. */
if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
grub_util_error ("%s", grub_errmsg);
/* Sync is a Good Thing. */
sync ();
free (core_img);
free (boot_img);
grub_device_close (dest_dev);
grub_device_close (root_dev);
}
static struct option options[] =
{
{"boot-image", required_argument, 0, 'b'},
{"core-image", required_argument, 0, 'c'},
{"directory", required_argument, 0, 'd'},
{"device-map", required_argument, 0, 'm'},
{"root-device", required_argument, 0, 'r'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-setup --help'' for more information.\n");
else
printf ("\
Usage: grub-setup [OPTION]... DEVICE\n\
\n\
Set up images to boot from DEVICE.\n\
DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
\n\
-b, --boot-image=FILE use FILE as the boot image [default=%s]\n\
-c, --core-image=FILE use FILE as the core image [default=%s]\n\
-d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
-r, --root-device=DEV use DEV as the root device [default=guessed]\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\
Report bugs to <%s>.\n\
",
DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
exit (status);
}
struct grub_setup_info
{
char *boot_file;
char *core_file;
char *dir;
char *dev_map;
char *root_dev;
char *prefix;
char *dest_dev;
};
static void
init_info (struct grub_setup_info *gp)
{
gp->boot_file = NULL;
gp->core_file = NULL;
gp->dir = NULL;
gp->dev_map = NULL;
gp->root_dev = NULL;
gp->prefix = NULL;
gp->dest_dev = NULL;
}
static int
parse_options (struct grub_setup_info *gp, int argc, char *argv[])
{
while (1)
{
int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'b':
if (gp->boot_file)
free (gp->boot_file);
gp->boot_file = xstrdup (optarg);
break;
case 'c':
if (gp->core_file)
free (gp->core_file);
gp->core_file = xstrdup (optarg);
break;
case 'd':
if (gp->dir)
free (gp->dir);
gp->dir = xstrdup (optarg);
break;
case 'm':
if (gp->dev_map)
free (gp->dev_map);
gp->dev_map = xstrdup (optarg);
break;
case 'r':
if (gp->root_dev)
free (gp->root_dev);
gp->root_dev = xstrdup (optarg);
break;
case 'h':
usage (0);
break;
case 'V':
printf ("grub-setup (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
if (verbosity > 1)
grub_env_set ("debug", "all");
if (optind >= argc)
{
fprintf (stderr, "No device is specified.\n");
usage (1);
}
if (optind + 1 != argc)
{
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
usage (1);
}
return 1;
}
static char *
get_device_name (char *dev)
{
size_t len = strlen (dev);
if (dev[0] != '(' || dev[len - 1] != ')')
return 0;
dev[len - 1] = '\0';
return dev + 1;
}
static void
find_dest_dev (struct grub_setup_info *gp, char *argv[])
{
gp->dest_dev = get_device_name (argv[optind]);
if (! gp->dest_dev)
{
/* Possibly, the user specified an OS device file. */
gp->dest_dev = grub_util_get_grub_dev (argv[optind]);
if (! gp->dest_dev)
{
fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
usage (1);
}
grub_util_info ("transformed OS device '%s' into GRUB device '%s'",
argv[optind], gp->dest_dev);
}
else
{
/* For simplicity. */
gp->dest_dev = xstrdup (gp->dest_dev);
grub_util_info ("Using '%s' as GRUB device", gp->dest_dev);
}
}
static void
check_root_dev (struct grub_setup_info *gp)
{
if (gp->root_dev)
{
char *tmp = get_device_name (gp->root_dev);
if (! tmp)
grub_util_error ("Invalid root device `%s'", gp->root_dev);
tmp = xstrdup (tmp);
free (gp->root_dev);
gp->root_dev = tmp;
}
else
{
char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY;
char *root_device = grub_guess_root_device (dir);
gp->root_dev = grub_util_get_grub_dev (root_device);
if (! gp->root_dev)
{
grub_util_info ("guessing the root device failed, because of `%s'",
grub_errmsg);
grub_util_error ("Cannot guess the root device. "
"Specify the option ``--root-device''.");
}
grub_util_info ("Guessed root device '%s' and root_dev '%s' from "
"dir '%s'", root_device, gp->root_dev, dir);
}
}
static void
free_memory (struct grub_setup_info *gp)
{
free (gp->boot_file);
free (gp->core_file);
free (gp->dir);
free (gp->dev_map);
free (gp->root_dev);
free (gp->prefix);
free (gp->dest_dev);
}
int
main (int argc, char *argv[])
{
struct grub_setup_info ginfo;
progname = "grub-setup";
init_info (&ginfo);
if (!parse_options (&ginfo, argc, argv))
return 0;
/* Initialize the emulated biosdisk driver. */
grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP);
/* Initialize all modules. */
grub_init_all ();
find_dest_dev (&ginfo, argv);
ginfo.prefix = grub_get_prefix (ginfo.dir ? : DEFAULT_DIRECTORY);
check_root_dev (&ginfo);
/* Do the real work. */
setup (ginfo.prefix,
ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY,
ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE,
ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE,
ginfo.root_dev, ginfo.dest_dev);
/* Free resources. */
grub_fini_all ();
free_memory (&ginfo);
return 0;
}

View file

@ -0,0 +1,33 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <setjmp.h>
#include <grub/util/misc.h>
void
grub_reboot (void)
{
longjmp (main_env, 1);
}
void
grub_halt (void)
{
grub_reboot ();
}