| /* |
| * 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; |
| |
| 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); |