Hello,
Here are some fixes to GRUB (cvs checkout 1999-05-30).
For details see ChangeLog.
* Handle input of '\' correctly.
* Fix some problems with Linux' /sbin/grub.
With these fixes and I_AM_VERY_BRAVE #defined in grub/asmstub.c I
successfully booted a Multiboot Kernel from floppy without NATIVE
grub.
Next step (after 3 weeks vacation :-) will be a first try on
Harddisk.
* Add some code to enable TAB expansion completing unique input text
for DEVICES & FILE/DIRNAMES.
Patch attached.
Klaus Reichl
--
Klaus Reichl voice: +43 (1) 27722 / 3884
Alcatel Austria AG/RTPM fax: +43 (1) 27722 / 3955
Scheydgasse 41 inet: [EMAIL PROTECTED]
A-1210 Wien, Austria/Europe
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/ChangeLog grub/ChangeLog
--- cvsgrub/ChangeLog Sun May 23 22:31:54 1999
+++ grub/ChangeLog Mon May 31 00:44:30 1999
@@ -1,4 +1,8 @@
+1999-05-23 Klaus Reichl <[EMAIL PROTECTED]>
+
+ * docs/.cvsignore: New file.
+
1999-05-21 OKUJI Yoshinori <[EMAIL PROTECTED]>
* docs/TODO: Moved to ...
* TODO: ... here.
@@ -7,8 +11,35 @@
* docs/COPYING: Removed.
* docs/Makefile.am (EXTRA_DIST): Get rid of BUGS.
* Makefile.am (EXTRA_DIST): Set to BUGS.
+1999-05-20 Klaus Reichl <[EMAIL PROTECTED]>
+
+ * grub/disk_io.c (print_a_completion): New function which saves
+ what has been printed to `unique_string' and printf it.
+ (print_completions): Use it.
+ * grub/fsys_ext2fs.c: ditto
+ * grub/fsys_fat.c: ditto
+ * grub/fsys_ffs.c: ditto.
+ * grub/shared.h (print_a_completion): Declare it.
+ * grub/main.c (main): if (hold) add some printfs to show user what
+ to do.
+
+1999-05-18 Klaus Reichl <[EMAIL PROTECTED]>
+
+ * grub/cmdline.c: Add (char *) cast to grub_read.
+ * grub/asmstub.c: Don't try /dev/fd1 under linux, if there is no
+ second floppy drive, the kernel has strange behaviour.
+ Probe 4 (not 2) IDE devices, continue on error, disks may be
+ connected sparse to the controllers.
+ Add code for ENOMEDIUM on `fopen', don't brake the loop if we have
+ this to find e.g. 2nd disk on 2nd controller.
+ Put nwrite under I_AM_VERY_BRAVE to avoid
+ compiler warning.
+ Add prototype for _llseek to avoid compiler warning.
+ Implement some `od' like code under #ifdef DEBUG_BIOSDISK_WRITE
+ Implement a trace wrapper over open under #ifdef DEBUG_OPEN
+
1999-05-17 OKUJI Yoshinori <[EMAIL PROTECTED]>
* acinclude.m4 (grub_ASM_EXT_C): Do not overrun the comman
shift. Reported by Pavel Roskin <[EMAIL PROTECTED]>.
@@ -51,8 +82,28 @@
* e2fs_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Set to 81920.
* fat_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Likewise.
* ffs_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Set to 7168.
+1999-05-08 Klaus Reichl <[EMAIL PROTECTED]>
+
+ * shared_src/disk_io.c (unique): New static to be able to
+ probagate the fact the a completion is unique.
+ (set_device): If user says "(<TAB>" let
+ disk_choice find all disks we have.
+ If user says "([fh][d]TAB" ditto.
+ (print_completions): Show only the disks we have according to the
+ string the user specifies. If its unique insert the text in users
+ input buffer.
+ (print_completions): If `open_partition' succeeds, add ")/" into
+ users input buffer.
+
+ * shared_src/char_io.c (get_cmdline): Handle situation where
+ `print_completion' adds something in input cmd line.
+
+1999-05-08 Klaus Reichl <[EMAIL PROTECTED]>
+
+ * shared_src/stage2.c (get_line_from_config): Fixed handling of '\\'.
+
1999-05-03 Gordon Matzigkeit <[EMAIL PROTECTED]>
From Pavel Roskin:
* shared_src/shared.h: Redeclare.
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/docs/.cvsignore
grub/docs/.cvsignore
--- cvsgrub/docs/.cvsignore Thu Jan 1 01:00:00 1970
+++ grub/docs/.cvsignore Mon May 31 01:03:04 1999
@@ -0,0 +1,3 @@
+*.info*
+version.texi
+stamp-vti
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/grub/asmstub.c
grub/grub/asmstub.c
--- cvsgrub/grub/asmstub.c Mon May 31 00:14:04 1999
+++ grub/grub/asmstub.c Mon May 31 00:47:42 1999
@@ -17,8 +17,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* Some debugging hooks */
+
+/* define for a trace of device opens */
+#define DEBUG_OPEN
+
+/* set this for debugging BIOSDISK_WRITE */
+/* #define DEBUG_BIOSDISK_WRITE */
+
/* Try to use glibc's transparant LFS support. */
#define _LARGEFILE_SOURCE 1
/* Simulator entry point. */
@@ -37,8 +45,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
+#include <string.h>
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
# include <linux/hdreg.h> /* HDIO_GETGEO */
@@ -131,26 +140,53 @@
memset (device_map, 0, NUM_DISKS * sizeof (char *));
/* Floppies. */
device_map[0] = strdup ("/dev/fd0");
+#ifndef __linux__
+ /* FIXME: leave linux out for now /dev/fd1 blocks for long time
+ if there is no second floppy ? */
device_map[1] = strdup ("/dev/fd1");
+#endif
/* IDE disks. */
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 4; i++)
{
char name[10];
FILE *fp;
char buf[512];
+
#ifdef __linux__
char unit = 'a' + i;
#else
char unit = '0' + i;
#endif
sprintf (name, "/dev/hd%c", unit);
fp = fopen (name, "r");
- if (! fp)
- break;
+ 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 */
+ /* register it, it may be inserted */
+ device_map[i + 0x80] = strdup (name);
+#endif
+ break;
+#endif /* ENOMEDIUM */
+ default:
+ /* break case and leave */
+ break;
+ }
+ /* continue: there may be more disks sitting sparse on the
+ controllers */
+ continue;
+ }
+
/* Attempt to read the first sector. */
if (fread (buf, 1, 512, fp) != 512)
break;
@@ -456,8 +492,36 @@
}
#endif
}
+#ifdef DEBUG_OPEN
+/* Wrapper for open: trace for the user what we do */
+static int
+asmstub_open (const char * dev, int flags)
+{
+ int res;
+ int nflags = flags;
+ int dont_know_flags = 0;
+
+ fprintf (stderr, "\r\ngrub: Trying to open (%s, %s",
+ dev, (((nflags & 3) == O_RDWR) ? (nflags &= ~O_RDWR, "O_RDWR")
+ : ((nflags & 3) == O_RDONLY) ? "O_RDONLY"
+ : ""));
+ fprintf (stderr, "%s", (nflags & O_SYNC ? (nflags &= ~O_SYNC, "|O_SYNC")
+ : (nflags == 0) ? ""
+ : (dont_know_flags = 1, "")));
+ if (dont_know_flags || nflags)
+ fprintf (stderr, "|%08x", nflags);
+ fprintf (stderr, ") = ");
+
+ res = open (dev, flags);
+ fprintf (stderr, "%d", res);
+ if (res == -1)
+ fprintf (stderr, " (errno = %d - %s)", errno, strerror (errno));
+ return res;
+}
+#define open asmstub_open
+#endif /* DEBUG_OPEN */
/* Low-level disk I/O. Our stubbed version just returns a file
descriptor, not the actual geometry. */
int
@@ -467,8 +531,12 @@
then severely abuse the GEOMETRY->flags field to pass a file
descriptor to biosdisk. Thank God nobody's looking at this comment,
or my reputation would be ruined. --Gord */
+ if (disks[drive].flags == -1)
+ /* some earlier call set this guy to error */
+ return -1;
+
/* See if we have a cached device. */
if (! disks[drive].flags)
{
/* The unpartitioned device name: /dev/XdX */
@@ -479,17 +547,48 @@
return -1;
/* Open read/write, or read-only if that failed. */
disks[drive].flags = open (devname, O_RDWR);
- if (! disks[drive].flags)
- disks[drive].flags = open (devname, O_RDONLY);
+ if (disks[drive].flags == -1)
+ {
+ if ((errno == EACCES || errno == EROFS))
+ {
+ disks[drive].flags = open (devname, O_RDONLY);
+ if (disks[drive].flags == -1)
+ {
+ /* code below assumes == 0 */
+ disks[drive].flags = 0;
+ }
+ }
+ else if (errno == ENODEV)
+ {
+ /* this is OK, leave -1 in */
+ return -1;
+ }
+ else if (errno == ENXIO)
+ {
+ /* maybe a removable volume - like a floppy */
+ disks[drive].flags = 0;
+ return -1;
+ }
+ else
+ {
+ /* show user what else can be wrong and exit */
+ fprintf (stderr, "get_diskinfo: Can't open %s: %s\n",
+ devname, strerror (errno));
+ exit (1);
+ }
+ }
- /* Attempt to read the first sector. */
- if (read (disks[drive].flags, buf, 512) != 512)
+ if (disks[drive].flags)
{
- close (disks[drive].flags);
- disks[drive].flags = 0;
- return -1;
+ /* Attempt to read the first sector. */
+ if (read (disks[drive].flags, buf, 512) != 512)
+ {
+ close (disks[drive].flags);
+ disks[drive].flags = 0;
+ return -1;
+ }
}
if (disks[drive].flags)
{
@@ -540,8 +639,33 @@
*geometry = disks[drive];
return 0;
}
+#ifdef DEBUG_BIOSDISK_WRITE
+/* like od -v -A x -x */
+static void
+od (unsigned char * p, int size)
+{
+ unsigned addr = 0;
+ int i;
+
+ while (size)
+ {
+ fprintf (stderr, "%06x ", addr);
+ for (i = 0; i < 8; i++)
+ {
+ fprintf (stderr, "%04x%s",
+ *((unsigned short *) p),
+ ((i == 7) ? "" : " "));
+ p += sizeof (unsigned short);
+ size -= sizeof (unsigned short);
+ }
+ fprintf (stderr, "\n\r");
+ }
+ fprintf (stderr, "%06x\n", addr);
+}
+#endif /* DEBUG_BIOSDISK_WRITE */
+
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
static int
nread (int fd, char *buf, size_t len)
@@ -566,8 +690,9 @@
return size;
}
+#ifdef I_AM_VERY_BRAVE
/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
static int
nwrite (int fd, char *buf, size_t len)
@@ -591,8 +716,9 @@
}
return size;
}
+#endif /* I_AM_VERY_BRAVE */
int
biosdisk (int subfunc, int drive, struct geometry *geometry,
int sector, int nsec, int segment)
@@ -608,8 +734,9 @@
#ifdef __linux__
/* FIXME: only use this section if libc doesn't have large file support */
{
loff_t offset, result;
+ static int _llseek (uint fd, ulong hi, ulong lo, loff_t * res, uint wh);
_syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
@@ -636,8 +763,20 @@
case BIOSDISK_WRITE:
if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
return -1;
break;
+#endif
+#ifdef DEBUG_BIOSDISK_WRITE
+ case BIOSDISK_WRITE:
+ fprintf (stderr, "\r\n");
+ fprintf (stderr, "grub: Don't know how to BIOSDISK_WRITE yet\r\n");
+ fprintf (stderr, "grub; drive: %d, sector: %d\r\n", drive, sector);
+ fprintf (stderr, "grub: od -v -A x -x %08x\r\n", segment << 4);
+ od ((unsigned char *) (segment << 4), nsec * 512);
+ fprintf (stderr, "grub: Press a key to continue\r");
+ getkey ();
+ /* fake things did OK */
+ fprintf (stderr, "\r\ngrub: Fake OK\r\n");
#endif
default:
grub_printf ("unknown subfunc %d\n", subfunc);
break;
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/grub/main.c grub/grub/main.c
--- cvsgrub/grub/main.c Sat May 8 21:27:27 1999
+++ grub/grub/main.c Thu May 20 21:21:05 1999
@@ -172,10 +172,19 @@
}
while (c != EOF);
/* Wait until the HOLD variable is cleared by an attached debugger. */
- while (hold)
- sleep (1);
+ if (hold)
+ {
+ printf ("Use:\n"
+ " gdb %s\n"
+ " attach %d\n", program_name, getpid ());
+ while (hold)
+ {
+ sleep (1);
+ }
+ }
+
/* Transfer control to the stage2 simulator. */
exit (grub_stage2 ());
}
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/char_io.c
grub/shared_src/char_io.c
--- cvsgrub/shared_src/char_io.c Tue May 18 20:37:15 1999
+++ grub/shared_src/char_io.c Tue May 18 22:19:06 1999
@@ -275,8 +275,12 @@
if (i <= j)
i = j + 1;
/* print possible completions */
print_completions (cmdline + i);
+ /* if somebody in print_completions has added something,
+ account for that */
+ while (cmdline[lpos])
+ lpos++, llen_old++;
}
else if (commands)
printf (commands);
else
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/cmdline.c
grub/shared_src/cmdline.c
--- cvsgrub/shared_src/cmdline.c Tue May 18 20:37:15 1999
+++ grub/shared_src/cmdline.c Thu May 20 22:45:46 1999
@@ -465,9 +465,9 @@
while (*(str++)); /* find string */
while ((*(str++) = *(ptr++)) != 0); /* do copy */
}
- grub_read (RAW_ADDR (0x100000), -1);
+ grub_read ((char *) RAW_ADDR (0x100000), -1);
buf_track = -1;
if (!errnum
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/disk_io.c
grub/shared_src/disk_io.c
--- cvsgrub/shared_src/disk_io.c Tue May 18 20:37:16 1999
+++ grub/shared_src/disk_io.c Fri May 21 00:18:41 1999
@@ -573,8 +573,12 @@
/* XX used for device completion in 'set_device' and 'print_completions' */
static int incomplete, disk_choice;
+#ifndef STAGE1_5
+static int unique;
+static char unique_string[128]; /* XXX Don't know yet */
+#endif
static enum
{
PART_UNSPECIFIED = 0,
PART_DISK,
@@ -594,14 +598,33 @@
part_choice = PART_UNSPECIFIED;
current_drive = saved_drive;
current_partition = 0xFFFFFF;
+ if (*device == '(' && !*(device + 1))
+ /* user has given '(' only, let disk_choice handle what disks we have */
+ return device + 1;
+
if (*device == '(' && *(++device))
{
if (*device != ',' && *device != ')')
{
char ch = *device;
+ if (*device == 'f' || *device == 'h')
+ {
+ /* user has given '([fh]', check for resp. add 'd' and
+ let disk_choice handle what disks we have */
+ if (!*(device + 1))
+ {
+ device++;
+ *device++ = 'd';
+ *device = '\0';
+ return device;
+ }
+ else if (*(device + 1) == 'd' && !*(device + 2))
+ return device + 2;
+ }
+
if ((*device == 'f' || *device == 'h')
&& (device += 2, (*(device - 1) != 'd')))
errnum = ERR_NUMBER_PARSING;
@@ -879,8 +902,37 @@
#endif /* STAGE1_5 */
#ifndef STAGE1_5
/*
+ * print_a_completion saves what has been printed to unique_string
+ * printf's with a leading ' '
+ */
+
+void
+print_a_completion (char *filename)
+{
+ char * f = filename;
+ char * u = unique_string;
+
+ if (! *u && unique == 0)
+ {
+ /* copy first string, this is unique */
+ while ((*u++ = *f++))
+ ;
+ }
+ else
+ {
+ while (*u && (*u == *f))
+ u++, f++;
+ /* mismatch, strip it */
+ *u = '\0';
+ }
+ unique++;
+
+ printf (" %s", filename);
+}
+
+/*
* This lists the possible completions of a device string, filename, or
* any sane combination of the two.
*/
@@ -888,8 +940,11 @@
print_completions (char *filename)
{
char *ptr = filename;
+ *unique_string = '\0';
+ unique = 0;
+
if (*filename == '/' || (ptr = set_device (filename)) || incomplete)
{
errnum = 0;
@@ -902,19 +957,47 @@
struct geometry geom;
printf (" Possible disks are: ");
- for (i = 0; i < 2; i++)
+ for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0);
+ i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2);
+ i++)
{
for (j = 0; j < 8; j++)
{
disk_no = (i * 0x80) + j;
if ((disk_choice || disk_no == current_drive) &&
! get_diskinfo (disk_no, &geom))
- printf (" %cd%d", (i ? 'h' : 'f'), j);
+ {
+ char dev_name [4];
+
+ dev_name[0] = (i ? 'h' : 'f');
+ dev_name[1] = 'd';
+ dev_name[2] = '0' + j;
+ dev_name[3] = '\0';
+ print_a_completion (dev_name);
+ }
}
}
+ ptr = filename;
+ while (*ptr != '(')
+ ptr--;
+ ptr++;
+ {
+ char *u = unique_string;
+ while ((*ptr++ = *u++))
+ ;
+ ptr--;
+ }
+ 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';
+
putchar ('\n');
}
else
{
@@ -926,17 +1009,42 @@
}
else
{
if (open_partition ())
- check_and_print_mount ();
+ {
+ check_and_print_mount ();
+ /* XXX: Can talk about linux only, do we need
+ to know about syntax here? */
+ ptr = filename;
+ while (*ptr)
+ ptr++;
+ if (*(ptr - 1) != ')')
+ *ptr++ = ')';
+ *ptr++ = '/';
+ *ptr = '\0';
+ }
}
}
}
else if (*ptr == '/')
{
/* filename completions */
printf (" Possible files are:");
dir (filename);
+ {
+ char *u = unique_string;
+
+ if (*u)
+ {
+ while (*ptr++)
+ ;
+ while (*ptr != '/')
+ ptr--;
+ ptr++;
+ while ((*ptr++ = *u++))
+ ;
+ }
+ }
}
else
errnum = ERR_BAD_FILENAME;
}
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_ext2fs.c
grub/shared_src/fsys_ext2fs.c
--- cvsgrub/shared_src/fsys_ext2fs.c Tue May 18 20:37:16 1999
+++ grub/shared_src/fsys_ext2fs.c Fri May 21 00:00:08 1999
@@ -756,9 +756,9 @@
&& (!*dirname || str_chk <= 0))
{
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
- printf (" %s", dp->name);
+ print_a_completion (dp->name);
}
# endif
dp->name[dp->name_len] = saved_c;
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_fat.c
grub/shared_src/fsys_fat.c
--- cvsgrub/shared_src/fsys_fat.c Mon Mar 15 03:08:09 1999
+++ grub/shared_src/fsys_fat.c Fri May 21 00:00:08 1999
@@ -239,9 +239,9 @@
&& (!*dirname || substring (dirname, filename) <= 0))
{
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
- printf (" %s", filename);
+ print_a_completion (filename);
}
# endif /* STAGE1_5 */
}
while (substring (dirname, filename) != 0 ||
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_ffs.c
grub/shared_src/fsys_ffs.c
--- cvsgrub/shared_src/fsys_ffs.c Sun Mar 28 00:35:35 1999
+++ grub/shared_src/fsys_ffs.c Fri May 21 00:00:01 1999
@@ -251,9 +251,9 @@
{
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
- printf (" %s", dp->d_name);
+ print_a_completion (dp->d_name);
}
#endif /* STAGE1_5 */
}
while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/shared.h
grub/shared_src/shared.h
--- cvsgrub/shared_src/shared.h Sat May 8 21:27:27 1999
+++ grub/shared_src/shared.h Thu May 20 22:45:30 1999
@@ -511,8 +511,9 @@
/* Display statistics on the current active device. */
void print_fsys_type (void);
/* Display device and filename completions. */
+void print_a_completion (char *filename);
void print_completions (char *filename);
/* Copies the current partition data to the desired address. */
void copy_current_part_entry (char *buf);
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/stage2.c
grub/shared_src/stage2.c
--- cvsgrub/shared_src/stage2.c Sun May 2 23:30:41 1999
+++ grub/shared_src/stage2.c Tue May 18 22:25:51 1999
@@ -469,9 +469,9 @@
while (grub_read (&c, 1))
{
/* translate characters first! */
- if (c == '\\')
+ if ((c == '\\') && !literal)
{
literal = 1;
continue;
}