(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
jmicron_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  
      11  #include <stdio.h>
      12  #include <stdlib.h>
      13  #include <unistd.h>
      14  #include <string.h>
      15  #include <stdint.h>
      16  
      17  #include "superblocks.h"
      18  
      19  #define JM_SIGNATURE		"JM"
      20  #define JM_MINOR_VERSION(_x)	((_x)->version & 0xFF)
      21  #define JM_MAJOR_VERSION(_x)	((_x)->version >> 8)
      22  #define JM_SPARES		2
      23  #define JM_MEMBERS		8
      24  
      25  struct jm_metadata {
      26  	int8_t		signature[2];	/* 0x0 - 0x01 */
      27  
      28  	uint16_t	version;	/* 0x03 - 0x04 JMicron version */
      29  
      30  	uint16_t	checksum;	/* 0x04 - 0x05 */
      31  	uint8_t		filler[10];
      32  
      33  	uint32_t	identity;	/* 0x10 - 0x13 */
      34  
      35  	struct {
      36  		uint32_t	base;	/* 0x14 - 0x17 */
      37  		uint32_t	range;	/* 0x18 - 0x1B range */
      38  		uint16_t	range2;	/* 0x1C - 0x1D range2 */
      39  	} segment;
      40  
      41  	int8_t		name[16];	/* 0x20 - 0x2F */
      42  
      43  	uint8_t		mode;		/* 0x30 RAID level */
      44  	uint8_t		block;		/* 0x31 stride size (2=4K, 3=8K, ...) */
      45  	uint16_t	attribute;	/* 0x32 - 0x33 */
      46  	uint8_t		filler1[4];
      47  
      48  	uint32_t	spare[JM_SPARES];	/* 0x38 - 0x3F */
      49  	uint32_t	member[JM_MEMBERS];	/* 0x40 - 0x5F */
      50  
      51  	uint8_t		filler2[0x20];
      52  } __attribute__ ((packed));
      53  
      54  static void jm_to_cpu(struct jm_metadata *jm)
      55  {
      56  	unsigned int i;
      57  
      58  	jm->version = le16_to_cpu(jm->version);
      59  	jm->checksum = le16_to_cpu(jm->checksum);
      60  	jm->identity = le32_to_cpu(jm->identity);
      61  	jm->segment.base = le32_to_cpu(jm->segment.base);
      62  	jm->segment.range = le32_to_cpu(jm->segment.range);
      63  	jm->segment.range2 = le16_to_cpu(jm->segment.range2);
      64  
      65  	jm->attribute = le16_to_cpu(jm->attribute);
      66  
      67  	for (i = 0; i < JM_SPARES; i++)
      68  		jm->spare[i] = le32_to_cpu(jm->spare[i]);
      69  
      70  	for (i = 0; i < JM_MEMBERS; i++)
      71  		jm->member[i] = le32_to_cpu(jm->member[i]);
      72  }
      73  
      74  static int jm_checksum(const struct jm_metadata *jm)
      75  {
      76          size_t count = sizeof(*jm) / sizeof(uint16_t);
      77          uint16_t sum = 0;
      78          unsigned char *ptr = (unsigned char *) jm;
      79  
      80          while (count--) {
      81                  uint16_t val;
      82  
      83                  memcpy(&val, ptr, sizeof(uint16_t));
      84                  sum += le16_to_cpu(val);
      85  
      86                  ptr += sizeof(uint16_t);
      87          }
      88  
      89          return sum == 0 || sum == 1;
      90  }
      91  
      92  static int probe_jmraid(blkid_probe pr,
      93  		const struct blkid_idmag *mag __attribute__((__unused__)))
      94  {
      95  	uint64_t off;
      96  	struct jm_metadata *jm;
      97  
      98  	if (pr->size < 0x10000)
      99  		return 1;
     100  	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
     101  		return 1;
     102  
     103  	off = ((pr->size / 0x200) - 1) * 0x200;
     104  	jm = (struct jm_metadata *)
     105  		blkid_probe_get_buffer(pr,
     106  				off,
     107  				sizeof(struct jm_metadata));
     108  	if (!jm)
     109  		return errno ? -errno : 1;
     110  
     111  	if (memcmp(jm->signature, JM_SIGNATURE, sizeof(JM_SIGNATURE) - 1) != 0)
     112  		return 1;
     113  
     114  	if (!jm_checksum(jm))
     115  		return 1;
     116  
     117  	jm_to_cpu(jm);
     118  
     119  	if (jm->mode > 5)
     120  		return 1;
     121  
     122  	if (blkid_probe_sprintf_version(pr, "%u.%u",
     123  			JM_MAJOR_VERSION(jm), JM_MINOR_VERSION(jm)) != 0)
     124  		return 1;
     125  	if (blkid_probe_set_magic(pr, off, sizeof(jm->signature),
     126  				(unsigned char *) jm->signature))
     127  		return 1;
     128  	return 0;
     129  }
     130  
     131  const struct blkid_idinfo jmraid_idinfo = {
     132  	.name		= "jmicron_raid_member",
     133  	.usage		= BLKID_USAGE_RAID,
     134  	.probefunc	= probe_jmraid,
     135  	.magics		= BLKID_NONE_MAGIC
     136  };