162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/fs/hfsplus/part_tbl.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1996-1997 Paul H. Hargrove 562306a36Sopenharmony_ci * This file may be distributed under the terms of 662306a36Sopenharmony_ci * the GNU General Public License. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Original code to handle the new style Mac partition table based on 962306a36Sopenharmony_ci * a patch contributed by Holger Schemel (aeglos@valinor.owl.de). 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * In function preconditions the term "valid" applied to a pointer to 1262306a36Sopenharmony_ci * a structure means that the pointer is non-NULL and the structure it 1362306a36Sopenharmony_ci * points to has all fields initialized to consistent values. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/slab.h> 1862306a36Sopenharmony_ci#include "hfsplus_fs.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* offsets to various blocks */ 2162306a36Sopenharmony_ci#define HFS_DD_BLK 0 /* Driver Descriptor block */ 2262306a36Sopenharmony_ci#define HFS_PMAP_BLK 1 /* First block of partition map */ 2362306a36Sopenharmony_ci#define HFS_MDB_BLK 2 /* Block (w/i partition) of MDB */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* magic numbers for various disk blocks */ 2662306a36Sopenharmony_ci#define HFS_DRVR_DESC_MAGIC 0x4552 /* "ER": driver descriptor map */ 2762306a36Sopenharmony_ci#define HFS_OLD_PMAP_MAGIC 0x5453 /* "TS": old-type partition map */ 2862306a36Sopenharmony_ci#define HFS_NEW_PMAP_MAGIC 0x504D /* "PM": new-type partition map */ 2962306a36Sopenharmony_ci#define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ 3062306a36Sopenharmony_ci#define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * The new style Mac partition map 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * For each partition on the media there is a physical block (512-byte 3662306a36Sopenharmony_ci * block) containing one of these structures. These blocks are 3762306a36Sopenharmony_ci * contiguous starting at block 1. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_cistruct new_pmap { 4062306a36Sopenharmony_ci __be16 pmSig; /* signature */ 4162306a36Sopenharmony_ci __be16 reSigPad; /* padding */ 4262306a36Sopenharmony_ci __be32 pmMapBlkCnt; /* partition blocks count */ 4362306a36Sopenharmony_ci __be32 pmPyPartStart; /* physical block start of partition */ 4462306a36Sopenharmony_ci __be32 pmPartBlkCnt; /* physical block count of partition */ 4562306a36Sopenharmony_ci u8 pmPartName[32]; /* (null terminated?) string 4662306a36Sopenharmony_ci giving the name of this 4762306a36Sopenharmony_ci partition */ 4862306a36Sopenharmony_ci u8 pmPartType[32]; /* (null terminated?) string 4962306a36Sopenharmony_ci giving the type of this 5062306a36Sopenharmony_ci partition */ 5162306a36Sopenharmony_ci /* a bunch more stuff we don't need */ 5262306a36Sopenharmony_ci} __packed; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* 5562306a36Sopenharmony_ci * The old style Mac partition map 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * The partition map consists for a 2-byte signature followed by an 5862306a36Sopenharmony_ci * array of these structures. The map is terminated with an all-zero 5962306a36Sopenharmony_ci * one of these. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistruct old_pmap { 6262306a36Sopenharmony_ci __be16 pdSig; /* Signature bytes */ 6362306a36Sopenharmony_ci struct old_pmap_entry { 6462306a36Sopenharmony_ci __be32 pdStart; 6562306a36Sopenharmony_ci __be32 pdSize; 6662306a36Sopenharmony_ci __be32 pdFSID; 6762306a36Sopenharmony_ci } pdEntry[42]; 6862306a36Sopenharmony_ci} __packed; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, 7162306a36Sopenharmony_ci sector_t *part_start, sector_t *part_size) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 7462306a36Sopenharmony_ci int i; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci for (i = 0; i < 42; i++) { 7762306a36Sopenharmony_ci struct old_pmap_entry *p = &pm->pdEntry[i]; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (p->pdStart && p->pdSize && 8062306a36Sopenharmony_ci p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && 8162306a36Sopenharmony_ci (sbi->part < 0 || sbi->part == i)) { 8262306a36Sopenharmony_ci *part_start += be32_to_cpu(p->pdStart); 8362306a36Sopenharmony_ci *part_size = be32_to_cpu(p->pdSize); 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return -ENOENT; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int hfs_parse_new_pmap(struct super_block *sb, void *buf, 9262306a36Sopenharmony_ci struct new_pmap *pm, sector_t *part_start, sector_t *part_size) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 9562306a36Sopenharmony_ci int size = be32_to_cpu(pm->pmMapBlkCnt); 9662306a36Sopenharmony_ci int buf_size = hfsplus_min_io_size(sb); 9762306a36Sopenharmony_ci int res; 9862306a36Sopenharmony_ci int i = 0; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci do { 10162306a36Sopenharmony_ci if (!memcmp(pm->pmPartType, "Apple_HFS", 9) && 10262306a36Sopenharmony_ci (sbi->part < 0 || sbi->part == i)) { 10362306a36Sopenharmony_ci *part_start += be32_to_cpu(pm->pmPyPartStart); 10462306a36Sopenharmony_ci *part_size = be32_to_cpu(pm->pmPartBlkCnt); 10562306a36Sopenharmony_ci return 0; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (++i >= size) 10962306a36Sopenharmony_ci return -ENOENT; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); 11262306a36Sopenharmony_ci if ((u8 *)pm - (u8 *)buf >= buf_size) { 11362306a36Sopenharmony_ci res = hfsplus_submit_bio(sb, 11462306a36Sopenharmony_ci *part_start + HFS_PMAP_BLK + i, 11562306a36Sopenharmony_ci buf, (void **)&pm, REQ_OP_READ); 11662306a36Sopenharmony_ci if (res) 11762306a36Sopenharmony_ci return res; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return -ENOENT; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* 12562306a36Sopenharmony_ci * Parse the partition map looking for the start and length of a 12662306a36Sopenharmony_ci * HFS/HFS+ partition. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ciint hfs_part_find(struct super_block *sb, 12962306a36Sopenharmony_ci sector_t *part_start, sector_t *part_size) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci void *buf, *data; 13262306a36Sopenharmony_ci int res; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); 13562306a36Sopenharmony_ci if (!buf) 13662306a36Sopenharmony_ci return -ENOMEM; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, 13962306a36Sopenharmony_ci buf, &data, REQ_OP_READ); 14062306a36Sopenharmony_ci if (res) 14162306a36Sopenharmony_ci goto out; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci switch (be16_to_cpu(*((__be16 *)data))) { 14462306a36Sopenharmony_ci case HFS_OLD_PMAP_MAGIC: 14562306a36Sopenharmony_ci res = hfs_parse_old_pmap(sb, data, part_start, part_size); 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci case HFS_NEW_PMAP_MAGIC: 14862306a36Sopenharmony_ci res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci default: 15162306a36Sopenharmony_ci res = -ENOENT; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ciout: 15562306a36Sopenharmony_ci kfree(buf); 15662306a36Sopenharmony_ci return res; 15762306a36Sopenharmony_ci} 158