add a workaround for the bug in Linux into the grub shell.
This commit is contained in:
parent
028049bbd4
commit
7ab4e9c240
9 changed files with 350 additions and 51 deletions
33
ChangeLog
33
ChangeLog
|
@ -1,3 +1,36 @@
|
||||||
|
2000-08-09 OKUJI Yoshinori <okuji@gnu.org>
|
||||||
|
|
||||||
|
* stage2/builtins.c [GRUB_UTIL]: Include stdio.h.
|
||||||
|
(embed_func) [GRUB_UTIL && __linux__]: When embedding a Stage
|
||||||
|
1.5 into a partition, call write_to_partition instead of
|
||||||
|
biosdisk.
|
||||||
|
(install_func): Set DEST_PARTITION to the partition where Stage
|
||||||
|
1 resides.
|
||||||
|
Set SRC_PART_START to the starting address of the partition
|
||||||
|
where Stage 2 resides.
|
||||||
|
(install_func) [GRUB_UTIL]: Set STAGE2_OS_FILE to the file name
|
||||||
|
of Stage 2 under an OS, if the new option "--stage2" is
|
||||||
|
specified. Otherwise, set it to null.
|
||||||
|
If STAGE2_OS_FILE is not null, modify the Stage 2 via the
|
||||||
|
filesystem serviced by the OS.
|
||||||
|
(install_func) [GRUB_UTIL && __linux__]: If STAGE2_OS_FILE is
|
||||||
|
null but the Stage2 resides in a partition, use
|
||||||
|
write_to_partition.
|
||||||
|
If DEST_PARTITION is not 0xFFFFFF, use write_to_partition, to
|
||||||
|
embed Stage 1.
|
||||||
|
(setup_func) [GRUB_UTIL]: If --stage2 is specified, set
|
||||||
|
STAGE2_ARG to the string pointing to the option. Otherwise, set
|
||||||
|
it to null.
|
||||||
|
(setup_func) [!GRUB_UTIL]: Set STAGE2_ARG to null.
|
||||||
|
(setup_func): If STAGE2_ARG is not null, add STAGE2_ARG and a
|
||||||
|
space character into CMD_ARG.
|
||||||
|
* lib/device.c (_LARGEFILE_SOURCE): Defined.
|
||||||
|
(_FILE_OFFSET_BITS): Likewise.
|
||||||
|
[__linux__] (write_to_partition): New function.
|
||||||
|
* lib/device.h [__linux__] (write_to_partition): Declared.
|
||||||
|
* util/grub-install.in: Specify the option "--stage2" for the
|
||||||
|
command "setup".
|
||||||
|
|
||||||
2000-08-04 Jochen Hoenicke <jochen@gnu.org>
|
2000-08-04 Jochen Hoenicke <jochen@gnu.org>
|
||||||
|
|
||||||
* stage2/fsys_fat.c (fat_superblock): clust_eof_marker added.
|
* stage2/fsys_fat.c (fat_superblock): clust_eof_marker added.
|
||||||
|
|
8
NEWS
8
NEWS
|
@ -9,6 +9,14 @@ New in 0.5.96 - XXXX-XX-XX:
|
||||||
* Now GRUB is compliant with the Linux/i386 boot protocol version 2.02.
|
* Now GRUB is compliant with the Linux/i386 boot protocol version 2.02.
|
||||||
* The network support is updated to Etherboot-4.6.4.
|
* The network support is updated to Etherboot-4.6.4.
|
||||||
* Symlinks in ReiserFS are supported.
|
* Symlinks in ReiserFS are supported.
|
||||||
|
* Add a workaround into the grub shell, so that it works fine even under
|
||||||
|
Linux 2.4.
|
||||||
|
* Add a new option `--stage2' into the commands "install" and "setup",
|
||||||
|
to let the grub shell know what the file name of Stage 2 is under your
|
||||||
|
operating system. You must specify the option correctly, if you cannot
|
||||||
|
unmount the partition where GRUB images reside. We'd recommend _not_
|
||||||
|
using those commands directly, but using the utility "grub-install"
|
||||||
|
instead, because this is safer.
|
||||||
|
|
||||||
New in 0.5.95 - 2000-06-27:
|
New in 0.5.95 - 2000-06-27:
|
||||||
* NetBSD ELF kernel support is added. You have to specify the new option
|
* NetBSD ELF kernel support is added. You have to specify the new option
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
||||||
.TH GRUB-INSTALL "8" "July 2000" "grub-install (GNU GRUB 0.5.96)" FSF
|
.TH GRUB-INSTALL "8" "August 2000" "grub-install (GNU GRUB 0.5.96)" FSF
|
||||||
.SH NAME
|
.SH NAME
|
||||||
grub-install \- install GRUB on your drive
|
grub-install \- install GRUB on your drive
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
||||||
.TH GRUB "8" "July 2000" "GNU GRUB 0.5.96" FSF
|
.TH GRUB "8" "August 2000" "GNU GRUB 0.5.96" FSF
|
||||||
.SH NAME
|
.SH NAME
|
||||||
GRUB \- the grub shell
|
GRUB \- the grub shell
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.020.
|
||||||
.TH MBCHK "1" "July 2000" "mbchk (GNU GRUB 0.5.96)" FSF
|
.TH MBCHK "1" "August 2000" "mbchk (GNU GRUB 0.5.96)" FSF
|
||||||
.SH NAME
|
.SH NAME
|
||||||
mbchk \- check the format of a Multiboot kernel
|
mbchk \- check the format of a Multiboot kernel
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
83
lib/device.c
83
lib/device.c
|
@ -18,6 +18,11 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Try to use glibc's transparant LFS support. */
|
||||||
|
#define _LARGEFILE_SOURCE 1
|
||||||
|
/* lseek becomes synonymous with lseek64. */
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -30,6 +35,11 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#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 */
|
# include <sys/ioctl.h> /* ioctl */
|
||||||
# include <linux/hdreg.h> /* HDIO_GETGEO */
|
# include <linux/hdreg.h> /* HDIO_GETGEO */
|
||||||
# include <linux/major.h> /* FLOPPY_MAJOR */
|
# include <linux/major.h> /* FLOPPY_MAJOR */
|
||||||
|
@ -508,3 +518,76 @@ restore_device_map (char **map)
|
||||||
|
|
||||||
free (map);
|
free (map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
/* Linux-only function, because Linux has a bug that the disk cache for
|
||||||
|
a whole disk is not consistent with the one for a partition of the
|
||||||
|
disk. */
|
||||||
|
int
|
||||||
|
write_to_partition (char **map, int drive, int partition,
|
||||||
|
int sector, int size, const char *buf)
|
||||||
|
{
|
||||||
|
char dev[64]; /* XXX */
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if ((partition & 0x00FF00) != 0x00FF00)
|
||||||
|
{
|
||||||
|
/* If the partition is a BSD partition, it is difficult to
|
||||||
|
obtain the representation in Linux. So don't support that. */
|
||||||
|
errnum = ERR_DEV_VALUES;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (map[drive] != 0);
|
||||||
|
sprintf (dev, "%s%d", map[drive], ((partition >> 16) & 0xFF) + 1);
|
||||||
|
|
||||||
|
/* Open the partition. */
|
||||||
|
fd = open (dev, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
errnum = ERR_NO_PART;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
||||||
|
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
||||||
|
/* Maybe libc doesn't have large file support. */
|
||||||
|
{
|
||||||
|
loff_t offset, result;
|
||||||
|
static int _llseek (uint filedes, ulong hi, ulong lo,
|
||||||
|
loff_t *res, uint wh);
|
||||||
|
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
||||||
|
loff_t *, res, uint, wh);
|
||||||
|
|
||||||
|
offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
|
||||||
|
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||||
|
{
|
||||||
|
errnum = ERR_DEV_VALUES;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
|
||||||
|
|
||||||
|
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||||
|
{
|
||||||
|
errnum = ERR_DEV_VALUES;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sync (); /* Paranoia. */
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
|
@ -39,4 +39,9 @@ extern int init_device_map (char ***map, const char *map_file,
|
||||||
int no_floppies);
|
int no_floppies);
|
||||||
extern void restore_device_map (char **map);
|
extern void restore_device_map (char **map);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
extern int write_to_partition (char **map, int drive, int partition,
|
||||||
|
int offset, int size, const char *buf);
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#endif /* DEVICE_MAP_HEADER */
|
#endif /* DEVICE_MAP_HEADER */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
|
# include <stdio.h>
|
||||||
# include <device.h>
|
# include <device.h>
|
||||||
#else /* ! GRUB_UTIL */
|
#else /* ! GRUB_UTIL */
|
||||||
# include <apic.h>
|
# include <apic.h>
|
||||||
|
@ -851,7 +852,6 @@ embed_func (char *arg, int flags)
|
||||||
char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
|
char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
|
||||||
int len, size;
|
int len, size;
|
||||||
int sector;
|
int sector;
|
||||||
int i;
|
|
||||||
|
|
||||||
stage1_5 = arg;
|
stage1_5 = arg;
|
||||||
device = skip_to (0, stage1_5);
|
device = skip_to (0, stage1_5);
|
||||||
|
@ -929,20 +929,39 @@ embed_func (char *arg, int flags)
|
||||||
|
|
||||||
/* Clear the cache. */
|
/* Clear the cache. */
|
||||||
buf_track = -1;
|
buf_track = -1;
|
||||||
|
|
||||||
/* Now perform the embedding. */
|
/* Now perform the embedding. */
|
||||||
for (i = 0; i < size; i++)
|
#if defined(GRUB_UTIL) && defined(__linux__)
|
||||||
|
if (current_partition != 0xFFFFFF)
|
||||||
{
|
{
|
||||||
grub_memmove ((char *) SCRATCHADDR, stage1_5_buffer + i * SECTOR_SIZE,
|
/* If the grub shell is running under Linux and the user wants to
|
||||||
SECTOR_SIZE);
|
embed a Stage 1.5 into a partition instead of a MBR, use system
|
||||||
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom,
|
calls directly instead of biosdisk, because of the bug in
|
||||||
sector + i, 1, SCRATCHSEG))
|
Linux. *sigh* */
|
||||||
|
|
||||||
|
if (! write_to_partition (device_map, current_drive, current_partition,
|
||||||
|
sector - part_start, size, stage1_5_buffer))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* GRUB_UTIL && __linux__ */
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
errnum = ERR_WRITE;
|
grub_memmove ((char *) SCRATCHADDR,
|
||||||
return 1;
|
stage1_5_buffer + i * SECTOR_SIZE,
|
||||||
|
SECTOR_SIZE);
|
||||||
|
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom,
|
||||||
|
sector + i, 1, SCRATCHSEG))
|
||||||
|
{
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf (" %d sectors are embedded.\n", size);
|
grub_printf (" %d sectors are embedded.\n", size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1452,8 +1471,8 @@ install_func (char *arg, int flags)
|
||||||
char *config_filename = stage2_second_buffer + SECTOR_SIZE;
|
char *config_filename = stage2_second_buffer + SECTOR_SIZE;
|
||||||
char *dummy = config_filename + SECTOR_SIZE;
|
char *dummy = config_filename + SECTOR_SIZE;
|
||||||
int new_drive = 0xFF;
|
int new_drive = 0xFF;
|
||||||
int dest_drive, dest_sector;
|
int dest_drive, dest_partition, dest_sector;
|
||||||
int src_drive, src_partition;
|
int src_drive, src_partition, src_part_start;
|
||||||
int i;
|
int i;
|
||||||
struct geometry dest_geom, src_geom;
|
struct geometry dest_geom, src_geom;
|
||||||
int saved_sector;
|
int saved_sector;
|
||||||
|
@ -1471,6 +1490,12 @@ install_func (char *arg, int flags)
|
||||||
/* Was the last sector full? */
|
/* Was the last sector full? */
|
||||||
int last_length = SECTOR_SIZE;
|
int last_length = SECTOR_SIZE;
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
/* If the Stage 2 is in a partition mounted by an OS, this will store
|
||||||
|
the filename under the OS. */
|
||||||
|
char *stage2_os_file = 0;
|
||||||
|
#endif /* GRUB_UTIL */
|
||||||
|
|
||||||
/* Save the first sector of Stage2 in STAGE2_SECT. */
|
/* Save the first sector of Stage2 in STAGE2_SECT. */
|
||||||
static void disk_read_savesect_func (int sector, int offset, int length)
|
static void disk_read_savesect_func (int sector, int offset, int length)
|
||||||
{
|
{
|
||||||
|
@ -1522,10 +1547,23 @@ install_func (char *arg, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First, check the GNU-style long option. */
|
/* First, check the GNU-style long option. */
|
||||||
if (grub_memcmp ("--force-lba", arg, 11) == 0)
|
while (1)
|
||||||
{
|
{
|
||||||
is_force_lba = 1;
|
if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
|
||||||
arg = skip_to (0, arg);
|
{
|
||||||
|
is_force_lba = 1;
|
||||||
|
arg = skip_to (0, arg);
|
||||||
|
}
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
|
||||||
|
{
|
||||||
|
stage2_os_file = arg + sizeof ("--stage2=") - 1;
|
||||||
|
arg = skip_to (0, arg);
|
||||||
|
nul_terminate (stage2_os_file);
|
||||||
|
}
|
||||||
|
#endif /* GRUB_UTIL */
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage1_file = arg;
|
stage1_file = arg;
|
||||||
|
@ -1568,6 +1606,7 @@ install_func (char *arg, int flags)
|
||||||
|
|
||||||
/* Store the information for the destination device. */
|
/* Store the information for the destination device. */
|
||||||
dest_drive = current_drive;
|
dest_drive = current_drive;
|
||||||
|
dest_partition = current_partition;
|
||||||
dest_geom = buf_geom;
|
dest_geom = buf_geom;
|
||||||
dest_sector = part_start;
|
dest_sector = part_start;
|
||||||
|
|
||||||
|
@ -1612,6 +1651,7 @@ install_func (char *arg, int flags)
|
||||||
|
|
||||||
src_drive = current_drive;
|
src_drive = current_drive;
|
||||||
src_partition = current_partition;
|
src_partition = current_partition;
|
||||||
|
src_part_start = part_start;
|
||||||
src_geom = buf_geom;
|
src_geom = buf_geom;
|
||||||
|
|
||||||
if (! new_drive)
|
if (! new_drive)
|
||||||
|
@ -1810,16 +1850,65 @@ install_func (char *arg, int flags)
|
||||||
|
|
||||||
/* Copy the name. */
|
/* Copy the name. */
|
||||||
grub_strcpy (location, real_config_filename);
|
grub_strcpy (location, real_config_filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write it to the disk. */
|
/* Write it to the disk. */
|
||||||
buf_track = -1;
|
buf_track = -1;
|
||||||
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom,
|
|
||||||
saved_sector, 1, SCRATCHSEG))
|
#ifdef GRUB_UTIL
|
||||||
|
/* In the grub shell, access the Stage 2 via the OS filesystem
|
||||||
|
service, if possible. */
|
||||||
|
if (stage2_os_file)
|
||||||
{
|
{
|
||||||
errnum = ERR_WRITE;
|
FILE *fp;
|
||||||
goto fail;
|
|
||||||
|
fp = fopen (stage2_os_file, "r");
|
||||||
|
if (! fp)
|
||||||
|
{
|
||||||
|
errnum = ERR_FILE_NOT_FOUND;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
errnum = ERR_BAD_VERSION;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite ((const void *) SCRATCHADDR, 1, SECTOR_SIZE, fp)
|
||||||
|
!= SECTOR_SIZE)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# ifdef __linux__
|
||||||
|
/* Avoid the bug in Linux, which makes the disk cache for
|
||||||
|
the whole disk inconsistent with the one for the partition. */
|
||||||
|
if (current_partition != 0xFFFFFF)
|
||||||
|
{
|
||||||
|
if (! write_to_partition (device_map, current_drive,
|
||||||
|
current_partition,
|
||||||
|
saved_sector - part_start,
|
||||||
|
1,
|
||||||
|
(const char *) SCRATCHADDR))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif /* __linux__ */
|
||||||
|
#endif /* GRUB_UTIL */
|
||||||
|
{
|
||||||
|
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom,
|
||||||
|
saved_sector, 1, SCRATCHSEG))
|
||||||
|
{
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1827,31 +1916,90 @@ install_func (char *arg, int flags)
|
||||||
/* Clear the cache. */
|
/* Clear the cache. */
|
||||||
buf_track = -1;
|
buf_track = -1;
|
||||||
|
|
||||||
/* Write the modified first sector of Stage2 to the disk. */
|
/* Write the modified sectors of Stage2 to the disk. */
|
||||||
grub_memmove ((char *) SCRATCHADDR, stage2_first_buffer, SECTOR_SIZE);
|
#ifdef GRUB_UTIL
|
||||||
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom,
|
if (! is_stage1_5 && stage2_os_file)
|
||||||
stage2_first_sector, 1, SCRATCHSEG))
|
|
||||||
{
|
{
|
||||||
errnum = ERR_WRITE;
|
FILE *fp;
|
||||||
goto fail;
|
|
||||||
|
fp = fopen (stage2_os_file, "r");
|
||||||
|
if (! fp)
|
||||||
|
{
|
||||||
|
errnum = ERR_FILE_NOT_FOUND;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Write the modified second sector of Stage2 to the disk. */
|
# ifdef __linux__
|
||||||
grub_memmove ((char *) SCRATCHADDR, stage2_second_buffer, SECTOR_SIZE);
|
if (src_partition != 0xFFFFFF)
|
||||||
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom,
|
{
|
||||||
stage2_second_sector, 1, SCRATCHSEG))
|
if (! write_to_partition (device_map, src_drive, src_partition,
|
||||||
|
stage2_first_sector - src_part_start,
|
||||||
|
1, stage2_first_buffer))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (! write_to_partition (device_map, src_drive, src_partition,
|
||||||
|
stage2_second_sector - src_part_start,
|
||||||
|
1, stage2_second_buffer))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif /* __linux__ */
|
||||||
|
#endif /* GRUB_UTIL */
|
||||||
{
|
{
|
||||||
errnum = ERR_WRITE;
|
/* The first. */
|
||||||
goto fail;
|
grub_memmove ((char *) SCRATCHADDR, stage2_first_buffer, SECTOR_SIZE);
|
||||||
|
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom,
|
||||||
|
stage2_first_sector, 1, SCRATCHSEG))
|
||||||
|
{
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The second. */
|
||||||
|
grub_memmove ((char *) SCRATCHADDR, stage2_second_buffer, SECTOR_SIZE);
|
||||||
|
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom,
|
||||||
|
stage2_second_sector, 1, SCRATCHSEG))
|
||||||
|
{
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the modified sector of Stage 1 to the disk. */
|
/* Write the modified sector of Stage 1 to the disk. */
|
||||||
grub_memmove ((char *) SCRATCHADDR, stage1_buffer, SECTOR_SIZE);
|
#if defined(GRUB_UTIL) && defined(__linux__)
|
||||||
if (biosdisk (BIOSDISK_WRITE, dest_drive, &dest_geom,
|
if (dest_partition != 0xFFFFFF)
|
||||||
dest_sector, 1, SCRATCHSEG))
|
|
||||||
{
|
{
|
||||||
errnum = ERR_WRITE;
|
if (! write_to_partition (device_map, dest_drive, dest_partition,
|
||||||
goto fail;
|
0, 1, stage1_buffer))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* GRUB_UTIL && __linux__ */
|
||||||
|
{
|
||||||
|
grub_memmove ((char *) SCRATCHADDR, stage1_buffer, SECTOR_SIZE);
|
||||||
|
if (biosdisk (BIOSDISK_WRITE, dest_drive, &dest_geom,
|
||||||
|
dest_sector, 1, SCRATCHSEG))
|
||||||
|
{
|
||||||
|
errnum = ERR_WRITE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1872,7 +2020,7 @@ static struct builtin builtin_install =
|
||||||
"install",
|
"install",
|
||||||
install_func,
|
install_func,
|
||||||
BUILTIN_CMDLINE,
|
BUILTIN_CMDLINE,
|
||||||
"install [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
|
"install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
|
||||||
"Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
|
"Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
|
||||||
" as a Stage 2. If the option `d' is present, the Stage 1 will always"
|
" as a Stage 2. If the option `d' is present, the Stage 1 will always"
|
||||||
" look for the disk where STAGE2 was installed, rather than using"
|
" look for the disk where STAGE2 was installed, rather than using"
|
||||||
|
@ -1885,7 +2033,8 @@ static struct builtin builtin_install =
|
||||||
" 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
|
" 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
|
||||||
" patched with the configuration filename REAL_CONFIG_FILE."
|
" patched with the configuration filename REAL_CONFIG_FILE."
|
||||||
" If the option `--force-lba' is specified, disable some sanity checks"
|
" If the option `--force-lba' is specified, disable some sanity checks"
|
||||||
" for LBA mode."
|
" for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
|
||||||
|
" 2 via your OS's filesystem instead of the raw device."
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2729,6 +2878,7 @@ setup_func (char *arg, int flags)
|
||||||
char device[16];
|
char device[16];
|
||||||
char *buffer = (char *) RAW_ADDR (0x100000);
|
char *buffer = (char *) RAW_ADDR (0x100000);
|
||||||
int is_force_lba = 0;
|
int is_force_lba = 0;
|
||||||
|
char *stage2_arg = 0;
|
||||||
|
|
||||||
static void sprint_device (int drive, int partition)
|
static void sprint_device (int drive, int partition)
|
||||||
{
|
{
|
||||||
|
@ -2772,10 +2922,23 @@ setup_func (char *arg, int flags)
|
||||||
tmp_partition = saved_partition;
|
tmp_partition = saved_partition;
|
||||||
|
|
||||||
/* Check if the user specifies --force-lba. */
|
/* Check if the user specifies --force-lba. */
|
||||||
if (grub_memcmp ("--force-lba", arg, 11) == 0)
|
while (1)
|
||||||
{
|
{
|
||||||
is_force_lba = 1;
|
if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
|
||||||
arg = skip_to (0, arg);
|
{
|
||||||
|
is_force_lba = 1;
|
||||||
|
arg = skip_to (0, arg);
|
||||||
|
}
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
|
||||||
|
{
|
||||||
|
stage2_arg = arg;
|
||||||
|
arg = skip_to (0, arg);
|
||||||
|
nul_terminate (stage2_arg);
|
||||||
|
}
|
||||||
|
#endif /* GRUB_UTIL */
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
install_ptr = arg;
|
install_ptr = arg;
|
||||||
|
@ -2889,8 +3052,10 @@ setup_func (char *arg, int flags)
|
||||||
|
|
||||||
#ifdef NO_BUGGY_BIOS_IN_THE_WORLD
|
#ifdef NO_BUGGY_BIOS_IN_THE_WORLD
|
||||||
/* I prefer this, but... */
|
/* I prefer this, but... */
|
||||||
grub_sprintf (cmd_arg, "%s%s %s%s %s p %s",
|
grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s",
|
||||||
is_force_lba? "--force-lba " : "",
|
is_force_lba? "--force-lba" : "",
|
||||||
|
stage2_arg? stage2_arg : "",
|
||||||
|
stage2_arg? " " : "",
|
||||||
stage1,
|
stage1,
|
||||||
(installed_drive != image_drive) ? "d " : "",
|
(installed_drive != image_drive) ? "d " : "",
|
||||||
device,
|
device,
|
||||||
|
@ -2901,8 +3066,10 @@ setup_func (char *arg, int flags)
|
||||||
may not expect that your BIOS will pass a booting drive to stage1
|
may not expect that your BIOS will pass a booting drive to stage1
|
||||||
correctly. Thus, always specify the option `d', whether
|
correctly. Thus, always specify the option `d', whether
|
||||||
INSTALLED_DRIVE is identical with IMAGE_DRIVE or not. *sigh* */
|
INSTALLED_DRIVE is identical with IMAGE_DRIVE or not. *sigh* */
|
||||||
grub_sprintf (cmd_arg, "%s%s d %s %s p %s",
|
grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s",
|
||||||
is_force_lba? "--force-lba " : "",
|
is_force_lba? "--force-lba " : "",
|
||||||
|
stage2_arg? stage2_arg : "",
|
||||||
|
stage2_arg? " " : "",
|
||||||
stage1,
|
stage1,
|
||||||
device,
|
device,
|
||||||
stage2,
|
stage2,
|
||||||
|
@ -2932,7 +3099,7 @@ static struct builtin builtin_setup =
|
||||||
"setup",
|
"setup",
|
||||||
setup_func,
|
setup_func,
|
||||||
BUILTIN_CMDLINE,
|
BUILTIN_CMDLINE,
|
||||||
"setup [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
|
"setup [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
|
||||||
"Set up the installation of GRUB automatically. This command uses"
|
"Set up the installation of GRUB automatically. This command uses"
|
||||||
" the more flexible command \"install\" in the backend and installs"
|
" the more flexible command \"install\" in the backend and installs"
|
||||||
" GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
|
" GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
|
||||||
|
@ -2940,6 +3107,9 @@ static struct builtin builtin_setup =
|
||||||
" use the current \"root device\", which can be set by the command"
|
" use the current \"root device\", which can be set by the command"
|
||||||
" \"root\". If you know that your BIOS should support LBA but GRUB"
|
" \"root\". If you know that your BIOS should support LBA but GRUB"
|
||||||
" doesn't work in LBA mode, specify the option `--force-lba'."
|
" doesn't work in LBA mode, specify the option `--force-lba'."
|
||||||
|
" If you install GRUB under the grub shell and you cannot unmount the"
|
||||||
|
" partition where GRUB images reside, specify the option `--stage2'"
|
||||||
|
" to tell GRUB the file name under your OS."
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ test -x /bin/tempfile && log_file=`tempfile --prefix=grub`
|
||||||
# Now perform the installation.
|
# Now perform the installation.
|
||||||
$grub_shell --batch --device-map=$device_map <<EOF >$log_file
|
$grub_shell --batch --device-map=$device_map <<EOF >$log_file
|
||||||
root $root_drive
|
root $root_drive
|
||||||
setup $force_lba $install_drive
|
setup $force_lba --stage2=$grub_dir/stage2 $install_drive
|
||||||
quit
|
quit
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue