]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2009-06-18 Pavel Roskin <proski@gnu.org>
authorproski <proski@localhost>
Thu, 18 Jun 2009 20:00:34 +0000 (20:00 +0000)
committerproski <proski@localhost>
Thu, 18 Jun 2009 20:00:34 +0000 (20:00 +0000)
* conf/common.rmk: Add fs_file.mod.
* disk/fs_file.c: New file.
* include/grub/disk.h (enum grub_disk_dev_id): Add
GRUB_DISK_DEVICE_FILE_ID.

ChangeLog
conf/common.rmk
disk/fs_file.c [new file with mode: 0644]
include/grub/disk.h

index 2d872b60b5f68bad965db56c1c3da5a54ef5d20c..982c8bc72dd1547c095b97c1c6fbc19174283b2b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-06-18  Pavel Roskin  <proski@gnu.org>
+
+       * conf/common.rmk: Add fs_file.mod.
+       * disk/fs_file.c: New file.
+       * include/grub/disk.h (enum grub_disk_dev_id): Add
+       GRUB_DISK_DEVICE_FILE_ID.
+
 2009-06-18  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Fix build with Apple's toolchain. Part 2
index d0c142be9c5e2ff46265b5f0a2a2cd69efae2df4..fbca2e4beb5c1176cc4f02633c5892d4ca562500 100644 (file)
@@ -349,8 +349,8 @@ scsi_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # Commands.
 pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \
-        ls.mod cmp.mod cat.mod help.mod search.mod             \
-       loopback.mod fs_uuid.mod configfile.mod echo.mod        \
+       ls.mod cmp.mod cat.mod help.mod search.mod loopback.mod \
+       fs_file.mod fs_uuid.mod configfile.mod echo.mod         \
        terminfo.mod test.mod blocklist.mod hexdump.mod         \
        read.mod sleep.mod loadenv.mod crc.mod parttool.mod     \
        pcpart.mod memrw.mod normal.mod sh.mod lua.mod  \
@@ -431,6 +431,11 @@ loopback_mod_SOURCES = disk/loopback.c
 loopback_mod_CFLAGS = $(COMMON_CFLAGS)
 loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For fs_file.mod
+fs_file_mod_SOURCES = disk/fs_file.c
+fs_file_mod_CFLAGS = $(COMMON_CFLAGS)
+fs_file_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For fs_uuid.mod
 fs_uuid_mod_SOURCES = disk/fs_uuid.c
 fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/disk/fs_file.c b/disk/fs_file.c
new file mode 100644 (file)
index 0000000..e095682
--- /dev/null
@@ -0,0 +1,136 @@
+/* fs_file.c - Access partition by a file it contains.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+
+static grub_device_t
+search_fs_file (const char *key, unsigned long *count)
+{
+  char *filename = NULL;
+  grub_device_t ret = NULL;
+  *count = 0;
+
+  auto int iterate_device (const char *name);
+  int iterate_device (const char *name)
+  {
+    int len;
+    grub_file_t file;
+
+    (*count)++;
+
+    len = grub_strlen (name) + 2 + grub_strlen (key) + 1;
+    filename = grub_realloc (filename, len);
+    if (! filename)
+      return 1;
+
+    grub_sprintf (filename, "(%s)%s", name, key);
+    file = grub_file_open (filename);
+    if (file)
+      {
+       grub_file_close (file);
+       ret = grub_device_open (name);
+       return 1;
+      }
+
+    grub_errno = GRUB_ERR_NONE;
+    return 0;
+  }
+
+  grub_device_iterate (iterate_device);
+  grub_free (filename);
+
+  return ret;
+}
+
+static grub_err_t
+grub_fs_file_open (const char *name, grub_disk_t disk)
+{
+  grub_device_t dev;
+
+  if (grub_strncmp (name, "FILE=", sizeof ("FILE=") - 1))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a FILE virtual volume");
+
+  dev = search_fs_file (name + sizeof ("FILE=") - 1, &disk->id);
+  if (! dev)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file found");
+
+  disk->total_sectors = dev->disk->total_sectors;
+  disk->has_partitions = 0;
+  if (dev->disk->partition)
+    {
+      disk->partition = grub_malloc (sizeof (*disk->partition));
+      if (disk->partition)
+       grub_memcpy (disk->partition, dev->disk->partition,
+                    sizeof (*disk->partition));
+    }
+  else
+    disk->partition = NULL;
+
+  disk->data = dev;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_fs_file_close (grub_disk_t disk)
+{
+  grub_device_t parent = disk->data;
+  grub_device_close (parent);
+}
+
+static grub_err_t
+grub_fs_file_read (grub_disk_t disk, grub_disk_addr_t sector,
+                  grub_size_t size, char *buf)
+{
+  grub_device_t parent = disk->data;
+  return parent->disk->dev->read (parent->disk, sector, size, buf);
+}
+
+static grub_err_t
+grub_fs_file_write (grub_disk_t disk, grub_disk_addr_t sector,
+                   grub_size_t size, const char *buf)
+{
+  grub_device_t parent = disk->data;
+  return parent->disk->dev->write (parent->disk, sector, size, buf);
+}
+
+static struct grub_disk_dev grub_fs_file_dev = {
+  .name = "fs_file",
+  .id = GRUB_DISK_DEVICE_FILE_ID,
+  .open = grub_fs_file_open,
+  .close = grub_fs_file_close,
+  .read = grub_fs_file_read,
+  .write = grub_fs_file_write,
+  .next = 0
+};
+
+GRUB_MOD_INIT (fs_file)
+{
+  grub_disk_dev_register (&grub_fs_file_dev);
+}
+
+GRUB_MOD_FINI (fs_file)
+{
+  grub_disk_dev_unregister (&grub_fs_file_dev);
+}
index a0cc6427d4b9db9dacb1148ad1252b0e0900d7cf..a47e113372b5e4cec43f01ced5c90067fe5798be 100644 (file)
@@ -41,6 +41,7 @@ enum grub_disk_dev_id
     GRUB_DISK_DEVICE_UUID_ID,
     GRUB_DISK_DEVICE_PXE_ID,
     GRUB_DISK_DEVICE_SCSI_ID,
+    GRUB_DISK_DEVICE_FILE_ID,
   };
 
 struct grub_disk;