(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
ddf_raid.c
       1  /*
       2   * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
       3   *
       4   * Inspired by libvolume_id by
       5   *     Kay Sievers <kay.sievers@vrfy.org>
       6   *
       7   * This file may be redistributed under the terms of the
       8   * GNU Lesser General Public License.
       9   */
      10  #include <stdio.h>
      11  #include <stdlib.h>
      12  #include <unistd.h>
      13  #include <string.h>
      14  #include <stdint.h>
      15  
      16  #include "superblocks.h"
      17  
      18  /* http://www.snia.org/standards/home */
      19  #define DDF_GUID_LENGTH			24
      20  #define DDF_REV_LENGTH			8
      21  #define DDF_MAGIC			0xDE11DE11
      22  
      23  
      24  struct ddf_header {
      25  	uint32_t	signature;
      26  	uint32_t	crc;
      27  	uint8_t		guid[DDF_GUID_LENGTH];
      28  	char		ddf_rev[8];	/* 01.02.00 */
      29  	uint32_t	seq;		/* starts at '1' */
      30  	uint32_t	timestamp;
      31  	uint8_t		openflag;
      32  	uint8_t		foreignflag;
      33  	uint8_t		enforcegroups;
      34  	uint8_t		pad0;		/* 0xff */
      35  	uint8_t		pad1[12];	/* 12 * 0xff */
      36  	/* 64 bytes so far */
      37  	uint8_t		header_ext[32];	/* reserved: fill with 0xff */
      38  	uint64_t	primary_lba;
      39  	uint64_t	secondary_lba;
      40  	uint8_t		type;
      41  	uint8_t		pad2[3];	/* 0xff */
      42  	uint32_t	workspace_len;	/* sectors for vendor space -
      43  					 * at least 32768(sectors) */
      44  	uint64_t	workspace_lba;
      45  	uint16_t	max_pd_entries;	/* one of 15, 63, 255, 1023, 4095 */
      46  	uint16_t	max_vd_entries; /* 2^(4,6,8,10,12)-1 : i.e. as above */
      47  	uint16_t	max_partitions; /* i.e. max num of configuration
      48  					   record entries per disk */
      49  	uint16_t	config_record_len; /* 1 +ROUNDUP(max_primary_element_entries
      50  				           *12/512) */
      51  	uint16_t	max_primary_element_entries; /* 16, 64, 256, 1024, or 4096 */
      52  	uint8_t		pad3[54];	/* 0xff */
      53  	/* 192 bytes so far */
      54  	uint32_t	controller_section_offset;
      55  	uint32_t	controller_section_length;
      56  	uint32_t	phys_section_offset;
      57  	uint32_t	phys_section_length;
      58  	uint32_t	virt_section_offset;
      59  	uint32_t	virt_section_length;
      60  	uint32_t	config_section_offset;
      61  	uint32_t	config_section_length;
      62  	uint32_t	data_section_offset;
      63  	uint32_t	data_section_length;
      64  	uint32_t	bbm_section_offset;
      65  	uint32_t	bbm_section_length;
      66  	uint32_t	diag_space_offset;
      67  	uint32_t	diag_space_length;
      68  	uint32_t	vendor_offset;
      69  	uint32_t	vendor_length;
      70  	/* 256 bytes so far */
      71  	uint8_t		pad4[256];	/* 0xff */
      72  } __attribute__((packed));
      73  
      74  static int probe_ddf(blkid_probe pr,
      75  		const struct blkid_idmag *mag __attribute__((__unused__)))
      76  {
      77  	int hdrs[] = { 1, 257 };
      78  	size_t i;
      79  	struct ddf_header *ddf = NULL;
      80  	char version[DDF_REV_LENGTH + 1];
      81  	uint64_t off = 0, lba;
      82  
      83  	if (pr->size < 0x30000)
      84  		return 1;
      85  
      86  	for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
      87  		off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
      88  
      89  		ddf = (struct ddf_header *) blkid_probe_get_buffer(pr,
      90  					off,
      91  					sizeof(struct ddf_header));
      92  		if (!ddf)
      93  			return errno ? -errno : 1;
      94  		if (ddf->signature == cpu_to_be32(DDF_MAGIC) ||
      95  		    ddf->signature == cpu_to_le32(DDF_MAGIC))
      96  			break;
      97  		ddf = NULL;
      98  	}
      99  
     100  	if (!ddf)
     101  		return 1;
     102  
     103  	lba = ddf->signature == cpu_to_be32(DDF_MAGIC) ?
     104  			be64_to_cpu(ddf->primary_lba) :
     105  			le64_to_cpu(ddf->primary_lba);
     106  
     107  	if (lba > 0) {
     108  		/* check primary header */
     109  		unsigned char *buf;
     110  
     111  		buf = blkid_probe_get_buffer(pr,
     112  					lba << 9, sizeof(ddf->signature));
     113  		if (!buf)
     114  			return errno ? -errno : 1;
     115  
     116  		if (memcmp(buf, &ddf->signature, 4) != 0)
     117  			return 1;
     118  	}
     119  
     120  	blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
     121  
     122  	memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
     123  	*(version + sizeof(ddf->ddf_rev)) = '\0';
     124  
     125  	if (blkid_probe_set_version(pr, version) != 0)
     126  		return 1;
     127  	if (blkid_probe_set_magic(pr, off,
     128  			sizeof(ddf->signature),
     129  			(unsigned char *) &ddf->signature))
     130  		return 1;
     131  	return 0;
     132  }
     133  
     134  const struct blkid_idinfo ddfraid_idinfo = {
     135  	.name		= "ddf_raid_member",
     136  	.usage		= BLKID_USAGE_RAID,
     137  	.probefunc	= probe_ddf,
     138  	.magics		= BLKID_NONE_MAGIC
     139  };
     140  
     141