1 /* 2 * linux/fs/hfsplus/part_tbl.c 3 * 4 * Copyright (C) 1996-1997 Paul H. Hargrove 5 * This file may be distributed under the terms of the GNU General Public License. 6 * 7 * Original code to handle the new style Mac partition table based on 8 * a patch contributed by Holger Schemel (aeglos@valinor.owl.de). 9 * 10 * In function preconditions the term "valid" applied to a pointer to 11 * a structure means that the pointer is non-NULL and the structure it 12 * points to has all fields initialized to consistent values. 13 * 14 */ 15 16 #include "hfsplus_fs.h" 17 18 /* offsets to various blocks */ 19 #define HFS_DD_BLK 0 /* Driver Descriptor block */ 20 #define HFS_PMAP_BLK 1 /* First block of partition map */ 21 #define HFS_MDB_BLK 2 /* Block (w/i partition) of MDB */ 22 23 /* magic numbers for various disk blocks */ 24 #define HFS_DRVR_DESC_MAGIC 0x4552 /* "ER": driver descriptor map */ 25 #define HFS_OLD_PMAP_MAGIC 0x5453 /* "TS": old-type partition map */ 26 #define HFS_NEW_PMAP_MAGIC 0x504D /* "PM": new-type partition map */ 27 #define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ 28 #define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ 29 30 /* 31 * The new style Mac partition map 32 * 33 * For each partition on the media there is a physical block (512-byte 34 * block) containing one of these structures. These blocks are 35 * contiguous starting at block 1. 36 */ 37 struct new_pmap { 38 __be16 pmSig; /* signature */ 39 __be16 reSigPad; /* padding */ 40 __be32 pmMapBlkCnt; /* partition blocks count */ 41 __be32 pmPyPartStart; /* physical block start of partition */ 42 __be32 pmPartBlkCnt; /* physical block count of partition */ 43 u8 pmPartName[32]; /* (null terminated?) string 44 giving the name of this 45 partition */ 46 u8 pmPartType[32]; /* (null terminated?) string 47 giving the type of this 48 partition */ 49 /* a bunch more stuff we don't need */ 50 } __packed; 51 52 /* 53 * The old style Mac partition map 54 * 55 * The partition map consists for a 2-byte signature followed by an 56 * array of these structures. The map is terminated with an all-zero 57 * one of these. 58 */ 59 struct old_pmap { 60 __be16 pdSig; /* Signature bytes */ 61 struct old_pmap_entry { 62 __be32 pdStart; 63 __be32 pdSize; 64 __be32 pdFSID; 65 } pdEntry[42]; 66 } __packed; 67 68 /* 69 * hfs_part_find() 70 * 71 * Parse the partition map looking for the 72 * start and length of the 'part'th HFS partition. 73 */ 74 int hfs_part_find(struct super_block *sb, 75 sector_t *part_start, sector_t *part_size) 76 { 77 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 78 struct buffer_head *bh; 79 __be16 *data; 80 int i, size, res; 81 82 res = -ENOENT; 83 bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data); 84 if (!bh) 85 return -EIO; 86 87 switch (be16_to_cpu(*data)) { 88 case HFS_OLD_PMAP_MAGIC: 89 { 90 struct old_pmap *pm; 91 struct old_pmap_entry *p; 92 93 pm = (struct old_pmap *)bh->b_data; 94 p = pm->pdEntry; 95 size = 42; 96 for (i = 0; i < size; p++, i++) { 97 if (p->pdStart && p->pdSize && 98 p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && 99 (sbi->part < 0 || sbi->part == i)) { 100 *part_start += be32_to_cpu(p->pdStart); 101 *part_size = be32_to_cpu(p->pdSize); 102 res = 0; 103 } 104 } 105 break; 106 } 107 case HFS_NEW_PMAP_MAGIC: 108 { 109 struct new_pmap *pm; 110 111 pm = (struct new_pmap *)bh->b_data; 112 size = be32_to_cpu(pm->pmMapBlkCnt); 113 for (i = 0; i < size;) { 114 if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && 115 (sbi->part < 0 || sbi->part == i)) { 116 *part_start += be32_to_cpu(pm->pmPyPartStart); 117 *part_size = be32_to_cpu(pm->pmPartBlkCnt); 118 res = 0; 119 break; 120 } 121 brelse(bh); 122 bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm); 123 if (!bh) 124 return -EIO; 125 if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC)) 126 break; 127 } 128 break; 129 } 130 } 131 brelse(bh); 132 133 return res; 134 } 135