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