(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
silicon_raid.c
       1  /*
       2   * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
       3   * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
       4   *
       5   * Inspired by libvolume_id by
       6   *     Kay Sievers <kay.sievers@vrfy.org>
       7   *
       8   * This file may be redistributed under the terms of the
       9   * GNU Lesser General Public License.
      10   */
      11  #include <stdio.h>
      12  #include <stdlib.h>
      13  #include <unistd.h>
      14  #include <string.h>
      15  #include <errno.h>
      16  #include <ctype.h>
      17  #include <stdint.h>
      18  #include <stddef.h>
      19  
      20  #include "superblocks.h"
      21  
      22  struct silicon_metadata {
      23  	uint8_t		unknown0[0x2E];
      24  	uint8_t		ascii_version[0x36 - 0x2E];
      25  	int8_t		diskname[0x56 - 0x36];
      26  	int8_t		unknown1[0x60 - 0x56];
      27  	uint32_t	magic;
      28  	int8_t		unknown1a[0x6C - 0x64];
      29  	uint32_t	array_sectors_low;
      30  	uint32_t	array_sectors_high;
      31  	int8_t		unknown2[0x78 - 0x74];
      32  	uint32_t	thisdisk_sectors;
      33  	int8_t		unknown3[0x100 - 0x7C];
      34  	int8_t		unknown4[0x104 - 0x100];
      35  	uint16_t	product_id;
      36  	uint16_t	vendor_id;
      37  	uint16_t	minor_ver;
      38  	uint16_t	major_ver;
      39  	uint8_t		seconds;
      40  	uint8_t		minutes;
      41  	uint8_t		hour;
      42  	uint8_t		day;
      43  	uint8_t		month;
      44  	uint8_t		year;
      45  	uint16_t	raid0_stride;
      46  	int8_t		unknown6[0x116 - 0x114];
      47  	uint8_t		disk_number;
      48  	uint8_t		type;			/* SILICON_TYPE_* */
      49  	int8_t		drives_per_striped_set;
      50  	int8_t		striped_set_number;
      51  	int8_t		drives_per_mirrored_set;
      52  	int8_t		mirrored_set_number;
      53  	uint32_t	rebuild_ptr_low;
      54  	uint32_t	rebuild_ptr_high;
      55  	uint32_t	incarnation_no;
      56  	uint8_t		member_status;
      57  	uint8_t		mirrored_set_state;	/* SILICON_MIRROR_* */
      58  	uint8_t		reported_device_location;
      59  	uint8_t		idechannel;
      60  	uint8_t		auto_rebuild;
      61  	uint8_t		unknown8;
      62  	uint8_t		text_type[0x13E - 0x12E];
      63  	uint16_t	checksum1;
      64  	int8_t		assumed_zeros[0x1FE - 0x140];
      65  	uint16_t	checksum2;
      66  } __attribute__((packed));
      67  
      68  #define SILICON_MAGIC		0x2F000000
      69  
      70  static uint16_t silraid_checksum(struct silicon_metadata *sil)
      71  {
      72  	int sum = 0;
      73  	unsigned short count = offsetof(struct silicon_metadata, checksum1) / 2;
      74  	unsigned char *ptr = (unsigned char *) sil;
      75  
      76  	while (count--) {
      77  		uint16_t val;
      78  
      79  		memcpy(&val, ptr, sizeof(uint16_t));
      80  		sum += le16_to_cpu(val);
      81  
      82  		ptr += sizeof(uint16_t);
      83  	}
      84  
      85  	return (-sum & 0xFFFF);
      86  }
      87  
      88  static int probe_silraid(blkid_probe pr,
      89  		const struct blkid_idmag *mag __attribute__((__unused__)))
      90  {
      91  	uint64_t off;
      92  	struct silicon_metadata *sil;
      93  
      94  	if (pr->size < 0x10000)
      95  		return 1;
      96  	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
      97  		return 1;
      98  
      99  	off = ((pr->size / 0x200) - 1) * 0x200;
     100  
     101  	sil = (struct silicon_metadata *)
     102  			blkid_probe_get_buffer(pr, off,
     103  				sizeof(struct silicon_metadata));
     104  	if (!sil)
     105  		return errno ? -errno : 1;
     106  
     107  	if (le32_to_cpu(sil->magic) != SILICON_MAGIC)
     108  		return 1;
     109  	if (sil->disk_number >= 8)
     110  		return 1;
     111  	if (!blkid_probe_verify_csum(pr, silraid_checksum(sil), le16_to_cpu(sil->checksum1)))
     112  		return 1;
     113  
     114  	if (blkid_probe_sprintf_version(pr, "%u.%u",
     115  				le16_to_cpu(sil->major_ver),
     116  				le16_to_cpu(sil->minor_ver)) != 0)
     117  		return 1;
     118  
     119  	if (blkid_probe_set_magic(pr,
     120  			off + offsetof(struct silicon_metadata, magic),
     121  			sizeof(sil->magic),
     122  			(unsigned char *) &sil->magic))
     123  		return 1;
     124  	return 0;
     125  }
     126  
     127  const struct blkid_idinfo silraid_idinfo = {
     128  	.name		= "silicon_medley_raid_member",
     129  	.usage		= BLKID_USAGE_RAID,
     130  	.probefunc	= probe_silraid,
     131  	.magics		= BLKID_NONE_MAGIC
     132  };
     133  
     134