(root)/
util-linux-2.39/
libblkid/
src/
partitions/
mac.c
       1  /*
       2   * mac partitions parsing code
       3   *
       4   * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
       5   *
       6   * This file may be redistributed under the terms of the
       7   * GNU Lesser General Public License.
       8   *
       9   */
      10  #include <stdio.h>
      11  #include <string.h>
      12  #include <stdlib.h>
      13  #include <stdint.h>
      14  
      15  #include "partitions.h"
      16  
      17  #define MAC_PARTITION_MAGIC		0x504d
      18  #define MAC_PARTITION_MAGIC_OLD		0x5453
      19  
      20  /*
      21   * Mac partition entry
      22   * http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-126.html
      23   */
      24  struct mac_partition {
      25  	uint16_t	signature;	/* expected to be MAC_PARTITION_MAGIC */
      26  	uint16_t	reserved;	/* reserved */
      27  	uint32_t	map_count;	/* # blocks in partition map */
      28  	uint32_t	start_block;	/* absolute starting block # of partition */
      29  	uint32_t	block_count;	/* number of blocks in partition */
      30  	char		name[32];	/* partition name */
      31  	char		type[32];	/* string type description */
      32  	uint32_t	data_start;	/* rel block # of first data block */
      33  	uint32_t	data_count;	/* number of data blocks */
      34  	uint32_t	status;		/* partition status bits */
      35  	uint32_t	boot_start;	/* first logical block of boot code */
      36  	uint32_t	boot_size;	/* size of boot code, in bytes */
      37  	uint32_t	boot_load;	/* boot code load address */
      38  	uint32_t	boot_load2;	/* reserved */
      39  	uint32_t	boot_entry;	/* boot code entry point */
      40  	uint32_t	boot_entry2;	/* reserved */
      41  	uint32_t	boot_cksum;	/* boot code checksum */
      42  	char		processor[16];	/* identifies ISA of boot */
      43  
      44  	/* there is more stuff after this that we don't need */
      45  } __attribute__((packed));
      46  
      47  /*
      48   * Driver descriptor structure, in block 0
      49   * http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-121.html
      50   */
      51  struct mac_driver_desc {
      52  	uint16_t	signature;	/* expected to be MAC_DRIVER_MAGIC */
      53  	uint16_t	block_size;	/* block size of the device */
      54  	uint32_t	block_count;	/* number of blocks on the device */
      55  
      56  	/* there is more stuff after this that we don't need */
      57  } __attribute__((packed));
      58  
      59  static inline unsigned char *get_mac_block(
      60  					blkid_probe pr,
      61  					uint16_t block_size,
      62  					uint32_t num)
      63  {
      64  	return blkid_probe_get_buffer(pr, (uint64_t) num * block_size, block_size);
      65  }
      66  
      67  static inline int has_part_signature(struct mac_partition *p)
      68  {
      69  	return	be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC ||
      70  		be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC_OLD;
      71  }
      72  
      73  static int probe_mac_pt(blkid_probe pr,
      74  		const struct blkid_idmag *mag __attribute__((__unused__)))
      75  {
      76  	struct mac_driver_desc *md;
      77  	struct mac_partition *p;
      78  	blkid_parttable tab = NULL;
      79  	blkid_partlist ls;
      80  	uint16_t block_size;
      81  	uint16_t ssf;	/* sector size fragment */
      82  	uint32_t nblks, nprts, i;
      83  
      84  
      85  	/* The driver descriptor record is always located at physical block 0,
      86  	 * the first block on the disk.
      87  	 */
      88  	md = (struct mac_driver_desc *) blkid_probe_get_sector(pr, 0);
      89  	if (!md) {
      90  		if (errno)
      91  			return -errno;
      92  		goto nothing;
      93  	}
      94  
      95  	block_size = be16_to_cpu(md->block_size);
      96  	if (block_size < sizeof(struct mac_partition))
      97  		goto nothing;
      98  
      99  	/* The partition map always begins at physical block 1,
     100  	 * the second block on the disk.
     101  	 */
     102  	p = (struct mac_partition *) get_mac_block(pr, block_size, 1);
     103  	if (!p) {
     104  		if (errno)
     105  			return -errno;
     106  		goto nothing;
     107  	}
     108  
     109  	/* check the first partition signature */
     110  	if (!has_part_signature(p))
     111  		goto nothing;
     112  
     113  	if (blkid_partitions_need_typeonly(pr))
     114  		/* caller does not ask for details about partitions */
     115  		return 0;
     116  
     117  	ls = blkid_probe_get_partlist(pr);
     118  	if (!ls)
     119  		goto nothing;
     120  
     121  	tab = blkid_partlist_new_parttable(ls, "mac", 0);
     122  	if (!tab)
     123  		goto err;
     124  
     125  	ssf = block_size / 512;
     126  	nblks = be32_to_cpu(p->map_count);
     127  	if (nblks > 256) {
     128  		nprts = 256;
     129  		DBG(LOWPROBE, ul_debug(
     130  			"mac: map_count too large, entry[0]: %u, "
     131  			"enforcing limit of %u", nblks, nprts));
     132  	} else
     133  		nprts = nblks;
     134  
     135  	for (i = 0; i < nprts; ++i) {
     136  		blkid_partition par;
     137  		uint32_t start;
     138  		uint32_t size;
     139  
     140  		p = (struct mac_partition *) get_mac_block(pr, block_size, i + 1);
     141  		if (!p) {
     142  			if (errno)
     143  				return -errno;
     144  			goto nothing;
     145  		}
     146  		if (!has_part_signature(p))
     147  			goto nothing;
     148  
     149  		if (be32_to_cpu(p->map_count) != nblks) {
     150  			DBG(LOWPROBE, ul_debug(
     151  				"mac: inconsistent map_count in partition map, "
     152  				"entry[0]: %u, entry[%u]: %u",
     153  				nblks, i,
     154  				be32_to_cpu(p->map_count)));
     155  		}
     156  
     157  		/*
     158  		 * note that libparted ignores some mac partitions according to
     159  		 * the partition name (e.g. "Apple_Free" or "Apple_Void"). We
     160  		 * follows Linux kernel and all partitions are visible
     161  		 */
     162  
     163  		start = be32_to_cpu(p->start_block) * ssf;
     164  		size = be32_to_cpu(p->block_count) * ssf;
     165  
     166  		par = blkid_partlist_add_partition(ls, tab, start, size);
     167  		if (!par)
     168  			goto err;
     169  
     170  		blkid_partition_set_name(par, (unsigned char *) p->name,
     171  						sizeof(p->name));
     172  
     173  		blkid_partition_set_type_string(par, (unsigned char *) p->type,
     174  						sizeof(p->type));
     175  	}
     176  
     177  	return BLKID_PROBE_OK;
     178  
     179  nothing:
     180  	return BLKID_PROBE_NONE;
     181  err:
     182  	return -ENOMEM;
     183  }
     184  
     185  /*
     186   * Mac disk always begin with "Driver Descriptor Record"
     187   * (struct mac_driver_desc) and magic 0x4552.
     188   */
     189  const struct blkid_idinfo mac_pt_idinfo =
     190  {
     191  	.name		= "mac",
     192  	.probefunc	= probe_mac_pt,
     193  	.magics		=
     194  	{
     195  		/* big-endian magic string */
     196  		{ .magic = "\x45\x52", .len = 2 },
     197  		{ NULL }
     198  	}
     199  };
     200