diff --git a/fs/ext2.c b/fs/ext2.c index ffe9e33..999bd80 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -257,12 +257,11 @@ inline static grub_err_t grub_ext2_blockgroup (struct grub_ext2_data *data, int group, struct grub_ext2_block_group *blkgrp) { - return grub_disk_read (data->disk, - (grub_fshelp_map_block (data->journal, - grub_le_to_cpu32 (data->sblock.first_data_block) + 1) - << LOG2_EXT2_BLOCK_SIZE (data)), - group * sizeof (struct grub_ext2_block_group), - sizeof (struct grub_ext2_block_group), (char *) blkgrp); + return grub_fshelp_read (data->disk, data->journal, + grub_le_to_cpu32 (data->sblock.first_data_block) + 1, + group * sizeof (struct grub_ext2_block_group), + sizeof (struct grub_ext2_block_group), + (char *) blkgrp, LOG2_EXT2_BLOCK_SIZE (data)); } @@ -283,11 +282,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { grub_uint32_t indir[blksz / 4]; - if (grub_disk_read (data->disk, - grub_fshelp_map_block(data->journal, - grub_le_to_cpu32 (inode->blocks.indir_block)) - << log2_blksz, - 0, blksz, (char *) indir)) + if (grub_fshelp_read (data->disk, data->journal, + grub_le_to_cpu32 (inode->blocks.indir_block), + 0, blksz, (char *) indir, log2_blksz)) return grub_errno; blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]); @@ -300,18 +297,14 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + blksz / 4); grub_uint32_t indir[blksz / 4]; - if (grub_disk_read (data->disk, - grub_fshelp_map_block(data->journal, - grub_le_to_cpu32 (inode->blocks.double_indir_block)) - << log2_blksz, - 0, blksz, (char *) indir)) + if (grub_fshelp_read (data->disk, data->journal, + grub_le_to_cpu32 (inode->blocks.double_indir_block), + 0, blksz, (char *) indir, log2_blksz)) return grub_errno; - if (grub_disk_read (data->disk, - grub_fshelp_map_block(data->journal, - grub_le_to_cpu32 (indir[rblock / perblock])) - << log2_blksz, - 0, blksz, (char *) indir)) + if (grub_fshelp_read (data->disk, data->journal, + grub_le_to_cpu32 (indir[rblock / perblock]), + 0, blksz, (char *) indir, log2_blksz)) return grub_errno; @@ -372,12 +365,11 @@ grub_ext2_read_inode (struct grub_ext2_data *data, % inodes_per_block; /* Read the inode. */ - if (grub_disk_read (data->disk, - grub_fshelp_map_block(data->journal, - grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) - << LOG2_EXT2_BLOCK_SIZE (data), - EXT2_INODE_SIZE (data) * blkoff, - sizeof (struct grub_ext2_inode), (char *) inode)) + if (grub_fshelp_read (data->disk, data->journal, + grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno, + EXT2_INODE_SIZE (data) * blkoff, + sizeof (struct grub_ext2_inode), (char *) inode, + LOG2_EXT2_BLOCK_SIZE (data))) return grub_errno; return 0; diff --git a/fs/fshelp.c b/fs/fshelp.c index faec1f7..52131b0 100644 --- a/fs/fshelp.c +++ b/fs/fshelp.c @@ -215,6 +215,45 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, } +/* Read LEN bytes from the block BLOCK on disk DISK into the buffer BUF, + beginning with the block POS. Apply mappings from LOG. The blocks + have a size of LOG2BLOCKSIZE (in log2). */ +grub_err_t grub_fshelp_read (grub_disk_t disk, grub_fshelp_journal_t log, + grub_disk_addr_t block, grub_off_t pos, + grub_size_t len, char *buf, int log2blocksize) +{ + grub_off_t relblk; + + relblk = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); + block += relblk; + pos -= relblk << (log2blocksize + GRUB_DISK_SECTOR_BITS); + + while (len > 0) + { + grub_err_t ret; + grub_size_t size; + + size = (GRUB_DISK_SECTOR_SIZE << log2blocksize) - pos; + if (size > len) + size = len; + + ret = grub_disk_read (disk, + grub_fshelp_map_block (log, block) << log2blocksize, + pos, size, buf); + + if (ret) + return ret; + + block++; + pos = 0; + buf += size; + len -= size; + } + + return 0; +} + + /* 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 diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h index 0120cbf..847f78e 100644 --- a/include/grub/fshelp.h +++ b/include/grub/fshelp.h @@ -84,6 +84,15 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path, enum grub_fshelp_filetype expect); +/* Read LEN bytes from the block BLOCK on disk DISK into the buffer BUF, + beginning with the block POS. Apply mappings from LOG. The blocks + have a size of LOG2BLOCKSIZE (in log2). */ +grub_err_t +EXPORT_FUNC(grub_fshelp_read) (grub_disk_t disk, grub_fshelp_journal_t log, + grub_disk_addr_t block, grub_off_t pos, + grub_size_t len, char *buf, int log2blocksize); + + /* 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