reduce the size of Stage 1.5, improve the completion, fix some bugs.

This commit is contained in:
okuji 1999-09-29 09:28:37 +00:00
parent 55d36b7e2b
commit 3ccfc3bed1
19 changed files with 374 additions and 101 deletions

View file

@ -15,3 +15,6 @@ OKUJI Yoshinori contributed many bugfixes and new features, such as
working LBA support, and /sbin/grub support for configuration files.
Peter Astrand added support for a color menu.
Pavel Roskin contributed many bugfixes and new features, such as FreeBSD
support in the grub shell, and configure process cleanups.

View file

@ -1,3 +1,81 @@
1999-09-29 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage2/builtins.c (install_func): If the Stage 2 id in FILE is
not STAGE2_ID_STAGE2, set IS_STAGE1_5 to 1, otherwise to 0.
Use CONFIG_FILE_LOCATION to point to the location of the name of
a configuration file in Stage 2.
If the option `p' is present and IS_STAGE1_5 is non-zero, reset
the device information in CONFIG_FILE_LOCATION.
(cat_func): New function.
(builtin_cat): New variable.
(builtin_table): Added a pointer to BUILTIN_CAT.
(geometry_func): Call real_open_partition with the argument 1
after printing out the drive information.
* stage2/disk_io.c (real_open_partition): Made global.
[!STAGE1_5] (print_completions): In the command completion and
the filename completion, print a newline at the last if
IS_COMPLETION is zero.
* stage2/shared.h (real_open_partition): Declared.
* stage2/fsys_ext2fs.c (ext2fs_dir): Do not print a newline even
if PRINT_POSSIBILITIES is less than zero.
* stage2/fsys_ffs.c (ffs_dir): Likewise.
* stage2/fsys_fat.c (fat_dir): Likewise.
* stage2/fsys_minix.c (minix_dir): Likewise.
1999-09-29 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage1/stage1.S [!FFS_STAGE1_5] (blocklist_default_len): Do
not divide the size by 512, but shift the size to the right by
9 instead, because of a binutils-2.9.1.0.x bug.
* stage1/stage1_lba.S [!FFS_STAGE1_5] (blocklist_default_len):
Likewise.
* stage2/builtins.c (install_func): When installing Stage 1.5,
if set_device returns NULL, then set CURRENT_DRIVE to 0xFF and
CONFIG_FILE to PTR.
1999-09-26 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage2/char_io.c [!STAGE1_5] (get_cmdline): In cl_insert, call
cl_setcpos before printing BUF, even if LPOS is equal to LLEN.
In the completion, if RET is zero, do not call cl_init.
* stage2/disk_io.c [!STAGE1_5] (print_completions): In the
filename completion, if UNIQUE is 1, check if UNIQUE_STRING is a
directory or not. If so, append '/' to BUF.
In the partition completion, if IS_COMPLETION is non-zero and
*UNIQUE_STRING is not NUL, copy UNIQUE_STRING to PTR. Do not
append '/'.
(real_open_partition) [!STAGE1_5]: If DO_COMPRESSION is non-zero,
call print_a_completion.
(check_BSD_parts) [!STAGE1_5]: Likewise.
[!STAGE1_5] (print_a_completion): Ignore NAME if it is "." or
"..".
1999-09-25 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* acinclude.m4 (grub_CHECK_USCORE_END_SYMBOL): Do not call
AC_DEFINE within AC_CACHE_VAL. Call it after AC_CACHE_VAL.
* stage2/Makefile.am (STAGE1_5_COMPILE): Do not define
CONFIG_FILE_ASM.
* stage2/asm.S (config_file) [STAGE1_5]: Set the first 4 bytes
to 0xffffffff and the following to "/boot/grub/stage2".
(config_file) [!STAGE1_5]: Set to "/boot/grub/menu.lst".
* stage2/builtins.c (install_func): Read a Stage 2 before
handling the `p' option.
If the `configfile' option is present and FILE is a Stage 2,
translate the device name to the internal device representation
and copy the result to STR.
* stage2/disk_io.c [STAGE1_5] (sane_partition): Eliminated.
[STAGE1_5] (incomplete): Likewise.
[STAGE1_5] (disk_choice): Likewise.
[STAGE1_5] (part_choice): Likewise.
(set_device) [STAGE1_5]: Assume that the first 4 bytes of DEVICE
is a device number. Set DRIVE to the forth byte of DEV and
PARTITION to the first 3 bytes of DEV. If DRIVE is 0xFF, set
CURRENT_DRIVE and CURRENT_PARTITION to SAVED_DRIVE and
SAVED_PARTITION, respectively. Otherwise set to DRIVE and
PARTITION, respectively.
(setup_part) [STAGE1_5]: Always call set_device.
1999-09-24 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* acinclude.m4 (grub_CHECK_END_SYMBOL): Add a missing

2
NEWS
View file

@ -27,6 +27,8 @@ New in 0.5.93:
* Killing (C-u and C-k), yanking (C-y) and manipulating the history
(C-p and C-n) are supported.
* The address argument for the command "install" is now optional.
* Better completion support.
* The command "cat" displays the contents of a file.
New in 0.5.92 - 1999-07-26:
* Bug fixes (i.e. Stage 1.5 can work fine again).

19
README
View file

@ -18,8 +18,23 @@ you use the following utilities:
* binutils 2.9.1.0.23 and later (Do not use early 2.9.1.0.x!)
Binutils has changed the behavior of 16bit assembler between 2.9.1
and 2.9.1.0.x, and we support only 2.9.1.0.x. It is available from
ftp.XX.kernel.org (XX is the country code, such as `jp').
and 2.9.1.0.x, and we support only 2.9.1.0.x and higher. It is available
from ftp.varesearch.com:/pub/support/hjl/binutils.
NOTE: you should check for the version of your binutils by the following
command:
$ gcc -Wl,-v 2>&1 | grep "GNU ld"
This will show two versions, like this:
GNU ld version 2.9.5 (with BFD 2.9.5.0.13)
The latter is what you should see. If you have installed a recent
version of binutils but this version number is not identical with it,
GCC uses a fixed path rather than the environment variable PATH to find
binutils. In this case, you need to install your binutils into the path
which GCC sees (typically, /usr/bin), or reinstall GCC.
These below are required when you develop GRUB or when you get it from

View file

@ -270,11 +270,11 @@ else
grub_cv_check_uscore_end_symbol=no
fi
rm -f conftest*])
if test "x$grub_cv_check_uscore_end_symbol" = xyes; then
AC_DEFINE([HAVE_USCORE_END_SYMBOL])
fi
rm -f conftest*])
AC_MSG_RESULT([$grub_cv_check_uscore_end_symbol])
])

4
aclocal.m4 vendored
View file

@ -282,12 +282,12 @@ else
grub_cv_check_uscore_end_symbol=no
fi
rm -f conftest*])
if test "x$grub_cv_check_uscore_end_symbol" = xyes; then
AC_DEFINE([HAVE_USCORE_END_SYMBOL])
fi
rm -f conftest*])
AC_MSG_RESULT([$grub_cv_check_uscore_end_symbol])
])

8
configure vendored
View file

@ -1765,6 +1765,10 @@ else
grub_cv_check_uscore_end_symbol=no
fi
rm -f conftest*
fi
if test "x$grub_cv_check_uscore_end_symbol" = xyes; then
cat >> confdefs.h <<\EOF
#define HAVE_USCORE_END_SYMBOL 1
@ -1772,10 +1776,6 @@ EOF
fi
rm -f conftest*
fi
echo "$ac_t""$grub_cv_check_uscore_end_symbol" 1>&6
if test "x$grub_cv_check_end_symbol" != "xyes" \

View file

@ -405,7 +405,7 @@ blocklist_default_start:
sectors from the start of the disk, sector 0 */
blocklist_default_len:
/* this is the number of sectors to read */
.word (STAGE2_SIZE + 511) / 512
.word (STAGE2_SIZE + 511) >> 9
blocklist_default_seg:
.word 0x0800 /* this is the segment of the starting address
to load the data into */

View file

@ -352,7 +352,7 @@ blocklist_default_start:
sectors from the start of the disk, sector 0 */
blocklist_default_len:
/* this is the number of sectors to read */
.word (STAGE2_SIZE + 511) / 512
.word (STAGE2_SIZE + 511) >> 9
blocklist_default_seg:
.word 0x0800 /* this is the segment of the starting address
to load the data into */

View file

@ -32,8 +32,7 @@ STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc
STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 \
-DCONFIG_FILE_ASM='.string "/boot/grub/stage2"'
STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
# asm.S absolutely needs to come first!
# For stage2 target.

View file

@ -66,11 +66,12 @@ VARIABLE(stage2_id)
VARIABLE(version_string)
.string VERSION
VARIABLE(config_file)
#ifndef CONFIG_FILE_ASM
#ifndef STAGE1_5
.string "/boot/grub/menu.lst"
#else /* CONFIG_FILE_ASM */
CONFIG_FILE_ASM
#endif /* CONFIG_FILE_ASM */
#else /* STAGE1_5 */
.long 0xffffffff
.string "/boot/grub/stage2"
#endif /* STAGE1_5 */
/*
* Leave some breathing room for the config file name.

View file

@ -127,6 +127,37 @@ static struct builtin builtin_boot =
"Boot the OS/chain-loader which has been loaded."
};
static int
cat_func (char *arg, int flags)
{
int len;
char *ptr;
if (! grub_open (arg))
return 1;
len = grub_read ((char *) RAW_ADDR (0x100000), -1);
if (errnum)
return 1;
ptr = (char *) RAW_ADDR (0x100000);
while (len--)
grub_putchar (*ptr++);
return 0;
}
static struct builtin builtin_cat =
{
"cat",
cat_func,
BUILTIN_CMDLINE,
"cat FILE",
"Print the contents of the file FILE."
};
/* chainloader */
static int
@ -502,6 +533,7 @@ geometry_func (char *arg, int flags)
current_drive,
geom.cylinders, geom.heads, geom.sectors,
geom.total_sectors, msg);
real_open_partition (1);
return 0;
}
@ -728,6 +760,10 @@ install_func (char *arg, int flags)
int stage2_sect;
char *ptr;
int installaddr, installlist;
/* Point to the location of the name of a configuration file in Stage 2. */
char *config_file_location;
/* If FILE is a Stage 1.5? */
int is_stage1_5 = 0;
/* Save the first sector of Stage2 in STAGE2_SECT. */
static void disk_read_savesect_func (int sector)
@ -926,33 +962,16 @@ install_func (char *arg, int flags)
/* Stage 2. */
installaddr = 0x8000;
else
{
/* Stage 1.5. */
installaddr = 0x2000;
is_stage1_5 = 1;
}
}
*((unsigned short *) (BOOTSEC_LOCATION + STAGE1_INSTALLADDR))
= installaddr;
if (*ptr == 'p')
{
write_stage2_sect = 1;
*((long *) (SCRATCHADDR + STAGE2_INSTALLPART)) = current_partition;
ptr = skip_to (0, ptr);
}
if (*ptr)
{
char *str = ((char *) (SCRATCHADDR + STAGE2_VER_STR_OFFS));
write_stage2_sect = 1;
/* Find a string for the configuration filename. */
while (*(str++))
;
/* Copy the filename to Stage 2. */
while ((*(str++) = *(ptr++)) != 0)
;
}
/* Read the whole of Stage 2. */
filepos = 0;
disk_read_hook = disk_read_blocklist_func;
@ -962,6 +981,55 @@ install_func (char *arg, int flags)
return 1;
}
/* Find a string for the configuration filename. */
config_file_location = ((char *) (SCRATCHADDR + STAGE2_VER_STR_OFFS));
while (*(config_file_location++))
;
if (*ptr == 'p')
{
write_stage2_sect = 1;
*((long *) (SCRATCHADDR + STAGE2_INSTALLPART)) = current_partition;
if (is_stage1_5)
{
/* Reset the device information in FILE if it is a Stage 1.5. */
int device = 0xFFFFFFFF;
grub_memmove (config_file_location, (char *) &device, sizeof (int));
}
ptr = skip_to (0, ptr);
}
if (*ptr)
{
write_stage2_sect = 1;
if (! is_stage1_5)
/* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */
grub_strcpy (config_file_location, ptr);
else
{
char *config_file;
int device;
int tmp = current_drive;
/* Translate the external device syntax to the internal device
syntax. */
if (! (config_file = set_device (ptr)))
{
errnum = 0;
current_drive = 0xFF;
config_file = ptr;
}
device = current_drive << 24 | current_partition;
current_drive = tmp;
grub_memmove (config_file_location, (char *) &device, sizeof (int));
grub_strcpy (config_file_location + sizeof (int), config_file);
}
}
/* Clear the cache. */
buf_track = -1;
@ -1507,6 +1575,7 @@ static struct builtin builtin_uppermem =
struct builtin *builtin_table[] =
{
&builtin_boot,
&builtin_cat,
&builtin_chainloader,
&builtin_color,
&builtin_configfile,

View file

@ -300,6 +300,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
if (lpos == llen)
{
grub_memmove (buf + lpos, str, l + 1);
cl_setcpos ();
cl_print (buf + lpos, echo_char);
lpos += l;
cl_setcpos ();
@ -432,6 +433,8 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
/* Restore the command-line. */
if (equal_pos >= 0)
buf[equal_pos] = '=';
if (ret)
cl_init ();
}
break;

View file

@ -242,14 +242,13 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
byte_len, buf);
}
#ifndef STAGE1_5
static int
sane_partition (void)
{
#ifndef STAGE1_5
/* network drive */
if (current_drive == 0x20)
return 1;
#endif
if (!(current_partition & 0xFF000000uL)
&& (current_drive & 0xFFFFFF7F) < 8
@ -263,6 +262,7 @@ sane_partition (void)
errnum = ERR_DEV_VALUES;
return 0;
}
#endif /* ! STAGE1_5 */
static void
attempt_mount (void)
@ -415,6 +415,16 @@ check_BSD_parts (int flags)
if (! do_completion)
printf (" BSD Partition num: \'%c\', ", part_no + 'a');
else
{
char str[16];
grub_sprintf (str, "%d,%c)",
(current_partition >> 16) & 0xFF,
part_no + 'a');
print_a_completion (str);
}
check_and_print_mount ();
}
else
@ -446,7 +456,7 @@ check_BSD_parts (int flags)
static char cur_part_desc[16];
#endif
static int
int
real_open_partition (int flags)
{
char mbr_buf[SECTOR_SIZE];
@ -543,14 +553,30 @@ real_open_partition (int flags)
{
current_partition |= 0xFFFF;
if (! do_completion)
{
printf (" Partition num: %d, ", slice_no);
if (! IS_PC_SLICE_TYPE_BSD (current_slice))
check_and_print_mount ();
else
check_BSD_parts (1);
}
else
{
if (! IS_PC_SLICE_TYPE_BSD (current_slice))
{
char str[8];
grub_sprintf (str, "%d)", slice_no);
print_a_completion (str);
}
else
check_BSD_parts (1);
}
errnum = ERR_NONE;
}
# endif /* STAGE1_5 */
# endif /* ! STAGE1_5 */
/*
* If we've found the right partition, we're done
*/
@ -636,20 +662,42 @@ open_partition (void)
}
#ifndef STAGE1_5
/* XX used for device completion in 'set_device' and 'print_completions' */
static int incomplete, disk_choice;
static enum
{
{
PART_UNSPECIFIED = 0,
PART_DISK,
PART_CHOSEN,
}
}
part_choice;
#endif /* ! STAGE1_5 */
char *
set_device (char *device)
{
#ifdef STAGE1_5
/* In Stage 1.5, the first 4 bytes of FILENAME has a device number. */
int dev = *((int *) device);
int drive = dev >> 24;
int partition = dev & 0xFFFFFF;
if (drive == 0xFF)
{
current_drive = saved_drive;
current_partition = saved_partition;
}
else
{
current_drive = drive;
current_partition = partition;
}
return device + sizeof (int);
#else /* ! STAGE1_5 */
/* The use of retval in this function is not really clean, but it works */
char *retval = 0;
@ -659,11 +707,9 @@ set_device (char *device)
current_drive = saved_drive;
current_partition = 0xFFFFFF;
#ifndef STAGE1_5
if (*device == '(' && !*(device + 1))
/* user has given '(' only, let disk_choice handle what disks we have */
return device + 1;
#endif
if (*device == '(' && *(++device))
{
@ -671,7 +717,6 @@ set_device (char *device)
{
char ch = *device;
#ifndef STAGE1_5
if (*device == 'f' || *device == 'h')
{
/* user has given '([fh]', check for resp. add 'd' and
@ -686,7 +731,6 @@ set_device (char *device)
else if (*(device + 1) == 'd' && !*(device + 2))
return device + 2;
}
#endif
if ((*device == 'f' || *device == 'h' || *device == 'n')
&& (device += 2, (*(device - 1) != 'd')))
@ -846,6 +890,8 @@ set_device (char *device)
}
return retval;
#endif /* ! STAGE1_5 */
}
/*
@ -901,6 +947,23 @@ set_bootdev (int hdbias)
static char *
setup_part (char *filename)
{
#ifdef STAGE1_5
if (! (filename = set_device (filename)))
{
current_drive = 0xFF;
return 0;
}
# ifndef NO_BLOCK_FILES
if (*filename != '/')
open_partition ();
else
# endif /* ! NO_BLOCK_FILES */
open_device ();
#else /* ! STAGE1_5 */
/* FIXME: decide on syntax for blocklist vs. old-style vs. /dev/hd0s1 */
/* Strip any leading /dev. */
if (substring ("/dev/", filename) < 1)
@ -913,11 +976,11 @@ setup_part (char *filename)
current_drive = 0xFF;
return 0;
}
#ifndef NO_BLOCK_FILES
# ifndef NO_BLOCK_FILES
if (*filename != '/')
open_partition ();
else
#endif /* NO_BLOCK_FILES */
# endif /* ! NO_BLOCK_FILES */
open_device ();
}
else if (saved_drive != current_drive
@ -929,14 +992,16 @@ setup_part (char *filename)
current_partition = saved_partition;
/* allow for the error case of "no filesystem" after the partition
is found. This makes block files work fine on no filesystem */
#ifndef NO_BLOCK_FILES
# ifndef NO_BLOCK_FILES
if (*filename != '/')
open_partition ();
else
#endif /* NO_BLOCK_FILES */
# endif /* ! NO_BLOCK_FILES */
open_device ();
}
#endif /* ! STAGE1_5 */
if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT))
return 0;
else
@ -982,6 +1047,10 @@ print_fsys_type (void)
void
print_a_completion (char *name)
{
/* If NAME is "." or "..", do not count it. */
if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0)
return;
if (do_completion)
{
char *buf = unique_string;
@ -1053,6 +1122,9 @@ print_completions (int is_filename, int is_completion)
grub_strcpy (buf, unique_string);
}
if (! is_completion)
grub_putchar ('\n');
do_completion = 0;
return unique - 1;
}
@ -1082,12 +1154,9 @@ print_completions (int is_filename, int is_completion)
if ((disk_choice || disk_no == current_drive)
&& ! get_diskinfo (disk_no, &geom))
{
char dev_name[4];
char dev_name[8];
dev_name[0] = (i ? 'h' : 'f');
dev_name[1] = 'd';
dev_name[2] = '0' + j;
dev_name[3] = '\0';
grub_sprintf (dev_name, "%cd%d", i ? 'h' : 'f', j);
print_a_completion (dev_name);
}
}
@ -1099,23 +1168,26 @@ print_completions (int is_filename, int is_completion)
while (*ptr != '(')
ptr--;
ptr++;
grub_strcpy (ptr, unique_string);
if (unique == 1)
{
char *u = unique_string;
while ((*ptr++ = *u++))
;
ptr--;
ptr += grub_strlen (ptr);
if (*unique_string == 'h')
{
*ptr++ = ',';
*ptr = 0;
}
else
{
*ptr++ = ')';
*ptr = 0;
}
}
}
ptr--;
if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd')
&& ('0' <= *ptr && *ptr <= '8'))
*(ptr + 1) = ',', *(ptr + 2) = '\0';
if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd')
&& ('0' <= *ptr && *ptr <= '8'))
*(ptr + 1) = ')', *(ptr + 2) = '\0';
if (! is_completion)
grub_putchar ('\n');
}
}
else
{
/* partition completions */
@ -1124,21 +1196,26 @@ print_completions (int is_filename, int is_completion)
if (! is_completion)
grub_printf (" Possible partitions are:\n");
real_open_partition (1);
if (is_completion && *unique_string)
{
ptr = buf;
while (*ptr++ != ',')
;
grub_strcpy (ptr, unique_string);
}
}
else
{
if (open_partition ())
{
check_and_print_mount ();
/* FIXME: Can talk about linux only, do we need
to know about syntax here? */
ptr = buf;
while (*ptr)
ptr++;
unique = 1;
ptr = buf + grub_strlen (buf);
if (*(ptr - 1) != ')')
{
*ptr++ = ')';
*ptr++ = '/';
*ptr = '\0';
*ptr = 0;
}
}
}
}
@ -1158,16 +1235,33 @@ print_completions (int is_filename, int is_completion)
ptr--;
ptr++;
grub_strcpy (ptr, unique_string);
if (unique == 1)
{
char *u = unique_string + grub_strlen (unique_string);
ptr += grub_strlen (unique_string);
*u++ = ' ';
*u = 0;
/* Check if the file UNIQUE_STRING is a directory. */
*ptr = '/';
*(ptr + 1) = 0;
dir (buf);
/* Restore the original unique value. */
unique = 1;
if (errnum)
{
/* Regular file */
errnum = 0;
*ptr = ' ';
*(ptr + 1) = 0;
}
}
}
grub_strcpy (ptr, unique_string);
}
if (! is_completion)
grub_putchar ('\n');
}
else
errnum = ERR_BAD_FILENAME;

View file

@ -705,7 +705,9 @@ ext2fs_dir (char *dirname)
{
if (print_possibilities < 0)
{
# if 0
putchar ('\n');
# endif
}
else
{

View file

@ -211,7 +211,9 @@ loop:
{
if (print_possibilities < 0)
{
#if 0
putchar ('\n');
#endif
return 1;
}

View file

@ -240,7 +240,9 @@ loop:
{
if (loc >= INODE->i_size)
{
#if 0
putchar ('\n');
#endif
if (print_possibilities < 0)
return 1;

View file

@ -463,7 +463,9 @@ minix_dir (char *dirname)
{
if (print_possibilities < 0)
{
#if 0
putchar ('\n');
#endif
}
else
{

View file

@ -640,6 +640,7 @@ int devread (int sector, int byte_offset, int byte_len, char *buf);
/* Parse a device string and initialize the global parameters. */
char *set_device (char *device);
int open_device (void);
int real_open_partition (int flags);
int open_partition (void);
/* Sets device to the one represented by the SAVED_* parameters. */