Blame SOURCES/0162-Remove-nested-functions-from-disk-and-file-read-hook.patch

f96e0b
From 0ddc619999a799152c6fb5e81653bbef2a19a1d5 Mon Sep 17 00:00:00 2001
f96e0b
From: Colin Watson <cjwatson@ubuntu.com>
f96e0b
Date: Wed, 27 Feb 2013 17:19:15 +0100
f96e0b
Subject: [PATCH 162/482] 	Remove nested functions from disk and file
f96e0b
 read hooks.
f96e0b
f96e0b
	* include/grub/disk.h (grub_disk_read_hook_t): New type.
f96e0b
	(struct grub_disk): Add read_hook_data member.
f96e0b
	* include/grub/file.h (struct grub_file): Likewise.
f96e0b
	* include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data
f96e0b
	argument.
f96e0b
f96e0b
	Update all callers.
f96e0b
---
f96e0b
 ChangeLog                      |  12 +++
f96e0b
 config.h.in                    |   6 +-
f96e0b
 grub-core/commands/blocklist.c | 106 ++++++++++++---------
f96e0b
 grub-core/commands/loadenv.c   |  80 +++++++++-------
f96e0b
 grub-core/commands/testload.c  |  22 +++--
f96e0b
 grub-core/fs/affs.c            |   2 +-
f96e0b
 grub-core/fs/bfs.c             |  41 ++++----
f96e0b
 grub-core/fs/ext2.c            |  15 +--
f96e0b
 grub-core/fs/fat.c             |  15 +--
f96e0b
 grub-core/fs/fshelp.c          |  10 +-
f96e0b
 grub-core/fs/hfs.c             |   7 +-
f96e0b
 grub-core/fs/hfsplus.c         |  23 ++---
f96e0b
 grub-core/fs/iso9660.c         |   1 +
f96e0b
 grub-core/fs/jfs.c             |   9 +-
f96e0b
 grub-core/fs/minix.c           |  17 ++--
f96e0b
 grub-core/fs/nilfs2.c          |  17 ++--
f96e0b
 grub-core/fs/ntfs.c            |  48 ++++------
f96e0b
 grub-core/fs/ntfscomp.c        |   1 +
f96e0b
 grub-core/fs/reiserfs.c        |  15 ++-
f96e0b
 grub-core/fs/romfs.c           |   1 +
f96e0b
 grub-core/fs/sfs.c             |   9 +-
f96e0b
 grub-core/fs/udf.c             |  22 ++---
f96e0b
 grub-core/fs/ufs.c             |  17 ++--
f96e0b
 grub-core/fs/xfs.c             |  15 +--
f96e0b
 grub-core/kern/disk.c          |   2 +-
f96e0b
 include/grub/disk.h            |  12 ++-
f96e0b
 include/grub/file.h            |   7 +-
f96e0b
 include/grub/fshelp.h          |   6 +-
f96e0b
 util/grub-setup.c              | 210 +++++++++++++++++++++--------------------
f96e0b
 29 files changed, 406 insertions(+), 342 deletions(-)
f96e0b
f96e0b
diff --git a/ChangeLog b/ChangeLog
f96e0b
index c77a6a6..dbecfef 100644
f96e0b
--- a/ChangeLog
f96e0b
+++ b/ChangeLog
f96e0b
@@ -1,3 +1,15 @@
f96e0b
+2013-02-27  Colin Watson  <cjwatson@ubuntu.com>
f96e0b
+
f96e0b
+	Remove nested functions from disk and file read hooks.
f96e0b
+
f96e0b
+	* include/grub/disk.h (grub_disk_read_hook_t): New type.
f96e0b
+	(struct grub_disk): Add read_hook_data member.
f96e0b
+	* include/grub/file.h (struct grub_file): Likewise.
f96e0b
+	* include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data
f96e0b
+	argument.
f96e0b
+
f96e0b
+	Update all callers.
f96e0b
+
f96e0b
 2012-02-27  Andrey Borzenkov <arvidjaar@gmail.com>
f96e0b
 
f96e0b
 	* grub-core/partmap/msdos.c (grub_partition_msdos_iterate):
f96e0b
diff --git a/config.h.in b/config.h.in
f96e0b
index a7eaf19..91afd98 100644
f96e0b
--- a/config.h.in
f96e0b
+++ b/config.h.in
f96e0b
@@ -5,6 +5,10 @@
f96e0b
 #if defined(__PPC__) && !defined(__powerpc__)
f96e0b
 #define __powerpc__ 1
f96e0b
 #endif
f96e0b
+
f96e0b
+/* Define to 1 to enable disk cache statistics.  */
f96e0b
+#define DISK_CACHE_STATS @DISK_CACHE_STATS@
f96e0b
+
f96e0b
 #if defined (GRUB_UTIL) || !defined (GRUB_MACHINE)
f96e0b
 #include <config-util.h>
f96e0b
 #define NESTED_FUNC_ATTR
f96e0b
@@ -39,8 +43,6 @@
f96e0b
 #define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@
f96e0b
 /* Define to 1 if GCC generates calls to __register_frame_info().  */
f96e0b
 #define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@
f96e0b
-/* Define to 1 to enable disk cache statistics.  */
f96e0b
-#define DISK_CACHE_STATS @DISK_CACHE_STATS@
f96e0b
 
f96e0b
 #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@"
f96e0b
 #define GRUB_PLATFORM "@GRUB_PLATFORM@"
f96e0b
diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c
f96e0b
index 164a6fe..c531e44 100644
f96e0b
--- a/grub-core/commands/blocklist.c
f96e0b
+++ b/grub-core/commands/blocklist.c
f96e0b
@@ -28,58 +28,71 @@
f96e0b
 
f96e0b
 GRUB_MOD_LICENSE ("GPLv3+");
f96e0b
 
f96e0b
-static grub_err_t
f96e0b
-grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
f96e0b
-		    int argc, char **args)
f96e0b
+/* Context for grub_cmd_blocklist.  */
f96e0b
+struct blocklist_ctx
f96e0b
 {
f96e0b
-  grub_file_t file;
f96e0b
-  char buf[GRUB_DISK_SECTOR_SIZE];
f96e0b
-  unsigned long start_sector = 0;
f96e0b
-  unsigned num_sectors = 0;
f96e0b
-  int num_entries = 0;
f96e0b
-  grub_disk_addr_t part_start = 0;
f96e0b
-  auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
f96e0b
-			    unsigned length);
f96e0b
-  auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
f96e0b
-			     unsigned offset, unsigned length);
f96e0b
-
f96e0b
-  void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
f96e0b
-		       unsigned length)
f96e0b
+  unsigned long start_sector;
f96e0b
+  unsigned num_sectors;
f96e0b
+  int num_entries;
f96e0b
+  grub_disk_addr_t part_start;
f96e0b
+};
f96e0b
+
f96e0b
+/* Helper for grub_cmd_blocklist.  */
f96e0b
+static void
f96e0b
+print_blocklist (grub_disk_addr_t sector, unsigned num,
f96e0b
+		 unsigned offset, unsigned length, struct blocklist_ctx *ctx)
f96e0b
+{
f96e0b
+  if (ctx->num_entries++)
f96e0b
+    grub_printf (",");
f96e0b
+
f96e0b
+  grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start));
f96e0b
+  if (num > 0)
f96e0b
+    grub_printf ("+%u", num);
f96e0b
+  if (offset != 0 || length != 0)
f96e0b
+    grub_printf ("[%u-%u]", offset, offset + length);
f96e0b
+}
f96e0b
+
f96e0b
+/* Helper for grub_cmd_blocklist.  */
f96e0b
+static void
f96e0b
+read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length,
f96e0b
+		void *data)
f96e0b
+{
f96e0b
+  struct blocklist_ctx *ctx = data;
f96e0b
+
f96e0b
+  if (ctx->num_sectors > 0)
f96e0b
     {
f96e0b
-      if (num_sectors > 0)
f96e0b
+      if (ctx->start_sector + ctx->num_sectors == sector
f96e0b
+	  && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
f96e0b
 	{
f96e0b
-	  if (start_sector + num_sectors == sector
f96e0b
-	      && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
f96e0b
-	    {
f96e0b
-	      num_sectors++;
f96e0b
-	      return;
f96e0b
-	    }
f96e0b
-
f96e0b
-	  print_blocklist (start_sector, num_sectors, 0, 0);
f96e0b
-	  num_sectors = 0;
f96e0b
+	  ctx->num_sectors++;
f96e0b
+	  return;
f96e0b
 	}
f96e0b
 
f96e0b
-      if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
f96e0b
-	{
f96e0b
-	  start_sector = sector;
f96e0b
-	  num_sectors++;
f96e0b
-	}
f96e0b
-      else
f96e0b
-	print_blocklist (sector, 0, offset, length);
f96e0b
+      print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
f96e0b
+      ctx->num_sectors = 0;
f96e0b
     }
f96e0b
 
f96e0b
-  void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
f96e0b
-			unsigned offset, unsigned length)
f96e0b
+  if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
f96e0b
     {
f96e0b
-      if (num_entries++)
f96e0b
-	grub_printf (",");
f96e0b
-
f96e0b
-      grub_printf ("%llu", (unsigned long long) (sector - part_start));
f96e0b
-      if (num > 0)
f96e0b
-	grub_printf ("+%u", num);
f96e0b
-      if (offset != 0 || length != 0)
f96e0b
-	grub_printf ("[%u-%u]", offset, offset + length);
f96e0b
+      ctx->start_sector = sector;
f96e0b
+      ctx->num_sectors++;
f96e0b
     }
f96e0b
+  else
f96e0b
+    print_blocklist (sector, 0, offset, length, ctx);
f96e0b
+}
f96e0b
+
f96e0b
+static grub_err_t
f96e0b
+grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
f96e0b
+		    int argc, char **args)
f96e0b
+{
f96e0b
+  grub_file_t file;
f96e0b
+  char buf[GRUB_DISK_SECTOR_SIZE];
f96e0b
+  struct blocklist_ctx ctx = {
f96e0b
+    .start_sector = 0,
f96e0b
+    .num_sectors = 0,
f96e0b
+    .num_entries = 0,
f96e0b
+    .part_start = 0
f96e0b
+  };
f96e0b
 
f96e0b
   if (argc < 1)
f96e0b
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
f96e0b
@@ -93,15 +106,16 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
f96e0b
     return grub_error (GRUB_ERR_BAD_DEVICE,
f96e0b
 		       "this command is available only for disk devices");
f96e0b
 
f96e0b
-  part_start = grub_partition_get_start (file->device->disk->partition);
f96e0b
+  ctx.part_start = grub_partition_get_start (file->device->disk->partition);
f96e0b
 
f96e0b
   file->read_hook = read_blocklist;
f96e0b
+  file->read_hook_data = &ctx;
f96e0b
 
f96e0b
   while (grub_file_read (file, buf, sizeof (buf)) > 0)
f96e0b
     ;
f96e0b
 
f96e0b
-  if (num_sectors > 0)
f96e0b
-    print_blocklist (start_sector, num_sectors, 0, 0);
f96e0b
+  if (ctx.num_sectors > 0)
f96e0b
+    print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx;;
f96e0b
 
f96e0b
   grub_file_close (file);
f96e0b
 
f96e0b
diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
f96e0b
index 9a35550..4b94173 100644
f96e0b
--- a/grub-core/commands/loadenv.c
f96e0b
+++ b/grub-core/commands/loadenv.c
f96e0b
@@ -284,44 +284,51 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
f96e0b
   return 1;
f96e0b
 }
f96e0b
 
f96e0b
+/* Context for grub_cmd_save_env.  */
f96e0b
+struct grub_cmd_save_env_ctx
f96e0b
+{
f96e0b
+  struct blocklist *head, *tail;
f96e0b
+};
f96e0b
+
f96e0b
+/* Store blocklists in a linked list.  */
f96e0b
+static void
f96e0b
+save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
f96e0b
+		    void *data)
f96e0b
+{
f96e0b
+  struct grub_cmd_save_env_ctx *ctx = data;
f96e0b
+  struct blocklist *block;
f96e0b
+
f96e0b
+  if (offset + length > GRUB_DISK_SECTOR_SIZE)
f96e0b
+    /* Seemingly a bug.  */
f96e0b
+    return;
f96e0b
+
f96e0b
+  block = grub_malloc (sizeof (*block));
f96e0b
+  if (! block)
f96e0b
+    return;
f96e0b
+
f96e0b
+  block->sector = sector;
f96e0b
+  block->offset = offset;
f96e0b
+  block->length = length;
f96e0b
+
f96e0b
+  /* Slightly complicated, because the list should be FIFO.  */
f96e0b
+  block->next = 0;
f96e0b
+  if (ctx->tail)
f96e0b
+    ctx->tail->next = block;
f96e0b
+  ctx->tail = block;
f96e0b
+  if (! ctx->head)
f96e0b
+    ctx->head = block;
f96e0b
+}
f96e0b
+
f96e0b
 static grub_err_t
f96e0b
 grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
f96e0b
 {
f96e0b
   struct grub_arg_list *state = ctxt->state;
f96e0b
   grub_file_t file;
f96e0b
   grub_envblk_t envblk;
f96e0b
-  struct blocklist *head = 0;
f96e0b
-  struct blocklist *tail = 0;
f96e0b
-
f96e0b
-  /* Store blocklists in a linked list.  */
f96e0b
-  auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
f96e0b
-                                        unsigned offset,
f96e0b
-                                        unsigned length);
f96e0b
-  void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
f96e0b
-                                   unsigned offset, unsigned length)
f96e0b
-    {
f96e0b
-      struct blocklist *block;
f96e0b
-
f96e0b
-      if (offset + length > GRUB_DISK_SECTOR_SIZE)
f96e0b
-        /* Seemingly a bug.  */
f96e0b
-        return;
f96e0b
-
f96e0b
-      block = grub_malloc (sizeof (*block));
f96e0b
-      if (! block)
f96e0b
-        return;
f96e0b
-
f96e0b
-      block->sector = sector;
f96e0b
-      block->offset = offset;
f96e0b
-      block->length = length;
f96e0b
-
f96e0b
-      /* Slightly complicated, because the list should be FIFO.  */
f96e0b
-      block->next = 0;
f96e0b
-      if (tail)
f96e0b
-        tail->next = block;
f96e0b
-      tail = block;
f96e0b
-      if (! head)
f96e0b
-        head = block;
f96e0b
-    }
f96e0b
+  struct grub_cmd_save_env_ctx ctx = {
f96e0b
+    .head = 0,
f96e0b
+    .tail = 0
f96e0b
+  };
f96e0b
 
f96e0b
   if (! argc)
f96e0b
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
f96e0b
@@ -336,13 +343,14 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
f96e0b
       return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
f96e0b
     }
f96e0b
 
f96e0b
-  file->read_hook = read_hook;
f96e0b
+  file->read_hook = save_env_read_hook;
f96e0b
+  file->read_hook_data = &ctx;
f96e0b
   envblk = read_envblk_file (file);
f96e0b
   file->read_hook = 0;
f96e0b
   if (! envblk)
f96e0b
     goto fail;
f96e0b
 
f96e0b
-  if (check_blocklists (envblk, head, file))
f96e0b
+  if (check_blocklists (envblk, ctx.head, file))
f96e0b
     goto fail;
f96e0b
 
f96e0b
   while (argc)
f96e0b
@@ -363,12 +371,12 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
f96e0b
       args++;
f96e0b
     }
f96e0b
 
f96e0b
-  write_blocklists (envblk, head, file);
f96e0b
+  write_blocklists (envblk, ctx.head, file);
f96e0b
 
f96e0b
  fail:
f96e0b
   if (envblk)
f96e0b
     grub_envblk_close (envblk);
f96e0b
-  free_blocklists (head);
f96e0b
+  free_blocklists (ctx.head);
f96e0b
   grub_file_close (file);
f96e0b
   return grub_errno;
f96e0b
 }
f96e0b
diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c
f96e0b
index a1bf775..4d0280a 100644
f96e0b
--- a/grub-core/commands/testload.c
f96e0b
+++ b/grub-core/commands/testload.c
f96e0b
@@ -31,6 +31,17 @@
f96e0b
 
f96e0b
 GRUB_MOD_LICENSE ("GPLv3+");
f96e0b
 
f96e0b
+/* Helper for grub_cmd_testload.  */
f96e0b
+static void
f96e0b
+read_progress (grub_disk_addr_t sector __attribute__ ((unused)),
f96e0b
+	       unsigned offset __attribute__ ((unused)),
f96e0b
+	       unsigned len __attribute__ ((unused)),
f96e0b
+	       void *data __attribute__ ((unused)))
f96e0b
+{
f96e0b
+  grub_xputs (".");
f96e0b
+  grub_refresh ();
f96e0b
+}
f96e0b
+
f96e0b
 static grub_err_t
f96e0b
 grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
f96e0b
 		   int argc, char *argv[])
f96e0b
@@ -39,15 +50,6 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
f96e0b
   char *buf;
f96e0b
   grub_size_t size;
f96e0b
   grub_off_t pos;
f96e0b
-  auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len);
f96e0b
-
f96e0b
-  void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)),
f96e0b
-		  unsigned offset __attribute__ ((unused)),
f96e0b
-		  unsigned len __attribute__ ((unused)))
f96e0b
-    {
f96e0b
-      grub_xputs (".");
f96e0b
-      grub_refresh ();
f96e0b
-    }
f96e0b
 
f96e0b
   if (argc < 1)
f96e0b
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
f96e0b
@@ -68,7 +70,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
f96e0b
     goto fail;
f96e0b
 
f96e0b
   grub_printf ("Reading %s sequentially", argv[0]);
f96e0b
-  file->read_hook = read_func;
f96e0b
+  file->read_hook = read_progress;
f96e0b
   if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
f96e0b
     goto fail;
f96e0b
   grub_printf (" Done.\n");
f96e0b
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
f96e0b
index 6c49e5d..726704e 100644
f96e0b
--- a/grub-core/fs/affs.c
f96e0b
+++ b/grub-core/fs/affs.c
f96e0b
@@ -531,7 +531,7 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
     (struct grub_affs_data *) file->data;
f96e0b
 
f96e0b
   return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
f96e0b
-				file->read_hook,
f96e0b
+				file->read_hook, file->read_hook_data,
f96e0b
 				file->offset, len, buf, grub_affs_read_block,
f96e0b
 				grub_be_to_cpu32 (data->diropen.di.size),
f96e0b
 				data->log_blocksize, 0);
f96e0b
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
f96e0b
index fa2fc3f..f2e39d3 100644
f96e0b
--- a/grub-core/fs/bfs.c
f96e0b
+++ b/grub-core/fs/bfs.c
f96e0b
@@ -217,9 +217,7 @@ read_bfs_file (grub_disk_t disk,
f96e0b
 	       const struct grub_bfs_superblock *sb,
f96e0b
 	       const struct grub_bfs_inode *ino,
f96e0b
 	       grub_off_t off, void *buf, grub_size_t len,
f96e0b
-	       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-						   unsigned offset,
f96e0b
-						   unsigned length))
f96e0b
+	       grub_disk_read_hook_t read_hook, void *read_hook_data)
f96e0b
 {
f96e0b
   if (len == 0)
f96e0b
     return GRUB_ERR_NONE;
f96e0b
@@ -245,6 +243,7 @@ read_bfs_file (grub_disk_t disk,
f96e0b
 	      if (read_size > len)
f96e0b
 		read_size = len;
f96e0b
 	      disk->read_hook = read_hook;
f96e0b
+	      disk->read_hook_data = read_hook_data;
f96e0b
 	      err = read_extent (disk, sb, &ino->direct[i], 0, off - pos,
f96e0b
 				 buf, read_size);
f96e0b
 	      disk->read_hook = 0;
f96e0b
@@ -290,6 +289,7 @@ read_bfs_file (grub_disk_t disk,
f96e0b
 	      if (read_size > len)
f96e0b
 		read_size = len;
f96e0b
 	      disk->read_hook = read_hook;
f96e0b
+	      disk->read_hook_data = read_hook_data;
f96e0b
 	      err = read_extent (disk, sb, &entries[i], 0, off - pos,
f96e0b
 				 buf, read_size);
f96e0b
 	      disk->read_hook = 0;
f96e0b
@@ -401,6 +401,7 @@ read_bfs_file (grub_disk_t disk,
f96e0b
 	if (read_size > len)
f96e0b
 	  read_size = len;
f96e0b
 	disk->read_hook = read_hook;
f96e0b
+	disk->read_hook_data = read_hook_data;
f96e0b
 	err = read_extent (disk, sb, &l2_entries[l2n], 0, boff,
f96e0b
 			   buf, read_size);
f96e0b
 	disk->read_hook = 0;
f96e0b
@@ -431,7 +432,7 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
   int level;
f96e0b
   grub_uint64_t node_off;
f96e0b
 
f96e0b
-  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
f96e0b
+  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
f96e0b
   if (err)
f96e0b
     return 0;
f96e0b
   node_off = grub_bfs_to_cpu64 (head.root);
f96e0b
@@ -441,7 +442,8 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
     {
f96e0b
       struct grub_bfs_btree_node node;
f96e0b
       grub_uint64_t key_value;
f96e0b
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
f96e0b
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
f96e0b
+			   0, 0);
f96e0b
       if (err)
f96e0b
 	return 0;
f96e0b
       err = read_bfs_file (disk, sb, ino, node_off
f96e0b
@@ -451,7 +453,7 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
 				       BTREE_ALIGN) +
f96e0b
 			   grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
 			   sizeof (grub_uint16_t), &key_value,
f96e0b
-			   sizeof (grub_uint64_t), 0);
f96e0b
+			   sizeof (grub_uint64_t), 0, 0);
f96e0b
       if (err)
f96e0b
 	return 0;
f96e0b
 
f96e0b
@@ -461,7 +463,8 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
   while (1)
f96e0b
     {
f96e0b
       struct grub_bfs_btree_node node;
f96e0b
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
f96e0b
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
f96e0b
+			   0, 0);
f96e0b
       if (err)
f96e0b
 	return 0;
f96e0b
       {
f96e0b
@@ -473,7 +476,7 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
 
f96e0b
 	err =
f96e0b
 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
f96e0b
-			 grub_bfs_to_cpu_treehead (node.total_key_len), 0);
f96e0b
+			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return 0;
f96e0b
 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
f96e0b
@@ -483,7 +486,7 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
 					 (node.total_key_len), BTREE_ALIGN),
f96e0b
 			     keylen_idx,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
-			     sizeof (grub_uint16_t), 0);
f96e0b
+			     sizeof (grub_uint16_t), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return 0;
f96e0b
 	err = read_bfs_file (disk, sb, ino, node_off
f96e0b
@@ -494,7 +497,7 @@ iterate_in_b_tree (grub_disk_t disk,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
 			     sizeof (grub_uint16_t), key_values,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
-			     sizeof (grub_uint64_t), 0);
f96e0b
+			     sizeof (grub_uint64_t), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return 0;
f96e0b
 
f96e0b
@@ -556,7 +559,7 @@ find_in_b_tree (grub_disk_t disk,
f96e0b
   int level;
f96e0b
   grub_uint64_t node_off;
f96e0b
 
f96e0b
-  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
f96e0b
+  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
f96e0b
   if (err)
f96e0b
     return err;
f96e0b
   node_off = grub_bfs_to_cpu64 (head.root);
f96e0b
@@ -565,7 +568,8 @@ find_in_b_tree (grub_disk_t disk,
f96e0b
   while (1)
f96e0b
     {
f96e0b
       struct grub_bfs_btree_node node;
f96e0b
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
f96e0b
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
f96e0b
+			   0, 0);
f96e0b
       if (err)
f96e0b
 	return err;
f96e0b
       if (node.count_keys == 0)
f96e0b
@@ -578,7 +582,7 @@ find_in_b_tree (grub_disk_t disk,
f96e0b
 	unsigned i;
f96e0b
 	err =
f96e0b
 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
f96e0b
-			 grub_bfs_to_cpu_treehead (node.total_key_len), 0);
f96e0b
+			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return err;
f96e0b
 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
f96e0b
@@ -589,7 +593,7 @@ find_in_b_tree (grub_disk_t disk,
f96e0b
 								 total_key_len),
f96e0b
 				       BTREE_ALIGN), keylen_idx,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
-			     sizeof (grub_uint16_t), 0);
f96e0b
+			     sizeof (grub_uint16_t), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return err;
f96e0b
 	err = read_bfs_file (disk, sb, ino, node_off
f96e0b
@@ -600,7 +604,7 @@ find_in_b_tree (grub_disk_t disk,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
 			     sizeof (grub_uint16_t), key_values,
f96e0b
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
f96e0b
-			     sizeof (grub_uint64_t), 0);
f96e0b
+			     sizeof (grub_uint64_t), 0, 0);
f96e0b
 	if (err)
f96e0b
 	  return err;
f96e0b
 
f96e0b
@@ -771,7 +775,7 @@ find_file (const char *path, grub_disk_t disk,
f96e0b
 		  return grub_errno;
f96e0b
 		}
f96e0b
 	      grub_free (old_alloc);
f96e0b
-	      err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0);
f96e0b
+	      err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0);
f96e0b
 	      if (err)
f96e0b
 		{
f96e0b
 		  grub_free (alloc);
f96e0b
@@ -974,7 +978,8 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_bfs_data *data = file->data;
f96e0b
 
f96e0b
   err = read_bfs_file (file->device->disk, &data->sb,
f96e0b
-		       data->ino, file->offset, buf, len, file->read_hook);
f96e0b
+		       data->ino, file->offset, buf, len,
f96e0b
+		       file->read_hook, file->read_hook_data);
f96e0b
   if (err)
f96e0b
     return -1;
f96e0b
   return len;
f96e0b
@@ -1056,7 +1061,7 @@ read_bfs_attr (grub_disk_t disk,
f96e0b
       if (read > len)
f96e0b
 	read = len;
f96e0b
 
f96e0b
-      err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0);
f96e0b
+      err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0, 0);
f96e0b
       if (err)
f96e0b
 	return -1;
f96e0b
       return read;
f96e0b
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
f96e0b
index 0ebde35..18429ac 100644
f96e0b
--- a/grub-core/fs/ext2.c
f96e0b
+++ b/grub-core/fs/ext2.c
f96e0b
@@ -525,11 +525,11 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_ext2_read_file (grub_fshelp_node_t node,
f96e0b
-		     void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					unsigned offset, unsigned length),
f96e0b
+		     grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		     grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
 				pos, len, buf, grub_ext2_read_block,
f96e0b
 				grub_cpu_to_le32 (node->inode.size)
f96e0b
 				| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
f96e0b
@@ -676,7 +676,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
f96e0b
 		  grub_le_to_cpu32 (diro->inode.size));
f96e0b
   else
f96e0b
     {
f96e0b
-      grub_ext2_read_file (diro, 0, 0,
f96e0b
+      grub_ext2_read_file (diro, 0, 0, 0,
f96e0b
 			   grub_le_to_cpu32 (diro->inode.size),
f96e0b
 			   symlink);
f96e0b
       if (grub_errno)
f96e0b
@@ -709,7 +709,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
f96e0b
     {
f96e0b
       struct ext2_dirent dirent;
f96e0b
 
f96e0b
-      grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
f96e0b
+      grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent),
f96e0b
 			   (char *) &dirent);
f96e0b
       if (grub_errno)
f96e0b
 	return 0;
f96e0b
@@ -723,7 +723,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	  struct grub_fshelp_node *fdiro;
f96e0b
 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
f96e0b
 
f96e0b
-	  grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
f96e0b
+	  grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent),
f96e0b
 			       dirent.namelen, filename);
f96e0b
 	  if (grub_errno)
f96e0b
 	    return 0;
f96e0b
@@ -850,7 +850,8 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
   struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
f96e0b
 
f96e0b
-  return grub_ext2_read_file (&data->diropen, file->read_hook,
f96e0b
+  return grub_ext2_read_file (&data->diropen,
f96e0b
+			      file->read_hook, file->read_hook_data,
f96e0b
 			      file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
f96e0b
index 7664153..db28158 100644
f96e0b
--- a/grub-core/fs/fat.c
f96e0b
+++ b/grub-core/fs/fat.c
f96e0b
@@ -454,8 +454,7 @@ grub_fat_mount (grub_disk_t disk)
f96e0b
 
f96e0b
 static grub_ssize_t
f96e0b
 grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
f96e0b
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				       unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t offset, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   grub_size_t size;
f96e0b
@@ -561,6 +560,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
f96e0b
 	size = len;
f96e0b
 
f96e0b
       disk->read_hook = read_hook;
f96e0b
+      disk->read_hook_data = read_hook_data;
f96e0b
       grub_disk_read (disk, sector, offset, size, buf);
f96e0b
       disk->read_hook = 0;
f96e0b
       if (grub_errno)
f96e0b
@@ -630,7 +630,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
f96e0b
 
f96e0b
       ctxt->offset += sizeof (dir);
f96e0b
 
f96e0b
-      if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (dir),
f96e0b
+      if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir),
f96e0b
 			      (char *) &dir)
f96e0b
 	   != sizeof (dir))
f96e0b
 	break;
f96e0b
@@ -652,7 +652,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
f96e0b
 	    {
f96e0b
 	      struct grub_fat_dir_entry sec;
f96e0b
 	      ctxt->offset += sizeof (sec);
f96e0b
-	      if (grub_fat_read_data (disk, data, 0,
f96e0b
+	      if (grub_fat_read_data (disk, data, 0, 0,
f96e0b
 				      ctxt->offset, sizeof (sec), (char *) &sec)
f96e0b
 		  != sizeof (sec))
f96e0b
 		break;
f96e0b
@@ -729,7 +729,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
f96e0b
       ctxt->offset += sizeof (ctxt->dir);
f96e0b
 
f96e0b
       /* Read a directory entry.  */
f96e0b
-      if (grub_fat_read_data (disk, data, 0,
f96e0b
+      if (grub_fat_read_data (disk, data, 0, 0,
f96e0b
 			      ctxt->offset, sizeof (ctxt->dir),
f96e0b
 			      (char *) &ctxt->dir)
f96e0b
 	   != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
f96e0b
@@ -1031,7 +1031,8 @@ grub_fat_open (grub_file_t file, const char *name)
f96e0b
 static grub_ssize_t
f96e0b
 grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
-  return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
f96e0b
+  return grub_fat_read_data (file->device->disk, file->data,
f96e0b
+			     file->read_hook, file->read_hook_data,
f96e0b
 			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
@@ -1064,7 +1065,7 @@ grub_fat_label (grub_device_t device, char **label)
f96e0b
     {
f96e0b
       offset += sizeof (dir);
f96e0b
 
f96e0b
-      if (grub_fat_read_data (disk, data, 0,
f96e0b
+      if (grub_fat_read_data (disk, data, 0, 0,
f96e0b
 			       offset, sizeof (dir), (char *) &dir)
f96e0b
 	   != sizeof (dir))
f96e0b
 	break;
f96e0b
diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c
f96e0b
index 11a1259..d56e63f 100644
f96e0b
--- a/grub-core/fs/fshelp.c
f96e0b
+++ b/grub-core/fs/fshelp.c
f96e0b
@@ -248,14 +248,13 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
f96e0b
 
f96e0b
 /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
f96e0b
    beginning with the block POS.  READ_HOOK should be set before
f96e0b
-   reading a block from the file.  GET_BLOCK is used to translate file
f96e0b
-   blocks to disk blocks.  The file is FILESIZE bytes big and the
f96e0b
+   reading a block from the file.  READ_HOOK_DATA is passed through as
f96e0b
+   the DATA argument to READ_HOOK.  GET_BLOCK is used to translate
f96e0b
+   file blocks to disk blocks.  The file is FILESIZE bytes big and the
f96e0b
    blocks have a size of LOG2BLOCKSIZE (in log2).  */
f96e0b
 grub_ssize_t
f96e0b
 grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
f96e0b
-		       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-                                                           unsigned offset,
f96e0b
-                                                           unsigned length),
f96e0b
+		       grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		       grub_off_t pos, grub_size_t len, char *buf,
f96e0b
 		       grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
f96e0b
                                                       grub_disk_addr_t block),
f96e0b
@@ -307,6 +306,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
f96e0b
       if (blknr)
f96e0b
 	{
f96e0b
 	  disk->read_hook = read_hook;
f96e0b
+	  disk->read_hook_data = read_hook_data;
f96e0b
 
f96e0b
 	  grub_disk_read (disk, blknr + blocks_start, skipfirst,
f96e0b
 			  blockend, buf);
f96e0b
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
f96e0b
index 9ed3330..4b2b5aa 100644
f96e0b
--- a/grub-core/fs/hfs.c
f96e0b
+++ b/grub-core/fs/hfs.c
f96e0b
@@ -243,8 +243,7 @@ grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat,
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_hfs_read_file (struct grub_hfs_data *data,
f96e0b
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				       unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   grub_off_t i;
f96e0b
@@ -289,6 +288,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
f96e0b
       if (blknr)
f96e0b
 	{
f96e0b
 	  data->disk->read_hook = read_hook;
f96e0b
+	  data->disk->read_hook_data = read_hook_data;
f96e0b
 	  grub_disk_read (data->disk, blknr, skipfirst,
f96e0b
 			  blockend, buf);
f96e0b
 	  data->disk->read_hook = 0;
f96e0b
@@ -1269,7 +1269,8 @@ grub_hfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_hfs_data *data =
f96e0b
     (struct grub_hfs_data *) file->data;
f96e0b
 
f96e0b
-  return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf);
f96e0b
+  return grub_hfs_read_file (data, file->read_hook, file->read_hook_data,
f96e0b
+			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 
f96e0b
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
f96e0b
index dcca581..29a3a94 100644
f96e0b
--- a/grub-core/fs/hfsplus.c
f96e0b
+++ b/grub-core/fs/hfsplus.c
f96e0b
@@ -375,11 +375,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_hfsplus_read_file (grub_fshelp_node_t node,
f96e0b
-			void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					   unsigned offset, unsigned length),
f96e0b
+			grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 			grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
 				pos, len, buf, grub_hfsplus_read_block,
f96e0b
 				node->size,
f96e0b
 				node->data->log2blksize - GRUB_DISK_SECTOR_BITS,
f96e0b
@@ -477,7 +477,7 @@ grub_hfsplus_mount (grub_disk_t disk)
f96e0b
     grub_be_to_cpu64 (data->volheader.extents_file.size);
f96e0b
 
f96e0b
   /* Read the essential information about the trees.  */
f96e0b
-  if (grub_hfsplus_read_file (&data->catalog_tree.file, 0,
f96e0b
+  if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, 0,
f96e0b
 			      sizeof (struct grub_hfsplus_btnode),
f96e0b
 			      sizeof (header), (char *) &header) <= 0)
f96e0b
     goto fail;
f96e0b
@@ -487,14 +487,14 @@ grub_hfsplus_mount (grub_disk_t disk)
f96e0b
   data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) &&
f96e0b
 			  (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE));
f96e0b
 
f96e0b
-  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0,
f96e0b
+  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
f96e0b
 			      sizeof (struct grub_hfsplus_btnode),
f96e0b
 			      sizeof (header), (char *) &header) <= 0)
f96e0b
     goto fail;
f96e0b
 
f96e0b
   data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
f96e0b
 
f96e0b
-  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
f96e0b
+  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, 0,
f96e0b
 			      sizeof (node), (char *) &node) <= 0)
f96e0b
     goto fail;
f96e0b
 
f96e0b
@@ -605,7 +605,7 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
f96e0b
   if (!symlink)
f96e0b
     return 0;
f96e0b
 
f96e0b
-  numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink);
f96e0b
+  numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink);
f96e0b
   if (numread != (grub_ssize_t) node->size)
f96e0b
     {
f96e0b
       grub_free (symlink);
f96e0b
@@ -649,7 +649,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
f96e0b
 	saved_node = first_node->next;
f96e0b
       node_count++;
f96e0b
 
f96e0b
-      if (grub_hfsplus_read_file (&btree->file, 0,
f96e0b
+      if (grub_hfsplus_read_file (&btree->file, 0, 0,
f96e0b
 				  (((grub_disk_addr_t)
f96e0b
 				    grub_be_to_cpu32 (first_node->next))
f96e0b
 				   * btree->nodesize),
f96e0b
@@ -702,7 +702,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
f96e0b
       node_count++;
f96e0b
 
f96e0b
       /* Read a node.  */
f96e0b
-      if (grub_hfsplus_read_file (&btree->file, 0,
f96e0b
+      if (grub_hfsplus_read_file (&btree->file, 0, 0,
f96e0b
 				  (grub_disk_addr_t) currnode
f96e0b
 				  * (grub_disk_addr_t) btree->nodesize,
f96e0b
 				  btree->nodesize, (char *) node) <= 0)
f96e0b
@@ -971,8 +971,9 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_hfsplus_data *data =
f96e0b
     (struct grub_hfsplus_data *) file->data;
f96e0b
 
f96e0b
-  return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
f96e0b
-				     file->offset, len, buf);
f96e0b
+  return grub_hfsplus_read_file (&data->opened_file,
f96e0b
+				 file->read_hook, file->read_hook_data,
f96e0b
+				 file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 /* Context for grub_hfsplus_dir.  */
f96e0b
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
f96e0b
index e37553d..19471e8 100644
f96e0b
--- a/grub-core/fs/iso9660.c
f96e0b
+++ b/grub-core/fs/iso9660.c
f96e0b
@@ -961,6 +961,7 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 
f96e0b
   /* XXX: The file is stored in as a single extent.  */
f96e0b
   data->disk->read_hook = file->read_hook;
f96e0b
+  data->disk->read_hook_data = file->read_hook_data;
f96e0b
   read_node (data->node, file->offset, len, buf);
f96e0b
   data->disk->read_hook = NULL;
f96e0b
 
f96e0b
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
f96e0b
index 7c17192..88b21ad 100644
f96e0b
--- a/grub-core/fs/jfs.c
f96e0b
+++ b/grub-core/fs/jfs.c
f96e0b
@@ -577,8 +577,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_jfs_read_file (struct grub_jfs_data *data,
f96e0b
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				       unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   grub_off_t i;
f96e0b
@@ -616,6 +615,7 @@ grub_jfs_read_file (struct grub_jfs_data *data,
f96e0b
 	}
f96e0b
 
f96e0b
       data->disk->read_hook = read_hook;
f96e0b
+      data->disk->read_hook_data = read_hook_data;
f96e0b
       grub_disk_read (data->disk,
f96e0b
 		      blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz)
f96e0b
 				- GRUB_DISK_SECTOR_BITS),
f96e0b
@@ -782,7 +782,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
f96e0b
 
f96e0b
   if (size <= sizeof (data->currinode.symlink.path))
f96e0b
     grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
f96e0b
-  else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
f96e0b
+  else if (grub_jfs_read_file (data, 0, 0, 0, size, symlink) < 0)
f96e0b
     return grub_errno;
f96e0b
 
f96e0b
   symlink[size] = '\0';
f96e0b
@@ -894,7 +894,8 @@ grub_jfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_jfs_data *data =
f96e0b
     (struct grub_jfs_data *) file->data;
f96e0b
 
f96e0b
-  return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf);
f96e0b
+  return grub_jfs_read_file (data, file->read_hook, file->read_hook_data,
f96e0b
+			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 
f96e0b
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
f96e0b
index 9655211..918fe56 100644
f96e0b
--- a/grub-core/fs/minix.c
f96e0b
+++ b/grub-core/fs/minix.c
f96e0b
@@ -249,8 +249,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_minix_read_file (struct grub_minix_data *data,
f96e0b
-		      void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					 unsigned offset, unsigned length),
f96e0b
+		      grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		      grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   grub_uint32_t i;
f96e0b
@@ -301,6 +300,7 @@ grub_minix_read_file (struct grub_minix_data *data,
f96e0b
 	}
f96e0b
 
f96e0b
       data->disk->read_hook = read_hook;
f96e0b
+      data->disk->read_hook_data = read_hook_data;
f96e0b
       grub_disk_read (data->disk,
f96e0b
 		      GRUB_MINIX_ZONE2SECT(blknr),
f96e0b
 		      skipfirst, blockend, buf);
f96e0b
@@ -352,7 +352,7 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino)
f96e0b
   if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
f96e0b
     return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
f96e0b
 
f96e0b
-  if (grub_minix_read_file (data, 0, 0,
f96e0b
+  if (grub_minix_read_file (data, 0, 0, 0,
f96e0b
 			    GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
f96e0b
     return grub_errno;
f96e0b
 
f96e0b
@@ -409,10 +409,10 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
f96e0b
       if (grub_strlen (name) == 0)
f96e0b
 	return GRUB_ERR_NONE;
f96e0b
 
f96e0b
-      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
f96e0b
+      if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
f96e0b
 				(char *) &ino) < 0)
f96e0b
 	return grub_errno;
f96e0b
-      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
f96e0b
+      if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
f96e0b
 				data->filename_size, (char *) filename)< 0)
f96e0b
 	return grub_errno;
f96e0b
 
f96e0b
@@ -568,11 +568,11 @@ grub_minix_dir (grub_device_t device, const char *path,
f96e0b
       grub_memset (&info, 0, sizeof (info));
f96e0b
 
f96e0b
 
f96e0b
-      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
f96e0b
+      if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
f96e0b
 				(char *) &ino) < 0)
f96e0b
 	return grub_errno;
f96e0b
 
f96e0b
-      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
f96e0b
+      if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
f96e0b
 				data->filename_size,
f96e0b
 				(char *) filename) < 0)
f96e0b
 	return grub_errno;
f96e0b
@@ -649,7 +649,8 @@ grub_minix_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_minix_data *data =
f96e0b
     (struct grub_minix_data *) file->data;
f96e0b
 
f96e0b
-  return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
f96e0b
+  return grub_minix_read_file (data, file->read_hook, file->read_hook_data,
f96e0b
+			       file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 
f96e0b
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
f96e0b
index 9bd4444..3f28bd7 100644
f96e0b
--- a/grub-core/fs/nilfs2.c
f96e0b
+++ b/grub-core/fs/nilfs2.c
f96e0b
@@ -630,13 +630,11 @@ grub_nilfs2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_nilfs2_read_file (grub_fshelp_node_t node,
f96e0b
-		       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
f96e0b
-							   sector,
f96e0b
-							   unsigned offset,
f96e0b
-							   unsigned length),
f96e0b
+		       grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		       grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
 				pos, len, buf, grub_nilfs2_read_block,
f96e0b
 				grub_le_to_cpu64 (node->inode.i_size),
f96e0b
 				LOG2_NILFS2_BLOCK_SIZE (node->data), 0);
f96e0b
@@ -856,7 +854,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node)
f96e0b
   if (!symlink)
f96e0b
     return 0;
f96e0b
 
f96e0b
-  grub_nilfs2_read_file (diro, 0, 0,
f96e0b
+  grub_nilfs2_read_file (diro, 0, 0, 0,
f96e0b
 			 grub_le_to_cpu64 (diro->inode.i_size), symlink);
f96e0b
   if (grub_errno)
f96e0b
     {
f96e0b
@@ -887,7 +885,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
f96e0b
     {
f96e0b
       struct grub_nilfs2_dir_entry dirent;
f96e0b
 
f96e0b
-      grub_nilfs2_read_file (diro, 0, fpos,
f96e0b
+      grub_nilfs2_read_file (diro, 0, 0, fpos,
f96e0b
 			     sizeof (struct grub_nilfs2_dir_entry),
f96e0b
 			     (char *) &dirent);
f96e0b
       if (grub_errno)
f96e0b
@@ -902,7 +900,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	  struct grub_fshelp_node *fdiro;
f96e0b
 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
f96e0b
 
f96e0b
-	  grub_nilfs2_read_file (diro, 0,
f96e0b
+	  grub_nilfs2_read_file (diro, 0, 0,
f96e0b
 				 fpos + sizeof (struct grub_nilfs2_dir_entry),
f96e0b
 				 dirent.name_len, filename);
f96e0b
 	  if (grub_errno)
f96e0b
@@ -1025,7 +1023,8 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
   struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data;
f96e0b
 
f96e0b
-  return grub_nilfs2_read_file (&data->diropen, file->read_hook,
f96e0b
+  return grub_nilfs2_read_file (&data->diropen,
f96e0b
+				file->read_hook, file->read_hook_data,
f96e0b
 				file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
f96e0b
index 7ac46f9..5ea2e1b 100644
f96e0b
--- a/grub-core/fs/ntfs.c
f96e0b
+++ b/grub-core/fs/ntfs.c
f96e0b
@@ -91,21 +91,15 @@ static grub_err_t read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf,
f96e0b
 static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest,
f96e0b
 			     grub_disk_addr_t ofs, grub_size_t len,
f96e0b
 			     int cached,
f96e0b
-			     void
f96e0b
-			     NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
f96e0b
-							    sector,
f96e0b
-							    unsigned offset,
f96e0b
-							    unsigned length));
f96e0b
+			     grub_disk_read_hook_t read_hook,
f96e0b
+			     void *read_hook_data);
f96e0b
 
f96e0b
 static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
f96e0b
 			     grub_uint8_t *dest,
f96e0b
 			     grub_disk_addr_t ofs, grub_size_t len,
f96e0b
 			     int cached,
f96e0b
-			     void
f96e0b
-			     NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
f96e0b
-							    sector,
f96e0b
-							    unsigned offset,
f96e0b
-							    unsigned length));
f96e0b
+			     grub_disk_read_hook_t read_hook,
f96e0b
+			     void *read_hook_data);
f96e0b
 
f96e0b
 static void
f96e0b
 init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
f96e0b
@@ -207,7 +201,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
f96e0b
 	  at->edat_buf = grub_malloc (n);
f96e0b
 	  if (!at->edat_buf)
f96e0b
 	    return NULL;
f96e0b
-	  if (read_data (at, pa, at->edat_buf, 0, n, 0, 0))
f96e0b
+	  if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
f96e0b
 	    {
f96e0b
 	      grub_error (GRUB_ERR_BAD_FS,
f96e0b
 			  "fail to read non-resident attribute list");
f96e0b
@@ -249,7 +243,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
f96e0b
 	      if (read_attr
f96e0b
 		  (at, pa + 0x10,
f96e0b
 		   u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
f96e0b
-		   at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
f96e0b
+		   at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
f96e0b
 		return NULL;
f96e0b
 	      pa += u16at (pa, 4);
f96e0b
 	    }
f96e0b
@@ -325,9 +319,7 @@ retry:
f96e0b
     {
f96e0b
       if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
f96e0b
 	{
f96e0b
-	  void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector,
f96e0b
-					      unsigned offset,
f96e0b
-					      unsigned length);
f96e0b
+	  grub_disk_read_hook_t save_hook;
f96e0b
 
f96e0b
 	  save_hook = ctx->comp.disk->read_hook;
f96e0b
 	  ctx->comp.disk->read_hook = 0;
f96e0b
@@ -379,9 +371,7 @@ grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
f96e0b
 static grub_err_t
f96e0b
 read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
f96e0b
 	   grub_disk_addr_t ofs, grub_size_t len, int cached,
f96e0b
-	   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					       unsigned offset,
f96e0b
-					       unsigned length))
f96e0b
+	   grub_disk_read_hook_t read_hook, void *read_hook_data)
f96e0b
 {
f96e0b
   grub_disk_addr_t vcn;
f96e0b
   struct grub_ntfs_rlst cc, *ctx;
f96e0b
@@ -480,7 +470,8 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
f96e0b
   if (!(ctx->flags & GRUB_NTFS_RF_COMP))
f96e0b
     {
f96e0b
       grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
f96e0b
-			     read_hook, ofs, len, (char *) dest,
f96e0b
+			     read_hook, read_hook_data, ofs, len,
f96e0b
+			     (char *) dest,
f96e0b
 			     grub_ntfs_read_block, ofs + len,
f96e0b
 			     ctx->comp.log_spc, 0);
f96e0b
       return grub_errno;
f96e0b
@@ -495,9 +486,7 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
f96e0b
 static grub_err_t
f96e0b
 read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
f96e0b
 	   grub_size_t len, int cached,
f96e0b
-	   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					       unsigned offset,
f96e0b
-					       unsigned length))
f96e0b
+	   grub_disk_read_hook_t read_hook, void *read_hook_data)
f96e0b
 {
f96e0b
   grub_uint8_t *save_cur;
f96e0b
   grub_uint8_t attr;
f96e0b
@@ -532,7 +521,8 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
f96e0b
     }
f96e0b
   pp = find_attr (at, attr);
f96e0b
   if (pp)
f96e0b
-    ret = read_data (at, pp, dest, ofs, len, cached, read_hook);
f96e0b
+    ret = read_data (at, pp, dest, ofs, len, cached,
f96e0b
+		     read_hook, read_hook_data);
f96e0b
   else
f96e0b
     ret =
f96e0b
       (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
f96e0b
@@ -546,7 +536,7 @@ read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint32_t mftno)
f96e0b
 {
f96e0b
   if (read_attr
f96e0b
       (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
f96e0b
-       data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
f96e0b
+       data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
f96e0b
     return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno);
f96e0b
   return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE");
f96e0b
 }
f96e0b
@@ -717,7 +707,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node)
f96e0b
     }
f96e0b
 
f96e0b
   err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0,
f96e0b
-		   sizeof (struct symlink_descriptor), 1, 0);
f96e0b
+		   sizeof (struct symlink_descriptor), 1, 0, 0);
f96e0b
   if (err)
f96e0b
     return NULL;
f96e0b
 
f96e0b
@@ -743,7 +733,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node)
f96e0b
   if (!buf16)
f96e0b
     return NULL;
f96e0b
 
f96e0b
-  err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0);
f96e0b
+  err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0, 0);
f96e0b
   if (err)
f96e0b
     return NULL;
f96e0b
 
f96e0b
@@ -852,7 +842,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	    }
f96e0b
           else
f96e0b
             {
f96e0b
-              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0))
f96e0b
+              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
f96e0b
                 {
f96e0b
                   grub_error (GRUB_ERR_BAD_FS,
f96e0b
                               "fails to read non-resident $BITMAP");
f96e0b
@@ -899,7 +889,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	    {
f96e0b
 	      if ((read_attr
f96e0b
 		   (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
f96e0b
-		    (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0))
f96e0b
+		    (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0))
f96e0b
 		  || (fixup (indx, mft->data->idx_size,
f96e0b
 			     (const grub_uint8_t *) "INDX")))
f96e0b
 		goto done;
f96e0b
@@ -1136,7 +1126,7 @@ grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
     mft->attr.save_pos = 1;
f96e0b
 
f96e0b
   read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1,
f96e0b
-	     file->read_hook);
f96e0b
+	     file->read_hook, file->read_hook_data);
f96e0b
   return (grub_errno) ? -1 : (grub_ssize_t) len;
f96e0b
 }
f96e0b
 
f96e0b
diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c
f96e0b
index 02ea9fd..cf9e348 100644
f96e0b
--- a/grub-core/fs/ntfscomp.c
f96e0b
+++ b/grub-core/fs/ntfscomp.c
f96e0b
@@ -302,6 +302,7 @@ ntfscomp (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
f96e0b
   ret = 0;
f96e0b
 
f96e0b
   //ctx->comp.disk->read_hook = read_hook;
f96e0b
+  //ctx->comp.disk->read_hook_data = read_hook_data;
f96e0b
 
f96e0b
   if ((vcn > ctx->target_vcn) &&
f96e0b
       (read_block
f96e0b
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
f96e0b
index 686e4da..eaa7ade 100644
f96e0b
--- a/grub-core/fs/reiserfs.c
f96e0b
+++ b/grub-core/fs/reiserfs.c
f96e0b
@@ -240,9 +240,8 @@ struct grub_reiserfs_data
f96e0b
 static grub_ssize_t
f96e0b
 grub_reiserfs_read_real (struct grub_fshelp_node *node,
f96e0b
 			 grub_off_t off, char *buf, grub_size_t len,
f96e0b
-			 void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-							     unsigned offset,
f96e0b
-							     unsigned length));
f96e0b
+			 grub_disk_read_hook_t read_hook,
f96e0b
+			 void *read_hook_data);
f96e0b
 
f96e0b
 /* Internal-only functions. Not to be used outside of this file.  */
f96e0b
 
f96e0b
@@ -674,7 +673,7 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node)
f96e0b
   if (! symlink_buffer)
f96e0b
     return 0;
f96e0b
 
f96e0b
-  ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0);
f96e0b
+  ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0);
f96e0b
   if (ret < 0)
f96e0b
     {
f96e0b
       grub_free (symlink_buffer);
f96e0b
@@ -1036,9 +1035,7 @@ grub_reiserfs_open (struct grub_file *file, const char *name)
f96e0b
 static grub_ssize_t
f96e0b
 grub_reiserfs_read_real (struct grub_fshelp_node *node,
f96e0b
 			 grub_off_t off, char *buf, grub_size_t len,
f96e0b
-			 void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-							     unsigned offset,
f96e0b
-							     unsigned length))
f96e0b
+			 grub_disk_read_hook_t read_hook, void *read_hook_data)
f96e0b
 {
f96e0b
   unsigned int indirect_block, indirect_block_count;
f96e0b
   struct grub_reiserfs_key key;
f96e0b
@@ -1105,6 +1102,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
f96e0b
                             (unsigned) block, (unsigned) offset,
f96e0b
                             (unsigned) (offset + length));
f96e0b
               found.data->disk->read_hook = read_hook;
f96e0b
+              found.data->disk->read_hook_data = read_hook_data;
f96e0b
               grub_disk_read (found.data->disk,
f96e0b
                               block,
f96e0b
                               offset
f96e0b
@@ -1131,6 +1129,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
f96e0b
           if (grub_errno)
f96e0b
             goto fail;
f96e0b
           found.data->disk->read_hook = read_hook;
f96e0b
+          found.data->disk->read_hook_data = read_hook_data;
f96e0b
           for (indirect_block = 0;
f96e0b
                indirect_block < indirect_block_count
f96e0b
                  && current_position < final_position;
f96e0b
@@ -1236,7 +1235,7 @@ static grub_ssize_t
f96e0b
 grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
   return grub_reiserfs_read_real (file->data, file->offset, buf, len,
f96e0b
-				  file->read_hook);
f96e0b
+				  file->read_hook, file->read_hook_data);
f96e0b
 }
f96e0b
 
f96e0b
 /* Close the file FILE.  */
f96e0b
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
f96e0b
index b79b1e1..2e35444 100644
f96e0b
--- a/grub-core/fs/romfs.c
f96e0b
+++ b/grub-core/fs/romfs.c
f96e0b
@@ -399,6 +399,7 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 
f96e0b
   /* XXX: The file is stored in as a single extent.  */
f96e0b
   data->data->disk->read_hook = file->read_hook;
f96e0b
+  data->data->disk->read_hook_data = file->read_hook_data;
f96e0b
   grub_disk_read (data->data->disk,
f96e0b
 		  (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS,
f96e0b
 		  (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1),		  
f96e0b
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
f96e0b
index fed17d3..e7d2f72 100644
f96e0b
--- a/grub-core/fs/sfs.c
f96e0b
+++ b/grub-core/fs/sfs.c
f96e0b
@@ -345,11 +345,11 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_sfs_read_file (grub_fshelp_node_t node,
f96e0b
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				       unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
 				pos, len, buf, grub_sfs_read_block,
f96e0b
 				node->size, node->data->log_blocksize, 0);
f96e0b
 }
f96e0b
@@ -646,7 +646,8 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
   struct grub_sfs_data *data = (struct grub_sfs_data *) file->data;
f96e0b
 
f96e0b
-  return grub_sfs_read_file (&data->diropen, file->read_hook,
f96e0b
+  return grub_sfs_read_file (&data->diropen,
f96e0b
+			     file->read_hook, file->read_hook_data,
f96e0b
 			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
f96e0b
index b7f3afb..405935e 100644
f96e0b
--- a/grub-core/fs/udf.c
f96e0b
+++ b/grub-core/fs/udf.c
f96e0b
@@ -564,9 +564,7 @@ fail:
f96e0b
 
f96e0b
 static grub_ssize_t
f96e0b
 grub_udf_read_file (grub_fshelp_node_t node,
f96e0b
-		    void NESTED_FUNC_ATTR
f96e0b
-		    (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				  unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
f96e0b
@@ -591,10 +589,11 @@ grub_udf_read_file (grub_fshelp_node_t node,
f96e0b
       return 0;
f96e0b
     }
f96e0b
 
f96e0b
-  return  grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
-				 pos, len, buf, grub_udf_read_block,
f96e0b
-				 U64 (node->block.fe.file_size),
f96e0b
-				 node->data->lbshift, 0);
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
+				pos, len, buf, grub_udf_read_block,
f96e0b
+				U64 (node->block.fe.file_size),
f96e0b
+				node->data->lbshift, 0);
f96e0b
 }
f96e0b
 
f96e0b
 static unsigned sblocklist[] = { 256, 512, 0 };
f96e0b
@@ -861,7 +860,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 
f96e0b
   while (offset < U64 (dir->block.fe.file_size))
f96e0b
     {
f96e0b
-      if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
f96e0b
+      if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent),
f96e0b
 			      (char *) &dirent) != sizeof (dirent))
f96e0b
 	return 0;
f96e0b
 
f96e0b
@@ -898,7 +897,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	      if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
f96e0b
 		type = GRUB_FSHELP_SYMLINK;
f96e0b
 
f96e0b
-	      if ((grub_udf_read_file (dir, 0, offset,
f96e0b
+	      if ((grub_udf_read_file (dir, 0, 0, offset,
f96e0b
 				       dirent.file_ident_length,
f96e0b
 				       (char *) raw))
f96e0b
 		  != dirent.file_ident_length)
f96e0b
@@ -937,7 +936,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
f96e0b
   raw = grub_malloc (sz);
f96e0b
   if (!raw)
f96e0b
     return NULL;
f96e0b
-  if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0)
f96e0b
+  if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0)
f96e0b
     {
f96e0b
       grub_free (raw);
f96e0b
       return NULL;
f96e0b
@@ -1149,7 +1148,8 @@ grub_udf_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
 {
f96e0b
   struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data;
f96e0b
 
f96e0b
-  return grub_udf_read_file (node, file->read_hook, file->offset, len, buf);
f96e0b
+  return grub_udf_read_file (node, file->read_hook, file->read_hook_data,
f96e0b
+			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 static grub_err_t
f96e0b
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
f96e0b
index 089a5c6..c155912 100644
f96e0b
--- a/grub-core/fs/ufs.c
f96e0b
+++ b/grub-core/fs/ufs.c
f96e0b
@@ -331,8 +331,7 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_ufs_read_file (struct grub_ufs_data *data,
f96e0b
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-				       unsigned offset, unsigned length),
f96e0b
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		    grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
   struct grub_ufs_sblock *sblock = &data->sblock;
f96e0b
@@ -380,6 +379,7 @@ grub_ufs_read_file (struct grub_ufs_data *data,
f96e0b
       if (blknr)
f96e0b
 	{
f96e0b
 	  data->disk->read_hook = read_hook;
f96e0b
+	  data->disk->read_hook_data = read_hook_data;
f96e0b
 	  grub_disk_read (data->disk,
f96e0b
 			  blknr << grub_ufs_to_cpu32 (data->sblock.log2_blksz),
f96e0b
 			  skipfirst, blockend, buf);
f96e0b
@@ -455,7 +455,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
f96e0b
       && INODE_SIZE (data) <= sizeof (data->inode.symlink))
f96e0b
     grub_strcpy (symlink, (char *) data->inode.symlink);
f96e0b
   else
f96e0b
-    grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink);
f96e0b
+    grub_ufs_read_file (data, 0, 0, 0, INODE_SIZE (data), symlink);
f96e0b
   symlink[INODE_SIZE (data)] = '\0';
f96e0b
 
f96e0b
   /* The symlink is an absolute path, go back to the root inode.  */
f96e0b
@@ -509,7 +509,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
f96e0b
       if (grub_strlen (name) == 0)
f96e0b
 	return GRUB_ERR_NONE;
f96e0b
 
f96e0b
-      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
f96e0b
+      if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
f96e0b
 			      (char *) &dirent) < 0)
f96e0b
 	return grub_errno;
f96e0b
 
f96e0b
@@ -521,7 +521,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
f96e0b
       {
f96e0b
 	char filename[namelen + 1];
f96e0b
 
f96e0b
-	if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
f96e0b
+	if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
f96e0b
 				namelen, filename) < 0)
f96e0b
 	  return grub_errno;
f96e0b
 
f96e0b
@@ -659,7 +659,7 @@ grub_ufs_dir (grub_device_t device, const char *path,
f96e0b
       struct grub_ufs_dirent dirent;
f96e0b
       int namelen;
f96e0b
 
f96e0b
-      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
f96e0b
+      if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
f96e0b
 			      (char *) &dirent) < 0)
f96e0b
 	break;
f96e0b
 
f96e0b
@@ -679,7 +679,7 @@ grub_ufs_dir (grub_device_t device, const char *path,
f96e0b
 
f96e0b
 	grub_memset (&info, 0, sizeof (info));
f96e0b
 
f96e0b
-	if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
f96e0b
+	if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
f96e0b
 				namelen, filename) < 0)
f96e0b
 	  break;
f96e0b
 
f96e0b
@@ -752,7 +752,8 @@ grub_ufs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_ufs_data *data =
f96e0b
     (struct grub_ufs_data *) file->data;
f96e0b
 
f96e0b
-  return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf);
f96e0b
+  return grub_ufs_read_file (data, file->read_hook, file->read_hook_data,
f96e0b
+			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 
f96e0b
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
f96e0b
index aee1582..a5a1700 100644
f96e0b
--- a/grub-core/fs/xfs.c
f96e0b
+++ b/grub-core/fs/xfs.c
f96e0b
@@ -379,11 +379,11 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
f96e0b
    POS.  Return the amount of read bytes in READ.  */
f96e0b
 static grub_ssize_t
f96e0b
 grub_xfs_read_file (grub_fshelp_node_t node,
f96e0b
-		     void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-					unsigned offset, unsigned length),
f96e0b
+		     grub_disk_read_hook_t read_hook, void *read_hook_data,
f96e0b
 		     grub_off_t pos, grub_size_t len, char *buf)
f96e0b
 {
f96e0b
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
f96e0b
+  return grub_fshelp_read_file (node->data->disk, node,
f96e0b
+				read_hook, read_hook_data,
f96e0b
 				pos, len, buf, grub_xfs_read_block,
f96e0b
 				grub_be_to_cpu64 (node->inode.size),
f96e0b
 				node->data->sblock.log2_bsize
f96e0b
@@ -410,7 +410,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
f96e0b
 	if (!symlink)
f96e0b
 	  return 0;
f96e0b
 
f96e0b
-	numread = grub_xfs_read_file (node, 0, 0, size, symlink);
f96e0b
+	numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink);
f96e0b
 	if (numread != size)
f96e0b
 	  {
f96e0b
 	    grub_free (symlink);
f96e0b
@@ -592,7 +592,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
f96e0b
 	    struct grub_xfs_dirblock_tail *tail;
f96e0b
 	    tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
f96e0b
 
f96e0b
-	    numread = grub_xfs_read_file (dir, 0,
f96e0b
+	    numread = grub_xfs_read_file (dir, 0, 0,
f96e0b
 					  blk << dirblk_log2,
f96e0b
 					  dirblk_size, dirblock);
f96e0b
 	    if (numread != dirblk_size)
f96e0b
@@ -829,8 +829,9 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len)
f96e0b
   struct grub_xfs_data *data =
f96e0b
     (struct grub_xfs_data *) file->data;
f96e0b
 
f96e0b
-  return grub_xfs_read_file (&data->diropen, file->read_hook,
f96e0b
-			      file->offset, len, buf);
f96e0b
+  return grub_xfs_read_file (&data->diropen,
f96e0b
+			     file->read_hook, file->read_hook_data,
f96e0b
+			     file->offset, len, buf);
f96e0b
 }
f96e0b
 
f96e0b
 
f96e0b
diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
f96e0b
index 94318af..76ff450 100644
f96e0b
--- a/grub-core/kern/disk.c
f96e0b
+++ b/grub-core/kern/disk.c
f96e0b
@@ -603,7 +603,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
f96e0b
 	  cl = GRUB_DISK_SECTOR_SIZE - o;
f96e0b
 	  if (cl > l)
f96e0b
 	    cl = l;
f96e0b
-	  (disk->read_hook) (s, o, cl);
f96e0b
+	  (disk->read_hook) (s, o, cl, disk->read_hook_data);
f96e0b
 	  s++;
f96e0b
 	  l -= cl;
f96e0b
 	  o = 0;
f96e0b
diff --git a/include/grub/disk.h b/include/grub/disk.h
f96e0b
index 013ca1f..f0e3df3 100644
f96e0b
--- a/include/grub/disk.h
f96e0b
+++ b/include/grub/disk.h
f96e0b
@@ -19,6 +19,8 @@
f96e0b
 #ifndef GRUB_DISK_HEADER
f96e0b
 #define GRUB_DISK_HEADER	1
f96e0b
 
f96e0b
+#include <config.h>
f96e0b
+
f96e0b
 #include <grub/symbol.h>
f96e0b
 #include <grub/err.h>
f96e0b
 #include <grub/types.h>
f96e0b
@@ -99,6 +101,10 @@ extern grub_disk_dev_t EXPORT_VAR (grub_disk_dev_list);
f96e0b
 
f96e0b
 struct grub_partition;
f96e0b
 
f96e0b
+typedef void (*grub_disk_read_hook_t) (grub_disk_addr_t sector,
f96e0b
+				       unsigned offset, unsigned length,
f96e0b
+				       void *data);
f96e0b
+
f96e0b
 /* Disk.  */
f96e0b
 struct grub_disk
f96e0b
 {
f96e0b
@@ -122,8 +128,10 @@ struct grub_disk
f96e0b
 
f96e0b
   /* Called when a sector was read. OFFSET is between 0 and
f96e0b
      the sector size minus 1, and LENGTH is between 0 and the sector size.  */
f96e0b
-  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-		     unsigned offset, unsigned length);
f96e0b
+  grub_disk_read_hook_t read_hook;
f96e0b
+
f96e0b
+  /* Caller-specific data passed to the read hook.  */
f96e0b
+  void *read_hook_data;
f96e0b
 
f96e0b
   /* Device-specific data.  */
f96e0b
   void *data;
f96e0b
diff --git a/include/grub/file.h b/include/grub/file.h
f96e0b
index ae86401..8003985 100644
f96e0b
--- a/include/grub/file.h
f96e0b
+++ b/include/grub/file.h
f96e0b
@@ -23,6 +23,7 @@
f96e0b
 #include <grub/err.h>
f96e0b
 #include <grub/device.h>
f96e0b
 #include <grub/fs.h>
f96e0b
+#include <grub/disk.h>
f96e0b
 
f96e0b
 /* File description.  */
f96e0b
 struct grub_file
f96e0b
@@ -46,8 +47,10 @@ struct grub_file
f96e0b
   void *data;
f96e0b
 
f96e0b
   /* This is called when a sector is read. Used only for a disk device.  */
f96e0b
-  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-		     unsigned offset, unsigned length);
f96e0b
+  grub_disk_read_hook_t read_hook;
f96e0b
+
f96e0b
+  /* Caller-specific data passed to the read hook.  */
f96e0b
+  void *read_hook_data;
f96e0b
 };
f96e0b
 typedef struct grub_file *grub_file_t;
f96e0b
 
f96e0b
diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h
f96e0b
index e437d4c..5c57236 100644
f96e0b
--- a/include/grub/fshelp.h
f96e0b
+++ b/include/grub/fshelp.h
f96e0b
@@ -23,6 +23,7 @@
f96e0b
 #include <grub/types.h>
f96e0b
 #include <grub/symbol.h>
f96e0b
 #include <grub/err.h>
f96e0b
+#include <grub/disk.h>
f96e0b
 
f96e0b
 typedef struct grub_fshelp_node *grub_fshelp_node_t;
f96e0b
 
f96e0b
@@ -68,9 +69,8 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
f96e0b
    blocks have a size of LOG2BLOCKSIZE (in log2).  */
f96e0b
 grub_ssize_t
f96e0b
 EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
f96e0b
-				    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
f96e0b
-                                                                        unsigned offset,
f96e0b
-                                                                        unsigned length),
f96e0b
+				    grub_disk_read_hook_t read_hook,
f96e0b
+				    void *read_hook_data,
f96e0b
 				    grub_off_t pos, grub_size_t len, char *buf,
f96e0b
 				    grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
f96e0b
                                                                    grub_disk_addr_t block),
f96e0b
diff --git a/util/grub-setup.c b/util/grub-setup.c
f96e0b
index 187345a..5a7a857 100644
f96e0b
--- a/util/grub-setup.c
f96e0b
+++ b/util/grub-setup.c
f96e0b
@@ -138,6 +138,70 @@ write_rootdev (grub_device_t root_dev,
f96e0b
 #define BOOT_SECTOR 0
f96e0b
 #endif
f96e0b
 
f96e0b
+/* Helper for setup.  */
f96e0b
+static void
f96e0b
+save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length,
f96e0b
+		   void *data)
f96e0b
+{
f96e0b
+  grub_disk_addr_t *first_sector = data;
f96e0b
+  grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
f96e0b
+		  sector, offset, length);
f96e0b
+
f96e0b
+  if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
f96e0b
+    grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
f96e0b
+
f96e0b
+  *first_sector = sector;
f96e0b
+}
f96e0b
+
f96e0b
+struct blocklists
f96e0b
+{
f96e0b
+  struct grub_boot_blocklist *first_block, *block;
f96e0b
+#ifdef GRUB_SETUP_BIOS
f96e0b
+  grub_uint16_t current_segment;
f96e0b
+#endif
f96e0b
+  grub_uint16_t last_length;
f96e0b
+};
f96e0b
+
f96e0b
+/* Helper for setup.  */
f96e0b
+static void
f96e0b
+save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
f96e0b
+		 void *data)
f96e0b
+{
f96e0b
+  struct blocklists *bl = data;
f96e0b
+  struct grub_boot_blocklist *prev = bl->block + 1;
f96e0b
+
f96e0b
+  grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
f96e0b
+		  sector, offset, length);
f96e0b
+
f96e0b
+  if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
f96e0b
+    grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
f96e0b
+
f96e0b
+  if (bl->block != bl->first_block
f96e0b
+      && (grub_target_to_host64 (prev->start)
f96e0b
+	  + grub_target_to_host16 (prev->len)) == sector)
f96e0b
+    {
f96e0b
+      grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
f96e0b
+      prev->len = grub_host_to_target16 (t);
f96e0b
+    }
f96e0b
+  else
f96e0b
+    {
f96e0b
+      bl->block->start = grub_host_to_target64 (sector);
f96e0b
+      bl->block->len = grub_host_to_target16 (1);
f96e0b
+#ifdef GRUB_SETUP_BIOS
f96e0b
+      bl->block->segment = grub_host_to_target16 (bl->current_segment);
f96e0b
+#endif
f96e0b
+
f96e0b
+      bl->block--;
f96e0b
+      if (bl->block->len)
f96e0b
+	grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
f96e0b
+    }
f96e0b
+
f96e0b
+  bl->last_length = length;
f96e0b
+#ifdef GRUB_SETUP_BIOS
f96e0b
+  bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
f96e0b
+#endif
f96e0b
+}
f96e0b
+
f96e0b
 #ifdef GRUB_SETUP_BIOS
f96e0b
 /* Context for setup/identify_partmap.  */
f96e0b
 struct identify_partmap_ctx
f96e0b
@@ -147,7 +211,7 @@ struct identify_partmap_ctx
f96e0b
   int multiple_partmaps;
f96e0b
 };
f96e0b
 
f96e0b
-/* Helper for setup/identify_partmap.
f96e0b
+/* Helper for setup.
f96e0b
    Unlike root_dev, with dest_dev we're interested in the partition map even
f96e0b
    if dest_dev itself is a whole disk.  */
f96e0b
 static int
f96e0b
@@ -190,73 +254,16 @@ setup (const char *dir,
f96e0b
   grub_uint16_t core_sectors;
f96e0b
 #endif
f96e0b
   grub_device_t root_dev = 0, dest_dev, core_dev;
f96e0b
-  struct grub_boot_blocklist *first_block, *block;
f96e0b
+  struct blocklists bl;
f96e0b
   char *tmp_img;
f96e0b
   grub_disk_addr_t first_sector;
f96e0b
-#ifdef GRUB_SETUP_BIOS
f96e0b
-  grub_uint16_t current_segment
f96e0b
-    = GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
f96e0b
-#endif
f96e0b
-  grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
f96e0b
   FILE *fp;
f96e0b
 
f96e0b
-  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
f96e0b
-						unsigned offset,
f96e0b
-						unsigned length);
f96e0b
-  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
f96e0b
-					      unsigned offset,
f96e0b
-					      unsigned length);
f96e0b
-
f96e0b
-  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
f96e0b
-					   unsigned offset,
f96e0b
-					   unsigned length)
f96e0b
-    {
f96e0b
-      grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
f96e0b
-		      sector, offset, length);
f96e0b
-
f96e0b
-      if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
f96e0b
-	grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
f96e0b
-
f96e0b
-      first_sector = sector;
f96e0b
-    }
f96e0b
-
f96e0b
-  void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
f96e0b
-					 unsigned offset,
f96e0b
-					 unsigned length)
f96e0b
-    {
f96e0b
-      struct grub_boot_blocklist *prev = block + 1;
f96e0b
-
f96e0b
-      grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
f96e0b
-		      sector, offset, length);
f96e0b
-
f96e0b
-      if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
f96e0b
-	grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
f96e0b
-
f96e0b
-      if (block != first_block
f96e0b
-	  && (grub_target_to_host64 (prev->start)
f96e0b
-	      + grub_target_to_host16 (prev->len)) == sector)
f96e0b
-	{
f96e0b
-	  grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
f96e0b
-	  prev->len = grub_host_to_target16 (t);
f96e0b
-	}
f96e0b
-      else
f96e0b
-	{
f96e0b
-	  block->start = grub_host_to_target64 (sector);
f96e0b
-	  block->len = grub_host_to_target16 (1);
f96e0b
 #ifdef GRUB_SETUP_BIOS
f96e0b
-	  block->segment = grub_host_to_target16 (current_segment);
f96e0b
+  bl.current_segment =
f96e0b
+    GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
f96e0b
 #endif
f96e0b
-
f96e0b
-	  block--;
f96e0b
-	  if (block->len)
f96e0b
-	    grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
f96e0b
-	}
f96e0b
-
f96e0b
-      last_length = length;
f96e0b
-#ifdef GRUB_SETUP_BIOS
f96e0b
-      current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
f96e0b
-#endif
f96e0b
-    }
f96e0b
+  bl.last_length = GRUB_DISK_SECTOR_SIZE;
f96e0b
 
f96e0b
   /* Read the boot image by the OS service.  */
f96e0b
   boot_path = grub_util_get_path (dir, boot_file);
f96e0b
@@ -283,9 +290,9 @@ setup (const char *dir,
f96e0b
   core_img = grub_util_read_image (core_path);
f96e0b
 
f96e0b
   /* Have FIRST_BLOCK to point to the first blocklist.  */
f96e0b
-  first_block = (struct grub_boot_blocklist *) (core_img
f96e0b
-						+ GRUB_DISK_SECTOR_SIZE
f96e0b
-						- sizeof (*block));
f96e0b
+  bl.first_block = (struct grub_boot_blocklist *) (core_img
f96e0b
+						   + GRUB_DISK_SECTOR_SIZE
f96e0b
+						   - sizeof (*bl.block));
f96e0b
   grub_util_info ("root is `%s', dest is `%s'", root, dest);
f96e0b
 
f96e0b
   grub_util_info ("Opening dest");
f96e0b
@@ -511,38 +518,38 @@ setup (const char *dir,
f96e0b
     assert (nsec <= maxsec);
f96e0b
 
f96e0b
     /* Clean out the blocklists.  */
f96e0b
-    block = first_block;
f96e0b
-    while (block->len)
f96e0b
+    bl.block = bl.first_block;
f96e0b
+    while (bl.block->len)
f96e0b
       {
f96e0b
-	grub_memset (block, 0, sizeof (block));
f96e0b
+	grub_memset (bl.block, 0, sizeof (bl.block));
f96e0b
       
f96e0b
-	block--;
f96e0b
+	bl.block--;
f96e0b
 
f96e0b
-	if ((char *) block <= core_img)
f96e0b
+	if ((char *) bl.block <= core_img)
f96e0b
 	  grub_util_error ("%s", _("no terminator in the core image"));
f96e0b
       }
f96e0b
 
f96e0b
     save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
f96e0b
-		       0, GRUB_DISK_SECTOR_SIZE);
f96e0b
+		       0, GRUB_DISK_SECTOR_SIZE, &first_sector);
f96e0b
 
f96e0b
-    block = first_block;
f96e0b
+    bl.block = bl.first_block;
f96e0b
     for (i = 1; i < nsec; i++)
f96e0b
       save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
f96e0b
-		       0, GRUB_DISK_SECTOR_SIZE);
f96e0b
+		       0, GRUB_DISK_SECTOR_SIZE, &bl);
f96e0b
 
f96e0b
     /* Make sure that the last blocklist is a terminator.  */
f96e0b
-    if (block == first_block)
f96e0b
-      block--;
f96e0b
-    block->start = 0;
f96e0b
-    block->len = 0;
f96e0b
-    block->segment = 0;
f96e0b
+    if (bl.block == bl.first_block)
f96e0b
+      bl.block--;
f96e0b
+    bl.block->start = 0;
f96e0b
+    bl.block->len = 0;
f96e0b
+    bl.block->segment = 0;
f96e0b
 
f96e0b
     write_rootdev (root_dev, boot_img, first_sector);
f96e0b
 
f96e0b
     core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
f96e0b
-    first_block = (struct grub_boot_blocklist *) (core_img
f96e0b
-						  + GRUB_DISK_SECTOR_SIZE
f96e0b
-						  - sizeof (*block));
f96e0b
+    bl.first_block = (struct grub_boot_blocklist *) (core_img
f96e0b
+						     + GRUB_DISK_SECTOR_SIZE
f96e0b
+						     - sizeof (*bl.block));
f96e0b
 
f96e0b
     grub_size_t no_rs_length;
f96e0b
     grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE
f96e0b
@@ -698,22 +705,22 @@ unable_to_embed:
f96e0b
 #endif
f96e0b
 
f96e0b
   /* Clean out the blocklists.  */
f96e0b
-  block = first_block;
f96e0b
-  while (block->len)
f96e0b
+  bl.block = bl.first_block;
f96e0b
+  while (bl.block->len)
f96e0b
     {
f96e0b
-      block->start = 0;
f96e0b
-      block->len = 0;
f96e0b
+      bl.block->start = 0;
f96e0b
+      bl.block->len = 0;
f96e0b
 #ifdef GRUB_SETUP_BIOS
f96e0b
-      block->segment = 0;
f96e0b
+      bl.block->segment = 0;
f96e0b
 #endif
f96e0b
 
f96e0b
-      block--;
f96e0b
+      bl.block--;
f96e0b
 
f96e0b
-      if ((char *) block <= core_img)
f96e0b
+      if ((char *) bl.block <= core_img)
f96e0b
 	grub_util_error ("%s", _("no terminator in the core image"));
f96e0b
     }
f96e0b
 
f96e0b
-  block = first_block;
f96e0b
+  bl.block = bl.first_block;
f96e0b
 
f96e0b
 #ifdef __linux__
f96e0b
   {
f96e0b
@@ -766,11 +773,11 @@ unable_to_embed:
f96e0b
 		if (i == 0 && j == 0)
f96e0b
 		  save_first_sector (((grub_uint64_t) blk) * mul
f96e0b
 				     + container_start,
f96e0b
-				     0, rest);
f96e0b
+				     0, rest, &first_sector);
f96e0b
 		else
f96e0b
 		  save_blocklists (((grub_uint64_t) blk) * mul + j
f96e0b
 				   + container_start,
f96e0b
-				   0, rest);
f96e0b
+				   0, rest, &bl);
f96e0b
 	      }
f96e0b
 	  }
f96e0b
       }
f96e0b
@@ -806,13 +813,14 @@ unable_to_embed:
f96e0b
 				      >> GRUB_DISK_SECTOR_BITS)
f96e0b
 				     + j + container_start,
f96e0b
 				     fie2->fm_extents[i].fe_physical
f96e0b
-				     & (GRUB_DISK_SECTOR_SIZE - 1), len);
f96e0b
+				     & (GRUB_DISK_SECTOR_SIZE - 1), len,
f96e0b
+				     &first_sector);
f96e0b
 		else
f96e0b
 		  save_blocklists ((fie2->fm_extents[i].fe_physical
f96e0b
 				    >> GRUB_DISK_SECTOR_BITS)
f96e0b
 				   + j + container_start,
f96e0b
 				   fie2->fm_extents[i].fe_physical
f96e0b
-				   & (GRUB_DISK_SECTOR_SIZE - 1), len);
f96e0b
+				   & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl);
f96e0b
 
f96e0b
 
f96e0b
 	      }
f96e0b
@@ -830,12 +838,14 @@ unable_to_embed:
f96e0b
       grub_util_error ("%s", grub_errmsg);
f96e0b
 
f96e0b
     file->read_hook = save_first_sector;
f96e0b
+    file->read_hook_data = &first_sector;
f96e0b
     if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
f96e0b
 	!= GRUB_DISK_SECTOR_SIZE)
f96e0b
       grub_util_error ("%s", _("failed to read the first sector of the core image"));
f96e0b
 
f96e0b
-    block = first_block;
f96e0b
+    bl.block = bl.first_block;
f96e0b
     file->read_hook = save_blocklists;
f96e0b
+    file->read_hook_data = &bl;
f96e0b
     if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
f96e0b
 	!= (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
f96e0b
       grub_util_error ("%s", _("failed to read the rest sectors of the core image"));
f96e0b
@@ -913,11 +923,11 @@ unable_to_embed:
f96e0b
     ptr += GRUB_DISK_SECTOR_SIZE;
f96e0b
     len -= GRUB_DISK_SECTOR_SIZE;
f96e0b
 
f96e0b
-    block = first_block;
f96e0b
-    while (block->len)
f96e0b
+    bl.block = bl.first_block;
f96e0b
+    while (bl.block->len)
f96e0b
       {
f96e0b
-	size_t cur = grub_target_to_host16 (block->len) << GRUB_DISK_SECTOR_BITS;
f96e0b
-	blk = grub_target_to_host64 (block->start);
f96e0b
+	size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS;
f96e0b
+	blk = grub_target_to_host64 (bl.block->start);
f96e0b
 
f96e0b
 	if (cur > len)
f96e0b
 	  cur = len;
f96e0b
@@ -932,9 +942,9 @@ unable_to_embed:
f96e0b
 
f96e0b
 	ptr += cur;
f96e0b
 	len -= cur;
f96e0b
-	block--;
f96e0b
+	bl.block--;
f96e0b
 	
f96e0b
-	if ((char *) block <= core_img)
f96e0b
+	if ((char *) bl.block <= core_img)
f96e0b
 	  grub_util_error ("%s", _("no terminator in the core image"));
f96e0b
       }
f96e0b
     core_dev->disk->partition = container;
f96e0b
-- 
f96e0b
1.8.2.1
f96e0b