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
|
|||
|
|