162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/fs/hfs/part_tbl.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1996-1997 Paul H. Hargrove 562306a36Sopenharmony_ci * (C) 2003 Ardis Technologies <roman@ardistech.com> 662306a36Sopenharmony_ci * This file may be distributed under the terms of 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 1262306a36Sopenharmony_ci#include "hfs_fs.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * The new style Mac partition map 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * For each partition on the media there is a physical block (512-byte 1862306a36Sopenharmony_ci * block) containing one of these structures. These blocks are 1962306a36Sopenharmony_ci * contiguous starting at block 1. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_cistruct new_pmap { 2262306a36Sopenharmony_ci __be16 pmSig; /* signature */ 2362306a36Sopenharmony_ci __be16 reSigPad; /* padding */ 2462306a36Sopenharmony_ci __be32 pmMapBlkCnt; /* partition blocks count */ 2562306a36Sopenharmony_ci __be32 pmPyPartStart; /* physical block start of partition */ 2662306a36Sopenharmony_ci __be32 pmPartBlkCnt; /* physical block count of partition */ 2762306a36Sopenharmony_ci u8 pmPartName[32]; /* (null terminated?) string 2862306a36Sopenharmony_ci giving the name of this 2962306a36Sopenharmony_ci partition */ 3062306a36Sopenharmony_ci u8 pmPartType[32]; /* (null terminated?) string 3162306a36Sopenharmony_ci giving the type of this 3262306a36Sopenharmony_ci partition */ 3362306a36Sopenharmony_ci /* a bunch more stuff we don't need */ 3462306a36Sopenharmony_ci} __packed; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * The old style Mac partition map 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * The partition map consists for a 2-byte signature followed by an 4062306a36Sopenharmony_ci * array of these structures. The map is terminated with an all-zero 4162306a36Sopenharmony_ci * one of these. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_cistruct old_pmap { 4462306a36Sopenharmony_ci __be16 pdSig; /* Signature bytes */ 4562306a36Sopenharmony_ci struct old_pmap_entry { 4662306a36Sopenharmony_ci __be32 pdStart; 4762306a36Sopenharmony_ci __be32 pdSize; 4862306a36Sopenharmony_ci __be32 pdFSID; 4962306a36Sopenharmony_ci } pdEntry[42]; 5062306a36Sopenharmony_ci} __packed; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* 5362306a36Sopenharmony_ci * hfs_part_find() 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * Parse the partition map looking for the 5662306a36Sopenharmony_ci * start and length of the 'part'th HFS partition. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ciint hfs_part_find(struct super_block *sb, 5962306a36Sopenharmony_ci sector_t *part_start, sector_t *part_size) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct buffer_head *bh; 6262306a36Sopenharmony_ci __be16 *data; 6362306a36Sopenharmony_ci int i, size, res; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci res = -ENOENT; 6662306a36Sopenharmony_ci bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data); 6762306a36Sopenharmony_ci if (!bh) 6862306a36Sopenharmony_ci return -EIO; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci switch (be16_to_cpu(*data)) { 7162306a36Sopenharmony_ci case HFS_OLD_PMAP_MAGIC: 7262306a36Sopenharmony_ci { 7362306a36Sopenharmony_ci struct old_pmap *pm; 7462306a36Sopenharmony_ci struct old_pmap_entry *p; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci pm = (struct old_pmap *)bh->b_data; 7762306a36Sopenharmony_ci p = pm->pdEntry; 7862306a36Sopenharmony_ci size = 42; 7962306a36Sopenharmony_ci for (i = 0; i < size; p++, i++) { 8062306a36Sopenharmony_ci if (p->pdStart && p->pdSize && 8162306a36Sopenharmony_ci p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && 8262306a36Sopenharmony_ci (HFS_SB(sb)->part < 0 || HFS_SB(sb)->part == i)) { 8362306a36Sopenharmony_ci *part_start += be32_to_cpu(p->pdStart); 8462306a36Sopenharmony_ci *part_size = be32_to_cpu(p->pdSize); 8562306a36Sopenharmony_ci res = 0; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci case HFS_NEW_PMAP_MAGIC: 9162306a36Sopenharmony_ci { 9262306a36Sopenharmony_ci struct new_pmap *pm; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci pm = (struct new_pmap *)bh->b_data; 9562306a36Sopenharmony_ci size = be32_to_cpu(pm->pmMapBlkCnt); 9662306a36Sopenharmony_ci for (i = 0; i < size;) { 9762306a36Sopenharmony_ci if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && 9862306a36Sopenharmony_ci (HFS_SB(sb)->part < 0 || HFS_SB(sb)->part == i)) { 9962306a36Sopenharmony_ci *part_start += be32_to_cpu(pm->pmPyPartStart); 10062306a36Sopenharmony_ci *part_size = be32_to_cpu(pm->pmPartBlkCnt); 10162306a36Sopenharmony_ci res = 0; 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci brelse(bh); 10562306a36Sopenharmony_ci bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm); 10662306a36Sopenharmony_ci if (!bh) 10762306a36Sopenharmony_ci return -EIO; 10862306a36Sopenharmony_ci if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC)) 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci brelse(bh); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci return res; 11762306a36Sopenharmony_ci} 118