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