1dbcc3abmav/*-
2a82e3a8pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3a82e3a8pfg *
4dbcc3abmav * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org>
5dbcc3abmav * All rights reserved.
6dbcc3abmav *
7dbcc3abmav * Redistribution and use in source and binary forms, with or without
8dbcc3abmav * modification, are permitted provided that the following conditions
9dbcc3abmav * are met:
10dbcc3abmav * 1. Redistributions of source code must retain the above copyright
11dbcc3abmav *    notice, this list of conditions and the following disclaimer.
12dbcc3abmav * 2. Redistributions in binary form must reproduce the above copyright
13dbcc3abmav *    notice, this list of conditions and the following disclaimer in the
14dbcc3abmav *    documentation and/or other materials provided with the distribution.
15dbcc3abmav *
16dbcc3abmav * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17dbcc3abmav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18dbcc3abmav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19dbcc3abmav * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20dbcc3abmav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21dbcc3abmav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22dbcc3abmav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23dbcc3abmav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24dbcc3abmav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25dbcc3abmav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dbcc3abmav * SUCH DAMAGE.
27dbcc3abmav */
28dbcc3abmav
29dbcc3abmav#include <sys/cdefs.h>
30dbcc3abmav__FBSDID("$FreeBSD$");
31dbcc3abmav
32dbcc3abmav#include <sys/param.h>
33dbcc3abmav#include <sys/bio.h>
348581c5bdelphij#include <sys/gsb_crc32.h>
35dbcc3abmav#include <sys/endian.h>
36dbcc3abmav#include <sys/kernel.h>
37dbcc3abmav#include <sys/kobj.h>
38dbcc3abmav#include <sys/limits.h>
39dbcc3abmav#include <sys/lock.h>
40dbcc3abmav#include <sys/malloc.h>
41dbcc3abmav#include <sys/mutex.h>
42dbcc3abmav#include <sys/systm.h>
43dbcc3abmav#include <sys/time.h>
44dbcc3abmav#include <sys/clock.h>
452e02693sbruno#include <sys/disk.h>
46dbcc3abmav#include <geom/geom.h>
4710d53fccem#include <geom/geom_dbg.h>
48dbcc3abmav#include "geom/raid/g_raid.h"
49dbcc3abmav#include "geom/raid/md_ddf.h"
50dbcc3abmav#include "g_raid_md_if.h"
51dbcc3abmav
52dbcc3abmavstatic MALLOC_DEFINE(M_MD_DDF, "md_ddf_data", "GEOM_RAID DDF metadata");
53dbcc3abmav
54dbcc3abmav#define	DDF_MAX_DISKS_HARD	128
55dbcc3abmav
56dbcc3abmav#define	DDF_MAX_DISKS	16
57dbcc3abmav#define	DDF_MAX_VDISKS	7
58dbcc3abmav#define	DDF_MAX_PARTITIONS	1
59dbcc3abmav
60dbcc3abmav#define DECADE (3600*24*(365*10+2))	/* 10 years in seconds. */
61dbcc3abmav
62dbcc3abmavstruct ddf_meta {
63dbcc3abmav	u_int	sectorsize;
64dbcc3abmav	u_int	bigendian;
65dbcc3abmav	struct ddf_header *hdr;
66dbcc3abmav	struct ddf_cd_record *cdr;
67dbcc3abmav	struct ddf_pd_record *pdr;
68dbcc3abmav	struct ddf_vd_record *vdr;
69dbcc3abmav	void *cr;
70dbcc3abmav	struct ddf_pdd_record *pdd;
71dbcc3abmav	struct ddf_bbm_log *bbm;
72dbcc3abmav};
73dbcc3abmav
74dbcc3abmavstruct ddf_vol_meta {
75dbcc3abmav	u_int	sectorsize;
76dbcc3abmav	u_int	bigendian;
77dbcc3abmav	struct ddf_header *hdr;
78dbcc3abmav	struct ddf_cd_record *cdr;
79dbcc3abmav	struct ddf_vd_entry *vde;
80dbcc3abmav	struct ddf_vdc_record *vdc;
81dbcc3abmav	struct ddf_vdc_record *bvdc[DDF_MAX_DISKS_HARD];
82dbcc3abmav};
83dbcc3abmav
84dbcc3abmavstruct g_raid_md_ddf_perdisk {
85dbcc3abmav	struct ddf_meta	 pd_meta;
86dbcc3abmav};
87dbcc3abmav
88dbcc3abmavstruct g_raid_md_ddf_pervolume {
89dbcc3abmav	struct ddf_vol_meta		 pv_meta;
90dbcc3abmav	int				 pv_started;
91dbcc3abmav	struct callout			 pv_start_co;	/* STARTING state timer. */
92dbcc3abmav};
93dbcc3abmav
94dbcc3abmavstruct g_raid_md_ddf_object {
95dbcc3abmav	struct g_raid_md_object	 mdio_base;
966a0688cmav	u_int			 mdio_bigendian;
97dbcc3abmav	struct ddf_meta		 mdio_meta;
983a7fb06mav	int			 mdio_starting;
99dbcc3abmav	struct callout		 mdio_start_co;	/* STARTING state timer. */
100dbcc3abmav	int			 mdio_started;
101dbcc3abmav	struct root_hold_token	*mdio_rootmount; /* Root mount delay token. */
102dbcc3abmav};
103dbcc3abmav
1046a0688cmavstatic g_raid_md_create_req_t g_raid_md_create_req_ddf;
105dbcc3abmavstatic g_raid_md_taste_t g_raid_md_taste_ddf;
106dbcc3abmavstatic g_raid_md_event_t g_raid_md_event_ddf;
107dbcc3abmavstatic g_raid_md_volume_event_t g_raid_md_volume_event_ddf;
108dbcc3abmavstatic g_raid_md_ctl_t g_raid_md_ctl_ddf;
109dbcc3abmavstatic g_raid_md_write_t g_raid_md_write_ddf;
110dbcc3abmavstatic g_raid_md_fail_disk_t g_raid_md_fail_disk_ddf;
111dbcc3abmavstatic g_raid_md_free_disk_t g_raid_md_free_disk_ddf;
112dbcc3abmavstatic g_raid_md_free_volume_t g_raid_md_free_volume_ddf;
113dbcc3abmavstatic g_raid_md_free_t g_raid_md_free_ddf;
114dbcc3abmav
115dbcc3abmavstatic kobj_method_t g_raid_md_ddf_methods[] = {
1166a0688cmav	KOBJMETHOD(g_raid_md_create_req,	g_raid_md_create_req_ddf),
117dbcc3abmav	KOBJMETHOD(g_raid_md_taste,	g_raid_md_taste_ddf),
118dbcc3abmav	KOBJMETHOD(g_raid_md_event,	g_raid_md_event_ddf),
119dbcc3abmav	KOBJMETHOD(g_raid_md_volume_event,	g_raid_md_volume_event_ddf),
120dbcc3abmav	KOBJMETHOD(g_raid_md_ctl,	g_raid_md_ctl_ddf),
121dbcc3abmav	KOBJMETHOD(g_raid_md_write,	g_raid_md_write_ddf),
122dbcc3abmav	KOBJMETHOD(g_raid_md_fail_disk,	g_raid_md_fail_disk_ddf),
123dbcc3abmav	KOBJMETHOD(g_raid_md_free_disk,	g_raid_md_free_disk_ddf),
124dbcc3abmav	KOBJMETHOD(g_raid_md_free_volume,	g_raid_md_free_volume_ddf),
125dbcc3abmav	KOBJMETHOD(g_raid_md_free,	g_raid_md_free_ddf),
126dbcc3abmav	{ 0, 0 }
127dbcc3abmav};
128dbcc3abmav
129dbcc3abmavstatic struct g_raid_md_class g_raid_md_ddf_class = {
130dbcc3abmav	"DDF",
131dbcc3abmav	g_raid_md_ddf_methods,
132dbcc3abmav	sizeof(struct g_raid_md_ddf_object),
133db9e01amav	.mdc_enable = 1,
134dbcc3abmav	.mdc_priority = 100
135dbcc3abmav};
136dbcc3abmav
137dbcc3abmav#define GET8(m, f)	((m)->f)
138dbcc3abmav#define GET16(m, f)	((m)->bigendian ? be16dec(&(m)->f) : le16dec(&(m)->f))
139dbcc3abmav#define GET32(m, f)	((m)->bigendian ? be32dec(&(m)->f) : le32dec(&(m)->f))
140dbcc3abmav#define GET64(m, f)	((m)->bigendian ? be64dec(&(m)->f) : le64dec(&(m)->f))
141dbcc3abmav#define GET8D(m, f)	(f)
142dbcc3abmav#define GET16D(m, f)	((m)->bigendian ? be16dec(&f) : le16dec(&f))
143dbcc3abmav#define GET32D(m, f)	((m)->bigendian ? be32dec(&f) : le32dec(&f))
144dbcc3abmav#define GET64D(m, f)	((m)->bigendian ? be64dec(&f) : le64dec(&f))
145dbcc3abmav#define GET8P(m, f)	(*(f))
146dbcc3abmav#define GET16P(m, f)	((m)->bigendian ? be16dec(f) : le16dec(f))
147dbcc3abmav#define GET32P(m, f)	((m)->bigendian ? be32dec(f) : le32dec(f))
148dbcc3abmav#define GET64P(m, f)	((m)->bigendian ? be64dec(f) : le64dec(f))
149dbcc3abmav
150dbcc3abmav#define SET8P(m, f, v)							\
151dbcc3abmav	(*(f) = (v))
152dbcc3abmav#define SET16P(m, f, v)							\
153dbcc3abmav	do {								\
154dbcc3abmav		if ((m)->bigendian)					\
155dbcc3abmav			be16enc((f), (v));				\
156dbcc3abmav		else							\
157dbcc3abmav			le16enc((f), (v));				\
158dbcc3abmav	} while (0)
159dbcc3abmav#define SET32P(m, f, v)							\
160dbcc3abmav	do {								\
161dbcc3abmav		if ((m)->bigendian)					\
162dbcc3abmav			be32enc((f), (v));				\
163dbcc3abmav		else							\
164dbcc3abmav			le32enc((f), (v));				\
165dbcc3abmav	} while (0)
166dbcc3abmav#define SET64P(m, f, v)							\
167dbcc3abmav	do {								\
168dbcc3abmav		if ((m)->bigendian)					\
169dbcc3abmav			be64enc((f), (v));				\
170dbcc3abmav		else							\
171dbcc3abmav			le64enc((f), (v));				\
172dbcc3abmav	} while (0)
173dbcc3abmav#define SET8(m, f, v)	SET8P((m), &((m)->f), (v))
174dbcc3abmav#define SET16(m, f, v)	SET16P((m), &((m)->f), (v))
175dbcc3abmav#define SET32(m, f, v)	SET32P((m), &((m)->f), (v))
176dbcc3abmav#define SET64(m, f, v)	SET64P((m), &((m)->f), (v))
177dbcc3abmav#define SET8D(m, f, v)	SET8P((m), &(f), (v))
178dbcc3abmav#define SET16D(m, f, v)	SET16P((m), &(f), (v))
179dbcc3abmav#define SET32D(m, f, v)	SET32P((m), &(f), (v))
180dbcc3abmav#define SET64D(m, f, v)	SET64P((m), &(f), (v))
181dbcc3abmav
18208b90a5mav#define GETCRNUM(m)	(GET32((m), hdr->cr_length) /			\
18308b90a5mav	GET16((m), hdr->Configuration_Record_Length))
18408b90a5mav
18508b90a5mav#define GETVDCPTR(m, n)	((struct ddf_vdc_record *)((uint8_t *)(m)->cr +	\
18608b90a5mav	(n) * GET16((m), hdr->Configuration_Record_Length) *		\
18708b90a5mav	(m)->sectorsize))
18808b90a5mav
189ecf215emav#define GETSAPTR(m, n)	((struct ddf_sa_record *)((uint8_t *)(m)->cr +	\
190ecf215emav	(n) * GET16((m), hdr->Configuration_Record_Length) *		\
191ecf215emav	(m)->sectorsize))
192ecf215emav
193dbcc3abmavstatic int
194dbcc3abmavisff(uint8_t *buf, int size)
195dbcc3abmav{
196dbcc3abmav	int i;
197dbcc3abmav
198dbcc3abmav	for (i = 0; i < size; i++)
199dbcc3abmav		if (buf[i] != 0xff)
200dbcc3abmav			return (0);
201dbcc3abmav	return (1);
202dbcc3abmav}
203dbcc3abmav
204dbcc3abmavstatic void
205dbcc3abmavprint_guid(uint8_t *buf)
206dbcc3abmav{
207dbcc3abmav	int i, ascii;
208dbcc3abmav
209dbcc3abmav	ascii = 1;
210dbcc3abmav	for (i = 0; i < 24; i++) {
211dbcc3abmav		if (buf[i] != 0 && (buf[i] < ' ' || buf[i] > 127)) {
212dbcc3abmav			ascii = 0;
213dbcc3abmav			break;
214dbcc3abmav		}
215dbcc3abmav	}
216dbcc3abmav	if (ascii) {
217dbcc3abmav		printf("'%.24s'", buf);
218dbcc3abmav	} else {
219dbcc3abmav		for (i = 0; i < 24; i++)
220dbcc3abmav			printf("%02x", buf[i]);
221dbcc3abmav	}
222dbcc3abmav}
223dbcc3abmav
224dbcc3abmavstatic void
225dbcc3abmavg_raid_md_ddf_print(struct ddf_meta *meta)
226dbcc3abmav{
227dbcc3abmav	struct ddf_vdc_record *vdc;
228dbcc3abmav	struct ddf_vuc_record *vuc;
229dbcc3abmav	struct ddf_sa_record *sa;
230dbcc3abmav	uint64_t *val2;
231dbcc3abmav	uint32_t val;
232dbcc3abmav	int i, j, k, num, num2;
233dbcc3abmav
234dbcc3abmav	if (g_raid_debug < 1)
235dbcc3abmav		return;
236dbcc3abmav
237dbcc3abmav	printf("********* DDF Metadata *********\n");
238dbcc3abmav	printf("**** Header ****\n");
239dbcc3abmav	printf("DDF_Header_GUID      ");
240dbcc3abmav	print_guid(meta->hdr->DDF_Header_GUID);
241dbcc3abmav	printf("\n");
242dbcc3abmav	printf("DDF_rev              %8.8s\n", (char *)&meta->hdr->DDF_rev[0]);
243dbcc3abmav	printf("Sequence_Number      0x%08x\n", GET32(meta, hdr->Sequence_Number));
244dbcc3abmav	printf("TimeStamp            0x%08x\n", GET32(meta, hdr->TimeStamp));
245dbcc3abmav	printf("Open_Flag            0x%02x\n", GET16(meta, hdr->Open_Flag));
246dbcc3abmav	printf("Foreign_Flag         0x%02x\n", GET16(meta, hdr->Foreign_Flag));
247dbcc3abmav	printf("Diskgrouping         0x%02x\n", GET16(meta, hdr->Diskgrouping));
248dbcc3abmav	printf("Primary_Header_LBA   %ju\n", GET64(meta, hdr->Primary_Header_LBA));
249dbcc3abmav	printf("Secondary_Header_LBA %ju\n", GET64(meta, hdr->Secondary_Header_LBA));
250dbcc3abmav	printf("WorkSpace_Length     %u\n", GET32(meta, hdr->WorkSpace_Length));
251dbcc3abmav	printf("WorkSpace_LBA        %ju\n", GET64(meta, hdr->WorkSpace_LBA));
252dbcc3abmav	printf("Max_PD_Entries       %u\n", GET16(meta, hdr->Max_PD_Entries));
253dbcc3abmav	printf("Max_VD_Entries       %u\n", GET16(meta, hdr->Max_VD_Entries));
254dbcc3abmav	printf("Max_Partitions       %u\n", GET16(meta, hdr->Max_Partitions));
255dbcc3abmav	printf("Configuration_Record_Length %u\n", GET16(meta, hdr->Configuration_Record_Length));
256dbcc3abmav	printf("Max_Primary_Element_Entries %u\n", GET16(meta, hdr->Max_Primary_Element_Entries));
257dbcc3abmav	printf("Controller Data      %u:%u\n", GET32(meta, hdr->cd_section), GET32(meta, hdr->cd_length));
258dbcc3abmav	printf("Physical Disk        %u:%u\n", GET32(meta, hdr->pdr_section), GET32(meta, hdr->pdr_length));
259dbcc3abmav	printf("Virtual Disk         %u:%u\n", GET32(meta, hdr->vdr_section), GET32(meta, hdr->vdr_length));
260dbcc3abmav	printf("Configuration Recs   %u:%u\n", GET32(meta, hdr->cr_section), GET32(meta, hdr->cr_length));
261dbcc3abmav	printf("Physical Disk Recs   %u:%u\n", GET32(meta, hdr->pdd_section), GET32(meta, hdr->pdd_length));
262dbcc3abmav	printf("BBM Log              %u:%u\n", GET32(meta, hdr->bbmlog_section), GET32(meta, hdr->bbmlog_length));
263dbcc3abmav	printf("Diagnostic Space     %u:%u\n", GET32(meta, hdr->Diagnostic_Space), GET32(meta, hdr->Diagnostic_Space_Length));
264dbcc3abmav	printf("Vendor_Specific_Logs %u:%u\n", GET32(meta, hdr->Vendor_Specific_Logs), GET32(meta, hdr->Vendor_Specific_Logs_Length));
265586d106pfg	printf("**** Controller Data ****\n");
266dbcc3abmav	printf("Controller_GUID      ");
267dbcc3abmav	print_guid(meta->cdr->Controller_GUID);
268dbcc3abmav	printf("\n");
269dbcc3abmav	printf("Controller_Type      0x%04x%04x 0x%04x%04x\n",
270dbcc3abmav	    GET16(meta, cdr->Controller_Type.Vendor_ID),
271dbcc3abmav	    GET16(meta, cdr->Controller_Type.Device_ID),
272dbcc3abmav	    GET16(meta, cdr->Controller_Type.SubVendor_ID),
273dbcc3abmav	    GET16(meta, cdr->Controller_Type.SubDevice_ID));
274dbcc3abmav	printf("Product_ID           '%.16s'\n", (char *)&meta->cdr->Product_ID[0]);
27508b90a5mav	printf("**** Physical Disk Records ****\n");
276dbcc3abmav	printf("Populated_PDEs       %u\n", GET16(meta, pdr->Populated_PDEs));
277dbcc3abmav	printf("Max_PDE_Supported    %u\n", GET16(meta, pdr->Max_PDE_Supported));
278dbcc3abmav	for (j = 0; j < GET16(meta, pdr->Populated_PDEs); j++) {
279dbcc3abmav		if (isff(meta->pdr->entry[j].PD_GUID, 24))
280dbcc3abmav			continue;
281dbcc3abmav		if (GET32(meta, pdr->entry[j].PD_Reference) == 0xffffffff)
282dbcc3abmav			continue;
283dbcc3abmav		printf("PD_GUID              ");
284dbcc3abmav		print_guid(meta->pdr->entry[j].PD_GUID);
285dbcc3abmav		printf("\n");
286dbcc3abmav		printf("PD_Reference         0x%08x\n",
287dbcc3abmav		    GET32(meta, pdr->entry[j].PD_Reference));
288dbcc3abmav		printf("PD_Type              0x%04x\n",
289dbcc3abmav		    GET16(meta, pdr->entry[j].PD_Type));
290dbcc3abmav		printf("PD_State             0x%04x\n",
291dbcc3abmav		    GET16(meta, pdr->entry[j].PD_State));
292dbcc3abmav		printf("Configured_Size      %ju\n",
293dbcc3abmav		    GET64(meta, pdr->entry[j].Configured_Size));
294dbcc3abmav		printf("Block_Size           %u\n",
295dbcc3abmav		    GET16(meta, pdr->entry[j].Block_Size));
296dbcc3abmav	}
29708b90a5mav	printf("**** Virtual Disk Records ****\n");
298dbcc3abmav	printf("Populated_VDEs       %u\n", GET16(meta, vdr->Populated_VDEs));
299dbcc3abmav	printf("Max_VDE_Supported    %u\n", GET16(meta, vdr->Max_VDE_Supported));
300dbcc3abmav	for (j = 0; j < GET16(meta, vdr->Populated_VDEs); j++) {
301dbcc3abmav		if (isff(meta->vdr->entry[j].VD_GUID, 24))
302dbcc3abmav			continue;
303dbcc3abmav		printf("VD_GUID              ");
304dbcc3abmav		print_guid(meta->vdr->entry[j].VD_GUID);
305dbcc3abmav		printf("\n");
306dbcc3abmav		printf("VD_Number            0x%04x\n",
307dbcc3abmav		    GET16(meta, vdr->entry[j].VD_Number));
308ecf215emav		printf("VD_Type              0x%04x\n",
309ecf215emav		    GET16(meta, vdr->entry[j].VD_Type));
310dbcc3abmav		printf("VD_State             0x%02x\n",
311dbcc3abmav		    GET8(meta, vdr->entry[j].VD_State));
312dbcc3abmav		printf("Init_State           0x%02x\n",
313dbcc3abmav		    GET8(meta, vdr->entry[j].Init_State));
314dbcc3abmav		printf("Drive_Failures_Remaining %u\n",
315dbcc3abmav		    GET8(meta, vdr->entry[j].Drive_Failures_Remaining));
316dbcc3abmav		printf("VD_Name              '%.16s'\n",
317dbcc3abmav		    (char *)&meta->vdr->entry[j].VD_Name);
318dbcc3abmav	}
319dbcc3abmav	printf("**** Configuration Records ****\n");
32008b90a5mav	num = GETCRNUM(meta);
321dbcc3abmav	for (j = 0; j < num; j++) {
32208b90a5mav		vdc = GETVDCPTR(meta, j);
323dbcc3abmav		val = GET32D(meta, vdc->Signature);
324dbcc3abmav		switch (val) {
325dbcc3abmav		case DDF_VDCR_SIGNATURE:
326dbcc3abmav			printf("** Virtual Disk Configuration **\n");
327dbcc3abmav			printf("VD_GUID              ");
328dbcc3abmav			print_guid(vdc->VD_GUID);
329dbcc3abmav			printf("\n");
330dbcc3abmav			printf("Timestamp            0x%08x\n",
331dbcc3abmav			    GET32D(meta, vdc->Timestamp));
332dbcc3abmav			printf("Sequence_Number      0x%08x\n",
333dbcc3abmav			    GET32D(meta, vdc->Sequence_Number));
334dbcc3abmav			printf("Primary_Element_Count %u\n",
335dbcc3abmav			    GET16D(meta, vdc->Primary_Element_Count));
336dbcc3abmav			printf("Stripe_Size          %u\n",
337dbcc3abmav			    GET8D(meta, vdc->Stripe_Size));
338dbcc3abmav			printf("Primary_RAID_Level   0x%02x\n",
339dbcc3abmav			    GET8D(meta, vdc->Primary_RAID_Level));
340dbcc3abmav			printf("RLQ                  0x%02x\n",
341dbcc3abmav			    GET8D(meta, vdc->RLQ));
342dbcc3abmav			printf("Secondary_Element_Count %u\n",
343dbcc3abmav			    GET8D(meta, vdc->Secondary_Element_Count));
344dbcc3abmav			printf("Secondary_Element_Seq %u\n",
345dbcc3abmav			    GET8D(meta, vdc->Secondary_Element_Seq));
346dbcc3abmav			printf("Secondary_RAID_Level 0x%02x\n",
347dbcc3abmav			    GET8D(meta, vdc->Secondary_RAID_Level));
348dbcc3abmav			printf("Block_Count          %ju\n",
349dbcc3abmav			    GET64D(meta, vdc->Block_Count));
350dbcc3abmav			printf("VD_Size              %ju\n",
351dbcc3abmav			    GET64D(meta, vdc->VD_Size));
352dbcc3abmav			printf("Block_Size           %u\n",
353dbcc3abmav			    GET16D(meta, vdc->Block_Size));
354dbcc3abmav			printf("Rotate_Parity_count  %u\n",
355dbcc3abmav			    GET8D(meta, vdc->Rotate_Parity_count));
356dbcc3abmav			printf("Associated_Spare_Disks");
357dbcc3abmav			for (i = 0; i < 8; i++) {
358dbcc3abmav				if (GET32D(meta, vdc->Associated_Spares[i]) != 0xffffffff)
359dbcc3abmav					printf(" 0x%08x", GET32D(meta, vdc->Associated_Spares[i]));
360dbcc3abmav			}
361dbcc3abmav			printf("\n");
362dbcc3abmav			printf("Cache_Flags          %016jx\n",
363dbcc3abmav			    GET64D(meta, vdc->Cache_Flags));
364dbcc3abmav			printf("BG_Rate              %u\n",
365dbcc3abmav			    GET8D(meta, vdc->BG_Rate));
366dbcc3abmav			printf("MDF_Parity_Disks     %u\n",
367dbcc3abmav			    GET8D(meta, vdc->MDF_Parity_Disks));
368dbcc3abmav			printf("MDF_Parity_Generator_Polynomial 0x%04x\n",
369dbcc3abmav			    GET16D(meta, vdc->MDF_Parity_Generator_Polynomial));
370dbcc3abmav			printf("MDF_Constant_Generation_Method 0x%02x\n",
371dbcc3abmav			    GET8D(meta, vdc->MDF_Constant_Generation_Method));
372dbcc3abmav			printf("Physical_Disks      ");
373dbcc3abmav			num2 = GET16D(meta, vdc->Primary_Element_Count);
374dbcc3abmav			val2 = (uint64_t *)&(vdc->Physical_Disk_Sequence[GET16(meta, hdr->Max_Primary_Element_Entries)]);
375dbcc3abmav			for (i = 0; i < num2; i++)
376dbcc3abmav				printf(" 0x%08x @ %ju",
377dbcc3abmav				    GET32D(meta, vdc->Physical_Disk_Sequence[i]),
378dbcc3abmav				    GET64P(meta, val2 + i));
379dbcc3abmav			printf("\n");
380dbcc3abmav			break;
381dbcc3abmav		case DDF_VUCR_SIGNATURE:
382dbcc3abmav			printf("** Vendor Unique Configuration **\n");
383dbcc3abmav			vuc = (struct ddf_vuc_record *)vdc;
384dbcc3abmav			printf("VD_GUID              ");
385dbcc3abmav			print_guid(vuc->VD_GUID);
386dbcc3abmav			printf("\n");
387dbcc3abmav			break;
388dbcc3abmav		case DDF_SA_SIGNATURE:
389dbcc3abmav			printf("** Spare Assignment Configuration **\n");
390dbcc3abmav			sa = (struct ddf_sa_record *)vdc;
391dbcc3abmav			printf("Timestamp            0x%08x\n",
392dbcc3abmav			    GET32D(meta, sa->Timestamp));
393dbcc3abmav			printf("Spare_Type           0x%02x\n",
394dbcc3abmav			    GET8D(meta, sa->Spare_Type));
395dbcc3abmav			printf("Populated_SAEs       %u\n",
396dbcc3abmav			    GET16D(meta, sa->Populated_SAEs));
397dbcc3abmav			printf("MAX_SAE_Supported    %u\n",
398dbcc3abmav			    GET16D(meta, sa->MAX_SAE_Supported));
399dbcc3abmav			for (i = 0; i < GET16D(meta, sa->Populated_SAEs); i++) {
400dbcc3abmav				if (isff(sa->entry[i].VD_GUID, 24))
401dbcc3abmav					continue;
402dbcc3abmav				printf("VD_GUID             ");
403dbcc3abmav				for (k = 0; k < 24; k++)
404dbcc3abmav					printf("%02x", sa->entry[i].VD_GUID[k]);
405dbcc3abmav				printf("\n");
406dbcc3abmav				printf("Secondary_Element   %u\n",
407dbcc3abmav				    GET16D(meta, sa->entry[i].Secondary_Element));
408dbcc3abmav			}
409dbcc3abmav			break;
410ecf215emav		case 0x00000000:
411dbcc3abmav		case 0xFFFFFFFF:
412dbcc3abmav			break;
413dbcc3abmav		default:
414dbcc3abmav			printf("Unknown configuration signature %08x\n", val);
415dbcc3abmav			break;
416dbcc3abmav		}
417dbcc3abmav	}
418dbcc3abmav	printf("**** Physical Disk Data ****\n");
419dbcc3abmav	printf("PD_GUID              ");
420dbcc3abmav	print_guid(meta->pdd->PD_GUID);
421dbcc3abmav	printf("\n");
422dbcc3abmav	printf("PD_Reference         0x%08x\n",
423dbcc3abmav	    GET32(meta, pdd->PD_Reference));
424dbcc3abmav	printf("Forced_Ref_Flag      0x%02x\n",
425dbcc3abmav	    GET8(meta, pdd->Forced_Ref_Flag));
426dbcc3abmav	printf("Forced_PD_GUID_Flag  0x%02x\n",
427dbcc3abmav	    GET8(meta, pdd->Forced_PD_GUID_Flag));
428dbcc3abmav}
429dbcc3abmav
430dbcc3abmavstatic int
431dbcc3abmavddf_meta_find_pd(struct ddf_meta *meta, uint8_t *GUID, uint32_t PD_Reference)
432dbcc3abmav{
433dbcc3abmav	int i;
434dbcc3abmav
435dbcc3abmav	for (i = 0; i < GET16(meta, pdr->Populated_PDEs); i++) {
436dbcc3abmav		if (GUID != NULL) {
437dbcc3abmav			if (memcmp(meta->pdr->entry[i].PD_GUID, GUID, 24) == 0)
438dbcc3abmav				return (i);
439dbcc3abmav		} else if (PD_Reference != 0xffffffff) {
440dbcc3abmav			if (GET32(meta, pdr->entry[i].PD_Reference) == PD_Reference)
441dbcc3abmav				return (i);
442dbcc3abmav		} else
443dbcc3abmav			if (isff(meta->pdr->entry[i].PD_GUID, 24))
444dbcc3abmav				return (i);
445dbcc3abmav	}
446dbcc3abmav	if (GUID == NULL && PD_Reference == 0xffffffff) {
447dbcc3abmav		if (i >= GET16(meta, pdr->Max_PDE_Supported))
448dbcc3abmav			return (-1);
449dbcc3abmav		SET16(meta, pdr->Populated_PDEs, i + 1);
450dbcc3abmav		return (i);
451dbcc3abmav	}
452dbcc3abmav	return (-1);
453dbcc3abmav}
454dbcc3abmav
455dbcc3abmavstatic int
456dbcc3abmavddf_meta_find_vd(struct ddf_meta *meta, uint8_t *GUID)
457dbcc3abmav{
458dbcc3abmav	int i;
459dbcc3abmav
460dbcc3abmav	for (i = 0; i < GET16(meta, vdr->Populated_VDEs); i++) {
461dbcc3abmav		if (GUID != NULL) {
462dbcc3abmav			if (memcmp(meta->vdr->entry[i].VD_GUID, GUID, 24) == 0)
463dbcc3abmav				return (i);
464dbcc3abmav		} else
465dbcc3abmav			if (isff(meta->vdr->entry[i].VD_GUID, 24))
466dbcc3abmav				return (i);
467dbcc3abmav	}
468dbcc3abmav	if (GUID == NULL) {
469dbcc3abmav		if (i >= GET16(meta, vdr->Max_VDE_Supported))
470dbcc3abmav			return (-1);
471dbcc3abmav		SET16(meta, vdr->Populated_VDEs, i + 1);
472dbcc3abmav		return (i);
473dbcc3abmav	}
474dbcc3abmav	return (-1);
475dbcc3abmav}
476dbcc3abmav
477dbcc3abmavstatic struct ddf_vdc_record *
478dbcc3abmavddf_meta_find_vdc(struct ddf_meta *meta, uint8_t *GUID)
479dbcc3abmav{
480dbcc3abmav	struct ddf_vdc_record *vdc;
481dbcc3abmav	int i, num;
482dbcc3abmav
48308b90a5mav	num = GETCRNUM(meta);
484dbcc3abmav	for (i = 0; i < num; i++) {
48508b90a5mav		vdc = GETVDCPTR(meta, i);
486dbcc3abmav		if (GUID != NULL) {
487dbcc3abmav			if (GET32D(meta, vdc->Signature) == DDF_VDCR_SIGNATURE &&
488dbcc3abmav			    memcmp(vdc->VD_GUID, GUID, 24) == 0)
489dbcc3abmav				return (vdc);
490dbcc3abmav		} else
491ecf215emav			if (GET32D(meta, vdc->Signature) == 0xffffffff ||
492ecf215emav			    GET32D(meta, vdc->Signature) == 0)
493dbcc3abmav				return (vdc);
494dbcc3abmav	}
495dbcc3abmav	return (NULL);
496dbcc3abmav}
497dbcc3abmav
498dbcc3abmavstatic int
499dbcc3abmavddf_meta_count_vdc(struct ddf_meta *meta, uint8_t *GUID)
500dbcc3abmav{
501dbcc3abmav	struct ddf_vdc_record *vdc;
502dbcc3abmav	int i, num, cnt;
503dbcc3abmav
504dbcc3abmav	cnt = 0;
50508b90a5mav	num = GETCRNUM(meta);
506dbcc3abmav	for (i = 0; i < num; i++) {
50708b90a5mav		vdc = GETVDCPTR(meta, i);
508dbcc3abmav		if (GET32D(meta, vdc->Signature) != DDF_VDCR_SIGNATURE)
509dbcc3abmav			continue;
510dbcc3abmav		if (GUID == NULL || memcmp(vdc->VD_GUID, GUID, 24) == 0)
511dbcc3abmav			cnt++;
512dbcc3abmav	}
513