This patch (sent mostly for Marco) adds HFS wrapper support to the HFS+
code. All Apple-created HFS+ partitions are contained in an HFS wrapper
for some backwards compatibility. The code is based on information
found at http://developer.apple.com/technotes/tn/tn1150.html#HFSWrapper
.
I only moved the minimum HFS code and structures into hfs.h. More could
go there if desired.
When I tested this patch, an embedded filesystem was recognized as
HFS+, but the HFS+ code itself did not discover any files, so there is
probably still something wrong.
-Hollis
Index: fs/hfs.c
===================================================================
RCS file: /cvsroot/grub/grub2/fs/hfs.c,v
retrieving revision 1.4
diff -u -p -r1.4 hfs.c
--- fs/hfs.c 13 Nov 2005 15:47:09 -0000 1.4
+++ fs/hfs.c 2 Jan 2006 20:30:21 -0000
@@ -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>
@@ -25,9 +28,10 @@
#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: fs/hfsplus.c
===================================================================
RCS file: /cvsroot/grub/grub2/fs/hfsplus.c,v
retrieving revision 1.1
diff -u -p -r1.1 hfsplus.c
--- fs/hfsplus.c 25 Dec 2005 15:59:50 -0000 1.1
+++ fs/hfsplus.c 2 Jan 2006 20:30:21 -0000
@@ -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>
@@ -26,6 +28,11 @@
#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];
@@ -214,6 +221,10 @@ struct grub_hfsplus_data
static grub_dl_t my_mod;
#endif
+/* This is the offset into the physical disk for an embedded HFS+ filesystem
+ * (one inside a plain HFS wrapper). */
+static int embedded_offset = 0;
+
/* Find the extent that points to FILEBLOCK. If it is not in one of
the 8 extents described by EXTENT, return -1. In that case set
@@ -268,7 +279,7 @@ grub_hfsplus_read_block (grub_fshelp_nod
/* 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 + 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,48 @@ 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
+ if (volheader.hfs.magic == GRUB_HFS_MAGIC)
+ {
+ int extent_start;
+ int ablk_size;
+ int ablk_start;
+
+ /* See if there's an embedded HFS+ filesystem. */
+ if (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);
+ embedded_offset = ablk_start + extent_start * (ablk_size / 512);
+
+ grub_disk_read (disk, 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 ((volheader.hfsplus.magic != GRUB_HFSPLUS_MAGIC)
+ && (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;
Index: include/grub/hfs.h
===================================================================
RCS file: include/grub/hfs.h
diff -N include/grub/hfs.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/grub/hfs.h 2 Jan 2006 20:30:21 -0000
@@ -0,0 +1,61 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 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 */
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel