* grub-core/fs/affs.c (grub_affs_mount): Support AFFS bootblock in
sector 1.
This commit is contained in:
parent
473959f052
commit
b78c312722
2 changed files with 76 additions and 72 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2012-09-26 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/fs/affs.c (grub_affs_mount): Support AFFS bootblock in
|
||||||
|
sector 1.
|
||||||
|
|
||||||
2012-09-24 Colin Watson <cjwatson@ubuntu.com>
|
2012-09-24 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
* util/grub-install.in: Make the error message if $source_dir
|
* util/grub-install.in: Make the error message if $source_dir
|
||||||
|
|
|
@ -97,6 +97,7 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AFFS_MAX_LOG_BLOCK_SIZE 4
|
#define AFFS_MAX_LOG_BLOCK_SIZE 4
|
||||||
|
#define AFFS_MAX_SUPERBLOCK 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,94 +185,92 @@ grub_affs_mount (grub_disk_t disk)
|
||||||
{
|
{
|
||||||
struct grub_affs_data *data;
|
struct grub_affs_data *data;
|
||||||
grub_uint32_t *rootblock = 0;
|
grub_uint32_t *rootblock = 0;
|
||||||
struct grub_affs_rblock *rblock;
|
struct grub_affs_rblock *rblock = 0;
|
||||||
int log_blocksize = 0;
|
int log_blocksize = 0;
|
||||||
|
int bsnum = 0;
|
||||||
|
|
||||||
data = grub_zalloc (sizeof (struct grub_affs_data));
|
data = grub_zalloc (sizeof (struct grub_affs_data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Read the bootblock. */
|
for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++)
|
||||||
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
|
|
||||||
&data->bblock);
|
|
||||||
if (grub_errno)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Make sure this is an affs filesystem. */
|
|
||||||
if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
|
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
|
/* Read the bootblock. */
|
||||||
goto fail;
|
grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock),
|
||||||
}
|
&data->bblock);
|
||||||
|
|
||||||
/* Test if the filesystem is a OFS filesystem. */
|
|
||||||
if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
|
|
||||||
{
|
|
||||||
grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No sane person uses more than 8KB for a block. At least I hope
|
|
||||||
for that person because in that case this won't work. */
|
|
||||||
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << AFFS_MAX_LOG_BLOCK_SIZE);
|
|
||||||
if (!rootblock)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
rblock = (struct grub_affs_rblock *) rootblock;
|
|
||||||
|
|
||||||
/* The filesystem blocksize is not stored anywhere in the filesystem
|
|
||||||
itself. One way to determine it is try reading blocks for the
|
|
||||||
rootblock until the checksum is correct. */
|
|
||||||
for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE;
|
|
||||||
log_blocksize++)
|
|
||||||
{
|
|
||||||
grub_uint32_t *currblock = rootblock;
|
|
||||||
unsigned int i;
|
|
||||||
grub_uint32_t checksum = 0;
|
|
||||||
|
|
||||||
/* Read the rootblock. */
|
|
||||||
grub_disk_read (disk,
|
|
||||||
(grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock)
|
|
||||||
<< log_blocksize, 0,
|
|
||||||
GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock);
|
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (rblock->type != grub_cpu_to_be32_compile_time (2)
|
/* Make sure this is an affs filesystem. */
|
||||||
|| rblock->htsize == 0
|
if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3) != 0
|
||||||
|| currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
/* Test if the filesystem is a OFS filesystem. */
|
||||||
/ sizeof (*currblock) - 1]
|
|| !(data->bblock.flags & GRUB_AFFS_FLAG_FFS))
|
||||||
!= grub_cpu_to_be32_compile_time (1))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
/* No sane person uses more than 8KB for a block. At least I hope
|
||||||
/ sizeof (*currblock);
|
for that person because in that case this won't work. */
|
||||||
i++)
|
if (!rootblock)
|
||||||
checksum += grub_be_to_cpu32 (currblock[i]);
|
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE
|
||||||
|
<< AFFS_MAX_LOG_BLOCK_SIZE);
|
||||||
|
if (!rootblock)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (checksum == 0)
|
rblock = (struct grub_affs_rblock *) rootblock;
|
||||||
break;
|
|
||||||
|
/* The filesystem blocksize is not stored anywhere in the filesystem
|
||||||
|
itself. One way to determine it is try reading blocks for the
|
||||||
|
rootblock until the checksum is correct. */
|
||||||
|
for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE;
|
||||||
|
log_blocksize++)
|
||||||
|
{
|
||||||
|
grub_uint32_t *currblock = rootblock;
|
||||||
|
unsigned int i;
|
||||||
|
grub_uint32_t checksum = 0;
|
||||||
|
|
||||||
|
/* Read the rootblock. */
|
||||||
|
grub_disk_read (disk,
|
||||||
|
(grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock)
|
||||||
|
<< log_blocksize, 0,
|
||||||
|
GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock);
|
||||||
|
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||||
|
{
|
||||||
|
grub_errno = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (grub_errno)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (rblock->type != grub_cpu_to_be32_compile_time (2)
|
||||||
|
|| rblock->htsize == 0
|
||||||
|
|| currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
||||||
|
/ sizeof (*currblock) - 1]
|
||||||
|
!= grub_cpu_to_be32_compile_time (1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
||||||
|
/ sizeof (*currblock);
|
||||||
|
i++)
|
||||||
|
checksum += grub_be_to_cpu32 (currblock[i]);
|
||||||
|
|
||||||
|
if (checksum == 0)
|
||||||
|
{
|
||||||
|
data->log_blocksize = log_blocksize;
|
||||||
|
data->disk = disk;
|
||||||
|
data->htsize = grub_be_to_cpu32 (rblock->htsize);
|
||||||
|
data->diropen.data = data;
|
||||||
|
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
|
||||||
|
data->diropen.parent = NULL;
|
||||||
|
grub_memcpy (&data->diropen.di, rootblock,
|
||||||
|
sizeof (data->diropen.di));
|
||||||
|
grub_free (rootblock);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (log_blocksize > AFFS_MAX_LOG_BLOCK_SIZE)
|
|
||||||
{
|
|
||||||
grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->log_blocksize = log_blocksize;
|
|
||||||
data->disk = disk;
|
|
||||||
data->htsize = grub_be_to_cpu32 (rblock->htsize);
|
|
||||||
data->diropen.data = data;
|
|
||||||
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
|
|
||||||
data->diropen.parent = NULL;
|
|
||||||
grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di));
|
|
||||||
|
|
||||||
grub_free (rootblock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||||
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
|
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
|
||||||
|
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
|
Loading…
Reference in a new issue