part_tbl.c 4.0 KB

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