|
|
a5bd9f6 |
From d36c4c3115977beb5f9247c6c6f0a2a209389f45 Mon Sep 17 00:00:00 2001
|
|
|
a5bd9f6 |
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
|
|
|
a5bd9f6 |
Date: Wed, 26 Sep 2012 09:33:41 +0200
|
|
|
a5bd9f6 |
Subject: [PATCH 047/364] * grub-core/fs/affs.c (grub_affs_mount):
|
|
|
a5bd9f6 |
Support AFFS bootblock in sector 1.
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
---
|
|
|
a5bd9f6 |
ChangeLog | 5 ++
|
|
|
a5bd9f6 |
grub-core/fs/affs.c | 139 ++++++++++++++++++++++++++--------------------------
|
|
|
a5bd9f6 |
2 files changed, 74 insertions(+), 70 deletions(-)
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
diff --git a/ChangeLog b/ChangeLog
|
|
|
a5bd9f6 |
index a53c5cc..d81a9a6 100644
|
|
|
a5bd9f6 |
--- a/ChangeLog
|
|
|
a5bd9f6 |
+++ b/ChangeLog
|
|
|
a5bd9f6 |
@@ -1,3 +1,8 @@
|
|
|
a5bd9f6 |
+2012-09-26 Vladimir Serbinenko <phcoder@gmail.com>
|
|
|
a5bd9f6 |
+
|
|
|
a5bd9f6 |
+ * grub-core/fs/affs.c (grub_affs_mount): Support AFFS bootblock in
|
|
|
a5bd9f6 |
+ sector 1.
|
|
|
a5bd9f6 |
+
|
|
|
a5bd9f6 |
2012-09-24 Colin Watson <cjwatson@ubuntu.com>
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
* util/grub-install.in: Make the error message if $source_dir
|
|
|
a5bd9f6 |
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
|
|
|
a5bd9f6 |
index ef65479..848a455 100644
|
|
|
a5bd9f6 |
--- a/grub-core/fs/affs.c
|
|
|
a5bd9f6 |
+++ b/grub-core/fs/affs.c
|
|
|
a5bd9f6 |
@@ -97,6 +97,7 @@ enum
|
|
|
a5bd9f6 |
};
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
#define AFFS_MAX_LOG_BLOCK_SIZE 4
|
|
|
a5bd9f6 |
+#define AFFS_MAX_SUPERBLOCK 1
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
@@ -184,94 +185,92 @@ grub_affs_mount (grub_disk_t disk)
|
|
|
a5bd9f6 |
{
|
|
|
a5bd9f6 |
struct grub_affs_data *data;
|
|
|
a5bd9f6 |
grub_uint32_t *rootblock = 0;
|
|
|
a5bd9f6 |
- struct grub_affs_rblock *rblock;
|
|
|
a5bd9f6 |
+ struct grub_affs_rblock *rblock = 0;
|
|
|
a5bd9f6 |
int log_blocksize = 0;
|
|
|
a5bd9f6 |
+ int bsnum = 0;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
data = grub_zalloc (sizeof (struct grub_affs_data));
|
|
|
a5bd9f6 |
if (!data)
|
|
|
a5bd9f6 |
return 0;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- /* Read the bootblock. */
|
|
|
a5bd9f6 |
- grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
|
|
|
a5bd9f6 |
- &data->bblock);
|
|
|
a5bd9f6 |
- if (grub_errno)
|
|
|
a5bd9f6 |
- goto fail;
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- /* Make sure this is an affs filesystem. */
|
|
|
a5bd9f6 |
- if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
|
|
|
a5bd9f6 |
- {
|
|
|
a5bd9f6 |
- grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
|
|
|
a5bd9f6 |
- goto fail;
|
|
|
a5bd9f6 |
- }
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- /* Test if the filesystem is a OFS filesystem. */
|
|
|
a5bd9f6 |
- if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
|
|
|
a5bd9f6 |
- {
|
|
|
a5bd9f6 |
- grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
|
|
|
a5bd9f6 |
- goto fail;
|
|
|
a5bd9f6 |
- }
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- /* No sane person uses more than 8KB for a block. At least I hope
|
|
|
a5bd9f6 |
- for that person because in that case this won't work. */
|
|
|
a5bd9f6 |
- rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << AFFS_MAX_LOG_BLOCK_SIZE);
|
|
|
a5bd9f6 |
- if (!rootblock)
|
|
|
a5bd9f6 |
- goto fail;
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- rblock = (struct grub_affs_rblock *) rootblock;
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- /* The filesystem blocksize is not stored anywhere in the filesystem
|
|
|
a5bd9f6 |
- itself. One way to determine it is try reading blocks for the
|
|
|
a5bd9f6 |
- rootblock until the checksum is correct. */
|
|
|
a5bd9f6 |
- for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE;
|
|
|
a5bd9f6 |
- log_blocksize++)
|
|
|
a5bd9f6 |
+ for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++)
|
|
|
a5bd9f6 |
{
|
|
|
a5bd9f6 |
- grub_uint32_t *currblock = rootblock;
|
|
|
a5bd9f6 |
- unsigned int i;
|
|
|
a5bd9f6 |
- grub_uint32_t checksum = 0;
|
|
|
a5bd9f6 |
-
|
|
|
a5bd9f6 |
- /* Read the rootblock. */
|
|
|
a5bd9f6 |
- grub_disk_read (disk,
|
|
|
a5bd9f6 |
- (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock)
|
|
|
a5bd9f6 |
- << log_blocksize, 0,
|
|
|
a5bd9f6 |
- GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock);
|
|
|
a5bd9f6 |
+ /* Read the bootblock. */
|
|
|
a5bd9f6 |
+ grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock),
|
|
|
a5bd9f6 |
+ &data->bblock);
|
|
|
a5bd9f6 |
if (grub_errno)
|
|
|
a5bd9f6 |
goto fail;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- if (rblock->type != grub_cpu_to_be32_compile_time (2)
|
|
|
a5bd9f6 |
- || rblock->htsize == 0
|
|
|
a5bd9f6 |
- || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
|
|
a5bd9f6 |
- / sizeof (*currblock) - 1]
|
|
|
a5bd9f6 |
- != grub_cpu_to_be32_compile_time (1))
|
|
|
a5bd9f6 |
+ /* Make sure this is an affs filesystem. */
|
|
|
a5bd9f6 |
+ if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3) != 0
|
|
|
a5bd9f6 |
+ /* Test if the filesystem is a OFS filesystem. */
|
|
|
a5bd9f6 |
+ || !(data->bblock.flags & GRUB_AFFS_FLAG_FFS))
|
|
|
a5bd9f6 |
continue;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
|
|
a5bd9f6 |
- / sizeof (*currblock);
|
|
|
a5bd9f6 |
- i++)
|
|
|
a5bd9f6 |
- checksum += grub_be_to_cpu32 (currblock[i]);
|
|
|
a5bd9f6 |
+ /* No sane person uses more than 8KB for a block. At least I hope
|
|
|
a5bd9f6 |
+ for that person because in that case this won't work. */
|
|
|
a5bd9f6 |
+ if (!rootblock)
|
|
|
a5bd9f6 |
+ rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE
|
|
|
a5bd9f6 |
+ << AFFS_MAX_LOG_BLOCK_SIZE);
|
|
|
a5bd9f6 |
+ if (!rootblock)
|
|
|
a5bd9f6 |
+ goto fail;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- if (checksum == 0)
|
|
|
a5bd9f6 |
- break;
|
|
|
a5bd9f6 |
- }
|
|
|
a5bd9f6 |
- if (log_blocksize > AFFS_MAX_LOG_BLOCK_SIZE)
|
|
|
a5bd9f6 |
- {
|
|
|
a5bd9f6 |
- grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
|
|
|
a5bd9f6 |
- goto fail;
|
|
|
a5bd9f6 |
- }
|
|
|
a5bd9f6 |
+ rblock = (struct grub_affs_rblock *) rootblock;
|
|
|
a5bd9f6 |
+
|
|
|
a5bd9f6 |
+ /* The filesystem blocksize is not stored anywhere in the filesystem
|
|
|
a5bd9f6 |
+ itself. One way to determine it is try reading blocks for the
|
|
|
a5bd9f6 |
+ rootblock until the checksum is correct. */
|
|
|
a5bd9f6 |
+ for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE;
|
|
|
a5bd9f6 |
+ log_blocksize++)
|
|
|
a5bd9f6 |
+ {
|
|
|
a5bd9f6 |
+ grub_uint32_t *currblock = rootblock;
|
|
|
a5bd9f6 |
+ unsigned int i;
|
|
|
a5bd9f6 |
+ grub_uint32_t checksum = 0;
|
|
|
a5bd9f6 |
+
|
|
|
a5bd9f6 |
+ /* Read the rootblock. */
|
|
|
a5bd9f6 |
+ grub_disk_read (disk,
|
|
|
a5bd9f6 |
+ (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock)
|
|
|
a5bd9f6 |
+ << log_blocksize, 0,
|
|
|
a5bd9f6 |
+ GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock);
|
|
|
a5bd9f6 |
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
|
|
a5bd9f6 |
+ {
|
|
|
a5bd9f6 |
+ grub_errno = 0;
|
|
|
a5bd9f6 |
+ break;
|
|
|
a5bd9f6 |
+ }
|
|
|
a5bd9f6 |
+ if (grub_errno)
|
|
|
a5bd9f6 |
+ goto fail;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- data->log_blocksize = log_blocksize;
|
|
|
a5bd9f6 |
- data->disk = disk;
|
|
|
a5bd9f6 |
- data->htsize = grub_be_to_cpu32 (rblock->htsize);
|
|
|
a5bd9f6 |
- data->diropen.data = data;
|
|
|
a5bd9f6 |
- data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
|
|
|
a5bd9f6 |
- data->diropen.parent = NULL;
|
|
|
a5bd9f6 |
- grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di));
|
|
|
a5bd9f6 |
+ if (rblock->type != grub_cpu_to_be32_compile_time (2)
|
|
|
a5bd9f6 |
+ || rblock->htsize == 0
|
|
|
a5bd9f6 |
+ || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
|
|
a5bd9f6 |
+ / sizeof (*currblock) - 1]
|
|
|
a5bd9f6 |
+ != grub_cpu_to_be32_compile_time (1))
|
|
|
a5bd9f6 |
+ continue;
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- grub_free (rootblock);
|
|
|
a5bd9f6 |
+ for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize)
|
|
|
a5bd9f6 |
+ / sizeof (*currblock);
|
|
|
a5bd9f6 |
+ i++)
|
|
|
a5bd9f6 |
+ checksum += grub_be_to_cpu32 (currblock[i]);
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
- return data;
|
|
|
a5bd9f6 |
+ if (checksum == 0)
|
|
|
a5bd9f6 |
+ {
|
|
|
a5bd9f6 |
+ data->log_blocksize = log_blocksize;
|
|
|
a5bd9f6 |
+ data->disk = disk;
|
|
|
a5bd9f6 |
+ data->htsize = grub_be_to_cpu32 (rblock->htsize);
|
|
|
a5bd9f6 |
+ data->diropen.data = data;
|
|
|
a5bd9f6 |
+ data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
|
|
|
a5bd9f6 |
+ data->diropen.parent = NULL;
|
|
|
a5bd9f6 |
+ grub_memcpy (&data->diropen.di, rootblock,
|
|
|
a5bd9f6 |
+ sizeof (data->diropen.di));
|
|
|
a5bd9f6 |
+ grub_free (rootblock);
|
|
|
a5bd9f6 |
+
|
|
|
a5bd9f6 |
+ return data;
|
|
|
a5bd9f6 |
+ }
|
|
|
a5bd9f6 |
+ }
|
|
|
a5bd9f6 |
+ }
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
fail:
|
|
|
a5bd9f6 |
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
|
|
a5bd9f6 |
+ if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
|
|
a5bd9f6 |
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
|
|
|
a5bd9f6 |
|
|
|
a5bd9f6 |
grub_free (data);
|
|
|
a5bd9f6 |
--
|
|
|
a5bd9f6 |
1.8.1.4
|
|
|
a5bd9f6 |
|