]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2006-01-03 Hollis Blanchard <hollis@penguinppc.org>
authormarco_g <marco_g@localhost>
Tue, 3 Jan 2006 14:30:57 +0000 (14:30 +0000)
committermarco_g <marco_g@localhost>
Tue, 3 Jan 2006 14:30:57 +0000 (14:30 +0000)
* fs/hfs.c: Include <grub/hfs.h>.  Added reference to the official
documentation.
(GRUB_HFS_EMBED_HFSPLUS_SIG): New macro.
(grub_hfs_mount): Grammar fix in error. Make sure this is not an
embedded HFS+ filesystem.
(GRUB_HFS_MAGIC, grub_hfs_extent, grub_hfs_datarecord_t)
(grub_hfs_sblock): Move from here...
* include/grub/hfs.h: To here...  New file.
* fs/hfsplus.c: Include <grub/hfs.h>.  Added reference to the official
documentation.
(GRUB_HFSPLUS_MAGIC, GRUB_HFSPLUSX_MAGIC, GRUB_HFSPLUS_SBLOCK):
New macros.
(grub_hfsplus_volheader): Change type of member `magic' to
`grub_uint16_t'.
(grub_hfsplus_data): Add new member `embedded_offset'.
(grub_hfsplus_read_block): Add the HFS+ wrapper offset to the
returned block.
(grub_hfsplus_mount): Read the HFS+ wrapper if it exists.
Calculate the offset.

ChangeLog
fs/hfs.c
fs/hfsplus.c
include/grub/hfs.h [new file with mode: 0644]

index 85ef91da1282aa3b93ed05f1000dd5e6ee097daa..4ec5cc97c3e675f8dba291014d21ba07860153d9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2006-01-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * fs/hfs.c: Include <grub/hfs.h>.  Added reference to the official
+       documentation.
+       (GRUB_HFS_EMBED_HFSPLUS_SIG): New macro.
+       (grub_hfs_mount): Grammar fix in error. Make sure this is not an
+       embedded HFS+ filesystem.
+       (GRUB_HFS_MAGIC, grub_hfs_extent, grub_hfs_datarecord_t)
+       (grub_hfs_sblock): Move from here...
+       * include/grub/hfs.h: To here...  New file.
+       * fs/hfsplus.c: Include <grub/hfs.h>.  Added reference to the official
+       documentation.
+       (GRUB_HFSPLUS_MAGIC, GRUB_HFSPLUSX_MAGIC, GRUB_HFSPLUS_SBLOCK):
+       New macros.
+       (grub_hfsplus_volheader): Change type of member `magic' to
+       `grub_uint16_t'.
+       (grub_hfsplus_data): Add new member `embedded_offset'.
+       (grub_hfsplus_read_block): Add the HFS+ wrapper offset to the
+       returned block.
+       (grub_hfsplus_mount): Read the HFS+ wrapper if it exists.
+       Calculate the offset.
+
 2005-12-25  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRP_ADDR):
index ac0c14a474f36a52ab96c23f83a6fabc3d4fb816..6224b4fddb0b770e8d07ea74b00fd18c640aa867 100644 (file)
--- a/fs/hfs.c
+++ b/fs/hfs.c
@@ -1,7 +1,7 @@
 /* hfs.c - HFS.  */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,6 +18,9 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* HFS is documented at
+   http://developer.apple.com/documentation/mac/Files/Files-2.html */
+
 #include <grub/err.h>
 #include <grub/file.h>
 #include <grub/mm.h>
 #include <grub/disk.h>
 #include <grub/dl.h>
 #include <grub/types.h>
+#include <grub/hfs.h>
 
 #define        GRUB_HFS_SBLOCK         2
-#define GRUB_HFS_MAGIC         0x4244
+#define GRUB_HFS_EMBED_HFSPLUS_SIG 0x482B
 
 #define GRUB_HFS_BLKS          (data->blksz >> 9)
 
@@ -40,37 +44,6 @@ enum
     GRUB_HFS_FILETYPE_FILE = 2
   };
 
-/* A single extent.  A file consists of suchs extents.  */
-struct grub_hfs_extent
-{
-  /* The first physical block.  */
-  grub_uint16_t first_block;
-  grub_uint16_t count;
-};
-
-/* HFS stores extents in groups of 3.  */
-typedef struct grub_hfs_extent grub_hfs_datarecord_t[3];
-
-/* The HFS superblock (The official name is `Master Directory
-   Block').  */
-struct grub_hfs_sblock
-{
-  grub_uint16_t magic;
-  grub_uint8_t unused[18];
-  grub_uint32_t blksz;
-  grub_uint8_t unused2[4];
-  grub_uint16_t first_block;
-  grub_uint8_t unused4[6];
-
-  /* A pascal style string that holds the volumename.  */
-  grub_uint8_t volname[28];
-  
-  grub_uint8_t unused5[70];
-  grub_hfs_datarecord_t extent_recs;
-  grub_uint32_t catalog_size;
-  grub_hfs_datarecord_t catalog_recs;
-} __attribute__ ((packed));
-
 /* A node desciptor.  This is the header of every node.  */
 struct grub_hfs_node
 {
@@ -345,7 +318,14 @@ grub_hfs_mount (grub_disk_t disk)
   /* Check if this is a HFS filesystem.  */
   if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC)
     {
-      grub_error (GRUB_ERR_BAD_FS, "not a hfs filesystem");
+      grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
+      goto fail;
+    }
+
+  /* Check if this is an embedded HFS+ filesystem.  */
+  if (grub_be_to_cpu16 (data->sblock.embed_sig) == GRUB_HFS_EMBED_HFSPLUS_SIG)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "embedded HFS+ filesystem");
       goto fail;
     }
   
index 19cec30b604467960b2ce9a876f74947773c2ab6..b6682685dd0285e47671f7bd05989bfd3a4df304 100644 (file)
@@ -1,7 +1,7 @@
 /* hfsplus.c - HFS+ Filesystem.  */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *  Copyright (C) 2005, 2006  Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,6 +18,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */
+
 #include <grub/err.h>
 #include <grub/file.h>
 #include <grub/mm.h>
 #include <grub/dl.h>
 #include <grub/types.h>
 #include <grub/fshelp.h>
+#include <grub/hfs.h>
+
+#define GRUB_HFSPLUS_MAGIC 0x482B
+#define GRUB_HFSPLUSX_MAGIC 0x4858
+#define GRUB_HFSPLUS_SBLOCK 2
 
 /* A HFS+ extent.  */
 struct grub_hfsplus_extent
@@ -48,7 +55,7 @@ struct grub_hfsplus_forkdata
 /* The HFS+ Volume Header.  */
 struct grub_hfsplus_volheader
 {
-  grub_uint8_t magic[2];
+  grub_uint16_t magic;
   grub_uint16_t version;
   grub_uint32_t attributes;
   grub_uint8_t unused[32];
@@ -208,6 +215,10 @@ struct grub_hfsplus_data
 
   struct grub_fshelp_node dirroot;
   struct grub_fshelp_node opened_file;
+
+  /* This is the offset into the physical disk for an embedded HFS+
+     filesystem (one inside a plain HFS wrapper).  */
+  int embedded_offset;
 };
 
 #ifndef GRUB_UTIL
@@ -268,7 +279,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, int fileblock)
       /* Try to find this block in the current set of extents.  */
       blk = grub_hfsplus_find_block (extents, fileblock, &retry);
       if (blk != -1)
-       return blk;
+       return blk + node->data->embedded_offset;
 
       /* The previous iteration of this loop allocated memory.  The
         code above used this memory, it can be free'ed now.  */
@@ -333,6 +344,10 @@ grub_hfsplus_mount (grub_disk_t disk)
   struct grub_hfsplus_data *data;
   struct grub_hfsplus_btheader header;
   struct grub_hfsplus_btnode node;
+  union {
+    struct grub_hfs_sblock hfs;
+    struct grub_hfsplus_volheader hfsplus;
+  } volheader;
 
   data = grub_malloc (sizeof (*data));
   if (!data)
@@ -341,20 +356,51 @@ grub_hfsplus_mount (grub_disk_t disk)
   data->disk = disk;
 
   /* Read the bootblock.  */
-  grub_disk_read (disk, 2, 0, sizeof (struct grub_hfsplus_volheader),
-                 (char *) &data->volheader);
+  grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
+                 (char *) &volheader);
   if (grub_errno)
     goto fail;
 
-  /* Make sure this is an hfs+ filesystem.  XXX: Do we really support
+  data->embedded_offset = 0;
+  if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
+    {
+      int extent_start;
+      int ablk_size;
+      int ablk_start;
+
+      /* See if there's an embedded HFS+ filesystem.  */
+      if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
+         goto fail;
+       }
+
+      /* Calculate the offset needed to translate HFS+ sector numbers.  */
+      extent_start = grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block);
+      ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
+      ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
+      data->embedded_offset = (ablk_start
+                              + extent_start
+                              * (ablk_size >> GRUB_DISK_SECTOR_BITS));
+
+      grub_disk_read (disk, data->embedded_offset + GRUB_HFSPLUS_SBLOCK, 0,
+                     sizeof (volheader), (char *) &volheader);
+      if (grub_errno)
+       goto fail;
+    }
+
+  /* Make sure this is an HFS+ filesystem.  XXX: Do we really support
      HFX?  */
-  if (grub_strncmp (data->volheader.magic, "H+", 2)
-      && grub_strncmp (data->volheader.magic, "HX", 2))
+  if ((grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUS_MAGIC)
+      && (grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUSX_MAGIC))
     {
       grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
       goto fail;
     }
 
+  grub_memcpy (&data->volheader, &volheader.hfsplus,
+      sizeof (volheader.hfsplus));
+
   if (grub_fshelp_log2blksize (grub_be_to_cpu32 (data->volheader.blksize),
                               &data->log2blksize))
     goto fail;
diff --git a/include/grub/hfs.h b/include/grub/hfs.h
new file mode 100644 (file)
index 0000000..88c0335
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005, 2006  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_HFS_HEADER
+#define GRUB_HFS_HEADER        1
+
+#include <grub/types.h>
+
+#define GRUB_HFS_MAGIC         0x4244
+
+/* A single extent.  A file consists of one or more extents.  */
+struct grub_hfs_extent
+{
+  /* The first physical block.  */
+  grub_uint16_t first_block;
+  grub_uint16_t count;
+};
+
+/* HFS stores extents in groups of 3.  */
+typedef struct grub_hfs_extent grub_hfs_datarecord_t[3];
+
+/* The HFS superblock (The official name is `Master Directory
+   Block').  */
+struct grub_hfs_sblock
+{
+  grub_uint16_t magic;
+  grub_uint8_t unused[18];
+  grub_uint32_t blksz;
+  grub_uint8_t unused2[4];
+  grub_uint16_t first_block;
+  grub_uint8_t unused4[6];
+
+  /* A pascal style string that holds the volumename.  */
+  grub_uint8_t volname[28];
+  
+  grub_uint8_t unused5[60];
+  grub_uint16_t embed_sig;
+  struct grub_hfs_extent embed_extent;
+  grub_uint8_t unused6[4];
+  grub_hfs_datarecord_t extent_recs;
+  grub_uint32_t catalog_size;
+  grub_hfs_datarecord_t catalog_recs;
+} __attribute__ ((packed));
+
+#endif /* ! GRUB_HFS_HEADER */