From: marco_g Date: Tue, 3 Jan 2006 14:30:57 +0000 (+0000) Subject: 2006-01-03 Hollis Blanchard X-Git-Tag: 1.98~2012 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00905879979ceaa3ea993b99e8c87e41a9a8449a;p=thirdparty%2Fgrub.git 2006-01-03 Hollis Blanchard * fs/hfs.c: Include . 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 . 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. --- diff --git a/ChangeLog b/ChangeLog index 85ef91da1..4ec5cc97c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2006-01-03 Hollis Blanchard + + * fs/hfs.c: Include . 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 . 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 * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRP_ADDR): diff --git a/fs/hfs.c b/fs/hfs.c index ac0c14a47..6224b4fdd 100644 --- 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 #include #include @@ -25,9 +28,10 @@ #include #include #include +#include #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; } diff --git a/fs/hfsplus.c b/fs/hfsplus.c index 19cec30b6..b6682685d 100644 --- a/fs/hfsplus.c +++ b/fs/hfsplus.c @@ -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 #include #include @@ -26,6 +28,11 @@ #include #include #include +#include + +#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 index 000000000..88c0335a4 --- /dev/null +++ b/include/grub/hfs.h @@ -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 + +#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 */