Blob Blame History Raw
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