diff options
Diffstat (limited to 'include/grub/hfsplus.h')
-rw-r--r-- | include/grub/hfsplus.h | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/include/grub/hfsplus.h b/include/grub/hfsplus.h new file mode 100644 index 0000000..e14dd31 --- /dev/null +++ b/include/grub/hfsplus.h @@ -0,0 +1,259 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2012,2013 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/disk.h> + +#define GRUB_HFSPLUS_MAGIC 0x482B +#define GRUB_HFSPLUSX_MAGIC 0x4858 +#define GRUB_HFSPLUS_SBLOCK 2 + +/* A HFS+ extent. */ +struct grub_hfsplus_extent +{ + /* The first block of a file on disk. */ + grub_uint32_t start; + /* The amount of blocks described by this extent. */ + grub_uint32_t count; +} GRUB_PACKED; + +/* The descriptor of a fork. */ +struct grub_hfsplus_forkdata +{ + grub_uint64_t size; + grub_uint32_t clumpsize; + grub_uint32_t blocks; + struct grub_hfsplus_extent extents[8]; +} GRUB_PACKED; + +/* The HFS+ Volume Header. */ +struct grub_hfsplus_volheader +{ + grub_uint16_t magic; + grub_uint16_t version; + grub_uint32_t attributes; + grub_uint8_t unused1[12]; + grub_uint32_t utime; + grub_uint8_t unused2[16]; + grub_uint32_t blksize; + grub_uint8_t unused3[36]; + + grub_uint32_t ppc_bootdir; + grub_uint32_t intel_bootfile; + /* Folder opened when disk is mounted. Unused by GRUB. */ + grub_uint32_t showfolder; + grub_uint32_t os9folder; + grub_uint8_t unused4[4]; + grub_uint32_t osxfolder; + + grub_uint64_t num_serial; + struct grub_hfsplus_forkdata allocations_file; + struct grub_hfsplus_forkdata extents_file; + struct grub_hfsplus_forkdata catalog_file; + struct grub_hfsplus_forkdata attr_file; + struct grub_hfsplus_forkdata startup_file; +} GRUB_PACKED; + +struct grub_hfsplus_compress_index +{ + grub_uint32_t start; + grub_uint32_t size; +}; + +struct grub_hfsplus_file +{ + struct grub_hfsplus_data *data; + struct grub_hfsplus_extent extents[8]; + struct grub_hfsplus_extent resource_extents[8]; + grub_uint64_t size; + grub_uint64_t resource_size; + grub_uint32_t fileid; + grub_int32_t mtime; + int compressed; + char *cbuf; + void *file; + struct grub_hfsplus_compress_index *compress_index; + grub_uint32_t cbuf_block; + grub_uint32_t compress_index_size; +}; + +struct grub_hfsplus_btree +{ + grub_uint32_t root; + grub_size_t nodesize; + + /* Catalog file node. */ + struct grub_hfsplus_file file; +}; + +/* Information about a "mounted" HFS+ filesystem. */ +struct grub_hfsplus_data +{ + struct grub_hfsplus_volheader volheader; + grub_disk_t disk; + + unsigned int log2blksize; + + struct grub_hfsplus_btree catalog_tree; + struct grub_hfsplus_btree extoverflow_tree; + struct grub_hfsplus_btree attr_tree; + + int extoverflow_tree_ready; + + struct grub_hfsplus_file dirroot; + struct grub_hfsplus_file opened_file; + + /* This is the offset into the physical disk for an embedded HFS+ + filesystem (one inside a plain HFS wrapper). */ + grub_disk_addr_t embedded_offset; + int case_sensitive; +}; + +/* Internal representation of a catalog key. */ +struct grub_hfsplus_catkey_internal +{ + grub_uint32_t parent; + const grub_uint16_t *name; + grub_size_t namelen; +}; + +/* Internal representation of an extent overflow key. */ +struct grub_hfsplus_extkey_internal +{ + grub_uint32_t fileid; + grub_uint32_t start; + grub_uint8_t type; +}; + +struct grub_hfsplus_attrkey +{ + grub_uint16_t keylen; + grub_uint16_t unknown1[1]; + grub_uint32_t cnid; + grub_uint16_t unknown2[2]; + grub_uint16_t namelen; + grub_uint16_t name[0]; +} GRUB_PACKED; + +struct grub_hfsplus_attrkey_internal +{ + grub_uint32_t cnid; + const grub_uint16_t *name; + grub_size_t namelen; +}; + +struct grub_hfsplus_key_internal +{ + union + { + struct grub_hfsplus_extkey_internal extkey; + struct grub_hfsplus_catkey_internal catkey; + struct grub_hfsplus_attrkey_internal attrkey; + }; +}; + +/* The on disk layout of a catalog key. */ +struct grub_hfsplus_catkey +{ + grub_uint16_t keylen; + grub_uint32_t parent; + grub_uint16_t namelen; + grub_uint16_t name[0]; +} GRUB_PACKED; + +/* The on disk layout of an extent overflow file key. */ +struct grub_hfsplus_extkey +{ + grub_uint16_t keylen; + grub_uint8_t type; + grub_uint8_t unused; + grub_uint32_t fileid; + grub_uint32_t start; +} GRUB_PACKED; + +struct grub_hfsplus_key +{ + union + { + struct grub_hfsplus_extkey extkey; + struct grub_hfsplus_catkey catkey; + struct grub_hfsplus_attrkey attrkey; + grub_uint16_t keylen; + }; +} GRUB_PACKED; + +struct grub_hfsplus_btnode +{ + grub_uint32_t next; + grub_uint32_t prev; + grub_int8_t type; + grub_uint8_t height; + grub_uint16_t count; + grub_uint16_t unused; +} GRUB_PACKED; + +/* Return the offset of the record with the index INDEX, in the node + NODE which is part of the B+ tree BTREE. */ +static inline grub_uint16_t +grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, + struct grub_hfsplus_btnode *node, unsigned index) +{ + char *cnode = (char *) node; + void *recptr; + if (btree->nodesize < index * sizeof (grub_uint16_t) + 2) + index = 0; + recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); + return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); +} + +/* Return a pointer to the record with the index INDEX, in the node + NODE which is part of the B+ tree BTREE. */ +static inline struct grub_hfsplus_key * +grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, + struct grub_hfsplus_btnode *node, unsigned index) +{ + char *cnode = (char *) node; + grub_uint16_t offset; + offset = grub_hfsplus_btree_recoffset (btree, node, index); + if (offset > btree->nodesize - sizeof (struct grub_hfsplus_key)) + offset = 0; + return (struct grub_hfsplus_key *) &cnode[offset]; +} + +extern grub_err_t (*grub_hfsplus_open_compressed) (struct grub_hfsplus_file *node); +extern grub_ssize_t (*grub_hfsplus_read_compressed) (struct grub_hfsplus_file *node, + grub_off_t pos, + grub_size_t len, + char *buf); + +grub_ssize_t +grub_hfsplus_read_file (struct grub_hfsplus_file *node, + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_off_t pos, grub_size_t len, char *buf); +grub_err_t +grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, + struct grub_hfsplus_key_internal *key, + int (*compare_keys) (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb), + struct grub_hfsplus_btnode **matchnode, + grub_off_t *keyoffset); +grub_err_t +grub_mac_bless_inode (grub_device_t dev, grub_uint32_t inode, int is_dir, + int intel); +grub_err_t +grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel); |