part_tbl.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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, void *buf,
  82. struct new_pmap *pm, 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 buf_size = hfsplus_min_io_size(sb);
  87. int res;
  88. int i = 0;
  89. do {
  90. if (!memcmp(pm->pmPartType, "Apple_HFS", 9) &&
  91. (sbi->part < 0 || sbi->part == i)) {
  92. *part_start += be32_to_cpu(pm->pmPyPartStart);
  93. *part_size = be32_to_cpu(pm->pmPartBlkCnt);
  94. return 0;
  95. }
  96. if (++i >= size)
  97. return -ENOENT;
  98. pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE);
  99. if ((u8 *)pm - (u8 *)buf >= buf_size) {
  100. res = hfsplus_submit_bio(sb,
  101. *part_start + HFS_PMAP_BLK + i,
  102. buf, (void **)&pm, READ);
  103. if (res)
  104. return res;
  105. }
  106. } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
  107. return -ENOENT;
  108. }
  109. /*
  110. * Parse the partition map looking for the start and length of a
  111. * HFS/HFS+ partition.
  112. */
  113. int hfs_part_find(struct super_block *sb,
  114. sector_t *part_start, sector_t *part_size)
  115. {
  116. void *buf, *data;
  117. int res;
  118. buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
  119. if (!buf)
  120. return -ENOMEM;
  121. res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK,
  122. buf, &data, READ);
  123. if (res)
  124. goto out;
  125. switch (be16_to_cpu(*((__be16 *)data))) {
  126. case HFS_OLD_PMAP_MAGIC:
  127. res = hfs_parse_old_pmap(sb, data, part_start, part_size);
  128. break;
  129. case HFS_NEW_PMAP_MAGIC:
  130. res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size);
  131. break;
  132. default:
  133. res = -ENOENT;
  134. break;
  135. }
  136. out:
  137. kfree(buf);
  138. return res;
  139. }