Added EZ-BIOS support.

Cleaned up the write code.
Added support for automatically embedding to file systems in setup_func.
This commit is contained in:
jochen 2000-12-17 19:25:50 +00:00
parent 47148b669b
commit 207a82b176
6 changed files with 257 additions and 232 deletions

5
BUGS
View file

@ -1,10 +1,5 @@
Known problems/bugs: Known problems/bugs:
- GRUB doesn't work with EZ-BIOS. GRUB shouldn't embed Stage 1.5 and
GRUB should use the MBR emulated by EZ-BIOS, if EZ-BIOS has been
installed. This is complicated, because Linux and EZ-BIOS hide a
real MBR from GRUB automatically.
- GRUB cannot boot newer versions of NetBSD or OpenBSD directly. - GRUB cannot boot newer versions of NetBSD or OpenBSD directly.
- The command "map" seems not to work in some environments. - The command "map" seems not to work in some environments.

View file

@ -1,3 +1,31 @@
2000-12-17 Jochen Hoenicke <jochen@gnu.org>
* stage2/disk_io.c (rawread): Check if there is a EZD partition
and remap sector 0 to sector 1 like EZ-BIOS does.
(rawwrite): New function to write to disk. Also does EZD
remapping.
(devwrite): New function. Does the special remapping to
partitions needed for linux. This contains the code that was
previously duplicated in embed_func and install_func at several
places.
(make_saved_active): Use rawwrite. Don't use SCRATCHSEG, as it is
needed by devwrite.
(set_partition_hidden_flag): Likewise.
* stage2/disk_io.h (rawwrite): New function.
(devwrite): Likewise.
* stage2/pc_slice.h (PC_SLICE_TYPE_EZD): New macro.
* stage2/builtins.c (embed_info): New variable to store the
position of the embedded stage1_5 for setup_func.
(embed_func): Don't embed after the MBR if an EZ-BIOS is detected
there. Use the new devwrite method. If embedding is successful
store position in embed_info.
(install_func): Use devwrite. Don't use SCRATCHSEG.
(partnew_func): Use rawwrite. Don't use SCRATCHSEG.
(parttype_func): Likewise.
(savedefault_func): Likewise.
(setup_func): New nested function embed_stage1_5. Stage1_5 is now
also be embedded into filesystems which supports that.
2000-12-17 OKUJI Yoshinori <okuji@gnu.org> 2000-12-17 OKUJI Yoshinori <okuji@gnu.org>
* stage2/builtins.c (chainloader_func): Set ERRNUM to * stage2/builtins.c (chainloader_func): Set ERRNUM to

View file

@ -930,6 +930,7 @@ static struct builtin builtin_displaymem =
}; };
static char embed_info[32];
/* embed */ /* embed */
/* Embed a Stage 1.5 in the first cylinder after MBR or in the /* Embed a Stage 1.5 in the first cylinder after MBR or in the
bootloader block in a FFS. */ bootloader block in a FFS. */
@ -968,6 +969,7 @@ embed_func (char *arg, int flags)
/* Embed it after the MBR. */ /* Embed it after the MBR. */
char mbr[SECTOR_SIZE]; char mbr[SECTOR_SIZE];
char ezbios_check[2*SECTOR_SIZE];
/* No floppy has MBR. */ /* No floppy has MBR. */
if (! (current_drive & 0x80)) if (! (current_drive & 0x80))
@ -994,6 +996,23 @@ embed_func (char *arg, int flags)
return 1; return 1;
} }
/* Check for EZ-BIOS signature. It should be in the third
* sector, but due to remapping it can appear in the second, so
* load and check both.
*/
if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
return 1;
if (! memcmp (ezbios_check + 3, "AERMH", 5)
|| ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
{
/* The space after the MBR is used by EZ-BIOS which we must
* not overwrite.
*/
errnum = ERR_DEV_VALUES;
return 1;
}
sector = 1; sector = 1;
} }
else else
@ -1020,38 +1039,11 @@ embed_func (char *arg, int flags)
buf_track = -1; buf_track = -1;
/* Now perform the embedding. */ /* Now perform the embedding. */
#if defined(GRUB_UTIL) && defined(__linux__) if (! devwrite (sector - part_start, size, stage1_5_buffer))
if (current_partition != 0xFFFFFF) return 1;
{
/* If the grub shell is running under Linux and the user wants to
embed a Stage 1.5 into a partition instead of a MBR, use system
calls directly instead of biosdisk, because of the bug in
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++)
{
grub_memmove ((char *) SCRATCHADDR,
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);
grub_sprintf (embed_info, "%d+%d", sector - part_start, size);
return 0; return 0;
} }
@ -1567,7 +1559,8 @@ install_func (char *arg, int flags)
{ {
char *stage1_file, *dest_dev, *file, *addr; char *stage1_file, *dest_dev, *file, *addr;
char *stage1_buffer = (char *) RAW_ADDR (0x100000); char *stage1_buffer = (char *) RAW_ADDR (0x100000);
char *old_sect = stage1_buffer + SECTOR_SIZE; char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
char *old_sect = stage2_buffer + SECTOR_SIZE;
char *stage2_first_buffer = old_sect + SECTOR_SIZE; char *stage2_first_buffer = old_sect + SECTOR_SIZE;
char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
/* XXX: Probably SECTOR_SIZE is reasonable. */ /* XXX: Probably SECTOR_SIZE is reasonable. */
@ -1921,7 +1914,7 @@ install_func (char *arg, int flags)
grub_seek (SECTOR_SIZE); grub_seek (SECTOR_SIZE);
disk_read_hook = disk_read_savesect_func; disk_read_hook = disk_read_savesect_func;
if (grub_read ((char *) SCRATCHADDR, SECTOR_SIZE) != SECTOR_SIZE) if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
goto fail; goto fail;
disk_read_hook = 0; disk_read_hook = 0;
@ -1929,16 +1922,14 @@ install_func (char *arg, int flags)
is_open = 0; is_open = 0;
/* Sanity check. */ /* Sanity check. */
if (*((unsigned char *) SCRATCHADDR + STAGE2_STAGE2_ID) if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)
!= STAGE2_ID_STAGE2)
{ {
errnum = ERR_BAD_VERSION; errnum = ERR_BAD_VERSION;
goto fail; goto fail;
} }
/* Set the "force LBA" flag for Stage2. */ /* Set the "force LBA" flag for Stage2. */
*((unsigned char *) (SCRATCHADDR + STAGE2_FORCE_LBA)) *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;
= is_force_lba;
/* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */ /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */
if (*real_config_filename) if (*real_config_filename)
@ -1947,7 +1938,7 @@ install_func (char *arg, int flags)
char *location; char *location;
/* Find a string for the configuration filename. */ /* Find a string for the configuration filename. */
location = (char *) SCRATCHADDR + STAGE2_VER_STR_OFFS; location = stage2_buffer + STAGE2_VER_STR_OFFS;
while (*(location++)) while (*(location++))
; ;
@ -1979,7 +1970,7 @@ install_func (char *arg, int flags)
goto fail; goto fail;
} }
if (fwrite ((const void *) SCRATCHADDR, 1, SECTOR_SIZE, fp) if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)
!= SECTOR_SIZE) != SECTOR_SIZE)
{ {
fclose (fp); fclose (fp);
@ -1990,28 +1981,10 @@ install_func (char *arg, int flags)
fclose (fp); fclose (fp);
} }
else 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 */ #endif /* GRUB_UTIL */
{ {
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
saved_sector, 1, SCRATCHSEG)) goto fail;
{
errnum = ERR_WRITE;
goto fail;
}
} }
} }
} }
@ -2049,61 +2022,31 @@ install_func (char *arg, int flags)
fclose (fp); fclose (fp);
} }
else else
# ifdef __linux__
if (src_partition != 0xFFFFFF)
{
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 */ #endif /* GRUB_UTIL */
{ {
/* The first. */ /* The first. */
grub_memmove ((char *) SCRATCHADDR, stage2_first_buffer, SECTOR_SIZE); current_drive = src_drive;
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom, current_partition = src_partition;
stage2_first_sector, 1, SCRATCHSEG))
{ if (! open_partition ())
errnum = ERR_WRITE; goto fail;
goto fail;
} if (! devwrite (stage2_first_sector - src_part_start, 1,
stage2_first_buffer))
/* The second. */ goto fail;
grub_memmove ((char *) SCRATCHADDR, stage2_second_buffer, SECTOR_SIZE);
if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom, if (! devwrite (stage2_second_sector - src_part_start, 1,
stage2_second_sector, 1, SCRATCHSEG)) stage2_second_buffer))
{ goto fail;
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. */
#if defined(GRUB_UTIL) && defined(__linux__) current_drive = dest_drive;
if (dest_partition != 0xFFFFFF) current_partition = dest_partition;
{ if (! open_partition ())
if (! write_to_partition (device_map, dest_drive, dest_partition, goto fail;
0, 1, stage1_buffer))
goto fail; devwrite (0, 1, stage1_buffer);
}
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:
if (is_open) if (is_open)
@ -2522,7 +2465,7 @@ partnew_func (char *arg, int flags)
int start_cl, start_ch, start_dh; int start_cl, start_ch, start_dh;
int end_cl, end_ch, end_dh; int end_cl, end_ch, end_dh;
int entry; int entry;
char *mbr = (char *) SCRATCHADDR; char mbr[512];
/* Convert a LBA address to a CHS address in the INT 13 format. */ /* Convert a LBA address to a CHS address in the INT 13 format. */
auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
@ -2616,11 +2559,8 @@ partnew_func (char *arg, int flags)
/* Write back the MBR to the disk. */ /* Write back the MBR to the disk. */
buf_track = -1; buf_track = -1;
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, 0, 1, SCRATCHSEG)) if (! rawwrite (current_drive, 0, mbr))
{ return 1;
errnum = ERR_WRITE;
return 1;
}
return 0; return 0;
} }
@ -2644,7 +2584,7 @@ parttype_func (char *arg, int flags)
unsigned long part = 0xFFFFFF; unsigned long part = 0xFFFFFF;
unsigned long start, len, offset, ext_offset; unsigned long start, len, offset, ext_offset;
int entry, type; int entry, type;
char *mbr = (char *) SCRATCHADDR; char mbr[512];
/* Get the drive and the partition. */ /* Get the drive and the partition. */
if (! set_device (arg)) if (! set_device (arg))
@ -2691,12 +2631,8 @@ parttype_func (char *arg, int flags)
/* Write back the MBR to the disk. */ /* Write back the MBR to the disk. */
buf_track = -1; buf_track = -1;
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, if (! rawwrite (current_drive, offset, mbr))
offset, 1, SCRATCHSEG)) return 1;
{
errnum = ERR_WRITE;
return 1;
}
/* Succeed. */ /* Succeed. */
return 0; return 0;
@ -3041,7 +2977,7 @@ static int
savedefault_func (char *arg, int flags) savedefault_func (char *arg, int flags)
{ {
#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) #if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
struct geometry geom; char buffer[512];
int *entryno_ptr; int *entryno_ptr;
/* This command is only useful when you boot an entry from the menu /* This command is only useful when you boot an entry from the menu
@ -3054,21 +2990,19 @@ savedefault_func (char *arg, int flags)
/* Get the geometry of the boot drive (i.e. the disk which contains /* Get the geometry of the boot drive (i.e. the disk which contains
this stage2). */ this stage2). */
if (get_diskinfo (boot_drive, &geom)) if (get_diskinfo (boot_drive, &buf_geom))
{ {
errnum = ERR_NO_DISK; errnum = ERR_NO_DISK;
return 1; return 1;
} }
/* Load the second sector of this stage2. */ /* Load the second sector of this stage2. */
if (biosdisk (BIOSDISK_READ, boot_drive, &geom, if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer))
install_second_sector, 1, SCRATCHSEG))
{ {
errnum = ERR_READ;
return 1; return 1;
} }
entryno_ptr = (int *) ((char *) SCRATCHADDR + STAGE2_SAVED_ENTRYNO); entryno_ptr = (int *) ((char *) buffer + STAGE2_SAVED_ENTRYNO);
/* Check if the saved entry number differs from current entry number. */ /* Check if the saved entry number differs from current entry number. */
if (*entryno_ptr != current_entryno) if (*entryno_ptr != current_entryno)
@ -3077,12 +3011,8 @@ savedefault_func (char *arg, int flags)
*entryno_ptr = current_entryno; *entryno_ptr = current_entryno;
/* Save the image in the disk. */ /* Save the image in the disk. */
if (biosdisk (BIOSDISK_WRITE, boot_drive, &geom, if (! rawwrite (boot_drive, install_second_sector, buffer))
install_second_sector, 1, SCRATCHSEG)) return 1;
{
errnum = ERR_WRITE;
return 1;
}
/* Clear the cache. */ /* Clear the cache. */
buf_track = -1; buf_track = -1;
@ -3527,6 +3457,7 @@ setup_func (char *arg, int flags)
auto int check_file (char *file); auto int check_file (char *file);
auto void sprint_device (int drive, int partition); auto void sprint_device (int drive, int partition);
auto int embed_stage1_5 (char * stage1_5, int drive, int partition);
/* Check if the file FILE exists like Autoconf. */ /* Check if the file FILE exists like Autoconf. */
int check_file (char *file) int check_file (char *file)
@ -3536,7 +3467,10 @@ setup_func (char *arg, int flags)
grub_printf (" Checking if \"%s\" exists... ", file); grub_printf (" Checking if \"%s\" exists... ", file);
ret = grub_open (file); ret = grub_open (file);
if (ret) if (ret)
grub_printf ("yes\n"); {
grub_close ();
grub_printf ("yes\n");
}
else else
grub_printf ("no\n"); grub_printf ("no\n");
@ -3563,6 +3497,31 @@ setup_func (char *arg, int flags)
} }
grub_strncat (device, ")", 256); grub_strncat (device, ")", 256);
} }
int embed_stage1_5 (char *stage1_5, int drive, int partition)
{
/* We install GRUB into the MBR, so try to embed the
Stage 1.5 in the sectors right after the MBR. */
sprint_device (drive, partition);
grub_sprintf (cmd_arg, "%s %s", stage1_5, device);
/* Notify what will be run. */
grub_printf (" Running \"embed %s\"... ", cmd_arg);
embed_func (cmd_arg, flags);
if (! errnum)
{
/* Construct the blocklist representation. */
grub_sprintf (buffer, "%s%s", device, embed_info);
grub_printf ("succeeded\n");
return 1;
}
else
{
grub_printf ("failed (this is not fatal)\n");
return 0;
}
}
struct stage1_5_map { struct stage1_5_map {
char *fsys; char *fsys;
@ -3663,7 +3622,6 @@ setup_func (char *arg, int flags)
if (! check_file (stage1)) if (! check_file (stage1))
goto fail; goto fail;
} }
grub_close ();
/* The prefix was determined. */ /* The prefix was determined. */
grub_sprintf (stage2, "%s%s", prefix, "/stage2"); grub_sprintf (stage2, "%s%s", prefix, "/stage2");
@ -3673,73 +3631,37 @@ setup_func (char *arg, int flags)
/* Check if stage2 exists. */ /* Check if stage2 exists. */
if (! check_file (stage2)) if (! check_file (stage2))
goto fail; goto fail;
grub_close ();
/* If the drive where stage2 resides is a hard disk, try to use a
Stage 1.5. */
if ((image_drive & 0x80) && (installed_drive & 0x80))
{
char *fsys = fsys_table[fsys_type].name;
int i;
int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
/* Iterate finding the same filesystem name as FSYS. */ {
for (i = 0; i < size; i++) char *fsys = fsys_table[fsys_type].name;
if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0) int i;
{ int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
/* OK, check if the Stage 1.5 exists. */
char stage1_5[64]; /* Iterate finding the same filesystem name as FSYS. */
for (i = 0; i < size; i++)
grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name); if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0)
if (check_file (stage1_5)) {
{ /* OK, check if the Stage 1.5 exists. */
int blocksize = (filemax + SECTOR_SIZE - 1) >> SECTOR_BITS; char stage1_5[64];
grub_close (); grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name);
grub_strcpy (real_config_filename, config_filename); if (check_file (stage1_5))
grub_strcpy (config_filename, stage2); {
grub_strcpy (stage2, stage1_5); if (embed_stage1_5 (stage1_5,
installed_drive, installed_partition)
if (installed_partition == 0xFFFFFF) || embed_stage1_5 (stage1_5,
{ image_drive, image_partition))
/* We install GRUB into the MBR, so try to embed the {
Stage 1.5 in the sectors right after the MBR. */ grub_strcpy (real_config_filename, config_filename);
sprint_device (installed_drive, installed_partition); sprint_device (image_drive, image_partition);
grub_sprintf (cmd_arg, "%s %s", stage2, device); grub_sprintf (config_filename, "%s%s", device, stage2);
grub_strcpy (stage2, buffer);
/* Notify what will be run. */ }
grub_printf (" Running \"embed %s\"... ", cmd_arg); }
errnum = 0;
embed_func (cmd_arg, flags); break;
if (! errnum) }
{ }
/* Construct the blocklist representation. */
grub_sprintf (stage2, "%s1+%d", device, blocksize);
/* Need to prepend the device name to the
configuration filename. */
sprint_device (image_drive, image_partition);
grub_sprintf (buffer, "%s%s", device, config_filename);
grub_strcpy (config_filename, buffer);
grub_printf ("succeeded\n");
}
else
grub_printf ("failed (this is not fatal)\n");
}
else if (fsys_table[fsys_type].embed_func != 0)
{
/* We can embed the Stage 1.5 into the "bootloader"
area in the FFS or ReiserFS partition. */
/* FIXME */
}
}
errnum = 0;
break;
}
}
/* Construct a string that is used by the command "install" as its /* Construct a string that is used by the command "install" as its
arguments. */ arguments. */

View file

@ -24,6 +24,10 @@
#include "filesys.h" #include "filesys.h"
#ifdef GRUB_UTIL
# include <device.h>
#endif
#ifndef STAGE1_5 #ifndef STAGE1_5
/* instrumentation variables */ /* instrumentation variables */
void (*disk_read_hook) (int, int, int) = NULL; void (*disk_read_hook) (int, int, int) = NULL;
@ -106,7 +110,6 @@ struct geometry buf_geom;
int filepos; int filepos;
int filemax; int filemax;
int int
rawread (int drive, int sector, int byte_offset, int byte_len, char *buf) rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
{ {
@ -180,8 +183,29 @@ rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
} }
else else
buf_track = track; buf_track = track;
}
if ((buf_track == 0 || sector == 0)
&& (PC_SLICE_TYPE (BUFFERADDR, 0) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (BUFFERADDR, 1) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (BUFFERADDR, 2) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (BUFFERADDR, 3) == PC_SLICE_TYPE_EZD))
{
/* This is a EZD disk map sector 0 to sector 1 */
if (buf_track == 0 || slen >= 2)
{
/* We already read the sector 1, copy it to sector 0 */
memmove ((char *) BUFFERADDR,
(char *) BUFFERADDR + SECTOR_SIZE, SECTOR_SIZE);
}
else
{
if (biosdisk (BIOSDISK_READ, drive, &buf_geom,
1, 1, BUFFERSEG))
errnum = ERR_READ;
}
}
}
if (size > ((num_sect * SECTOR_SIZE) - byte_offset)) if (size > ((num_sect * SECTOR_SIZE) - byte_offset))
size = (num_sect * SECTOR_SIZE) - byte_offset; size = (num_sect * SECTOR_SIZE) - byte_offset;
@ -260,6 +284,68 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
} }
#ifndef STAGE1_5 #ifndef STAGE1_5
int
rawwrite (int drive, int sector, char *buf)
{
if (sector == 0)
{
if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 0, 1, SCRATCHSEG))
{
errnum = ERR_WRITE;
return 0;
}
if (PC_SLICE_TYPE (SCRATCHADDR, 0) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (SCRATCHADDR, 1) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (SCRATCHADDR, 2) == PC_SLICE_TYPE_EZD
|| PC_SLICE_TYPE (SCRATCHADDR, 3) == PC_SLICE_TYPE_EZD)
sector = 1;
}
memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE);
if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom,
sector, 1, SCRATCHSEG))
{
errnum = ERR_WRITE;
return 0;
}
if (sector - sector % buf_geom.sectors == buf_track)
/* Clear the cache. */
buf_track = -1;
return 1;
}
int
devwrite (int sector, int sector_count, char *buf)
{
#if defined(GRUB_UTIL) && defined(__linux__)
if (current_partition != 0xFFFFFF)
{
/* If the grub shell is running under Linux and the user wants to
embed a Stage 1.5 into a partition instead of a MBR, use system
calls directly instead of biosdisk, because of the bug in
Linux. *sigh* */
return write_to_partition (device_map, current_drive, current_partition,
sector, sector_count, buf);
}
else
#endif /* GRUB_UTIL && __linux__ */
{
int i;
for (i = 0; i < sector_count; i++)
{
if (! rawwrite(current_drive, part_start + sector + i,
buf + (i << SECTOR_BITS)))
return 0;
}
return 1;
}
}
static int static int
sane_partition (void) sane_partition (void)
{ {
@ -302,12 +388,14 @@ attempt_mount (void)
#ifndef STAGE1_5 #ifndef STAGE1_5
/* Turn on the active flag for the partition SAVED_PARATITION in the /* Turn on the active flag for the partition SAVED_PARTITION in the
drive SAVED_DRIVE. If an error occurs, return zero, otherwise return drive SAVED_DRIVE. If an error occurs, return zero, otherwise return
non-zero. */ non-zero. */
int int
make_saved_active (void) make_saved_active (void)
{ {
char MBR[512];
if (saved_drive & 0x80) if (saved_drive & 0x80)
{ {
/* Hard disk */ /* Hard disk */
@ -322,39 +410,32 @@ make_saved_active (void)
} }
/* Read the MBR in the scratch space. */ /* Read the MBR in the scratch space. */
if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, (char *) SCRATCHADDR)) if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, (char *) MBR))
return 0; return 0;
/* If the partition is an extended partition, setting the active /* If the partition is an extended partition, setting the active
flag violates the specification by IBM. */ flag violates the specification by IBM. */
if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (SCRATCHADDR, part))) if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (MBR, part)))
{ {
errnum = ERR_DEV_VALUES; errnum = ERR_DEV_VALUES;
return 0; return 0;
} }
/* Check if the active flag is disabled. */ /* Check if the active flag is disabled. */
if (PC_SLICE_FLAG (SCRATCHADDR, part) != PC_SLICE_FLAG_BOOTABLE) if (PC_SLICE_FLAG (MBR, part) != PC_SLICE_FLAG_BOOTABLE)
{ {
int i; int i;
/* Clear all the active flags in this table. */ /* Clear all the active flags in this table. */
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
PC_SLICE_FLAG (SCRATCHADDR, i) = 0; PC_SLICE_FLAG (MBR, i) = 0;
/* Set the flag. */ /* Set the flag. */
PC_SLICE_FLAG (SCRATCHADDR, part) = PC_SLICE_FLAG_BOOTABLE; PC_SLICE_FLAG (MBR, part) = PC_SLICE_FLAG_BOOTABLE;
/* Clear the cache. */
buf_track = -1;
/* Write back the MBR. */ /* Write back the MBR. */
if (biosdisk (BIOSDISK_WRITE, saved_drive, &buf_geom, if (! rawwrite (saved_drive, 0, MBR))
0, 1, SCRATCHSEG)) return 0;
{
errnum = ERR_WRITE;
return 0;
}
} }
} }
else else
@ -372,6 +453,7 @@ make_saved_active (void)
int int
set_partition_hidden_flag (int hidden) set_partition_hidden_flag (int hidden)
{ {
char MBR[512];
if (current_drive & 0x80) if (current_drive & 0x80)
{ {
int part = current_partition >> 16; int part = current_partition >> 16;
@ -382,21 +464,16 @@ set_partition_hidden_flag (int hidden)
return 0; return 0;
} }
if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (char *) SCRATCHADDR)) if (! rawread (current_drive, 0, 0, SECTOR_SIZE, (char *) MBR))
return 0; return 0;
if (hidden) if (hidden)
PC_SLICE_TYPE (SCRATCHADDR, part) |= PC_SLICE_TYPE_HIDDEN_FLAG; PC_SLICE_TYPE (MBR, part) |= PC_SLICE_TYPE_HIDDEN_FLAG;
else else
PC_SLICE_TYPE (SCRATCHADDR, part) &= ~PC_SLICE_TYPE_HIDDEN_FLAG; PC_SLICE_TYPE (MBR, part) &= ~PC_SLICE_TYPE_HIDDEN_FLAG;
buf_track = -1; if (! rawwrite (current_drive, 0, MBR))
if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, return 0;
0, 1, SCRATCHSEG))
{
errnum = ERR_WRITE;
return 0;
}
} }
return 1; return 1;

View file

@ -109,6 +109,7 @@
#define PC_SLICE_TYPE_FAT32_LBA 0xc #define PC_SLICE_TYPE_FAT32_LBA 0xc
#define PC_SLICE_TYPE_FAT16_LBA 0xe #define PC_SLICE_TYPE_FAT16_LBA 0xe
#define PC_SLICE_TYPE_WIN95_EXTENDED 0xf #define PC_SLICE_TYPE_WIN95_EXTENDED 0xf
#define PC_SLICE_TYPE_EZD 0x55
#define PC_SLICE_TYPE_MINIX 0x80 #define PC_SLICE_TYPE_MINIX 0x80
#define PC_SLICE_TYPE_LINUX_MINIX 0x81 #define PC_SLICE_TYPE_LINUX_MINIX 0x81
#define PC_SLICE_TYPE_EXT2FS 0x83 #define PC_SLICE_TYPE_EXT2FS 0x83

View file

@ -933,6 +933,8 @@ int gunzip_read (char *buf, int len);
int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf); int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf);
int devread (int sector, int byte_offset, int byte_len, char *buf); int devread (int sector, int byte_offset, int byte_len, char *buf);
int rawwrite (int drive, int sector, char *buf);
int devwrite (int sector, int sector_len, char *buf);
/* Parse a device string and initialize the global parameters. */ /* Parse a device string and initialize the global parameters. */
char *set_device (char *device); char *set_device (char *device);