From: Marco Gerards <metgerards@student.han.nl>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: Loopback device
Date: Fri, 21 Jan 2005 19:36:36 +0000 [thread overview]
Message-ID: <87ekgefubf.fsf@marco.marco-g.com> (raw)
In-Reply-To: <200501211432.54494.okuji@enbug.org> (Yoshinori K. Okuji's message of "Fri, 21 Jan 2005 14:32:54 +0100")
"Yoshinori K. Okuji" <okuji@enbug.org> writes:
> On Friday 21 January 2005 01:12, Marco Gerards wrote:
>> Here is a patch to add loopback support to GRUB. Although a lot of
>> people told me they would find it useful, I just wrote it out of
>> boredom without thinking about its use, just to figure out how hard
>> it would be.
>
> That's great. That is the very thing I wanted to have.
>
> BTW, I think it is better to make it possible to choose a device type
> (i.e. if it has a partition table or not). I'm always annoyed with that
> Linux cannot deal with a hard disk image.
I did that and the new patch is included with this email.
Unfortunately it does not work well, but I believe that is a
filesystem problem. Can I commit this patch? I will put the
filesystem problem on the wiki so it is documented to have a look at
it later.
When the PPC port is mostly finished I plan to have a look at the bugs
in GRUB and do some testing. I think there are some regressions in
the filesystems, there are a few known bugs and perhaps I can write
some testing tools to make it easier to test filesystems.
Thanks,
Marco
2005-01-21 Marco Gerards <metgerards@student.han.nl>
Add the loopback device, a device via which files can be accessed
as devices.
* conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/loopback.c'.
(pkgdata_MODULES): Add loopback.mod.
(loopback_SOURCES): New variable.
(loopback_CFLAGS): Likewise.
* conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
`disk/loopback.c'.
(pkgdata_MODULES): Add loopback.mod.
(loopback_SOURCES): New variable.
(loopback_CFLAGS): Likewise.
* disk/loopback.c: new file.
* include/grub/normal.h (grub_loop_init): New prototype.
(grub_loop_fini): New prototype.
(util/grub-emu.c): Initialize and de-initialize loopback support.
* include/grub/disk.h (grub_disk_dev_id): Add
`GRUB_DISK_DEVICE_LOOPBACK_ID'.
Index: conf/i386-pc.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 i386-pc.rmk
--- conf/i386-pc.rmk 4 Dec 2004 18:45:45 -0000 1.23
+++ conf/i386-pc.rmk 21 Jan 2005 18:59:54 -0000
@@ -73,7 +73,7 @@ grub_emu_SOURCES = kern/main.c kern/devi
commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c \
util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/iso9660.c \
normal/cmdline.c normal/command.c normal/main.c normal/menu.c normal/arg.c \
- util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c
+ util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c disk/loopback.c
grub_emu_LDFLAGS = -lncurses
# For genmoddep.
@@ -83,7 +83,7 @@ genmoddep_SOURCES = util/genmoddep.c
pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod vga.mod font.mod _multiboot.mod ls.mod \
boot.mod cmp.mod cat.mod terminal.mod fshelp.mod chain.mod multiboot.mod \
- amiga.mod apple.mod pc.mod
+ amiga.mod apple.mod pc.mod loopback.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -190,3 +190,7 @@ apple_mod_CFLAGS = $(COMMON_CFLAGS)
# For pc.mod
pc_mod_SOURCES = partmap/pc.c
pc_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For loopback.mod
+loopback_SOURCES = disk/loopback.c
+loopback_CFLAGS = $(COMMON_CFLAGS)
Index: conf/powerpc-ieee1275.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/powerpc-ieee1275.rmk,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 powerpc-ieee1275.rmk
--- conf/powerpc-ieee1275.rmk 4 Jan 2005 14:01:45 -0000 1.19
+++ conf/powerpc-ieee1275.rmk 21 Jan 2005 18:59:55 -0000
@@ -41,7 +41,7 @@ grub_emu_SOURCES = kern/main.c kern/devi
normal/cmdline.c normal/command.c normal/main.c normal/menu.c \
normal/arg.c kern/partition.c \
util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c \
- kern/env.c commands/ls.c \
+ kern/env.c disk/loopback.c commands/ls.c \
commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c
grub_emu_LDFLAGS = -lncurses
@@ -64,7 +64,8 @@ genmoddep_SOURCES = util/genmoddep.c
# Modules.
pkgdata_MODULES = _linux.mod linux.mod fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod font.mod \
- boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod pc.mod
+ boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
+ pc.mod loopback.mod
# For fshelp.mod.
fshelp_mod_SOURCES = fs/fshelp.c
@@ -151,3 +152,7 @@ apple_mod_CFLAGS = $(COMMON_CFLAGS)
# For pc.mod
pc_mod_SOURCES = partmap/pc.c
pc_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For loopback.mod
+loopback_SOURCES = disk/loopback.c
+loopback_CFLAGS = $(COMMON_CFLAGS)
Index: disk/loopback.c
===================================================================
RCS file: disk/loopback.c
diff -N disk/loopback.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ disk/loopback.c 21 Jan 2005 18:59:55 -0000
@@ -0,0 +1,272 @@
+/* loopback.c - command to add loopback devices. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 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 2 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 GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+
+struct grub_loopback
+{
+ char *devname;
+ char *filename;
+ int has_partitions;
+ struct grub_loopback *next;
+};
+
+static struct grub_loopback *loopback_list;
+
+static const struct grub_arg_option options[] =
+ {
+ {"delete", 'd', 0, "Delete the loopback device entry", 0, 0},
+ {"partitions", 'p', 0, "Set that the drive has partitions to"
+ " simulate a harddrive", 0, 0},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+/* Delete the loopback device NAME. */
+static grub_err_t
+delete_loopback (const char *name)
+{
+ struct grub_loopback *dev;
+ struct grub_loopback **prev;
+
+ /* Search for the device. */
+ for (dev = loopback_list, prev = &loopback_list;
+ dev; prev = &dev->next, dev = dev->next)
+ if (!grub_strcmp (dev->devname, name))
+ break;
+ if (!dev)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "Device not found");
+
+ /* Remove the device from the list. */
+ *prev = dev->next;
+
+ grub_free (dev->devname);
+ grub_free (dev->filename);
+ grub_free (dev);
+
+ return 0;
+}
+
+
+/* The command to add and remove loopback devices. */
+static grub_err_t
+grub_cmd_loopback (struct grub_arg_list *state,
+ int argc, char **args)
+{
+ grub_file_t file;
+ struct grub_loopback *newdev;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+ /* Check if `-d' was used. */
+ if (state[0].set)
+ return delete_loopback (args[0]);
+
+ if (argc < 2)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+ file = grub_file_open (args[1]);
+ if (! file)
+ return grub_errno;
+
+ /* Close the file, the only reason for opening it is validation. */
+ grub_file_close (file);
+
+ /* First try to replace the old device. */
+ for (newdev = loopback_list; newdev; newdev = newdev->next)
+ if (!grub_strcmp (newdev->devname, args[0]))
+ break;
+ if (newdev)
+ {
+ char *newname = grub_strdup (args[1]);
+ if (!newname)
+ return grub_errno;
+
+ grub_free (newdev->filename);
+ newdev->filename = newname;
+
+ /* Set has_partitions when `--partitions' was used. */
+ newdev->has_partitions = state[1].set;
+
+ return 0;
+ }
+
+ /* Unable to replace it, make a new entry. */
+ newdev = grub_malloc (sizeof (struct grub_loopback));
+ if (!newdev)
+ return grub_errno;
+
+ newdev->devname = grub_strdup (args[0]);
+ if (!newdev->devname)
+ {
+ grub_free (newdev);
+ return grub_errno;
+ }
+
+ newdev->filename = grub_strdup (args[1]);
+ if (!newdev->devname)
+ {
+ grub_free (newdev->devname);
+ grub_free (newdev);
+ return grub_errno;
+ }
+
+ /* Set has_partitions when `--partitions' was used. */
+ newdev->has_partitions = state[1].set;
+
+ /* Add the new entry to the list. */
+ newdev->next = loopback_list;
+ loopback_list = newdev;
+
+ return 0;
+}
+
+\f
+static int
+grub_loopback_iterate (int (*hook) (const char *name))
+{
+ struct grub_loopback *d;
+ for (d = loopback_list; d; d = d->next)
+ {
+ if (hook (d->devname))
+ return 1;
+ }
+ return 0;
+}
+
+static grub_err_t
+grub_loopback_open (const char *name, grub_disk_t disk)
+{
+ grub_file_t file;
+ struct grub_loopback *dev;
+
+ for (dev = loopback_list; dev; dev = dev->next)
+ if (!grub_strcmp (dev->devname, name))
+ break;
+
+ if (! dev)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+
+ file = grub_file_open (dev->filename);
+ if (! file)
+ return grub_errno;
+
+ /* Use the filesize for the disk size, round up to a complete sector. */
+ disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1)
+ / GRUB_DISK_SECTOR_SIZE);
+ disk->id = (int) dev;
+
+ disk->has_partitions = dev->has_partitions;
+ disk->data = file;
+
+ return 0;
+}
+
+static void
+grub_loopback_close (grub_disk_t disk)
+{
+ grub_file_t file = (grub_file_t) disk->data;
+
+ grub_file_close (file);
+}
+
+static grub_err_t
+grub_loopback_read (grub_disk_t disk, unsigned long sector,
+ unsigned long size, char *buf)
+{
+ grub_file_t file = (grub_file_t) disk->data;
+ long pos;
+
+ grub_file_seek (file, sector * GRUB_DISK_SECTOR_SIZE);
+
+ grub_file_read (file, buf, size * GRUB_DISK_SECTOR_SIZE);
+ if (grub_errno)
+ return grub_errno;
+
+ /* In case there is more data read than there is available, in case
+ of files that are not a multiple of GRUB_DISK_SECTOR_SIZE, fill
+ the rest with zeros. */
+ pos = sector * GRUB_DISK_SECTOR_SIZE + size * GRUB_DISK_SECTOR_SIZE;
+ if (pos > file->size)
+ {
+ unsigned long amount = pos - file->size;
+ grub_memset (buf + pos - amount, amount, 0);
+ }
+
+ return 0;
+}
+
+static grub_err_t
+grub_loopback_write (grub_disk_t disk __attribute ((unused)),
+ unsigned long sector __attribute ((unused)),
+ unsigned long size __attribute ((unused)),
+ const char *buf __attribute ((unused)))
+{
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+static struct grub_disk_dev grub_loopback_dev =
+ {
+ .name = "loopback",
+ .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
+ .iterate = grub_loopback_iterate,
+ .open = grub_loopback_open,
+ .close = grub_loopback_close,
+ .read = grub_loopback_read,
+ .write = grub_loopback_write,
+ .next = 0
+ };
+
+
+\f
+#ifdef GRUB_UTIL
+void
+grub_loop_init (void)
+{
+ grub_register_command ("loopback", grub_cmd_loopback, GRUB_COMMAND_FLAG_BOTH,
+ "loopback [OPTIONS] DEVICENAME FILE", "Makes a device of a file", options);
+ grub_disk_dev_register (&grub_loopback_dev);
+
+}
+
+void
+grub_loop_fini (void)
+{
+ grub_unregister_command ("loopback");
+}
+#else /* ! GRUB_UTIL */
+GRUB_MOD_INIT
+{
+ (void)mod; /* To stop warning. */
+ grub_register_command ("loopback", grub_cmd_loopback, GRUB_COMMAND_FLAG_BOTH,
+ "loopback [OPTIONS] DEVICENAME FILE", "Makes a device of a file", options);
+}
+
+GRUB_MOD_FINI
+{
+ grub_unregister_command ("loopback");
+}
+#endif /* ! GRUB_UTIL */
Index: include/grub/disk.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/disk.h,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 disk.h
--- include/grub/disk.h 21 Aug 2004 13:54:22 -0000 1.5
+++ include/grub/disk.h 21 Jan 2005 18:59:56 -0000
@@ -31,6 +31,7 @@ enum grub_disk_dev_id
{
GRUB_DISK_DEVICE_BIOSDISK_ID,
GRUB_DISK_DEVICE_OFDISK_ID,
+ GRUB_DISK_DEVICE_LOOPBACK_ID
};
struct grub_disk;
Index: include/grub/normal.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/normal.h,v
retrieving revision 1.9
diff -u -p -u -p -r1.9 normal.h
--- include/grub/normal.h 17 Sep 2004 09:36:52 -0000 1.9
+++ include/grub/normal.h 21 Jan 2005 18:59:56 -0000
@@ -158,6 +158,8 @@ void grub_cmp_init (void);
void grub_cmp_fini (void);
void grub_terminal_init (void);
void grub_terminal_fini (void);
+void grub_loop_init (void);
+void grub_loop_fini (void);
#endif
#endif /* ! GRUB_NORMAL_HEADER */
Index: util/grub-emu.c
===================================================================
RCS file: /cvsroot/grub/grub2/util/grub-emu.c,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 grub-emu.c
--- util/grub-emu.c 20 Jan 2005 17:25:39 -0000 1.11
+++ util/grub-emu.c 21 Jan 2005 18:59:56 -0000
@@ -176,13 +176,15 @@ main (int argc, char *argv[])
grub_cmp_init ();
grub_cat_init ();
grub_terminal_init ();
-
+ grub_loop_init ();
+
/* XXX: Should normal mode be started by default? */
grub_normal_init ();
-
+
/* Start GRUB! */
grub_main ();
+ grub_loop_fini ();
grub_util_biosdisk_fini ();
grub_normal_fini ();
grub_ufs_fini ();
next prev parent reply other threads:[~2005-01-21 20:02 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-01-21 0:12 Loopback device Marco Gerards
2005-01-21 12:38 ` P
2005-01-21 12:58 ` Marco Gerards
2005-01-21 13:32 ` Yoshinori K. Okuji
2005-01-21 14:01 ` P
2005-01-21 14:07 ` Marco Gerards
2005-01-21 14:34 ` Yoshinori K. Okuji
2005-01-21 14:50 ` Vincent Pelletier
2005-01-21 14:46 ` Vincent Pelletier
2005-01-21 19:36 ` Marco Gerards [this message]
2005-01-21 20:46 ` Yoshinori K. Okuji
2005-01-21 21:37 ` Marco Gerards
-- strict thread matches above, loose matches on Subject: below --
2001-11-05 17:53 guenther.sohler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ekgefubf.fsf@marco.marco-g.com \
--to=metgerards@student.han.nl \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.