203 lines
6.3 KiB
Diff
203 lines
6.3 KiB
Diff
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
|
||
|