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