0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/slab.h>
0018 #include "hfsplus_fs.h"
0019
0020
0021 #define HFS_DD_BLK 0
0022 #define HFS_PMAP_BLK 1
0023 #define HFS_MDB_BLK 2
0024
0025
0026 #define HFS_DRVR_DESC_MAGIC 0x4552
0027 #define HFS_OLD_PMAP_MAGIC 0x5453
0028 #define HFS_NEW_PMAP_MAGIC 0x504D
0029 #define HFS_SUPER_MAGIC 0x4244
0030 #define HFS_MFS_SUPER_MAGIC 0xD2D7
0031
0032
0033
0034
0035
0036
0037
0038
0039 struct new_pmap {
0040 __be16 pmSig;
0041 __be16 reSigPad;
0042 __be32 pmMapBlkCnt;
0043 __be32 pmPyPartStart;
0044 __be32 pmPartBlkCnt;
0045 u8 pmPartName[32];
0046
0047
0048 u8 pmPartType[32];
0049
0050
0051
0052 } __packed;
0053
0054
0055
0056
0057
0058
0059
0060
0061 struct old_pmap {
0062 __be16 pdSig;
0063 struct old_pmap_entry {
0064 __be32 pdStart;
0065 __be32 pdSize;
0066 __be32 pdFSID;
0067 } pdEntry[42];
0068 } __packed;
0069
0070 static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
0071 sector_t *part_start, sector_t *part_size)
0072 {
0073 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
0074 int i;
0075
0076 for (i = 0; i < 42; i++) {
0077 struct old_pmap_entry *p = &pm->pdEntry[i];
0078
0079 if (p->pdStart && p->pdSize &&
0080 p->pdFSID == cpu_to_be32(0x54465331) &&
0081 (sbi->part < 0 || sbi->part == i)) {
0082 *part_start += be32_to_cpu(p->pdStart);
0083 *part_size = be32_to_cpu(p->pdSize);
0084 return 0;
0085 }
0086 }
0087
0088 return -ENOENT;
0089 }
0090
0091 static int hfs_parse_new_pmap(struct super_block *sb, void *buf,
0092 struct new_pmap *pm, sector_t *part_start, sector_t *part_size)
0093 {
0094 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
0095 int size = be32_to_cpu(pm->pmMapBlkCnt);
0096 int buf_size = hfsplus_min_io_size(sb);
0097 int res;
0098 int i = 0;
0099
0100 do {
0101 if (!memcmp(pm->pmPartType, "Apple_HFS", 9) &&
0102 (sbi->part < 0 || sbi->part == i)) {
0103 *part_start += be32_to_cpu(pm->pmPyPartStart);
0104 *part_size = be32_to_cpu(pm->pmPartBlkCnt);
0105 return 0;
0106 }
0107
0108 if (++i >= size)
0109 return -ENOENT;
0110
0111 pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE);
0112 if ((u8 *)pm - (u8 *)buf >= buf_size) {
0113 res = hfsplus_submit_bio(sb,
0114 *part_start + HFS_PMAP_BLK + i,
0115 buf, (void **)&pm, REQ_OP_READ);
0116 if (res)
0117 return res;
0118 }
0119 } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
0120
0121 return -ENOENT;
0122 }
0123
0124
0125
0126
0127
0128 int hfs_part_find(struct super_block *sb,
0129 sector_t *part_start, sector_t *part_size)
0130 {
0131 void *buf, *data;
0132 int res;
0133
0134 buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
0135 if (!buf)
0136 return -ENOMEM;
0137
0138 res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK,
0139 buf, &data, REQ_OP_READ);
0140 if (res)
0141 goto out;
0142
0143 switch (be16_to_cpu(*((__be16 *)data))) {
0144 case HFS_OLD_PMAP_MAGIC:
0145 res = hfs_parse_old_pmap(sb, data, part_start, part_size);
0146 break;
0147 case HFS_NEW_PMAP_MAGIC:
0148 res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size);
0149 break;
0150 default:
0151 res = -ENOENT;
0152 break;
0153 }
0154 out:
0155 kfree(buf);
0156 return res;
0157 }