grub2/0047-grub-core-fs-affs.c-grub_affs_mount-Support-AFFS-boo.patch

203 lines
6.3 KiB
Diff
Raw Normal View History

From d36c4c3115977beb5f9247c6c6f0a2a209389f45 Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Wed, 26 Sep 2012 09:33:41 +0200
Subject: [PATCH 047/364] * grub-core/fs/affs.c (grub_affs_mount):
Support AFFS bootblock in sector 1.
---
ChangeLog | 5 ++
grub-core/fs/affs.c | 139 ++++++++++++++++++++++++++--------------------------
2 files changed, 74 insertions(+), 70 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a53c5cc..d81a9a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* util/grub-install.in: Make the error message if $source_dir
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index ef65479..848a455 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -97,6 +97,7 @@ enum
};
#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;
grub_uint32_t *rootblock = 0;
- struct grub_affs_rblock *rblock;
+ struct grub_affs_rblock *rblock = 0;
int log_blocksize = 0;
+ int bsnum = 0;
data = grub_zalloc (sizeof (struct grub_affs_data));
if (!data)
return 0;
- /* Read the bootblock. */
- 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");
- goto fail;
- }
-
- /* 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++)
+ for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++)
{
- 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);
+ /* Read the bootblock. */
+ grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock),
+ &data->bblock);
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))
+ /* Make sure this is an affs filesystem. */
+ if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3) != 0
+ /* Test if the filesystem is a OFS filesystem. */
+ || !(data->bblock.flags & GRUB_AFFS_FLAG_FFS))
continue;
- for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
- / sizeof (*currblock);
- i++)
- checksum += grub_be_to_cpu32 (currblock[i]);
+ /* 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. */
+ if (!rootblock)
+ rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE
+ << AFFS_MAX_LOG_BLOCK_SIZE);
+ if (!rootblock)
+ goto fail;
- if (checksum == 0)
- break;
- }
- if (log_blocksize > AFFS_MAX_LOG_BLOCK_SIZE)
- {
- grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
- 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 == GRUB_ERR_OUT_OF_RANGE)
+ {
+ grub_errno = 0;
+ break;
+ }
+ if (grub_errno)
+ 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));
+ 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;
- grub_free (rootblock);
+ for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
+ / sizeof (*currblock);
+ i++)
+ checksum += grub_be_to_cpu32 (currblock[i]);
- return data;
+ 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;
+ }
+ }
+ }
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_free (data);
--
1.8.1.4