* include/grub/disk.h (grub_disk_read_hook_t): New type.
(struct grub_disk): Add read_hook_data member.
* include/grub/file.h (struct grub_file): Likewise.
* include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data
argument.
Update all callers.
+2013-02-27 Colin Watson <cjwatson@ubuntu.com>
+
+ Remove nested functions from disk and file read hooks.
+
+ * include/grub/disk.h (grub_disk_read_hook_t): New type.
+ (struct grub_disk): Add read_hook_data member.
+ * include/grub/file.h (struct grub_file): Likewise.
+ * include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data
+ argument.
+
+ Update all callers.
+
2012-02-27 Andrey Borzenkov <arvidjaar@gmail.com>
* grub-core/partmap/msdos.c (grub_partition_msdos_iterate):
#if defined(__PPC__) && !defined(__powerpc__)
#define __powerpc__ 1
#endif
+
+/* Define to 1 to enable disk cache statistics. */
+#define DISK_CACHE_STATS @DISK_CACHE_STATS@
+
#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE)
#include <config-util.h>
#define NESTED_FUNC_ATTR
#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@
/* Define to 1 if GCC generates calls to __register_frame_info(). */
#define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@
-/* Define to 1 to enable disk cache statistics. */
-#define DISK_CACHE_STATS @DISK_CACHE_STATS@
#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@"
#define GRUB_PLATFORM "@GRUB_PLATFORM@"
GRUB_MOD_LICENSE ("GPLv3+");
-static grub_err_t
-grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
- int argc, char **args)
+/* Context for grub_cmd_blocklist. */
+struct blocklist_ctx
{
- grub_file_t file;
- char buf[GRUB_DISK_SECTOR_SIZE];
- unsigned long start_sector = 0;
- unsigned num_sectors = 0;
- int num_entries = 0;
- grub_disk_addr_t part_start = 0;
- auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
- unsigned length);
- auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
- unsigned offset, unsigned length);
-
- void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
- unsigned length)
+ unsigned long start_sector;
+ unsigned num_sectors;
+ int num_entries;
+ grub_disk_addr_t part_start;
+};
+
+/* Helper for grub_cmd_blocklist. */
+static void
+print_blocklist (grub_disk_addr_t sector, unsigned num,
+ unsigned offset, unsigned length, struct blocklist_ctx *ctx)
+{
+ if (ctx->num_entries++)
+ grub_printf (",");
+
+ grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start));
+ if (num > 0)
+ grub_printf ("+%u", num);
+ if (offset != 0 || length != 0)
+ grub_printf ("[%u-%u]", offset, offset + length);
+}
+
+/* Helper for grub_cmd_blocklist. */
+static void
+read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ struct blocklist_ctx *ctx = data;
+
+ if (ctx->num_sectors > 0)
{
- if (num_sectors > 0)
+ if (ctx->start_sector + ctx->num_sectors == sector
+ && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
{
- if (start_sector + num_sectors == sector
- && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
- {
- num_sectors++;
- return;
- }
-
- print_blocklist (start_sector, num_sectors, 0, 0);
- num_sectors = 0;
+ ctx->num_sectors++;
+ return;
}
- if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
- {
- start_sector = sector;
- num_sectors++;
- }
- else
- print_blocklist (sector, 0, offset, length);
+ print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
+ ctx->num_sectors = 0;
}
- void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
- unsigned offset, unsigned length)
+ if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
{
- if (num_entries++)
- grub_printf (",");
-
- grub_printf ("%llu", (unsigned long long) (sector - part_start));
- if (num > 0)
- grub_printf ("+%u", num);
- if (offset != 0 || length != 0)
- grub_printf ("[%u-%u]", offset, offset + length);
+ ctx->start_sector = sector;
+ ctx->num_sectors++;
}
+ else
+ print_blocklist (sector, 0, offset, length, ctx);
+}
+
+static grub_err_t
+grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_file_t file;
+ char buf[GRUB_DISK_SECTOR_SIZE];
+ struct blocklist_ctx ctx = {
+ .start_sector = 0,
+ .num_sectors = 0,
+ .num_entries = 0,
+ .part_start = 0
+ };
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
return grub_error (GRUB_ERR_BAD_DEVICE,
"this command is available only for disk devices");
- part_start = grub_partition_get_start (file->device->disk->partition);
+ ctx.part_start = grub_partition_get_start (file->device->disk->partition);
file->read_hook = read_blocklist;
+ file->read_hook_data = &ctx;
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
- if (num_sectors > 0)
- print_blocklist (start_sector, num_sectors, 0, 0);
+ if (ctx.num_sectors > 0)
+ print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx);
grub_file_close (file);
return 1;
}
+/* Context for grub_cmd_save_env. */
+struct grub_cmd_save_env_ctx
+{
+ struct blocklist *head, *tail;
+};
+
+/* Store blocklists in a linked list. */
+static void
+save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ struct grub_cmd_save_env_ctx *ctx = data;
+ struct blocklist *block;
+
+ if (offset + length > GRUB_DISK_SECTOR_SIZE)
+ /* Seemingly a bug. */
+ return;
+
+ block = grub_malloc (sizeof (*block));
+ if (! block)
+ return;
+
+ block->sector = sector;
+ block->offset = offset;
+ block->length = length;
+
+ /* Slightly complicated, because the list should be FIFO. */
+ block->next = 0;
+ if (ctx->tail)
+ ctx->tail->next = block;
+ ctx->tail = block;
+ if (! ctx->head)
+ ctx->head = block;
+}
+
static grub_err_t
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
- struct blocklist *head = 0;
- struct blocklist *tail = 0;
-
- /* Store blocklists in a linked list. */
- auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length);
- void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
- unsigned offset, unsigned length)
- {
- struct blocklist *block;
-
- if (offset + length > GRUB_DISK_SECTOR_SIZE)
- /* Seemingly a bug. */
- return;
-
- block = grub_malloc (sizeof (*block));
- if (! block)
- return;
-
- block->sector = sector;
- block->offset = offset;
- block->length = length;
-
- /* Slightly complicated, because the list should be FIFO. */
- block->next = 0;
- if (tail)
- tail->next = block;
- tail = block;
- if (! head)
- head = block;
- }
+ struct grub_cmd_save_env_ctx ctx = {
+ .head = 0,
+ .tail = 0
+ };
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
}
- file->read_hook = read_hook;
+ file->read_hook = save_env_read_hook;
+ file->read_hook_data = &ctx;
envblk = read_envblk_file (file);
file->read_hook = 0;
if (! envblk)
goto fail;
- if (check_blocklists (envblk, head, file))
+ if (check_blocklists (envblk, ctx.head, file))
goto fail;
while (argc)
args++;
}
- write_blocklists (envblk, head, file);
+ write_blocklists (envblk, ctx.head, file);
fail:
if (envblk)
grub_envblk_close (envblk);
- free_blocklists (head);
+ free_blocklists (ctx.head);
grub_file_close (file);
return grub_errno;
}
GRUB_MOD_LICENSE ("GPLv3+");
+/* Helper for grub_cmd_testload. */
+static void
+read_progress (grub_disk_addr_t sector __attribute__ ((unused)),
+ unsigned offset __attribute__ ((unused)),
+ unsigned len __attribute__ ((unused)),
+ void *data __attribute__ ((unused)))
+{
+ grub_xputs (".");
+ grub_refresh ();
+}
+
static grub_err_t
grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
char *buf;
grub_size_t size;
grub_off_t pos;
- auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len);
-
- void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)),
- unsigned offset __attribute__ ((unused)),
- unsigned len __attribute__ ((unused)))
- {
- grub_xputs (".");
- grub_refresh ();
- }
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
grub_printf ("Reading %s sequentially", argv[0]);
- file->read_hook = read_func;
+ file->read_hook = read_progress;
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
goto fail;
grub_printf (" Done.\n");
(struct grub_affs_data *) file->data;
return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
- file->read_hook,
+ file->read_hook, file->read_hook_data,
file->offset, len, buf, grub_affs_read_block,
grub_be_to_cpu32 (data->diropen.di.size),
data->log_blocksize, 0);
const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino,
grub_off_t off, void *buf, grub_size_t len,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length))
+ grub_disk_read_hook_t read_hook, void *read_hook_data)
{
if (len == 0)
return GRUB_ERR_NONE;
if (read_size > len)
read_size = len;
disk->read_hook = read_hook;
+ disk->read_hook_data = read_hook_data;
err = read_extent (disk, sb, &ino->direct[i], 0, off - pos,
buf, read_size);
disk->read_hook = 0;
if (read_size > len)
read_size = len;
disk->read_hook = read_hook;
+ disk->read_hook_data = read_hook_data;
err = read_extent (disk, sb, &entries[i], 0, off - pos,
buf, read_size);
disk->read_hook = 0;
if (read_size > len)
read_size = len;
disk->read_hook = read_hook;
+ disk->read_hook_data = read_hook_data;
err = read_extent (disk, sb, &l2_entries[l2n], 0, boff,
buf, read_size);
disk->read_hook = 0;
int level;
grub_uint64_t node_off;
- err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
+ err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
if (err)
return 0;
node_off = grub_bfs_to_cpu64 (head.root);
{
struct grub_bfs_btree_node node;
grub_uint64_t key_value;
- err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+ err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+ 0, 0);
if (err)
return 0;
err = read_bfs_file (disk, sb, ino, node_off
BTREE_ALIGN) +
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), &key_value,
- sizeof (grub_uint64_t), 0);
+ sizeof (grub_uint64_t), 0, 0);
if (err)
return 0;
while (1)
{
struct grub_bfs_btree_node node;
- err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+ err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+ 0, 0);
if (err)
return 0;
{
err =
read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
- grub_bfs_to_cpu_treehead (node.total_key_len), 0);
+ grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
if (err)
return 0;
key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
(node.total_key_len), BTREE_ALIGN),
keylen_idx,
grub_bfs_to_cpu_treehead (node.count_keys) *
- sizeof (grub_uint16_t), 0);
+ sizeof (grub_uint16_t), 0, 0);
if (err)
return 0;
err = read_bfs_file (disk, sb, ino, node_off
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), key_values,
grub_bfs_to_cpu_treehead (node.count_keys) *
- sizeof (grub_uint64_t), 0);
+ sizeof (grub_uint64_t), 0, 0);
if (err)
return 0;
int level;
grub_uint64_t node_off;
- err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
+ err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
if (err)
return err;
node_off = grub_bfs_to_cpu64 (head.root);
while (1)
{
struct grub_bfs_btree_node node;
- err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+ err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+ 0, 0);
if (err)
return err;
if (node.count_keys == 0)
unsigned i;
err =
read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
- grub_bfs_to_cpu_treehead (node.total_key_len), 0);
+ grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
if (err)
return err;
key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
total_key_len),
BTREE_ALIGN), keylen_idx,
grub_bfs_to_cpu_treehead (node.count_keys) *
- sizeof (grub_uint16_t), 0);
+ sizeof (grub_uint16_t), 0, 0);
if (err)
return err;
err = read_bfs_file (disk, sb, ino, node_off
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), key_values,
grub_bfs_to_cpu_treehead (node.count_keys) *
- sizeof (grub_uint64_t), 0);
+ sizeof (grub_uint64_t), 0, 0);
if (err)
return err;
return grub_errno;
}
grub_free (old_alloc);
- err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0);
+ err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0);
if (err)
{
grub_free (alloc);
struct grub_bfs_data *data = file->data;
err = read_bfs_file (file->device->disk, &data->sb,
- data->ino, file->offset, buf, len, file->read_hook);
+ data->ino, file->offset, buf, len,
+ file->read_hook, file->read_hook_data);
if (err)
return -1;
return len;
if (read > len)
read = len;
- err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0);
+ err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0, 0);
if (err)
return -1;
return read;
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_ext2_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
pos, len, buf, grub_ext2_read_block,
grub_cpu_to_le32 (node->inode.size)
| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
grub_le_to_cpu32 (diro->inode.size));
else
{
- grub_ext2_read_file (diro, 0, 0,
+ grub_ext2_read_file (diro, 0, 0, 0,
grub_le_to_cpu32 (diro->inode.size),
symlink);
if (grub_errno)
{
struct ext2_dirent dirent;
- grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
+ grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent),
(char *) &dirent);
if (grub_errno)
return 0;
struct grub_fshelp_node *fdiro;
enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
- grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
+ grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent),
dirent.namelen, filename);
if (grub_errno)
return 0;
{
struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
- return grub_ext2_read_file (&data->diropen, file->read_hook,
+ return grub_ext2_read_file (&data->diropen,
+ file->read_hook, file->read_hook_data,
file->offset, len, buf);
}
static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t offset, grub_size_t len, char *buf)
{
grub_size_t size;
size = len;
disk->read_hook = read_hook;
+ disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector, offset, size, buf);
disk->read_hook = 0;
if (grub_errno)
ctxt->offset += sizeof (dir);
- if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (dir),
+ if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir),
(char *) &dir)
!= sizeof (dir))
break;
{
struct grub_fat_dir_entry sec;
ctxt->offset += sizeof (sec);
- if (grub_fat_read_data (disk, data, 0,
+ if (grub_fat_read_data (disk, data, 0, 0,
ctxt->offset, sizeof (sec), (char *) &sec)
!= sizeof (sec))
break;
ctxt->offset += sizeof (ctxt->dir);
/* Read a directory entry. */
- if (grub_fat_read_data (disk, data, 0,
+ if (grub_fat_read_data (disk, data, 0, 0,
ctxt->offset, sizeof (ctxt->dir),
(char *) &ctxt->dir)
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
static grub_ssize_t
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
{
- return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
+ return grub_fat_read_data (file->device->disk, file->data,
+ file->read_hook, file->read_hook_data,
file->offset, len, buf);
}
{
offset += sizeof (dir);
- if (grub_fat_read_data (disk, data, 0,
+ if (grub_fat_read_data (disk, data, 0, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
beginning with the block POS. READ_HOOK should be set before
- reading a block from the file. GET_BLOCK is used to translate file
- blocks to disk blocks. The file is FILESIZE bytes big and the
+ reading a block from the file. READ_HOOK_DATA is passed through as
+ the DATA argument to READ_HOOK. GET_BLOCK is used to translate
+ file blocks to disk blocks. The file is FILESIZE bytes big and the
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
if (blknr)
{
disk->read_hook = read_hook;
+ disk->read_hook_data = read_hook_data;
grub_disk_read (disk, blknr + blocks_start, skipfirst,
blockend, buf);
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_hfs_read_file (struct grub_hfs_data *data,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
grub_off_t i;
if (blknr)
{
data->disk->read_hook = read_hook;
+ data->disk->read_hook_data = read_hook_data;
grub_disk_read (data->disk, blknr, skipfirst,
blockend, buf);
data->disk->read_hook = 0;
struct grub_hfs_data *data =
(struct grub_hfs_data *) file->data;
- return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf);
+ return grub_hfs_read_file (data, file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_hfsplus_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
pos, len, buf, grub_hfsplus_read_block,
node->size,
node->data->log2blksize - GRUB_DISK_SECTOR_BITS,
grub_be_to_cpu64 (data->volheader.extents_file.size);
/* Read the essential information about the trees. */
- if (grub_hfsplus_read_file (&data->catalog_tree.file, 0,
+ if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, 0,
sizeof (struct grub_hfsplus_btnode),
sizeof (header), (char *) &header) <= 0)
goto fail;
data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) &&
(header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE));
- if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0,
+ if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
sizeof (struct grub_hfsplus_btnode),
sizeof (header), (char *) &header) <= 0)
goto fail;
data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
- if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
+ if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, 0,
sizeof (node), (char *) &node) <= 0)
goto fail;
if (!symlink)
return 0;
- numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink);
+ numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink);
if (numread != (grub_ssize_t) node->size)
{
grub_free (symlink);
saved_node = first_node->next;
node_count++;
- if (grub_hfsplus_read_file (&btree->file, 0,
+ if (grub_hfsplus_read_file (&btree->file, 0, 0,
(((grub_disk_addr_t)
grub_be_to_cpu32 (first_node->next))
* btree->nodesize),
node_count++;
/* Read a node. */
- if (grub_hfsplus_read_file (&btree->file, 0,
+ if (grub_hfsplus_read_file (&btree->file, 0, 0,
(grub_disk_addr_t) currnode
* (grub_disk_addr_t) btree->nodesize,
btree->nodesize, (char *) node) <= 0)
struct grub_hfsplus_data *data =
(struct grub_hfsplus_data *) file->data;
- return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
- file->offset, len, buf);
+ return grub_hfsplus_read_file (&data->opened_file,
+ file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
/* Context for grub_hfsplus_dir. */
/* XXX: The file is stored in as a single extent. */
data->disk->read_hook = file->read_hook;
+ data->disk->read_hook_data = file->read_hook_data;
read_node (data->node, file->offset, len, buf);
data->disk->read_hook = NULL;
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_jfs_read_file (struct grub_jfs_data *data,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
grub_off_t i;
}
data->disk->read_hook = read_hook;
+ data->disk->read_hook_data = read_hook_data;
grub_disk_read (data->disk,
blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS),
if (size <= sizeof (data->currinode.symlink.path))
grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
- else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
+ else if (grub_jfs_read_file (data, 0, 0, 0, size, symlink) < 0)
return grub_errno;
symlink[size] = '\0';
struct grub_jfs_data *data =
(struct grub_jfs_data *) file->data;
- return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf);
+ return grub_jfs_read_file (data, file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_minix_read_file (struct grub_minix_data *data,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
grub_uint32_t i;
}
data->disk->read_hook = read_hook;
+ data->disk->read_hook_data = read_hook_data;
grub_disk_read (data->disk,
GRUB_MINIX_ZONE2SECT(blknr),
skipfirst, blockend, buf);
if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
- if (grub_minix_read_file (data, 0, 0,
+ if (grub_minix_read_file (data, 0, 0, 0,
GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
return grub_errno;
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
- if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+ if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
(char *) &ino) < 0)
return grub_errno;
- if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+ if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
data->filename_size, (char *) filename)< 0)
return grub_errno;
grub_memset (&info, 0, sizeof (info));
- if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+ if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
(char *) &ino) < 0)
return grub_errno;
- if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+ if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
data->filename_size,
(char *) filename) < 0)
return grub_errno;
struct grub_minix_data *data =
(struct grub_minix_data *) file->data;
- return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
+ return grub_minix_read_file (data, file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_nilfs2_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
- sector,
- unsigned offset,
- unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
pos, len, buf, grub_nilfs2_read_block,
grub_le_to_cpu64 (node->inode.i_size),
LOG2_NILFS2_BLOCK_SIZE (node->data), 0);
if (!symlink)
return 0;
- grub_nilfs2_read_file (diro, 0, 0,
+ grub_nilfs2_read_file (diro, 0, 0, 0,
grub_le_to_cpu64 (diro->inode.i_size), symlink);
if (grub_errno)
{
{
struct grub_nilfs2_dir_entry dirent;
- grub_nilfs2_read_file (diro, 0, fpos,
+ grub_nilfs2_read_file (diro, 0, 0, fpos,
sizeof (struct grub_nilfs2_dir_entry),
(char *) &dirent);
if (grub_errno)
struct grub_fshelp_node *fdiro;
enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
- grub_nilfs2_read_file (diro, 0,
+ grub_nilfs2_read_file (diro, 0, 0,
fpos + sizeof (struct grub_nilfs2_dir_entry),
dirent.name_len, filename);
if (grub_errno)
{
struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data;
- return grub_nilfs2_read_file (&data->diropen, file->read_hook,
+ return grub_nilfs2_read_file (&data->diropen,
+ file->read_hook, file->read_hook_data,
file->offset, len, buf);
}
static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest,
grub_disk_addr_t ofs, grub_size_t len,
int cached,
- void
- NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
- sector,
- unsigned offset,
- unsigned length));
+ grub_disk_read_hook_t read_hook,
+ void *read_hook_data);
static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
grub_uint8_t *dest,
grub_disk_addr_t ofs, grub_size_t len,
int cached,
- void
- NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
- sector,
- unsigned offset,
- unsigned length));
+ grub_disk_read_hook_t read_hook,
+ void *read_hook_data);
static void
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
at->edat_buf = grub_malloc (n);
if (!at->edat_buf)
return NULL;
- if (read_data (at, pa, at->edat_buf, 0, n, 0, 0))
+ if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
{
grub_error (GRUB_ERR_BAD_FS,
"fail to read non-resident attribute list");
if (read_attr
(at, pa + 0x10,
u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
- at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
+ at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
return NULL;
pa += u16at (pa, 4);
}
{
if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
{
- void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length);
+ grub_disk_read_hook_t save_hook;
save_hook = ctx->comp.disk->read_hook;
ctx->comp.disk->read_hook = 0;
static grub_err_t
read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
grub_disk_addr_t ofs, grub_size_t len, int cached,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length))
+ grub_disk_read_hook_t read_hook, void *read_hook_data)
{
grub_disk_addr_t vcn;
struct grub_ntfs_rlst cc, *ctx;
if (!(ctx->flags & GRUB_NTFS_RF_COMP))
{
grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
- read_hook, ofs, len, (char *) dest,
+ read_hook, read_hook_data, ofs, len,
+ (char *) dest,
grub_ntfs_read_block, ofs + len,
ctx->comp.log_spc, 0);
return grub_errno;
static grub_err_t
read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
grub_size_t len, int cached,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length))
+ grub_disk_read_hook_t read_hook, void *read_hook_data)
{
grub_uint8_t *save_cur;
grub_uint8_t attr;
}
pp = find_attr (at, attr);
if (pp)
- ret = read_data (at, pp, dest, ofs, len, cached, read_hook);
+ ret = read_data (at, pp, dest, ofs, len, cached,
+ read_hook, read_hook_data);
else
ret =
(grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
{
if (read_attr
(&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
- data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
+ data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno);
return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE");
}
}
err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0,
- sizeof (struct symlink_descriptor), 1, 0);
+ sizeof (struct symlink_descriptor), 1, 0, 0);
if (err)
return NULL;
if (!buf16)
return NULL;
- err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0);
+ err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0, 0);
if (err)
return NULL;
}
else
{
- if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0))
+ if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
{
grub_error (GRUB_ERR_BAD_FS,
"fails to read non-resident $BITMAP");
{
if ((read_attr
(at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
- (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0))
+ (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0))
|| (fixup (indx, mft->data->idx_size,
(const grub_uint8_t *) "INDX")))
goto done;
mft->attr.save_pos = 1;
read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1,
- file->read_hook);
+ file->read_hook, file->read_hook_data);
return (grub_errno) ? -1 : (grub_ssize_t) len;
}
ret = 0;
//ctx->comp.disk->read_hook = read_hook;
+ //ctx->comp.disk->read_hook_data = read_hook_data;
if ((vcn > ctx->target_vcn) &&
(read_block
static grub_ssize_t
grub_reiserfs_read_real (struct grub_fshelp_node *node,
grub_off_t off, char *buf, grub_size_t len,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length));
+ grub_disk_read_hook_t read_hook,
+ void *read_hook_data);
/* Internal-only functions. Not to be used outside of this file. */
if (! symlink_buffer)
return 0;
- ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0);
+ ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0);
if (ret < 0)
{
grub_free (symlink_buffer);
static grub_ssize_t
grub_reiserfs_read_real (struct grub_fshelp_node *node,
grub_off_t off, char *buf, grub_size_t len,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length))
+ grub_disk_read_hook_t read_hook, void *read_hook_data)
{
unsigned int indirect_block, indirect_block_count;
struct grub_reiserfs_key key;
(unsigned) block, (unsigned) offset,
(unsigned) (offset + length));
found.data->disk->read_hook = read_hook;
+ found.data->disk->read_hook_data = read_hook_data;
grub_disk_read (found.data->disk,
block,
offset
if (grub_errno)
goto fail;
found.data->disk->read_hook = read_hook;
+ found.data->disk->read_hook_data = read_hook_data;
for (indirect_block = 0;
indirect_block < indirect_block_count
&& current_position < final_position;
grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
{
return grub_reiserfs_read_real (file->data, file->offset, buf, len,
- file->read_hook);
+ file->read_hook, file->read_hook_data);
}
/* Close the file FILE. */
/* XXX: The file is stored in as a single extent. */
data->data->disk->read_hook = file->read_hook;
+ data->data->disk->read_hook_data = file->read_hook_data;
grub_disk_read (data->data->disk,
(data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS,
(data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1),
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_sfs_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
pos, len, buf, grub_sfs_read_block,
node->size, node->data->log_blocksize, 0);
}
{
struct grub_sfs_data *data = (struct grub_sfs_data *) file->data;
- return grub_sfs_read_file (&data->diropen, file->read_hook,
+ return grub_sfs_read_file (&data->diropen,
+ file->read_hook, file->read_hook_data,
file->offset, len, buf);
}
static grub_ssize_t
grub_udf_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR
- (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
return 0;
}
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
- pos, len, buf, grub_udf_read_block,
- U64 (node->block.fe.file_size),
- node->data->lbshift, 0);
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
+ pos, len, buf, grub_udf_read_block,
+ U64 (node->block.fe.file_size),
+ node->data->lbshift, 0);
}
static unsigned sblocklist[] = { 256, 512, 0 };
while (offset < U64 (dir->block.fe.file_size))
{
- if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
+ if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent),
(char *) &dirent) != sizeof (dirent))
return 0;
if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
- if ((grub_udf_read_file (dir, 0, offset,
+ if ((grub_udf_read_file (dir, 0, 0, offset,
dirent.file_ident_length,
(char *) raw))
!= dirent.file_ident_length)
raw = grub_malloc (sz);
if (!raw)
return NULL;
- if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0)
+ if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0)
{
grub_free (raw);
return NULL;
{
struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data;
- return grub_udf_read_file (node, file->read_hook, file->offset, len, buf);
+ return grub_udf_read_file (node, file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
static grub_err_t
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_ufs_read_file (struct grub_ufs_data *data,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
struct grub_ufs_sblock *sblock = &data->sblock;
if (blknr)
{
data->disk->read_hook = read_hook;
+ data->disk->read_hook_data = read_hook_data;
grub_disk_read (data->disk,
blknr << grub_ufs_to_cpu32 (data->sblock.log2_blksz),
skipfirst, blockend, buf);
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
grub_strcpy (symlink, (char *) data->inode.symlink);
else
- grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink);
+ grub_ufs_read_file (data, 0, 0, 0, INODE_SIZE (data), symlink);
symlink[INODE_SIZE (data)] = '\0';
/* The symlink is an absolute path, go back to the root inode. */
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
- if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+ if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
(char *) &dirent) < 0)
return grub_errno;
{
char filename[namelen + 1];
- if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+ if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
namelen, filename) < 0)
return grub_errno;
struct grub_ufs_dirent dirent;
int namelen;
- if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+ if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
(char *) &dirent) < 0)
break;
grub_memset (&info, 0, sizeof (info));
- if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+ if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
namelen, filename) < 0)
break;
struct grub_ufs_data *data =
(struct grub_ufs_data *) file->data;
- return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf);
+ return grub_ufs_read_file (data, file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_xfs_read_file (grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length),
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf)
{
- return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
pos, len, buf, grub_xfs_read_block,
grub_be_to_cpu64 (node->inode.size),
node->data->sblock.log2_bsize
if (!symlink)
return 0;
- numread = grub_xfs_read_file (node, 0, 0, size, symlink);
+ numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink);
if (numread != size)
{
grub_free (symlink);
struct grub_xfs_dirblock_tail *tail;
tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
- numread = grub_xfs_read_file (dir, 0,
+ numread = grub_xfs_read_file (dir, 0, 0,
blk << dirblk_log2,
dirblk_size, dirblock);
if (numread != dirblk_size)
struct grub_xfs_data *data =
(struct grub_xfs_data *) file->data;
- return grub_xfs_read_file (&data->diropen, file->read_hook,
- file->offset, len, buf);
+ return grub_xfs_read_file (&data->diropen,
+ file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
}
cl = GRUB_DISK_SECTOR_SIZE - o;
if (cl > l)
cl = l;
- (disk->read_hook) (s, o, cl);
+ (disk->read_hook) (s, o, cl, disk->read_hook_data);
s++;
l -= cl;
o = 0;
#ifndef GRUB_DISK_HEADER
#define GRUB_DISK_HEADER 1
+#include <config.h>
+
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
struct grub_partition;
+typedef void (*grub_disk_read_hook_t) (grub_disk_addr_t sector,
+ unsigned offset, unsigned length,
+ void *data);
+
/* Disk. */
struct grub_disk
{
/* Called when a sector was read. OFFSET is between 0 and
the sector size minus 1, and LENGTH is between 0 and the sector size. */
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length);
+ grub_disk_read_hook_t read_hook;
+
+ /* Caller-specific data passed to the read hook. */
+ void *read_hook_data;
/* Device-specific data. */
void *data;
#include <grub/err.h>
#include <grub/device.h>
#include <grub/fs.h>
+#include <grub/disk.h>
/* File description. */
struct grub_file
void *data;
/* This is called when a sector is read. Used only for a disk device. */
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset, unsigned length);
+ grub_disk_read_hook_t read_hook;
+
+ /* Caller-specific data passed to the read hook. */
+ void *read_hook_data;
};
typedef struct grub_file *grub_file_t;
#include <grub/types.h>
#include <grub/symbol.h>
#include <grub/err.h>
+#include <grub/disk.h>
typedef struct grub_fshelp_node *grub_fshelp_node_t;
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
- void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length),
+ grub_disk_read_hook_t read_hook,
+ void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
#define BOOT_SECTOR 0
#endif
+/* Helper for setup. */
+static void
+save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ grub_disk_addr_t *first_sector = data;
+ grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
+ sector, offset, length);
+
+ if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
+
+ *first_sector = sector;
+}
+
+struct blocklists
+{
+ struct grub_boot_blocklist *first_block, *block;
+#ifdef GRUB_SETUP_BIOS
+ grub_uint16_t current_segment;
+#endif
+ grub_uint16_t last_length;
+};
+
+/* Helper for setup. */
+static void
+save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ struct blocklists *bl = data;
+ struct grub_boot_blocklist *prev = bl->block + 1;
+
+ grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
+ sector, offset, length);
+
+ if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
+
+ if (bl->block != bl->first_block
+ && (grub_target_to_host64 (prev->start)
+ + grub_target_to_host16 (prev->len)) == sector)
+ {
+ grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
+ prev->len = grub_host_to_target16 (t);
+ }
+ else
+ {
+ bl->block->start = grub_host_to_target64 (sector);
+ bl->block->len = grub_host_to_target16 (1);
+#ifdef GRUB_SETUP_BIOS
+ bl->block->segment = grub_host_to_target16 (bl->current_segment);
+#endif
+
+ bl->block--;
+ if (bl->block->len)
+ grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
+ }
+
+ bl->last_length = length;
+#ifdef GRUB_SETUP_BIOS
+ bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+#endif
+}
+
#ifdef GRUB_SETUP_BIOS
/* Context for setup/identify_partmap. */
struct identify_partmap_ctx
int multiple_partmaps;
};
-/* Helper for setup/identify_partmap.
+/* Helper for setup.
Unlike root_dev, with dest_dev we're interested in the partition map even
if dest_dev itself is a whole disk. */
static int
grub_uint16_t core_sectors;
#endif
grub_device_t root_dev = 0, dest_dev, core_dev;
- struct grub_boot_blocklist *first_block, *block;
+ struct blocklists bl;
char *tmp_img;
grub_disk_addr_t first_sector;
-#ifdef GRUB_SETUP_BIOS
- grub_uint16_t current_segment
- = GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
-#endif
- grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
FILE *fp;
- auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length);
- auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length);
-
- void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length)
- {
- grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
- sector, offset, length);
-
- if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
- grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
-
- first_sector = sector;
- }
-
- void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
- unsigned offset,
- unsigned length)
- {
- struct grub_boot_blocklist *prev = block + 1;
-
- grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
- sector, offset, length);
-
- if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
- grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
-
- if (block != first_block
- && (grub_target_to_host64 (prev->start)
- + grub_target_to_host16 (prev->len)) == sector)
- {
- grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
- prev->len = grub_host_to_target16 (t);
- }
- else
- {
- block->start = grub_host_to_target64 (sector);
- block->len = grub_host_to_target16 (1);
#ifdef GRUB_SETUP_BIOS
- block->segment = grub_host_to_target16 (current_segment);
+ bl.current_segment =
+ GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
#endif
-
- block--;
- if (block->len)
- grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
- }
-
- last_length = length;
-#ifdef GRUB_SETUP_BIOS
- current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
-#endif
- }
+ bl.last_length = GRUB_DISK_SECTOR_SIZE;
/* Read the boot image by the OS service. */
boot_path = grub_util_get_path (dir, boot_file);
core_img = grub_util_read_image (core_path);
/* Have FIRST_BLOCK to point to the first blocklist. */
- first_block = (struct grub_boot_blocklist *) (core_img
- + GRUB_DISK_SECTOR_SIZE
- - sizeof (*block));
+ bl.first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*bl.block));
grub_util_info ("root is `%s', dest is `%s'", root, dest);
grub_util_info ("Opening dest");
assert (nsec <= maxsec);
/* Clean out the blocklists. */
- block = first_block;
- while (block->len)
+ bl.block = bl.first_block;
+ while (bl.block->len)
{
- grub_memset (block, 0, sizeof (block));
+ grub_memset (bl.block, 0, sizeof (bl.block));
- block--;
+ bl.block--;
- if ((char *) block <= core_img)
+ if ((char *) bl.block <= core_img)
grub_util_error ("%s", _("no terminator in the core image"));
}
save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
- 0, GRUB_DISK_SECTOR_SIZE);
+ 0, GRUB_DISK_SECTOR_SIZE, &first_sector);
- block = first_block;
+ bl.block = bl.first_block;
for (i = 1; i < nsec; i++)
save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
- 0, GRUB_DISK_SECTOR_SIZE);
+ 0, GRUB_DISK_SECTOR_SIZE, &bl);
/* Make sure that the last blocklist is a terminator. */
- if (block == first_block)
- block--;
- block->start = 0;
- block->len = 0;
- block->segment = 0;
+ if (bl.block == bl.first_block)
+ bl.block--;
+ bl.block->start = 0;
+ bl.block->len = 0;
+ bl.block->segment = 0;
write_rootdev (root_dev, boot_img, first_sector);
core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
- first_block = (struct grub_boot_blocklist *) (core_img
- + GRUB_DISK_SECTOR_SIZE
- - sizeof (*block));
+ bl.first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*bl.block));
grub_size_t no_rs_length;
grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE
#endif
/* Clean out the blocklists. */
- block = first_block;
- while (block->len)
+ bl.block = bl.first_block;
+ while (bl.block->len)
{
- block->start = 0;
- block->len = 0;
+ bl.block->start = 0;
+ bl.block->len = 0;
#ifdef GRUB_SETUP_BIOS
- block->segment = 0;
+ bl.block->segment = 0;
#endif
- block--;
+ bl.block--;
- if ((char *) block <= core_img)
+ if ((char *) bl.block <= core_img)
grub_util_error ("%s", _("no terminator in the core image"));
}
- block = first_block;
+ bl.block = bl.first_block;
#ifdef __linux__
{
if (i == 0 && j == 0)
save_first_sector (((grub_uint64_t) blk) * mul
+ container_start,
- 0, rest);
+ 0, rest, &first_sector);
else
save_blocklists (((grub_uint64_t) blk) * mul + j
+ container_start,
- 0, rest);
+ 0, rest, &bl);
}
}
}
>> GRUB_DISK_SECTOR_BITS)
+ j + container_start,
fie2->fm_extents[i].fe_physical
- & (GRUB_DISK_SECTOR_SIZE - 1), len);
+ & (GRUB_DISK_SECTOR_SIZE - 1), len,
+ &first_sector);
else
save_blocklists ((fie2->fm_extents[i].fe_physical
>> GRUB_DISK_SECTOR_BITS)
+ j + container_start,
fie2->fm_extents[i].fe_physical
- & (GRUB_DISK_SECTOR_SIZE - 1), len);
+ & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl);
}
grub_util_error ("%s", grub_errmsg);
file->read_hook = save_first_sector;
+ file->read_hook_data = &first_sector;
if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
grub_util_error ("%s", _("failed to read the first sector of the core image"));
- block = first_block;
+ bl.block = bl.first_block;
file->read_hook = save_blocklists;
+ file->read_hook_data = &bl;
if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
!= (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
grub_util_error ("%s", _("failed to read the rest sectors of the core image"));
ptr += GRUB_DISK_SECTOR_SIZE;
len -= GRUB_DISK_SECTOR_SIZE;
- block = first_block;
- while (block->len)
+ bl.block = bl.first_block;
+ while (bl.block->len)
{
- size_t cur = grub_target_to_host16 (block->len) << GRUB_DISK_SECTOR_BITS;
- blk = grub_target_to_host64 (block->start);
+ size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS;
+ blk = grub_target_to_host64 (bl.block->start);
if (cur > len)
cur = len;
ptr += cur;
len -= cur;
- block--;
+ bl.block--;
- if ((char *) block <= core_img)
+ if ((char *) bl.block <= core_img)
grub_util_error ("%s", _("no terminator in the core image"));
}
core_dev->disk->partition = container;