+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):
/* 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
* 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)
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
{
/* 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;
}
/* 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
* 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
/* 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];
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
/* 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. */
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)
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;
--- /dev/null
+/*
+ * 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 */