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
131
132
133
134
135
136
137
138
139
140
141
|
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* 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 <stdint.h>
#include "superblocks.h"
/* http://www.snia.org/standards/home */
#define DDF_GUID_LENGTH 24
#define DDF_REV_LENGTH 8
#define DDF_MAGIC 0xDE11DE11
struct ddf_header {
uint32_t signature;
uint32_t crc;
uint8_t guid[DDF_GUID_LENGTH];
char ddf_rev[8]; /* 01.02.00 */
uint32_t seq; /* starts at '1' */
uint32_t timestamp;
uint8_t openflag;
uint8_t foreignflag;
uint8_t enforcegroups;
uint8_t pad0; /* 0xff */
uint8_t pad1[12]; /* 12 * 0xff */
/* 64 bytes so far */
uint8_t header_ext[32]; /* reserved: fill with 0xff */
uint64_t primary_lba;
uint64_t secondary_lba;
uint8_t type;
uint8_t pad2[3]; /* 0xff */
uint32_t workspace_len; /* sectors for vendor space -
* at least 32768(sectors) */
uint64_t workspace_lba;
uint16_t max_pd_entries; /* one of 15, 63, 255, 1023, 4095 */
uint16_t max_vd_entries; /* 2^(4,6,8,10,12)-1 : i.e. as above */
uint16_t max_partitions; /* i.e. max num of configuration
record entries per disk */
uint16_t config_record_len; /* 1 +ROUNDUP(max_primary_element_entries
*12/512) */
uint16_t max_primary_element_entries; /* 16, 64, 256, 1024, or 4096 */
uint8_t pad3[54]; /* 0xff */
/* 192 bytes so far */
uint32_t controller_section_offset;
uint32_t controller_section_length;
uint32_t phys_section_offset;
uint32_t phys_section_length;
uint32_t virt_section_offset;
uint32_t virt_section_length;
uint32_t config_section_offset;
uint32_t config_section_length;
uint32_t data_section_offset;
uint32_t data_section_length;
uint32_t bbm_section_offset;
uint32_t bbm_section_length;
uint32_t diag_space_offset;
uint32_t diag_space_length;
uint32_t vendor_offset;
uint32_t vendor_length;
/* 256 bytes so far */
uint8_t pad4[256]; /* 0xff */
} __attribute__((packed));
static int probe_ddf(blkid_probe pr,
const struct blkid_idmag *mag __attribute__((__unused__)))
{
int hdrs[] = { 1, 257 };
size_t i;
struct ddf_header *ddf = NULL;
char version[DDF_REV_LENGTH + 1];
uint64_t off = 0, lba;
if (pr->size < 0x30000)
return 1;
for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
ddf = (struct ddf_header *) blkid_probe_get_buffer(pr,
off,
sizeof(struct ddf_header));
if (!ddf)
return errno ? -errno : 1;
if (ddf->signature == cpu_to_be32(DDF_MAGIC) ||
ddf->signature == cpu_to_le32(DDF_MAGIC))
break;
ddf = NULL;
}
if (!ddf)
return 1;
lba = ddf->signature == cpu_to_be32(DDF_MAGIC) ?
be64_to_cpu(ddf->primary_lba) :
le64_to_cpu(ddf->primary_lba);
if (lba > 0) {
/* check primary header */
unsigned char *buf;
buf = blkid_probe_get_buffer(pr,
lba << 9, sizeof(ddf->signature));
if (!buf)
return errno ? -errno : 1;
if (memcmp(buf, &ddf->signature, 4) != 0)
return 1;
}
blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
*(version + sizeof(ddf->ddf_rev)) = '\0';
if (blkid_probe_set_version(pr, version) != 0)
return 1;
if (blkid_probe_set_magic(pr, off,
sizeof(ddf->signature),
(unsigned char *) &ddf->signature))
return 1;
return 0;
}
const struct blkid_idinfo ddfraid_idinfo = {
.name = "ddf_raid_member",
.usage = BLKID_USAGE_RAID,
.probefunc = probe_ddf,
.magics = BLKID_NONE_MAGIC
};
|