Resync with trunk

This commit is contained in:
Robert Millan 2010-01-18 15:02:21 +00:00
commit e68d3b243f
706 changed files with 157184 additions and 45875 deletions

View file

@ -1,7 +1,7 @@
/* console.c -- Ncurses console for GRUB. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2007 Free Software Foundation, Inc.
* Copyright (C) 2003,2005,2007,2008 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
@ -19,14 +19,6 @@
#include <config.h>
#if defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#endif
/* For compatibility. */
#ifndef A_NORMAL
# define A_NORMAL 0
@ -35,12 +27,42 @@
# define A_STANDOUT 0
#endif /* ! A_STANDOUT */
#include <grub/machine/console.h>
#include <grub/util/console.h>
#include <grub/term.h>
#include <grub/types.h>
#if defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#endif
static int grub_console_attr = A_NORMAL;
grub_uint8_t grub_console_cur_color = 7;
static grub_uint8_t grub_console_standard_color = 0x7;
static grub_uint8_t grub_console_normal_color = 0x7;
static grub_uint8_t grub_console_highlight_color = 0x70;
#define NUM_COLORS 8
static grub_uint8_t color_map[NUM_COLORS] =
{
COLOR_BLACK,
COLOR_BLUE,
COLOR_GREEN,
COLOR_CYAN,
COLOR_RED,
COLOR_MAGENTA,
COLOR_YELLOW,
COLOR_WHITE
};
static int use_color;
static void
grub_ncurses_putchar (grub_uint32_t c)
{
@ -84,7 +106,7 @@ grub_ncurses_putchar (grub_uint32_t c)
c = '?';
break;
}
addch (c | grub_console_attr);
}
@ -97,27 +119,49 @@ grub_ncurses_getcharwidth (grub_uint32_t code __attribute__ ((unused)))
static void
grub_ncurses_setcolorstate (grub_term_color_state state)
{
switch (state)
switch (state)
{
case GRUB_TERM_COLOR_STANDARD:
grub_console_cur_color = grub_console_standard_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_NORMAL:
grub_console_cur_color = grub_console_normal_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
grub_console_cur_color = grub_console_highlight_color;
grub_console_attr = A_STANDOUT;
break;
default:
break;
}
if (use_color)
{
grub_uint8_t fg, bg;
fg = (grub_console_cur_color & 7);
bg = (grub_console_cur_color >> 4) & 7;
grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
color_set ((bg << 3) + fg, 0);
}
}
/* XXX: This function is never called. */
static void
grub_ncurses_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
{
color_set (normal_color << 8 | highlight_color, 0);
grub_console_normal_color = normal_color;
grub_console_highlight_color = highlight_color;
}
static void
grub_ncurses_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
{
*normal_color = grub_console_normal_color;
*highlight_color = grub_console_highlight_color;
}
static int saved_char = ERR;
@ -126,12 +170,12 @@ static int
grub_ncurses_checkkey (void)
{
int c;
/* Check for SAVED_CHAR. This should not be true, because this
means checkkey is called twice continuously. */
if (saved_char != ERR)
return saved_char;
wtimeout (stdscr, 100);
c = getch ();
/* If C is not ERR, then put it back in the input queue. */
@ -148,7 +192,7 @@ static int
grub_ncurses_getkey (void)
{
int c;
/* If checkkey has already got a character, then return it. */
if (saved_char != ERR)
{
@ -170,7 +214,7 @@ grub_ncurses_getkey (void)
case KEY_RIGHT:
c = 6;
break;
case KEY_UP:
c = 16;
break;
@ -190,7 +234,7 @@ grub_ncurses_getkey (void)
case KEY_BACKSPACE:
/* XXX: For some reason ncurses on xterm does not return
KEY_BACKSPACE. */
case 127:
case 127:
c = 8;
break;
@ -272,7 +316,23 @@ grub_ncurses_init (void)
nonl ();
intrflush (stdscr, FALSE);
keypad (stdscr, TRUE);
start_color ();
if (has_colors ())
{
start_color ();
if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
{
int i, j, n;
n = 0;
for (i = 0; i < NUM_COLORS; i++)
for (j = 0; j < NUM_COLORS; j++)
init_pair(n++, color_map[j], color_map[i]);
use_color = 1;
}
}
return 0;
}
@ -285,32 +345,36 @@ grub_ncurses_fini (void)
}
static struct grub_term grub_ncurses_term =
static struct grub_term_input grub_ncurses_term_input =
{
.name = "console",
.checkkey = grub_ncurses_checkkey,
.getkey = grub_ncurses_getkey,
};
static struct grub_term_output grub_ncurses_term_output =
{
.name = "console",
.init = grub_ncurses_init,
.fini = grub_ncurses_fini,
.putchar = grub_ncurses_putchar,
.getcharwidth = grub_ncurses_getcharwidth,
.checkkey = grub_ncurses_checkkey,
.getkey = grub_ncurses_getkey,
.getxy = grub_ncurses_getxy,
.getwh = grub_ncurses_getwh,
.gotoxy = grub_ncurses_gotoxy,
.cls = grub_ncurses_cls,
.setcolorstate = grub_ncurses_setcolorstate,
.setcolor = grub_ncurses_setcolor,
.getcolor = grub_ncurses_getcolor,
.setcursor = grub_ncurses_setcursor,
.refresh = grub_ncurses_refresh,
.flags = 0,
.next = 0
.refresh = grub_ncurses_refresh
};
void
grub_console_init (void)
{
grub_term_register (&grub_ncurses_term);
grub_term_set_current (&grub_ncurses_term);
grub_term_register_output ("console", &grub_ncurses_term_output);
grub_term_register_input ("console", &grub_ncurses_term_input);
}
void

648
util/deviceiter.c Normal file
View file

@ -0,0 +1,648 @@
/* deviceiter.c - iterate over system devices */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <grub/util/misc.h>
#include <grub/util/deviceiter.h>
#ifdef __linux__
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
# include <linux/unistd.h> /* _llseek */
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
# include <sys/ioctl.h> /* ioctl */
# ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x0301 /* get device geometry */
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
defined. */
struct hd_geometry
{
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
# endif /* ! HDIO_GETGEO */
# ifndef FLOPPY_MAJOR
# define FLOPPY_MAJOR 2 /* the major number for floppy */
# endif /* ! FLOPPY_MAJOR */
# ifndef MAJOR
# define MAJOR(dev) \
({ \
unsigned long long __dev = (dev); \
(unsigned) ((__dev >> 8) & 0xfff) \
| ((unsigned int) (__dev >> 32) & ~0xfff); \
})
# endif /* ! MAJOR */
# ifndef CDROM_GET_CAPABILITY
# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
# endif /* ! CDROM_GET_CAPABILITY */
# ifndef BLKGETSIZE
# define BLKGETSIZE _IO(0x12,96) /* return device size */
# endif /* ! BLKGETSIZE */
#endif /* __linux__ */
/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
# define __FreeBSD_kernel__
#endif
#ifdef __FreeBSD_kernel__
/* Obtain version of kFreeBSD headers */
# include <osreldate.h>
# ifndef __FreeBSD_kernel_version
# define __FreeBSD_kernel_version __FreeBSD_version
# endif
/* Runtime detection of kernel */
# include <sys/utsname.h>
int
get_kfreebsd_version (void)
{
struct utsname uts;
int major;
int minor;
int v[2];
uname (&uts);
sscanf (uts.release, "%d.%d", &major, &minor);
if (major >= 9)
major = 9;
if (major >= 5)
{
v[0] = minor/10; v[1] = minor%10;
}
else
{
v[0] = minor%10; v[1] = minor/10;
}
return major*100000+v[0]*10000+v[1]*1000;
}
#endif /* __FreeBSD_kernel__ */
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/ioctl.h> /* ioctl */
# include <sys/disklabel.h>
# include <sys/cdio.h> /* CDIOCCLRDEBUG */
# if defined(__FreeBSD_kernel__)
# include <sys/param.h>
# if __FreeBSD_kernel_version >= 500040
# include <sys/disk.h>
# endif
# endif /* __FreeBSD_kernel__ */
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
#ifdef HAVE_OPENDISK
# include <util.h>
#endif /* HAVE_OPENDISK */
#ifdef __linux__
/* Check if we have devfs support. */
static int
have_devfs (void)
{
struct stat st;
return stat ("/dev/.devfsd", &st) == 0;
}
#endif /* __linux__ */
/* These three functions are quite different among OSes. */
static void
get_floppy_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
if (have_devfs ())
sprintf (name, "/dev/floppy/%d", unit);
else
sprintf (name, "/dev/fd%d", unit);
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/fd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/fd%d", unit);
else
sprintf (name, "/dev/rfd%d", unit);
#elif defined(__NetBSD__)
/* NetBSD */
/* opendisk() doesn't work for floppies. */
sprintf (name, "/dev/rfd%da", unit);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rfd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
sprintf (name, "/dev/fd%d", unit);
#elif defined(__CYGWIN__)
/* Cygwin */
sprintf (name, "/dev/fd%d", unit);
#elif defined(__MINGW32__)
(void) unit;
*name = 0;
#else
# warning "BIOS floppy drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
static void
get_ide_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
sprintf (name, "/dev/hd%c", unit + 'a');
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/hd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/ad%d", unit);
else
sprintf (name, "/dev/rwd%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
/* NetBSD */
char shortname[16];
int fd;
sprintf (shortname, "wd%d", unit);
fd = opendisk (shortname, O_RDONLY, name,
16, /* length of NAME */
0 /* char device */
);
close (fd);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rwd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
/* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
contain SCSI disks. */
sprintf (name, "/dev/hd%d", unit);
#elif defined(__CYGWIN__)
/* Cygwin emulates all disks as /dev/sdX. */
(void) unit;
*name = 0;
#elif defined(__MINGW32__)
sprintf (name, "//./PHYSICALDRIVE%d", unit);
#else
# warning "BIOS IDE drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
static void
get_scsi_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
sprintf (name, "/dev/sd%c", unit + 'a');
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/sd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/da%d", unit);
else
sprintf (name, "/dev/rda%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
/* NetBSD */
char shortname[16];
int fd;
sprintf (shortname, "sd%d", unit);
fd = opendisk (shortname, O_RDONLY, name,
16, /* length of NAME */
0 /* char device */
);
close (fd);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rsd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
/* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
disable the detection of SCSI disks here. */
*name = 0;
#elif defined(__CYGWIN__)
/* Cygwin emulates all disks as /dev/sdX. */
sprintf (name, "/dev/sd%c", unit + 'a');
#elif defined(__MINGW32__)
(void) unit;
*name = 0;
#else
# warning "BIOS SCSI drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
#ifdef __linux__
static void
get_virtio_disk_name (char *name, int unit)
{
#ifdef __sparc__
sprintf (name, "/dev/vdisk%c", unit + 'a');
#else
sprintf (name, "/dev/vd%c", unit + 'a');
#endif
}
static void
get_dac960_disk_name (char *name, int controller, int drive)
{
sprintf (name, "/dev/rd/c%dd%d", controller, drive);
}
static void
get_acceleraid_disk_name (char *name, int controller, int drive)
{
sprintf (name, "/dev/rs/c%dd%d", controller, drive);
}
static void
get_ataraid_disk_name (char *name, int unit)
{
sprintf (name, "/dev/ataraid/d%c", unit + '0');
}
static void
get_i2o_disk_name (char *name, char unit)
{
sprintf (name, "/dev/i2o/hd%c", unit);
}
static void
get_cciss_disk_name (char *name, int controller, int drive)
{
sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
}
static void
get_ida_disk_name (char *name, int controller, int drive)
{
sprintf (name, "/dev/ida/c%dd%d", controller, drive);
}
static void
get_mmc_disk_name (char *name, int unit)
{
sprintf (name, "/dev/mmcblk%d", unit);
}
static void
get_xvd_disk_name (char *name, int unit)
{
sprintf (name, "/dev/xvd%c", unit + 'a');
}
#endif
/* Check if DEVICE can be read. If an error occurs, return zero,
otherwise return non-zero. */
static int
check_device (const char *device)
{
char buf[512];
FILE *fp;
/* If DEVICE is empty, just return error. */
if (*device == 0)
return 0;
fp = fopen (device, "r");
if (! fp)
{
switch (errno)
{
#ifdef ENOMEDIUM
case ENOMEDIUM:
# if 0
/* At the moment, this finds only CDROMs, which can't be
read anyway, so leave it out. Code should be
reactivated if `removable disks' and CDROMs are
supported. */
/* Accept it, it may be inserted. */
return 1;
# endif
break;
#endif /* ENOMEDIUM */
default:
/* Break case and leave. */
break;
}
/* Error opening the device. */
return 0;
}
/* Make sure CD-ROMs don't get assigned a BIOS disk number
before SCSI disks! */
#ifdef __linux__
# ifdef CDROM_GET_CAPABILITY
if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
return 0;
# else /* ! CDROM_GET_CAPABILITY */
/* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
{
struct hd_geometry hdg;
struct stat st;
if (fstat (fileno (fp), &st))
return 0;
/* If it is a block device and isn't a floppy, check if HDIO_GETGEO
succeeds. */
if (S_ISBLK (st.st_mode)
&& MAJOR (st.st_rdev) != FLOPPY_MAJOR
&& ioctl (fileno (fp), HDIO_GETGEO, &hdg))
return 0;
}
# endif /* ! CDROM_GET_CAPABILITY */
#endif /* __linux__ */
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# ifdef CDIOCCLRDEBUG
if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
return 0;
# endif /* CDIOCCLRDEBUG */
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
/* Attempt to read the first sector. */
if (fread (buf, 1, 512, fp) != 512)
{
fclose (fp);
return 0;
}
fclose (fp);
return 1;
}
void
grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
int floppy_disks)
{
int i;
/* Floppies. */
for (i = 0; i < floppy_disks; i++)
{
char name[16];
struct stat st;
get_floppy_disk_name (name, i);
if (stat (name, &st) < 0)
break;
/* In floppies, write the map, whether check_device succeeds
or not, because the user just may not insert floppies. */
if (hook (name, 1))
return;
}
#ifdef __linux__
if (have_devfs ())
{
i = 0;
while (1)
{
char discn[32];
char name[PATH_MAX];
struct stat st;
/* Linux creates symlinks "/dev/discs/discN" for convenience.
The way to number disks is the same as GRUB's. */
sprintf (discn, "/dev/discs/disc%d", i++);
if (stat (discn, &st) < 0)
break;
if (realpath (discn, name))
{
strcat (name, "/disc");
if (hook (name, 0))
return;
}
}
return;
}
#endif /* __linux__ */
/* IDE disks. */
for (i = 0; i < 26; i++)
{
char name[16];
get_ide_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
#ifdef __linux__
/* Virtio disks. */
for (i = 0; i < 26; i++)
{
char name[16];
get_virtio_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
/* ATARAID disks. */
for (i = 0; i < 8; i++)
{
char name[20];
get_ataraid_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
/* Xen virtual block devices. */
for (i = 0; i < 26; i++)
{
char name[16];
get_xvd_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
#endif /* __linux__ */
/* The rest is SCSI disks. */
for (i = 0; i < 26; i++)
{
char name[16];
get_scsi_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
#ifdef __linux__
/* This is for DAC960 - we have
/dev/rd/c<controller>d<logical drive>p<partition>.
DAC960 driver currently supports up to 8 controllers, 32 logical
drives, and 7 partitions. */
{
int controller, drive;
for (controller = 0; controller < 8; controller++)
{
for (drive = 0; drive < 15; drive++)
{
char name[24];
get_dac960_disk_name (name, controller, drive);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
}
}
/* This is for Mylex Acceleraid - we have
/dev/rd/c<controller>d<logical drive>p<partition>. */
{
int controller, drive;
for (controller = 0; controller < 8; controller++)
{
for (drive = 0; drive < 15; drive++)
{
char name[24];
get_acceleraid_disk_name (name, controller, drive);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
}
}
/* This is for CCISS - we have
/dev/cciss/c<controller>d<logical drive>p<partition>. */
{
int controller, drive;
for (controller = 0; controller < 3; controller++)
{
for (drive = 0; drive < 16; drive++)
{
char name[24];
get_cciss_disk_name (name, controller, drive);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
}
}
/* This is for Compaq Intelligent Drive Array - we have
/dev/ida/c<controller>d<logical drive>p<partition>. */
{
int controller, drive;
for (controller = 0; controller < 3; controller++)
{
for (drive = 0; drive < 16; drive++)
{
char name[24];
get_ida_disk_name (name, controller, drive);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
}
}
/* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
{
char unit;
for (unit = 'a'; unit < 'f'; unit++)
{
char name[24];
get_i2o_disk_name (name, unit);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
}
/* MultiMediaCard (MMC). */
for (i = 0; i < 10; i++)
{
char name[16];
get_mmc_disk_name (name, i);
if (check_device (name))
{
if (hook (name, 0))
return;
}
}
#endif /* __linux__ */
}

13
util/devicemap.c Normal file
View file

@ -0,0 +1,13 @@
#include <stdio.h>
#include <grub/util/deviceiter.h>
void
grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
int *num_fd, int *num_hd)
{
if (is_floppy)
fprintf (fp, "(fd%d)\t%s\n", (*num_fd)++, name);
else
fprintf (fp, "(hd%d)\t%s\n", (*num_hd)++, name);
}

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 2004,2005,2006,2007,2008,2009,2010 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
@ -30,7 +30,10 @@
#include <grub/util/misc.h>
#include <grub/util/resolve.h>
#include <grub/kernel.h>
#include <grub/machine/kernel.h>
#include <grub/cpu/kernel.h>
#include <grub/i18n.h>
#include "progname.h"
#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
#define GRUB_IEEE1275_NOTE_TYPE 0x1275
@ -88,7 +91,7 @@ load_note (Elf32_Phdr *phdr, FILE *out)
/* Fill in the rest of the segment header. */
phdr->p_type = grub_host_to_target32 (PT_NOTE);
phdr->p_flags = grub_host_to_target32 (PF_R);
phdr->p_align = grub_host_to_target32 (sizeof (long));
phdr->p_align = grub_host_to_target32 (GRUB_TARGET_SIZEOF_LONG);
phdr->p_vaddr = 0;
phdr->p_paddr = 0;
phdr->p_filesz = grub_host_to_target32 (note_size);
@ -97,7 +100,7 @@ load_note (Elf32_Phdr *phdr, FILE *out)
void
load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
char *mods[], FILE *out)
char *mods[], FILE *out, char *memdisk_path)
{
char *module_img;
struct grub_util_path_list *path_list;
@ -105,11 +108,20 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
struct grub_module_info *modinfo;
size_t offset;
size_t total_module_size;
size_t memdisk_size = 0;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
offset = sizeof (struct grub_module_info);
total_module_size = sizeof (struct grub_module_info);
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);
}
for (p = path_list; p; p = p->next)
{
total_module_size += (grub_util_get_image_size (p->name)
@ -135,7 +147,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
mod_size = grub_util_get_image_size (p->name);
header = (struct grub_module_header *) (module_img + offset);
header->offset = grub_host_to_target32 (sizeof (*header));
header->type = OBJ_TYPE_ELF;
header->size = grub_host_to_target32 (mod_size + sizeof (*header));
grub_util_load_image (p->name, module_img + offset + sizeof (*header));
@ -143,6 +155,20 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
offset += sizeof (*header) + mod_size;
}
if (memdisk_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (module_img + offset);
header->type = OBJ_TYPE_MEMDISK;
header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (memdisk_path, module_img + offset);
offset += memdisk_size;
}
/* Write the module data to the new segment. */
grub_util_write_image_at (module_img, total_module_size,
grub_host_to_target32 (phdr->p_offset), out);
@ -150,7 +176,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
/* Fill in the rest of the segment header. */
phdr->p_type = grub_host_to_target32 (PT_LOAD);
phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
phdr->p_align = grub_host_to_target32 (sizeof (long));
phdr->p_align = grub_host_to_target32 (GRUB_TARGET_SIZEOF_LONG);
phdr->p_vaddr = grub_host_to_target32 (modbase);
phdr->p_paddr = grub_host_to_target32 (modbase);
phdr->p_filesz = grub_host_to_target32 (total_module_size);
@ -158,7 +184,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
}
void
add_segments (char *dir, FILE *out, int chrp, char *mods[])
add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path)
{
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs = NULL;
@ -166,19 +192,34 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
FILE *in;
char *kernel_path;
grub_addr_t grub_end = 0;
off_t phdroff;
int i;
off_t offset, first_segment;
int i, phdr_size;
/* Read ELF header. */
kernel_path = grub_util_get_path (dir, "kernel.elf");
kernel_path = grub_util_get_path (dir, "kernel.img");
in = fopen (kernel_path, "rb");
if (! in)
grub_util_error ("cannot open %s", kernel_path);
grub_util_read_at (&ehdr, sizeof (ehdr), 0, in);
phdrs = xmalloc (grub_target_to_host16 (ehdr.e_phentsize)
* (grub_target_to_host16 (ehdr.e_phnum) + 2));
offset = ALIGN_UP (sizeof (ehdr), GRUB_TARGET_SIZEOF_LONG);
ehdr.e_phoff = grub_host_to_target32 (offset);
phdr_size = (grub_target_to_host16 (ehdr.e_phentsize) *
grub_target_to_host16 (ehdr.e_phnum));
if (mods[0] != NULL)
phdr_size += grub_target_to_host16 (ehdr.e_phentsize);
if (chrp)
phdr_size += grub_target_to_host16 (ehdr.e_phentsize);
phdrs = xmalloc (phdr_size);
offset += ALIGN_UP (phdr_size, GRUB_TARGET_SIZEOF_LONG);
first_segment = offset;
/* Copy all existing segments. */
for (i = 0; i < grub_target_to_host16 (ehdr.e_phnum); i++)
{
@ -204,11 +245,15 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
/* Read segment data and write it to new file. */
segment_img = xmalloc (grub_target_to_host32 (phdr->p_filesz));
grub_util_read_at (segment_img, grub_target_to_host32 (phdr->p_filesz),
grub_target_to_host32 (phdr->p_offset), in);
phdr->p_offset = grub_host_to_target32 (offset);
grub_util_write_image_at (segment_img, grub_target_to_host32 (phdr->p_filesz),
grub_target_to_host32 (phdr->p_offset), out);
offset, out);
offset += ALIGN_UP (grub_target_to_host32 (phdr->p_filesz),
GRUB_TARGET_SIZEOF_LONG);
free (segment_img);
}
@ -226,9 +271,9 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
/* Fill in p_offset so the callees know where to write. */
phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out),
sizeof (long)));
GRUB_TARGET_SIZEOF_LONG));
load_modules (modbase, phdr, dir, mods, out);
load_modules (modbase, phdr, dir, mods, out, memdisk_path);
}
if (chrp)
@ -239,7 +284,7 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
/* Fill in p_offset so the callees know where to write. */
phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out),
sizeof (long)));
GRUB_TARGET_SIZEOF_LONG));
load_note (phdr, out);
}
@ -249,16 +294,19 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
ehdr.e_shnum = 0;
ehdr.e_shstrndx = 0;
/* Append entire segment table to the file. */
phdroff = ALIGN_UP (grub_util_get_fp_size (out), sizeof (long));
grub_util_write_image_at (phdrs, grub_target_to_host16 (ehdr.e_phentsize)
* grub_target_to_host16 (ehdr.e_phnum), phdroff,
out);
/* Write entire segment table to the file. */
grub_util_write_image_at (phdrs, phdr_size, grub_target_to_host32 (ehdr.e_phoff), out);
/* Write ELF header. */
ehdr.e_phoff = grub_host_to_target32 (phdroff);
grub_util_write_image_at (&ehdr, sizeof (ehdr), 0, out);
if (prefix)
{
if (GRUB_KERNEL_CPU_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_CPU_DATA_END)
grub_util_error ("prefix too long");
grub_util_write_image_at (prefix, strlen (prefix) + 1, first_segment + GRUB_KERNEL_CPU_PREFIX, out);
}
free (phdrs);
free (kernel_path);
}
@ -266,6 +314,8 @@ add_segments (char *dir, FILE *out, int chrp, char *mods[])
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'},
{"note", no_argument, 0, 'n'},
@ -278,22 +328,24 @@ static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
Usage: %s -o FILE [OPTION]... [MODULES]\n\
\n\
Make a bootable image of GRUB.\n\
\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-o, --output=FILE output a generated image to FILE\n\
-h, --help display this message and exit\n\
-n, --note add NOTE segment for CHRP Open Firmware\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-p, --prefix=DIR set grub_prefix directory\n\
-m, --memdisk=FILE embed FILE as a memdisk image\n\
-o, --output=FILE output a generated image to FILE\n\
-h, --help display this message and exit\n\
-n, --note add NOTE segment for CHRP Open Firmware\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\
Report bugs to <%s>.\n\
", GRUB_LIBDIR, PACKAGE_BUGREPORT);
", program_name, GRUB_LIBDIR, PACKAGE_BUGREPORT);
exit (status);
}
@ -304,13 +356,17 @@ main (int argc, char *argv[])
FILE *fp;
char *output = NULL;
char *dir = NULL;
char *prefix = NULL;
char *memdisk = NULL;
int chrp = 0;
progname = "grub-mkimage";
set_program_name (argv[0]);
grub_util_init_nls ();
while (1)
{
int c = getopt_long (argc, argv, "d:o:hVvn", options, 0);
int c = getopt_long (argc, argv, "d:p:m:o:hVvn", options, 0);
if (c == -1)
break;
@ -320,6 +376,21 @@ main (int argc, char *argv[])
if (dir)
free (dir);
dir = xstrdup (optarg);
break;
case 'p':
if (prefix)
free (prefix);
prefix = 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);
@ -351,7 +422,7 @@ main (int argc, char *argv[])
if (! fp)
grub_util_error ("cannot open %s", output);
add_segments (dir ? : GRUB_LIBDIR, fp, chrp, argv + optind);
add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk);
fclose (fp);

View file

@ -1,278 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#define BUF_SIZE 1024
#define SYMTAB_SIZE 509
struct symbol
{
const char *name;
const char *mod;
struct symbol *next;
};
struct module
{
const char *name;
struct module *next;
};
static char buf[BUF_SIZE];
static struct symbol *symtab[SYMTAB_SIZE];
static void
err (const char *fmt, ...)
{
va_list ap;
fprintf (stderr, "genmoddep: error: ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fputc ('\n', stderr);
exit (1);
}
static void *
xmalloc (size_t size)
{
void *p;
p = malloc (size);
if (! p)
err ("out of memory");
return p;
}
static char *
xstrdup (const char *str)
{
char *s;
size_t len;
len = strlen (str);
s = (char *) xmalloc (len + 1);
memcpy (s, str, len + 1);
return s;
}
static void
chomp (char *str)
{
int end;
end = strlen (str) - 1;
if (end < 0)
err ("empty string");
if (str[end] == '\n')
str[end] = '\0';
}
static unsigned
symbol_hash (const char *s)
{
unsigned key = 0;
while (*s)
key = key * 65599 + *s++;
return (key + (key >> 5)) % SYMTAB_SIZE;
}
static struct symbol *
get_symbol (const char *name)
{
unsigned k;
struct symbol *sym;
k = symbol_hash (name);
for (sym = symtab[k]; sym; sym = sym->next)
if (strcmp (sym->name, name) == 0)
return sym;
return 0;
}
static void
add_symbol (const char *name, const char *mod)
{
unsigned k;
struct symbol *sym;
if (get_symbol (name))
err ("duplicated symbol: %s", name);
sym = (struct symbol *) xmalloc (sizeof (*sym));
sym->name = xstrdup (name);
sym->mod = xstrdup (mod);
k = symbol_hash (name);
sym->next = symtab[k];
symtab[k] = sym;
}
static void
free_symbols (void)
{
int i;
for (i = 0; i < SYMTAB_SIZE; i++)
{
struct symbol *p, *q;
p = symtab[i];
while (p)
{
q = p->next;
free ((void *) p->name);
free ((void *) p->mod);
free (p);
p = q;
}
}
}
static void
read_defined_symbols (FILE *fp)
{
while (fgets (buf, sizeof (buf), fp))
{
char *p;
if (! *buf)
err ("empty symbol name: %s", buf);
p = strchr (buf, ' ');
if (! p)
err ("invalid line format: %s", buf);
p++;
if (! *p)
err ("empty module name: %s", buf);
*(p - 1) = '\0';
chomp (p);
add_symbol (buf, p);
}
}
static void
add_module (struct module **head, const char *name)
{
struct module *mod;
for (mod = *head; mod; mod = mod->next)
if (strcmp (mod->name, name) == 0)
return;
mod = (struct module *) xmalloc (sizeof (*mod));
mod->name = xstrdup (name);
mod->next = *head;
*head = mod;
}
static void
free_modules (struct module *head)
{
struct module *next;
while (head)
{
next = head->next;
free ((void *) head->name);
free (head);
head = next;
}
}
static void
find_dependencies (FILE *fp)
{
char *mod_name;
struct module *mod_list = 0;
struct module *mod;
if (! fgets (buf, sizeof (buf), fp) || buf[0] == '\n' || buf[0] == '\0')
err ("no module name");
chomp (buf);
mod_name = xstrdup (buf);
while (fgets (buf, sizeof (buf), fp))
{
struct symbol *sym;
chomp (buf);
sym = get_symbol (buf);
if (! sym)
err ("%s in %s is not defined", buf, mod_name);
add_module (&mod_list, sym->mod);
}
printf ("%s:", mod_name);
for (mod = mod_list; mod; mod = mod->next)
if (strcmp (mod->name, "kernel") != 0)
printf (" %s", mod->name);
putchar ('\n');
free_modules (mod_list);
}
int
main (int argc, char *argv[])
{
int i;
/* First, get defined symbols. */
read_defined_symbols (stdin);
/* Second, find the dependencies. */
for (i = 1; i < argc; i++)
{
FILE *fp;
fp = fopen (argv[i], "r");
if (! fp)
err ("cannot open %s", argv[i]);
find_dependencies (fp);
fclose (fp);
}
/* Last, free memory. */
free_symbols ();
return 0;
}

View file

@ -1,7 +1,7 @@
/* getroot.c - Get root device */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 1999,2000,2001,2002,2003,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
@ -17,13 +17,27 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#ifdef __CYGWIN__
# include <sys/fcntl.h>
# include <sys/cygwin.h>
# include <limits.h>
# define DEV_CYGDRIVE_MAJOR 98
#endif
#ifdef __GNU__
#include <hurd.h>
#include <hurd/lookup.h>
#include <hurd/fs.h>
#endif
#include <grub/util/misc.h>
#include <grub/util/biosdisk.h>
#include <grub/util/hostdisk.h>
#include <grub/util/getroot.h>
static void
@ -40,10 +54,11 @@ strip_extra_slashes (char *dir)
}
else if (p[1] == '\0')
{
p[0] = '\0';
if (p > dir)
p[0] = '\0';
break;
}
p++;
}
}
@ -64,6 +79,30 @@ xgetcwd (void)
return path;
}
#ifdef __CYGWIN__
/* Convert POSIX path to Win32 path,
remove drive letter, replace backslashes. */
static char *
get_win32_path (const char *path)
{
char winpath[PATH_MAX];
cygwin_conv_to_full_win32_path (path, winpath);
int len = strlen (winpath);
if (len > 2 && winpath[1] == ':')
{
len -= 2;
memmove (winpath, winpath + 2, len + 1);
}
int i;
for (i = 0; i < len; i++)
if (winpath[i] == '\\')
winpath[i] = '/';
return xstrdup (winpath);
}
#endif
char *
grub_get_prefix (const char *dir)
{
@ -71,19 +110,19 @@ grub_get_prefix (const char *dir)
char *abs_dir, *prev_dir;
char *prefix;
struct stat st, prev_st;
/* Save the current directory. */
saved_cwd = xgetcwd ();
if (chdir (dir) < 0)
grub_util_error ("Cannot change directory to `%s'", dir);
grub_util_error ("cannot change directory to `%s'", dir);
abs_dir = xgetcwd ();
strip_extra_slashes (abs_dir);
prev_dir = xstrdup (abs_dir);
if (stat (".", &prev_st) < 0)
grub_util_error ("Cannot stat `%s'", dir);
grub_util_error ("cannot stat `%s'", dir);
if (! S_ISDIR (prev_st.st_mode))
grub_util_error ("`%s' is not a directory", dir);
@ -91,13 +130,13 @@ grub_get_prefix (const char *dir)
while (1)
{
if (chdir ("..") < 0)
grub_util_error ("Cannot change directory to the parent");
grub_util_error ("cannot change directory to the parent");
if (stat (".", &st) < 0)
grub_util_error ("Cannot stat current directory");
grub_util_error ("cannot stat current directory");
if (! S_ISDIR (st.st_mode))
grub_util_error ("Current directory is not a directory???");
grub_util_error ("current directory is not a directory???");
if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
break;
@ -114,7 +153,20 @@ grub_get_prefix (const char *dir)
strip_extra_slashes (prefix);
if (chdir (saved_cwd) < 0)
grub_util_error ("Cannot change directory to `%s'", dir);
grub_util_error ("cannot change directory to `%s'", dir);
#ifdef __CYGWIN__
if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
{
/* Reached some mount point not below /cygdrive.
GRUB does not know Cygwin's emulated mounts,
convert to Win32 path. */
grub_util_info ("Cygwin prefix = %s", prefix);
char * wprefix = get_win32_path (prefix);
free (prefix);
prefix = wprefix;
}
#endif
free (saved_cwd);
free (abs_dir);
@ -124,13 +176,24 @@ grub_get_prefix (const char *dir)
return prefix;
}
#ifdef __MINGW32__
static char *
find_root_device (const char *dir __attribute__ ((unused)),
dev_t dev __attribute__ ((unused)))
{
return 0;
}
#elif ! defined(__CYGWIN__)
static char *
find_root_device (const char *dir, dev_t dev)
{
DIR *dp;
char *saved_cwd;
struct dirent *ent;
dp = opendir (dir);
if (! dp)
return 0;
@ -144,12 +207,15 @@ find_root_device (const char *dir, dev_t dev)
closedir (dp);
return 0;
}
while ((ent = readdir (dp)) != 0)
{
struct stat st;
if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0)
/* Avoid:
- dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
- dotdirs (like "/dev/.static") since they could contain duplicates. */
if (ent->d_name[0] == '.')
continue;
if (lstat (ent->d_name, &st) < 0)
@ -159,12 +225,10 @@ find_root_device (const char *dir, dev_t dev)
if (S_ISLNK (st.st_mode))
/* Don't follow symbolic links. */
continue;
if (S_ISDIR (st.st_mode) && ent->d_name[0] != '.')
if (S_ISDIR (st.st_mode))
{
/* Find it recursively, but avoid dotdirs (like ".static") since they
could contain duplicates, which would later break the
pathname-based check */
/* Find it recursively. */
char *res;
res = find_root_device (ent->d_name, dev);
@ -172,16 +236,31 @@ find_root_device (const char *dir, dev_t dev)
if (res)
{
if (chdir (saved_cwd) < 0)
grub_util_error ("Cannot restore the original directory");
grub_util_error ("cannot restore the original directory");
free (saved_cwd);
closedir (dp);
return res;
}
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
#else
if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
#endif
{
#ifdef __linux__
/* Skip device names like /dev/dm-0, which are short-hand aliases
to more descriptive device names, e.g. those under /dev/mapper */
if (ent->d_name[0] == 'd' &&
ent->d_name[1] == 'm' &&
ent->d_name[2] == '-' &&
ent->d_name[3] >= '0' &&
ent->d_name[3] <= '9')
continue;
#endif
/* Found! */
char *res;
char *cwd;
@ -200,7 +279,7 @@ find_root_device (const char *dir, dev_t dev)
continue;
if (chdir (saved_cwd) < 0)
grub_util_error ("Cannot restore the original directory");
grub_util_error ("cannot restore the original directory");
free (saved_cwd);
closedir (dp);
@ -209,47 +288,219 @@ find_root_device (const char *dir, dev_t dev)
}
if (chdir (saved_cwd) < 0)
grub_util_error ("Cannot restore the original directory");
grub_util_error ("cannot restore the original directory");
free (saved_cwd);
closedir (dp);
return 0;
}
#else /* __CYGWIN__ */
/* Read drive/partition serial number from mbr/boot sector,
return 0 on read error, ~0 on unknown serial. */
static unsigned
get_bootsec_serial (const char *os_dev, int mbr)
{
/* Read boot sector. */
int fd = open (os_dev, O_RDONLY);
if (fd < 0)
return 0;
unsigned char buf[0x200];
int n = read (fd, buf, sizeof (buf));
close (fd);
if (n != sizeof(buf))
return 0;
/* Check signature. */
if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
return ~0;
/* Serial number offset depends on boot sector type. */
if (mbr)
n = 0x1b8;
else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
n = 0x048;
else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
n = 0x043;
else if (memcmp (buf + 0x36, "FAT", 3) == 0)
n = 0x027;
else
return ~0;
unsigned serial = *(unsigned *)(buf + n);
if (serial == 0)
return ~0;
return serial;
}
static char *
find_cygwin_root_device (const char *path, dev_t dev)
{
/* No root device for /cygdrive. */
if (dev == (DEV_CYGDRIVE_MAJOR << 16))
return 0;
/* Convert to full POSIX and Win32 path. */
char fullpath[PATH_MAX], winpath[PATH_MAX];
cygwin_conv_to_full_posix_path (path, fullpath);
cygwin_conv_to_full_win32_path (fullpath, winpath);
/* If identical, this is no real filesystem path. */
if (strcmp (fullpath, winpath) == 0)
return 0;
/* Check for floppy drive letter. */
if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
/* Cygwin returns the partition serial number in stat.st_dev.
This is never identical to the device number of the emulated
/dev/sdXN device, so above find_root_device () does not work.
Search the partition with the same serial in boot sector instead. */
char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */
int d;
for (d = 'a'; d <= 'z'; d++)
{
sprintf (devpath, "/dev/sd%c", d);
if (get_bootsec_serial (devpath, 1) == 0)
continue;
int p;
for (p = 1; p <= 15; p++)
{
sprintf (devpath, "/dev/sd%c%d", d, p);
unsigned ser = get_bootsec_serial (devpath, 0);
if (ser == 0)
break;
if (ser != (unsigned)~0 && dev == (dev_t)ser)
return xstrdup (devpath);
}
}
return 0;
}
#endif /* __CYGWIN__ */
char *
grub_guess_root_device (const char *dir)
{
struct stat st;
char *os_dev;
if (stat (dir, &st) < 0)
grub_util_error ("Cannot stat `%s'", dir);
#ifdef __GNU__
file_t file;
mach_port_t *ports;
int *ints;
loff_t *offsets;
char *data;
error_t err;
mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
size_t name_len;
#ifdef __linux__
/* We first try to find the device in the /dev/mapper directory. If
we don't do this, we get useless device names like /dev/dm-0 for
LVM. */
os_dev = find_root_device ("/dev/mapper", st.st_dev);
if (!os_dev)
#endif
file = file_name_lookup (dir, 0, 0);
if (file == MACH_PORT_NULL)
return 0;
err = file_get_storage_info (file,
&ports, &num_ports,
&ints, &num_ints,
&offsets, &num_offsets,
&data, &data_len);
if (num_ints < 1)
grub_util_error ("Storage info for `%s' does not include type", dir);
if (ints[0] != STORAGE_DEVICE)
grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
if (num_ints < 5)
grub_util_error ("Storage info for `%s' does not include name", dir);
name_len = ints[4];
if (name_len < data_len)
grub_util_error ("Bogus name length for storage info for `%s'", dir);
if (data[name_len - 1] != '\0')
grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
os_dev = xmalloc (strlen ("/dev/") + data_len);
memcpy (os_dev, "/dev/", strlen ("/dev/"));
memcpy (os_dev + strlen ("/dev/"), data, data_len);
if (ports && num_ports > 0)
{
/* This might be truly slow, but is there any better way? */
os_dev = find_root_device ("/dev", st.st_dev);
mach_msg_type_number_t i;
for (i = 0; i < num_ports; i++)
{
mach_port_t port = ports[i];
if (port != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self(), port);
}
munmap ((caddr_t) ports, num_ports * sizeof (*ports));
}
if (ints && num_ints > 0)
munmap ((caddr_t) ints, num_ints * sizeof (*ints));
if (offsets && num_offsets > 0)
munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
if (data && data_len > 0)
munmap (data, data_len);
mach_port_deallocate (mach_task_self (), file);
#else /* !__GNU__ */
struct stat st;
if (stat (dir, &st) < 0)
grub_util_error ("cannot stat `%s'", dir);
#ifdef __CYGWIN__
/* Cygwin specific function. */
os_dev = find_cygwin_root_device (dir, st.st_dev);
#else
/* This might be truly slow, but is there any better way? */
os_dev = find_root_device ("/dev", st.st_dev);
#endif
#endif /* !__GNU__ */
return os_dev;
}
int
grub_util_is_dmraid (const char *os_dev)
{
if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
return 1;
return 0;
}
int
grub_util_get_dev_abstraction (const char *os_dev)
grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
{
#ifdef __linux__
/* Check for LVM. */
if (!strncmp (os_dev, "/dev/mapper/", 12))
if (!strncmp (os_dev, "/dev/mapper/", 12)
&& ! grub_util_is_dmraid (os_dev)
&& strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
return GRUB_DEV_ABSTRACTION_LVM;
/* Check for RAID. */
if (!strncmp (os_dev, "/dev/md", 7))
return GRUB_DEV_ABSTRACTION_RAID;
#endif
/* No abstraction found. */
return GRUB_DEV_ABSTRACTION_NONE;
@ -263,61 +514,84 @@ grub_util_get_grub_dev (const char *os_dev)
switch (grub_util_get_dev_abstraction (os_dev))
{
case GRUB_DEV_ABSTRACTION_LVM:
grub_dev = xmalloc (strlen (os_dev) - 12 + 1);
strcpy (grub_dev, os_dev + 12);
{
unsigned short i, len;
grub_size_t offset = sizeof ("/dev/mapper/") - 1;
len = strlen (os_dev) - offset + 1;
grub_dev = xmalloc (len);
for (i = 0; i < len; i++, offset++)
{
grub_dev[i] = os_dev[offset];
if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
offset++;
}
}
break;
case GRUB_DEV_ABSTRACTION_RAID:
grub_dev = xmalloc (20);
if (os_dev[7] == '_' && os_dev[8] == 'd')
{
const char *p;
/* This a partitionable RAID device of the form /dev/md_dNNpMM. */
int i;
grub_dev[0] = 'm';
grub_dev[1] = 'd';
i = 2;
p = os_dev + 9;
while (*p >= '0' && *p <= '9')
{
grub_dev[i] = *p;
i++;
p++;
}
char *p, *q;
if (*p == '\0')
grub_dev[i] = '\0';
else if (*p == 'p')
{
p++;
grub_dev[i] = ',';
i++;
p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
while (*p >= '0' && *p <= '9')
{
grub_dev[i] = *p;
i++;
p++;
}
q = strchr (p, 'p');
if (q)
*q = ',';
grub_dev[i] = '\0';
}
else
grub_util_error ("Unknown kind of RAID device `%s'", os_dev);
grub_dev = xasprintf ("md%s", p);
free (p);
}
else if (os_dev[7] == '/' && os_dev[8] == 'd')
{
/* This a partitionable RAID device of the form /dev/md/dNNpMM. */
char *p, *q;
p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
q = strchr (p, 'p');
if (q)
*q = ',';
grub_dev = xasprintf ("md%s", p);
free (p);
}
else if (os_dev[7] >= '0' && os_dev[7] <= '9')
{
memcpy (grub_dev, os_dev + 5, 7);
grub_dev[7] = '\0';
char *p , *q;
p = strdup (os_dev + sizeof ("/dev/md") - 1);
q = strchr (p, 'p');
if (q)
*q = ',';
grub_dev = xasprintf ("md%s", p);
free (p);
}
else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
{
char *p , *q;
p = strdup (os_dev + sizeof ("/dev/md/") - 1);
q = strchr (p, 'p');
if (q)
*q = ',';
grub_dev = xasprintf ("md%s", p);
free (p);
}
else
grub_util_error ("Unknown kind of RAID device `%s'", os_dev);
grub_util_error ("unknown kind of RAID device `%s'", os_dev);
break;
@ -327,3 +601,32 @@ grub_util_get_grub_dev (const char *os_dev)
return grub_dev;
}
const char *
grub_util_check_block_device (const char *blk_dev)
{
struct stat st;
if (stat (blk_dev, &st) < 0)
grub_util_error ("cannot stat `%s'", blk_dev);
if (S_ISBLK (st.st_mode))
return (blk_dev);
else
return 0;
}
const char *
grub_util_check_char_device (const char *blk_dev)
{
struct stat st;
if (stat (blk_dev, &st) < 0)
grub_util_error ("cannot stat `%s'", blk_dev);
if (S_ISCHR (st.st_mode))
return (blk_dev);
else
return 0;
}

320
util/grub-editenv.c Normal file
View file

@ -0,0 +1,320 @@
/* grub-editenv.c - tool to edit environment block. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009,2010 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/lib/envblk.h>
#include <grub/handler.h>
#include <grub/i18n.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include "progname.h"
#define DEFAULT_ENVBLK_SIZE 1024
void
grub_putchar (int c)
{
putchar (c);
}
void
grub_refresh (void)
{
fflush (stdout);
}
int
grub_getkey (void)
{
return 0;
}
char *
grub_env_get (const char *name __attribute__ ((unused)))
{
return NULL;
}
static struct option options[] = {
{"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 `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTIONS] [FILENAME] COMMAND\n\
\n\
Tool to edit environment block.\n\
\nCommands:\n\
create create a blank environment block file\n\
list list the current variables\n\
set [name=value ...] set variables\n\
unset [name ....] delete variables\n\
\nOptions:\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
\n\
If not given explicitly, FILENAME defaults to %s.\n\
\n\
Report bugs to <%s>.\n",
program_name, DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT);
exit (status);
}
static void
create_envblk_file (const char *name)
{
FILE *fp;
char *buf;
char *namenew;
buf = malloc (DEFAULT_ENVBLK_SIZE);
if (! buf)
grub_util_error ("out of memory");
namenew = xasprintf ("%s.new", name);
fp = fopen (namenew, "wb");
if (! fp)
grub_util_error ("cannot open the file %s", namenew);
memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#',
DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE)
grub_util_error ("cannot write to the file %s", namenew);
fsync (fileno (fp));
free (buf);
fclose (fp);
if (rename (namenew, name) < 0)
grub_util_error ("cannot rename the file %s to %s", namenew, name);
free (namenew);
}
static grub_envblk_t
open_envblk_file (const char *name)
{
FILE *fp;
char *buf;
size_t size;
grub_envblk_t envblk;
fp = fopen (name, "rb");
if (! fp)
{
/* Create the file implicitly. */
create_envblk_file (name);
fp = fopen (name, "rb");
if (! fp)
grub_util_error ("cannot open the file %s", name);
}
if (fseek (fp, 0, SEEK_END) < 0)
grub_util_error ("cannot seek the file %s", name);
size = (size_t) ftell (fp);
if (fseek (fp, 0, SEEK_SET) < 0)
grub_util_error ("cannot seek the file %s", name);
buf = malloc (size);
if (! buf)
grub_util_error ("out of memory");
if (fread (buf, 1, size, fp) != size)
grub_util_error ("cannot read the file %s", name);
fclose (fp);
envblk = grub_envblk_open (buf, size);
if (! envblk)
grub_util_error ("invalid environment block");
return envblk;
}
static void
list_variables (const char *name)
{
grub_envblk_t envblk;
auto int print_var (const char *name, const char *value);
int print_var (const char *name, const char *value)
{
printf ("%s=%s\n", name, value);
return 0;
}
envblk = open_envblk_file (name);
grub_envblk_iterate (envblk, print_var);
grub_envblk_close (envblk);
}
static void
write_envblk (const char *name, grub_envblk_t envblk)
{
FILE *fp;
fp = fopen (name, "wb");
if (! fp)
grub_util_error ("cannot open the file %s", name);
if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp)
!= grub_envblk_size (envblk))
grub_util_error ("cannot write to the file %s", name);
fsync (fileno (fp));
fclose (fp);
}
static void
set_variables (const char *name, int argc, char *argv[])
{
grub_envblk_t envblk;
envblk = open_envblk_file (name);
while (argc)
{
char *p;
p = strchr (argv[0], '=');
if (! p)
grub_util_error ("invalid parameter %s", argv[0]);
*(p++) = 0;
if (! grub_envblk_set (envblk, argv[0], p))
grub_util_error ("environment block too small");
argc--;
argv++;
}
write_envblk (name, envblk);
grub_envblk_close (envblk);
}
static void
unset_variables (const char *name, int argc, char *argv[])
{
grub_envblk_t envblk;
envblk = open_envblk_file (name);
while (argc)
{
grub_envblk_delete (envblk, argv[0]);
argc--;
argv++;
}
write_envblk (name, envblk);
grub_envblk_close (envblk);
}
int
main (int argc, char *argv[])
{
char *filename;
char *command;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
/* Obtain the filename. */
if (optind >= argc)
{
fprintf (stderr, "no filename specified\n");
usage (1);
}
if (optind + 1 >= argc)
{
filename = DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG;
command = argv[optind];
}
else
{
filename = argv[optind];
command = argv[optind + 1];
}
if (strcmp (command, "create") == 0)
create_envblk_file (filename);
else if (strcmp (command, "list") == 0)
list_variables (filename);
else if (strcmp (command, "set") == 0)
set_variables (filename, argc - optind - 2, argv + optind + 2);
else if (strcmp (command, "unset") == 0)
unset_variables (filename, argc - optind - 2, argv + optind + 2);
else
{
fprintf (stderr, "unknown command %s\n", command);
usage (1);
}
return 0;
}

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 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
@ -27,28 +27,31 @@
#include <grub/mm.h>
#include <grub/setjmp.h>
#include <grub/fs.h>
#include <grub/util/biosdisk.h>
#include <grub/util/hostdisk.h>
#include <grub/dl.h>
#include <grub/machine/console.h>
#include <grub/util/console.h>
#include <grub/util/misc.h>
#include <grub/kernel.h>
#include <grub/normal.h>
#include <grub/util/getroot.h>
#include <grub/env.h>
#include <grub/partition.h>
#include <grub/i18n.h>
#include <grub_emu_init.h>
#include "progname.h"
/* Used for going back to the main function. */
jmp_buf main_env;
static jmp_buf main_env;
/* Store the prefix specified by an argument. */
static char *prefix = 0;
static char *prefix = NULL;
grub_addr_t
grub_arch_modules_addr (void)
{
return 0;
return NULL;
}
grub_err_t
@ -68,11 +71,25 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
return GRUB_ERR_BAD_MODULE;
}
void
grub_reboot (void)
{
longjmp (main_env, 1);
}
void
grub_halt (
#ifdef GRUB_MACHINE_PCBIOS
int no_apm __attribute__ ((unused))
#endif
)
{
grub_reboot ();
}
void
grub_machine_init (void)
{
signal (SIGINT, SIG_IGN);
grub_console_init ();
}
void
@ -88,6 +105,11 @@ grub_machine_fini (void)
{
grub_console_fini ();
}
void
read_command_list (void)
{
}
static struct option options[] =
@ -102,15 +124,15 @@ static struct option options[] =
{ 0, 0, 0, 0 }
};
static int
static int
usage (int status)
{
if (status)
fprintf (stderr,
"Try ``grub-emu --help'' for more information.\n");
"Try `%s --help' for more information.\n", program_name);
else
printf (
"Usage: grub-emu [OPTION]...\n"
"Usage: %s [OPTION]...\n"
"\n"
"GRUB emulator.\n"
"\n"
@ -122,7 +144,7 @@ usage (int status)
" -h, --help display this message and exit\n"
" -V, --version print version information and exit\n"
"\n"
"Report bugs to <%s>.\n", DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
"Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
return status;
}
@ -135,8 +157,10 @@ main (int argc, char *argv[])
char *dev_map = DEFAULT_DEVICE_MAP;
volatile int hold = 0;
int opt;
progname = "grub-emu";
set_program_name (argv[0]);
grub_util_init_nls ();
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
switch (opt)
@ -159,7 +183,7 @@ main (int argc, char *argv[])
case 'h':
return usage (0);
case 'V':
printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
default:
return usage (1);
@ -174,7 +198,7 @@ main (int argc, char *argv[])
/* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
if (hold && verbosity > 0)
printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
progname, (int) getpid ());
program_name, (int) getpid ());
while (hold)
{
if (hold > 0)
@ -182,12 +206,13 @@ main (int argc, char *argv[])
sleep (1);
}
signal (SIGINT, SIG_IGN);
grub_console_init ();
/* XXX: This is a bit unportable. */
grub_util_biosdisk_init (dev_map);
grub_hostfs_init ();
grub_init_all ();
/* Make sure that there is a root device. */
@ -195,14 +220,14 @@ main (int argc, char *argv[])
{
char *device_name = grub_guess_root_device (dir);
if (! device_name)
grub_util_error ("cannot find a device for %s.\n", dir);
grub_util_error ("cannot find a device for %s", dir);
root_dev = grub_util_get_grub_dev (device_name);
if (! 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_error ("cannot guess the root device. Specify the option `--root-device'");
}
}
@ -210,16 +235,14 @@ main (int argc, char *argv[])
prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
sprintf (prefix, "(%s)%s", root_dev, dir);
free (dir);
/* Start GRUB! */
if (setjmp (main_env) == 0)
grub_main ();
grub_fini_all ();
grub_hostfs_fini ();
grub_machine_fini ();
return 0;
}

566
util/grub-fstest.c Normal file
View file

@ -0,0 +1,566 @@
/* grub-fstest.c - debug tool for filesystem driver */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009,2010 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/misc.h>
#include <grub/device.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/fs.h>
#include <grub/env.h>
#include <grub/term.h>
#include <grub/mm.h>
#include <grub/lib/hexdump.h>
#include <grub/lib/crc.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub_fstest_init.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include "progname.h"
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 grub_err_t
execute_command (char *name, int n, char **args)
{
grub_command_t cmd;
cmd = grub_command_find (name);
if (! cmd)
grub_util_error ("can\'t find command %s", name);
return (cmd->func) (cmd, n, args);
}
#define CMD_LS 1
#define CMD_CP 2
#define CMD_CMP 3
#define CMD_HEX 4
#define CMD_CRC 6
#define CMD_BLOCKLIST 7
#define BUF_SIZE 32256
static grub_disk_addr_t skip, leng;
static void
read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
{
static char buf[BUF_SIZE];
grub_file_t file;
grub_off_t ofs, len;
if ((pathname[0] == '-') && (pathname[1] == 0))
{
grub_device_t dev;
dev = grub_device_open (0);
if ((! dev) || (! dev->disk))
grub_util_error ("can\'t open device");
grub_util_info ("total sectors : %lld",
(unsigned long long) dev->disk->total_sectors);
if (! leng)
leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
while (leng)
{
grub_size_t len;
len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
if (grub_disk_read (dev->disk, 0, skip, len, buf))
grub_util_error ("disk read fails at offset %lld, length %d",
skip, len);
if (hook (skip, buf, len))
break;
skip += len;
leng -= len;
}
grub_device_close (dev);
return;
}
file = grub_file_open (pathname);
if (!file)
{
grub_util_error ("cannot open file %s", pathname);
return;
}
grub_util_info ("file size : %lld", (unsigned long long) file->size);
if (skip > file->size)
{
grub_util_error ("invalid skip value %lld", (unsigned long long) skip);
return;
}
ofs = skip;
len = file->size - skip;
if ((leng) && (leng < len))
len = leng;
file->offset = skip;
while (len)
{
grub_ssize_t sz;
sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
if (sz < 0)
{
grub_util_error ("read error at offset %llu", ofs);
break;
}
if ((sz == 0) || (hook (ofs, buf, sz)))
break;
ofs += sz;
len -= sz;
}
grub_file_close (file);
}
static void
cmd_cp (char *src, char *dest)
{
FILE *ff;
auto int cp_hook (grub_off_t ofs, char *buf, int len);
int cp_hook (grub_off_t ofs, char *buf, int len)
{
(void) ofs;
if ((int) fwrite (buf, 1, len, ff) != len)
{
grub_util_error ("write error");
return 1;
}
return 0;
}
ff = fopen (dest, "wb");
if (ff == NULL)
{
grub_util_error ("open error");
return;
}
read_file (src, cp_hook);
fclose (ff);
}
static void
cmd_cmp (char *src, char *dest)
{
FILE *ff;
static char buf_1[BUF_SIZE];
auto int cmp_hook (grub_off_t ofs, char *buf, int len);
int cmp_hook (grub_off_t ofs, char *buf, int len)
{
if ((int) fread (buf_1, 1, len, ff) != len)
{
grub_util_error ("read error at offset %llu", ofs);
return 1;
}
if (grub_memcmp (buf, buf_1, len))
{
int i;
for (i = 0; i < len; i++, ofs++)
if (buf_1[i] != buf[i])
{
grub_util_error ("compare fail at offset %llu", ofs);
return 1;
}
}
return 0;
}
ff = fopen (dest, "rb");
if (ff == NULL)
{
grub_util_error ("open error");
return;
}
if ((skip) && (fseeko (ff, skip, SEEK_SET)))
grub_util_error ("seek error");
read_file (src, cmp_hook);
fclose (ff);
}
static void
cmd_hex (char *pathname)
{
auto int hex_hook (grub_off_t ofs, char *buf, int len);
int hex_hook (grub_off_t ofs, char *buf, int len)
{
hexdump (ofs, buf, len);
return 0;
}
read_file (pathname, hex_hook);
}
static void
cmd_crc (char *pathname)
{
grub_uint32_t crc = 0;
auto int crc_hook (grub_off_t ofs, char *buf, int len);
int crc_hook (grub_off_t ofs, char *buf, int len)
{
(void) ofs;
crc = grub_getcrc32 (crc, buf, len);
return 0;
}
read_file (pathname, crc_hook);
printf ("%08x\n", crc);
}
static void
fstest (char **images, int num_disks, int cmd, int n, char **args)
{
char host_file[128];
char loop_name[8];
char *argv[3] = { "-p", loop_name, host_file};
int i;
for (i = 0; i < num_disks; i++)
{
if (grub_strlen (images[i]) + 7 > sizeof (host_file))
grub_util_error ("pathname %s too long", images[i]);
grub_sprintf (loop_name, "loop%d", i);
grub_sprintf (host_file, "(host)%s", images[i]);
if (execute_command ("loopback", 3, argv))
grub_util_error ("loopback command fails");
}
grub_lvm_fini ();
grub_mdraid_fini ();
grub_raid_fini ();
grub_raid_init ();
grub_mdraid_init ();
grub_lvm_init ();
switch (cmd)
{
case CMD_LS:
execute_command ("ls", n, args);
break;
case CMD_CP:
cmd_cp (args[0], args[1]);
break;
case CMD_CMP:
cmd_cmp (args[0], args[1]);
break;
case CMD_HEX:
cmd_hex (args[0]);
break;
case CMD_CRC:
cmd_crc (args[0]);
break;
case CMD_BLOCKLIST:
execute_command ("blocklist", n, args);
grub_printf ("\n");
}
argv[0] = "-d";
for (i = 0; i < num_disks; i++)
{
grub_sprintf (loop_name, "loop%d", i);
execute_command ("loopback", 2, argv);
}
}
static struct option options[] = {
{"root", required_argument, 0, 'r'},
{"skip", required_argument, 0, 's'},
{"length", required_argument, 0, 'n'},
{"diskcount", required_argument, 0, 'c'},
{"debug", required_argument, 0, 'd'},
{"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 `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTION]... IMAGE_PATH COMMANDS\n\
\n\
Debug tool for filesystem driver.\n\
\nCommands:\n\
ls PATH list files in PATH\n\
cp FILE LOCAL copy FILE to local file LOCAL\n\
cmp FILE LOCAL compare FILE with local file LOCAL\n\
hex FILE Hex dump FILE\n\
crc FILE Get crc32 checksum of FILE\n\
blocklist FILE display blocklist of FILE\n\
\nOptions:\n\
-r, --root=DEVICE_NAME set root device\n\
-s, --skip=N skip N bytes from output file\n\
-n, --length=N handle N bytes in output file\n\
-c, --diskcount=N N input files\n\
-d, --debug=S Set debug environment variable\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", program_name, PACKAGE_BUGREPORT);
exit (status);
}
int
main (int argc, char *argv[])
{
char *debug_str = NULL, *root = NULL, *default_root, *alloc_root;
int i, cmd, num_opts, image_index, num_disks = 1;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Find the first non option entry. */
for (num_opts = 1; num_opts < argc; num_opts++)
if (argv[num_opts][0] == '-')
{
if ((argv[num_opts][2] == 0) && (num_opts < argc - 1) &&
((argv[num_opts][1] == 'r') ||
(argv[num_opts][1] == 's') ||
(argv[num_opts][1] == 'n') ||
(argv[num_opts][1] == 'c') ||
(argv[num_opts][1] == 'd')))
num_opts++;
}
else
break;
/* Check for options. */
while (1)
{
int c = getopt_long (num_opts, argv, "r:s:n:c:d:hVv", options, 0);
char *p;
if (c == -1)
break;
else
switch (c)
{
case 'r':
root = optarg;
break;
case 's':
skip = grub_strtoul (optarg, &p, 0);
if (*p == 's')
skip <<= GRUB_DISK_SECTOR_BITS;
break;
case 'n':
leng = grub_strtoul (optarg, &p, 0);
if (*p == 's')
leng <<= GRUB_DISK_SECTOR_BITS;
break;
case 'c':
num_disks = grub_strtoul (optarg, NULL, 0);
if (num_disks < 1)
{
fprintf (stderr, "Invalid disk count.\n");
usage (1);
}
break;
case 'd':
debug_str = optarg;
break;
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
/* Obtain PATH. */
if (optind + num_disks - 1 >= argc)
{
fprintf (stderr, "Not enough pathname.\n");
usage (1);
}
image_index = optind;
for (i = 0; i < num_disks; i++, optind++)
if (argv[optind][0] != '/')
{
fprintf (stderr, "Must use absolute path.\n");
usage (1);
}
cmd = 0;
if (optind < argc)
{
int nparm = 0;
if (!grub_strcmp (argv[optind], "ls"))
{
cmd = CMD_LS;
}
else if (!grub_strcmp (argv[optind], "cp"))
{
cmd = CMD_CP;
nparm = 2;
}
else if (!grub_strcmp (argv[optind], "cmp"))
{
cmd = CMD_CMP;
nparm = 2;
}
else if (!grub_strcmp (argv[optind], "hex"))
{
cmd = CMD_HEX;
nparm = 1;
}
else if (!grub_strcmp (argv[optind], "crc"))
{
cmd = CMD_CRC;
nparm = 1;
}
else if (!grub_strcmp (argv[optind], "blocklist"))
{
cmd = CMD_BLOCKLIST;
nparm = 1;
}
else
{
fprintf (stderr, "Invalid command %s.\n", argv[optind]);
usage (1);
}
if (optind + 1 + nparm > argc)
{
fprintf (stderr, "Invalid parameter for command %s.\n",
argv[optind]);
usage (1);
}
optind++;
}
else
{
fprintf (stderr, "No command is specified.\n");
usage (1);
}
/* Initialize all modules. */
grub_init_all ();
if (debug_str)
grub_env_set ("debug", debug_str);
default_root = (num_disks == 1) ? "loop0" : "md0";
alloc_root = 0;
if (root)
{
if ((*root >= '0') && (*root <= '9'))
{
alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
sprintf (alloc_root, "%s,%s", default_root, root);
root = alloc_root;
}
}
else
root = default_root;
grub_env_set ("root", root);
if (alloc_root)
free (alloc_root);
/* Do it. */
fstest (argv + image_index, num_disks, cmd, argc - optind, argv + optind);
/* Free resources. */
grub_fini_all ();
return 0;
}

View file

@ -1,7 +1,7 @@
#! /bin/sh
# Install GRUB on your drive.
# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
# 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
@ -29,12 +29,18 @@ PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
target_cpu=@target_cpu@
platform=@platform@
host_os=@host_os@
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}`
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
else
grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
fi
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
rootdir=
grub_prefix=`echo /boot/grub | sed ${transform}`
modules=
@ -45,8 +51,13 @@ force_lba=
recheck=no
debug=no
# for make_system_path_relative_to_its_root()
. ${libdir}/grub/update-grub_lib
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
disk_module=biosdisk
elif [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
disk_module=
else
disk_module=ata
fi
# Usage: usage
# Print the usage.
@ -66,12 +77,22 @@ Install GRUB on your drive.
--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
--force install even if problems are detected
EOF
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
cat <<EOF
--disk-module=MODULE disk module to use
EOF
fi
cat <<EOF
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.
grub-install copies GRUB images into /boot/grub (or /grub on NetBSD and
OpenBSD), and uses grub-setup to install grub into the boot sector.
If the --root-directory option is used, then grub-install will copy
images into the operating system installation rooted at that directory.
Report bugs to <bug-grub@gnu.org>.
EOF
@ -102,9 +123,15 @@ for option in "$@"; do
no_floppy="--no-floppy" ;;
--recheck)
recheck=yes ;;
--disk-module=*)
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
disk_module=`echo "$option" | sed 's/--disk-module=//'`
fi ;;
# This is an undocumented feature...
--debug)
debug=yes ;;
-f | --force)
setup_force="--force" ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
@ -120,6 +147,9 @@ for option in "$@"; do
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
@ -127,8 +157,10 @@ if test "x$install_device" = x; then
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.
@ -148,13 +180,17 @@ esac
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
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
set $grub_setup dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
fi
set $grub_mkimage dummy
@ -201,17 +237,39 @@ if test -n "$tmp"; then
fi
# Copy the GRUB images to the GRUB directory.
for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img; do
for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do
if test -f $file && [ "`basename $file`" != menu.lst ]; then
rm -f $file || exit 1
fi
done
for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ${pkglibdir}/*.img; do
for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
cp -f $file ${grubdir} || exit 1
done
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
for file in ${pkglibdir}/*.img ${pkglibdir}/efiemu??.o; do
if test -f $file; then
cp -f $file ${grubdir} || exit 1
fi
done
fi
# Copy gettext files
mkdir -p ${grubdir}/locale/
for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do
if test -f "$file"; then
cp -f "$file" ${grubdir}/locale/
fi
done
# Write device to a variable so we don't have to traverse /dev every time.
grub_device=`$grub_probe --target=device ${grubdir}`
if ! test -f ${grubdir}/grubenv; then
$grub_editenv ${grubdir}/grubenv create
fi
# Create the core image. First, auto-detect the filesystem module.
fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
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
@ -221,28 +279,71 @@ 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-map=${device_map} ${grubdir} 2> /dev/null`
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-map=${device_map} ${grubdir}`
devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}`
# _chain is often useful
modules="$modules $fs_module $partmap_module biosdisk $devabstraction_module _chain"
# The order in this list is critical. Be careful when modifying it.
modules="$modules $disk_module"
modules="$modules $fs_module $partmap_module $devabstraction_module"
$grub_mkimage --output=${grubdir}/core.img --prefix=`make_system_path_relative_to_its_root ${grubdir}` $modules || exit 1
relative_grubdir=`make_system_path_relative_to_its_root ${grubdir}` || exit 1
if [ "x${relative_grubdir}" = "x" ] ; then
relative_grubdir=/
fi
# Now perform the installation.
$grub_setup --directory=${grubdir} --device-map=${device_map} \
${install_device} || exit 1
prefix_drive=
config_opt=
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]*[a-z]*//g`"
grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*[a-z]*//g`"
if [ "$disk_module" = ata ] ; then
# generic method (used on coreboot and ata mod)
uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`"
if [ "x${uuid}" = "x" ] ; then
echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
exit 1
fi
echo "search.fs_uuid ${uuid} root " > ${grubdir}/load.cfg
echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg
config_opt="-c ${grubdir}/load.cfg "
modules="$modules search_fs_uuid"
elif [ "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
echo "search.fs_uuid ${uuid} root " > ${grubdir}/load.cfg
echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg
config_opt="-c ${grubdir}/load.cfg "
modules="$modules search_fs_uuid"
fi
else
prefix_drive=`$grub_probe --target=drive --device ${grub_device}`
fi
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
$grub_mkimage ${config_opt} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
# Now perform the installation.
$grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \
${install_device} || exit 1
else
$grub_mkimage ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
fi
# 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

116
util/grub-macho2img.c Normal file
View file

@ -0,0 +1,116 @@
/* macho2img.c - tool to convert Mach-O to raw imagw. */
/*
* 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/types.h>
#include <grub/macho.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* XXX: this file assumes particular Mach-O layout and does no checks. */
/* However as build system ensures correct usage of this tool this
shouldn't be a problem. */
int
main (int argc, char **argv)
{
FILE *in, *out;
int do_bss = 0;
char *buf;
int bufsize;
struct grub_macho_header32 *head;
struct grub_macho_segment32 *curcmd;
unsigned i;
unsigned bssstart = 0;
unsigned bssend = 0;
if (argc && strcmp (argv[1], "--bss") == 0)
do_bss = 1;
if (argc < 2 + do_bss)
{
printf ("Usage: %s [--bss] filename.exec filename.img\n"
"Convert Mach-O into raw image\n", argv[0]);
return 0;
}
in = fopen (argv[1 + do_bss], "rb");
if (! in)
{
printf ("Couldn't open %s\n", argv[1 + do_bss]);
return 1;
}
out = fopen (argv[2 + do_bss], "wb");
if (! out)
{
fclose (in);
printf ("Couldn't open %s\n", argv[2 + do_bss]);
return 2;
}
fseek (in, 0, SEEK_END);
bufsize = ftell (in);
fseek (in, 0, SEEK_SET);
buf = malloc (bufsize);
if (! buf)
{
fclose (in);
fclose (out);
printf ("Couldn't allocate buffer\n");
return 3;
}
fread (buf, 1, bufsize, in);
head = (struct grub_macho_header32 *) buf;
if (grub_le_to_cpu32 (head->magic) != GRUB_MACHO_MAGIC32)
{
fclose (in);
fclose (out);
free (buf);
printf ("Invalid Mach-O fle\n");
return 4;
}
curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head));
for (i = 0; i < grub_le_to_cpu32 (head->ncmds); i++,
curcmd = (struct grub_macho_segment32 *)
(((char *) curcmd) + curcmd->cmdsize))
{
if (curcmd->cmd != GRUB_MACHO_CMD_SEGMENT32)
continue;
fwrite (buf + grub_le_to_cpu32 (curcmd->fileoff), 1,
grub_le_to_cpu32 (curcmd->filesize), out);
if (grub_le_to_cpu32 (curcmd->vmsize)
> grub_le_to_cpu32 (curcmd->filesize))
{
bssstart = grub_le_to_cpu32 (curcmd->vmaddr)
+ grub_le_to_cpu32 (curcmd->filesize) ;
bssend = grub_le_to_cpu32 (curcmd->vmaddr)
+ grub_le_to_cpu32 (curcmd->vmsize) ;
}
}
if (do_bss)
{
grub_uint32_t tmp;
fseek (out, 0x5c, SEEK_SET);
tmp = grub_cpu_to_le32 (bssstart);
fwrite (&tmp, 4, 1, out);
tmp = grub_cpu_to_le32 (bssend);
fwrite (&tmp, 4, 1, out);
}
fclose (in);
fclose (out);
printf("macho2img complete\n");
return 0;
}

265
util/grub-mkconfig.in Normal file
View file

@ -0,0 +1,265 @@
#! /bin/sh -e
# Generate grub.cfg by inspecting /boot contents.
# Copyright (C) 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/>.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
sbindir=@sbindir@
libdir=@libdir@
sysconfdir=@sysconfdir@
package_version=@PACKAGE_VERSION@
datarootdir=@datarootdir@
datadir=@datadir@
pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`
grub_prefix=`echo /boot/grub | sed ${transform}`
grub_cfg=""
grub_mkconfig_dir=${sysconfdir}/grub.d
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
# Usage: usage
# Print the usage.
usage () {
cat <<EOF
Usage: $0 [OPTION]
Generate a grub config file
-o, --output=FILE output generated config to FILE [default=stdout]
-h, --help print this message and exit
-v, --version print the version information and exit
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 "$0 (GNU GRUB ${package_version})"
exit 0 ;;
-o)
shift
grub_cfg=$1
;;
--output=*)
grub_cfg=`echo "$option" | sed 's/--output=//'`
;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
exit 1
;;
esac
done
. ${libdir}/grub/grub-mkconfig_lib
if [ "x$EUID" = "x" ] ; then
EUID=`id -u`
fi
if [ "$EUID" != 0 ] ; then
root=f
case "`uname 2>/dev/null`" in
CYGWIN*)
# Cygwin: Assume root if member of admin group
for g in `id -G 2>/dev/null` ; do
case $g in
0|544) root=t ;;
esac
done ;;
esac
if [ $root != t ] ; then
echo "$0: You must run this as root" >&2
exit 1
fi
fi
set $grub_mkdevicemap dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
set $grub_probe dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
mkdir -p ${grub_prefix}
if test -e ${grub_prefix}/device.map ; then : ; else
${grub_mkdevicemap}
fi
# Device containing our userland. Typically used for root= parameter.
GRUB_DEVICE="`${grub_probe} --target=device /`"
GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
# Device containing our /boot partition. Usually the same as GRUB_DEVICE.
GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
# Filesystem for the device containing our userland. Used for stuff like
# choosing Hurd filesystem module.
GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`"
if test -f ${sysconfdir}/default/grub ; then
. ${sysconfdir}/default/grub
fi
# XXX: should this be deprecated at some point?
if [ "x${GRUB_TERMINAL}" != "x" ] ; then
GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
fi
case x${GRUB_TERMINAL_OUTPUT} in
x | xgfxterm)
# If this platform supports gfxterm, try to use it.
if test -e ${grub_prefix}/gfxterm.mod ; then
# FIXME: this should do something smarter than just loading first
# video backend.
GRUB_VIDEO_BACKEND=$(head -n 1 ${grub_prefix}/video.lst || true)
if [ -n "${GRUB_VIDEO_BACKEND}" ] ; then
GRUB_TERMINAL_OUTPUT=gfxterm
elif [ "${GRUB_TERMINAL_OUTPUT}" = "gfxterm" ] ; then
echo "No suitable backend could be found for gfxterm." >&2 ; exit 1
fi
fi
;;
xconsole | xserial | xofconsole) ;;
*) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
esac
# check for terminals that require fonts
case ${GRUB_TERMINAL_OUTPUT} in
gfxterm)
if [ -n "$GRUB_FONT" ] ; then
if is_path_readable_by_grub ${GRUB_FONT} > /dev/null ; then
GRUB_FONT_PATH=${GRUB_FONT}
else
echo "No such font or not readable by grub: ${GRUB_FONT}" >&2
exit 1
fi
else
for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do
for basename in unicode unifont ascii; do
path="${dir}/${basename}.pf2"
if is_path_readable_by_grub ${path} > /dev/null ; then
GRUB_FONT_PATH=${path}
else
continue
fi
if [ "${basename}" = "ascii" ] ; then
# make sure all our children behave in conformance with ascii..
export LANG=C
fi
break 2
done
done
fi
if [ -z "${GRUB_FONT_PATH}" ] ; then
# fallback to the native terminal for this platform
unset GRUB_TERMINAL_OUTPUT
fi
;;
*)
# make sure all our children behave in conformance with ascii..
export LANG=C
esac
# These are defined in this script, export them here so that user can
# override them.
export GRUB_DEVICE \
GRUB_DEVICE_UUID \
GRUB_DEVICE_BOOT \
GRUB_DEVICE_BOOT_UUID \
GRUB_FS \
GRUB_FONT_PATH \
GRUB_PRELOAD_MODULES \
GRUB_VIDEO_BACKEND
# These are optional, user-defined variables.
export GRUB_DEFAULT \
GRUB_HIDDEN_TIMEOUT \
GRUB_HIDDEN_TIMEOUT_QUIET \
GRUB_TIMEOUT \
GRUB_DISTRIBUTOR \
GRUB_CMDLINE_LINUX \
GRUB_CMDLINE_LINUX_DEFAULT \
GRUB_TERMINAL_INPUT \
GRUB_TERMINAL_OUTPUT \
GRUB_SERIAL_COMMAND \
GRUB_DISABLE_LINUX_UUID \
GRUB_DISABLE_LINUX_RECOVERY \
GRUB_GFXMODE \
GRUB_DISABLE_OS_PROBER
if test "x${grub_cfg}" != "x"; then
rm -f ${grub_cfg}.new
exec > ${grub_cfg}.new
# Allow this to fail, since /boot/grub/ might need to be fatfs to support some
# firmware implementations (e.g. OFW or EFI).
chmod 400 ${grub_cfg}.new || grub_warn "Could not make ${grub_cfg}.new readable by only root.\
This means that if the generated config contains a password it is readable by everyone"
fi
echo "Generating grub.cfg ..." >&2
cat << EOF
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by $0 using templates
# from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub
#
EOF
for i in ${grub_mkconfig_dir}/* ; do
case "$i" in
# emacsen backup files. FIXME: support other editors
*~) ;;
*)
if grub_file_is_not_garbage "$i" && test -x "$i" ; then
echo
echo "### BEGIN $i ###"
"$i"
echo "### END $i ###"
fi
;;
esac
done
if test "x${grub_cfg}" != "x" ; then
# none of the children aborted with error, install the new grub.cfg
mv -f ${grub_cfg}.new ${grub_cfg}
fi
echo "done" >&2

190
util/grub-mkconfig_lib.in Normal file
View file

@ -0,0 +1,190 @@
# Helper library for grub-mkconfig
# Copyright (C) 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/>.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
datarootdir=@datarootdir@
datadir=@datadir@
bindir=@bindir@
sbindir=@sbindir@
pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`
if test "x$grub_probe" = x; then
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}`
fi
grub_warn ()
{
echo "Warning: $@" >&2
}
make_system_path_relative_to_its_root ()
{
path="`${grub_mkrelpath} $1`"
case "`uname 2>/dev/null`" in
CYGWIN*)
# Cygwin: Check if regular or emulated mount.
if [ -z "$dir" ] || [ "`stat -c %D "$dir/.."`" != 620000 ] ; then
# Reached some mount point not below /cygdrive.
# GRUB does not know Cygwin's emulated mounts,
# convert to Win32 path and remove drive letter.
path=`cygpath -m "$path" | sed -n 's,^[A-Za-z]:,,p'`
test ! -z "$path" || return 1
fi ;;
esac
echo "$path"
}
is_path_readable_by_grub ()
{
path=$1
# abort if path doesn't exist
if test -e $path ; then : ;else
return 1
fi
# abort if file is in a filesystem we can't read
if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else
return 1
fi
return 0
}
convert_system_path_to_grub_path ()
{
path=$1
grub_warn "convert_system_path_to_grub_path() is deprecated. Use prepare_grub_to_access_device() instead."
# abort if GRUB can't access the path
if is_path_readable_by_grub ${path} ; then : ; else
return 1
fi
if drive=`${grub_probe} -t drive $path` ; then : ; else
return 1
fi
if relative_path=`make_system_path_relative_to_its_root $path` ; then : ; else
return 1
fi
echo ${drive}${relative_path}
}
save_default_entry ()
{
if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then
cat << EOF
savedefault
EOF
fi
}
prepare_grub_to_access_device ()
{
device=$1
# Abstraction modules aren't auto-loaded.
abstraction="`${grub_probe} --device ${device} --target=abstraction`"
for module in ${abstraction} ; do
echo "insmod ${module}"
done
fs="`${grub_probe} --device ${device} --target=fs`"
for module in ${fs} ; do
echo "insmod ${module}"
done
# If there's a filesystem UUID that GRUB is capable of identifying, use it;
# otherwise set root as per value in device.map.
echo "set root=`${grub_probe} --device ${device} --target=drive`"
if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then
echo "search --no-floppy --fs-uuid --set ${fs_uuid}"
fi
}
grub_file_is_not_garbage ()
{
if test -f "$1" ; then
case "$1" in
*.dpkg-*) return 1 ;; # debian dpkg
esac
else
return 1
fi
return 0
}
version_test_numeric ()
{
local a=$1
local cmp=$2
local b=$3
if [ "$a" = "$b" ] ; then
case $cmp in
ge|eq|le) return 0 ;;
gt|lt) return 1 ;;
esac
fi
if [ "$cmp" = "lt" ] ; then
c=$a
a=$b
b=$c
fi
if (echo $a ; echo $b) | sort -n | head -n 1 | grep -qx $b ; then
return 0
else
return 1
fi
}
version_test_gt ()
{
local a=`echo $1 | sed -e "s/[^-]*-//"`
local b=`echo $2 | sed -e "s/[^-]*-//"`
local cmp=gt
if [ "x$b" = "x" ] ; then
return 0
fi
case $a:$b in
*.old:*.old) ;;
*.old:*) a=`echo -n $a | sed -e s/\.old$//` ; cmp=gt ;;
*:*.old) b=`echo -n $b | sed -e s/\.old$//` ; cmp=ge ;;
esac
version_test_numeric $a $cmp $b
return $?
}
version_find_latest ()
{
local a=""
for i in $@ ; do
if version_test_gt "$i" "$a" ; then
a="$i"
fi
done
echo "$a"
}

View file

@ -1,7 +1,7 @@
/* grub-mkdevicemap.c - make a device map file automatically */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007 Free Software Foundation, Inc.
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 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
@ -30,492 +30,40 @@
#include <limits.h>
#include <grub/util/misc.h>
#include <grub/util/deviceiter.h>
#include <grub/i18n.h>
#define _GNU_SOURCE 1
#include <getopt.h>
#ifdef __linux__
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
# include <linux/unistd.h> /* _llseek */
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
# include <sys/ioctl.h> /* ioctl */
# ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x0301 /* get device geometry */
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
defined. */
struct hd_geometry
{
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
# endif /* ! HDIO_GETGEO */
# ifndef FLOPPY_MAJOR
# define FLOPPY_MAJOR 2 /* the major number for floppy */
# endif /* ! FLOPPY_MAJOR */
# ifndef MAJOR
# define MAJOR(dev) \
({ \
unsigned long long __dev = (dev); \
(unsigned) ((__dev >> 8) & 0xfff) \
| ((unsigned int) (__dev >> 32) & ~0xfff); \
})
# endif /* ! MAJOR */
# ifndef CDROM_GET_CAPABILITY
# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
# endif /* ! CDROM_GET_CAPABILITY */
# ifndef BLKGETSIZE
# define BLKGETSIZE _IO(0x12,96) /* return device size */
# endif /* ! BLKGETSIZE */
#endif /* __linux__ */
/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
# define __FreeBSD_kernel__
#endif
#ifdef __FreeBSD_kernel__
/* Obtain version of kFreeBSD headers */
# include <osreldate.h>
# ifndef __FreeBSD_kernel_version
# define __FreeBSD_kernel_version __FreeBSD_version
# endif
/* Runtime detection of kernel */
# include <sys/utsname.h>
int
get_kfreebsd_version (void)
{
struct utsname uts;
int major;
int minor;
int v[2];
uname (&uts);
sscanf (uts.release, "%d.%d", &major, &minor);
if (major >= 9)
major = 9;
if (major >= 5)
{
v[0] = minor/10; v[1] = minor%10;
}
else
{
v[0] = minor%10; v[1] = minor/10;
}
return major*100000+v[0]*10000+v[1]*1000;
}
#endif /* __FreeBSD_kernel__ */
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/ioctl.h> /* ioctl */
# include <sys/disklabel.h>
# include <sys/cdio.h> /* CDIOCCLRDEBUG */
# if defined(__FreeBSD_kernel__)
# include <sys/param.h>
# if __FreeBSD_kernel_version >= 500040
# include <sys/disk.h>
# endif
# endif /* __FreeBSD_kernel__ */
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
#ifdef HAVE_OPENDISK
# include <util.h>
#endif /* HAVE_OPENDISK */
#ifdef __linux__
/* Check if we have devfs support. */
static int
have_devfs (void)
{
struct stat st;
return stat ("/dev/.devfsd", &st) == 0;
}
#endif /* __linux__ */
/* These three functions are quite different among OSes. */
static void
get_floppy_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
if (have_devfs ())
sprintf (name, "/dev/floppy/%d", unit);
else
sprintf (name, "/dev/fd%d", unit);
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/fd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/fd%d", unit);
else
sprintf (name, "/dev/rfd%d", unit);
#elif defined(__NetBSD__)
/* NetBSD */
/* opendisk() doesn't work for floppies. */
sprintf (name, "/dev/rfd%da", unit);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rfd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
sprintf (name, "/dev/fd%d", unit);
#else
# warning "BIOS floppy drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
static void
get_ide_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
sprintf (name, "/dev/hd%c", unit + 'a');
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/hd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/ad%d", unit);
else
sprintf (name, "/dev/rwd%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
/* NetBSD */
char shortname[16];
int fd;
sprintf (shortname, "wd%d", unit);
fd = opendisk (shortname, O_RDONLY, name,
16, /* length of NAME */
0 /* char device */
);
close (fd);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rwd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
/* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
contain SCSI disks. */
sprintf (name, "/dev/hd%d", unit);
#else
# warning "BIOS IDE drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
static void
get_scsi_disk_name (char *name, int unit)
{
#if defined(__linux__)
/* GNU/Linux */
sprintf (name, "/dev/sd%c", unit + 'a');
#elif defined(__GNU__)
/* GNU/Hurd */
sprintf (name, "/dev/sd%d", unit);
#elif defined(__FreeBSD_kernel__)
/* kFreeBSD */
if (get_kfreebsd_version () >= 400000)
sprintf (name, "/dev/da%d", unit);
else
sprintf (name, "/dev/rda%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
/* NetBSD */
char shortname[16];
int fd;
sprintf (shortname, "sd%d", unit);
fd = opendisk (shortname, O_RDONLY, name,
16, /* length of NAME */
0 /* char device */
);
close (fd);
#elif defined(__OpenBSD__)
/* OpenBSD */
sprintf (name, "/dev/rsd%dc", unit);
#elif defined(__QNXNTO__)
/* QNX RTP */
/* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
disable the detection of SCSI disks here. */
*name = 0;
#else
# warning "BIOS SCSI drives cannot be guessed in your operating system."
/* Set NAME to a bogus string. */
*name = 0;
#endif
}
#ifdef __linux__
static void
get_dac960_disk_name (char *name, int controller, int drive)
{
sprintf (name, "/dev/rd/c%dd%d", controller, drive);
}
static void
get_ataraid_disk_name (char *name, int unit)
{
sprintf (name, "/dev/ataraid/d%c", unit + '0');
}
static void
get_i2o_disk_name (char *name, char unit)
{
sprintf (name, "/dev/i2o/hd%c", unit);
}
#endif
/* Check if DEVICE can be read. If an error occurs, return zero,
otherwise return non-zero. */
int
check_device (const char *device)
{
char buf[512];
FILE *fp;
/* If DEVICE is empty, just return 1. */
if (*device == 0)
return 1;
fp = fopen (device, "r");
if (! fp)
{
switch (errno)
{
#ifdef ENOMEDIUM
case ENOMEDIUM:
# if 0
/* At the moment, this finds only CDROMs, which can't be
read anyway, so leave it out. Code should be
reactivated if `removable disks' and CDROMs are
supported. */
/* Accept it, it may be inserted. */
return 1;
# endif
break;
#endif /* ENOMEDIUM */
default:
/* Break case and leave. */
break;
}
/* Error opening the device. */
return 0;
}
/* Make sure CD-ROMs don't get assigned a BIOS disk number
before SCSI disks! */
#ifdef __linux__
# ifdef CDROM_GET_CAPABILITY
if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
return 0;
# else /* ! CDROM_GET_CAPABILITY */
/* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
{
struct hd_geometry hdg;
struct stat st;
if (fstat (fileno (fp), &st))
return 0;
/* If it is a block device and isn't a floppy, check if HDIO_GETGEO
succeeds. */
if (S_ISBLK (st.st_mode)
&& MAJOR (st.st_rdev) != FLOPPY_MAJOR
&& ioctl (fileno (fp), HDIO_GETGEO, &hdg))
return 0;
}
# endif /* ! CDROM_GET_CAPABILITY */
#endif /* __linux__ */
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# ifdef CDIOCCLRDEBUG
if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
return 0;
# endif /* CDIOCCLRDEBUG */
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
/* Attempt to read the first sector. */
if (fread (buf, 1, 512, fp) != 512)
{
fclose (fp);
return 0;
}
fclose (fp);
return 1;
}
#include "progname.h"
static void
make_device_map (const char *device_map, int floppy_disks)
{
FILE *fp;
int num_hd = 0;
int i;
int num_fd = 0;
FILE *fp;
auto int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy);
int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy)
{
grub_util_emit_devicemap_entry (fp, (char *) name,
is_floppy, &num_fd, &num_hd);
return 0;
}
if (strcmp (device_map, "-") == 0)
fp = stdout;
else
fp = fopen (device_map, "w");
if (! fp)
grub_util_error ("cannot open %s", device_map);
/* Floppies. */
for (i = 0; i < floppy_disks; i++)
{
char name[16];
struct stat st;
get_floppy_disk_name (name, i);
if (stat (name, &st) < 0)
break;
/* In floppies, write the map, whether check_device succeeds
or not, because the user just may not insert floppies. */
if (fp)
fprintf (fp, "(fd%d)\t%s\n", i, name);
}
#ifdef __linux__
if (have_devfs ())
{
while (1)
{
char discn[32];
char name[PATH_MAX];
struct stat st;
grub_util_iterate_devices (process_device, floppy_disks);
/* Linux creates symlinks "/dev/discs/discN" for convenience.
The way to number disks is the same as GRUB's. */
sprintf (discn, "/dev/discs/disc%d", num_hd);
if (stat (discn, &st) < 0)
break;
if (realpath (discn, name))
{
char *p;
strcat (name, "/disc");
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
}
num_hd++;
}
goto finish;
}
#endif /* __linux__ */
/* IDE disks. */
for (i = 0; i < 20; i++)
{
char name[16];
get_ide_disk_name (name, i);
if (check_device (name))
{
char *p;
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
num_hd++;
}
}
#ifdef __linux__
/* ATARAID disks. */
for (i = 0; i < 8; i++)
{
char name[20];
get_ataraid_disk_name (name, i);
if (check_device (name))
{
char *p;
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
num_hd++;
}
}
#endif /* __linux__ */
/* The rest is SCSI disks. */
for (i = 0; i < 16; i++)
{
char name[16];
get_scsi_disk_name (name, i);
if (check_device (name))
{
char *p;
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
num_hd++;
}
}
#ifdef __linux__
/* This is for DAC960 - we have
/dev/rd/c<controller>d<logical drive>p<partition>.
DAC960 driver currently supports up to 8 controllers, 32 logical
drives, and 7 partitions. */
{
int controller, drive;
for (controller = 0; controller < 8; controller++)
{
for (drive = 0; drive < 15; drive++)
{
char name[24];
get_dac960_disk_name (name, controller, drive);
if (check_device (name))
{
char *p;
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
num_hd++;
}
}
}
}
/* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
{
char unit;
for (unit = 'a'; unit < 'f'; unit++)
{
char name[24];
get_i2o_disk_name (name, unit);
if (check_device (name))
{
char *p;
p = grub_util_get_disk_name (num_hd, name);
fprintf (fp, "(%s)\t%s\n", p, name);
free (p);
num_hd++;
}
}
}
#endif /* __linux__ */
finish:
if (fp != stdout)
fclose (fp);
}
@ -536,10 +84,10 @@ usage (int status)
{
if (status)
fprintf (stderr,
"Try ``grub-mkdevicemap --help'' for more information.\n");
"Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: grub-mkdevicemap [OPTION]...\n\
Usage: %s [OPTION]...\n\
\n\
Generate a device map file automatically.\n\
\n\
@ -551,9 +99,9 @@ Generate a device map file automatically.\n\
-v, --verbose print verbose messages\n\
\n\
Report bugs to <%s>.\n\
",
", program_name,
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
exit (status);
}
@ -562,14 +110,16 @@ main (int argc, char *argv[])
{
char *dev_map = 0;
int floppy_disks = 1;
progname = "grub-mkdevicemap";
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
if (c == -1)
break;
else
@ -589,13 +139,13 @@ main (int argc, char *argv[])
case 's':
floppy_disks = 2;
break;
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
@ -611,6 +161,6 @@ main (int argc, char *argv[])
make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
free (dev_map);
return 0;
}

644
util/grub-mkfont.c Normal file
View file

@ -0,0 +1,644 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009,2010 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/i18n.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/ftsynth.h>
#include "progname.h"
#define GRUB_FONT_DEFAULT_SIZE 16
#define GRUB_FONT_RANGE_BLOCK 1024
struct grub_glyph_info
{
struct grub_glyph_info *next;
grub_uint32_t char_code;
int width;
int height;
int x_ofs;
int y_ofs;
int device_width;
int bitmap_size;
grub_uint8_t bitmap[0];
};
#define GRUB_FONT_FLAG_BOLD 1
#define GRUB_FONT_FLAG_NOBITMAP 2
#define GRUB_FONT_FLAG_NOHINTING 4
#define GRUB_FONT_FLAG_FORCEHINT 8
struct grub_font_info
{
char* name;
int style;
int desc;
int asce;
int size;
int max_width;
int max_height;
int min_y;
int max_y;
int flags;
int num_range;
grub_uint32_t *ranges;
struct grub_glyph_info *glyph;
};
static struct option options[] =
{
{"output", required_argument, 0, 'o'},
{"name", required_argument, 0, 'n'},
{"index", required_argument, 0, 'i'},
{"range", required_argument, 0, 'r'},
{"size", required_argument, 0, 's'},
{"desc", required_argument, 0, 'd'},
{"asce", required_argument, 0, 'c'},
{"bold", no_argument, 0, 'b'},
{"no-bitmap", no_argument, 0, 0x100},
{"no-hinting", no_argument, 0, 0x101},
{"force-autohint", no_argument, 0, 'a'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
int font_verbosity;
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTIONS] FONT_FILES\n\
\nOptions:\n\
-o, --output=FILE_NAME set output file name\n\
-i, --index=N set face index\n\
-r, --range=A-B[,C-D] set font range\n\
-n, --name=S set font family name\n\
-s, --size=N set font size\n\
-d, --desc=N set font descent\n\
-c, --asce=N set font ascent\n\
-b, --bold convert to bold font\n\
-a, --force-autohint force autohint\n\
--no-hinting disable hinting\n\
--no-bitmap ignore bitmap strikes when loading\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", program_name, PACKAGE_BUGREPORT);
exit (status);
}
void
add_pixel (grub_uint8_t **data, int *mask, int not_blank)
{
if (*mask == 0)
{
(*data)++;
**data = 0;
*mask = 128;
}
if (not_blank)
**data |= *mask;
*mask >>= 1;
}
void
add_char (struct grub_font_info *font_info, FT_Face face,
grub_uint32_t char_code)
{
struct grub_glyph_info *glyph_info, **p_glyph;
int width, height;
grub_uint8_t *data;
int mask, i, j, bitmap_size;
FT_GlyphSlot glyph;
int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
flag |= FT_LOAD_NO_BITMAP;
if (font_info->flags & GRUB_FONT_FLAG_NOHINTING)
flag |= FT_LOAD_NO_HINTING;
else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
flag |= FT_LOAD_FORCE_AUTOHINT;
if (FT_Load_Char (face, char_code, flag))
return;
glyph = face->glyph;
if (font_info->flags & GRUB_FONT_FLAG_BOLD)
FT_GlyphSlot_Embolden (glyph);
p_glyph = &font_info->glyph;
while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
{
p_glyph = &(*p_glyph)->next;
}
/* Ignore duplicated glyph. */
if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
return;
width = glyph->bitmap.width;
height = glyph->bitmap.rows;
bitmap_size = ((width * height + 7) / 8);
glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
glyph_info->bitmap_size = bitmap_size;
glyph_info->next = *p_glyph;
*p_glyph = glyph_info;
glyph_info->char_code = char_code;
glyph_info->width = width;
glyph_info->height = height;
glyph_info->x_ofs = glyph->bitmap_left;
glyph_info->y_ofs = glyph->bitmap_top - height;
glyph_info->device_width = glyph->metrics.horiAdvance / 64;
if (width > font_info->max_width)
font_info->max_width = width;
if (height > font_info->max_height)
font_info->max_height = height;
if (glyph_info->y_ofs < font_info->min_y && glyph_info->y_ofs > -font_info->size)
font_info->min_y = glyph_info->y_ofs;
if (glyph_info->y_ofs + height > font_info->max_y)
font_info->max_y = glyph_info->y_ofs + height;
mask = 0;
data = &glyph_info->bitmap[0] - 1;
for (j = 0; j < height; j++)
for (i = 0; i < width; i++)
add_pixel (&data, &mask,
glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
(1 << (7 - (i & 7))));
}
void
add_font (struct grub_font_info *font_info, FT_Face face)
{
if (font_info->num_range)
{
int i;
grub_uint32_t j;
for (i = 0; i < font_info->num_range; i++)
for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
j++)
add_char (font_info, face, j);
}
else
{
grub_uint32_t char_code, glyph_index;
for (char_code = FT_Get_First_Char (face, &glyph_index);
glyph_index;
char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
add_char (font_info, face, char_code);
}
}
void
write_string_section (char *name, char *str, int* offset, FILE* file)
{
grub_uint32_t leng, leng_be32;
leng = strlen (str) + 1;
leng_be32 = grub_cpu_to_be32 (leng);
grub_util_write_image (name, 4, file);
grub_util_write_image ((char *) &leng_be32, 4, file);
grub_util_write_image (str, leng, file);
*offset += 8 + leng;
}
void
write_be16_section (char *name, grub_uint16_t data, int* offset, FILE* file)
{
grub_uint32_t leng;
leng = grub_cpu_to_be32 (2);
data = grub_cpu_to_be16 (data);
grub_util_write_image (name, 4, file);
grub_util_write_image ((char *) &leng, 4, file);
grub_util_write_image ((char *) &data, 2, file);
*offset += 10;
}
void
print_glyphs (struct grub_font_info *font_info)
{
int num;
struct grub_glyph_info *glyph;
char line[512];
for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
{
int x, y, xmax, xmin, ymax, ymin;
grub_uint8_t *bitmap, mask;
printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code);
printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs,
glyph->device_width);
xmax = glyph->x_ofs + glyph->width;
if (xmax < glyph->device_width)
xmax = glyph->device_width;
xmin = glyph->x_ofs;
if (xmin > 0)
xmin = 0;
ymax = glyph->y_ofs + glyph->height;
if (ymax < font_info->asce)
ymax = font_info->asce;
ymin = glyph->y_ofs;
if (ymin > - font_info->desc)
ymin = - font_info->desc;
bitmap = glyph->bitmap;
mask = 0x80;
for (y = ymax - 1; y >= ymin; y--)
{
int line_pos;
line_pos = 0;
for (x = xmin; x < xmax; x++)
{
if ((x >= glyph->x_ofs) &&
(x < glyph->x_ofs + glyph->width) &&
(y >= glyph->y_ofs) &&
(y < glyph->y_ofs + glyph->height))
{
line[line_pos++] = (*bitmap & mask) ? '#' : '_';
mask >>= 1;
if (mask == 0)
{
mask = 0x80;
bitmap++;
}
}
else if ((x >= 0) &&
(x < glyph->device_width) &&
(y >= - font_info->desc) &&
(y < font_info->asce))
{
line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.';
}
else
line[line_pos++] = '*';
}
line[line_pos] = 0;
printf ("%s\n", line);
}
}
}
void
write_font (struct grub_font_info *font_info, char *output_file)
{
FILE *file;
grub_uint32_t leng, data;
char style_name[20], *font_name;
struct grub_glyph_info *cur, *pre;
int num, offset;
file = fopen (output_file, "wb");
if (! file)
grub_util_error ("can\'t write to file %s.", output_file);
offset = 0;
leng = grub_cpu_to_be32 (4);
grub_util_write_image ("FILE", 4, file);
grub_util_write_image ((char *) &leng, 4, file);
grub_util_write_image ("PFF2", 4, file);
offset += 12;
if (! font_info->name)
font_info->name = "Unknown";
if (font_info->flags & GRUB_FONT_FLAG_BOLD)
font_info->style |= FT_STYLE_FLAG_BOLD;
style_name[0] = 0;
if (font_info->style & FT_STYLE_FLAG_BOLD)
strcpy (style_name, " Bold");
if (font_info->style & FT_STYLE_FLAG_ITALIC)
strcat (style_name, " Italic");
if (! style_name[0])
strcpy (style_name, " Regular");
font_name = xasprintf ("%s %s %d", font_info->name, &style_name[1],
font_info->size);
write_string_section ("NAME", font_name, &offset, file);
write_string_section ("FAMI", font_info->name, &offset, file);
write_string_section ("WEIG",
(font_info->style & FT_STYLE_FLAG_BOLD) ?
"bold" : "normal",
&offset, file);
write_string_section ("SLAN",
(font_info->style & FT_STYLE_FLAG_ITALIC) ?
"italic" : "normal",
&offset, file);
write_be16_section ("PTSZ", font_info->size, &offset, file);
write_be16_section ("MAXW", font_info->max_width, &offset, file);
write_be16_section ("MAXH", font_info->max_height, &offset, file);
if (! font_info->desc)
{
if (font_info->min_y >= 0)
font_info->desc = 1;
else
font_info->desc = - font_info->min_y;
}
if (! font_info->asce)
{
if (font_info->max_y <= 0)
font_info->asce = 1;
else
font_info->asce = font_info->max_y;
}
write_be16_section ("ASCE", font_info->asce, &offset, file);
write_be16_section ("DESC", font_info->desc, &offset, file);
if (font_verbosity > 0)
{
printf ("Font name: %s\n", font_name);
printf ("Max width: %d\n", font_info->max_width);
printf ("Max height: %d\n", font_info->max_height);
printf ("Font ascent: %d\n", font_info->asce);
printf ("Font descent: %d\n", font_info->desc);
}
num = 0;
pre = 0;
cur = font_info->glyph;
while (cur)
{
struct grub_glyph_info *nxt;
nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
num++;
}
font_info->glyph = pre;
if (font_verbosity > 0)
printf ("Number of glyph: %d\n", num);
leng = grub_cpu_to_be32 (num * 9);
grub_util_write_image ("CHIX", 4, file);
grub_util_write_image ((char *) &leng, 4, file);
offset += 8 + num * 9 + 8;
for (cur = font_info->glyph; cur; cur = cur->next)
{
data = grub_cpu_to_be32 (cur->char_code);
grub_util_write_image ((char *) &data, 4, file);
data = 0;
grub_util_write_image ((char *) &data, 1, file);
data = grub_cpu_to_be32 (offset);
grub_util_write_image ((char *) &data, 4, file);
offset += 10 + cur->bitmap_size;
}
leng = 0xffffffff;
grub_util_write_image ("DATA", 4, file);
grub_util_write_image ((char *) &leng, 4, file);
for (cur = font_info->glyph; cur; cur = cur->next)
{
data = grub_cpu_to_be16 (cur->width);
grub_util_write_image ((char *) &data, 2, file);
data = grub_cpu_to_be16 (cur->height);
grub_util_write_image ((char *) &data, 2, file);
data = grub_cpu_to_be16 (cur->x_ofs);
grub_util_write_image ((char *) &data, 2, file);
data = grub_cpu_to_be16 (cur->y_ofs);
grub_util_write_image ((char *) &data, 2, file);
data = grub_cpu_to_be16 (cur->device_width);
grub_util_write_image ((char *) &data, 2, file);
grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file);
}
if (font_verbosity > 1)
print_glyphs (font_info);
fclose (file);
}
int
main (int argc, char *argv[])
{
struct grub_font_info font_info;
FT_Library ft_lib;
int font_index = 0;
int font_size = 0;
char *output_file = NULL;
memset (&font_info, 0, sizeof (font_info));
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'b':
font_info.flags |= GRUB_FONT_FLAG_BOLD;
break;
case 0x100:
font_info.flags |= GRUB_FONT_FLAG_NOBITMAP;
break;
case 0x101:
font_info.flags |= GRUB_FONT_FLAG_NOHINTING;
break;
case 'a':
font_info.flags |= GRUB_FONT_FLAG_FORCEHINT;
break;
case 'o':
output_file = optarg;
break;
case 'n':
font_info.name = optarg;
break;
case 'i':
font_index = strtoul (optarg, NULL, 0);
break;
case 's':
font_size = strtoul (optarg, NULL, 0);
break;
case 'r':
{
char *p = optarg;
while (1)
{
grub_uint32_t a, b;
a = strtoul (p, &p, 0);
if (*p != '-')
grub_util_error ("invalid font range");
b = strtoul (p + 1, &p, 0);
if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
font_info.ranges = xrealloc (font_info.ranges,
(font_info.num_range +
GRUB_FONT_RANGE_BLOCK) *
sizeof (int) * 2);
font_info.ranges[font_info.num_range * 2] = a;
font_info.ranges[font_info.num_range * 2 + 1] = b;
font_info.num_range++;
if (*p)
{
if (*p != ',')
grub_util_error ("invalid font range");
else
p++;
}
else
break;
}
break;
}
case 'd':
font_info.desc = strtoul (optarg, NULL, 0);
break;
case 'e':
font_info.asce = strtoul (optarg, NULL, 0);
break;
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
font_verbosity++;
break;
default:
usage (1);
break;
}
}
if (! output_file)
grub_util_error ("no output file is specified");
if (FT_Init_FreeType (&ft_lib))
grub_util_error ("FT_Init_FreeType fails");
for (; optind < argc; optind++)
{
FT_Face ft_face;
int size;
if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face))
{
grub_util_info ("can't open file %s, index %d", argv[optind],
font_index);
continue;
}
if ((! font_info.name) && (ft_face->family_name))
font_info.name = xstrdup (ft_face->family_name);
size = font_size;
if (! size)
{
if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) ||
(! ft_face->num_fixed_sizes))
size = GRUB_FONT_DEFAULT_SIZE;
else
size = ft_face->available_sizes[0].height;
}
font_info.style = ft_face->style_flags;
font_info.size = size;
FT_Set_Pixel_Sizes (ft_face, size, size);
add_font (&font_info, ft_face);
FT_Done_Face (ft_face);
}
FT_Done_FreeType (ft_lib);
write_font (&font_info, output_file);
return 0;
}

341
util/grub-mkpasswd-pbkdf2.c Normal file
View file

@ -0,0 +1,341 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1992-1999,2001,2003,2004,2005,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/types.h>
#include <grub/crypto.h>
#include <grub/util/misc.h>
#include <grub/i18n.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <termios.h>
#include "progname.h"
/* Few functions to make crypto happy. */
void *
grub_memmove (void *dest, const void *src, grub_size_t n)
{
return memmove (dest, src, n);
}
void *
grub_memset (void *s, int c, grub_size_t n)
{
return memset (s, c, n);
}
int
grub_vprintf (const char *fmt, va_list args)
{
return vprintf (fmt, args);
}
int
grub_vsprintf (char *str, const char *fmt, va_list args)
{
return vsprintf (str, fmt, args);
}
void
grub_abort (void)
{
abort ();
}
static struct option options[] =
{
{"iteration_count", required_argument, 0, 'c'},
{"buflen", required_argument, 0, 'l'},
{"saltlen", required_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTIONS]\n\
\nOptions:\n\
-c number, --iteration-count=number Number of PBKDF2 iterations\n\
-l number, --buflen=number Length of generated hash\n\
-s number, --salt=number Length of salt\n\
\n\
Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
exit (status);
}
static void
hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
{
while (n--)
{
if (((*bin & 0xf0) >> 4) < 10)
*hex = ((*bin & 0xf0) >> 4) + '0';
else
*hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
hex++;
if ((*bin & 0xf) < 10)
*hex = (*bin & 0xf) + '0';
else
*hex = (*bin & 0xf) + 'A' - 10;
hex++;
bin++;
}
*hex = 0;
}
int
main (int argc, char *argv[])
{
unsigned int c = 10000, buflen = 64, saltlen = 64;
char *pass1, *pass2;
char *bufhex, *salthex;
gcry_err_code_t gcry_err;
grub_uint8_t *buf, *salt;
ssize_t nr;
FILE *in, *out;
struct termios s, t;
int tty_changed;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0);
if (c == -1)
break;
switch (c)
{
case 'c':
c = strtoul (optarg, NULL, 0);
break;
case 'l':
buflen = strtoul (optarg, NULL, 0);
break;
case 's':
saltlen = strtoul (optarg, NULL, 0);
break;
case 'h':
usage (0);
return 0;
case 'V':
printf ("%s (%s) %s\n", program_name,
PACKAGE_NAME, PACKAGE_VERSION);
return 0;
default:
usage (1);
return 1;
}
}
bufhex = malloc (buflen * 2 + 1);
if (!bufhex)
grub_util_error ("out of memory");
buf = malloc (buflen);
if (!buf)
{
free (bufhex);
grub_util_error ("out of memory");
}
salt = malloc (saltlen);
if (!salt)
{
free (bufhex);
free (buf);
grub_util_error ("out of memory");
}
salthex = malloc (saltlen * 2 + 1);
if (!salthex)
{
free (salt);
free (bufhex);
free (buf);
grub_util_error ("out of memory");
}
/* Disable echoing. Based on glibc. */
in = fopen ("/dev/tty", "w+c");
if (in == NULL)
{
in = stdin;
out = stderr;
}
else
out = in;
if (tcgetattr (fileno (in), &t) == 0)
{
/* Save the old one. */
s = t;
/* Tricky, tricky. */
t.c_lflag &= ~(ECHO|ISIG);
tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
}
else
tty_changed = 0;
printf ("Enter password: ");
pass1 = NULL;
{
grub_size_t n;
nr = getline (&pass1, &n, stdin);
}
if (nr < 0 || !pass1)
{
free (buf);
free (bufhex);
free (salthex);
free (salt);
/* Restore the original setting. */
if (tty_changed)
(void) tcsetattr (fileno (in), TCSAFLUSH, &s);
grub_util_error ("failure to read password");
}
if (nr >= 1 && pass1[nr-1] == '\n')
pass1[nr-1] = 0;
printf ("\nReenter password: ");
pass2 = NULL;
{
grub_size_t n;
nr = getline (&pass2, &n, stdin);
}
/* Restore the original setting. */
if (tty_changed)
(void) tcsetattr (fileno (in), TCSAFLUSH, &s);
printf ("\n");
if (nr < 0 || !pass2)
{
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("failure to read password");
}
if (nr >= 1 && pass2[nr-1] == '\n')
pass2[nr-1] = 0;
if (strcmp (pass1, pass2) != 0)
{
memset (pass1, 0, strlen (pass1));
memset (pass2, 0, strlen (pass2));
free (pass1);
free (pass2);
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("passwords don't match");
}
memset (pass2, 0, strlen (pass2));
free (pass2);
#if ! defined (__linux__) && ! defined (__FreeBSD__)
printf ("WARNING: your random generator isn't known to be secure\n");
#endif
{
FILE *f;
size_t rd;
f = fopen ("/dev/random", "rb");
if (!f)
{
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
fclose (f);
grub_util_error ("couldn't retrieve random data for salt");
}
rd = fread (salt, 1, saltlen, f);
if (rd != saltlen)
{
fclose (f);
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
fclose (f);
grub_util_error ("couldn't retrieve random data for salt");
}
fclose (f);
}
gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
(grub_uint8_t *) pass1, strlen (pass1),
salt, saltlen,
c, buf, buflen);
memset (pass1, 0, strlen (pass1));
free (pass1);
if (gcry_err)
{
memset (buf, 0, buflen);
memset (bufhex, 0, 2 * buflen);
free (buf);
free (bufhex);
memset (salt, 0, saltlen);
memset (salthex, 0, 2 * saltlen);
free (salt);
free (salthex);
grub_util_error ("cryptographic error number %d", gcry_err);
}
hexify (bufhex, buf, buflen);
hexify (salthex, salt, saltlen);
printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex);
memset (buf, 0, buflen);
memset (bufhex, 0, 2 * buflen);
free (buf);
free (bufhex);
memset (salt, 0, saltlen);
memset (salthex, 0, 2 * saltlen);
free (salt);
free (salthex);
return 0;
}

105
util/grub-mkrelpath.c Normal file
View file

@ -0,0 +1,105 @@
/* grub-mkrelpath.c - make a system path relative to its root */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009,2010 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/i18n.h>
#include <getopt.h>
#include "progname.h"
static struct option options[] =
{
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTIONS] PATH\n\
\n\
Make a system path relative to it's root.\n\
\n\
Options:\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
\n\
Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
exit (status);
}
int
main (int argc, char *argv[])
{
char *argument, *relpath;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "hV", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
default:
usage (1);
break;
}
}
if (optind >= argc)
{
fprintf (stderr, "No path is specified.\n");
usage (1);
}
if (optind + 1 != argc)
{
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
usage (1);
}
argument = argv[optind];
relpath = make_system_path_relative_to_its_root (argument);
printf ("%s\n", relpath);
free (relpath);
return 0;
}

192
util/grub-mkrescue.in Normal file
View file

@ -0,0 +1,192 @@
#! /bin/sh -e
# Make GRUB rescue image
# 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@
bindir=@bindir@
libdir=@libdir@
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
target_cpu=@target_cpu@
native_platform=@platform@
pkglib_DATA="@pkglib_DATA@"
coreboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/${target_cpu}-coreboot
pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/${target_cpu}-pc
# Usage: usage
# Print the usage.
usage () {
cat <<EOF
Usage: $0 [OPTION] SOURCE...
Make GRUB rescue image.
-h, --help print this message and exit
-v, --version print the version information and exit
--modules=MODULES pre-load specified modules MODULES
--output=FILE save output in FILE [required]
$0 generates a bootable rescue image with specified source files or directories.
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 "$0 (GNU GRUB ${PACKAGE_VERSION})"
exit 0 ;;
--modules=*)
modules=`echo "$option" | sed 's/--modules=//'` ;;
--output=*)
output_image=`echo "$option" | sed 's/--output=//'` ;;
# Intentionally undocumented
--override-directory=*)
override_dir=`echo "${option}/" | sed 's/--override-directory=//'`
PATH=${override_dir}:$PATH
export PATH
;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
exit 1
;;
*)
source="${source} ${option}" ;;
esac
done
if [ "x${output_image}" = x ] ; then
echo "output file must be given" >&2
usage
exit 1
fi
iso9660_dir=`mktemp -d`
mkdir -p ${iso9660_dir}/boot/grub
process_input_dir ()
{
input_dir="$1"
platform="$2"
mkdir -p ${iso9660_dir}/boot/grub/${target_cpu}-${platform}
for file in ${input_dir}/*.mod; do
if test -f "$file"; then
cp -f "$file" ${iso9660_dir}/boot/grub/${target_cpu}-${platform}/
fi
done
for file in ${pkglib_DATA}; do
if test -f "${input_dir}/${file}"; then
cp -f "${input_dir}/${file}" ${iso9660_dir}/boot/grub/${target_cpu}-${platform}/
fi
done
mkdir -p ${iso9660_dir}/boot/grub/locale
for file in ${input_dir}/po/*.mo; do
if test -f "$file"; then
cp -f "$file" ${iso9660_dir}/boot/grub/locale/
fi
done
}
if [ "${override_dir}" = "" ] ; then
if test -e "${coreboot_dir}" ; then
process_input_dir ${coreboot_dir} coreboot
fi
if test -e "${pc_dir}" ; then
process_input_dir ${pc_dir} pc
fi
else
process_input_dir ${override_dir} ${native_platform}
coreboot_dir=
pc_dir=
case "${native_platform}" in
coreboot) coreboot_dir=${override_dir} ;;
pc) pc_dir=${override_dir} ;;
esac
fi
# build coreboot core.img
if test -e "${coreboot_dir}" ; then
echo "Enabling coreboot support ..."
memdisk_img=`mktemp`
memdisk_dir=`mktemp -d`
mkdir -p ${memdisk_dir}/boot/grub
# obtain date-based UUID
iso_uuid=$(date +%Y-%m-%d-%H-%M-%S-00)
modules="$(cat ${coreboot_dir}/partmap.lst) ${modules}"
cat << EOF > ${memdisk_dir}/boot/grub/grub.cfg
search --fs-uuid --set ${iso_uuid}
set prefix=(\${root})/boot/grub/${target_cpu}-coreboot
EOF
(for i in ${modules} ; do
echo "insmod $i"
done ; \
echo "source /boot/grub/grub.cfg") \
> ${iso9660_dir}/boot/grub/i386-pc/grub.cfg
tar -C ${memdisk_dir} -cf ${memdisk_img} boot
rm -rf ${memdisk_dir}
grub-mkelfimage -d ${coreboot_dir}/ -m ${memdisk_img} -o ${iso9660_dir}/boot/multiboot.img \
memdisk tar search iso9660 configfile sh \
ata at_keyboard
rm -f ${memdisk_img}
grub_mkisofs_arguments="${grub_mkisofs_arguments} --modification-date=$(echo ${iso_uuid} | sed -e s/-//g)"
fi
# build BIOS core.img
if test -e "${pc_dir}" ; then
echo "Enabling BIOS support ..."
core_img=`mktemp`
grub-mkimage -d ${pc_dir}/ -o ${core_img} --prefix=/boot/grub/i386-pc \
iso9660 biosdisk
cat ${pc_dir}/cdboot.img ${core_img} > ${iso9660_dir}/boot/grub/i386-pc/eltorito.img
embed_img=`mktemp`
cat ${pc_dir}/boot.img ${core_img} > ${embed_img}
rm -f ${core_img}
modules="$(cat ${pc_dir}/partmap.lst) ${modules}"
(for i in ${modules} ; do
echo "insmod $i"
done ; \
echo "source /boot/grub/grub.cfg") \
> ${iso9660_dir}/boot/grub/i386-pc/grub.cfg
grub_mkisofs_arguments="${grub_mkisofs_arguments} -b boot/grub/i386-pc/eltorito.img -boot-info-table \
--embedded-boot ${embed_img}"
fi
# build iso image
grub-mkisofs ${grub_mkisofs_arguments} --protective-msdos-label -o ${output_image} -r ${iso9660_dir} ${source}
rm -rf ${iso9660_dir}
rm -f ${embed_img}
exit 0

521
util/grub-pe2elf.c Normal file
View file

@ -0,0 +1,521 @@
/* grub-pe2elf.c - tool to convert pe image to elf. */
/*
* 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/util/misc.h>
#include <grub/elf.h>
#include <grub/efi/pe32.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
static struct option options[] = {
{"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 `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [OPTIONS] input [output]\n\
\n\
Tool to convert pe image to elf.\n\
\nOptions:\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", program_name, PACKAGE_BUGREPORT);
exit (status);
}
/*
* Section layout
*
* null
* .text
* .rdata
* .data
* .bss
* .modname
* .moddeps
* .symtab
* .strtab
* relocation sections
*/
#define TEXT_SECTION 1
#define RDATA_SECTION 2
#define DATA_SECTION 3
#define BSS_SECTION 4
#define MODNAME_SECTION 5
#define MODDEPS_SECTION 6
#define SYMTAB_SECTION 7
#define STRTAB_SECTION 8
#define REL_SECTION 9
#define MAX_SECTIONS 12
#define STRTAB_BLOCK 256
static char *strtab;
static int strtab_max, strtab_len;
Elf32_Ehdr ehdr;
Elf32_Shdr shdr[MAX_SECTIONS];
int num_sections;
grub_uint32_t offset;
static int
insert_string (char *name)
{
int len, result;
if (*name == '_')
name++;
len = strlen (name);
if (strtab_len + len >= strtab_max)
{
strtab_max += STRTAB_BLOCK;
strtab = xrealloc (strtab, strtab_max);
}
strcpy (strtab + strtab_len, name);
result = strtab_len;
strtab_len += len + 1;
return result;
}
static int *
write_section_data (FILE* fp, char *image,
struct grub_pe32_coff_header *pe_chdr,
struct grub_pe32_section_table *pe_shdr)
{
int *section_map;
int i;
section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int));
section_map[0] = 0;
for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++)
{
grub_uint32_t idx;
if (! strcmp (pe_shdr->name, ".text"))
{
idx = TEXT_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
}
else if (! strcmp (pe_shdr->name, ".rdata"))
{
idx = RDATA_SECTION;
shdr[idx].sh_flags = SHF_ALLOC;
}
else if (! strcmp (pe_shdr->name, ".data"))
{
idx = DATA_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
}
else if (! strcmp (pe_shdr->name, ".bss"))
{
idx = BSS_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
}
else if (! strcmp (pe_shdr->name, ".modname"))
idx = MODNAME_SECTION;
else if (! strcmp (pe_shdr->name, ".moddeps"))
idx = MODDEPS_SECTION;
else
{
section_map[i + 1] = -1;
continue;
}
section_map[i + 1] = idx;
shdr[idx].sh_type = (idx == BSS_SECTION) ? SHT_NOBITS : SHT_PROGBITS;
shdr[idx].sh_size = pe_shdr->raw_data_size;
shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
GRUB_PE32_SCN_ALIGN_SHIFT) &
GRUB_PE32_SCN_ALIGN_MASK) - 1);
if (idx != BSS_SECTION)
{
shdr[idx].sh_offset = offset;
grub_util_write_image_at (image + pe_shdr->raw_data_offset,
pe_shdr->raw_data_size, offset, fp);
offset += pe_shdr->raw_data_size;
}
if (pe_shdr->relocations_offset)
{
char name[5 + strlen (pe_shdr->name)];
if (num_sections >= MAX_SECTIONS)
grub_util_error ("too many sections");
sprintf (name, ".rel%s", pe_shdr->name);
shdr[num_sections].sh_name = insert_string (name);
shdr[num_sections].sh_link = i;
shdr[num_sections].sh_info = idx;
shdr[idx].sh_name = shdr[num_sections].sh_name + 4;
num_sections++;
}
else
shdr[idx].sh_name = insert_string (pe_shdr->name);
}
return section_map;
}
static void
write_reloc_section (FILE* fp, char *image,
struct grub_pe32_coff_header *pe_chdr,
struct grub_pe32_section_table *pe_shdr,
Elf32_Sym *symtab,
int *symtab_map)
{
int i;
for (i = REL_SECTION; i < num_sections; i++)
{
struct grub_pe32_section_table *pe_sec;
struct grub_pe32_reloc *pe_rel;
Elf32_Rel *rel;
int num_rels, j, modified;
pe_sec = pe_shdr + shdr[i].sh_link;
pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
rel = (Elf32_Rel *) xmalloc (pe_sec->num_relocations * sizeof (Elf32_Rel));
num_rels = 0;
modified = 0;
for (j = 0; j < pe_sec->num_relocations; j++, pe_rel++)
{
int type;
grub_uint32_t ofs, *addr;
if ((pe_rel->symtab_index >= pe_chdr->num_symbols) ||
(symtab_map[pe_rel->symtab_index] == -1))
grub_util_error ("invalid symbol");
if (pe_rel->type == GRUB_PE32_REL_I386_DIR32)
type = R_386_32;
else if (pe_rel->type == GRUB_PE32_REL_I386_REL32)
type = R_386_PC32;
else
grub_util_error ("unknown pe relocation type %d\n", pe_rel->type);
ofs = pe_rel->offset - pe_sec->virtual_address;
addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs);
if (type == R_386_PC32)
{
unsigned char code;
code = image[pe_sec->raw_data_offset + ofs - 1];
if (((code != 0xe8) && (code != 0xe9)) || (*addr))
grub_util_error ("invalid relocation (%x %x)", code, *addr);
modified = 1;
if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx)
{
if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
!= shdr[i].sh_info)
grub_util_error ("cross section call is not allowed");
*addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value
- ofs - 4);
continue;
}
else
*addr = -4;
}
rel[num_rels].r_offset = ofs;
rel[num_rels].r_info = ELF32_R_INFO (symtab_map[pe_rel->symtab_index],
type);
num_rels++;
}
if (modified)
grub_util_write_image_at (image + pe_sec->raw_data_offset,
shdr[shdr[i].sh_info].sh_size,
shdr[shdr[i].sh_info].sh_offset,
fp);
shdr[i].sh_type = SHT_REL;
shdr[i].sh_offset = offset;
shdr[i].sh_link = SYMTAB_SECTION;
shdr[i].sh_addralign = 4;
shdr[i].sh_entsize = sizeof (Elf32_Rel);
shdr[i].sh_size = num_rels * sizeof (Elf32_Rel);
grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp);
offset += shdr[i].sh_size;
free (rel);
}
}
static void
write_symbol_table (FILE* fp, char *image,
struct grub_pe32_coff_header *pe_chdr,
struct grub_pe32_section_table *pe_shdr,
int *section_map)
{
struct grub_pe32_symbol *pe_symtab;
char *pe_strtab;
Elf32_Sym *symtab;
int *symtab_map, num_syms;
int i;
pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
symtab = (Elf32_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
sizeof (Elf32_Sym));
memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf32_Sym));
num_syms = 1;
symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
for (i = 0; i < (int) pe_chdr->num_symbols;
i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1)
{
int bind, type;
symtab_map[i] = -1;
if ((pe_symtab->section > pe_chdr->num_sections) ||
(section_map[pe_symtab->section] == -1))
continue;
if (! pe_symtab->section)
type = STT_NOTYPE;
else if (pe_symtab->type == GRUB_PE32_DT_FUNCTION)
type = STT_FUNC;
else
type = STT_OBJECT;
if (pe_symtab->storage_class == GRUB_PE32_SYM_CLASS_EXTERNAL)
bind = STB_GLOBAL;
else
bind = STB_LOCAL;
if ((type != STT_FUNC) && (pe_symtab->num_aux))
{
if (! pe_symtab->value)
type = STT_SECTION;
symtab[num_syms].st_name = shdr[section_map[pe_symtab->section]].sh_name;
}
else
{
char short_name[9];
char *name;
if (pe_symtab->long_name[0])
{
strncpy (short_name, pe_symtab->short_name, 8);
short_name[8] = 0;
name = short_name;
}
else
name = pe_strtab + pe_symtab->long_name[1];
if ((strcmp (name, "_grub_mod_init")) &&
(strcmp (name, "_grub_mod_fini")) &&
(bind == STB_LOCAL))
continue;
symtab[num_syms].st_name = insert_string (name);
}
symtab[num_syms].st_shndx = section_map[pe_symtab->section];
symtab[num_syms].st_value = pe_symtab->value;
symtab[num_syms].st_info = ELF32_ST_INFO (bind, type);
symtab_map[i] = num_syms;
num_syms++;
}
write_reloc_section (fp, image, pe_chdr, pe_shdr, symtab, symtab_map);
shdr[SYMTAB_SECTION].sh_name = insert_string (".symtab");
shdr[SYMTAB_SECTION].sh_type = SHT_SYMTAB;
shdr[SYMTAB_SECTION].sh_offset = offset;
shdr[SYMTAB_SECTION].sh_size = num_syms * sizeof (Elf32_Sym);
shdr[SYMTAB_SECTION].sh_entsize = sizeof (Elf32_Sym);
shdr[SYMTAB_SECTION].sh_link = STRTAB_SECTION;
shdr[SYMTAB_SECTION].sh_addralign = 4;
grub_util_write_image_at (symtab, shdr[SYMTAB_SECTION].sh_size,
offset, fp);
offset += shdr[SYMTAB_SECTION].sh_size;
free (symtab);
free (symtab_map);
}
static void
write_string_table (FILE* fp)
{
shdr[STRTAB_SECTION].sh_name = insert_string (".strtab");
shdr[STRTAB_SECTION].sh_type = SHT_STRTAB;
shdr[STRTAB_SECTION].sh_offset = offset;
shdr[STRTAB_SECTION].sh_size = strtab_len;
shdr[STRTAB_SECTION].sh_addralign = 1;
grub_util_write_image_at (strtab, strtab_len, offset, fp);
offset += strtab_len;
free (strtab);
}
static void
write_section_header (FILE* fp)
{
ehdr.e_ident[EI_MAG0] = ELFMAG0;
ehdr.e_ident[EI_MAG1] = ELFMAG1;
ehdr.e_ident[EI_MAG2] = ELFMAG2;
ehdr.e_ident[EI_MAG3] = ELFMAG3;
ehdr.e_ident[EI_VERSION] = EV_CURRENT;
ehdr.e_version = EV_CURRENT;
ehdr.e_type = ET_REL;
ehdr.e_ident[EI_CLASS] = ELFCLASS32;
ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
ehdr.e_machine = EM_386;
ehdr.e_ehsize = sizeof (ehdr);
ehdr.e_shentsize = sizeof (Elf32_Shdr);
ehdr.e_shstrndx = STRTAB_SECTION;
ehdr.e_shoff = offset;
ehdr.e_shnum = num_sections;
grub_util_write_image_at (&shdr, sizeof (Elf32_Shdr) * num_sections,
offset, fp);
grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp);
}
static void
convert_pe (FILE* fp, char *image)
{
struct grub_pe32_coff_header *pe_chdr;
struct grub_pe32_section_table *pe_shdr;
int *section_map;
pe_chdr = (struct grub_pe32_coff_header *) image;
if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386)
grub_util_error ("invalid coff image");
strtab = xmalloc (STRTAB_BLOCK);
strtab_max = STRTAB_BLOCK;
strtab[0] = 0;
strtab_len = 1;
offset = sizeof (ehdr);
pe_shdr = (struct grub_pe32_section_table *) (pe_chdr + 1);
num_sections = REL_SECTION;
section_map = write_section_data (fp, image, pe_chdr, pe_shdr);
write_symbol_table (fp, image, pe_chdr, pe_shdr, section_map);
free (section_map);
write_string_table (fp);
write_section_header (fp);
}
int
main (int argc, char *argv[])
{
char *image;
FILE* fp;
set_program_name (argv[0]);
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbosity++;
break;
default:
usage (1);
break;
}
}
/* Obtain PATH. */
if (optind >= argc)
{
fprintf (stderr, "Filename not specified.\n");
usage (1);
}
image = grub_util_read_image (argv[optind]);
if (optind + 1 < argc)
optind++;
fp = fopen (argv[optind], "wb");
if (! fp)
grub_util_error ("cannot open %s", argv[optind]);
convert_pe (fp, image);
fclose (fp);
return 0;
}

View file

@ -1,7 +1,7 @@
/* grub-probe.c - probe device information for a given path */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 2005,2006,2007,2008,2009,2010 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
@ -25,10 +25,13 @@
#include <grub/file.h>
#include <grub/fs.h>
#include <grub/partition.h>
#include <grub/pc_partition.h>
#include <grub/util/biosdisk.h>
#include <grub/msdos_partition.h>
#include <grub/util/hostdisk.h>
#include <grub/util/getroot.h>
#include <grub/term.h>
#include <grub/env.h>
#include <grub/raid.h>
#include <grub/i18n.h>
#include <grub_probe_init.h>
@ -41,8 +44,11 @@
#define _GNU_SOURCE 1
#include <getopt.h>
#include "progname.h"
enum {
PRINT_FS,
PRINT_FS_UUID,
PRINT_DRIVE,
PRINT_DEVICE,
PRINT_PARTMAP,
@ -50,6 +56,7 @@ enum {
};
int print = PRINT_FS;
static unsigned int argument_is_device = 0;
void
grub_putchar (int c)
@ -63,30 +70,60 @@ grub_getkey (void)
return -1;
}
grub_term_t
grub_term_get_current (void)
{
return 0;
}
struct grub_handler_class grub_term_input_class;
struct grub_handler_class grub_term_output_class;
void
grub_refresh (void)
{
fflush (stdout);
}
static void
probe (const char *path)
probe_partmap (grub_disk_t disk)
{
if (disk->partition == NULL)
{
grub_util_info ("no partition map found for %s", disk->name);
return;
}
printf ("%s\n", disk->partition->partmap->name);
}
static int
probe_raid_level (grub_disk_t disk)
{
if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID)
return -1;
return ((struct grub_raid_array *) disk->data)->level;
}
static void
probe (const char *path, char *device_name)
{
char *device_name;
char *drive_name = NULL;
char *grub_path = NULL;
char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
int abstraction_type;
grub_device_t dev = NULL;
device_name = grub_guess_root_device (path);
grub_fs_t fs;
if (path == NULL)
{
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (! grub_util_check_char_device (device_name))
grub_util_error ("%s is not a character device", device_name);
#else
if (! grub_util_check_block_device (device_name))
grub_util_error ("%s is not a block device", device_name);
#endif
}
else
device_name = grub_guess_root_device (path);
if (! device_name)
grub_util_error ("cannot find a device for %s.\n", path);
grub_util_error ("cannot find a device for %s (is /dev mounted?)", path);
if (print == PRINT_DEVICE)
{
@ -94,32 +131,10 @@ probe (const char *path)
goto end;
}
abstraction_type = grub_util_get_dev_abstraction (device_name);
/* No need to check for errors; lack of abstraction is permissible. */
if (print == PRINT_ABSTRACTION)
{
char *abstraction_name;
switch (abstraction_type)
{
case GRUB_DEV_ABSTRACTION_NONE:
grub_util_info ("did not find LVM/RAID in %s, assuming raw device", device_name);
goto end;
case GRUB_DEV_ABSTRACTION_LVM:
abstraction_name = "lvm";
break;
case GRUB_DEV_ABSTRACTION_RAID:
abstraction_name = "raid";
break;
}
printf ("%s\n", abstraction_name);
goto end;
}
drive_name = grub_util_get_grub_dev (device_name);
if (! drive_name)
grub_util_error ("cannot find a GRUB drive for %s.\n", device_name);
grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name);
if (print == PRINT_DRIVE)
{
printf ("(%s)\n", drive_name);
@ -131,76 +146,156 @@ probe (const char *path)
if (! dev)
grub_util_error ("%s", grub_errmsg);
if (print == PRINT_PARTMAP)
if (print == PRINT_ABSTRACTION)
{
if (dev->disk->partition == NULL)
grub_util_error ("Cannot detect partition map for %s", drive_name);
grub_disk_memberlist_t list = NULL, tmp;
const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
int is_raid = 0;
int is_raid5 = 0;
int is_raid6 = 0;
int raid_level;
raid_level = probe_raid_level (dev->disk);
if (raid_level >= 0)
{
is_raid = 1;
is_raid5 |= (raid_level == 5);
is_raid6 |= (raid_level == 6);
}
if ((is_lvm) && (dev->disk->dev->memberlist))
list = dev->disk->dev->memberlist (dev->disk);
while (list)
{
raid_level = probe_raid_level (list->disk);
if (raid_level >= 0)
{
is_raid = 1;
is_raid5 |= (raid_level == 5);
is_raid6 |= (raid_level == 6);
}
tmp = list->next;
free (list);
list = tmp;
}
if (is_raid)
{
printf ("raid ");
if (is_raid5)
printf ("raid5rec ");
if (is_raid6)
printf ("raid6rec ");
printf ("mdraid ");
}
if (is_lvm)
printf ("lvm ");
printf ("\n");
if (strcmp (dev->disk->partition->partmap->name, "amiga_partition_map") == 0)
printf ("amiga\n");
else if (strcmp (dev->disk->partition->partmap->name, "apple_partition_map") == 0)
printf ("apple\n");
else if (strcmp (dev->disk->partition->partmap->name, "gpt_partition_map") == 0)
printf ("gpt\n");
else if (strcmp (dev->disk->partition->partmap->name, "pc_partition_map") == 0)
printf ("pc\n");
else if (strcmp (dev->disk->partition->partmap->name, "sun_partition_map") == 0)
printf ("sun\n");
else
grub_util_error ("Unknown partition map %s", dev->disk->partition->partmap->name);
goto end;
}
if (print == PRINT_PARTMAP)
{
grub_disk_memberlist_t list = NULL, tmp;
/* Check if dev->disk itself is contained in a partmap. */
probe_partmap (dev->disk);
/* In case of LVM/RAID, check the member devices as well. */
if (dev->disk->dev->memberlist)
list = dev->disk->dev->memberlist (dev->disk);
while (list)
{
probe_partmap (list->disk);
/* LVM on RAID */
if (list->disk->dev->memberlist)
{
grub_disk_memberlist_t sub_list;
sub_list = list->disk->dev->memberlist (list->disk);
while (sub_list)
{
probe_partmap (sub_list->disk);
tmp = sub_list->next;
free (sub_list);
sub_list = tmp;
}
}
tmp = list->next;
free (list);
list = tmp;
}
goto end;
}
fs = grub_fs_probe (dev);
if (! fs)
grub_util_error ("%s", grub_errmsg);
if (print == PRINT_FS)
{
struct stat st;
grub_fs_t fs;
if (path)
{
struct stat st;
stat (path, &st);
stat (path, &st);
if (st.st_mode == S_IFREG)
{
/* Regular file. Verify that we can read it properly. */
if (S_ISREG (st.st_mode))
{
/* Regular file. Verify that we can read it properly. */
grub_file_t file;
grub_util_info ("reading %s via OS facilities", path);
filebuf_via_sys = grub_util_read_image (path);
grub_util_info ("reading %s via GRUB facilities", path);
asprintf (&grub_path, "(%s)%s", drive_name, path);
file = grub_file_open (grub_path);
filebuf_via_grub = xmalloc (file->size);
grub_file_read (file, filebuf_via_grub, file->size);
grub_util_info ("comparing");
if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size))
grub_util_error ("files differ");
grub_file_t file;
char *rel_path;
grub_util_info ("reading %s via OS facilities", path);
filebuf_via_sys = grub_util_read_image (path);
fs = file->fs;
}
else
{
fs = grub_fs_probe (dev);
if (! fs)
grub_util_error ("%s", grub_errmsg);
rel_path = make_system_path_relative_to_its_root (path);
grub_path = xasprintf ("(%s)%s", drive_name, rel_path);
free (rel_path);
grub_util_info ("reading %s via GRUB facilities", grub_path);
file = grub_file_open (grub_path);
if (! file)
grub_util_error ("cannot open %s via GRUB facilities", grub_path);
filebuf_via_grub = xmalloc (file->size);
grub_file_read (file, filebuf_via_grub, file->size);
grub_util_info ("comparing");
if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size))
grub_util_error ("files differ");
}
}
printf ("%s\n", fs->name);
}
if (print == PRINT_FS_UUID)
{
char *uuid;
if (! fs->uuid)
grub_util_error ("%s does not support UUIDs", fs->name);
fs->uuid (dev, &uuid);
printf ("%s\n", uuid);
}
end:
if (dev)
grub_device_close (dev);
free (grub_path);
free (filebuf_via_grub);
free (filebuf_via_sys);
free (device_name);
free (drive_name);
}
static struct option options[] =
{
{"device", no_argument, 0, 'd'},
{"device-map", required_argument, 0, 'm'},
{"target", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
@ -214,24 +309,25 @@ usage (int status)
{
if (status)
fprintf (stderr,
"Try ``grub-probe --help'' for more information.\n");
"Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: grub-probe [OPTION]... PATH\n\
Usage: %s [OPTION]... [PATH|DEVICE]\n\
\n\
Probe device information for a given path.\n\
Probe device information for a given path (or device, if the -d option is given).\n\
\n\
-d, --device given argument is a system device, not a path\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
-t, --target=(fs|drive|device|partmap|abstraction)\n\
-t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\
print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\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\
",
", program_name,
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
exit (status);
}
@ -239,20 +335,26 @@ int
main (int argc, char *argv[])
{
char *dev_map = 0;
char *path;
progname = "grub-probe";
char *argument;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "m:t:hVv", options, 0);
int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'd':
argument_is_device = 1;
break;
case 'm':
if (dev_map)
free (dev_map);
@ -263,6 +365,8 @@ main (int argc, char *argv[])
case 't':
if (!strcmp (optarg, "fs"))
print = PRINT_FS;
else if (!strcmp (optarg, "fs_uuid"))
print = PRINT_FS_UUID;
else if (!strcmp (optarg, "drive"))
print = PRINT_DRIVE;
else if (!strcmp (optarg, "device"))
@ -280,7 +384,7 @@ main (int argc, char *argv[])
break;
case 'V':
printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
@ -293,10 +397,13 @@ main (int argc, char *argv[])
}
}
/* Obtain PATH. */
if (verbosity > 1)
grub_env_set ("debug", "all");
/* Obtain ARGUMENT. */
if (optind >= argc)
{
fprintf (stderr, "No path is specified.\n");
fprintf (stderr, "No path or device is specified.\n");
usage (1);
}
@ -306,22 +413,25 @@ main (int argc, char *argv[])
usage (1);
}
path = argv[optind];
argument = argv[optind];
/* Initialize the emulated biosdisk driver. */
grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
/* Initialize all modules. */
grub_init_all ();
/* Do it. */
probe (path);
if (argument_is_device)
probe (NULL, argument);
else
probe (argument, NULL);
/* Free resources. */
grub_fini_all ();
grub_util_biosdisk_fini ();
free (dev_map);
return 0;
}

108
util/grub-reboot.in Normal file
View file

@ -0,0 +1,108 @@
#! /bin/sh
#
# Set a default boot entry for GRUB, for the next boot only.
# Copyright (C) 2004,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@
bindir=@bindir@
grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
rootdir=
# Usage: usage
# Print the usage.
usage () {
cat <<EOF
Usage: $0 [OPTION] entry
Set the default boot entry for GRUB, for the next boot only.
-h, --help print this message and exit
-v, --version print the version information and exit
--root-directory=DIR expect GRUB images under the directory DIR
instead of the root directory
ENTRY is a number or a menu item title.
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-reboot (GNU GRUB ${PACKAGE_VERSION})"
exit 0 ;;
--root-directory=*)
rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
exit 1
;;
*)
if test "x$entry" != x; then
echo "More than one entry?" 1>&2
usage
exit 1
fi
entry="${option}" ;;
esac
done
if test "x$entry" = x; then
echo "entry not specified." 1>&2
usage
exit 1
fi
# Initialize these directories here, since ROOTDIR was initialized.
case "$host_os" in
netbsd* | openbsd*)
# Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
# instead of /boot/grub.
grub_prefix=`echo /grub | sed ${transform}`
bootdir=${rootdir}
;;
*)
# Use /boot/grub by default.
bootdir=${rootdir}/boot
;;
esac
grubdir=${bootdir}/`echo grub | sed ${transform}`
prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'`
if [ "$prev_saved_entry" ]; then
$grub_editenv ${grubdir}/grubenv set prev_saved_entry="$prev_saved_entry"
else
# We need some non-empty value for prev_saved_entry so that GRUB will
# recognise that grub-reboot has been used and restore the previous
# saved entry. "0" is the same as an empty value, i.e. the first menu
# entry.
$grub_editenv ${grubdir}/grubenv set prev_saved_entry=0
fi
$grub_editenv ${grubdir}/grubenv set saved_entry="$entry"
# Bye.
exit 0

250
util/grub-script-check.c Normal file
View file

@ -0,0 +1,250 @@
/* grub-script-check.c - check grub script file for syntax errors */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 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/mm.h>
#include <grub/misc.h>
#include <grub/util/misc.h>
#include <grub/i18n.h>
#include <grub/parser.h>
#include <grub/script_sh.h>
#include <grub_script_check_init.h>
#define _GNU_SOURCE 1
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "progname.h"
void
grub_putchar (int c)
{
putchar (c);
}
int
grub_getkey (void)
{
return -1;
}
void
grub_refresh (void)
{
fflush (stdout);
}
char *
grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused)))
{
return 0;
}
grub_err_t
grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused)))
{
return 0;
}
grub_err_t
grub_script_execute_cmdblock (struct grub_script_cmd *cmd __attribute__ ((unused)))
{
return 0;
}
grub_err_t
grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused)))
{
return 0;
}
grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
{
struct grub_script_cmd_menuentry *menu;
menu = (struct grub_script_cmd_menuentry *)cmd;
if (menu->sourcecode)
{
grub_free (menu->sourcecode);
menu->sourcecode = 0;
}
return 0;
}
grub_err_t
grub_script_execute (struct grub_script *script)
{
if (script == 0 || script->cmd == 0)
return 0;
return script->cmd->exec (script->cmd);
}
static struct option options[] =
{
{"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 ``%s --help'' for more information.\n", program_name);
else
printf ("\
Usage: %s [PATH]\n\
\n\
Checks GRUB script configuration file for syntax errors.\n\
\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print script being processed\n\
\n\
Report bugs to <%s>.\n\
", program_name,
PACKAGE_BUGREPORT);
exit (status);
}
int
main (int argc, char *argv[])
{
char *argument;
char *input;
FILE *file = 0;
int verbose = 0;
struct grub_script *script;
auto grub_err_t get_config_line (char **line, int cont);
grub_err_t get_config_line (char **line, int cont __attribute__ ((unused)))
{
char *cmdline = 0;
size_t len = 0;
ssize_t read;
read = getline(&cmdline, &len, (file ?: stdin));
if (read == -1)
{
*line = 0;
grub_errno = GRUB_ERR_READ_ERROR;
if (cmdline)
free (cmdline);
return grub_errno;
}
if (verbose)
grub_printf("%s", cmdline);
*line = grub_strdup (cmdline);
free (cmdline);
return 0;
}
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "hvV", options, 0);
if (c == -1)
break;
else
switch (c)
{
case 'h':
usage (0);
break;
case 'V':
printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
return 0;
case 'v':
verbose = 1;
break;
default:
usage (1);
break;
}
}
/* Obtain ARGUMENT. */
if (optind >= argc)
{
file = 0; /* read from stdin */
}
else if (optind + 1 != argc)
{
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
usage (1);
}
else
{
argument = argv[optind];
file = fopen (argument, "r");
if (! file)
{
fprintf (stderr, "%s: %s: %s\n", program_name, argument, strerror(errno));
usage (1);
}
}
/* Initialize all modules. */
grub_init_all ();
do
{
input = 0;
get_config_line(&input, 0);
if (! input)
break;
script = grub_script_parse (input, get_config_line);
if (script)
{
grub_script_execute (script);
grub_script_free (script);
}
grub_free (input);
} while (script != 0);
/* Free resources. */
grub_fini_all ();
if (file) fclose (file);
return (script == 0);
}

99
util/grub-set-default.in Normal file
View file

@ -0,0 +1,99 @@
#! /bin/sh
#
# Set a default boot entry for GRUB.
# Copyright (C) 2004,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@
bindir=@bindir@
grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
rootdir=
# Usage: usage
# Print the usage.
usage () {
cat <<EOF
Usage: $0 [OPTION] entry
Set the default boot entry for GRUB.
-h, --help print this message and exit
-v, --version print the version information and exit
--root-directory=DIR expect GRUB images under the directory DIR
instead of the root directory
ENTRY is a number or a menu item title.
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-set-default (GNU GRUB ${PACKAGE_VERSION})"
exit 0 ;;
--root-directory=*)
rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
exit 1
;;
*)
if test "x$entry" != x; then
echo "More than one entry?" 1>&2
usage
exit 1
fi
entry="${option}" ;;
esac
done
if test "x$entry" = x; then
echo "entry not specified." 1>&2
usage
exit 1
fi
# Initialize these directories here, since ROOTDIR was initialized.
case "$host_os" in
netbsd* | openbsd*)
# Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
# instead of /boot/grub.
grub_prefix=`echo /grub | sed ${transform}`
bootdir=${rootdir}
;;
*)
# Use /boot/grub by default.
bootdir=${rootdir}/boot
;;
esac
grubdir=${bootdir}/`echo grub | sed ${transform}`
$grub_editenv ${grubdir}/grubenv unset prev_saved_entry
$grub_editenv ${grubdir}/grubenv set saved_entry="$entry"
# Bye.
exit 0

View file

@ -1,7 +1,7 @@
#! /bin/sh -e
# update-grub helper script.
# Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
# grub-mkconfig helper script.
# Copyright (C) 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
@ -16,50 +16,132 @@
# You should have received a copy of the GNU General Public License
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
platform=@platform@
grub_prefix=`echo /boot/grub | sed ${transform}`
locale_dir=`echo /boot/grub/locale | sed ${transform}`
grub_lang=`echo $LANG | cut -d _ -f 1`
# for convert_system_path_to_grub_path()
. ${libdir}/grub/update-grub_lib
. ${libdir}/grub/grub-mkconfig_lib
# Do this as early as possible, since other commands might depend on it.
# (e.g. the `font' command might need lvm or raid modules)
# (e.g. the `loadfont' command might need lvm or raid modules)
for i in ${GRUB_PRELOAD_MODULES} ; do
echo "insmod $i"
done
if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi
if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi
if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi
if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi
cat << EOF
set default=${GRUB_DEFAULT}
set timeout=${GRUB_TIMEOUT}
EOF
if [ "x${GRUB_DRIVE}" = "x" ] ; then : ; else
echo "set root=${GRUB_DRIVE}"
if [ -s \$prefix/grubenv ]; then
load_env
fi
set default="${GRUB_DEFAULT}"
if [ \${prev_saved_entry} ]; then
set saved_entry=\${prev_saved_entry}
save_env saved_entry
set prev_saved_entry=
save_env prev_saved_entry
set boot_once=true
fi
if [ "x${GRUB_FONT_PATH}" = "x" ] ; then : ; else
echo "font ${GRUB_FONT_PATH}"
fi
case ${platform}:${GRUB_TERMINAL} in
pc:gfxterm) cat << EOF
set gfxmode=640x480
insmod gfxterm
insmod vbe
function savedefault {
if [ -z \${boot_once} ]; then
saved_entry=\${chosen}
save_env saved_entry
fi
}
EOF
;;
*:serial)
case ${GRUB_TERMINAL_INPUT}:${GRUB_TERMINAL_OUTPUT} in
serial:* | *:serial)
if ! test -e ${grub_prefix}/serial.mod ; then
echo "Serial terminal not available on this platform." >&2 ; exit 1
fi
if [ "x${GRUB_SERIAL_COMMAND}" = "x" ] ; then
echo "Warning, requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used." >&2
grub_warn "Requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used."
GRUB_SERIAL_COMMAND=serial
fi
echo "${GRUB_SERIAL_COMMAND}"
;;
esac
echo "terminal ${GRUB_TERMINAL}"
case x${GRUB_TERMINAL_INPUT} in
x)
# Just use the native terminal
;;
x*)
cat << EOF
if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else
# For backward compatibility with versions of terminal.mod that don't
# understand terminal_input
terminal ${GRUB_TERMINAL_INPUT}
fi
EOF
;;
esac
case x${GRUB_TERMINAL_OUTPUT} in
xgfxterm)
# Make the font accessible
prepare_grub_to_access_device `${grub_probe} --target=device ${GRUB_FONT_PATH}`
cat << EOF
if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then
set gfxmode=${GRUB_GFXMODE}
insmod gfxterm
insmod ${GRUB_VIDEO_BACKEND}
if terminal_output gfxterm ; then true ; else
# For backward compatibility with versions of terminal.mod that don't
# understand terminal_output
terminal gfxterm
fi
fi
EOF
;;
x)
# Just use the native terminal
;;
x*)
cat << EOF
if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else
# For backward compatibility with versions of terminal.mod that don't
# understand terminal_output
terminal ${GRUB_TERMINAL_OUTPUT}
fi
EOF
;;
esac
# Gettext variables and module
if [ "x${LANG}" != "xC" ] ; then
cat << EOF
set locale_dir=${locale_dir}
set lang=${grub_lang}
insmod gettext
EOF
fi
if [ "x${GRUB_HIDDEN_TIMEOUT}" != "x" ] ; then
if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then
verbose=
else
verbose=" --verbose"
fi
cat << EOF
if sleep$verbose --interruptible ${GRUB_HIDDEN_TIMEOUT} ; then
set timeout=${GRUB_TIMEOUT}
fi
EOF
else
cat << EOF
set timeout=${GRUB_TIMEOUT}
EOF
fi

View file

@ -1,7 +1,7 @@
#! /bin/sh -e
# update-grub helper script.
# Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
# grub-mkconfig helper script.
# Copyright (C) 2006,2007,2008,2009,2010 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
@ -16,6 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
. ${libdir}/grub/grub-mkconfig_lib
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
OS=GNU
else
@ -31,9 +36,9 @@ for i in /boot/gnumach.gz /boot/gnumach ; do
if test -e $i ; then
basename=`basename $i`
dirname=`dirname $i`
grub_dirname=`echo ${dirname} | sed -e "s%^/boot%${GRUB_DRIVE_BOOT}%g"`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
echo "Found GNU Mach: $i" >&2
kernel=${grub_dirname}/${basename}
kernel=${rel_dirname}/${basename}
at_least_one=true
fi
done
@ -45,7 +50,7 @@ case "${GRUB_FS}" in
esac
for i in /hurd/${hurd_fs}.static /hurd/exec ; do
if test -e "$i" ; then
if test -e "$i" ; then
echo "Found Hurd module: $i" >&2
at_least_one=true
else
@ -65,13 +70,22 @@ fi
cat << EOF
menuentry "${OS}" {
multiboot ${kernel} root=device:${GRUB_DEVICE}
module /hurd/${hurd_fs}.static --readonly \\
EOF
prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
cat << EOF
echo $(gettext "Loading GNU Mach ...")
multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/}
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/"
cat << EOF
echo $(gettext "Loading the Hurd ...")
module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\
--multiboot-command-line='\${kernel-command-line}' \\
--host-priv-port='\${host-port}' \\
--device-master-port='\${device-port}' \\
--exec-server-task='\${exec-task}' -T typed '\${root}' \\
'\$(task-create)' '\$(task-resume)'
module /lib/ld.so.1 /hurd/exec '\$(exec-task=task-create)'
module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
}
EOF

116
util/grub.d/10_kfreebsd.in Normal file
View file

@ -0,0 +1,116 @@
#! /bin/sh -e
# grub-mkconfig helper script.
# Copyright (C) 2006,2007,2008,2009,2010 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/>.
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
. ${libdir}/grub/grub-mkconfig_lib
. ${bindir}/gettext.sh
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
case "${GRUB_DISTRIBUTOR}" in
Debian) OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" ;;
*) OS="FreeBSD" ;;
esac
kfreebsd_entry ()
{
os="$1"
version="$2"
recovery="$3" # not used yet
args="$4" # not used yet
title="$(gettext "%s, with kFreeBSD %s")"
printf "menuentry \"${title}\" {\n" "${os}" "${version}"
save_default_entry | sed -e "s/^/\t/"
if [ -z "${prepare_boot_cache}" ]; then
prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
fi
printf '%s\n' "${prepare_boot_cache}"
cat << EOF
echo $(printf "$(gettext "Loading kernel of FreeBSD %s ...")" ${version})
kfreebsd ${rel_dirname}/${basename}
EOF
if test -n "${devices}" ; then
cat << EOF
kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename}
EOF
fi
if test -n "${acpi_ko}" ; then
cat << EOF
kfreebsd_module_elf ${acpi_ko_rel_dirname}/${acpi_ko_basename}
EOF
fi
cat << EOF
set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE}
set kFreeBSD.vfs.root.mountfrom.options=rw
}
EOF
}
list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do
if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
done`
prepare_boot_cache=
while [ "x$list" != "x" ] ; do
kfreebsd=`version_find_latest $list`
echo "Found kernel of FreeBSD: $kfreebsd" >&2
basename=`basename $kfreebsd`
dirname=`dirname $kfreebsd`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
if [ -f /boot/device.hints ] ; then
devices=/boot/device.hints
devices_basename=`basename $devices`
devices_dirname=`dirname $devices`
devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname`
fi
case ${GRUB_FS} in
ufs1 | ufs2) kfreebsd_fs=ufs ;;
*) kfreebsd_fs=${GRUB_FS} ;;
esac
version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"`
alt_version=`echo $version | sed -e "s,\.old$,,g"`
acpi_ko=
for i in "/lib/modules/${version}/acpi.ko" "/lib/modules/${alt_version}/acpi.ko" \
"/boot/kernel/acpi.ko"; do
if test -e "$i" ; then
acpi_ko="$i"
break
fi
done
if test -n "${acpi_ko}" ; then
echo "Found ACPI module: ${acpi_ko}" >&2
acpi_ko_basename=`basename ${acpi_ko}`
acpi_ko_dirname=`dirname ${acpi_ko}`
acpi_ko_rel_dirname=`make_system_path_relative_to_its_root $acpi_ko_dirname`
fi
kfreebsd_entry "${OS}" "${version}"
list=`echo $list | tr ' ' '\n' | grep -vx $kfreebsd | tr '\n' ' '`
done

View file

@ -1,7 +1,7 @@
#! /bin/sh -e
# update-grub helper script.
# Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
# grub-mkconfig helper script.
# Copyright (C) 2006,2007,2008,2009,2010 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
@ -18,8 +18,13 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
. ${libdir}/grub/update-grub_lib
. ${libdir}/grub/grub-mkconfig_lib
. ${bindir}/gettext.sh
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
OS=GNU/Linux
@ -27,73 +32,72 @@ else
OS="${GRUB_DISTRIBUTOR} GNU/Linux"
fi
test_numeric ()
# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
case ${GRUB_DEVICE} in
/dev/loop/*|/dev/loop[0-9])
GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
;;
esac
if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
|| ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then
LINUX_ROOT_DEVICE=${GRUB_DEVICE}
else
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
linux_entry ()
{
local a=$1
local cmp=$2
local b=$3
if [ "$a" = "$b" ] ; then
case $cmp in
ge|eq|le) return 0 ;;
gt|lt) return 1 ;;
esac
fi
if [ "$cmp" = "lt" ] ; then
c=$a
a=$b
b=$c
fi
if (echo $a ; echo $b) | sort -n | head -n 1 | grep -qx $b ; then
return 0
os="$1"
version="$2"
recovery="$3"
args="$4"
if ${recovery} ; then
title="$(gettext "%s, with Linux %s (recovery mode)")"
else
return 1
title="$(gettext "%s, with Linux %s")"
fi
}
test_gt ()
{
local a=`echo $1 | sed -e "s/vmlinu[zx]-//g"`
local b=`echo $2 | sed -e "s/vmlinu[zx]-//g"`
local cmp=gt
if [ "x$b" = "x" ] ; then
return 0
printf "menuentry \"${title}\" {\n" "${os}" "${version}"
save_default_entry | sed -e "s/^/\t/"
if [ -z "${prepare_boot_cache}" ]; then
prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
fi
case $a:$b in
*.old:*.old) ;;
*.old:*) a=`echo -n $a | sed -e s/\.old$//g` ; cmp=gt ;;
*:*.old) b=`echo -n $b | sed -e s/\.old$//g` ; cmp=ge ;;
esac
test_numeric $a $cmp $b
return $?
printf '%s\n' "${prepare_boot_cache}"
cat << EOF
echo $(printf "$(gettext "Loading Linux %s ...")" ${version})
linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
if test -n "${initrd}" ; then
cat << EOF
echo $(gettext "Loading initial ramdisk ...")
initrd ${rel_dirname}/${initrd}
EOF
fi
cat << EOF
}
find_latest ()
{
local a=""
for i in $@ ; do
if test_gt "$i" "$a" ; then
a="$i"
fi
done
echo "$a"
EOF
}
list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
done`
prepare_boot_cache=
while [ "x$list" != "x" ] ; do
linux=`find_latest $list`
linux=`version_find_latest $list`
echo "Found linux image: $linux" >&2
basename=`basename $linux`
dirname=`dirname $linux`
grub_dirname=`echo ${dirname} | sed -e "s%^/boot%${GRUB_DRIVE_BOOT}%g"`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
alt_version=`echo $version | sed -e "s,\.old$,,g"`
linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
initrd=
for i in "initrd.img-${version}" "initrd-${version}.img" \
"initrd.img-${alt_version}" "initrd-${alt_version}.img"; do
"initrd-${version}" "initrd.img-${alt_version}" \
"initrd-${alt_version}.img" "initrd-${alt_version}"; do
if test -e "${dirname}/${i}" ; then
initrd="$i"
break
@ -101,33 +105,17 @@ while [ "x$list" != "x" ] ; do
done
if test -n "${initrd}" ; then
echo "Found initrd image: ${dirname}/${initrd}" >&2
else
# "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here.
linux_root_device_thisversion=${GRUB_DEVICE}
fi
cat << EOF
menuentry "${OS}, linux ${version}" {
linux ${grub_dirname}/${basename} root=${GRUB_DEVICE} ro ${GRUB_CMDLINE_LINUX}
EOF
if test -n "${initrd}" ; then
cat << EOF
initrd ${grub_dirname}/${initrd}
EOF
linux_entry "${OS}" "${version}" false \
"${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then
linux_entry "${OS}" "${version}" true \
"single ${GRUB_CMDLINE_LINUX}"
fi
cat << EOF
}
EOF
cat << EOF
menuentry "${OS}, linux ${version} (single-user mode)" {
linux ${grub_dirname}/${basename} root=${GRUB_DEVICE} ro single ${GRUB_CMDLINE_LINUX}
EOF
if test -n "${initrd}" ; then
cat << EOF
initrd ${grub_dirname}/${initrd}
EOF
fi
cat << EOF
}
EOF
list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
done

84
util/grub.d/10_windows.in Normal file
View file

@ -0,0 +1,84 @@
#! /bin/sh -e
# grub-mkconfig helper script.
# Copyright (C) 2008 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/>.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
. ${libdir}/grub/grub-mkconfig_lib
case "`uname 2>/dev/null`" in
CYGWIN*) ;;
*) exit 0 ;;
esac
# Try C: even if current system is on other partition.
case "$SYSTEMDRIVE" in
[Cc]:) dirlist="C:" ;;
[D-Zd-z]:) dirlist="C: $SYSTEMDRIVE" ;;
*) exit 0 ;;
esac
get_os_name_from_boot_ini ()
{
# Fail if no or more than one partition.
test "`sed -n 's,^\(\(multi\|scsi\)[^=]*\)=.*$,\1,p' "$1" 2>/dev/null | \
sort | uniq | wc -l`" = 1 || return 1
# Search 'default=PARTITION'
local part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'`
test -n "$part" || return 1
# Search 'PARTITION="NAME" ...'
local name=`sed -n 's,\\\\,/,g;s,^'"$part"'="\([^"]*\)".*$,\1,p' "$1" | sed 1q`
test -n "$name" || return 1
echo "$name"
}
for dir in $dirlist ; do
# Check for Vista bootmgr.
if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then
OS="Windows Vista bootmgr"
# Check for NTLDR.
elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then
OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="Windows NT/2000/XP loader"
else
continue
fi
# Get boot /dev/ice.
dev=`${grub_probe} -t device "$dir" 2>/dev/null` || continue
echo "Found $OS on $dir ($dev)" >&2
cat << EOF
menuentry "$OS" {
EOF
save_default_entry | sed -e 's,^,\t,'
prepare_grub_to_access_device "$dev" | sed 's,^,\t,'
cat << EOF
chainloader +1
}
EOF
done

203
util/grub.d/30_os-prober.in Normal file
View file

@ -0,0 +1,203 @@
#! /bin/sh -e
# grub-mkconfig helper script.
# Copyright (C) 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/>.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
. ${libdir}/grub/grub-mkconfig_lib
if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
exit 0
fi
if [ -z "`which os-prober 2> /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then
# missing os-prober and/or linux-boot-prober
exit 0
fi
OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
if [ -z "${OSPROBED}" ] ; then
# empty os-prober output, nothing doing
exit 0
fi
osx_entry() {
cat << EOF
menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" {
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
cat << EOF
insmod ${GRUB_VIDEO_BACKEND}
set do_resume=0
if [ /var/vm/sleepimage -nt10 / ]; then
if xnu_resume /var/vm/sleepimage; then
set do_resume=1
fi
fi
if [ \$do_resume == 0 ]; then
xnu_uuid ${OSXUUID} uuid
if [ -f /Extra/DSDT.aml ]; then
acpi -e /Extra/DSDT.aml
fi
$1 /mach_kernel boot-uuid=\${uuid} rd=*uuid
if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
xnu_mkext /System/Library/Extensions.mkext
else
xnu_kextdir /System/Library/Extensions
fi
if [ -f /Extra/Extensions.mkext ]; then
xnu_mkext /Extra/Extensions.mkext
fi
if [ -d /Extra/Extensions ]; then
xnu_kextdir /Extra/Extensions
fi
if [ -f /Extra/devprop.bin ]; then
xnu_devprop_load /Extra/devprop.bin
fi
if [ -f /Extra/splash.jpg ]; then
insmod jpeg
xnu_splash /Extra/splash.jpg
fi
if [ -f /Extra/splash.png ]; then
insmod png
xnu_splash /Extra/splash.png
fi
if [ -f /Extra/splash.tga ]; then
insmod tga
xnu_splash /Extra/splash.tga
fi
fi
}
EOF
}
for OS in ${OSPROBED} ; do
DEVICE="`echo ${OS} | cut -d ':' -f 1`"
LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
BOOT="`echo ${OS} | cut -d ':' -f 4`"
if [ -z "${LONGNAME}" ] ; then
LONGNAME="${LABEL}"
fi
echo "Found ${LONGNAME} on ${DEVICE}" >&2
case ${BOOT} in
chain)
cat << EOF
menuentry "${LONGNAME} (on ${DEVICE})" {
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
case ${LONGNAME} in
Windows\ Vista*|Windows\ 7*)
;;
*)
cat << EOF
drivemap -s (hd0) \${root}
EOF
;;
esac
cat <<EOF
chainloader +1
}
EOF
;;
linux)
LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
prepare_boot_cache=
for LINUX in ${LINUXPROBED} ; do
LROOT="`echo ${LINUX} | cut -d ':' -f 1`"
LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"
LLABEL="`echo ${LINUX} | cut -d ':' -f 3 | tr '^' ' '`"
LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
LINITRD="`echo ${LINUX} | cut -d ':' -f 5`"
LPARAMS="`echo ${LINUX} | cut -d ':' -f 6- | tr '^' ' '`"
if [ -z "${LLABEL}" ] ; then
LLABEL="${LONGNAME}"
fi
if [ "${LROOT}" != "${LBOOT}" ]; then
LKERNEL="${LKERNEL#/boot}"
LINITRD="${LINITRD#/boot}"
fi
cat << EOF
menuentry "${LLABEL} (on ${DEVICE})" {
EOF
save_default_entry | sed -e "s/^/\t/"
if [ -z "${prepare_boot_cache}" ]; then
prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")"
fi
printf '%s\n' "${prepare_boot_cache}"
cat << EOF
linux ${LKERNEL} ${LPARAMS}
EOF
if [ -n "${LINITRD}" ] ; then
cat << EOF
initrd ${LINITRD}
EOF
fi
cat << EOF
}
EOF
done
;;
macosx)
OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
osx_entry xnu_kernel 32
osx_entry xnu_kernel64 64
;;
hurd)
cat << EOF
menuentry "${LONGNAME} (on ${DEVICE})" {
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
grub_device="`${grub_probe} --device ${DEVICE} --target=drive`"
mach_device="`echo "${grub_device}" | tr -d '()' | tr , s`"
grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`"
case "${grub_fs}" in
*fs) hurd_fs="${grub_fs}" ;;
*) hurd_fs="${grub_fs}fs" ;;
esac
cat << EOF
multiboot /boot/gnumach.gz root=device:${mach_device}
module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\
--multiboot-command-line='\${kernel-command-line}' \\
--host-priv-port='\${host-port}' \\
--device-master-port='\${device-port}' \\
--exec-server-task='\${exec-task}' -T typed '\${root}' \\
'\$(task-create)' '\$(task-resume)'
module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
}
EOF
;;
*)
echo " ${LONGNAME} is not yet supported by grub-mkconfig." >&2
;;
esac
done

5
util/grub.d/40_custom.in Normal file
View file

@ -0,0 +1,5 @@
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/* hostfs.c - Dummy filesystem to provide access to the hosts filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright (C) 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
@ -16,17 +16,18 @@
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#define _BSD_SOURCE
#include <grub/fs.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/util/misc.h>
#include <dirent.h>
#include <stdio.h>
#ifndef DT_DIR
/* dirent.d_type is a BSD extension, not part of POSIX */
#include <sys/stat.h>
#include <string.h>
@ -51,11 +52,11 @@ is_dir (const char *path, const char *name)
return 0;
return S_ISDIR (st.st_mode);
}
#endif
static grub_err_t
grub_hostfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, int dir))
grub_hostfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
DIR *dir;
@ -71,16 +72,16 @@ grub_hostfs_dir (grub_device_t device, const char *path,
while (1)
{
struct dirent *de;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
de = readdir (dir);
if (! de)
break;
#ifdef DT_DIR
hook (de->d_name, de->d_type == DT_DIR);
#else
hook (de->d_name, is_dir (path, de->d_name));
#endif
info.dir = !! is_dir (path, de->d_name);
hook (de->d_name, &info);
}
closedir (dir);
@ -94,15 +95,19 @@ grub_hostfs_open (struct grub_file *file, const char *name)
{
FILE *f;
f = fopen (name, "r");
f = fopen (name, "rb");
if (! f)
return grub_error (GRUB_ERR_BAD_FILENAME,
"can't open `%s'", name);
file->data = f;
fseek (f, 0, SEEK_END);
file->size = ftell (f);
fseek (f, 0, SEEK_SET);
#ifdef __MINGW32__
file->size = grub_util_get_disk_size (name);
#else
fseeko (f, 0, SEEK_END);
file->size = ftello (f);
fseeko (f, 0, SEEK_SET);
#endif
return GRUB_ERR_NONE;
}
@ -113,7 +118,7 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len)
FILE *f;
f = (FILE *) file->data;
fseek (f, file->offset, SEEK_SET);
fseeko (f, file->offset, SEEK_SET);
int s = fread (buf, 1, len, f);
return s;
@ -151,14 +156,12 @@ static struct grub_fs grub_hostfs_fs =
void
grub_hostfs_init (void)
GRUB_MOD_INIT(hostfs)
{
grub_fs_register (&grub_hostfs_fs);
}
void
grub_hostfs_fini (void)
GRUB_MOD_FINI(hostfs)
{
grub_fs_unregister (&grub_hostfs_fs);
}

View file

@ -0,0 +1,22 @@
#!/bin/sh
#
# 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/>.
if [ x$1 == x ]; then
echo "Filename required".
fi
ioreg -lw0 -p IODeviceTree -n efi -r -x |grep device-properties | sed 's/.*<//;s/>.*//;' | xxd -r -p > $1

View file

@ -29,11 +29,13 @@ PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
target_cpu=@target_cpu@
platform=@platform@
host_os=@host_os@
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | 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}`
grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
rootdir=
grub_prefix=`echo /boot/grub | sed ${transform}`
modules=
@ -178,6 +180,10 @@ for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
cp -f $file ${grubdir} || exit 1
done
if ! test -f ${grubdir}/grubenv; then
$grub_editenv ${grubdir}/grubenv create
fi
# Create the core image. First, auto-detect the filesystem module.
fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
if test "x$fs_module" = xfat; then :; else
@ -193,8 +199,8 @@ partmap_module=`$grub_probe --target=partmap --device-map=${device_map} ${grubdi
# Device abstraction module, if any (lvm, raid).
devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`
# _chain is often useful
modules="$modules $fs_module $partmap_module $devabstraction_module _chain"
# The order in this list is critical. Be careful when modifying it.
modules="$modules $fs_module $partmap_module $devabstraction_module"
$grub_mkimage --output=${grubdir}/grub.efi $modules || exit 1

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007 Free Software Foundation, Inc.
* Copyright (C) 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
@ -30,17 +30,24 @@
#include <grub/kernel.h>
#include <grub/efi/pe32.h>
#include <grub/machine/kernel.h>
#include "progname.h"
#if GRUB_TARGET_WORDSIZE == 32
# define grub_le_to_cpu(val) grub_le_to_cpu32(val)
#elif GRUB_TARGET_WORDSIZE == 64
# define grub_le_to_cpu(val) grub_le_to_cpu64(val)
#endif
static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
static inline Elf32_Addr
align_address (Elf32_Addr addr, unsigned alignment)
static inline Elf_Addr
align_address (Elf_Addr addr, unsigned alignment)
{
return (addr + alignment - 1) & ~(alignment - 1);
}
static inline Elf32_Addr
align_pe32_section (Elf32_Addr addr)
static inline Elf_Addr
align_pe32_section (Elf_Addr addr)
{
return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT);
}
@ -48,26 +55,22 @@ align_pe32_section (Elf32_Addr addr)
/* Read the whole kernel image. Return the pointer to a read image,
and store the size in bytes in *SIZE. */
static char *
read_kernel_module (const char *dir, char *prefix, size_t *size)
read_kernel_image (const char *dir, size_t *size)
{
char *kernel_image;
char *kernel_path;
kernel_path = grub_util_get_path (dir, "kernel.mod");
kernel_path = grub_util_get_path (dir, "kernel.img");
*size = grub_util_get_image_size (kernel_path);
kernel_image = grub_util_read_image (kernel_path);
free (kernel_path);
if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
grub_util_error ("prefix too long");
strcpy (kernel_image + 0x34 + GRUB_KERNEL_MACHINE_PREFIX, prefix);
return kernel_image;
}
/* Return if the ELF header is valid. */
static int
check_elf_header (Elf32_Ehdr *e, size_t size)
check_elf_header (Elf_Ehdr *e, size_t size)
{
if (size < sizeof (*e)
|| e->e_ident[EI_MAG0] != ELFMAG0
@ -76,9 +79,11 @@ check_elf_header (Elf32_Ehdr *e, size_t size)
|| e->e_ident[EI_MAG3] != ELFMAG3
|| e->e_ident[EI_VERSION] != EV_CURRENT
|| e->e_version != grub_cpu_to_le32 (EV_CURRENT)
|| e->e_ident[EI_CLASS] != ELFCLASS32
|| ((e->e_ident[EI_CLASS] != ELFCLASS32) &&
(e->e_ident[EI_CLASS] != ELFCLASS64))
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|| e->e_machine != grub_cpu_to_le16 (EM_386))
|| ((e->e_machine != grub_cpu_to_le16 (EM_386)) &&
(e->e_machine != grub_cpu_to_le16 (EM_X86_64))))
return 0;
return 1;
@ -87,7 +92,7 @@ check_elf_header (Elf32_Ehdr *e, size_t size)
/* Return the starting address right after the header,
aligned by the section alignment. Allocate 4 section tables for
.text, .data, .reloc, and mods. */
static Elf32_Addr
static Elf_Addr
get_starting_section_address (void)
{
return align_pe32_section (sizeof (struct grub_pe32_header)
@ -97,7 +102,7 @@ get_starting_section_address (void)
/* Determine if this section is a text section. Return false if this
section is not allocated. */
static int
is_text_section (Elf32_Shdr *s)
is_text_section (Elf_Shdr *s)
{
return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
== grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
@ -107,7 +112,7 @@ is_text_section (Elf32_Shdr *s)
BSS is also a data section, since the converter initializes BSS
when producing PE32 to avoid a bug in EFI implementations. */
static int
is_data_section (Elf32_Shdr *s)
is_data_section (Elf_Shdr *s)
{
return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
&& ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
@ -116,15 +121,15 @@ is_data_section (Elf32_Shdr *s)
/* Locate section addresses by merging code sections and data sections
into .text and .data, respectively. Return the array of section
addresses. */
static Elf32_Addr *
locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
Elf32_Half num_sections, const char *strtab)
static Elf_Addr *
locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
Elf_Half num_sections, const char *strtab)
{
int i;
Elf32_Addr current_address;
Elf32_Addr *section_addresses;
Elf32_Shdr *s;
Elf_Addr current_address;
Elf_Addr *section_addresses;
Elf_Shdr *s;
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
@ -133,15 +138,15 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
/* .text */
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_text_section (s))
{
Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
current_address = align_address (current_address, align);
grub_util_info ("locating the section %s at 0x%x",
name, current_address);
section_addresses[i] = current_address;
@ -153,15 +158,15 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
/* .data */
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_data_section (s))
{
Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
current_address = align_address (current_address, align);
grub_util_info ("locating the section %s at 0x%x",
name, current_address);
section_addresses[i] = current_address;
@ -172,16 +177,16 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
}
/* Return the symbol table section, if any. */
static Elf32_Shdr *
find_symtab_section (Elf32_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections)
static Elf_Shdr *
find_symtab_section (Elf_Shdr *sections,
Elf_Half section_entsize, Elf_Half num_sections)
{
int i;
Elf32_Shdr *s;
Elf_Shdr *s;
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
return s;
@ -190,12 +195,12 @@ find_symtab_section (Elf32_Shdr *sections,
/* Return the address of the string table. */
static const char *
find_strtab (Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize)
find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
{
Elf32_Shdr *s;
Elf_Shdr *s;
char *strtab;
s = (Elf32_Shdr *) ((char *) sections
s = (Elf_Shdr *) ((char *) sections
+ grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
return strtab;
@ -203,41 +208,45 @@ find_strtab (Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize)
/* Relocate symbols; note that this function overwrites the symbol table.
Return the address of a start symbol. */
static Elf32_Addr
relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
Elf32_Shdr *symtab_section, Elf32_Addr *section_addresses,
Elf32_Half section_entsize, Elf32_Half num_sections)
static Elf_Addr
relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections)
{
Elf32_Word symtab_size, sym_size, num_syms;
Elf32_Off symtab_offset;
Elf32_Addr start_address = 0;
Elf32_Sym *sym;
Elf32_Word i;
Elf32_Shdr *strtab_section;
Elf_Word symtab_size, sym_size, num_syms;
Elf_Off symtab_offset;
Elf_Addr start_address = 0;
Elf_Sym *sym;
Elf_Word i;
Elf_Shdr *strtab_section;
const char *strtab;
strtab_section
= (Elf32_Shdr *) ((char *) sections
= (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (symtab_section->sh_link)
* section_entsize));
strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
symtab_size = grub_le_to_cpu32 (symtab_section->sh_size);
sym_size = grub_le_to_cpu32 (symtab_section->sh_entsize);
symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
num_syms = symtab_size / sym_size;
for (i = 0, sym = (Elf32_Sym *) ((char *) e + symtab_offset);
for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
i < num_syms;
i++, sym = (Elf32_Sym *) ((char *) sym + sym_size))
i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
{
Elf32_Section index;
Elf_Section index;
const char *name;
name = strtab + grub_le_to_cpu32 (sym->st_name);
index = grub_le_to_cpu16 (sym->st_shndx);
if (index == STN_UNDEF)
if (index == STN_ABS)
{
continue;
}
else if ((index == STN_UNDEF))
{
if (sym->st_name)
grub_util_error ("undefined symbol %s", name);
@ -246,7 +255,7 @@ relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
}
else if (index >= num_sections)
grub_util_error ("section %d does not exist", index);
sym->st_value = (grub_le_to_cpu32 (sym->st_value)
+ section_addresses[index]);
grub_util_info ("locating %s at 0x%x", name, sym->st_value);
@ -260,22 +269,22 @@ relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
}
/* Return the address of a symbol at the index I in the section S. */
static Elf32_Addr
get_symbol_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Word i)
static Elf_Addr
get_symbol_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i)
{
Elf32_Sym *sym;
sym = (Elf32_Sym *) ((char *) e
Elf_Sym *sym;
sym = (Elf_Sym *) ((char *) e
+ grub_le_to_cpu32 (s->sh_offset)
+ i * grub_le_to_cpu32 (s->sh_entsize));
return sym->st_value;
}
/* Return the address of a modified value. */
static Elf32_Addr
get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset)
static Elf_Addr *
get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
{
return (Elf32_Addr) e + grub_le_to_cpu32 (s->sh_offset) + offset;
return (Elf_Addr *) ((char *) e + grub_le_to_cpu32 (s->sh_offset) + offset);
}
/* Deal with relocation information. This function relocates addresses
@ -283,34 +292,35 @@ get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset)
addresses can be fully resolved. Absolute addresses must be relocated
again by a PE32 relocator when loaded. */
static void
relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
Elf32_Addr *section_addresses,
Elf32_Half section_entsize, Elf32_Half num_sections,
relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
Elf32_Half i;
Elf32_Shdr *s;
Elf_Half i;
Elf_Shdr *s;
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
(s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{
Elf32_Rel *r;
Elf32_Word rtab_size, r_size, num_rs;
Elf32_Off rtab_offset;
Elf32_Shdr *symtab_section;
Elf32_Word target_section_index;
Elf32_Addr target_section_addr;
Elf32_Shdr *target_section;
Elf32_Word j;
Elf_Rela *r;
Elf_Word rtab_size, r_size, num_rs;
Elf_Off rtab_offset;
Elf_Shdr *symtab_section;
Elf_Word target_section_index;
Elf_Addr target_section_addr;
Elf_Shdr *target_section;
Elf_Word j;
symtab_section = (Elf32_Shdr *) ((char *) sections
symtab_section = (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (s->sh_link)
* section_entsize));
target_section_index = grub_le_to_cpu32 (s->sh_info);
target_section_addr = section_addresses[target_section_index];
target_section = (Elf32_Shdr *) ((char *) sections
target_section = (Elf_Shdr *) ((char *) sections
+ (target_section_index
* section_entsize));
@ -323,31 +333,35 @@ relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
rtab_offset = grub_le_to_cpu32 (s->sh_offset);
num_rs = rtab_size / r_size;
for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
j < num_rs;
j++, r = (Elf32_Rel *) ((char *) r + r_size))
j++, r = (Elf_Rela *) ((char *) r + r_size))
{
Elf32_Word info;
Elf32_Addr offset;
Elf32_Addr sym_addr;
Elf32_Addr *target;
offset = grub_le_to_cpu32 (r->r_offset);
target = (Elf32_Addr *) get_target_address (e, target_section,
offset);
info = grub_le_to_cpu32 (r->r_info);
sym_addr = get_symbol_address (e, symtab_section,
ELF32_R_SYM (info));
Elf_Addr info;
Elf_Addr offset;
Elf_Addr sym_addr;
Elf_Addr *target;
Elf_Addr addend;
switch (ELF32_R_TYPE (info))
offset = grub_le_to_cpu (r->r_offset);
target = get_target_address (e, target_section, offset);
info = grub_le_to_cpu (r->r_info);
sym_addr = get_symbol_address (e, symtab_section,
ELF_R_SYM (info));
addend = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
r->r_addend : 0;
switch (ELF_R_TYPE (info))
{
#if GRUB_TARGET_SIZEOF_VOID_P == 4
case R_386_NONE:
break;
case R_386_32:
/* This is absolute. */
*target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
+ sym_addr);
+ addend + sym_addr);
grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
*target, offset);
break;
@ -355,15 +369,50 @@ relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
case R_386_PC32:
/* This is relative. */
*target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
+ sym_addr
+ addend + sym_addr
- target_section_addr - offset);
grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
*target, offset);
break;
#else
case R_X86_64_NONE:
break;
case R_X86_64_64:
*target = grub_cpu_to_le64 (grub_le_to_cpu64 (*target)
+ addend + sym_addr);
grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
*target, offset);
break;
case R_X86_64_PC32:
{
grub_uint32_t *t32 = (grub_uint32_t *) target;
*t32 = grub_cpu_to_le64 (grub_le_to_cpu32 (*t32)
+ addend + sym_addr
- target_section_addr - offset);
grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
*t32, offset);
break;
}
case R_X86_64_32:
case R_X86_64_32S:
{
grub_uint32_t *t32 = (grub_uint32_t *) target;
*t32 = grub_cpu_to_le64 (grub_le_to_cpu32 (*t32)
+ addend + sym_addr);
grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
*t32, offset);
break;
}
#endif
default:
grub_util_error ("unknown relocation type %d",
ELF32_R_TYPE (info));
ELF_R_TYPE (info));
break;
}
}
@ -382,13 +431,13 @@ write_padding (FILE *out, size_t size)
/* Add a PE32's fixup entry for a relocation. Return the resulting address
after having written to the file OUT. */
Elf32_Addr
Elf_Addr
add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
Elf32_Addr addr, int flush, Elf32_Addr current_address,
Elf_Addr addr, int flush, Elf_Addr current_address,
FILE *out)
{
struct grub_pe32_fixup_block *b = *block;
/* First, check if it is necessary to write out the current block. */
if (b)
{
@ -400,10 +449,10 @@ add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
{
/* Add as much padding as necessary to align the address
with a section boundary. */
Elf32_Addr next_address;
Elf_Addr next_address;
unsigned padding_size;
size_t index;
next_address = current_address + b->block_size;
padding_size = ((align_pe32_section (next_address)
- next_address)
@ -446,7 +495,7 @@ add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
{
grub_uint16_t entry;
size_t index;
/* If not allocated yet, allocate a block with enough entries. */
if (! b)
{
@ -473,11 +522,11 @@ add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
}
/* Write out zeros to make space for the header. */
static Elf32_Addr
static Elf_Addr
make_header_space (FILE *out)
{
Elf32_Addr addr;
Elf_Addr addr;
addr = get_starting_section_address ();
write_padding (out, addr);
@ -485,26 +534,26 @@ make_header_space (FILE *out)
}
/* Write text sections. */
static Elf32_Addr
write_text_sections (FILE *out, Elf32_Addr current_address,
Elf32_Ehdr *e, Elf32_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections,
static Elf_Addr
write_text_sections (FILE *out, Elf_Addr current_address,
Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
Elf32_Half i;
Elf32_Shdr *s;
Elf32_Addr addr;
Elf_Half i;
Elf_Shdr *s;
Elf_Addr addr;
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_text_section (s))
{
Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
{
addr = align_address (current_address, align);
@ -516,13 +565,13 @@ write_text_sections (FILE *out, Elf32_Addr current_address,
current_address = addr;
}
}
grub_util_info ("writing the text section %s at 0x%x",
name, current_address);
if (fwrite ((char *) e + offset, size, 1, out) != 1)
grub_util_error ("write failed");
current_address += size;
}
@ -533,31 +582,31 @@ write_text_sections (FILE *out, Elf32_Addr current_address,
addr - current_address);
write_padding (out, addr - current_address);
}
return addr;
}
/* Write data sections. */
static Elf32_Addr
write_data_sections (FILE *out, Elf32_Addr current_address,
Elf32_Ehdr *e, Elf32_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections,
static Elf_Addr
write_data_sections (FILE *out, Elf_Addr current_address,
Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
Elf32_Half i;
Elf32_Shdr *s;
Elf32_Addr addr;
Elf_Half i;
Elf_Shdr *s;
Elf_Addr addr;
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_data_section (s))
{
Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
{
addr = align_address (current_address, align);
@ -569,19 +618,19 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
current_address = addr;
}
}
grub_util_info ("writing the data section %s at 0x%x",
name, current_address);
if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS))
write_padding (out, size);
else
if (fwrite ((char *) e + offset, size, 1, out) != 1)
grub_util_error ("write failed");
current_address += size;
}
addr = align_pe32_section (current_address);
if (addr != current_address)
{
@ -589,23 +638,25 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
addr - current_address);
write_padding (out, addr - current_address);
}
return addr;
}
/* Write modules. */
static Elf32_Addr
make_mods_section (FILE *out, Elf32_Addr current_address,
static Elf_Addr
make_mods_section (FILE *out, Elf_Addr current_address,
const char *dir, char *mods[])
{
struct grub_util_path_list *path_list;
grub_size_t total_module_size;
struct grub_util_path_list *p;
struct grub_module_info modinfo;
Elf32_Addr addr;
Elf_Addr addr;
memset (&modinfo, 0, sizeof (modinfo));
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
total_module_size = sizeof (struct grub_module_info);
for (p = path_list; p; p = p->next)
{
@ -627,13 +678,15 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
struct grub_module_header header;
size_t mod_size;
char *mod_image;
memset (&header, 0, sizeof (header));
grub_util_info ("adding module %s", p->name);
mod_size = grub_util_get_image_size (p->name);
header.offset = grub_cpu_to_le32 (sizeof (header));
header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
header.type = OBJ_TYPE_ELF;
header.size = grub_host_to_target32 (mod_size + sizeof (header));
mod_image = grub_util_read_image (p->name);
if (fwrite (&header, sizeof (header), 1, out) != 1
@ -642,7 +695,7 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
free (mod_image);
}
for (p = path_list; p; )
{
struct grub_util_path_list *q;
@ -651,9 +704,9 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
free (p);
p = q;
}
current_address += total_module_size;
addr = align_pe32_section (current_address);
if (addr != current_address)
{
@ -666,51 +719,53 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
}
/* Make a .reloc section. */
static Elf32_Addr
make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
Elf32_Addr *section_addresses, Elf32_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections,
static Elf_Addr
make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
Elf_Addr *section_addresses, Elf_Shdr *sections,
Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
Elf32_Half i;
Elf32_Shdr *s;
Elf_Half i;
Elf_Shdr *s;
struct grub_pe32_fixup_block *fixup_block = 0;
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
(s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{
Elf32_Rel *r;
Elf32_Word rtab_size, r_size, num_rs;
Elf32_Off rtab_offset;
Elf32_Addr section_address;
Elf32_Word j;
Elf_Rel *r;
Elf_Word rtab_size, r_size, num_rs;
Elf_Off rtab_offset;
Elf_Addr section_address;
Elf_Word j;
grub_util_info ("translating the relocation section %s",
strtab + grub_le_to_cpu32 (s->sh_name));
rtab_size = grub_le_to_cpu32 (s->sh_size);
r_size = grub_le_to_cpu32 (s->sh_entsize);
rtab_offset = grub_le_to_cpu32 (s->sh_offset);
num_rs = rtab_size / r_size;
section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
j < num_rs;
j++, r = (Elf32_Rel *) ((char *) r + r_size))
j++, r = (Elf_Rel *) ((char *) r + r_size))
{
Elf32_Word info;
Elf32_Addr offset;
Elf_Addr info;
Elf_Addr offset;
offset = grub_le_to_cpu32 (r->r_offset);
info = grub_le_to_cpu32 (r->r_info);
/* Necessary to relocate only absolute addresses. */
if (ELF32_R_TYPE (info) == R_386_32)
#if GRUB_TARGET_SIZEOF_VOID_P == 4
if (ELF_R_TYPE (info) == R_386_32)
{
Elf32_Addr addr;
Elf_Addr addr;
addr = section_address + offset;
grub_util_info ("adding a relocation entry for 0x%x", addr);
@ -719,6 +774,25 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
addr, 0, current_address,
out);
}
#else
if ((ELF_R_TYPE (info) == R_X86_64_32) ||
(ELF_R_TYPE (info) == R_X86_64_32S))
{
grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
}
else if (ELF_R_TYPE (info) == R_X86_64_64)
{
Elf_Addr addr;
addr = section_address + offset;
grub_util_info ("adding a relocation entry for 0x%llx", addr);
current_address = add_fixup_entry (&fixup_block,
GRUB_PE32_REL_BASED_DIR64,
addr,
0, current_address,
out);
}
#endif
}
}
@ -730,9 +804,9 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
/* Create the header. */
static void
make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
Elf32_Addr mods_address, Elf32_Addr reloc_address,
Elf32_Addr end_address, Elf32_Addr start_address)
make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
Elf_Addr mods_address, Elf_Addr reloc_address,
Elf_Addr end_address, Elf_Addr start_address)
{
struct grub_pe32_header header;
struct grub_pe32_coff_header *c;
@ -747,14 +821,22 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
/* The COFF file header. */
c = &header.coff_header;
#if GRUB_TARGET_SIZEOF_VOID_P == 4
c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
#else
c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64);
#endif
c->num_sections = grub_cpu_to_le16 (4);
c->time = grub_cpu_to_le32 (time (0));
c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
| GRUB_PE32_LINE_NUMS_STRIPPED
#if GRUB_TARGET_SIZEOF_VOID_P == 4
| GRUB_PE32_32BIT_MACHINE
#endif
| GRUB_PE32_LOCAL_SYMS_STRIPPED
| GRUB_PE32_32BIT_MACHINE);
| GRUB_PE32_DEBUG_STRIPPED);
/* The PE Optional header. */
o = &header.optional_header;
@ -764,14 +846,16 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
o->bss_size = 0;
o->entry_addr = grub_cpu_to_le32 (start_address);
o->code_base = grub_cpu_to_le32 (text_address);
#if GRUB_TARGET_SIZEOF_VOID_P == 4
o->data_base = grub_cpu_to_le32 (data_address);
#endif
o->image_base = 0;
o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
o->image_size = grub_cpu_to_le32 (end_address);
o->header_size = grub_cpu_to_le32 (text_address);
o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
/* Do these really matter? */
o->stack_reserve_size = grub_cpu_to_le32 (0x10000);
o->stack_commit_size = grub_cpu_to_le32 (0x10000);
@ -779,7 +863,7 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
o->heap_commit_size = grub_cpu_to_le32 (0x10000);
o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address);
o->base_relocation_table.size = grub_cpu_to_le32 (end_address
- reloc_address);
@ -829,7 +913,7 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
| GRUB_PE32_SCN_MEM_READ);
/* Write them out. */
if (fseek (out, 0, SEEK_SET) < 0)
if (fseeko (out, 0, SEEK_SET) < 0)
grub_util_error ("seek failed");
if (fwrite (&header, sizeof (header), 1, out) != 1
@ -847,41 +931,58 @@ convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
char *kernel_image;
size_t kernel_size;
const char *strtab;
Elf32_Ehdr *e;
Elf32_Shdr *sections;
Elf32_Off section_offset;
Elf32_Half section_entsize;
Elf32_Half num_sections;
Elf32_Addr *section_addresses;
Elf32_Shdr *symtab_section;
Elf32_Addr start_address;
Elf32_Addr text_address, data_address, reloc_address, mods_address;
Elf32_Addr end_address;
Elf_Ehdr *e;
Elf_Shdr *sections;
Elf_Off section_offset;
Elf_Half section_entsize;
Elf_Half num_sections;
Elf_Addr *section_addresses;
Elf_Shdr *symtab_section;
Elf_Addr start_address;
Elf_Addr text_address, data_address, reloc_address, mods_address;
Elf_Addr end_address;
Elf_Shdr *s;
int i;
/* Get the kernel image and check the format. */
kernel_image = read_kernel_module (dir, prefix, &kernel_size);
e = (Elf32_Ehdr *) kernel_image;
kernel_image = read_kernel_image (dir, &kernel_size);
e = (Elf_Ehdr *) kernel_image;
if (! check_elf_header (e, kernel_size))
grub_util_error ("invalid ELF header");
section_offset = grub_cpu_to_le32 (e->e_shoff);
section_entsize = grub_cpu_to_le16 (e->e_shentsize);
num_sections = grub_cpu_to_le16 (e->e_shnum);
if (kernel_size < section_offset + section_entsize * num_sections)
grub_util_error ("invalid ELF format");
sections = (Elf32_Shdr *) (kernel_image + section_offset);
sections = (Elf_Shdr *) (kernel_image + section_offset);
strtab = find_strtab (e, sections, section_entsize);
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_text_section (s))
{
Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
grub_util_error ("prefix too long");
strcpy (kernel_image + offset + GRUB_KERNEL_MACHINE_PREFIX, prefix);
break;
}
/* Relocate sections then symbols in the virtual address space. */
section_addresses = locate_sections (sections, section_entsize,
num_sections, strtab);
symtab_section = find_symtab_section (sections,
section_entsize, num_sections);
if (! symtab_section)
grub_util_error ("no symbol table");
start_address = relocate_symbols (e, sections, symtab_section,
section_addresses, section_entsize,
num_sections);
@ -928,22 +1029,22 @@ static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
Usage: %s -o FILE [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\
-o, --output=FILE output a generated image to FILE\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-p, --prefix=DIR set grub_prefix directory [default=%s]\n\
-o, --output=FILE output a generated image to FILE\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);
", program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
exit (status);
}
@ -956,7 +1057,7 @@ main (int argc, char *argv[])
char *dir = NULL;
char *prefix = NULL;
progname = "grub-mkimage";
program_name = "grub-mkimage";
while (1)
{

View file

@ -1,31 +0,0 @@
/* get_disk_name.c */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007 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>
char *
grub_util_get_disk_name (int disk, char *name)
{
char *p;
p = xmalloc (16);
sprintf (p, "hd%d", disk);
return p;
}

View file

@ -1,7 +1,7 @@
/* grub-mkimage.c - make a bootable image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 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
@ -22,6 +22,7 @@
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <grub/machine/memory.h>
#include <grub/i18n.h>
#include <grub/kernel.h>
#include <grub/disk.h>
#include <grub/util/misc.h>
@ -32,58 +33,74 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define _GNU_SOURCE 1
#include <getopt.h>
#if defined(HAVE_LZO_LZO1X_H)
# include <lzo/lzo1x.h>
#elif defined(HAVE_LZO1X_H)
# include <lzo1x.h>
#endif
#include "progname.h"
#ifdef ENABLE_LZMA
#include <grub/lib/LzmaEnc.h>
static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); }
static void SzFree(void *p, void *address) { p = p; free(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void
compress_kernel (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size)
{
lzo_uint size;
char *wrkmem;
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
CLzmaEncProps props;
unsigned char out_props[5];
size_t out_props_size = 5;
LzmaEncProps_Init(&props);
props.dictSize = 1 << 16;
props.lc = 3;
props.lp = 0;
props.pb = 2;
props.numThreads = 1;
if (kernel_size < GRUB_KERNEL_MACHINE_RAW_SIZE)
grub_util_error ("the core image is too small");
if (lzo_init () != LZO_E_OK)
grub_util_error ("cannot initialize LZO");
*core_img = xmalloc (kernel_size + kernel_size / 64 + 16 + 3);
wrkmem = xmalloc (LZO1X_999_MEM_COMPRESS);
grub_util_error (_("the core image is too small"));
*core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, GRUB_KERNEL_MACHINE_RAW_SIZE);
grub_util_info ("compressing the core image");
if (lzo1x_999_compress ((const lzo_byte *) (kernel_img
+ GRUB_KERNEL_MACHINE_RAW_SIZE),
kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE,
(lzo_byte *) (*core_img
+ GRUB_KERNEL_MACHINE_RAW_SIZE),
&size, wrkmem)
!= LZO_E_OK)
grub_util_error ("cannot compress the kernel image");
free (wrkmem);
*core_size = kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE;
if (LzmaEncode((unsigned char *) *core_img + GRUB_KERNEL_MACHINE_RAW_SIZE,
core_size,
(unsigned char *) kernel_img + GRUB_KERNEL_MACHINE_RAW_SIZE,
kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE,
&props, out_props, &out_props_size,
0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
grub_util_error (_("cannot compress the kernel image"));
*core_size = (size_t) size + GRUB_KERNEL_MACHINE_RAW_SIZE;
*core_size += GRUB_KERNEL_MACHINE_RAW_SIZE;
}
#else /* No lzma compression */
static void
generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *memdisk_path)
compress_kernel (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size)
{
*core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size);
*core_size = kernel_size;
}
#endif /* No lzma compression */
static void
generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
char *memdisk_path, char *config_path)
{
grub_addr_t module_addr = 0;
char *kernel_img, *boot_img, *core_img;
size_t kernel_size, boot_size, total_module_size, core_size, memdisk_size = 0;
size_t kernel_size, boot_size, total_module_size, core_size;
size_t memdisk_size = 0, config_size = 0;
char *kernel_path, *boot_path;
unsigned num;
size_t offset;
struct grub_util_path_list *path_list, *p, *next;
struct grub_module_info *modinfo;
@ -94,27 +111,37 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *me
kernel_size = grub_util_get_image_size (kernel_path);
total_module_size = sizeof (struct grub_module_info);
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);
}
if (config_path)
{
config_size = grub_util_get_image_size (config_path) + 1;
grub_util_info ("the size of config file is 0x%x", config_size);
total_module_size += config_size + sizeof (struct grub_module_header);
}
for (p = path_list; p; p = p->next)
total_module_size += (grub_util_get_image_size (p->name)
+ sizeof (struct grub_module_header));
grub_util_info ("the total module size is 0x%x", total_module_size);
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);
}
kernel_img = xmalloc (kernel_size + total_module_size + memdisk_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");
grub_util_error (_("prefix is 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);
memset (modinfo, 0, sizeof (struct grub_module_info));
modinfo->magic = GRUB_MODULE_MAGIC;
modinfo->offset = sizeof (struct grub_module_info);
modinfo->size = total_module_size;
@ -126,10 +153,11 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *me
size_t mod_size;
mod_size = grub_util_get_image_size (p->name);
header = (struct grub_module_header *) (kernel_img + offset);
header->offset = grub_cpu_to_le32 (sizeof (*header));
header->size = grub_cpu_to_le32 (mod_size + sizeof (*header));
memset (header, 0, sizeof (struct grub_module_header));
header->type = OBJ_TYPE_ELF;
header->size = grub_host_to_target32 (mod_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (p->name, kernel_img + offset);
@ -138,54 +166,133 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *me
if (memdisk_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = OBJ_TYPE_MEMDISK;
header->size = grub_host_to_target32 (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 + memdisk_size,
if (config_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = OBJ_TYPE_CONFIG;
header->size = grub_host_to_target32 (config_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (config_path, kernel_img + offset);
offset += config_size;
*(kernel_img + offset - 1) = 0;
}
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_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);
if (num > 0xffff)
grub_util_error ("the core image is too big");
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);
/* i386 is a little endian architecture. */
*((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
- GRUB_BOOT_MACHINE_LIST_SIZE + 8))
= grub_cpu_to_le16 (num);
#if defined(GRUB_MACHINE_PCBIOS)
{
unsigned num;
num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
if (num > 0xffff)
grub_util_error (_("the core image is too big"));
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 size must be %u bytes"), GRUB_DISK_SECTOR_SIZE);
boot_img = grub_util_read_image (boot_path);
{
struct grub_boot_blocklist *block;
block = (struct grub_boot_blocklist *) (boot_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof (*block));
block->len = grub_host_to_target16 (num);
grub_util_write_image (boot_img, boot_size, out);
free (boot_img);
free (boot_path);
module_addr = (path_list
? (GRUB_BOOT_MACHINE_KERNEL_ADDR + GRUB_DISK_SECTOR_SIZE
+ kernel_size)
: 0);
/* This is filled elsewhere. Verify it just in case. */
assert (block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE >> 4)));
}
grub_util_write_image (boot_img, boot_size, out);
free (boot_img);
free (boot_path);
}
#elif defined(GRUB_MACHINE_QEMU)
{
char *rom_img;
size_t rom_size;
grub_util_info ("the first module address is 0x%x", module_addr);
boot_path = grub_util_get_path (dir, "boot.img");
boot_size = grub_util_get_image_size (boot_path);
boot_img = grub_util_read_image (boot_path);
/* Rom sizes must be 64k-aligned. */
rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024);
rom_img = xmalloc (rom_size);
memset (rom_img, 0, rom_size);
*((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR))
= grub_cpu_to_le32 ((grub_uint32_t) -rom_size);
memcpy (rom_img, core_img, core_size);
*((grub_int32_t *) (boot_img + GRUB_BOOT_MACHINE_CORE_ENTRY_ADDR))
= grub_cpu_to_le32 ((grub_uint32_t) -rom_size);
memcpy (rom_img + rom_size - boot_size, boot_img, boot_size);
free (core_img);
core_img = rom_img;
core_size = rom_size;
free (boot_img);
free (boot_path);
}
#endif
#ifdef GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE))
= grub_cpu_to_le32 (total_module_size);
#endif
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
= grub_cpu_to_le32 (kernel_size);
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE))
= grub_cpu_to_le32 (memdisk_size);
#ifdef GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
= grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
#endif
#if defined(GRUB_KERNEL_MACHINE_INSTALL_DOS_PART) && defined(GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
/* If we included a drive in our prefix, let GRUB know it doesn't have to
prepend the drive told by BIOS. */
if (prefix[0] == '(')
{
*((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART))
= grub_cpu_to_le32 (-2);
*((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART))
= grub_cpu_to_le32 (-2);
}
#endif
#ifdef GRUB_MACHINE_PCBIOS
if (GRUB_KERNEL_MACHINE_LINK_ADDR + core_size > GRUB_MEMORY_MACHINE_UPPER)
grub_util_error (_("core image is too big (%p > %p)"),
GRUB_KERNEL_MACHINE_LINK_ADDR + core_size, GRUB_MEMORY_MACHINE_UPPER);
#endif
if (core_size > GRUB_MEMORY_MACHINE_UPPER - GRUB_MEMORY_MACHINE_LINK_ADDR)
grub_util_error ("Core image is too big (%p > %p)\n", core_size,
GRUB_MEMORY_MACHINE_UPPER - GRUB_MEMORY_MACHINE_LINK_ADDR);
grub_util_write_image (core_img, core_size, out);
free (kernel_img);
free (core_img);
@ -207,6 +314,7 @@ static struct option options[] =
{"directory", required_argument, 0, 'd'},
{"prefix", required_argument, 0, 'p'},
{"memdisk", required_argument, 0, 'm'},
{"config", required_argument, 0, 'c'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
@ -218,23 +326,24 @@ static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name);
else
printf ("\
Usage: grub-mkimage [OPTION]... [MODULES]\n\
printf (_("\
Usage: %s [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\
-c, --config=FILE embed FILE as boot config\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);
"), program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
exit (status);
}
@ -246,13 +355,16 @@ main (int argc, char *argv[])
char *dir = NULL;
char *prefix = NULL;
char *memdisk = NULL;
char *config = NULL;
FILE *fp = stdout;
progname = "grub-mkimage";
set_program_name (argv[0]);
grub_util_init_nls ();
while (1)
{
int c = getopt_long (argc, argv, "d:p:m:o:hVv", options, 0);
int c = getopt_long (argc, argv, "d:p:m:c:o:hVv", options, 0);
if (c == -1)
break;
@ -262,7 +374,7 @@ main (int argc, char *argv[])
case 'o':
if (output)
free (output);
output = xstrdup (optarg);
break;
@ -278,6 +390,18 @@ main (int argc, char *argv[])
free (memdisk);
memdisk = xstrdup (optarg);
if (prefix)
free (prefix);
prefix = xstrdup ("(memdisk)/boot/grub");
break;
case 'c':
if (config)
free (config);
config = xstrdup (optarg);
break;
case 'h':
@ -309,10 +433,12 @@ main (int argc, char *argv[])
{
fp = fopen (output, "wb");
if (! fp)
grub_util_error ("cannot open %s", output);
grub_util_error (_("cannot open %s"), output);
free (output);
}
generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind, memdisk);
generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp,
argv + optind, memdisk, config);
fclose (fp);

View file

@ -1,7 +1,7 @@
/* grub-setup.c - make GRUB usable */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 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
@ -25,14 +25,19 @@
#include <grub/file.h>
#include <grub/fs.h>
#include <grub/partition.h>
#include <grub/pc_partition.h>
#include <grub/msdos_partition.h>
#include <grub/gpt_partition.h>
#include <grub/env.h>
#include <grub/util/biosdisk.h>
#include <grub/util/hostdisk.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <grub/term.h>
#include <grub/i18n.h>
#include <grub/util/raid.h>
#include <grub/util/lvm.h>
#include <grub/util/getroot.h>
static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
#include <grub_setup_init.h>
@ -43,7 +48,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <grub/util/getroot.h>
#include <assert.h>
#include "progname.h"
#define _GNU_SOURCE 1
#include <getopt.h>
@ -51,14 +57,6 @@
#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_uint16_t len;
grub_uint16_t segment;
} __attribute__ ((packed));
void
grub_putchar (int c)
{
@ -71,33 +69,32 @@ grub_getkey (void)
return -1;
}
grub_term_t
grub_term_get_current (void)
{
return 0;
}
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,
setup (const char *dir,
const char *boot_file, const char *core_file,
const char *root, const char *dest, int must_embed)
const char *root, const char *dest, int must_embed, int force, int fs_probe)
{
char *boot_path, *core_path;
char *boot_path, *core_path, *core_path_dev, *core_path_dev_full;
char *boot_img, *core_img;
size_t boot_size, core_size;
grub_uint16_t core_sectors;
grub_device_t root_dev, dest_dev;
const char *dest_partmap;
grub_uint8_t *boot_drive;
grub_disk_addr_t *kernel_sector;
grub_uint16_t *boot_drive_check;
struct boot_blocklist *first_block, *block;
struct grub_boot_blocklist *first_block, *block;
grub_int32_t *install_dos_part, *install_bsd_part;
char *install_prefix;
grub_int32_t dos_part, bsd_part;
char *tmp_img;
int i;
grub_disk_addr_t first_sector;
@ -106,38 +103,60 @@ setup (const char *prefix, const char *dir,
grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
grub_file_t file;
FILE *fp;
unsigned long first_start = ~0UL;
int able_to_embed = 1;
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 offset,
unsigned length);
auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset,
unsigned length);
auto int find_first_partition_start (grub_disk_t disk,
const grub_partition_t p);
int find_first_partition_start (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk,
const grub_partition_t p);
int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
{
struct grub_pc_partition *pcdata = p->data;
struct grub_msdos_partition *pcdata = p->data;
/* There's always an embed region, and it starts right after the MBR. */
embed_region.start = 1;
/* For its end offset, include as many dummy partitions as we can. */
if (! grub_msdos_partition_is_empty (pcdata->dos_type)
&& ! grub_msdos_partition_is_bsd (pcdata->dos_type)
&& embed_region.end > p->start)
embed_region.end = p->start;
if (! grub_pc_partition_is_empty (pcdata->dos_type)
&& ! grub_pc_partition_is_bsd (pcdata->dos_type)
&& first_start > p->start)
first_start = p->start;
return 0;
}
auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk,
const grub_partition_t p);
int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
{
struct grub_gpt_partentry *gptdata = p->data;
/* If there's an embed region, it is in a dedicated partition. */
if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16))
{
embed_region.start = p->start;
embed_region.end = p->start + p->len;
return 1;
}
return 0;
}
void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset,
unsigned length)
{
grub_util_info ("the 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");
grub_util_error (_("the first sector of the core file is not sector-aligned"));
first_sector = sector;
}
@ -145,13 +164,13 @@ setup (const char *prefix, const char *dir,
void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset,
unsigned length)
{
struct boot_blocklist *prev = block + 1;
struct grub_boot_blocklist *prev = block + 1;
grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x",
sector, offset, length, (unsigned) current_segment);
if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
grub_util_error ("Non-sector-aligned data is found in the core file");
grub_util_error (_("non-sector-aligned data is found in the core file"));
if (block != first_block
&& (grub_le_to_cpu64 (prev->start)
@ -165,60 +184,54 @@ setup (const char *prefix, const char *dir,
block--;
if (block->len)
grub_util_error ("The sectors of the core file are too fragmented");
grub_util_error (_("the sectors of the core file are too fragmented"));
}
last_length = length;
current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
}
/* 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",
grub_util_error (_("the size of `%s' is not %u"),
boot_path, GRUB_DISK_SECTOR_SIZE);
boot_img = grub_util_read_image (boot_path);
free (boot_path);
/* Set the addresses of BOOT_DRIVE, KERNEL_SECTOR and BOOT_DRIVE_CHECK. */
/* Set the addresses of variables in the boot image. */
boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE);
kernel_sector = (grub_disk_addr_t *) (boot_img
+ GRUB_BOOT_MACHINE_KERNEL_SECTOR);
boot_drive_check = (grub_uint16_t *) (boot_img
+ GRUB_BOOT_MACHINE_DRIVE_CHECK);
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);
grub_util_error (_("the size of `%s' is too small"), core_path);
else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE)
grub_util_error ("The size of `%s' is too large", core_path);
grub_util_error (_("the size of `%s' is too large"), 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));
first_block = (struct grub_boot_blocklist *) (core_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof (*block));
install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+ GRUB_KERNEL_MACHINE_INSTALL_DOS_PART);
install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+ GRUB_KERNEL_MACHINE_INSTALL_BSD_PART);
install_prefix = (core_img + GRUB_DISK_SECTOR_SIZE
+ GRUB_KERNEL_MACHINE_PREFIX);
/* Open the root device and the destination device. */
if (!must_embed)
{
root_dev = grub_device_open (root);
if (! root_dev)
grub_util_error ("%s", grub_errmsg);
}
root_dev = grub_device_open (root);
if (! root_dev)
grub_util_error ("%s", grub_errmsg);
dest_dev = grub_device_open (dest);
if (! dest_dev)
@ -233,6 +246,22 @@ setup (const char *prefix, const char *dir,
if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img))
grub_util_error ("%s", grub_errmsg);
if (dest_dev->disk->partition && fs_probe)
{
grub_fs_t fs;
fs = grub_fs_probe (dest_dev);
if (! fs)
grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
dest_dev->disk->name);
if (! fs->reserved_first_sector)
grub_util_error (_("%s appears to contain a %s filesystem which isn't known to "
"reserve space for DOS-style boot. Installing GRUB there could "
"result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
"by grub-setup (--skip-fs-probe disables this "
"check, use at your own risk)"), dest_dev->disk->name, fs->name);
}
/* Copy the possible DOS BPB. */
memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START,
tmp_img + GRUB_BOOT_MACHINE_BPB_START,
@ -245,118 +274,175 @@ setup (const char *prefix, const char *dir,
GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
free (tmp_img);
/* If DEST_DRIVE is a hard disk, enable the workaround, which is
for buggy BIOSes which don't pass boot drive correctly. Instead,
they pass 0x00 or 0x01 even when booted from 0x80. */
if (dest_dev->disk->id & 0x80)
/* Replace the jmp (2 bytes) with double nop's. */
*boot_drive_check = 0x9090;
/* If the destination device can have partitions and it is the MBR,
try to embed the core image into after the MBR. */
if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition)
/* If we hardcoded drive as part of prefix, we don't want to
override the current setting. */
if (*install_dos_part != -2)
{
grub_partition_iterate (dest_dev->disk, find_first_partition_start);
/* If there is enough space... */
if ((unsigned long) core_sectors + 1 <= first_start)
/* Embed information about the installed location. */
if (root_dev->disk->partition)
{
grub_util_info ("will embed the core image into after the MBR");
/* The first blocklist contains the whole sectors. */
first_block->start = grub_cpu_to_le64 (2);
first_block->len = grub_cpu_to_le16 (core_sectors - 1);
first_block->segment
= grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE >> 4));
/* Make sure that the second blocklist is a terminator. */
block = first_block - 1;
block->start = 0;
block->len = 0;
block->segment = 0;
/* Embed information about the installed location. */
if (must_embed)
*install_dos_part = *install_bsd_part = grub_cpu_to_le32 (-2);
else if (root_dev->disk->partition)
if (strcmp (root_dev->disk->partition->partmap->name,
"part_msdos") == 0)
{
if (strcmp (root_dev->disk->partition->partmap->name,
"pc_partition_map") == 0)
{
struct grub_pc_partition *pcdata =
root_dev->disk->partition->data;
*install_dos_part
= grub_cpu_to_le32 (pcdata->dos_part);
*install_bsd_part
= grub_cpu_to_le32 (pcdata->bsd_part);
}
else if (strcmp (root_dev->disk->partition->partmap->name,
"gpt_partition_map") == 0)
{
*install_dos_part = grub_cpu_to_le32 (root_dev->disk->partition->index);
*install_bsd_part = grub_cpu_to_le32 (-1);
}
else
grub_util_error ("No PC style partitions found");
struct grub_msdos_partition *pcdata =
root_dev->disk->partition->data;
dos_part = pcdata->dos_part;
bsd_part = pcdata->bsd_part;
}
else if (strcmp (root_dev->disk->partition->partmap->name,
"part_gpt") == 0)
{
dos_part = root_dev->disk->partition->index;
bsd_part = -1;
}
else
*install_dos_part = *install_bsd_part = grub_cpu_to_le32 (-1);
grub_util_info ("dos partition is %d, bsd partition is %d, prefix is %s",
grub_le_to_cpu32 (*install_dos_part),
grub_le_to_cpu32 (*install_bsd_part),
prefix);
strcpy (install_prefix, prefix);
/* Write the core image onto the disk. */
if (grub_disk_write (dest_dev->disk, 1, 0, core_size, core_img))
grub_util_error ("%s", grub_errmsg);
/* The boot image and the core image are on the same drive,
so there is no need to specify the boot drive explicitly. */
*boot_drive = 0xff;
*kernel_sector = grub_cpu_to_le64 (1);
/* Write the boot image onto the disk. */
if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE,
boot_img))
grub_util_error ("%s", grub_errmsg);
goto finish;
grub_util_error (_("no DOS-style partitions found"));
}
else
able_to_embed = 0;
dos_part = bsd_part = -1;
}
else
able_to_embed = 0;
{
dos_part = grub_le_to_cpu32 (*install_dos_part);
bsd_part = grub_le_to_cpu32 (*install_bsd_part);
}
grub_util_info ("dos partition is %d, bsd partition is %d",
dos_part, bsd_part);
if (! dest_dev->disk->has_partitions)
{
grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea."));
goto unable_to_embed;
}
if (dest_dev->disk->partition)
{
grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea."));
goto unable_to_embed;
}
/* Unlike root_dev, with dest_dev we're interested in the partition map even
if dest_dev itself is a whole disk. */
auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk,
const grub_partition_t p);
int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p)
{
dest_partmap = p->partmap->name;
return 1;
}
dest_partmap = 0;
grub_partition_iterate (dest_dev->disk, identify_partmap);
if (! dest_partmap)
{
grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea."));
goto unable_to_embed;
}
if (strcmp (dest_partmap, "part_msdos") == 0)
grub_partition_iterate (dest_dev->disk, find_usable_region_msdos);
else if (strcmp (dest_partmap, "part_gpt") == 0)
grub_partition_iterate (dest_dev->disk, find_usable_region_gpt);
else
grub_util_error (_("No DOS-style partitions found"));
if (embed_region.end == embed_region.start)
{
if (! strcmp (dest_partmap, "part_msdos"))
grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!"));
else
grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!"));
goto unable_to_embed;
}
if ((unsigned long) core_sectors > embed_region.end - embed_region.start)
{
if (core_sectors > 62)
grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area."));
else /* embed_region.end - embed_region.start < 62 */
grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it."));
goto unable_to_embed;
}
grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start);
*install_dos_part = grub_cpu_to_le32 (dos_part);
*install_bsd_part = grub_cpu_to_le32 (bsd_part);
/* The first blocklist contains the whole sectors. */
first_block->start = grub_cpu_to_le64 (embed_region.start + 1);
/* These are filled elsewhere. Verify them just in case. */
assert (first_block->len == grub_host_to_target16 (core_sectors - 1));
assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE >> 4)));
/* Make sure that the second blocklist is a terminator. */
block = first_block - 1;
block->start = 0;
block->len = 0;
block->segment = 0;
/* Write the core image onto the disk. */
if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img))
grub_util_error ("%s", grub_errmsg);
/* FIXME: can this be skipped? */
*boot_drive = 0xFF;
*kernel_sector = grub_cpu_to_le64 (embed_region.start);
/* Write the boot image onto the disk. */
if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE,
boot_img))
grub_util_error ("%s", grub_errmsg);
goto finish;
unable_to_embed:
if (must_embed)
grub_util_error (_("embedding is not possible, but this is required when "
"the root device is on a RAID array or LVM volume"));
grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this "
"setup by using blocklists. However, blocklists are UNRELIABLE and "
"its use is discouraged."));
if (! force)
grub_util_error (_("if you really want blocklists, use --force"));
if (must_embed && !able_to_embed)
grub_util_error ("Can't embed the core image, but this is required when\n"
"the root device is on a RAID array or LVM volume.");
/* 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);
core_path_dev_full = grub_util_get_path (dir, core_file);
core_path_dev = make_system_path_relative_to_its_root (core_path_dev_full);
free (core_path_dev_full);
/* 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_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB")
: _("attempting to read the core image `%s' from GRUB again"),
core_path_dev);
grub_disk_cache_invalidate_all ();
file = grub_file_open (core_path);
file = grub_file_open (core_path_dev);
if (file)
{
if (grub_file_size (file) != core_size)
@ -371,7 +457,7 @@ setup (const char *prefix, const char *dir,
#if 0
FILE *dump;
FILE *dump2;
dump = fopen ("dump.img", "wb");
if (dump)
{
@ -385,8 +471,8 @@ setup (const char *prefix, const char *dir,
fwrite (core_img, 1, core_size, dump2);
fclose (dump2);
}
#endif
#endif
grub_util_info ("succeeded in opening the core image but the data is different");
}
else
@ -402,14 +488,14 @@ setup (const char *prefix, const char *dir,
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);
grub_util_error (_("cannot read `%s' correctly"), core_path_dev);
/* Clean out the blocklists. */
block = first_block;
@ -420,83 +506,48 @@ setup (const char *prefix, const char *dir,
block->segment = 0;
block--;
if ((char *) block <= core_img)
grub_util_error ("No terminator in the core image");
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);
file = grub_file_open (core_path_dev);
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");
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_util_error (_("failed to read the rest sectors of the core image"));
grub_file_close (file);
free (core_path);
free (core_path_dev);
free (tmp_img);
*kernel_sector = grub_cpu_to_le64 (first_sector);
/* If the destination device is different from the root device,
it is necessary to embed the boot drive explicitly. */
if (root_dev->disk->id != dest_dev->disk->id)
*boot_drive = (grub_uint8_t) root_dev->disk->id;
else
*boot_drive = 0xFF;
/* FIXME: can this be skipped? */
*boot_drive = 0xFF;
/* Embed information about the installed location. */
if (root_dev->disk->partition)
{
struct grub_pc_partition *pcdata =
root_dev->disk->partition->data;
*install_dos_part = grub_cpu_to_le32 (dos_part);
*install_bsd_part = grub_cpu_to_le32 (bsd_part);
if (strcmp (root_dev->disk->partition->partmap->name,
"pc_partition_map") == 0)
{
*install_dos_part
= grub_cpu_to_le32 (pcdata->dos_part);
*install_bsd_part
= grub_cpu_to_le32 (pcdata->bsd_part);
}
else if (strcmp (root_dev->disk->partition->partmap->name,
"gpt_partition_map") == 0)
{
*install_dos_part = grub_cpu_to_le32 (root_dev->disk->partition->index);
*install_bsd_part = grub_cpu_to_le32 (-1);
}
else
grub_util_error ("No PC style partitions found");
}
else
*install_dos_part = *install_bsd_part = grub_cpu_to_le32 (-1);
grub_util_info ("dos partition is %d, bsd partition is %d, prefix is %s",
grub_le_to_cpu32 (*install_dos_part),
grub_le_to_cpu32 (*install_bsd_part),
prefix);
strcpy (install_prefix, prefix);
/* 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_error (_("cannot open `%s'"), core_path);
grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp);
fclose (fp);
free (core_path);
/* Write the boot image onto the disk. */
if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
@ -506,12 +557,12 @@ setup (const char *prefix, const char *dir,
/* Sync is a Good Thing. */
sync ();
free (core_path);
free (core_img);
free (boot_img);
grub_device_close (dest_dev);
if (!must_embed)
grub_device_close (root_dev);
grub_device_close (root_dev);
}
static struct option options[] =
@ -521,6 +572,8 @@ static struct option options[] =
{"directory", required_argument, 0, 'd'},
{"device-map", required_argument, 0, 'm'},
{"root-device", required_argument, 0, 'r'},
{"force", no_argument, 0, 'f'},
{"skip-fs-probe", no_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
@ -531,25 +584,28 @@ static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-setup --help'' for more information.\n");
fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name);
else
printf ("\
Usage: grub-setup [OPTION]... DEVICE\n\
printf (_("\
Usage: %s [OPTION]... DEVICE\n\
\n\
Set up images to boot from DEVICE.\n\
DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\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\
-f, --force install even if problems are detected\n\
-s, --skip-fs-probe do not probe for filesystems in DEVICE\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\
",
"),
program_name,
DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
@ -560,7 +616,7 @@ static char *
get_device_name (char *dev)
{
size_t len = strlen (dev);
if (dev[0] != '(' || dev[len - 1] != ')')
return 0;
@ -576,16 +632,17 @@ main (int argc, char *argv[])
char *dir = 0;
char *dev_map = 0;
char *root_dev = 0;
char *prefix;
char *dest_dev;
int must_embed = 0;
progname = "grub-setup";
int must_embed = 0, force = 0, fs_probe = 1;
set_program_name (argv[0]);
grub_util_init_nls ();
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0);
int c = getopt_long (argc, argv, "b:c:d:m:r:hVvf", options, 0);
if (c == -1)
break;
@ -612,7 +669,7 @@ main (int argc, char *argv[])
dir = xstrdup (optarg);
break;
case 'm':
if (dev_map)
free (dev_map);
@ -626,7 +683,15 @@ main (int argc, char *argv[])
root_dev = xstrdup (optarg);
break;
case 'f':
force = 1;
break;
case 's':
fs_probe = 0;
break;
case 'h':
usage (0);
break;
@ -645,16 +710,19 @@ main (int argc, char *argv[])
}
}
if (verbosity > 1)
grub_env_set ("debug", "all");
/* Obtain DEST_DEV. */
if (optind >= argc)
{
fprintf (stderr, "No device is specified.\n");
fprintf (stderr, _("No device is specified.\n"));
usage (1);
}
if (optind + 1 != argc)
{
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]);
usage (1);
}
@ -663,7 +731,7 @@ main (int argc, char *argv[])
/* Initialize all modules. */
grub_init_all ();
dest_dev = get_device_name (argv[optind]);
if (! dest_dev)
{
@ -671,7 +739,7 @@ main (int argc, char *argv[])
dest_dev = grub_util_get_grub_dev (argv[optind]);
if (! dest_dev)
{
fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]);
usage (1);
}
}
@ -679,15 +747,13 @@ main (int argc, char *argv[])
/* For simplicity. */
dest_dev = xstrdup (dest_dev);
prefix = grub_get_prefix (dir ? : DEFAULT_DIRECTORY);
if (root_dev)
{
char *tmp = get_device_name (root_dev);
if (! tmp)
grub_util_error ("Invalid root device `%s'", root_dev);
grub_util_error (_("invalid root device `%s'"), root_dev);
tmp = xstrdup (tmp);
free (root_dev);
root_dev = tmp;
@ -699,66 +765,55 @@ main (int argc, char *argv[])
{
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_error (_("cannot guess the root device. Specify the option `--root-device'"));
}
}
#ifdef __linux__
if (grub_util_lvm_isvolume (root_dev))
{
char *newprefix;
must_embed = 1;
must_embed = 1;
newprefix = xmalloc (1 + strlen (root_dev) + 1 + strlen (prefix) + 1);
sprintf (newprefix, "(%s)%s", root_dev, prefix);
free (prefix);
prefix = newprefix;
if (root_dev[0] == 'm' && root_dev[1] == 'd'
&& root_dev[2] >= '0' && root_dev[2] <= '9')
{
/* FIXME: we can avoid this on RAID1. */
must_embed = 1;
}
if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
&& dest_dev[2] >= '0' && dest_dev[2] <= '9')
{
char **devicelist;
char *raid_prefix;
int i;
raid_prefix = xmalloc (1 + strlen (dest_dev) + 1 + strlen (prefix) + 1);
sprintf (raid_prefix, "(%s)%s", dest_dev, prefix);
devicelist = grub_util_raid_getmembers (dest_dev);
for (i = 0; devicelist[i]; i++)
{
setup (raid_prefix,
dir ? : DEFAULT_DIRECTORY,
setup (dir ? : DEFAULT_DIRECTORY,
boot_file ? : DEFAULT_BOOT_FILE,
core_file ? : DEFAULT_CORE_FILE,
root_dev, grub_util_get_grub_dev (devicelist[i]), 1);
root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, fs_probe);
}
free (raid_prefix);
}
else
#endif
/* Do the real work. */
setup (prefix,
dir ? : DEFAULT_DIRECTORY,
setup (dir ? : DEFAULT_DIRECTORY,
boot_file ? : DEFAULT_BOOT_FILE,
core_file ? : DEFAULT_CORE_FILE,
root_dev, dest_dev, must_embed);
root_dev, dest_dev, must_embed, force, fs_probe);
/* Free resources. */
grub_fini_all ();
grub_util_biosdisk_fini ();
free (boot_file);
free (core_file);
free (dir);
free (dev_map);
free (root_dev);
free (prefix);
free (dest_dev);
return 0;
}

49
util/ieee1275/devicemap.c Normal file
View file

@ -0,0 +1,49 @@
#include <stdio.h>
#include <string.h>
#include <grub/types.h>
#include <grub/util/deviceiter.h>
#include <grub/util/ofpath.h>
#include <grub/util/misc.h>
/* Since OF path names can have "," characters in them, and GRUB
internally uses "," to indicate partitions (unlike OF which uses
":" for this purpose) we escape such commas. */
static char *
escape_of_path (const char *orig_path)
{
char *new_path, *d, c;
const char *p;
if (!strchr (orig_path, ','))
return (char *) orig_path;
new_path = xmalloc (strlen (orig_path) * 2);
p = orig_path;
d = new_path;
while ((c = *p++) != '\0')
{
if (c == ',')
*d++ = '\\';
*d++ = c;
}
free ((char *) orig_path);
return new_path;
}
void
grub_util_emit_devicemap_entry (FILE *fp, char *name,
int is_floppy __attribute__((unused)),
int *num_fd __attribute__((unused)),
int *num_hd __attribute__((unused)))
{
const char *orig_path = grub_util_devname_to_ofpath (name);
char *ofpath = escape_of_path (orig_path);
fprintf(fp, "(%s)\t%s\n", ofpath, name);
free (ofpath);
}

View file

@ -1,60 +0,0 @@
/* get_disk_name.c */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007 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 <stdio.h>
#include <grub/util/misc.h>
char *
grub_util_get_disk_name (int disk, char *name)
{
int p[2];
char *line = NULL;
int zero = 0;
int len;
pipe (p);
switch (fork ())
{
case -1:
perror ("fork");
exit (1);
case 0:
close (1);
dup (p[1]);
close (p[0]);
close (p[1]);
execlp ("ofpathname", "ofpathname", "-a", name, NULL);
perror ("execlp");
default:
close (0);
dup (p[0]);
close (p[0]);
close (p[1]);
}
len = getline (&line, &zero, stdin);
if (len < 2)
grub_util_error ("ofpathname didn't print a meaningful alias name");
line[len - 1] = '\0';
return line;
}

View file

@ -34,9 +34,10 @@ target_cpu=@target_cpu@
platform=@platform@
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
rootdir=
grub_prefix=`echo /boot/grub | sed ${transform}`
modules=
@ -163,6 +164,10 @@ for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ; do
cp -f $file ${grubdir} || exit 1
done
if ! test -f ${grubdir}/grubenv; then
$grub_editenv ${grubdir}/grubenv create
fi
# Create the core image. First, auto-detect the filesystem module.
fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
if test "x$fs_module" = x -a "x$modules" = x; then
@ -182,7 +187,7 @@ devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_ma
modules="$modules $fs_module $partmap_module $devabstraction_module"
# Now perform the installation.
"$grub_mkimage" --output=${grubdir}/grub $modules || exit 1
"$grub_mkimage" --directory=${pkglibdir} --output=${grubdir}/grub $modules || exit 1
if test $update_nvram = yes; then
set $ofpathname dummy

418
util/ieee1275/ofpath.c Normal file
View file

@ -0,0 +1,418 @@
/* ofpath.c - calculate OpenFirmware path names given an OS 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/>.
*/
#undef OFPATH_STANDALONE
#ifndef OFPATH_STANDALONE
#include <grub/types.h>
#include <grub/util/misc.h>
#include <grub/util/ofpath.h>
#endif
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#ifdef OFPATH_STANDALONE
#define xmalloc malloc
void
grub_util_error (const char *fmt, ...)
{
va_list ap;
fprintf (stderr, "ofpath: error: ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fputc ('\n', stderr);
exit (1);
}
#endif
static void
kill_trailing_dir(char *path)
{
char *end = path + strlen(path) - 1;
while (end >= path)
{
if (*end != '/')
{
end--;
continue;
}
*end = '\0';
break;
}
}
static void
trim_newline (char *path)
{
char *end = path + strlen(path) - 1;
while (*end == '\n')
*end-- = '\0';
}
#define OF_PATH_MAX 256
static void
find_obppath(char *of_path, const char *sysfs_path_orig)
{
char *sysfs_path, *path;
sysfs_path = xmalloc (PATH_MAX);
path = xmalloc (PATH_MAX);
strcpy(sysfs_path, sysfs_path_orig);
while (1)
{
int fd;
snprintf(path, PATH_MAX, "%s/obppath", sysfs_path);
#if 0
printf("Trying %s\n", path);
#endif
fd = open(path, O_RDONLY);
if (fd < 0)
{
kill_trailing_dir(sysfs_path);
if (!strcmp(sysfs_path, "/sys"))
grub_util_error("'obppath' not found in parent dirs of %s",
sysfs_path_orig);
continue;
}
memset(of_path, 0, OF_PATH_MAX);
read(fd, of_path, OF_PATH_MAX);
close(fd);
trim_newline(of_path);
break;
}
free (path);
free (sysfs_path);
}
static void
block_device_get_sysfs_path_and_link(const char *devicenode,
char *sysfs_path, int sysfs_path_len)
{
char *rpath = xmalloc (PATH_MAX);
snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode);
if (!realpath (sysfs_path, rpath))
grub_util_error ("cannot get the real path of `%s'", sysfs_path);
strcat(rpath, "/device");
if (!realpath (rpath, sysfs_path))
grub_util_error ("cannot get the real path of `%s'", rpath);
free (rpath);
}
static const char *
trailing_digits (const char *p)
{
const char *end;
end = p + strlen(p) - 1;
while (end >= p)
{
if (! isdigit(*end))
break;
end--;
}
return end + 1;
}
static void
__of_path_common(char *of_path, char *sysfs_path,
const char *device, int devno)
{
const char *digit_string;
char disk[64];
find_obppath(of_path, sysfs_path);
digit_string = trailing_digits (device);
if (*digit_string == '\0')
{
sprintf(disk, "/disk@%d", devno);
}
else
{
int part;
sscanf(digit_string, "%d", &part);
sprintf(disk, "/disk@%d:%c", devno, 'a' + (part - 1));
}
strcat(of_path, disk);
}
static char *
get_basename(char *p)
{
char *ret = p;
while (*p)
{
if (*p == '/')
ret = p + 1;
p++;
}
return ret;
}
static void
of_path_of_vdisk(char *of_path,
const char *devname __attribute__((unused)),
const char *device,
const char *devnode __attribute__((unused)),
const char *devicenode)
{
char *sysfs_path, *p;
int devno, junk;
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "vdc-port-%d-%d", &devno, &junk);
__of_path_common(of_path, sysfs_path, device, devno);
free (sysfs_path);
}
static void
of_path_of_ide(char *of_path,
const char *devname __attribute__((unused)), const char *device,
const char *devnode __attribute__((unused)),
const char *devicenode)
{
char *sysfs_path, *p;
int chan, devno;
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "%d.%d", &chan, &devno);
__of_path_common(of_path, sysfs_path, device, devno);
free (sysfs_path);
}
static int
vendor_is_ATA(const char *path)
{
int fd, err;
char *buf;
buf = xmalloc (PATH_MAX);
snprintf(buf, PATH_MAX, "%s/vendor", path);
fd = open(buf, O_RDONLY);
if (fd < 0)
grub_util_error ("cannot open 'vendor' node of `%s'", path);
memset(buf, 0, PATH_MAX);
err = read(fd, buf, PATH_MAX);
if (err < 0)
grub_util_error ("cannot read 'vendor' node of `%s'", path);
close(fd);
free (buf);
if (!strncmp(buf, "ATA", 3))
return 1;
return 0;
}
static void
check_sas (char *sysfs_path, int *tgt)
{
char *ed = strstr (sysfs_path, "end_device");
char *p, *q, *path;
char phy[16];
int fd;
if (!ed)
return;
/* SAS devices are identified using disk@$PHY_ID */
p = strdup (sysfs_path);
ed = strstr(p, "end_device");
q = ed;
while (*q && *q != '/')
q++;
*q = '\0';
path = xmalloc (PATH_MAX);
sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed);
fd = open(path, O_RDONLY);
if (fd < 0)
grub_util_error("cannot open SAS PHY ID `%s'\n", path);
memset (phy, 0, sizeof (phy));
read (fd, phy, sizeof (phy));
sscanf (phy, "%d", tgt);
free (path);
free (p);
}
static void
of_path_of_scsi(char *of_path,
const char *devname __attribute__((unused)), const char *device,
const char *devnode __attribute__((unused)),
const char *devicenode)
{
const char *p, *digit_string, *disk_name;
int host, bus, tgt, lun;
char *sysfs_path, disk[64];
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun);
check_sas (sysfs_path, &tgt);
if (vendor_is_ATA(sysfs_path))
{
__of_path_common(of_path, sysfs_path, device, tgt);
free (sysfs_path);
return;
}
find_obppath(of_path, sysfs_path);
free (sysfs_path);
if (strstr (of_path, "qlc"))
strcat (of_path, "/fp@0,0");
if (strstr (of_path, "sbus"))
disk_name = "sd";
else
disk_name = "disk";
digit_string = trailing_digits (device);
if (*digit_string == '\0')
{
sprintf(disk, "/%s@%x,%d", disk_name, tgt, lun);
}
else
{
int part;
sscanf(digit_string, "%d", &part);
sprintf(disk, "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1));
}
strcat(of_path, disk);
}
static char *
strip_trailing_digits (const char *p)
{
char *new, *end;
new = strdup (p);
end = new + strlen(new) - 1;
while (end >= new)
{
if (! isdigit(*end))
break;
*end-- = '\0';
}
return new;
}
char *
grub_util_devname_to_ofpath (char *devname)
{
char *name_buf, *device, *devnode, *devicenode, *ofpath;
name_buf = xmalloc (PATH_MAX);
name_buf = realpath (devname, name_buf);
if (! name_buf)
grub_util_error ("cannot get the real path of `%s'", devname);
device = get_basename (devname);
devnode = strip_trailing_digits (devname);
devicenode = strip_trailing_digits (device);
ofpath = xmalloc (OF_PATH_MAX);
if (device[0] == 'h' && device[1] == 'd')
of_path_of_ide(ofpath, name_buf, device, devnode, devicenode);
else if (device[0] == 's'
&& (device[1] == 'd' || device[1] == 'r'))
of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode);
else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i'
&& device[3] == 's' && device[4] == 'k')
of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode);
free (devnode);
free (devicenode);
free (name_buf);
return ofpath;
}
#ifdef OFPATH_STANDALONE
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);
return 0;
}
#endif

339
util/import_gcry.py Normal file
View file

@ -0,0 +1,339 @@
#*
#* 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/>.
#*
import re
import sys
import os
import datetime
if len (sys.argv) < 3:
print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
exit (0)
indir = sys.argv[1]
outdir = sys.argv[2]
basedir = os.path.join (outdir, "lib/libgcrypt-grub")
try:
os.makedirs (basedir)
except:
print ("WARNING: %s already exists" % basedir)
cipher_dir_in = os.path.join (indir, "cipher")
cipher_dir_out = os.path.join (basedir, "cipher")
try:
os.makedirs (cipher_dir_out)
except:
print ("WARNING: %s already exists" % cipher_dir_out)
cipher_files = os.listdir (cipher_dir_in)
conf = open (os.path.join (outdir, "conf", "gcry.rmk"), "w")
conf.write ("# -*- makefile -*-\n\n")
chlog = ""
# Strictly speaking CRC32/CRC24 work on bytes so this value should be 1
# But libgcrypt uses 64. Let's keep the value for compatibility. Since
# noone uses CRC24/CRC32 for HMAC this is no problem
mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
"_gcry_digest_spec_crc32_rfc1510" : 64,
"_gcry_digest_spec_crc24_rfc2440" : 64,
"_gcry_digest_spec_md4" : 64,
"_gcry_digest_spec_md5" : 64,
"_gcry_digest_spec_rmd160" : 64,
"_gcry_digest_spec_sha1" : 64,
"_gcry_digest_spec_sha224" : 64,
"_gcry_digest_spec_sha256" : 64,
"_gcry_digest_spec_sha384" : 128,
"_gcry_digest_spec_sha512" : 128,
"_gcry_digest_spec_tiger" : 64,
"_gcry_digest_spec_whirlpool" : 64}
cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w")
# rijndael is the only cipher using aliases. So no need for mangling, just
# hardcode it
cryptolist.write ("RIJNDAEL: gcry_rijndael\n");
cryptolist.write ("RIJNDAEL192: gcry_rijndael\n");
cryptolist.write ("RIJNDAEL256: gcry_rijndael\n");
cryptolist.write ("AES128: gcry_rijndael\n");
cryptolist.write ("AES-128: gcry_rijndael\n");
cryptolist.write ("AES-192: gcry_rijndael\n");
cryptolist.write ("AES-256: gcry_rijndael\n");
for cipher_file in cipher_files:
infile = os.path.join (cipher_dir_in, cipher_file)
outfile = os.path.join (cipher_dir_out, cipher_file)
if cipher_file == "ChangeLog":
continue
chlognew = " * %s" % cipher_file
if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file):
chlog = "%s%s: Removed\n" % (chlog, chlognew)
continue
# Autogenerated files. Not even worth mentionning in ChangeLog
if re.match ("Makefile\.in$", cipher_file):
continue
nch = False
if re.match (".*\.[ch]$", cipher_file):
isc = re.match (".*\.c$", cipher_file)
f = open (infile, "r")
fw = open (outfile, "w")
fw.write ("/* This file was automatically imported with \n")
fw.write (" import_gcry.py. Please don't modify it */\n");
ciphernames = []
mdnames = []
hold = False
skip = False
skip2 = False
ismd = False
iscryptostart = False
iscomma = False
isglue = False
skip_statement = False
if isc:
modname = cipher_file [0:len(cipher_file) - 2]
if re.match (".*-glue$", modname):
modname = modname.replace ("-glue", "")
isglue = True
modname = "gcry_%s" % modname
for line in f:
if skip_statement:
if not re.search (";", line) is None:
skip_statement = False
continue
if skip:
if line[0] == "}":
skip = False
continue
if skip2:
if not re.search (" *};", line) is None:
skip2 = False
continue
if iscryptostart:
s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
if not s is None:
sg = s.groups()[0]
cryptolist.write (("%s: %s\n") % (sg, modname))
iscryptostart = False
if ismd:
if not re.search (" *};", line) is None:
if not mdblocksizes.has_key (mdname):
print ("ERROR: Unknown digest blocksize: %s\n" % mdname)
exit (1)
if not iscomma:
fw.write (" ,\n")
fw.write (" .blocksize = %s\n" % mdblocksizes [mdname])
ismd = False
iscomma = not re.search (",$", line) is None
# Used only for selftests.
m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line)
if not m is None:
skip = True
fname = m.groups ()[1]
chmsg = "(%s): Removed." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
if hold:
hold = False
# We're optimising for size.
if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info)", line) is None:
skip = True
fname = re.match ("[a-zA-Z0-9_]*", line).group ()
chmsg = "(%s): Removed." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
else:
fw.write (holdline)
m = re.match ("#include <.*>", line)
if not m is None:
chmsg = "Removed including of %s" % \
m.group () [len ("#include <"):len (m.group ()) - 1]
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s: %s" % (chlognew, chmsg)
nch = True
continue
m = re.match ("gcry_cipher_spec_t", line)
if isc and not m is None:
assert (not iscryptostart)
ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
ciphernames.append (ciphername)
iscryptostart = True
m = re.match ("gcry_md_spec_t", line)
if isc and not m is None:
assert (not ismd)
assert (not iscryptostart)
mdname = line [len ("gcry_md_spec_t"):].strip ()
mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
mdnames.append (mdname)
ismd = True
iscryptostart = True
m = re.match ("static const char \*selftest.*;$", line)
if not m is None:
fname = line[len ("static const char \*"):]
fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
chmsg = "(%s): Removed declaration." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t)$", line)
if not m is None:
hold = True
holdline = line
continue
m = re.match ("static int tripledes_set2keys \(.*\);", line)
if not m is None:
continue
m = re.match ("static int tripledes_set2keys \(", line)
if not m is None:
skip_statement = True
continue
m = re.match ("cipher_extra_spec_t", line)
if isc and not m is None:
skip2 = True
fname = line[len ("cipher_extra_spec_t "):]
fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
chmsg = "(%s): Removed." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
m = re.match ("md_extra_spec_t", line)
if isc and not m is None:
skip2 = True
fname = line[len ("md_extra_spec_t "):]
fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
chmsg = "(%s): Removed." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
fw.write (line)
if len (ciphernames) > 0 or len (mdnames) > 0:
if isglue:
modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
% (cipher_file, cipher_file.replace ("-glue.c", ".c"))
else:
modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s%s" % (chlognew, chmsg)
nch = True
fw.write ("\n\nGRUB_MOD_INIT(%s)\n" % modname)
fw.write ("{\n")
for ciphername in ciphernames:
chmsg = "Register cipher %s" % ciphername
chlognew = "%s\n %s" % (chlognew, chmsg)
fw.write (" grub_cipher_register (&%s);\n" % ciphername)
for mdname in mdnames:
chmsg = "Register digest %s" % mdname
chlognew = "%s\n %s" % (chlognew, chmsg)
fw.write (" grub_md_register (&%s);\n" % mdname)
fw.write ("}")
chmsg = "(GRUB_MOD_FINI(%s)): New function\n" % modname
chlognew = "%s\n %s" % (chlognew, chmsg)
fw.write ("\n\nGRUB_MOD_FINI(%s)\n" % modname)
fw.write ("{\n")
for ciphername in ciphernames:
chmsg = "Unregister cipher %s" % ciphername
chlognew = "%s\n %s" % (chlognew, chmsg)
fw.write (" grub_cipher_unregister (&%s);\n" % ciphername)
for mdname in mdnames:
chmsg = "Unregister MD %s" % mdname
chlognew = "%s\n %s" % (chlognew, chmsg)
fw.write (" grub_md_unregister (&%s);\n" % mdname)
fw.write ("}\n")
conf.write ("pkglib_MODULES += %s.mod\n" % modname)
conf.write ("%s_mod_SOURCES = %s\n" %\
(modname, modfiles))
conf.write ("%s_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap\n" % modname)
conf.write ("%s_mod_LDFLAGS = $(COMMON_LDFLAGS)\n\n" % modname)
elif isc and cipher_file != "camellia.c":
print ("WARNING: C file isn't a module: %s" % cipher_file)
f.close ()
fw.close ()
if nch:
chlog = "%s%s\n" % (chlog, chlognew)
continue
chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
print ("WARNING: unknown file %s" % cipher_file)
cryptolist.close ()
chlog = "%s * crypto.lst: New file.\n" % chlog
outfile = os.path.join (cipher_dir_out, "types.h")
fw=open (outfile, "w")
fw.write ("#include <grub/types.h>\n")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * types.h: New file.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "memory.h")
fw=open (outfile, "w")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * memory.h: New file.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "cipher.h")
fw=open (outfile, "w")
fw.write ("#include <grub/crypto.h>\n")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * cipher.h: Likewise.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "g10lib.h")
fw=open (outfile, "w")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * g10lib.h: Likewise.\n" % chlog
fw.close ()
infile = os.path.join (cipher_dir_in, "ChangeLog")
outfile = os.path.join (cipher_dir_out, "ChangeLog")
f=open (infile, "r")
fw=open (outfile, "w")
dt = datetime.date.today ()
fw.write ("%04d-%02d-%02d Automatic import tool\n" % \
(dt.year,dt.month, dt.day))
fw.write ("\n")
fw.write (" Imported ciphers to GRUB\n")
fw.write ("\n")
fw.write (chlog)
fw.write ("\n")
for line in f:
fw.write (line)
f.close ()
fw.close ()

View file

@ -1,7 +1,7 @@
/* lvm.c - LVM support for GRUB utils. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
* Copyright (C) 2006,2007,2008 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
@ -21,6 +21,7 @@
#ifdef __linux__
#include <grub/util/misc.h>
#include <grub/util/lvm.h>
#include <string.h>
#include <sys/stat.h>
@ -31,7 +32,7 @@ grub_util_lvm_isvolume (char *name)
char *devname;
struct stat st;
int err;
devname = xmalloc (strlen (name) + 13);
strcpy (devname, "/dev/mapper/");

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2006,2007 Free Software Foundation, Inc.
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010 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
@ -18,19 +18,29 @@
#include <config.h>
#include <errno.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <grub/kernel.h>
#include <grub/misc.h>
#include <grub/cache.h>
#include <grub/util/misc.h>
#include <grub/mm.h>
#include <grub/term.h>
#include <grub/machine/time.h>
#include <grub/time.h>
#include <grub/i18n.h>
#include "progname.h"
/* Include malloc.h, only if memalign is available. It is known that
memalign is declared in malloc.h in all systems, if present. */
@ -38,21 +48,40 @@
# include <malloc.h>
#endif
char *progname = 0;
#ifdef __MINGW32__
#include <windows.h>
#include <winioctl.h>
#endif
int verbosity = 0;
void
grub_util_warn (const char *fmt, ...)
{
va_list ap;
fprintf (stderr, _("%s: warn:"), program_name);
fprintf (stderr, " ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fprintf (stderr, ".\n");
fflush (stderr);
}
void
grub_util_info (const char *fmt, ...)
{
if (verbosity > 0)
{
va_list ap;
fprintf (stderr, "%s: info: ", progname);
fprintf (stderr, _("%s: info:"), program_name);
fprintf (stderr, " ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fputc ('\n', stderr);
fprintf (stderr, ".\n");
fflush (stderr);
}
}
@ -61,20 +90,34 @@ void
grub_util_error (const char *fmt, ...)
{
va_list ap;
fprintf (stderr, "%s: error: ", progname);
fprintf (stderr, _("%s: error:"), program_name);
fprintf (stderr, " ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fputc ('\n', stderr);
fprintf (stderr, ".\n");
exit (1);
}
int
grub_err_printf (const char *fmt, ...)
{
va_list ap;
int ret;
va_start (ap, fmt);
ret = vfprintf (stderr, fmt, ap);
va_end (ap);
return ret;
}
void *
xmalloc (size_t size)
{
void *p;
p = malloc (size);
if (! p)
grub_util_error ("out of memory");
@ -97,7 +140,7 @@ xstrdup (const char *str)
{
size_t len;
char *dup;
len = strlen (str);
dup = (char *) xmalloc (len + 1);
memcpy (dup, str, len + 1);
@ -109,7 +152,7 @@ char *
grub_util_get_path (const char *dir, const char *file)
{
char *path;
path = (char *) xmalloc (strlen (dir) + 1 + strlen (file) + 1);
sprintf (path, "%s/%s", dir, file);
return path;
@ -119,13 +162,13 @@ size_t
grub_util_get_fp_size (FILE *fp)
{
struct stat st;
if (fflush (fp) == EOF)
grub_util_error ("fflush failed");
if (fstat (fileno (fp), &st) == -1)
grub_util_error ("fstat failed");
return st.st_size;
}
@ -133,20 +176,20 @@ size_t
grub_util_get_image_size (const char *path)
{
struct stat st;
grub_util_info ("getting the size of %s", path);
if (stat (path, &st) == -1)
grub_util_error ("cannot stat %s", path);
return st.st_size;
}
void
grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp)
{
if (fseek (fp, offset, SEEK_SET) == -1)
grub_util_error ("fseek failed");
if (fseeko (fp, offset, SEEK_SET) == -1)
grub_util_error ("seek failed");
if (fread (img, 1, size, fp) != size)
grub_util_error ("read failed");
@ -158,7 +201,7 @@ grub_util_read_image (const char *path)
char *img;
FILE *fp;
size_t size;
grub_util_info ("reading %s", path);
size = grub_util_get_image_size (path);
@ -171,7 +214,7 @@ grub_util_read_image (const char *path)
grub_util_read_at (img, size, 0, fp);
fclose (fp);
return img;
}
@ -180,11 +223,11 @@ grub_util_load_image (const char *path, char *buf)
{
FILE *fp;
size_t size;
grub_util_info ("reading %s", path);
size = grub_util_get_image_size (path);
fp = fopen (path, "rb");
if (! fp)
grub_util_error ("cannot open %s", path);
@ -199,7 +242,7 @@ void
grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
{
grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
if (fseek (out, offset, SEEK_SET) == -1)
if (fseeko (out, offset, SEEK_SET) == -1)
grub_util_error ("seek failed");
if (fwrite (img, 1, size, out) != size)
grub_util_error ("write failed");
@ -219,6 +262,16 @@ grub_malloc (grub_size_t size)
return xmalloc (size);
}
void *
grub_zalloc (grub_size_t size)
{
void *ret;
ret = xmalloc (size);
memset (ret, 0, size);
return ret;
}
void
grub_free (void *ptr)
{
@ -242,12 +295,14 @@ grub_memalign (grub_size_t align, grub_size_t size)
#elif defined(HAVE_MEMALIGN)
p = memalign (align, size);
#else
(void) align;
(void) size;
grub_util_error ("grub_memalign is not supported");
#endif
if (! p)
grub_util_error ("out of memory");
return p;
}
@ -275,14 +330,262 @@ grub_get_rtc (void)
struct timeval tv;
gettimeofday (&tv, 0);
return (tv.tv_sec * GRUB_TICKS_PER_SECOND
+ (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec)
* GRUB_TICKS_PER_SECOND / 1000000));
}
void
grub_uint64_t
grub_get_time_ms (void)
{
struct timeval tv;
gettimeofday (&tv, 0);
return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
#ifdef __MINGW32__
void
grub_millisleep (grub_uint32_t ms)
{
Sleep (ms);
}
#else
void
grub_millisleep (grub_uint32_t ms)
{
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep (&ts, NULL);
}
#endif
void
grub_arch_sync_caches (void *address __attribute__ ((unused)),
grub_size_t len __attribute__ ((unused)))
{
}
#ifndef HAVE_VASPRINTF
int
vasprintf (char **buf, const char *fmt, va_list ap)
{
/* Should be large enough. */
*buf = xmalloc (512);
return vsprintf (*buf, fmt, ap);
}
#endif
#ifndef HAVE_ASPRINTF
int
asprintf (char **buf, const char *fmt, ...)
{
int status;
va_list ap;
va_start (ap, fmt);
status = vasprintf (*buf, fmt, ap);
va_end (ap);
return status;
}
#endif
char *
xasprintf (const char *fmt, ...)
{
va_list ap;
char *result;
va_start (ap, fmt);
if (vasprintf (&result, fmt, ap) < 0)
{
if (errno == ENOMEM)
grub_util_error ("out of memory");
return NULL;
}
return result;
}
#ifdef __MINGW32__
void sync (void)
{
}
int fsync (int fno __attribute__ ((unused)))
{
return 0;
}
void sleep (int s)
{
Sleep (s * 1000);
}
grub_int64_t
grub_util_get_disk_size (char *name)
{
HANDLE hd;
grub_int64_t size = -1LL;
hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
if (hd == INVALID_HANDLE_VALUE)
return size;
if (((name[0] == '/') || (name[0] == '\\')) &&
((name[1] == '/') || (name[1] == '\\')) &&
(name[2] == '.') &&
((name[3] == '/') || (name[3] == '\\')) &&
(! strncasecmp (name + 4, "PHYSICALDRIVE", 13)))
{
DWORD nr;
DISK_GEOMETRY g;
if (! DeviceIoControl (hd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
0, 0, &g, sizeof (g), &nr, 0))
goto fail;
size = g.Cylinders.QuadPart;
size *= g.TracksPerCylinder * g.SectorsPerTrack * g.BytesPerSector;
}
else
{
LARGE_INTEGER s;
s.LowPart = GetFileSize (hd, &s.HighPart);
size = s.QuadPart;
}
fail:
CloseHandle (hd);
return size;
}
#endif /* __MINGW32__ */
char *
canonicalize_file_name (const char *path)
{
char *ret;
#ifdef PATH_MAX
ret = xmalloc (PATH_MAX);
(void) realpath (path, ret);
#else
ret = realpath (path, NULL);
#endif
return ret;
}
/* This function never prints trailing slashes (so that its output
can be appended a slash unconditionally). */
char *
make_system_path_relative_to_its_root (const char *path)
{
struct stat st;
char *p, *buf, *buf2, *buf3;
uintptr_t offset = 0;
dev_t num;
size_t len;
/* canonicalize. */
p = canonicalize_file_name (path);
if (p == NULL)
grub_util_error ("failed to get canonical path of %s", path);
len = strlen (p) + 1;
buf = strdup (p);
free (p);
if (stat (buf, &st) < 0)
grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
buf2 = strdup (buf);
num = st.st_dev;
/* This loop sets offset to the number of chars of the root
directory we're inspecting. */
while (1)
{
p = strrchr (buf, '/');
if (p == NULL)
/* This should never happen. */
grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
if (p != buf)
*p = 0;
else
*++p = 0;
if (stat (buf, &st) < 0)
grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
/* buf is another filesystem; we found it. */
if (st.st_dev != num)
{
/* offset == 0 means path given is the mount point. */
if (offset == 0)
{
free (buf);
free (buf2);
return strdup ("/");
}
else
break;
}
offset = p - buf;
/* offset == 1 means root directory. */
if (offset == 1)
{
free (buf);
len = strlen (buf2);
while (buf2[len - 1] == '/' && len > 1)
{
buf2[len - 1] = '\0';
len--;
}
return buf2;
}
}
free (buf);
buf3 = strdup (buf2 + offset);
free (buf2);
len = strlen (buf3);
while (buf3[len - 1] == '/' && len > 1)
{
buf3[len - 1] = '\0';
len--;
}
return buf3;
}
void
grub_util_init_nls (void)
{
#if ENABLE_NLS
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif /* ENABLE_NLS */
}

20
util/mkisofs/defaults.h Normal file
View file

@ -0,0 +1,20 @@
/*
* Header file defaults.h - assorted default values for character strings in
* the volume descriptor.
*
* $Id: defaults.h,v 1.8 1999/03/02 03:41:25 eric Exp $
*/
#define PREPARER_DEFAULT NULL
#define PUBLISHER_DEFAULT NULL
#ifndef APPID_DEFAULT
#define APPID_DEFAULT PACKAGE_NAME " ISO 9660 filesystem builder"
#endif
#define COPYRIGHT_DEFAULT NULL
#define BIBLIO_DEFAULT NULL
#define ABSTRACT_DEFAULT NULL
#define VOLSET_ID_DEFAULT NULL
#define VOLUME_ID_DEFAULT "CDROM"
#define BOOT_CATALOG_DEFAULT "boot.catalog"
#define BOOT_IMAGE_DEFAULT NULL
#define SYSTEM_ID_DEFAULT "GNU"

343
util/mkisofs/eltorito.c Normal file
View file

@ -0,0 +1,343 @@
/*
* Program eltorito.c - Handle El Torito specific extensions to iso9660.
*
Written by Michael Fulbright <msf@redhat.com> (1996).
Copyright 1996 RedHat Software, Incorporated
Copyright (C) 2009 Free Software Foundation, Inc.
Boot Info Table generation based on code from genisoimage.c
(from cdrkit 1.1.9), which was originally licensed under GPLv2+.
This program 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, or (at your option)
any later version.
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include "config.h"
#include "mkisofs.h"
#include "iso9660.h"
/* used by Win32 for opening binary file - not used by Unix */
#ifndef O_BINARY
#define O_BINARY 0
#endif /* O_BINARY */
#undef MIN
#define MIN(a, b) (((a) < (b))? (a): (b))
static struct eltorito_validation_entry valid_desc;
static struct eltorito_defaultboot_entry default_desc;
static struct eltorito_boot_descriptor gboot_desc;
static int tvd_write __PR((FILE * outfile));
/*
* Check for presence of boot catalog. If it does not exist then make it
*/
void FDECL1(init_boot_catalog, const char *, path)
{
FILE *bcat;
char * bootpath; /* filename of boot catalog */
char * buf;
struct stat statbuf;
bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
strcpy(bootpath, path);
if (bootpath[strlen(bootpath)-1] != '/')
{
strcat(bootpath,"/");
}
strcat(bootpath, boot_catalog);
/*
* check for the file existing
*/
#ifdef DEBUG_TORITO
fprintf(stderr,"Looking for boot catalog file %s\n",bootpath);
#endif
if (!stat_filter(bootpath, &statbuf))
{
/*
* make sure its big enough to hold what we want
*/
if (statbuf.st_size == 2048)
{
/*
* printf("Boot catalog exists, so we do nothing\n");
*/
free(bootpath);
return;
}
else
{
fprintf (stderr, _("A boot catalog exists and appears corrupted.\n"));
fprintf (stderr, _("Please check the following file: %s.\n"), bootpath);
fprintf (stderr, _("This file must be removed before a bootable CD can be done.\n"));
free (bootpath);
exit (1);
}
}
/*
* file does not exist, so we create it
* make it one CD sector long
*/
bcat = fopen (bootpath, "wb");
if (bcat == NULL)
error (1, errno, _("Error creating boot catalog (%s)"), bootpath);
buf = (char *) e_malloc( 2048 );
if (fwrite (buf, 1, 2048, bcat) != 2048)
error (1, errno, _("Error writing to boot catalog (%s)"), bootpath);
fclose (bcat);
chmod (bootpath, S_IROTH | S_IRGRP | S_IRWXU);
free(bootpath);
} /* init_boot_catalog(... */
void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
{
FILE *bootcat;
int checksum;
unsigned char * checksum_ptr;
struct directory_entry * de;
struct directory_entry * de2;
unsigned int i;
int nsectors;
memset(boot_desc, 0, sizeof(*boot_desc));
boot_desc->id[0] = 0;
memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
boot_desc->version[0] = 1;
memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
/*
* search from root of iso fs to find boot catalog
*/
de2 = search_tree_file(root, boot_catalog);
if (!de2)
{
fprintf (stderr, _("Boot catalog cannot be found!\n"));
exit (1);
}
set_731(boot_desc->bootcat_ptr,
(unsigned int) get_733(de2->isorec.extent));
/*
* now adjust boot catalog
* lets find boot image first
*/
de=search_tree_file(root, boot_image);
if (!de)
{
fprintf (stderr, _("Boot image cannot be found!\n"));
exit (1);
}
/*
* we have the boot image, so write boot catalog information
* Next we write out the primary descriptor for the disc
*/
memset(&valid_desc, 0, sizeof(valid_desc));
valid_desc.headerid[0] = 1;
valid_desc.arch[0] = EL_TORITO_ARCH_x86;
/*
* we'll shove start of publisher id into id field, may get truncated
* but who really reads this stuff!
*/
if (publisher)
memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher)));
valid_desc.key1[0] = 0x55;
valid_desc.key2[0] = 0xAA;
/*
* compute the checksum
*/
checksum=0;
checksum_ptr = (unsigned char *) &valid_desc;
for (i=0; i<sizeof(valid_desc); i+=2)
{
/*
* skip adding in ckecksum word, since we dont have it yet!
*/
if (i == 28)
{
continue;
}
checksum += (unsigned int)checksum_ptr[i];
checksum += ((unsigned int)checksum_ptr[i+1])*256;
}
/*
* now find out the real checksum
*/
checksum = -checksum;
set_721(valid_desc.cksum, (unsigned int) checksum);
/*
* now make the initial/default entry for boot catalog
*/
memset(&default_desc, 0, sizeof(default_desc));
default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
/*
* use default BIOS loadpnt
*/
set_721(default_desc.loadseg, 0);
default_desc.arch[0] = EL_TORITO_ARCH_x86;
/*
* figure out size of boot image in sectors, for now hard code to
* assume 512 bytes/sector on a bootable floppy
*/
nsectors = ((de->size + 511) & ~(511))/512;
fprintf (stderr, _("\nSize of boot image is %d sectors"), nsectors);
fprintf (stderr, " -> ");
if (! use_eltorito_emul_floppy)
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
fprintf (stderr, _("No emulation\n"));
}
else if (nsectors == 2880 )
/*
* choose size of emulated floppy based on boot image size
*/
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
fprintf (stderr, _("Emulating a 1.44 meg floppy\n"));
}
else if (nsectors == 5760 )
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
fprintf (stderr, _("Emulating a 2.88 meg floppy\n"));
}
else if (nsectors == 2400 )
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
fprintf (stderr, _("Emulating a 1.2 meg floppy\n"));
}
else
{
fprintf (stderr, _("\nError - boot image is not the an allowable size.\n"));
exit (1);
}
/*
* FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!!
*/
nsectors = 1;
set_721(default_desc.nsect, (unsigned int) nsectors );
#ifdef DEBUG_TORITO
fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent));
#endif
set_731(default_desc.bootoff,
(unsigned int) get_733(de->isorec.extent));
/*
* now write it to disk
*/
bootcat = fopen (de2->whole_name, "r+b");
if (bootcat == NULL)
error (1, errno, _("Error opening boot catalog for update"));
/*
* write out
*/
if (fwrite (&valid_desc, 1, 32, bootcat) != 32)
error (1, errno, _("Error writing to boot catalog"));
if (fwrite (&default_desc, 1, 32, bootcat) != 32)
error (1, errno, _("Error writing to boot catalog"));
fclose (bootcat);
/* If the user has asked for it, patch the boot image */
if (use_boot_info_table)
{
FILE *bootimage;
uint32_t bi_checksum;
unsigned int total_len;
static char csum_buffer[SECTOR_SIZE];
int len;
struct eltorito_boot_info bi_table;
bootimage = fopen (de->whole_name, "r+b");
if (bootimage == NULL)
error (1, errno, _("Error opening boot image file `%s' for update"),
de->whole_name);
/* Compute checksum of boot image, sans 64 bytes */
total_len = 0;
bi_checksum = 0;
while ((len = fread (csum_buffer, 1, SECTOR_SIZE, bootimage)) > 0)
{
if (total_len & 3)
error (1, 0, _("Odd alignment at non-end-of-file in boot image `%s'"),
de->whole_name);
if (total_len < 64)
memset (csum_buffer, 0, 64 - total_len);
if (len < SECTOR_SIZE)
memset (csum_buffer + len, 0, SECTOR_SIZE - len);
for (i = 0; i < SECTOR_SIZE; i += 4)
bi_checksum += get_731 (&csum_buffer[i]);
total_len += len;
}
if (total_len != de->size)
error (1, 0, _("Boot image file `%s' changed unexpectedly"),
de->whole_name);
/* End of file, set position to byte 8 */
fseeko (bootimage, (off_t) 8, SEEK_SET);
memset (&bi_table, 0, sizeof (bi_table));
/* Is it always safe to assume PVD is at session_start+16? */
set_731 (bi_table.pvd_addr, session_start + 16);
set_731 (bi_table.file_addr, de->starting_block);
set_731 (bi_table.file_length, de->size);
set_731 (bi_table.file_checksum, bi_checksum);
if (fwrite (&bi_table, 1, sizeof (bi_table), bootimage) != sizeof (bi_table))
error (1, errno, _("Error writing to boot image (%s)"), bootimage);
fclose (bootimage);
}
} /* get_torito_desc(... */
/*
* Function to write the EVD for the disc.
*/
static int FDECL1(tvd_write, FILE *, outfile)
{
/*
* Next we write out the boot volume descriptor for the disc
*/
get_torito_desc(&gboot_desc);
xfwrite(&gboot_desc, 1, 2048, outfile);
last_extent_written ++;
return 0;
}
struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};

10
util/mkisofs/exclude.h Normal file
View file

@ -0,0 +1,10 @@
/*
* 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
* added 'exclude' option (-x) to specify pathnames NOT to be included in
* CD image.
*
* $Id: exclude.h,v 1.2 1999/03/02 03:41:25 eric Exp $
*/
void exclude __PR((char * fn));
int is_excluded __PR((char * fn));

225
util/mkisofs/hash.c Normal file
View file

@ -0,0 +1,225 @@
/*
* File hash.c - generate hash tables for iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program 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 2, or (at your option)
any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h>
#include "config.h"
#include "mkisofs.h"
#define NR_HASH 1024
#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH)
static struct file_hash * hash_table[NR_HASH] = {0,};
void FDECL1(add_hash, struct directory_entry *, spnt){
struct file_hash * s_hash;
unsigned int hash_number;
if(spnt->size == 0 || spnt->starting_block == 0)
if(spnt->size != 0 || spnt->starting_block != 0) {
fprintf(stderr,"Non zero-length file assigned zero extent.\n");
exit(1);
};
if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
#if 0
if (verbose > 1) fprintf(stderr,"%s ",spnt->name);
#endif
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = hash_table[hash_number];
s_hash->inode = spnt->inode;
s_hash->dev = spnt->dev;
s_hash->starting_block = spnt->starting_block;
s_hash->size = spnt->size;
hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
static struct file_hash * directory_hash_table[NR_HASH] = {0,};
void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){
struct file_hash * s_hash;
unsigned int hash_number;
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = directory_hash_table[hash_number];
s_hash->inode = inode;
s_hash->dev = dev;
directory_hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = directory_hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
struct name_hash
{
struct name_hash * next;
struct directory_entry * de;
};
#define NR_NAME_HASH 128
static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
/*
* Find the hash bucket for this name.
*/
static unsigned int FDECL1(name_hash, const char *, name)
{
unsigned int hash = 0;
const char * p;
p = name;
while (*p)
{
/*
* Don't hash the iso9660 version number. This way
* we can detect duplicates in cases where we have
* directories (i.e. foo) and non-directories
* (i.e. foo;1).
*/
if( *p == ';' )
{
break;
}
hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
}
return hash % NR_NAME_HASH;
}
void FDECL1(add_file_hash, struct directory_entry *, de){
struct name_hash * new;
int hash;
new = (struct name_hash *) e_malloc(sizeof(struct name_hash));
new->de = de;
new->next = NULL;
hash = name_hash(de->isorec.name);
/* Now insert into the hash table */
new->next = name_hash_table[hash];
name_hash_table[hash] = new;
}
struct directory_entry * FDECL1(find_file_hash, char *, name)
{
struct name_hash * nh;
char * p1;
char * p2;
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
{
p1 = name;
p2 = nh->de->isorec.name;
/*
* Look for end of string, or a mismatch.
*/
while(1==1)
{
if( (*p1 == '\0' || *p1 == ';')
|| (*p2 == '\0' || *p2 == ';')
|| (*p1 != *p2) )
{
break;
}
p1++;
p2++;
}
/*
* If we are at the end of both strings, then
* we have a match.
*/
if( (*p1 == '\0' || *p1 == ';')
&& (*p2 == '\0' || *p2 == ';') )
{
return nh->de;
}
}
return NULL;
}
int FDECL1(delete_file_hash, struct directory_entry *, de){
struct name_hash * nh, *prev;
int hash;
prev = NULL;
hash = name_hash(de->isorec.name);
for(nh = name_hash_table[hash]; nh; nh = nh->next) {
if(nh->de == de) break;
prev = nh;
}
if(!nh) return 1;
if(!prev)
name_hash_table[hash] = nh->next;
else
prev->next = nh->next;
free(nh);
return 0;
}
void flush_file_hash(){
struct name_hash * nh, *nh1;
int i;
for(i=0; i<NR_NAME_HASH; i++) {
nh = name_hash_table[i];
while(nh) {
nh1 = nh->next;
free(nh);
nh = nh1;
}
name_hash_table[i] = NULL;
}
}

View file

@ -0,0 +1,57 @@
/* @(#)fctldefs.h 1.2 98/10/08 Copyright 1996 J. Schilling */
/*
* Generic header for users of open(), creat() and chmod()
*
* Copyright (c) 1996 J. Schilling
*/
/*
* This program 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 2, or (at your option)
* any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _FCTLDEFS_H
#define _FCTLDEFS_H
#ifndef _MCONFIG_H
#include <mconfig.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#else /* HAVE_FCNTL_H */
# include <sys/file.h>
#endif /* HAVE_FCNTL_H */
/*
* Do not define more than O_RDONLY / O_WRONLY / O_RDWR
* The values may differ.
*/
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_WRONLY
#define O_WRONLY 1
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#endif /* _FCTLDEFS_H */

View file

@ -0,0 +1,253 @@
/* @(#)mconfig.h 1.24 98/12/14 Copyright 1995 J. Schilling */
/*
* definitions for machine configuration
*
* Copyright (c) 1995 J. Schilling
*
* This file must be included before any other file.
* Use only cpp instructions.
*
* NOTE: SING: (Schily Is Not Gnu)
*/
/*
* This program 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 2, or (at your option)
* any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _MCONFIG_H
#define _MCONFIG_H
#include <config.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(unix) || defined(__unix) || defined(__unix__)
# define IS_UNIX
#endif
#ifdef __MSDOS__
# define IS_MSDOS
#endif
#if defined(tos) || defined(__tos)
# define IS_TOS
#endif
#ifdef THINK_C
# define IS_MAC
#endif
#if defined(sun) || defined(__sun) || defined(__sun__)
# define IS_SUN
#endif
#if defined(__CYGWIN32__)
# define IS_GCC_WIN32
#endif
/*--------------------------------------------------------------------------*/
/*
* Some magic that cannot (yet) be figured out with autoconf.
*/
#ifdef sparc
# ifndef HAVE_LDSTUB
# define HAVE_LDSTUB
# endif
# ifndef HAVE_SCANSTACK
# define HAVE_SCANSTACK
# endif
#endif
#if defined(__i386_) || defined(i386)
# ifndef HAVE_XCHG
# define HAVE_XCHG
# endif
# ifndef HAVE_SCANSTACK
# define HAVE_SCANSTACK
# endif
#endif
#if defined(SOL2) || defined(SOL2) || defined(S5R4) || defined(__S5R4) \
|| defined(SVR4)
# ifndef __SVR4
# define __SVR4
# endif
#endif
#ifdef __SVR4
# ifndef SVR4
# define SVR4
# endif
#endif
/*
* SunOS 4.x / SunOS 5.x
*/
#if defined(IS_SUN)
# define HAVE_GETAV0
#endif
/*
* AIX
*/
#if defined(_IBMR2) || defined(_AIX)
# define IS_UNIX /* ??? really ??? */
#endif
/*
* Silicon Graphics (must be before SVR4)
*/
#if defined(sgi) || defined(__sgi)
# define __NOT_SVR4__ /* Not a real SVR4 implementation */
#endif
/*
* Data General
*/
#if defined(__DGUX__)
#ifdef XXXXXXX
# undef HAVE_MTGET_DSREG
# undef HAVE_MTGET_RESID
# undef HAVE_MTGET_FILENO
# undef HAVE_MTGET_BLKNO
#endif
# define mt_type mt_model
# define mt_dsreg mt_status1
# define mt_erreg mt_status2
/*
* DGUX hides its flock as dg_flock.
*/
# define HAVE_FLOCK
# define flock dg_flock
/*
* Use the BSD style wait on DGUX to get the resource usages of child
* processes.
*/
# define _BSD_WAIT_FLAVOR
#endif
/*
* Apple Rhapsody
*/
#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody
# define HAVE_OSDEF /* prevent later definitions to overwrite current */
#endif
/*
* NextStep
*/
#if defined(__NeXT__) && !defined(HAVE_OSDEF)
#define NO_PRINT_OVR
#undef HAVE_USG_STDIO /*
* NeXT Step 3.x uses __flsbuf(unsigned char , FILE *)
* instead of __flsbuf(int, FILE *)
*/
#endif
/*
* NextStep 3.x has a broken linker that does not allow us to override
* these functions.
*/
#ifndef __OPRINTF__
#ifdef NO_PRINT_OVR
# define printf Xprintf
# define fprintf Xfprintf
# define sprintf Xsprintf
#endif
#endif /* __OPRINTF__ */
/*--------------------------------------------------------------------------*/
/*
* If there is no flock defined by the system, use emulation
* through fcntl record locking.
*/
#ifndef HAVE_FLOCK
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* don't block when locking */
#define LOCK_UN 8 /* unlock */
#endif
#include <prototyp.h>
/*
* gcc 2.x generally implements the long long type.
*/
#ifdef __GNUC__
# if __GNUC__ > 1
# ifndef HAVE_LONGLONG
# define HAVE_LONGLONG
# endif
# endif
#endif
/*
* Convert to GNU name
*/
#ifdef HAVE_STDC_HEADERS
# ifndef STDC_HEADERS
# define STDC_HEADERS
# endif
#endif
/*
* Convert to SCHILY name
*/
#ifdef STDC_HEADERS
# ifndef HAVE_STDC_HEADERS
# define HAVE_STDC_HEADERS
# endif
#endif
#ifdef IS_UNIX
# define PATH_DELIM '/'
# define PATH_DELIM_STR "/"
# define far
# define near
#endif
#ifdef IS_GCC_WIN32
# define PATH_DELIM '/'
# define PATH_DELIM_STR "/"
# define far
# define near
#endif
#ifdef IS_MSDOS
# define PATH_DELIM '\\'
# define PATH_DELIM_STR "\\"
#endif
#ifdef IS_TOS
# define PATH_DELIM '\\'
# define PATH_DELIM_STR "\\"
# define far
# define near
#endif
#ifdef IS_MAC
# define PATH_DELIM ':'
# define PATH_DELIM_STR ":"
# define far
# define near
#endif
#ifdef __cplusplus
}
#endif
#endif /* _MCONFIG_H */

View file

@ -0,0 +1,74 @@
/* @(#)prototyp.h 1.7 98/10/08 Copyright 1995 J. Schilling */
/*
* Definitions for dealing with ANSI / KR C-Compilers
*
* Copyright (c) 1995 J. Schilling
*/
/*
* This program 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 2, or (at your option)
* any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PROTOTYP_H
#define _PROTOTYP_H
#ifndef PROTOTYPES
/*
* If this has already been defined,
* someone else knows better than us...
*/
# ifdef __STDC__
# if __STDC__ /* ANSI C */
# define PROTOTYPES
# endif
# if defined(sun) && __STDC__ - 0 == 0 /* Sun C */
# define PROTOTYPES
# endif
# endif
#endif /* PROTOTYPES */
/*
* If we have prototypes, we should have stdlib.h string.h stdarg.h
*/
#ifdef PROTOTYPES
#if !(defined(SABER) && defined(sun))
# ifndef HAVE_STDARG_H
# define HAVE_STDARG_H
# endif
#endif
# ifndef HAVE_STDLIB_H
# define HAVE_STDLIB_H
# endif
# ifndef HAVE_STRING_H
# define HAVE_STRING_H
# endif
# ifndef HAVE_STDC_HEADERS
# define HAVE_STDC_HEADERS
# endif
# ifndef STDC_HEADERS
# define STDC_HEADERS /* GNU name */
# endif
#endif
#ifdef NO_PROTOTYPES /* Force not to use prototypes */
# undef PROTOTYPES
#endif
#ifdef PROTOTYPES
# define __PR(a) a
#else
# define __PR(a) ()
#endif
#endif /* _PROTOTYP_H */

View file

@ -0,0 +1,139 @@
/* @(#)statdefs.h 1.1 98/11/22 Copyright 1998 J. Schilling */
/*
* Definitions for stat() file mode
*
* Copyright (c) 1998 J. Schilling
*/
/*
* This program 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 2, or (at your option)
* any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _STATDEFS_H
#define _STATDEFS_H
#ifndef _MCONFIG_H
#include <mconfig.h>
#endif
#ifdef STAT_MACROS_BROKEN
#undef S_ISFIFO /* Named pipe */
#undef S_ISCHR /* Character special */
#undef S_ISMPC /* UNUSED multiplexed c */
#undef S_ISDIR /* Directory */
#undef S_ISNAM /* Named file (XENIX) */
#undef S_ISBLK /* Block special */
#undef S_ISMPB /* UNUSED multiplexed b */
#undef S_ISREG /* Regular file */
#undef S_ISCNT /* Contiguous file */
#undef S_ISLNK /* Symbolic link */
#undef S_ISSHAD /* Solaris shadow inode */
#undef S_ISSOCK /* UNIX domain socket */
#undef S_ISDOOR /* Solaris DOOR */
#endif
#ifndef S_ISFIFO /* Named pipe */
# ifdef S_IFIFO
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
# else
# define S_ISFIFO(m) (0)
# endif
#endif
#ifndef S_ISCHR /* Character special */
# ifdef S_IFCHR
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
# else
# define S_ISCHR(m) (0)
# endif
#endif
#ifndef S_ISMPC /* UNUSED multiplexed c */
# ifdef S_IFMPC
# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
# else
# define S_ISMPC(m) (0)
# endif
#endif
#ifndef S_ISDIR /* Directory */
# ifdef S_IFDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
# else
# define S_ISDIR(m) (0)
# endif
#endif
#ifndef S_ISNAM /* Named file (XENIX) */
# ifdef S_IFNAM
# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
# else
# define S_ISNAM(m) (0)
# endif
#endif
#ifndef S_ISBLK /* Block special */
# ifdef S_IFBLK
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
# else
# define S_ISBLK(m) (0)
# endif
#endif
#ifndef S_ISMPB /* UNUSED multiplexed b */
# ifdef S_IFMPB
# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
# else
# define S_ISMPB(m) (0)
# endif
#endif
#ifndef S_ISREG /* Regular file */
# ifdef S_IFREG
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
# else
# define S_ISREG(m) (0)
# endif
#endif
#ifndef S_ISCNT /* Contiguous file */
# ifdef S_IFCNT
# define S_ISCNT(m) (((m) & S_IFMT) == S_IFCNT)
# else
# define S_ISCNT(m) (0)
# endif
#endif
#ifndef S_ISLNK /* Symbolic link */
# ifdef S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
# else
# define S_ISLNK(m) (0)
# endif
#endif
#ifndef S_ISSHAD /* Solaris shadow inode */
# ifdef S_IFSHAD
# define S_ISSHAD(m) (((m) & S_IFMT) == S_IFSHAD)
# else
# define S_ISSHAD(m) (0)
# endif
#endif
#ifndef S_ISSOCK /* UNIX domain socket */
# ifdef S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
# else
# define S_ISSOCK(m) (0)
# endif
#endif
#ifndef S_ISDOOR /* Solaris DOOR */
# ifdef S_IFDOOR
# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
# else
# define S_ISDOOR(m) (0)
# endif
#endif
#endif /* _STATDEFS_H */

174
util/mkisofs/iso9660.h Normal file
View file

@ -0,0 +1,174 @@
/*
* Header file iso9660.h - assorted structure definitions and typecasts.
* specific to iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
Copyright (C) 2009 Free Software Foundation, Inc.
This program 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, or (at your option)
any later version.
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id: iso9660.h,v 1.2 1997/05/17 15:46:44 eric Exp $
*/
#ifndef _ISOFS_FS_H
#define _ISOFS_FS_H
/*
* The isofs filesystem constants/structures
*/
/* This part borrowed from the bsd386 isofs */
#define ISODCL(from, to) (to - from + 1)
struct iso_volume_descriptor {
char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
/* volume descriptor types */
#define ISO_VD_PRIMARY 1
#define ISO_VD_SUPPLEMENTARY 2 /* Used by Joliet */
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
#define EL_TORITO_ID "EL TORITO SPECIFICATION"
#define EL_TORITO_ARCH_x86 0
#define EL_TORITO_ARCH_PPC 1
#define EL_TORITO_ARCH_MAC 2
#define EL_TORITO_BOOTABLE 0x88
#define EL_TORITO_MEDIA_NOEMUL 0
#define EL_TORITO_MEDIA_12FLOP 1
#define EL_TORITO_MEDIA_144FLOP 2
#define EL_TORITO_MEDIA_288FLOP 3
#define EL_TORITO_MEDIA_HD 4
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char escape_sequences [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
/* El Torito Boot Record Volume Descriptor */
struct eltorito_boot_descriptor {
char id [ISODCL ( 1, 1)]; /* 711 */
char id2 [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char system_id [ISODCL ( 8, 39)];
char unused2 [ISODCL ( 40, 71)];
char bootcat_ptr [ISODCL ( 72 , 75)];
char unused5 [ISODCL ( 76, 2048)];
};
/* Validation entry for El Torito */
struct eltorito_validation_entry {
char headerid [ISODCL ( 1, 1)]; /* 711 */
char arch [ISODCL ( 2, 2)];
char pad1 [ISODCL ( 3, 4)]; /* 711 */
char id [ISODCL ( 5, 28)];
char cksum [ISODCL ( 29, 30)];
char key1 [ISODCL ( 31, 31)];
char key2 [ISODCL ( 32, 32)];
};
/* El Torito initial/default entry in boot catalog */
struct eltorito_defaultboot_entry {
char boot_id [ISODCL ( 1, 1)]; /* 711 */
char boot_media [ISODCL ( 2, 2)];
char loadseg [ISODCL ( 3, 4)]; /* 711 */
char arch [ISODCL ( 5, 5)];
char pad1 [ISODCL ( 6, 6)];
char nsect [ISODCL ( 7, 8)];
char bootoff [ISODCL ( 9, 12)];
char pad2 [ISODCL ( 13, 32)];
};
/* El Torito boot information table */
struct eltorito_boot_info
{
/* Address of Primary Volume Descriptor. */
char pvd_addr[ISODCL (1, 4)];
/* Boot file address. */
char file_addr[ISODCL (5, 8)];
/* Boot file length. */
char file_length[ISODCL (9, 12)];
/* Boot file checksum. */
char file_checksum[ISODCL (13, 16)];
char dummy[ISODCL (17, 56)];
};
/* We use this to help us look up the parent inode numbers. */
struct iso_path_table{
unsigned char name_len[2]; /* 721 */
char extent[4]; /* 731 */
char parent[2]; /* 721 */
char name[1];
};
struct iso_directory_record {
unsigned char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
char extent [ISODCL (3, 10)]; /* 733 */
char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
char name [34]; /* Not really, but we need something here */
};
#endif

1023
util/mkisofs/joliet.c Normal file

File diff suppressed because it is too large Load diff

76
util/mkisofs/match.c Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "fnmatch.h"
#include "match.h"
struct pattern
{
char *str;
struct pattern *next;
};
static struct pattern *patlist = NULL;
static struct pattern *i_patlist = NULL; /* ISO9660/RR */
static struct pattern *j_patlist = NULL; /* Joliet */
#define DECL_ADD_MATCH(function, list) \
void \
function (char *pattern) \
{ \
struct pattern *new; \
new = malloc (sizeof (*new)); \
new->str = strdup (pattern); \
new->next = list; \
list = new; \
}
DECL_ADD_MATCH (add_match, patlist)
DECL_ADD_MATCH (i_add_match, i_patlist)
DECL_ADD_MATCH (j_add_match, j_patlist)
#define DECL_MATCHES(function, list) \
int \
function (char *str) \
{ \
struct pattern *i; \
for (i = list; i != NULL; i = i->next) \
if (fnmatch (i->str, str, FNM_FILE_NAME) != FNM_NOMATCH) \
return 1; \
return 0; \
}
DECL_MATCHES (matches, patlist)
DECL_MATCHES (i_matches, i_patlist)
DECL_MATCHES (j_matches, j_patlist)
int
i_ishidden()
{
return (i_patlist != NULL);
}
int j_ishidden()
{
return (j_patlist != NULL);
}

29
util/mkisofs/match.h Normal file
View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
extern void add_match (char *);
extern void i_add_match (char *);
extern void j_add_match (char *);
extern int matches (char *);
extern int i_matches (char *);
extern int j_matches (char *);
extern int i_ishidden ();
extern int j_ishidden ();

1422
util/mkisofs/mkisofs.c Normal file

File diff suppressed because it is too large Load diff

530
util/mkisofs/mkisofs.h Normal file
View file

@ -0,0 +1,530 @@
/*
* Header file mkisofs.h - assorted structure definitions and typecasts.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
Copyright (C) 2009,2010 Free Software Foundation, Inc.
This program 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, or (at your option)
any later version.
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id: mkisofs.h,v 1.20 1999/03/02 04:16:41 eric Exp $
*/
#include <stdio.h>
#include <stdint.h>
#include <prototyp.h>
#include <sys/stat.h>
#if ENABLE_NLS
# include <locale.h>
# include <libintl.h>
#else /* ! ENABLE_NLS */
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
#endif /* ENABLE_NLS */
#define _(str) gettext(str)
#define N_(str) str
/* This symbol is used to indicate that we do not have things like
symlinks, devices, and so forth available. Just files and dirs */
#ifdef VMS
#define NON_UNIXFS
#endif
#ifdef DJGPP
#define NON_UNIXFS
#endif
#ifdef VMS
#include <sys/dir.h>
#define dirent direct
#endif
#ifdef _WIN32
#define NON_UNIXFS
#endif /* _WIN32 */
#ifndef S_IROTH
#define S_IROTH 0
#endif
#ifndef S_IRGRP
#define S_IRGRP 0
#endif
#ifndef HAVE_GETUID
static inline int
getuid ()
{
return 0;
}
#endif
#ifndef HAVE_GETGID
static inline int
getgid ()
{
return 0;
}
#endif
#ifndef HAVE_LSTAT
static inline int
lstat (const char *filename, struct stat *buf)
{
return stat (filename, buf);
}
#endif
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined(HAVE_DIRENT_H)
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if defined(HAVE_SYS_NDIR_H)
# include <sys/ndir.h>
# endif
# if defined(HAVE_SYS_DIR_H)
# include <sys/dir.h>
# endif
# if defined(HAVE_NDIR_H)
# include <ndir.h>
# endif
#endif
#if defined(HAVE_STRING_H)
#include <string.h>
#else
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#endif
#ifdef ultrix
extern char *strdup();
#endif
#ifdef __STDC__
#define DECL(NAME,ARGS) NAME ARGS
#define FDECL1(NAME,TYPE0, ARG0) \
NAME(TYPE0 ARG0)
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \
NAME(TYPE0 ARG0, TYPE1 ARG1)
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2)
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3)
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4)
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5)
#else
#define DECL(NAME,ARGS) NAME()
#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0;
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1;
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2;
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3;
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4;
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5;
#define const
#endif
#ifdef __SVR4
#include <stdlib.h>
#else
extern int optind;
extern char *optarg;
/* extern int getopt (int __argc, char **__argv, char *__optstring); */
#endif
#include "iso9660.h"
#include "defaults.h"
struct directory_entry{
struct directory_entry * next;
struct directory_entry * jnext;
struct iso_directory_record isorec;
uint64_t starting_block;
uint64_t size;
unsigned short priority;
unsigned char jreclen; /* Joliet record len */
char * name;
char * table;
char * whole_name;
struct directory * filedir;
struct directory_entry * parent_rec;
unsigned int de_flags;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned char * rr_attributes;
unsigned int rr_attr_size;
unsigned int total_rr_attr_size;
unsigned int got_rr_name;
};
struct file_hash{
struct file_hash * next;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned int starting_block;
unsigned int size;
};
/*
* This structure is used to control the output of fragments to the cdrom
* image. Everything that will be written to the output image will eventually
* go through this structure. There are two pieces - first is the sizing where
* we establish extent numbers for everything, and the second is when we actually
* generate the contents and write it to the output image.
*
* This makes it trivial to extend mkisofs to write special things in the image.
* All you need to do is hook an additional structure in the list, and the rest
* works like magic.
*
* The three passes each do the following:
*
* The 'size' pass determines the size of each component and assigns the extent number
* for that component.
*
* The 'generate' pass will adjust the contents and pointers as required now that extent
* numbers are assigned. In some cases, the contents of the record are also generated.
*
* The 'write' pass actually writes the data to the disc.
*/
struct output_fragment
{
struct output_fragment * of_next;
#ifdef __STDC__
int (*of_size)(int);
int (*of_generate)(void);
int (*of_write)(FILE *);
#else
int (*of_size)();
int (*of_generate)();
int (*of_write)();
#endif
};
extern struct output_fragment * out_list;
extern struct output_fragment * out_tail;
extern struct output_fragment padblock_desc;
extern struct output_fragment voldesc_desc;
extern struct output_fragment joliet_desc;
extern struct output_fragment torito_desc;
extern struct output_fragment end_vol;
extern struct output_fragment pathtable_desc;
extern struct output_fragment jpathtable_desc;
extern struct output_fragment dirtree_desc;
extern struct output_fragment dirtree_clean;
extern struct output_fragment jdirtree_desc;
extern struct output_fragment extension_desc;
extern struct output_fragment files_desc;
/*
* This structure describes one complete directory. It has pointers
* to other directories in the overall tree so that it is clear where
* this directory lives in the tree, and it also must contain pointers
* to the contents of the directory. Note that subdirectories of this
* directory exist twice in this stucture. Once in the subdir chain,
* and again in the contents chain.
*/
struct directory{
struct directory * next; /* Next directory at same level as this one */
struct directory * subdir; /* First subdirectory in this directory */
struct directory * parent;
struct directory_entry * contents;
struct directory_entry * jcontents;
struct directory_entry * self;
char * whole_name; /* Entire path */
char * de_name; /* Entire path */
unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */
unsigned int depth;
unsigned int size;
unsigned int extent;
unsigned int jsize;
unsigned int jextent;
unsigned short path_index;
unsigned short jpath_index;
unsigned short dir_flags;
unsigned short dir_nlink;
};
extern int goof;
extern struct directory * root;
extern struct directory * reloc_dir;
extern uint64_t next_extent;
extern uint64_t last_extent;
extern uint64_t last_extent_written;
extern uint64_t session_start;
extern unsigned int path_table_size;
extern unsigned int path_table[4];
extern unsigned int path_blocks;
extern char * path_table_l;
extern char * path_table_m;
extern unsigned int jpath_table_size;
extern unsigned int jpath_table[4];
extern unsigned int jpath_blocks;
extern char * jpath_table_l;
extern char * jpath_table_m;
extern struct iso_directory_record root_record;
extern struct iso_directory_record jroot_record;
extern int use_eltorito;
extern int use_embedded_boot;
extern int use_protective_msdos_label;
extern int use_eltorito_emul_floppy;
extern int use_boot_info_table;
extern int use_RockRidge;
extern int use_Joliet;
extern int rationalize;
extern int follow_links;
extern int verbose;
extern int all_files;
extern int generate_tables;
extern int print_size;
extern int split_output;
extern int omit_period;
extern int omit_version_number;
extern int transparent_compression;
extern unsigned int RR_relocation_depth;
extern int full_iso9660_filenames;
extern int split_SL_component;
extern int split_SL_field;
/* tree.c */
extern int DECL(stat_filter, (char *, struct stat *));
extern int DECL(lstat_filter, (char *, struct stat *));
extern int DECL(sort_tree,(struct directory *));
extern struct directory *
DECL(find_or_create_directory,(struct directory *, const char *,
struct directory_entry * self, int));
extern void DECL (finish_cl_pl_entries, (void));
extern int DECL(scan_directory_tree,(struct directory * this_dir,
char * path,
struct directory_entry * self));
extern int DECL(insert_file_entry,(struct directory *, char *,
char *));
extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
extern void DECL(dump_tree,(struct directory * node));
extern struct directory_entry * DECL(search_tree_file, (struct
directory * node,char * filename));
extern void DECL(update_nlink_field,(struct directory * node));
extern void DECL (init_fstatbuf, (void));
extern struct stat root_statbuf;
/* eltorito.c */
extern void DECL(init_boot_catalog, (const char * path ));
extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path ));
/* write.c */
extern int DECL(get_731,(char *));
extern int DECL(get_733,(char *));
extern int DECL(isonum_733,(unsigned char *));
extern void DECL(set_723,(char *, unsigned int));
extern void DECL(set_731,(char *, unsigned int));
extern void DECL(set_721,(char *, unsigned int));
extern void DECL(set_733,(char *, unsigned int));
extern int DECL(sort_directory,(struct directory_entry **));
extern void DECL(generate_one_directory,(struct directory *, FILE*));
extern void DECL(memcpy_max, (char *, char *, int));
extern int DECL(oneblock_size, (int starting_extent));
extern struct iso_primary_descriptor vol_desc;
extern void DECL(xfwrite, (void * buffer, uint64_t count, uint64_t size, FILE * file));
extern void DECL(set_732, (char * pnt, unsigned int i));
extern void DECL(set_722, (char * pnt, unsigned int i));
extern void DECL(outputlist_insert, (struct output_fragment * frag));
/*
* Set by user command-line to override default date values
*/
extern char *creation_date;
extern char *modification_date;
extern char *expiration_date;
extern char *effective_date;
/* multi.c */
extern FILE * in_image;
extern struct iso_directory_record *
DECL(merge_isofs,(char * path));
extern int DECL(free_mdinfo, (struct directory_entry **, int len));
extern struct directory_entry **
DECL(read_merging_directory,(struct iso_directory_record *, int*));
extern void
DECL(merge_remaining_entries, (struct directory *,
struct directory_entry **, int));
extern int
DECL(merge_previous_session, (struct directory *,
struct iso_directory_record *));
extern int DECL(get_session_start, (int *));
/* joliet.c */
int DECL(joliet_sort_tree, (struct directory * node));
/* match.c */
extern int DECL(matches, (char *));
extern void DECL(add_match, (char *));
/* files.c */
struct dirent * DECL(readdir_add_files, (char **, char *, DIR *));
/* */
extern int DECL(iso9660_file_length,(const char* name,
struct directory_entry * sresult, int flag));
extern int DECL(iso9660_date,(char *, time_t));
extern void DECL(add_hash,(struct directory_entry *));
extern struct file_hash * DECL(find_hash,(dev_t, ino_t));
extern void DECL(add_directory_hash,(dev_t, ino_t));
extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t));
extern void DECL (flush_file_hash, (void));
extern int DECL(delete_file_hash,(struct directory_entry *));
extern struct directory_entry * DECL(find_file_hash,(char *));
extern void DECL(add_file_hash,(struct directory_entry *));
extern int DECL(generate_rock_ridge_attributes,(char *, char *,
struct directory_entry *,
struct stat *, struct stat *,
int deep_flag));
extern char * DECL(generate_rr_extension_record,(char * id, char * descriptor,
char * source, int * size));
extern int DECL(check_prev_session, (struct directory_entry **, int len,
struct directory_entry *,
struct stat *,
struct stat *,
struct directory_entry **));
#ifdef USE_SCG
/* scsi.c */
#ifdef __STDC__
extern int readsecs(int startsecno, void *buffer, int sectorcount);
extern int scsidev_open(char *path);
#else
extern int readsecs();
extern int scsidev_open();
#endif
#endif
extern char * extension_record;
extern int extension_record_extent;
extern int n_data_extents;
/* These are a few goodies that can be specified on the command line, and are
filled into the root record */
extern char *preparer;
extern char *publisher;
extern char *copyright;
extern char *biblio;
extern char *abstract;
extern char *appid;
extern char *volset_id;
extern char *system_id;
extern char *volume_id;
extern char *boot_catalog;
extern char *boot_image;
extern char *boot_image_embed;
extern int volume_set_size;
extern int volume_sequence_number;
extern void * DECL(e_malloc,(size_t));
#define SECTOR_SIZE (2048)
#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
#define NEED_RE 1
#define NEED_PL 2
#define NEED_CL 4
#define NEED_CE 8
#define NEED_SP 16
#define PREV_SESS_DEV (sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd)
#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe)
#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff)
#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff)
#ifdef VMS
#define STAT_INODE(X) (X.st_ino[0])
#define PATH_SEPARATOR ']'
#define SPATH_SEPARATOR ""
#else
#define STAT_INODE(X) (X.st_ino)
#define PATH_SEPARATOR '/'
#define SPATH_SEPARATOR "/"
#endif
/*
* When using multi-session, indicates that we can reuse the
* TRANS.TBL information for this directory entry. If this flag
* is set for all entries in a directory, it means we can just
* reuse the TRANS.TBL and not generate a new one.
*/
#define SAFE_TO_REUSE_TABLE_ENTRY 0x01
#define DIR_HAS_DOT 0x02
#define DIR_HAS_DOTDOT 0x04
#define INHIBIT_JOLIET_ENTRY 0x08
#define INHIBIT_RR_ENTRY 0x10
#define RELOCATED_DIRECTORY 0x20
#define INHIBIT_ISO9660_ENTRY 0x40
/*
* Volume sequence number to use in all of the iso directory records.
*/
#define DEF_VSN 1
/*
* Make sure we have a definition for this. If not, take a very conservative
* guess. From what I can tell SunOS is the only one with this trouble.
*/
#ifndef NAME_MAX
#ifdef FILENAME_MAX
#define NAME_MAX FILENAME_MAX
#else
#define NAME_MAX 128
#endif
#endif

View file

@ -0,0 +1,75 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2004,2007 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/>.
*/
#ifndef MSDOS_PARTITION_H
#define MSDOS_PARTITION_H 1
#include <stdint.h>
/* The signature. */
#define MSDOS_PARTITION_SIGNATURE ((0xaa << 8) | 0x55)
/* This is not a flag actually, but used as if it were a flag. */
#define MSDOS_PARTITION_TYPE_HIDDEN_FLAG 0x10
/* The partition entry. */
struct msdos_partition_entry
{
/* If active, 0x80, otherwise, 0x00. */
uint8_t flag;
/* The head of the start. */
uint8_t start_head;
/* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C
is the cylinder of the start. Note that S is counted from one. */
uint8_t start_sector;
/* (C & 0xFF) where C is the cylinder of the start. */
uint8_t start_cylinder;
/* The partition type. */
uint8_t type;
/* The end versions of start_head, start_sector and start_cylinder,
respectively. */
uint8_t end_head;
uint8_t end_sector;
uint8_t end_cylinder;
/* The start sector. Note that this is counted from zero. */
uint32_t start;
/* The length in sector units. */
uint32_t length;
} __attribute__ ((packed));
/* The structure of MBR. */
struct msdos_partition_mbr
{
/* The code area (actually, including BPB). */
uint8_t code[446];
/* Four partition entries. */
struct msdos_partition_entry entries[4];
/* The signature 0xaa55. */
uint16_t signature;
} __attribute__ ((packed));
#endif

1201
util/mkisofs/multi.c Normal file

File diff suppressed because it is too large Load diff

394
util/mkisofs/name.c Normal file
View file

@ -0,0 +1,394 @@
/*
* File name.c - map full Unix file names to unique 8.3 names that
* would be valid on DOS.
*
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program 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 2, or (at your option)
any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "mkisofs.h"
#include <ctype.h>
extern int allow_leading_dots;
/*
* Function: iso9660_file_length
*
* Purpose: Map file name to 8.3 format, return length
* of result.
*
* Arguments: name file name we need to map.
* sresult directory entry structure to contain mapped name.
* dirflag flag indicating whether this is a directory or not.
*
* Notes: This procedure probably needs to be rationalized somehow.
* New options to affect the behavior of this function
* would also be nice to have.
*/
int FDECL3(iso9660_file_length,
const char*, name,
struct directory_entry *, sresult,
int, dirflag)
{
char * c;
int chars_after_dot = 0;
int chars_before_dot = 0;
int current_length = 0;
int extra = 0;
int ignore = 0;
char * last_dot;
const char * pnt;
int priority = 32767;
char * result;
int seen_dot = 0;
int seen_semic = 0;
int tildes = 0;
result = sresult->isorec.name;
/*
* For the '.' entry, generate the correct record, and return
* 1 for the length.
*/
if(strcmp(name,".") == 0)
{
if(result)
{
*result = 0;
}
return 1;
}
/*
* For the '..' entry, generate the correct record, and return
* 1 for the length.
*/
if(strcmp(name,"..") == 0)
{
if(result)
{
*result++ = 1;
*result++ = 0;
}
return 1;
}
/*
* Now scan the directory one character at a time, and figure out
* what to do.
*/
pnt = name;
/*
* Find the '.' that we intend to use for the extension. Usually this
* is the last dot, but if we have . followed by nothing or a ~, we
* would consider this to be unsatisfactory, and we keep searching.
*/
last_dot = strrchr (pnt,'.');
if( (last_dot != NULL)
&& ( (last_dot[1] == '~')
|| (last_dot[1] == '\0')) )
{
c = last_dot;
*c = '\0';
last_dot = strrchr (pnt,'.');
*c = '.';
}
while(*pnt)
{
#ifdef VMS
if( strcmp(pnt,".DIR;1") == 0 )
{
break;
}
#endif
/*
* This character indicates a Unix style of backup file
* generated by some editors. Lower the priority of
* the file.
*/
if(*pnt == '#')
{
priority = 1;
pnt++;
continue;
}
/*
* This character indicates a Unix style of backup file
* generated by some editors. Lower the priority of
* the file.
*/
if(*pnt == '~')
{
priority = 1;
tildes++;
pnt++;
continue;
}
/*
* This might come up if we had some joker already try and put
* iso9660 version numbers into the file names. This would be
* a silly thing to do on a Unix box, but we check for it
* anyways. If we see this, then we don't have to add our
* own version number at the end.
* UNLESS the ';' is part of the filename and no version
* number is following. [VK]
*/
if(*pnt == ';')
{
/* [VK] */
if (pnt[1] != '\0' && (pnt[1] < '0' || pnt[1] > '9'))
{
pnt++;
ignore++;
continue;
}
}
/*
* If we have a name with multiple '.' characters, we ignore everything
* after we have gotten the extension.
*/
if(ignore)
{
pnt++;
continue;
}
/*
* Spin past any iso9660 version number we might have.
*/
if(seen_semic)
{
if(*pnt >= '0' && *pnt <= '9')
{
*result++ = *pnt;
}
extra++;
pnt++;
continue;
}
/*
* If we have full names, the names we generate will not
* work on a DOS machine, since they are not guaranteed
* to be 8.3. Nonetheless, in many cases this is a useful
* option. We still only allow one '.' character in the
* name, however.
*/
if(full_iso9660_filenames)
{
/* Here we allow a more relaxed syntax. */
if(*pnt == '.')
{
if (seen_dot)
{
ignore++;
continue;
}
seen_dot++;
}
if(current_length < 30)
{
if( !isascii (*pnt))
{
*result++ = '_';
}
else
{
*result++ = (islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt);
}
}
}
else
{
/*
* Dos style filenames. We really restrict the
* names here.
*/
/* It would be nice to have .tar.gz transform to .tgz,
* .ps.gz to .psz, ...
*/
if(*pnt == '.')
{
if (!chars_before_dot && !allow_leading_dots)
{
/* DOS can't read files with dot first */
chars_before_dot++;
if (result)
{
*result++ = '_'; /* Substitute underscore */
}
}
else if( pnt != last_dot )
{
/*
* If this isn't the dot that we use for the extension,
* then change the character into a '_' instead.
*/
if(chars_before_dot < 8)
{
chars_before_dot++;
if(result)
{
*result++ = '_';
}
}
}
else
{
if (seen_dot)
{
ignore++; continue;
}
if(result)
{
*result++ = '.';
}
seen_dot++;
}
}
else
{
if( (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
|| (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
{
if(result)
{
switch (*pnt)
{
default:
if( !isascii (*pnt) )
{
*result++ = '_';
}
else
{
*result++ = islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt;
}
break;
/*
* Descriptions of DOS's 'Parse Filename'
* (function 29H) describes V1 and V2.0+
* separator and terminator characters.
* These characters in a DOS name make
* the file visible but un-manipulable
* (all useful operations error off.
*/
/* separators */
case '+':
case '=':
case '%': /* not legal DOS filename */
case ':':
case ';': /* already handled */
case '.': /* already handled */
case ',': /* already handled */
case '\t':
case ' ':
/* V1 only separators */
case '/':
case '"':
case '[':
case ']':
/* terminators */
case '>':
case '<':
case '|':
/* Hmm - what to do here? Skip?
* Win95 looks like it substitutes '_'
*/
*result++ = '_';
break;
} /* switch (*pnt) */
} /* if (result) */
} /* if (chars_{after,before}_dot) ... */
} /* else *pnt == '.' */
} /* else DOS file names */
current_length++;
pnt++;
} /* while (*pnt) */
/*
* OK, that wraps up the scan of the name. Now tidy up a few other
* things.
*/
/*
* Look for emacs style of numbered backups, like foo.c.~3~. If
* we see this, convert the version number into the priority
* number. In case of name conflicts, this is what would end
* up being used as the 'extension'.
*/
if(tildes == 2)
{
int prio1 = 0;
pnt = name;
while (*pnt && *pnt != '~')
{
pnt++;
}
if (*pnt)
{
pnt++;
}
while(*pnt && *pnt != '~')
{
prio1 = 10*prio1 + *pnt - '0';
pnt++;
}
priority = prio1;
}
/*
* If this is not a directory, force a '.' in case we haven't
* seen one, and add a version number if we haven't seen one
* of those either.
*/
if (!dirflag)
{
if (!seen_dot && !omit_period)
{
if (result) *result++ = '.';
extra++;
}
if(!omit_version_number && !seen_semic)
{
if(result)
{
*result++ = ';';
*result++ = '1';
};
extra += 2;
}
}
if(result)
{
*result++ = 0;
}
sresult->priority = priority;
return (chars_before_dot + chars_after_dot + seen_dot + extra);
}

597
util/mkisofs/rock.c Normal file
View file

@ -0,0 +1,597 @@
/*
* File rock.c - generate RRIP records for iso9660 filesystems.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
Copyright (C) 2009,2010 Free Software Foundation, Inc.
This program 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, or (at your option)
any later version.
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "config.h"
#ifndef VMS
#if defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#if defined(MAJOR_IN_MKDEV)
#include <sys/types.h>
#include <sys/mkdev.h>
#endif
#include "mkisofs.h"
#include "iso9660.h"
#include <string.h>
#include <errno.h>
#ifdef DOESNT_WORK
#ifdef NON_UNIXFS
#define S_ISLNK(m) (0)
#else
#ifndef S_ISLNK
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#endif
#else
#include <statdefs.h>
#endif
#define SU_VERSION 1
#define SL_ROOT 8
#define SL_PARENT 4
#define SL_CURRENT 2
#define SL_CONTINUE 1
#define CE_SIZE 28
#define CL_SIZE 12
#define ER_SIZE 8
#define NM_SIZE 5
#define PL_SIZE 12
#define PN_SIZE 20
#define PX_SIZE 36
#define RE_SIZE 4
#define SL_SIZE 20
#define ZZ_SIZE 15
#ifdef __QNX__
#define TF_SIZE (5 + 4 * 7)
#else
#define TF_SIZE (5 + 3 * 7)
#endif
/* If we need to store this number of bytes, make sure we
do not box ourselves in so that we do not have room for
a CE entry for the continuation record */
#define MAYBE_ADD_CE_ENTRY(BYTES) \
((unsigned) ((BYTES) + CE_SIZE + currlen + ipnt) > (unsigned) (recstart + reclimit) ? 1 : 0)
/*
* Buffer to build RR attributes
*/
static unsigned char Rock[16384];
static unsigned char symlink_buff[256];
static int ipnt = 0;
static int recstart = 0;
static int currlen = 0;
static int mainrec = 0;
static int reclimit;
static void add_CE_entry __PR((void));
static void add_CE_entry(){
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
Rock[ipnt++] ='C';
Rock[ipnt++] ='E';
Rock[ipnt++] = CE_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
recstart = ipnt;
currlen = 0;
if(!mainrec) mainrec = ipnt;
reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
}
#ifdef __STDC__
int generate_rock_ridge_attributes (char * whole_name, char * name,
struct directory_entry * s_entry,
struct stat * statbuf,
struct stat * lstatbuf,
int deep_opt)
#else
int generate_rock_ridge_attributes (whole_name, name,
s_entry,
statbuf,
lstatbuf,
deep_opt)
char * whole_name; char * name; struct directory_entry * s_entry;
struct stat * statbuf, *lstatbuf;
int deep_opt;
#endif
{
int flagpos, flagval;
int need_ce;
statbuf = statbuf; /* this shuts up unreferenced compiler warnings */
mainrec = recstart = ipnt = 0;
reclimit = 0xf8;
/* no need to fill in the RR stuff if we won't see the file */
if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
return 0;
/* Obtain the amount of space that is currently used for the directory
record. Assume max for name, since name conflicts may cause us
to rename the file later on */
currlen = sizeof(s_entry->isorec);
/* Identify that we are using the SUSP protocol */
if(deep_opt & NEED_SP){
Rock[ipnt++] ='S';
Rock[ipnt++] ='P';
Rock[ipnt++] = 7;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0xbe;
Rock[ipnt++] = 0xef;
Rock[ipnt++] = 0;
};
/* First build the posix name field */
Rock[ipnt++] ='R';
Rock[ipnt++] ='R';
Rock[ipnt++] = 5;
Rock[ipnt++] = SU_VERSION;
flagpos = ipnt;
flagval = 0;
Rock[ipnt++] = 0; /* We go back and fix this later */
if(strcmp(name,".") && strcmp(name,"..")){
char * npnt;
int remain, use;
remain = strlen(name);
npnt = name;
while(remain){
use = remain;
need_ce = 0;
/* Can we fit this SUSP and a CE entry? */
if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
/* Only room for 256 per SUSP field */
if(use > 0xf8) use = 0xf8;
/* First build the posix name field */
Rock[ipnt++] ='N';
Rock[ipnt++] ='M';
Rock[ipnt++] = NM_SIZE + use;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = (remain != use ? 1 : 0);
flagval |= (1<<3);
strncpy((char *)&Rock[ipnt], npnt, use);
npnt += use;
ipnt += use;
remain -= use;
if(remain && need_ce) add_CE_entry();
};
};
/*
* Add the posix modes
*/
if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='X';
Rock[ipnt++] = PX_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<0);
set_733((char*)Rock + ipnt, lstatbuf->st_mode);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_uid);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_gid);
ipnt += 8;
/*
* Check for special devices
*/
#ifndef NON_UNIXFS
if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='N';
Rock[ipnt++] = PN_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<1);
#if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)
set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
ipnt += 8;
set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
ipnt += 8;
#else
/*
* If we don't have sysmacros.h, then we have to guess as to how
* best to pick apart the device number for major/minor.
* Note: this may very well be wrong for many systems, so
* it is always best to use the major/minor macros if the
* system supports it.
*/
if(sizeof(dev_t) <= 2) {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
ipnt += 8;
}
else if(sizeof(dev_t) <= 4) {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
ipnt += 8;
}
else {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
ipnt += 8;
}
#endif
};
#endif
/*
* Check for and symbolic links. VMS does not have these.
*/
if (S_ISLNK(lstatbuf->st_mode)){
int lenpos, lenval, j0, j1;
int nchar;
unsigned char * cpnt, *cpnt1;
nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff));
symlink_buff[nchar < 0 ? 0 : nchar] = 0;
nchar = strlen((char *) symlink_buff);
set_733(s_entry->isorec.size, 0);
cpnt = &symlink_buff[0];
flagval |= (1<<2);
if (! split_SL_field)
{
int sl_bytes = 0;
for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++)
{
if (*cpnt1 == '/')
{
sl_bytes += 4;
}
else
{
sl_bytes += 1;
}
}
if (sl_bytes > 250)
{
/*
* the symbolic link won't fit into one SL System Use Field
* print an error message and continue with splited one
*/
fprintf (stderr, _("symbolic link `%s' too long for one SL System Use Field, splitting"), cpnt);
}
if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry();
}
while(nchar){
if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
Rock[ipnt++] ='S';
Rock[ipnt++] ='L';
lenpos = ipnt;
Rock[ipnt++] = SL_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0; /* Flags */
lenval = 5;
while(*cpnt){
cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
if(cpnt1) {
nchar--;
*cpnt1 = 0;
};
/* We treat certain components in a special way. */
if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_PARENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 2;
} else if(cpnt[0] == '.' && cpnt[1] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_CURRENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 1;
} else if(cpnt[0] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_ROOT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
} else {
/* If we do not have enough room for a component, start
a new continuations segment now */
if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) :
MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt)))
{
add_CE_entry();
if(cpnt1)
{
*cpnt1 = '/';
nchar++;
cpnt1 = NULL; /* A kluge so that we can restart properly */
}
break;
}
j0 = strlen((char *) cpnt);
while(j0) {
j1 = j0;
if(j1 > 0xf8) j1 = 0xf8;
need_ce = 0;
if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
Rock[ipnt++] = j1;
strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
ipnt += j1;
lenval += j1 + 2;
cpnt += j1;
nchar -= j1; /* Number we processed this time */
j0 -= j1;
if(need_ce) {
add_CE_entry();
if(cpnt1) {
*cpnt1 = '/';
nchar++;
cpnt1 = NULL; /* A kluge so that we can restart properly */
}
break;
}
}
};
if(cpnt1) {
cpnt = cpnt1 + 1;
} else
break;
}
Rock[lenpos] = lenval;
if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
} /* while nchar */
} /* Is a symbolic link */
/*
* Add in the Rock Ridge TF time field
*/
if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
Rock[ipnt++] ='T';
Rock[ipnt++] ='F';
Rock[ipnt++] = TF_SIZE;
Rock[ipnt++] = SU_VERSION;
#ifdef __QNX__
Rock[ipnt++] = 0x0f;
#else
Rock[ipnt++] = 0x0e;
#endif
flagval |= (1<<7);
#ifdef __QNX__
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
ipnt += 7;
#endif
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
ipnt += 7;
/*
* Add in the Rock Ridge RE time field
*/
if(deep_opt & NEED_RE){
if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
Rock[ipnt++] ='R';
Rock[ipnt++] ='E';
Rock[ipnt++] = RE_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<6);
};
/*
* Add in the Rock Ridge PL record, if required.
*/
if(deep_opt & NEED_PL){
if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='L';
Rock[ipnt++] = PL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<5);
};
/*
* Add in the Rock Ridge CL field, if required.
*/
if(deep_opt & NEED_CL){
if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
Rock[ipnt++] ='C';
Rock[ipnt++] ='L';
Rock[ipnt++] = CL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<4);
};
#ifndef VMS
/* If transparent compression was requested, fill in the correct
field for this file */
if(transparent_compression &&
S_ISREG(lstatbuf->st_mode) &&
strlen(name) > 3 &&
strcmp(name + strlen(name) - 3,".gZ") == 0){
FILE * zipfile;
char * checkname;
unsigned int file_size;
unsigned char header[8];
int OK_flag;
/* First open file and verify that the correct algorithm was used */
file_size = 0;
OK_flag = 1;
zipfile = fopen(whole_name, "rb");
if (fread (header, 1, sizeof (header), zipfile) != sizeof(header))
error (1, errno, "fread");
/* Check some magic numbers from gzip. */
if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
/* Make sure file was blocksized. */
if(((header[3] & 0x40) == 0)) OK_flag = 0;
/* OK, now go to the end of the file and get some more info */
if(OK_flag){
int status;
status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
if(status == -1) OK_flag = 0;
}
if(OK_flag){
if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
OK_flag = 0;
else {
int blocksize;
blocksize = (header[3] << 8) | header[2];
file_size = ((unsigned int)header[7] << 24) |
((unsigned int)header[6] << 16) |
((unsigned int)header[5] << 8) | header[4];
#if 0
fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
#endif
if(blocksize != SECTOR_SIZE) OK_flag = 0;
}
}
fclose(zipfile);
checkname = strdup(whole_name);
checkname[strlen(whole_name)-3] = 0;
zipfile = fopen(checkname, "rb");
if(zipfile) {
OK_flag = 0;
fprintf (stderr, _("Unable to insert transparent compressed file - name conflict\n"));
fclose(zipfile);
}
free(checkname);
if(OK_flag){
if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
Rock[ipnt++] ='Z';
Rock[ipnt++] ='Z';
Rock[ipnt++] = ZZ_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 'g'; /* Identify compression technique used */
Rock[ipnt++] = 'z';
Rock[ipnt++] = 3;
set_733((char*)Rock + ipnt, file_size); /* Real file size */
ipnt += 8;
};
}
#endif
/*
* Add in the Rock Ridge CE field, if required. We use this for the
* extension record that is stored in the root directory.
*/
if(deep_opt & NEED_CE) add_CE_entry();
/*
* Done filling in all of the fields. Now copy it back to a buffer for the
* file in question.
*/
/* Now copy this back to the buffer for the file */
Rock[flagpos] = flagval;
/* If there was a CE, fill in the size field */
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt - recstart);
s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
s_entry->total_rr_attr_size = ipnt;
s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
memcpy(s_entry->rr_attributes, Rock, ipnt);
return ipnt;
}
/* Guaranteed to return a single sector with the relevant info */
char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor,
char *, source, int *, size){
int lipnt = 0;
char * pnt;
int len_id, len_des, len_src;
len_id = strlen(id);
len_des = strlen(descriptor);
len_src = strlen(source);
Rock[lipnt++] ='E';
Rock[lipnt++] ='R';
Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
Rock[lipnt++] = 1;
Rock[lipnt++] = len_id;
Rock[lipnt++] = len_des;
Rock[lipnt++] = len_src;
Rock[lipnt++] = 1;
memcpy(Rock + lipnt, id, len_id);
lipnt += len_id;
memcpy(Rock + lipnt, descriptor, len_des);
lipnt += len_des;
memcpy(Rock + lipnt, source, len_src);
lipnt += len_src;
if(lipnt > SECTOR_SIZE)
error (1, 0, _("Extension record too long\n"));
pnt = (char *) e_malloc(SECTOR_SIZE);
memset(pnt, 0, SECTOR_SIZE);
memcpy(pnt, Rock, lipnt);
*size = lipnt;
return pnt;
}

1865
util/mkisofs/tree.c Normal file

File diff suppressed because it is too large Load diff

1483
util/mkisofs/write.c Normal file

File diff suppressed because it is too large Load diff

76
util/pci.c Normal file
View file

@ -0,0 +1,76 @@
/* pci.c - Generic PCI interfaces. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,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/pci.h>
#include <grub/dl.h>
#include <grub/util/misc.h>
grub_pci_address_t
grub_pci_make_address (grub_pci_device_t dev, int reg)
{
grub_pci_address_t ret;
ret.dev = dev;
ret.pos = reg << 2;
return ret;
}
void
grub_pci_iterate (grub_pci_iteratefunc_t hook)
{
struct pci_device_iterator *iter;
struct pci_slot_match slot;
struct pci_device *dev;
slot.domain = PCI_MATCH_ANY;
slot.bus = PCI_MATCH_ANY;
slot.dev = PCI_MATCH_ANY;
slot.func = PCI_MATCH_ANY;
iter = pci_slot_match_iterator_create (&slot);
while ((dev = pci_device_next (iter)))
hook (dev, dev->vendor_id | (dev->device_id << 16));
pci_iterator_destroy (iter);
}
void *
grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
grub_size_t size)
{
void *addr;
int err;
err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
if (err)
grub_util_error ("mapping 0x%x failed (error %d)\n", base, err);
return addr;
}
void
grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
grub_size_t size)
{
pci_device_unmap_range (dev, mem, size);
}
GRUB_MOD_INIT (pci)
{
pci_system_init ();
}
GRUB_MOD_FINI (pci)
{
pci_system_cleanup ();
}

View file

@ -1,7 +1,7 @@
#! /bin/sh -e
# Make GRUB rescue image
# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 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
@ -30,7 +30,7 @@ target_cpu=@target_cpu@
platform=@platform@
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
# Usage: usage
# Print the usage.
@ -42,20 +42,17 @@ Make GRUB rescue image.
-h, --help print this message and exit
-v, --version print the version information and exit
--modules=MODULES pre-load specified modules MODULES
--overlay=DIR overlay directory DIR in the memdisk image
--pkglibdir=DIR use images from directory DIR instead of ${pkglibdir}
--pkglibdir=DIR use images from directory DIR
default: ${pkglibdir}
--grub-mkimage=FILE use FILE as grub-mkimage
--image-type=TYPE select floppy or cdrom (default)
grub-mkimage generates a bootable rescue image of the specified type.
grub-mkimage generates a bootable rescue CD image for PowerMac and CHRP.
Report bugs to <grub-devel@gnu.org>.
Report bugs to <bug-grub@gnu.org>.
EOF
}
image_type=cdrom
input_dir=${pkglibdir}
grub_mkimage=grub-mkimage
# Check the arguments.
for option in "$@"; do
@ -64,24 +61,14 @@ for option in "$@"; do
usage
exit 0 ;;
-v | --version)
echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})"
exit 0 ;;
--modules=*)
modules=`echo "$option" | sed 's/--modules=//'` ;;
--overlay=*)
overlay=`echo "$option" | sed 's/--overlay=//'` ;;
--pkglibdir=*)
input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;;
--grub-mkimage=*)
grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
--image-type=*)
image_type=`echo "$option" | sed 's/--image-type=//'`
case "$image_type" in
floppy|cdrom) ;;
*)
echo "Unknown image type \`$image_type'" 1>&2
exit 1 ;;
esac ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
@ -102,41 +89,27 @@ if test "x$output_image" = x; then
exit 1
fi
if [ "x${image_type}" = "xfloppy" ] ; then
floppy_image=${output_image}
else
floppy_image=`mktemp`
if [ "x${modules}" = "x" ] ; then
modules=`cd ${input_dir}/ && ls *.mod`
fi
memdisk_dir=`mktemp -d`
mkdir -p ${memdisk_dir}/boot/grub
cp ${input_dir}/*.mod \
${input_dir}/command.lst ${input_dir}/moddep.lst ${input_dir}/fs.lst \
${memdisk_dir}/boot/grub/
if test "x$overlay" = x ; then : ; else
cp -dpR ${overlay}/* ${memdisk_dir}/
fi
memdisk_img=`mktemp`
tar -C ${memdisk_dir} -cf ${memdisk_img} boot
rm -rf ${memdisk_dir}
core_img=`mktemp`
${grub_mkimage} -d ${input_dir}/ -m ${memdisk_img} -o ${core_img} memdisk cpio biosdisk ${modules}
rm -f ${memdisk_img}
cat ${input_dir}/boot.img ${core_img} /dev/zero | dd bs=1024 count=1440 > $floppy_image
rm -f ${core_img}
if [ "x${image_type}" = "xfloppy" ] ; then
exit 0
fi
map_file=`mktemp`
cat >${map_file} <<EOF
# EXTN XLate CREATOR TYPE Comment
grub.img Raw 'UNIX' 'tbxi' "bootstrap"
EOF
iso_dir=`mktemp -d`
cp $floppy_image ${iso_dir}/floppy.img
genisoimage -b floppy.img -o ${output_image} -r ${iso_dir}
rm -rf ${iso_dir}
boot_dir=${iso_dir}/boot/grub
mkdir ${iso_dir}/boot
mkdir ${boot_dir}
core_img=${boot_dir}/grub.img
${grub_mkimage} -n -d ${input_dir}/ -o ${core_img} ${modules}
genisoimage -hfs -part -no-desktop -r -J -o ${output_image} \
-map ${map_file} -hfs-bless ${boot_dir} -chrp-boot -sysid PPC \
${iso_dir}
rm -f ${floppy_image}
rm -rf ${iso_dir}
rm -f ${map_file}
exit 0

View file

@ -1,33 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2007 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 ();
}

View file

@ -1,7 +1,7 @@
/* raid.c - RAID support for GRUB utils. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
* Copyright (C) 2006,2007,2008 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
@ -20,6 +20,7 @@
/* We only support RAID on Linux. */
#ifdef __linux__
#include <grub/util/misc.h>
#include <grub/util/raid.h>
#include <string.h>
#include <fcntl.h>
@ -31,7 +32,7 @@
#include <linux/raid/md_p.h>
#include <linux/raid/md_u.h>
char *
static char *
grub_util_getdiskname (int major, int minor)
{
char *name = xmalloc (15);
@ -49,8 +50,8 @@ grub_util_getdiskname (int major, int minor)
else if (major == SCSI_DISK0_MAJOR)
sprintf (name, "/dev/sd%c", 'a' + minor / 16);
else
grub_util_error ("Unknown device number: %d, %d", major, minor);
grub_util_error ("unknown device number: %d, %d", major, minor);
return name;
}
@ -71,7 +72,7 @@ grub_util_raid_getmembers (char *name)
fd = open (devname, O_RDONLY);
if (fd == -1)
grub_util_error ("Can't open %s: %s", devname, strerror (errno));
grub_util_error ("can't open %s: %s", devname, strerror (errno));
free (devname);
@ -80,9 +81,9 @@ grub_util_raid_getmembers (char *name)
grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
if (version.major != 0 || version.minor != 90)
grub_util_error ("Unsupported RAID version: %d.%d",
grub_util_error ("unsupported RAID version: %d.%d",
version.major, version.minor);
ret = ioctl (fd, GET_ARRAY_INFO, &info);
if (ret != 0)
grub_util_error ("ioctl GET_ARRAY_INFO error: %s", strerror (errno));
@ -104,7 +105,7 @@ grub_util_raid_getmembers (char *name)
}
devicelist[j] = NULL;
return devicelist;
}

View file

@ -75,7 +75,7 @@ static struct dep_list *
read_dep_list (FILE *fp)
{
struct dep_list *dep_list = 0;
while (fgets (buf, sizeof (buf), fp))
{
char *p;
@ -91,7 +91,7 @@ read_dep_list (FILE *fp)
dep = xmalloc (sizeof (*dep));
dep->name = xstrdup (buf);
dep->list = 0;
dep->next = dep_list;
dep_list = dep;
@ -101,7 +101,7 @@ read_dep_list (FILE *fp)
struct mod_list *mod;
char *name;
/* Skip white spaces. */
/* Skip whitespace. */
while (*p && isspace (*p))
p++;
@ -110,12 +110,12 @@ read_dep_list (FILE *fp)
name = p;
/* Skip non-WSPs. */
/* Skip non-whitespace. */
while (*p && ! isspace (*p))
p++;
*p++ = '\0';
mod = (struct mod_list *) xmalloc (sizeof (*mod));
mod->name = xstrdup (name);
mod->next = dep->list;
@ -131,7 +131,7 @@ get_module_name (const char *str)
{
char *base;
char *ext;
base = strrchr (str, '/');
if (! base)
base = (char *) str;
@ -142,13 +142,13 @@ get_module_name (const char *str)
if (ext && strcmp (ext, ".mod") == 0)
{
char *name;
name = xmalloc (ext - base + 1);
memcpy (name, base, ext - base);
name[ext - base] = '\0';
return name;
}
return xstrdup (base);
}
@ -159,7 +159,7 @@ get_module_path (const char *prefix, const char *str)
char *base;
char *ext;
char *ret;
ext = strrchr (str, '.');
if (ext && strcmp (ext, ".mod") == 0)
base = xstrdup (str);
@ -168,7 +168,7 @@ get_module_path (const char *prefix, const char *str)
base = xmalloc (strlen (str) + 4 + 1);
sprintf (base, "%s.mod", str);
}
dir = strchr (str, '/');
if (dir)
return base;
@ -189,7 +189,7 @@ add_module (const char *dir,
struct grub_util_path_list *path;
struct mod_list *mod;
struct dep_list *dep;
mod_name = get_module_name (name);
/* Check if the module has already been added. */

View file

@ -0,0 +1,300 @@
/* grub-mkimage.c - make a bootable image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009,2010 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/i18n.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>
#include "progname.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 = OBJ_TYPE_ELF;
header->size = grub_host_to_target32 (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 = OBJ_TYPE_MEMDISK;
header->size = grub_host_to_target32 (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 `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [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\
", program_name, 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;
set_program_name (argv[0]);
grub_util_init_nls ();
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

@ -1,6 +1,7 @@
/* grub-ofpathname.c - Find OpenBOOT path for a given device */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
* Copyright (C) 2009,2010 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
@ -16,18 +17,31 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <setjmp.h>
#include <grub/util/misc.h>
#include <grub/util/ofpath.h>
void
grub_reboot (void)
{
longjmp (main_env, 1);
}
#include <grub/i18n.h>
void
grub_halt (int no_apm __attribute__ ((unused)))
#include "progname.h"
int main(int argc, char **argv)
{
grub_reboot ();
char *of_path;
set_program_name (argv[0]);
grub_util_init_nls ();
if (argc != 2)
{
printf("Usage: %s DEVICE\n", program_name);
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,655 @@
/* grub-setup.c - make GRUB usable */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 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/i18n.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/fs.h>
#include <grub/partition.h>
#include <grub/msdos_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>
#include "progname.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 second 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 char *compute_dest_ofpath (const char *dest)
{
int len = strlen (dest);
char *res, *p, c;
res = xmalloc (len);
p = res;
while ((c = *dest++) != '\0')
{
if (c == '\\' && *dest == ',')
{
*p++ = ',';
dest++;
}
else
*p++ = c;
}
*p++ = '\0';
return res;
}
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, *dest_ofpath;
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;
}
dest_ofpath = compute_dest_ofpath (dest);
/* 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', dest is `%s', and dest_ofpath is `%s'",
root, dest, dest_ofpath);
/* 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_ofpath);
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 `%s --help' for more information.\n", program_name);
else
printf ("\
Usage: %s [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\
", program_name,
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;
set_program_name (argv[0]);
grub_util_init_nls ();
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

@ -1,87 +0,0 @@
#! /usr/bin/ruby -w
#
# Copyright (C) 2003 Free Software Foundation, Inc.
#
# This unifont2pff.rb is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# The magic number of the font file.
MAGIC = "PPF\x7f"
def usage(status = 0)
puts "Usage: ruby unifont2pff.rb [RANGE ...] FILE"
exit(status)
end
if ARGV.length == 0
usage(1)
end
file = ARGV.pop
ranges = []
ARGV.each do |range|
if /\A0x([0-9a-fA-F]+)[:-]0x([0-9a-fA-F]+)\z/ =~ range
ranges << [$1.hex, $2.hex]
elsif /\A0x([0-9a-fA-F]+)\z/ =~ range
ranges << [$1.hex, $1.hex]
elsif /\A([0-9]+)[:-]([0-9]+)\z/ =~ range
ranges << [$1.to_i, $2.to_i]
elsif /\A([0-9]+)\z/ =~ range
ranges << [$1.to_i, $1.to_i]
else
usage(1)
end
end
def ranges.contain?(code)
if self.empty?
true
else
self.each do |r|
return true if r[0] <= code and r[1] >= code
end
false
end
end
fonts = []
IO.foreach(file) do |line|
if /^([0-9A-F]+):([0-9A-F]+)$/ =~ line
code = $1.hex
next unless ranges.contain?(code)
bitmap = $2
if bitmap.size != 32 and bitmap.size != 64
raise "invalid bitmap size: #{bitmap}"
end
fonts << [code, bitmap]
else
raise "invalid line format: #{line}"
end
end
fonts.sort! {|a,b| a[0] <=> b[0]}
# Output the result.
print MAGIC
print [fonts.size].pack('V')
offset = 8 + fonts.size * 8
fonts.each do |f|
print [f[0]].pack('V')
print [offset].pack('V')
offset += 4 + 16 * f[1].size / 32
end
fonts.each do |f|
print [f[1].size / 32].pack('V')
print f[1].scan(/../).collect {|a| a.hex}.pack('C*')
end

View file

@ -1,164 +0,0 @@
#! /bin/sh -e
# Generate grub.cfg by inspecting /boot contents.
# Copyright (C) 2006,2007,2008 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/>.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
sbindir=@sbindir@
libdir=@libdir@
sysconfdir=@sysconfdir@
grub_prefix=`echo /boot/grub | sed ${transform}`
grub_cfg=${grub_prefix}/grub.cfg
update_grub_dir=${sysconfdir}/grub.d
platform=@platform@
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
# for convert_system_path_to_grub_path(), font_path()
. ${libdir}/grub/update-grub_lib
if [ "x$UID" = "x" ] ; then
UID=`id -u`
fi
if [ "$UID" != 0 ] ; then
echo "$0: You must run this as root" >&2
exit 1
fi
if [ "$1" = "-y" ] ; then
echo "$0: warning: Ignoring -y option (no longer needed)." >&2
fi
set $grub_mkdevicemap dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
set $grub_probe dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
mkdir -p ${grub_prefix}
if test -e ${grub_prefix}/device.map ; then : ; else
grub-mkdevicemap
fi
# Device containing our userland. Typically used for root= parameter.
GRUB_DEVICE="`grub-probe --target=device /`"
# Filesystem for the device containing our userland. Used for stuff like
# choosing Hurd filesystem module.
GRUB_FS="`grub-probe --target=fs / 2> /dev/null || echo unknown`"
# GRUB path to /. Only used for "set root=". Not critical.
GRUB_DRIVE="`grub-probe --target=drive /`" || true
# GRUB path to /boot
GRUB_DRIVE_BOOT="`convert_system_path_to_grub_path /boot`"
# GRUB path to /boot/grub
GRUB_DRIVE_BOOT_GRUB="`convert_system_path_to_grub_path /boot/grub`"
if test -f ${sysconfdir}/default/grub ; then
. ${sysconfdir}/default/grub
fi
# if ${GRUB_TERMINAL} is set, check it has a sane value. if undefined,
# fallback to our default
case ${platform}:${GRUB_TERMINAL} in
pc:) GRUB_TERMINAL=gfxterm ;;
pc:console | pc:serial) ;;
ieee1275:) GRUB_TERMINAL=ofconsole ;;
ieee1275:ofconsole) ;;
*:) GRUB_TERMINAL=console ;;
*:*) echo "Invalid terminal \"${GRUB_TERMINAL}\"" >&2 ; exit 1 ;;
esac
# check for terminals that require fonts
case ${GRUB_TERMINAL} in
gfxterm)
if path=`font_path` ; then
GRUB_FONT_PATH="`convert_system_path_to_grub_path ${path}`"
GRUB_PRELOAD_MODULES="`${GRUB_PRELOAD_MODULES} ${grub_probe} -t abstraction ${path}`"
else
# fallback to console
GRUB_TERMINAL=console
fi
;;
esac
# does our terminal support utf-8 ?
case ${platform}:${GRUB_TERMINAL} in
*:gfxterm) ;;
*:*)
# make sure all our children behave in conformance with ascii..
export LANG=C
;;
esac
# These are defined in this script, export them here so that user can
# override them.
export GRUB_DEVICE GRUB_FS GRUB_DRIVE GRUB_DRIVE_BOOT GRUB_DRIVE_BOOT_GRUB GRUB_FONT_PATH GRUB_PRELOAD_MODULES
# These are optional, user-defined variables.
export GRUB_DEFAULT GRUB_TIMEOUT GRUB_DISTRIBUTOR GRUB_CMDLINE_LINUX GRUB_TERMINAL GRUB_SERIAL_COMMAND
exec > ${grub_cfg}.new
chmod 444 ${grub_cfg}.new
echo "Updating ${grub_cfg} ..." >&2
cat << EOF
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by $0 using templates
# from ${update_grub_dir} and settings from ${sysconfdir}/default/grub
#
EOF
for i in ${update_grub_dir}/* ; do
case "$i" in
# emacsen backup files. FIXME: support other editors
*~) ;;
*)
if grub_file_is_not_garbage "$i" && test -x "$i" ; then
echo
echo "### BEGIN $i ###"
"$i"
echo "### END $i ###"
fi
;;
esac
done
# none of the children aborted with error, install the new grub.cfg
mv ${grub_cfg}.new ${grub_cfg}
echo "done" >&2

View file

@ -1,4 +1,4 @@
# Helper library for update-grub
# stub for new grub-mkconfig_lib
# Copyright (C) 2007,2008 Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
@ -14,109 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
transform="@program_transform_name@"
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sbindir=@sbindir@
pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`
libdir=@libdir@
grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
. ${libdir}/grub/grub-mkconfig_lib
make_system_path_relative_to_its_root ()
{
path=$1
# abort if file doesn't exist
if test -e $path ; then : ;else
return 1
fi
# canonicalize
if path=`readlink -f $path` ; then : ; else
return 1
fi
# if not a directory, climb up to the directory containing it
if test -d $path ; then
dir=$path
else
dir=`echo $path | sed -e "s,/[^/]*$,,g"`
fi
num=`stat -c %d $dir`
# this loop sets $dir to the root directory of the filesystem we're inspecting
while : ; do
parent=`readlink -f $dir/..`
if [ "x`stat -c %d $parent`" = "x$num" ] ; then : ; else
# $parent is another filesystem; we found it.
break
fi
if [ "x$dir" = "x/" ] ; then
# / is our root.
break
fi
dir=$parent
done
echo $path | sed -e "s,^$dir,/,g" -e "s,//,/,g"
}
convert_system_path_to_grub_path ()
{
path=$1
# abort if file doesn't exist
if test -e $path ; then : ;else
return 1
fi
# abort if file is in a filesystem we can't read
if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else
return 1
fi
if drive=`${grub_probe} -t drive $path` ; then : ; else
return 1
fi
if relative_path=`make_system_path_relative_to_its_root $path` ; then : ; else
return 1
fi
# remove any trailing slash, even if that slash is everything we have
relative_path=`echo ${relative_path} | sed -e "s,/*$,,g"`
echo ${drive}${relative_path}
}
font_path ()
{
# Prefer system path for space reasons (/boot/grub might be a very small
# partition in case of OpenFirmware, etc).
for dir in ${pkgdatadir} /usr/share/grub /boot/grub ; do
# Prefer complete fonts over incomplete ones.
for basename in unicode unifont ascii ; do
path="${dir}/${basename}.pff"
if convert_system_path_to_grub_path ${path} > /dev/null ; then
echo "${path}"
return 0
fi
done
done
return 1
}
grub_file_is_not_garbage ()
{
if test -f "$1" ; then
case "$1" in
*.dpkg-dist|*.dpkg-old|*.dpkg-tmp) return 1 ;; # debian dpkg
esac
else
return 1
fi
return 0
}
grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead"

195
util/usb.c Normal file
View file

@ -0,0 +1,195 @@
/* usb.c -- libusb USB support for GRUB. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 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/misc.h>
#include <grub/mm.h>
#include <usb.h>
#include <grub/usb.h>
#include <grub/dl.h>
static struct grub_usb_controller_dev usb_controller =
{
.name = "libusb"
};
static struct grub_usb_device *grub_usb_devs[128];
struct usb_bus *busses;
static grub_err_t
grub_libusb_devices (void)
{
struct usb_bus *bus;
int last = 0;
busses = usb_get_busses();
for (bus = busses; bus; bus = bus->next)
{
struct usb_device *usbdev;
struct grub_usb_device *dev;
for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
{
struct usb_device_descriptor *desc = &usbdev->descriptor;
grub_err_t err;
if (! desc->bcdUSB)
continue;
dev = grub_malloc (sizeof (*dev));
if (! dev)
return grub_errno;
dev->data = usbdev;
/* Fill in all descriptors. */
err = grub_usb_device_initialize (dev);
if (err)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
/* Register the device. */
grub_usb_devs[last++] = dev;
}
}
return GRUB_USB_ERR_NONE;
}
int
grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
{
int i;
for (i = 0; i < 128; i++)
{
if (grub_usb_devs[i])
{
if (hook (grub_usb_devs[i]))
return 1;
}
}
return 0;
}
grub_usb_err_t
grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
{
return GRUB_USB_ERR_NONE;
}
grub_usb_err_t
grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
grub_uint8_t request, grub_uint16_t value,
grub_uint16_t index, grub_size_t size, char *data)
{
usb_dev_handle *devh;
struct usb_device *d = dev->data;
devh = usb_open (d);
if (usb_control_msg (devh, reqtype, request,
value, index, data, size, 20) < 0)
{
usb_close (devh);
return GRUB_USB_ERR_STALL;
}
usb_close (devh);
return GRUB_USB_ERR_NONE;
}
grub_usb_err_t
grub_usb_bulk_read (grub_usb_device_t dev,
int endpoint, grub_size_t size, char *data)
{
usb_dev_handle *devh;
struct usb_device *d = dev->data;
devh = usb_open (d);
if (usb_claim_interface (devh, 0) < 1)
{
usb_close (devh);
return GRUB_USB_ERR_STALL;
}
if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
{
usb_close (devh);
return GRUB_USB_ERR_STALL;
}
usb_release_interface (devh, 0);
usb_close (devh);
return GRUB_USB_ERR_NONE;
}
grub_usb_err_t
grub_usb_bulk_write (grub_usb_device_t dev,
int endpoint, grub_size_t size, char *data)
{
usb_dev_handle *devh;
struct usb_device *d = dev->data;
devh = usb_open (d);
if (usb_claim_interface (devh, 0) < 0)
goto fail;
if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
goto fail;
if (usb_release_interface (devh, 0) < 0)
goto fail;
usb_close (devh);
return GRUB_USB_ERR_NONE;
fail:
usb_close (devh);
return GRUB_USB_ERR_STALL;
}
GRUB_MOD_INIT (libusb)
{
usb_init();
usb_find_busses();
usb_find_devices();
if (grub_libusb_devices ())
return;
grub_usb_controller_dev_register (&usb_controller);
return;
}
GRUB_MOD_FINI (libusb)
{
return;
}