* grub-core/fs/ufs.c (grub_ufs_get_file_block): Support triple indirect.
This commit is contained in:
parent
59fd2aacd0
commit
c82f16c1be
2 changed files with 49 additions and 12 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/fs/ufs.c (grub_ufs_get_file_block): Support triple indirect.
|
||||||
|
|
||||||
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
2012-05-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Use proper check for
|
* grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Use proper check for
|
||||||
|
|
|
@ -65,9 +65,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
|
#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
|
||||||
#ifdef MODE_UFS2
|
#ifdef MODE_UFS2
|
||||||
#define INODE_BLKSZ 8
|
#define LOG_INODE_BLKSZ 3
|
||||||
#else
|
#else
|
||||||
#define INODE_BLKSZ 4
|
#define LOG_INODE_BLKSZ 2
|
||||||
#endif
|
#endif
|
||||||
#ifdef MODE_UFS2
|
#ifdef MODE_UFS2
|
||||||
#define UFS_INODE_PER_BLOCK 2
|
#define UFS_INODE_PER_BLOCK 2
|
||||||
|
@ -227,11 +227,11 @@ static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data,
|
||||||
|
|
||||||
|
|
||||||
static grub_disk_addr_t
|
static grub_disk_addr_t
|
||||||
grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
|
grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
|
||||||
{
|
{
|
||||||
struct grub_ufs_sblock *sblock = &data->sblock;
|
struct grub_ufs_sblock *sblock = &data->sblock;
|
||||||
unsigned int indirsz;
|
unsigned long indirsz;
|
||||||
int log2_blksz;
|
int log2_blksz, log_indirsz;
|
||||||
|
|
||||||
/* Direct. */
|
/* Direct. */
|
||||||
if (blk < GRUB_UFS_DIRBLKS)
|
if (blk < GRUB_UFS_DIRBLKS)
|
||||||
|
@ -241,7 +241,8 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
|
||||||
|
|
||||||
blk -= GRUB_UFS_DIRBLKS;
|
blk -= GRUB_UFS_DIRBLKS;
|
||||||
|
|
||||||
indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ;
|
log_indirsz = data->log2_blksz - LOG_INODE_BLKSZ;
|
||||||
|
indirsz = 1 << log_indirsz;
|
||||||
/* Single indirect block. */
|
/* Single indirect block. */
|
||||||
if (blk < indirsz)
|
if (blk < indirsz)
|
||||||
{
|
{
|
||||||
|
@ -250,14 +251,16 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
|
||||||
#else
|
#else
|
||||||
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
||||||
#endif
|
#endif
|
||||||
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 0) << log2_blksz,
|
grub_disk_read (data->disk,
|
||||||
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0))
|
||||||
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
0, sizeof (indir), indir);
|
||||||
return indir[blk];
|
return indir[blk];
|
||||||
}
|
}
|
||||||
blk -= indirsz;
|
blk -= indirsz;
|
||||||
|
|
||||||
/* Double indirect block. */
|
/* Double indirect block. */
|
||||||
if (blk < indirsz * indirsz)
|
if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz)
|
||||||
{
|
{
|
||||||
#ifdef MODE_UFS2
|
#ifdef MODE_UFS2
|
||||||
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
||||||
|
@ -265,19 +268,49 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
|
||||||
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1) << log2_blksz,
|
grub_disk_read (data->disk,
|
||||||
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1))
|
||||||
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
0, sizeof (indir), indir);
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
(indir [blk / indirsz])
|
((grub_disk_addr_t) indir [blk >> log_indirsz])
|
||||||
<< log2_blksz,
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
0, sizeof (indir), indir);
|
||||||
|
|
||||||
return indir[blk % indirsz];
|
return indir[blk & ((1 << log_indirsz) - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz;
|
||||||
|
|
||||||
|
/* Triple indirect block. */
|
||||||
|
if (!(blk >> (3 * log_indirsz)))
|
||||||
|
{
|
||||||
|
#ifdef MODE_UFS2
|
||||||
|
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
||||||
|
#else
|
||||||
|
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
grub_disk_read (data->disk,
|
||||||
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2))
|
||||||
|
<< log2_blksz,
|
||||||
|
0, sizeof (indir), indir);
|
||||||
|
grub_disk_read (data->disk,
|
||||||
|
((grub_disk_addr_t) indir [blk >> (2 * log_indirsz)])
|
||||||
|
<< log2_blksz,
|
||||||
|
0, sizeof (indir), indir);
|
||||||
|
|
||||||
|
grub_disk_read (data->disk,
|
||||||
|
((grub_disk_addr_t) indir [(blk >> log_indirsz)
|
||||||
|
& ((1 << log_indirsz) - 1)])
|
||||||
|
<< log2_blksz,
|
||||||
|
0, sizeof (indir), indir);
|
||||||
|
|
||||||
|
return indir[blk & ((1 << log_indirsz) - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"ufs does not support triple indirect blocks");
|
"ufs does not support quadruple indirect blocks");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue