xref: /illumos-gate/usr/src/cmd/nvmeadm/nvmeadm_ocp.c (revision 56566d3ad46b71a5a32fad910c82ced1b1343e32)
1*56566d3aSRobert Mustacchi /*
2*56566d3aSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*56566d3aSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*56566d3aSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*56566d3aSRobert Mustacchi  * 1.0 of the CDDL.
6*56566d3aSRobert Mustacchi  *
7*56566d3aSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*56566d3aSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*56566d3aSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*56566d3aSRobert Mustacchi  */
11*56566d3aSRobert Mustacchi 
12*56566d3aSRobert Mustacchi /*
13*56566d3aSRobert Mustacchi  * Copyright 2026 Oxide Computer Company
14*56566d3aSRobert Mustacchi  */
15*56566d3aSRobert Mustacchi 
16*56566d3aSRobert Mustacchi /*
17*56566d3aSRobert Mustacchi  * Field information for OCP logs.
18*56566d3aSRobert Mustacchi  */
19*56566d3aSRobert Mustacchi 
20*56566d3aSRobert Mustacchi #include <err.h>
21*56566d3aSRobert Mustacchi #include <string.h>
22*56566d3aSRobert Mustacchi #include <sys/stddef.h>
23*56566d3aSRobert Mustacchi #include <sys/sysmacros.h>
24*56566d3aSRobert Mustacchi #include <sys/nvme/ocp.h>
25*56566d3aSRobert Mustacchi 
26*56566d3aSRobert Mustacchi #include "nvmeadm.h"
27*56566d3aSRobert Mustacchi 
28*56566d3aSRobert Mustacchi #define	OCP_F_SMART(f)	.nf_off = offsetof(ocp_vul_smart_t, osh_##f), \
29*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_smart_t *)NULL)->osh_##f)
30*56566d3aSRobert Mustacchi 
31*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_smart_block_bits[] = { {
32*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 47,
33*56566d3aSRobert Mustacchi 	.nfb_short = "raw",
34*56566d3aSRobert Mustacchi 	.nfb_desc = "Raw Count",
35*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
36*56566d3aSRobert Mustacchi }, {
37*56566d3aSRobert Mustacchi 	.nfb_lowbit = 48, .nfb_hibit = 63,
38*56566d3aSRobert Mustacchi 	.nfb_short = "norm",
39*56566d3aSRobert Mustacchi 	.nfb_desc = "Normalized Value",
40*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_PERCENT,
41*56566d3aSRobert Mustacchi } };
42*56566d3aSRobert Mustacchi 
43*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_smart_e2e_bits[] = { {
44*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 31,
45*56566d3aSRobert Mustacchi 	.nfb_short = "det",
46*56566d3aSRobert Mustacchi 	.nfb_desc = "Detected Errors",
47*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
48*56566d3aSRobert Mustacchi }, {
49*56566d3aSRobert Mustacchi 	.nfb_lowbit = 32, .nfb_hibit = 63,
50*56566d3aSRobert Mustacchi 	.nfb_short = "cor",
51*56566d3aSRobert Mustacchi 	.nfb_desc = "Corrected Errors",
52*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX
53*56566d3aSRobert Mustacchi } };
54*56566d3aSRobert Mustacchi 
55*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_smart_udec_bits[] = { {
56*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 31,
57*56566d3aSRobert Mustacchi 	.nfb_short = "max",
58*56566d3aSRobert Mustacchi 	.nfb_desc = "Maximum Count",
59*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
60*56566d3aSRobert Mustacchi }, {
61*56566d3aSRobert Mustacchi 	.nfb_lowbit = 32, .nfb_hibit = 63,
62*56566d3aSRobert Mustacchi 	.nfb_short = "min",
63*56566d3aSRobert Mustacchi 	.nfb_desc = "Minimum Count",
64*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX
65*56566d3aSRobert Mustacchi } };
66*56566d3aSRobert Mustacchi 
67*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_smart_therm_bits[] = { {
68*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 7,
69*56566d3aSRobert Mustacchi 	.nfb_short = "events",
70*56566d3aSRobert Mustacchi 	.nfb_desc = "Throttling Events",
71*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
72*56566d3aSRobert Mustacchi }, {
73*56566d3aSRobert Mustacchi 	.nfb_lowbit = 8, .nfb_hibit = 15,
74*56566d3aSRobert Mustacchi 	.nfb_short = "status",
75*56566d3aSRobert Mustacchi 	.nfb_desc = "Current Throttling Status",
76*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
77*56566d3aSRobert Mustacchi 	.nfb_strs = { "unthrottled", "first level", "second level",
78*56566d3aSRobert Mustacchi 	    "third level" }
79*56566d3aSRobert Mustacchi } };
80*56566d3aSRobert Mustacchi 
81*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_smart_dssd_bits[] = { {
82*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 7,
83*56566d3aSRobert Mustacchi 	.nfb_short = "errata",
84*56566d3aSRobert Mustacchi 	.nfb_desc = "Errata Version",
85*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
86*56566d3aSRobert Mustacchi }, {
87*56566d3aSRobert Mustacchi 	.nfb_lowbit = 8, .nfb_hibit = 23,
88*56566d3aSRobert Mustacchi 	.nfb_short = "point",
89*56566d3aSRobert Mustacchi 	.nfb_desc = "Point Version",
90*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
91*56566d3aSRobert Mustacchi }, {
92*56566d3aSRobert Mustacchi 	.nfb_lowbit = 24, .nfb_hibit = 39,
93*56566d3aSRobert Mustacchi 	.nfb_short = "minor",
94*56566d3aSRobert Mustacchi 	.nfb_desc = "Minor Version",
95*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
96*56566d3aSRobert Mustacchi }, {
97*56566d3aSRobert Mustacchi 	.nfb_lowbit = 40, .nfb_hibit = 47,
98*56566d3aSRobert Mustacchi 	.nfb_short = "major",
99*56566d3aSRobert Mustacchi 	.nfb_desc = "Major Version",
100*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX,
101*56566d3aSRobert Mustacchi } };
102*56566d3aSRobert Mustacchi 
103*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_smart_fields[] = { {
104*56566d3aSRobert Mustacchi 	OCP_F_SMART(pmed_write),
105*56566d3aSRobert Mustacchi 	.nf_short = "pmuw",
106*56566d3aSRobert Mustacchi 	.nf_desc = "Physical Media Units Written",
107*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_BYTES
108*56566d3aSRobert Mustacchi }, {
109*56566d3aSRobert Mustacchi 	OCP_F_SMART(pmed_read),
110*56566d3aSRobert Mustacchi 	.nf_short = "pmur",
111*56566d3aSRobert Mustacchi 	.nf_desc = "Physical Media Units Read",
112*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_BYTES
113*56566d3aSRobert Mustacchi }, {
114*56566d3aSRobert Mustacchi 	OCP_F_SMART(bunb),
115*56566d3aSRobert Mustacchi 	.nf_short = "bunb",
116*56566d3aSRobert Mustacchi 	.nf_desc = "Bad User NAND Blocks",
117*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_block_bits)
118*56566d3aSRobert Mustacchi }, {
119*56566d3aSRobert Mustacchi 	OCP_F_SMART(bsnb),
120*56566d3aSRobert Mustacchi 	.nf_short = "bsnb",
121*56566d3aSRobert Mustacchi 	.nf_desc = "Bad System NAND Blocks",
122*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_block_bits)
123*56566d3aSRobert Mustacchi }, {
124*56566d3aSRobert Mustacchi 	OCP_F_SMART(xor_rec),
125*56566d3aSRobert Mustacchi 	.nf_short = "xrc",
126*56566d3aSRobert Mustacchi 	.nf_desc = "XOR Recovery Count",
127*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
128*56566d3aSRobert Mustacchi }, {
129*56566d3aSRobert Mustacchi 	OCP_F_SMART(read_unrec),
130*56566d3aSRobert Mustacchi 	.nf_short = "urec",
131*56566d3aSRobert Mustacchi 	.nf_desc = "Uncorrectable Read Error Count",
132*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
133*56566d3aSRobert Mustacchi }, {
134*56566d3aSRobert Mustacchi 	OCP_F_SMART(soft_ecc_err),
135*56566d3aSRobert Mustacchi 	.nf_short = "seec",
136*56566d3aSRobert Mustacchi 	.nf_desc = "Soft ECC Error Count",
137*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
138*56566d3aSRobert Mustacchi }, {
139*56566d3aSRobert Mustacchi 	OCP_F_SMART(e2e),
140*56566d3aSRobert Mustacchi 	.nf_short = "e2e",
141*56566d3aSRobert Mustacchi 	.nf_desc = "End to End Correction Counts",
142*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_e2e_bits)
143*56566d3aSRobert Mustacchi }, {
144*56566d3aSRobert Mustacchi 	OCP_F_SMART(sys_used),
145*56566d3aSRobert Mustacchi 	.nf_short = "sdu",
146*56566d3aSRobert Mustacchi 	.nf_desc = "System Data Percent Used",
147*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_PERCENT
148*56566d3aSRobert Mustacchi }, {
149*56566d3aSRobert Mustacchi 	OCP_F_SMART(refresh),
150*56566d3aSRobert Mustacchi 	.nf_short = "refresh",
151*56566d3aSRobert Mustacchi 	.nf_desc = "Refresh Counts",
152*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
153*56566d3aSRobert Mustacchi }, {
154*56566d3aSRobert Mustacchi 	OCP_F_SMART(udec),
155*56566d3aSRobert Mustacchi 	.nf_short = "udec",
156*56566d3aSRobert Mustacchi 	.nf_desc = "User Data Erase Counts",
157*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_udec_bits)
158*56566d3aSRobert Mustacchi }, {
159*56566d3aSRobert Mustacchi 	OCP_F_SMART(therm),
160*56566d3aSRobert Mustacchi 	.nf_short = "therm",
161*56566d3aSRobert Mustacchi 	.nf_desc = "Thermal Throttling Status and Count",
162*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_therm_bits)
163*56566d3aSRobert Mustacchi }, {
164*56566d3aSRobert Mustacchi 	OCP_F_SMART(dssd),
165*56566d3aSRobert Mustacchi 	.nf_short = "dssd",
166*56566d3aSRobert Mustacchi 	.nf_desc = "DSSD Specification Version",
167*56566d3aSRobert Mustacchi 	.nf_rev = 3,
168*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_smart_dssd_bits)
169*56566d3aSRobert Mustacchi }, {
170*56566d3aSRobert Mustacchi 	OCP_F_SMART(pcie_errcor),
171*56566d3aSRobert Mustacchi 	.nf_short = "pcicor",
172*56566d3aSRobert Mustacchi 	.nf_desc = "PCIe Correctable Error Count",
173*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
174*56566d3aSRobert Mustacchi }, {
175*56566d3aSRobert Mustacchi 	OCP_F_SMART(inc_shut),
176*56566d3aSRobert Mustacchi 	.nf_short = "incshut",
177*56566d3aSRobert Mustacchi 	.nf_desc = "Incomplete Shutdowns",
178*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
179*56566d3aSRobert Mustacchi }, {
180*56566d3aSRobert Mustacchi 	OCP_F_SMART(free),
181*56566d3aSRobert Mustacchi 	.nf_short = "freeblk",
182*56566d3aSRobert Mustacchi 	.nf_desc = "Percent Free Blocks",
183*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_PERCENT
184*56566d3aSRobert Mustacchi }, {
185*56566d3aSRobert Mustacchi 	OCP_F_SMART(cap_health),
186*56566d3aSRobert Mustacchi 	.nf_short = "cap",
187*56566d3aSRobert Mustacchi 	.nf_desc = "Capacitor Health",
188*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_PERCENT
189*56566d3aSRobert Mustacchi }, {
190*56566d3aSRobert Mustacchi 	OCP_F_SMART(nvme_base_errata),
191*56566d3aSRobert Mustacchi 	.nf_short = "baseev",
192*56566d3aSRobert Mustacchi 	.nf_desc = "NVMe Base Errata Version",
193*56566d3aSRobert Mustacchi 	.nf_rev = 3,
194*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_ASCII
195*56566d3aSRobert Mustacchi }, {
196*56566d3aSRobert Mustacchi 	OCP_F_SMART(nvme_cmd_errata),
197*56566d3aSRobert Mustacchi 	.nf_short = "cmdev",
198*56566d3aSRobert Mustacchi 	.nf_desc = "NVMe Command Set Errata Version",
199*56566d3aSRobert Mustacchi 	.nf_rev = 4,
200*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_ASCII
201*56566d3aSRobert Mustacchi }, {
202*56566d3aSRobert Mustacchi 	OCP_F_SMART(unaligned),
203*56566d3aSRobert Mustacchi 	.nf_short = "unalign",
204*56566d3aSRobert Mustacchi 	.nf_desc = "Unaligned I/O",
205*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
206*56566d3aSRobert Mustacchi }, {
207*56566d3aSRobert Mustacchi 	OCP_F_SMART(sec_vers),
208*56566d3aSRobert Mustacchi 	.nf_short = "secvers",
209*56566d3aSRobert Mustacchi 	.nf_desc = "Security Version Number",
210*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
211*56566d3aSRobert Mustacchi }, {
212*56566d3aSRobert Mustacchi 	OCP_F_SMART(nuse),
213*56566d3aSRobert Mustacchi 	.nf_short = "nuse",
214*56566d3aSRobert Mustacchi 	.nf_desc = "Total NUSE",
215*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
216*56566d3aSRobert Mustacchi }, {
217*56566d3aSRobert Mustacchi 	OCP_F_SMART(plp_start),
218*56566d3aSRobert Mustacchi 	.nf_short = "plp",
219*56566d3aSRobert Mustacchi 	.nf_desc = "PLP Start Count",
220*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
221*56566d3aSRobert Mustacchi }, {
222*56566d3aSRobert Mustacchi 	OCP_F_SMART(endurance),
223*56566d3aSRobert Mustacchi 	.nf_short = "endest",
224*56566d3aSRobert Mustacchi 	.nf_desc = "Endurance Estimate",
225*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_BYTES
226*56566d3aSRobert Mustacchi }, {
227*56566d3aSRobert Mustacchi 	OCP_F_SMART(pcie_retrain),
228*56566d3aSRobert Mustacchi 	.nf_short = "retrain",
229*56566d3aSRobert Mustacchi 	.nf_desc = "PCIe Link Retraining Count",
230*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
231*56566d3aSRobert Mustacchi }, {
232*56566d3aSRobert Mustacchi 	OCP_F_SMART(ps_change),
233*56566d3aSRobert Mustacchi 	.nf_short = "pstate",
234*56566d3aSRobert Mustacchi 	.nf_desc = "Power State Change Count",
235*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
236*56566d3aSRobert Mustacchi }, {
237*56566d3aSRobert Mustacchi 	OCP_F_SMART(min_fwrev),
238*56566d3aSRobert Mustacchi 	.nf_short = "minfw",
239*56566d3aSRobert Mustacchi 	.nf_desc = "Lowest Permitted Firmware Revision",
240*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_ASCII
241*56566d3aSRobert Mustacchi }, {
242*56566d3aSRobert Mustacchi 	OCP_F_SMART(vers),
243*56566d3aSRobert Mustacchi 	.nf_short = "lpv",
244*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page Version",
245*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
246*56566d3aSRobert Mustacchi }, {
247*56566d3aSRobert Mustacchi 	OCP_F_SMART(guid),
248*56566d3aSRobert Mustacchi 	.nf_short = "lpg",
249*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page GUID",
250*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_GUID
251*56566d3aSRobert Mustacchi } };
252*56566d3aSRobert Mustacchi 
253*56566d3aSRobert Mustacchi static uint32_t
ocp_vul_smart_getvers(const void * data,size_t len)254*56566d3aSRobert Mustacchi ocp_vul_smart_getvers(const void *data, size_t len)
255*56566d3aSRobert Mustacchi {
256*56566d3aSRobert Mustacchi 	if (len < sizeof (ocp_vul_smart_t)) {
257*56566d3aSRobert Mustacchi 		errx(-1, "cannot parse revision information, found 0x%zx "
258*56566d3aSRobert Mustacchi 		    "bytes, need at least 0x%zx", len,
259*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_smart_t));
260*56566d3aSRobert Mustacchi 	}
261*56566d3aSRobert Mustacchi 
262*56566d3aSRobert Mustacchi 	const ocp_vul_smart_t *log = data;
263*56566d3aSRobert Mustacchi 	return (log->osh_vers);
264*56566d3aSRobert Mustacchi }
265*56566d3aSRobert Mustacchi 
266*56566d3aSRobert Mustacchi const nvmeadm_log_field_info_t ocp_vul_smart_field_info = {
267*56566d3aSRobert Mustacchi 	.nlfi_log = "ocp/smart",
268*56566d3aSRobert Mustacchi 	.nlfi_fields = ocp_vul_smart_fields,
269*56566d3aSRobert Mustacchi 	.nlfi_nfields = ARRAY_SIZE(ocp_vul_smart_fields),
270*56566d3aSRobert Mustacchi 	.nlfi_min = sizeof (ocp_vul_smart_t),
271*56566d3aSRobert Mustacchi 	.nlfi_getrev = ocp_vul_smart_getvers
272*56566d3aSRobert Mustacchi };
273*56566d3aSRobert Mustacchi 
274*56566d3aSRobert Mustacchi #define	OCP_F_ERRREC(f)	.nf_off = offsetof(ocp_vul_errrec_t, oer_##f), \
275*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_errrec_t *)NULL)->oer_##f)
276*56566d3aSRobert Mustacchi 
277*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_errrec_pra_bits[] = { {
278*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
279*56566d3aSRobert Mustacchi 	.nfb_short = "ctrl",
280*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe Controller Reset",
281*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
282*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
283*56566d3aSRobert Mustacchi }, {
284*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
285*56566d3aSRobert Mustacchi 	.nfb_short = "subsys",
286*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe Subsystem Reset",
287*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
288*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
289*56566d3aSRobert Mustacchi }, {
290*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
291*56566d3aSRobert Mustacchi 	.nfb_short = "flr",
292*56566d3aSRobert Mustacchi 	.nfb_desc = "PCIe Function Level Reset",
293*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
294*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
295*56566d3aSRobert Mustacchi }, {
296*56566d3aSRobert Mustacchi 	.nfb_lowbit = 3, .nfb_hibit = 3,
297*56566d3aSRobert Mustacchi 	.nfb_short = "perst",
298*56566d3aSRobert Mustacchi 	.nfb_desc = "PERST#",
299*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
300*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
301*56566d3aSRobert Mustacchi }, {
302*56566d3aSRobert Mustacchi 	.nfb_lowbit = 4, .nfb_hibit = 4,
303*56566d3aSRobert Mustacchi 	.nfb_short = "power",
304*56566d3aSRobert Mustacchi 	.nfb_desc = "Main Power Cycle",
305*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
306*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
307*56566d3aSRobert Mustacchi }, {
308*56566d3aSRobert Mustacchi 	.nfb_lowbit = 5, .nfb_hibit = 5,
309*56566d3aSRobert Mustacchi 	.nfb_short = "hotrst",
310*56566d3aSRobert Mustacchi 	.nfb_desc = "PCIe Conventional Hot Reset",
311*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
312*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
313*56566d3aSRobert Mustacchi } };
314*56566d3aSRobert Mustacchi 
315*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_errrec_dra_bits[] = { {
316*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
317*56566d3aSRobert Mustacchi 	.nfb_short = "none",
318*56566d3aSRobert Mustacchi 	.nfb_desc = "No Action",
319*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
320*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
321*56566d3aSRobert Mustacchi }, {
322*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
323*56566d3aSRobert Mustacchi 	.nfb_short = "fmt",
324*56566d3aSRobert Mustacchi 	.nfb_desc = "Format NVM",
325*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
326*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
327*56566d3aSRobert Mustacchi }, {
328*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
329*56566d3aSRobert Mustacchi 	.nfb_short = "vsc",
330*56566d3aSRobert Mustacchi 	.nfb_desc = "Vendor Specific Command",
331*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
332*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
333*56566d3aSRobert Mustacchi }, {
334*56566d3aSRobert Mustacchi 	.nfb_lowbit = 3, .nfb_hibit = 3,
335*56566d3aSRobert Mustacchi 	.nfb_short = "valys",
336*56566d3aSRobert Mustacchi 	.nfb_desc = "Vendor Analysis",
337*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
338*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
339*56566d3aSRobert Mustacchi }, {
340*56566d3aSRobert Mustacchi 	.nfb_lowbit = 4, .nfb_hibit = 4,
341*56566d3aSRobert Mustacchi 	.nfb_short = "rep",
342*56566d3aSRobert Mustacchi 	.nfb_desc = "Device Replacement",
343*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
344*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
345*56566d3aSRobert Mustacchi }, {
346*56566d3aSRobert Mustacchi 	.nfb_lowbit = 5, .nfb_hibit = 5,
347*56566d3aSRobert Mustacchi 	.nfb_short = "san",
348*56566d3aSRobert Mustacchi 	.nfb_desc = "Sanitize",
349*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
350*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
351*56566d3aSRobert Mustacchi }, {
352*56566d3aSRobert Mustacchi 	.nfb_lowbit = 6, .nfb_hibit = 6,
353*56566d3aSRobert Mustacchi 	.nfb_short = "udl",
354*56566d3aSRobert Mustacchi 	.nfb_desc = "User Data Loss",
355*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
356*56566d3aSRobert Mustacchi 	.nfb_strs = { "not required", "required" }
357*56566d3aSRobert Mustacchi } };
358*56566d3aSRobert Mustacchi 
359*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_errrec_devcap_bits[] = { {
360*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
361*56566d3aSRobert Mustacchi 	.nfb_short = "aen",
362*56566d3aSRobert Mustacchi 	.nfb_desc = "Panic AEN",
363*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
364*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
365*56566d3aSRobert Mustacchi }, {
366*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
367*56566d3aSRobert Mustacchi 	.nfb_short = "cfs",
368*56566d3aSRobert Mustacchi 	.nfb_desc = "Panic CFS",
369*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
370*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
371*56566d3aSRobert Mustacchi } };
372*56566d3aSRobert Mustacchi 
373*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_errrec_fields[] = { {
374*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(prwt),
375*56566d3aSRobert Mustacchi 	.nf_short = "prwt",
376*56566d3aSRobert Mustacchi 	.nf_desc = "Panic Reset Wait Time",
377*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
378*56566d3aSRobert Mustacchi }, {
379*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(pra),
380*56566d3aSRobert Mustacchi 	.nf_short = "pra",
381*56566d3aSRobert Mustacchi 	.nf_desc = "Panic Reset Action",
382*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_errrec_pra_bits)
383*56566d3aSRobert Mustacchi }, {
384*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(dra),
385*56566d3aSRobert Mustacchi 	.nf_short = "dra",
386*56566d3aSRobert Mustacchi 	.nf_desc = "Device Recovery Action 1",
387*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_errrec_dra_bits)
388*56566d3aSRobert Mustacchi }, {
389*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(panic_id),
390*56566d3aSRobert Mustacchi 	.nf_short = "id",
391*56566d3aSRobert Mustacchi 	.nf_desc = "Panic ID",
392*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
393*56566d3aSRobert Mustacchi }, {
394*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(devcap),
395*56566d3aSRobert Mustacchi 	.nf_short = "devcap",
396*56566d3aSRobert Mustacchi 	.nf_desc = "Device Capabilities",
397*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_errrec_devcap_bits)
398*56566d3aSRobert Mustacchi }, {
399*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(vsr_opcode),
400*56566d3aSRobert Mustacchi 	.nf_short = "vsro",
401*56566d3aSRobert Mustacchi 	.nf_desc = "Vendor Specific Recovery Opcode",
402*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
403*56566d3aSRobert Mustacchi }, {
404*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(vsr_cdw12),
405*56566d3aSRobert Mustacchi 	.nf_short = "vcdw12",
406*56566d3aSRobert Mustacchi 	.nf_desc = "Vendor Specific Command CDW12",
407*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
408*56566d3aSRobert Mustacchi }, {
409*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(vsr_cdw13),
410*56566d3aSRobert Mustacchi 	.nf_short = "vcdw13",
411*56566d3aSRobert Mustacchi 	.nf_desc = "Vendor Specific Command CDW13",
412*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
413*56566d3aSRobert Mustacchi }, {
414*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(vsr_to),
415*56566d3aSRobert Mustacchi 	.nf_short = "vsct",
416*56566d3aSRobert Mustacchi 	.nf_desc = "Vendor Specific Command Timeout",
417*56566d3aSRobert Mustacchi 	.nf_rev = 2,
418*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
419*56566d3aSRobert Mustacchi }, {
420*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(dra2),
421*56566d3aSRobert Mustacchi 	.nf_short = "dra2",
422*56566d3aSRobert Mustacchi 	.nf_desc = "Device Recovery Action 2",
423*56566d3aSRobert Mustacchi 	.nf_rev = 3,
424*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_errrec_dra_bits)
425*56566d3aSRobert Mustacchi }, {
426*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(dra2_to),
427*56566d3aSRobert Mustacchi 	.nf_short = "dra2to",
428*56566d3aSRobert Mustacchi 	.nf_desc = "Device Recovery Action 2 Timeout",
429*56566d3aSRobert Mustacchi 	.nf_rev = 3,
430*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
431*56566d3aSRobert Mustacchi }, {
432*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(npanic),
433*56566d3aSRobert Mustacchi 	.nf_short = "npanic",
434*56566d3aSRobert Mustacchi 	.nf_desc = "Panic Count",
435*56566d3aSRobert Mustacchi 	.nf_rev = 3,
436*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
437*56566d3aSRobert Mustacchi }, {
438*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(old_panics[0]),
439*56566d3aSRobert Mustacchi 	.nf_short = "ppanic1",
440*56566d3aSRobert Mustacchi 	.nf_desc = "Previous Panic N-1",
441*56566d3aSRobert Mustacchi 	.nf_rev = 3,
442*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
443*56566d3aSRobert Mustacchi }, {
444*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(old_panics[1]),
445*56566d3aSRobert Mustacchi 	.nf_short = "ppanic2",
446*56566d3aSRobert Mustacchi 	.nf_desc = "Previous Panic N-2",
447*56566d3aSRobert Mustacchi 	.nf_rev = 3,
448*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
449*56566d3aSRobert Mustacchi }, {
450*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(old_panics[2]),
451*56566d3aSRobert Mustacchi 	.nf_short = "ppanic3",
452*56566d3aSRobert Mustacchi 	.nf_desc = "Previous Panic N-3",
453*56566d3aSRobert Mustacchi 	.nf_rev = 3,
454*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
455*56566d3aSRobert Mustacchi }, {
456*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(old_panics[3]),
457*56566d3aSRobert Mustacchi 	.nf_short = "ppanic4",
458*56566d3aSRobert Mustacchi 	.nf_desc = "Previous Panic N-4",
459*56566d3aSRobert Mustacchi 	.nf_rev = 3,
460*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
461*56566d3aSRobert Mustacchi }, {
462*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(vers),
463*56566d3aSRobert Mustacchi 	.nf_short = "lpv",
464*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page Version",
465*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
466*56566d3aSRobert Mustacchi }, {
467*56566d3aSRobert Mustacchi 	OCP_F_ERRREC(guid),
468*56566d3aSRobert Mustacchi 	.nf_short = "lpg",
469*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page GUID",
470*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_GUID
471*56566d3aSRobert Mustacchi } };
472*56566d3aSRobert Mustacchi 
473*56566d3aSRobert Mustacchi static uint32_t
ocp_vul_errrec_getvers(const void * data,size_t len)474*56566d3aSRobert Mustacchi ocp_vul_errrec_getvers(const void *data, size_t len)
475*56566d3aSRobert Mustacchi {
476*56566d3aSRobert Mustacchi 	if (len < sizeof (ocp_vul_errrec_t)) {
477*56566d3aSRobert Mustacchi 		errx(-1, "cannot parse revision information, found 0x%zx "
478*56566d3aSRobert Mustacchi 		    "bytes, need at least 0x%zx", len,
479*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_errrec_t));
480*56566d3aSRobert Mustacchi 	}
481*56566d3aSRobert Mustacchi 
482*56566d3aSRobert Mustacchi 	const ocp_vul_errrec_t *log = data;
483*56566d3aSRobert Mustacchi 	return (log->oer_vers);
484*56566d3aSRobert Mustacchi }
485*56566d3aSRobert Mustacchi 
486*56566d3aSRobert Mustacchi const nvmeadm_log_field_info_t ocp_vul_errrec_field_info = {
487*56566d3aSRobert Mustacchi 	.nlfi_log = "ocp/errrec",
488*56566d3aSRobert Mustacchi 	.nlfi_fields = ocp_vul_errrec_fields,
489*56566d3aSRobert Mustacchi 	.nlfi_nfields = ARRAY_SIZE(ocp_vul_errrec_fields),
490*56566d3aSRobert Mustacchi 	.nlfi_min = sizeof (ocp_vul_errrec_t),
491*56566d3aSRobert Mustacchi 	.nlfi_getrev = ocp_vul_errrec_getvers
492*56566d3aSRobert Mustacchi };
493*56566d3aSRobert Mustacchi 
494*56566d3aSRobert Mustacchi #define	OCP_F_DEVCAP(f)	.nf_off = offsetof(ocp_vul_devcap_t, odc_##f), \
495*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_devcap_t *)NULL)->odc_##f)
496*56566d3aSRobert Mustacchi 
497*56566d3aSRobert Mustacchi #define	OCP_F_DEVCAP_PSD(f)	{ .nf_off = offsetof(ocp_vul_devcap_t, \
498*56566d3aSRobert Mustacchi 	odc_dssd[f]), \
499*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_devcap_t *)NULL)->odc_dssd[f]), \
500*56566d3aSRobert Mustacchi 	.nf_short = "psd" #f, .nf_desc = "DSSD Power State Descriptor " #f, \
501*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_psd_bits) }
502*56566d3aSRobert Mustacchi 
503*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_oob_bits[] = { {
504*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
505*56566d3aSRobert Mustacchi 	.nfb_short = "smbus",
506*56566d3aSRobert Mustacchi 	.nfb_desc = "MCTP over SMBus",
507*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
508*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
509*56566d3aSRobert Mustacchi }, {
510*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
511*56566d3aSRobert Mustacchi 	.nfb_short = "vdm",
512*56566d3aSRobert Mustacchi 	.nfb_desc = "MCTP over PCIe VDM",
513*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
514*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
515*56566d3aSRobert Mustacchi }, {
516*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
517*56566d3aSRobert Mustacchi 	.nfb_short = "bmc",
518*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe Basic Management Command",
519*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
520*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
521*56566d3aSRobert Mustacchi }, {
522*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
523*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
524*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets OOB Management Requirements",
525*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
526*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
527*56566d3aSRobert Mustacchi } };
528*56566d3aSRobert Mustacchi 
529*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_wz_bits[] = { {
530*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
531*56566d3aSRobert Mustacchi 	.nfb_short = "wz",
532*56566d3aSRobert Mustacchi 	.nfb_desc = "Write Zeros Command",
533*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
534*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
535*56566d3aSRobert Mustacchi }, {
536*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
537*56566d3aSRobert Mustacchi 	.nfb_short = "deac",
538*56566d3aSRobert Mustacchi 	.nfb_desc = "Setting DEAC Bit",
539*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
540*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
541*56566d3aSRobert Mustacchi }, {
542*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
543*56566d3aSRobert Mustacchi 	.nfb_short = "fua",
544*56566d3aSRobert Mustacchi 	.nfb_desc = "Setting FUA Bit",
545*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
546*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
547*56566d3aSRobert Mustacchi }, {
548*56566d3aSRobert Mustacchi 	.nfb_lowbit = 3, .nfb_hibit = 3,
549*56566d3aSRobert Mustacchi 	.nfb_short = "io5",
550*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe-IO-5 Requirements",
551*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
552*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
553*56566d3aSRobert Mustacchi }, {
554*56566d3aSRobert Mustacchi 	.nfb_lowbit = 4, .nfb_hibit = 4,
555*56566d3aSRobert Mustacchi 	.nfb_short = "io6",
556*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe-IO-6 Requirements",
557*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
558*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
559*56566d3aSRobert Mustacchi }, {
560*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
561*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
562*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets Write Zeros Requirements",
563*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
564*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
565*56566d3aSRobert Mustacchi } };
566*56566d3aSRobert Mustacchi 
567*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_san_bits[] = { {
568*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
569*56566d3aSRobert Mustacchi 	.nfb_short = "san",
570*56566d3aSRobert Mustacchi 	.nfb_desc = "Sanitize Command",
571*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
572*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
573*56566d3aSRobert Mustacchi }, {
574*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
575*56566d3aSRobert Mustacchi 	.nfb_short = "crypto",
576*56566d3aSRobert Mustacchi 	.nfb_desc = "Crypto-Erase",
577*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
578*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
579*56566d3aSRobert Mustacchi }, {
580*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
581*56566d3aSRobert Mustacchi 	.nfb_short = "block",
582*56566d3aSRobert Mustacchi 	.nfb_desc = "Block Erase",
583*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
584*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
585*56566d3aSRobert Mustacchi }, {
586*56566d3aSRobert Mustacchi 	.nfb_lowbit = 3, .nfb_hibit = 3,
587*56566d3aSRobert Mustacchi 	.nfb_short = "ovr",
588*56566d3aSRobert Mustacchi 	.nfb_desc = "Overwrite",
589*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
590*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
591*56566d3aSRobert Mustacchi }, {
592*56566d3aSRobert Mustacchi 	.nfb_lowbit = 4, .nfb_hibit = 4,
593*56566d3aSRobert Mustacchi 	.nfb_short = "dea",
594*56566d3aSRobert Mustacchi 	.nfb_desc = "Deallocate LBAs",
595*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
596*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
597*56566d3aSRobert Mustacchi }, {
598*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
599*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
600*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets Sanitize Requirements",
601*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
602*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
603*56566d3aSRobert Mustacchi } };
604*56566d3aSRobert Mustacchi 
605*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_ds_bits[] = { {
606*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
607*56566d3aSRobert Mustacchi 	.nfb_short = "dsmgmt",
608*56566d3aSRobert Mustacchi 	.nfb_desc = "Dataset Management Command",
609*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
610*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
611*56566d3aSRobert Mustacchi }, {
612*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
613*56566d3aSRobert Mustacchi 	.nfb_short = "ad",
614*56566d3aSRobert Mustacchi 	.nfb_desc = "Attribute Deallocate",
615*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
616*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
617*56566d3aSRobert Mustacchi }, {
618*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
619*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
620*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets Dataset Management Requirements",
621*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
622*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
623*56566d3aSRobert Mustacchi } };
624*56566d3aSRobert Mustacchi 
625*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_wu_bits[] = { {
626*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
627*56566d3aSRobert Mustacchi 	.nfb_short = "wu",
628*56566d3aSRobert Mustacchi 	.nfb_desc = "Write Uncorrectable Command",
629*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
630*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
631*56566d3aSRobert Mustacchi }, {
632*56566d3aSRobert Mustacchi 	.nfb_lowbit = 1, .nfb_hibit = 1,
633*56566d3aSRobert Mustacchi 	.nfb_short = "slba",
634*56566d3aSRobert Mustacchi 	.nfb_desc = "Single LBA",
635*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
636*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
637*56566d3aSRobert Mustacchi }, {
638*56566d3aSRobert Mustacchi 	.nfb_lowbit = 2, .nfb_hibit = 2,
639*56566d3aSRobert Mustacchi 	.nfb_short = "maxlba",
640*56566d3aSRobert Mustacchi 	.nfb_desc = "Maximum Number of LBAs",
641*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
642*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
643*56566d3aSRobert Mustacchi }, {
644*56566d3aSRobert Mustacchi 	.nfb_lowbit = 3, .nfb_hibit = 3,
645*56566d3aSRobert Mustacchi 	.nfb_short = "io14",
646*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe-IO-14",
647*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
648*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
649*56566d3aSRobert Mustacchi }, {
650*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
651*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
652*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets Write Uncorrectable Requirements",
653*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
654*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
655*56566d3aSRobert Mustacchi } };
656*56566d3aSRobert Mustacchi 
657*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_fuse_bits[] = { {
658*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 0,
659*56566d3aSRobert Mustacchi 	.nfb_short = "cmpwr",
660*56566d3aSRobert Mustacchi 	.nfb_desc = "Compare and Write Fused Command",
661*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
662*56566d3aSRobert Mustacchi 	.nfb_strs = { "unsupported", "supported" }
663*56566d3aSRobert Mustacchi }, {
664*56566d3aSRobert Mustacchi 	.nfb_lowbit = 15, .nfb_hibit = 15,
665*56566d3aSRobert Mustacchi 	.nfb_short = "pass",
666*56566d3aSRobert Mustacchi 	.nfb_desc = "Meets Fused Command Requirements",
667*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
668*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
669*56566d3aSRobert Mustacchi } };
670*56566d3aSRobert Mustacchi 
671*56566d3aSRobert Mustacchi static const nvmeadm_field_bit_t ocp_vul_devcap_psd_bits[] = {  {
672*56566d3aSRobert Mustacchi 	.nfb_lowbit = 0, .nfb_hibit = 4,
673*56566d3aSRobert Mustacchi 	.nfb_short = "ps",
674*56566d3aSRobert Mustacchi 	.nfb_desc = "NVMe Power State",
675*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_HEX
676*56566d3aSRobert Mustacchi }, {
677*56566d3aSRobert Mustacchi 	.nfb_lowbit = 7, .nfb_hibit = 7,
678*56566d3aSRobert Mustacchi 	.nfb_short = "valid",
679*56566d3aSRobert Mustacchi 	.nfb_desc = "Valid DSSD Power State",
680*56566d3aSRobert Mustacchi 	.nfb_type = NVMEADM_FT_STRMAP,
681*56566d3aSRobert Mustacchi 	.nfb_strs = { "no", "yes" }
682*56566d3aSRobert Mustacchi } };
683*56566d3aSRobert Mustacchi 
684*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_devcap_fields[] = { {
685*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(nports),
686*56566d3aSRobert Mustacchi 	.nf_short = "nports",
687*56566d3aSRobert Mustacchi 	.nf_desc = "PCI Express Ports",
688*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
689*56566d3aSRobert Mustacchi }, {
690*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(oob_sup),
691*56566d3aSRobert Mustacchi 	.nf_short = "oob",
692*56566d3aSRobert Mustacchi 	.nf_desc = "OOB Management Support",
693*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_oob_bits)
694*56566d3aSRobert Mustacchi }, {
695*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(wz_sup),
696*56566d3aSRobert Mustacchi 	.nf_short = "wz",
697*56566d3aSRobert Mustacchi 	.nf_desc = "Write Zeroes Command Support",
698*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_wz_bits)
699*56566d3aSRobert Mustacchi }, {
700*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(san_sup),
701*56566d3aSRobert Mustacchi 	.nf_short = "san",
702*56566d3aSRobert Mustacchi 	.nf_desc = "Sanitize Command Support",
703*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_san_bits)
704*56566d3aSRobert Mustacchi }, {
705*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(dsmgmt_sup),
706*56566d3aSRobert Mustacchi 	.nf_short = "ds",
707*56566d3aSRobert Mustacchi 	.nf_desc = "Dataset Management Support",
708*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_ds_bits)
709*56566d3aSRobert Mustacchi }, {
710*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(wunc_sup),
711*56566d3aSRobert Mustacchi 	.nf_short = "wu",
712*56566d3aSRobert Mustacchi 	.nf_desc = "Write Uncorrectable Command Support",
713*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_wu_bits)
714*56566d3aSRobert Mustacchi }, {
715*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(fuse_sup),
716*56566d3aSRobert Mustacchi 	.nf_short = "fuse",
717*56566d3aSRobert Mustacchi 	.nf_desc = "Fused Operations Support",
718*56566d3aSRobert Mustacchi 	NVMEADM_F_BITS(ocp_vul_devcap_fuse_bits)
719*56566d3aSRobert Mustacchi }, {
720*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(dssd_min_valid),
721*56566d3aSRobert Mustacchi 	.nf_short = "minps",
722*56566d3aSRobert Mustacchi 	.nf_desc = "Minimum Valid DSSD Power State",
723*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
724*56566d3aSRobert Mustacchi },
725*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(1), OCP_F_DEVCAP_PSD(2), OCP_F_DEVCAP_PSD(3),
726*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(4), OCP_F_DEVCAP_PSD(5), OCP_F_DEVCAP_PSD(6),
727*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(7), OCP_F_DEVCAP_PSD(8), OCP_F_DEVCAP_PSD(9),
728*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(10), OCP_F_DEVCAP_PSD(11), OCP_F_DEVCAP_PSD(12),
729*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(13), OCP_F_DEVCAP_PSD(14), OCP_F_DEVCAP_PSD(15),
730*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(16), OCP_F_DEVCAP_PSD(17), OCP_F_DEVCAP_PSD(18),
731*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(19), OCP_F_DEVCAP_PSD(20), OCP_F_DEVCAP_PSD(21),
732*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(22), OCP_F_DEVCAP_PSD(23), OCP_F_DEVCAP_PSD(24),
733*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(25), OCP_F_DEVCAP_PSD(26), OCP_F_DEVCAP_PSD(27),
734*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(28), OCP_F_DEVCAP_PSD(29), OCP_F_DEVCAP_PSD(30),
735*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(31), OCP_F_DEVCAP_PSD(32), OCP_F_DEVCAP_PSD(33),
736*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(34), OCP_F_DEVCAP_PSD(35), OCP_F_DEVCAP_PSD(36),
737*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(37), OCP_F_DEVCAP_PSD(38), OCP_F_DEVCAP_PSD(39),
738*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(40), OCP_F_DEVCAP_PSD(41), OCP_F_DEVCAP_PSD(42),
739*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(43), OCP_F_DEVCAP_PSD(44), OCP_F_DEVCAP_PSD(45),
740*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(46), OCP_F_DEVCAP_PSD(47), OCP_F_DEVCAP_PSD(48),
741*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(49), OCP_F_DEVCAP_PSD(50), OCP_F_DEVCAP_PSD(51),
742*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(52), OCP_F_DEVCAP_PSD(53), OCP_F_DEVCAP_PSD(54),
743*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(55), OCP_F_DEVCAP_PSD(56), OCP_F_DEVCAP_PSD(57),
744*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(58), OCP_F_DEVCAP_PSD(59), OCP_F_DEVCAP_PSD(60),
745*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(61), OCP_F_DEVCAP_PSD(62), OCP_F_DEVCAP_PSD(63),
746*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(64), OCP_F_DEVCAP_PSD(65), OCP_F_DEVCAP_PSD(66),
747*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(67), OCP_F_DEVCAP_PSD(68), OCP_F_DEVCAP_PSD(69),
748*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(70), OCP_F_DEVCAP_PSD(71), OCP_F_DEVCAP_PSD(72),
749*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(73), OCP_F_DEVCAP_PSD(74), OCP_F_DEVCAP_PSD(75),
750*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(76), OCP_F_DEVCAP_PSD(77), OCP_F_DEVCAP_PSD(78),
751*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(79), OCP_F_DEVCAP_PSD(80), OCP_F_DEVCAP_PSD(81),
752*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(82), OCP_F_DEVCAP_PSD(83), OCP_F_DEVCAP_PSD(84),
753*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(85), OCP_F_DEVCAP_PSD(86), OCP_F_DEVCAP_PSD(87),
754*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(88), OCP_F_DEVCAP_PSD(89), OCP_F_DEVCAP_PSD(90),
755*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(91), OCP_F_DEVCAP_PSD(92), OCP_F_DEVCAP_PSD(93),
756*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(94), OCP_F_DEVCAP_PSD(95), OCP_F_DEVCAP_PSD(96),
757*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(97), OCP_F_DEVCAP_PSD(98), OCP_F_DEVCAP_PSD(99),
758*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(100), OCP_F_DEVCAP_PSD(101), OCP_F_DEVCAP_PSD(102),
759*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(103), OCP_F_DEVCAP_PSD(104), OCP_F_DEVCAP_PSD(105),
760*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(106), OCP_F_DEVCAP_PSD(107), OCP_F_DEVCAP_PSD(108),
761*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(109), OCP_F_DEVCAP_PSD(110), OCP_F_DEVCAP_PSD(111),
762*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(112), OCP_F_DEVCAP_PSD(113), OCP_F_DEVCAP_PSD(114),
763*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(115), OCP_F_DEVCAP_PSD(116), OCP_F_DEVCAP_PSD(117),
764*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(118), OCP_F_DEVCAP_PSD(119), OCP_F_DEVCAP_PSD(120),
765*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(121), OCP_F_DEVCAP_PSD(122), OCP_F_DEVCAP_PSD(123),
766*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(124), OCP_F_DEVCAP_PSD(125), OCP_F_DEVCAP_PSD(126),
767*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP_PSD(127),
768*56566d3aSRobert Mustacchi {
769*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(vers),
770*56566d3aSRobert Mustacchi 	.nf_short = "lpv",
771*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page Version",
772*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
773*56566d3aSRobert Mustacchi }, {
774*56566d3aSRobert Mustacchi 	OCP_F_DEVCAP(guid),
775*56566d3aSRobert Mustacchi 	.nf_short = "lpg",
776*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page GUID",
777*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_GUID
778*56566d3aSRobert Mustacchi } };
779*56566d3aSRobert Mustacchi 
780*56566d3aSRobert Mustacchi static uint32_t
ocp_vul_devcap_getvers(const void * data,size_t len)781*56566d3aSRobert Mustacchi ocp_vul_devcap_getvers(const void *data, size_t len)
782*56566d3aSRobert Mustacchi {
783*56566d3aSRobert Mustacchi 	if (len < sizeof (ocp_vul_devcap_t)) {
784*56566d3aSRobert Mustacchi 		errx(-1, "cannot parse revision information, found 0x%zx "
785*56566d3aSRobert Mustacchi 		    "bytes, need at least 0x%zx", len,
786*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_devcap_t));
787*56566d3aSRobert Mustacchi 	}
788*56566d3aSRobert Mustacchi 
789*56566d3aSRobert Mustacchi 	const ocp_vul_devcap_t *log = data;
790*56566d3aSRobert Mustacchi 	return (log->odc_vers);
791*56566d3aSRobert Mustacchi }
792*56566d3aSRobert Mustacchi 
793*56566d3aSRobert Mustacchi const nvmeadm_log_field_info_t ocp_vul_devcap_field_info = {
794*56566d3aSRobert Mustacchi 	.nlfi_log = "ocp/devcap",
795*56566d3aSRobert Mustacchi 	.nlfi_fields = ocp_vul_devcap_fields,
796*56566d3aSRobert Mustacchi 	.nlfi_nfields = ARRAY_SIZE(ocp_vul_devcap_fields),
797*56566d3aSRobert Mustacchi 	.nlfi_min = sizeof (ocp_vul_devcap_t),
798*56566d3aSRobert Mustacchi 	.nlfi_getrev = ocp_vul_devcap_getvers
799*56566d3aSRobert Mustacchi };
800*56566d3aSRobert Mustacchi 
801*56566d3aSRobert Mustacchi #define	OCP_F_UNSUP(f)	.nf_off = offsetof(ocp_vul_unsup_req_t, our_##f), \
802*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_unsup_req_t *)NULL)->our_##f)
803*56566d3aSRobert Mustacchi 
804*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_unsup_fields_head[] = { {
805*56566d3aSRobert Mustacchi 	OCP_F_UNSUP(nunsup),
806*56566d3aSRobert Mustacchi 	.nf_short = "count",
807*56566d3aSRobert Mustacchi 	.nf_desc = "Unsupported Count",
808*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
809*56566d3aSRobert Mustacchi } };
810*56566d3aSRobert Mustacchi 
811*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_unsup_fields_tail[] = { {
812*56566d3aSRobert Mustacchi 	OCP_F_UNSUP(vers),
813*56566d3aSRobert Mustacchi 	.nf_short = "lpv",
814*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page Version",
815*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
816*56566d3aSRobert Mustacchi }, {
817*56566d3aSRobert Mustacchi 	OCP_F_UNSUP(guid),
818*56566d3aSRobert Mustacchi 	.nf_short = "lpg",
819*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page GUID",
820*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_GUID
821*56566d3aSRobert Mustacchi } };
822*56566d3aSRobert Mustacchi 
823*56566d3aSRobert Mustacchi static uint32_t
ocp_vul_unsup_getvers(const void * data,size_t len)824*56566d3aSRobert Mustacchi ocp_vul_unsup_getvers(const void *data, size_t len)
825*56566d3aSRobert Mustacchi {
826*56566d3aSRobert Mustacchi 	if (len < sizeof (ocp_vul_unsup_req_t)) {
827*56566d3aSRobert Mustacchi 		errx(-1, "cannot parse revision information, found 0x%zx "
828*56566d3aSRobert Mustacchi 		    "bytes, need at least 0x%zx", len,
829*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_unsup_req_t));
830*56566d3aSRobert Mustacchi 	}
831*56566d3aSRobert Mustacchi 
832*56566d3aSRobert Mustacchi 	const ocp_vul_unsup_req_t *log = data;
833*56566d3aSRobert Mustacchi 	return (log->our_vers);
834*56566d3aSRobert Mustacchi }
835*56566d3aSRobert Mustacchi 
836*56566d3aSRobert Mustacchi /*
837*56566d3aSRobert Mustacchi  * We manually drive this so we can create the appropriate number of entries for
838*56566d3aSRobert Mustacchi  * the string table as there are a variable number of these.
839*56566d3aSRobert Mustacchi  */
840*56566d3aSRobert Mustacchi static bool
ocp_vul_unsup_drive(nvmeadm_field_print_t * print,const void * data,size_t len)841*56566d3aSRobert Mustacchi ocp_vul_unsup_drive(nvmeadm_field_print_t *print, const void *data, size_t len)
842*56566d3aSRobert Mustacchi {
843*56566d3aSRobert Mustacchi 	print->fp_header = NULL;
844*56566d3aSRobert Mustacchi 	print->fp_fields = ocp_vul_unsup_fields_head;
845*56566d3aSRobert Mustacchi 	print->fp_nfields = ARRAY_SIZE(ocp_vul_unsup_fields_head);
846*56566d3aSRobert Mustacchi 	print->fp_base = NULL;
847*56566d3aSRobert Mustacchi 	print->fp_data = data;
848*56566d3aSRobert Mustacchi 	print->fp_dlen = len;
849*56566d3aSRobert Mustacchi 	print->fp_off = 0;
850*56566d3aSRobert Mustacchi 	nvmeadm_field_print(print);
851*56566d3aSRobert Mustacchi 
852*56566d3aSRobert Mustacchi 	/*
853*56566d3aSRobert Mustacchi 	 * Look at the data and make sure we have an appropriate number of
854*56566d3aSRobert Mustacchi 	 * entries specified. While there is a uint16_t worth of entries the
855*56566d3aSRobert Mustacchi 	 * specification indicates there can be a maximum of 253.
856*56566d3aSRobert Mustacchi 	 */
857*56566d3aSRobert Mustacchi 	const ocp_vul_unsup_req_t *log = data;
858*56566d3aSRobert Mustacchi 	if (log->our_nunsup > 253) {
859*56566d3aSRobert Mustacchi 		warnx("log page has questionable data: log page count of "
860*56566d3aSRobert Mustacchi 		    "unsupported requirements %u exceeds spec max of 253",
861*56566d3aSRobert Mustacchi 		    log->our_nunsup);
862*56566d3aSRobert Mustacchi 	}
863*56566d3aSRobert Mustacchi 	size_t nlogs = MIN(log->our_nunsup, 253);
864*56566d3aSRobert Mustacchi 	for (size_t i = 0; i < nlogs; i++) {
865*56566d3aSRobert Mustacchi 		nvmeadm_field_t field;
866*56566d3aSRobert Mustacchi 		char shrt[32];
867*56566d3aSRobert Mustacchi 		char desc[128];
868*56566d3aSRobert Mustacchi 
869*56566d3aSRobert Mustacchi 		(void) snprintf(shrt, sizeof (shrt), "ureq%zu", i);
870*56566d3aSRobert Mustacchi 		(void) snprintf(desc, sizeof (desc), "Unsupported Requirement "
871*56566d3aSRobert Mustacchi 		    "%zu", i);
872*56566d3aSRobert Mustacchi 		(void) memset(&field, 0, sizeof (nvmeadm_field_t));
873*56566d3aSRobert Mustacchi 		field.nf_off = offsetof(ocp_vul_unsup_req_t, our_reqs[i]);
874*56566d3aSRobert Mustacchi 		field.nf_len = sizeof (ocp_req_str_t);
875*56566d3aSRobert Mustacchi 		field.nf_short = shrt;
876*56566d3aSRobert Mustacchi 		field.nf_desc = desc;
877*56566d3aSRobert Mustacchi 		field.nf_type = NVMEADM_FT_ASCIIZ;
878*56566d3aSRobert Mustacchi 
879*56566d3aSRobert Mustacchi 		print->fp_fields = &field;
880*56566d3aSRobert Mustacchi 		print->fp_nfields = 1;
881*56566d3aSRobert Mustacchi 		nvmeadm_field_print(print);
882*56566d3aSRobert Mustacchi 	}
883*56566d3aSRobert Mustacchi 
884*56566d3aSRobert Mustacchi 	print->fp_fields = ocp_vul_unsup_fields_tail;
885*56566d3aSRobert Mustacchi 	print->fp_nfields = ARRAY_SIZE(ocp_vul_unsup_fields_tail);
886*56566d3aSRobert Mustacchi 	nvmeadm_field_print(print);
887*56566d3aSRobert Mustacchi 	return (true);
888*56566d3aSRobert Mustacchi }
889*56566d3aSRobert Mustacchi 
890*56566d3aSRobert Mustacchi const nvmeadm_log_field_info_t ocp_vul_unsup_field_info = {
891*56566d3aSRobert Mustacchi 	.nlfi_log = "ocp/unsup",
892*56566d3aSRobert Mustacchi 	.nlfi_min = sizeof (ocp_vul_unsup_req_t),
893*56566d3aSRobert Mustacchi 	.nlfi_getrev = ocp_vul_unsup_getvers,
894*56566d3aSRobert Mustacchi 	.nlfi_drive = ocp_vul_unsup_drive
895*56566d3aSRobert Mustacchi };
896*56566d3aSRobert Mustacchi 
897*56566d3aSRobert Mustacchi #define	OCP_F_TELSTR(f)	.nf_off = offsetof(ocp_vul_telstr_t, ots_##f), \
898*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_telstr_t *)NULL)->ots_##f)
899*56566d3aSRobert Mustacchi 
900*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_telstr_fields[] = { {
901*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(vers),
902*56566d3aSRobert Mustacchi 	.nf_short = "lpv",
903*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page Version",
904*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX
905*56566d3aSRobert Mustacchi }, {
906*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(guid),
907*56566d3aSRobert Mustacchi 	.nf_short = "lpg",
908*56566d3aSRobert Mustacchi 	.nf_desc = "Log Page GUID",
909*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_GUID
910*56566d3aSRobert Mustacchi }, {
911*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(sls),
912*56566d3aSRobert Mustacchi 	.nf_short = "sls",
913*56566d3aSRobert Mustacchi 	.nf_desc = "Telemetry String Log Size",
914*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
915*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
916*56566d3aSRobert Mustacchi }, {
917*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(sits),
918*56566d3aSRobert Mustacchi 	.nf_short = "sits",
919*56566d3aSRobert Mustacchi 	.nf_desc = "Statistics Identifier String Table Start",
920*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
921*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
922*56566d3aSRobert Mustacchi }, {
923*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(sitz),
924*56566d3aSRobert Mustacchi 	.nf_short = "sitz",
925*56566d3aSRobert Mustacchi 	.nf_desc = "Statistics Identifier String Table Size",
926*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
927*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
928*56566d3aSRobert Mustacchi }, {
929*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(ests),
930*56566d3aSRobert Mustacchi 	.nf_short = "ests",
931*56566d3aSRobert Mustacchi 	.nf_desc = "Event String Table Start",
932*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
933*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
934*56566d3aSRobert Mustacchi }, {
935*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(estz),
936*56566d3aSRobert Mustacchi 	.nf_short = "estz",
937*56566d3aSRobert Mustacchi 	.nf_desc = "Event String Table Size",
938*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
939*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
940*56566d3aSRobert Mustacchi }, {
941*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(vuests),
942*56566d3aSRobert Mustacchi 	.nf_short = "vuests",
943*56566d3aSRobert Mustacchi 	.nf_desc = "VU Event String Table Start",
944*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
945*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
946*56566d3aSRobert Mustacchi }, {
947*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(vuestz),
948*56566d3aSRobert Mustacchi 	.nf_short = "vuestz",
949*56566d3aSRobert Mustacchi 	.nf_desc = "VU Event String Table Size",
950*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
951*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
952*56566d3aSRobert Mustacchi }, {
953*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(ascts),
954*56566d3aSRobert Mustacchi 	.nf_short = "asctss",
955*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII Table Start",
956*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
957*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
958*56566d3aSRobert Mustacchi }, {
959*56566d3aSRobert Mustacchi 	OCP_F_TELSTR(asctz),
960*56566d3aSRobert Mustacchi 	.nf_short = "asctsz",
961*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII Table Size",
962*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
963*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
964*56566d3aSRobert Mustacchi } };
965*56566d3aSRobert Mustacchi 
966*56566d3aSRobert Mustacchi #define	OCP_F_TELSTR_SIT(f)	.nf_off = offsetof(ocp_vul_telstr_sit_t, \
967*56566d3aSRobert Mustacchi 	ocp_sit_##f), \
968*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_telstr_sit_t *)NULL)->ocp_sit_##f)
969*56566d3aSRobert Mustacchi 
970*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_telstr_sit_fields[] = { {
971*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_SIT(id),
972*56566d3aSRobert Mustacchi 	.nf_short = "id",
973*56566d3aSRobert Mustacchi 	.nf_desc = "Vendor Unique Statistic Identifier",
974*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
975*56566d3aSRobert Mustacchi }, {
976*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_SIT(len),
977*56566d3aSRobert Mustacchi 	.nf_short = "len",
978*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII ID Length",
979*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
980*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_addend = 1 }
981*56566d3aSRobert Mustacchi }, {
982*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_SIT(off),
983*56566d3aSRobert Mustacchi 	.nf_short = "off",
984*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII ID Offset",
985*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
986*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
987*56566d3aSRobert Mustacchi } };
988*56566d3aSRobert Mustacchi 
989*56566d3aSRobert Mustacchi #define	OCP_F_TELSTR_EST(f)	.nf_off = offsetof(ocp_vul_telstr_est_t, \
990*56566d3aSRobert Mustacchi 	ocp_est_##f), \
991*56566d3aSRobert Mustacchi 	.nf_len = sizeof (((ocp_vul_telstr_est_t *)NULL)->ocp_est_##f)
992*56566d3aSRobert Mustacchi 
993*56566d3aSRobert Mustacchi /*
994*56566d3aSRobert Mustacchi  * This is the same currently for both the vendor unique and regular events so
995*56566d3aSRobert Mustacchi  * we use the same structure for the time being.
996*56566d3aSRobert Mustacchi  */
997*56566d3aSRobert Mustacchi static const nvmeadm_field_t ocp_vul_telstr_est_fields[] = { {
998*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_EST(class),
999*56566d3aSRobert Mustacchi 	.nf_short = "class",
1000*56566d3aSRobert Mustacchi 	.nf_desc = "Debug Event Class",
1001*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
1002*56566d3aSRobert Mustacchi }, {
1003*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_EST(eid),
1004*56566d3aSRobert Mustacchi 	.nf_short = "id",
1005*56566d3aSRobert Mustacchi 	.nf_desc = "Event Identifier",
1006*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
1007*56566d3aSRobert Mustacchi }, {
1008*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_EST(len),
1009*56566d3aSRobert Mustacchi 	.nf_short = "len",
1010*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII ID Length",
1011*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
1012*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_addend = 1 }
1013*56566d3aSRobert Mustacchi }, {
1014*56566d3aSRobert Mustacchi 	OCP_F_TELSTR_EST(off),
1015*56566d3aSRobert Mustacchi 	.nf_short = "off",
1016*56566d3aSRobert Mustacchi 	.nf_desc = "ASCII ID Offset",
1017*56566d3aSRobert Mustacchi 	.nf_type = NVMEADM_FT_HEX,
1018*56566d3aSRobert Mustacchi 	.nf_addend = { .nfa_shift = 2 }
1019*56566d3aSRobert Mustacchi } };
1020*56566d3aSRobert Mustacchi 
1021*56566d3aSRobert Mustacchi static uint32_t
ocp_vul_telstr_getvers(const void * data,size_t len)1022*56566d3aSRobert Mustacchi ocp_vul_telstr_getvers(const void *data, size_t len)
1023*56566d3aSRobert Mustacchi {
1024*56566d3aSRobert Mustacchi 	if (len < sizeof (ocp_vul_telstr_t)) {
1025*56566d3aSRobert Mustacchi 		errx(-1, "cannot parse revision information, found 0x%zx "
1026*56566d3aSRobert Mustacchi 		    "bytes, need at least 0x%zx", len,
1027*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_t));
1028*56566d3aSRobert Mustacchi 	}
1029*56566d3aSRobert Mustacchi 
1030*56566d3aSRobert Mustacchi 	const ocp_vul_telstr_t *log = data;
1031*56566d3aSRobert Mustacchi 	return (log->ots_vers);
1032*56566d3aSRobert Mustacchi }
1033*56566d3aSRobert Mustacchi 
1034*56566d3aSRobert Mustacchi static bool
ocp_vul_telstr_sanity(const char * name,uint64_t off_dw,uint64_t len_dw,size_t flen)1035*56566d3aSRobert Mustacchi ocp_vul_telstr_sanity(const char *name, uint64_t off_dw, uint64_t len_dw,
1036*56566d3aSRobert Mustacchi     size_t flen)
1037*56566d3aSRobert Mustacchi {
1038*56566d3aSRobert Mustacchi 	const uint64_t max_dw = UINT64_MAX / sizeof (uint32_t);
1039*56566d3aSRobert Mustacchi 
1040*56566d3aSRobert Mustacchi 	/*
1041*56566d3aSRobert Mustacchi 	 * These values are in units of uint32_t's. Make sure we can represent
1042*56566d3aSRobert Mustacchi 	 * them.
1043*56566d3aSRobert Mustacchi 	 */
1044*56566d3aSRobert Mustacchi 	if (off_dw > max_dw) {
1045*56566d3aSRobert Mustacchi 		warnx("telemetry log %s offset does not fit in a 64-bit "
1046*56566d3aSRobert Mustacchi 		    "quantity", name);
1047*56566d3aSRobert Mustacchi 		return (false);
1048*56566d3aSRobert Mustacchi 	}
1049*56566d3aSRobert Mustacchi 
1050*56566d3aSRobert Mustacchi 	if (len_dw > max_dw) {
1051*56566d3aSRobert Mustacchi 		warnx("telemetry log %s length does not fit in a 64-bit "
1052*56566d3aSRobert Mustacchi 		    "quantity", name);
1053*56566d3aSRobert Mustacchi 		return (false);
1054*56566d3aSRobert Mustacchi 	}
1055*56566d3aSRobert Mustacchi 
1056*56566d3aSRobert Mustacchi 	const uint64_t off_bytes = off_dw << 2;
1057*56566d3aSRobert Mustacchi 	const uint64_t len_bytes = len_dw << 2;
1058*56566d3aSRobert Mustacchi 
1059*56566d3aSRobert Mustacchi 	if (len_bytes > UINT64_MAX - off_bytes) {
1060*56566d3aSRobert Mustacchi 		warnx("telemetry log %s final offset would overflow a 64-bit "
1061*56566d3aSRobert Mustacchi 		    "quantity", name);
1062*56566d3aSRobert Mustacchi 		return (false);
1063*56566d3aSRobert Mustacchi 	}
1064*56566d3aSRobert Mustacchi 
1065*56566d3aSRobert Mustacchi 	const uint64_t end = off_bytes + len_bytes;
1066*56566d3aSRobert Mustacchi 	if (end > flen) {
1067*56566d3aSRobert Mustacchi 		warnx("telemetry log %s exceeds beyond the end of the file",
1068*56566d3aSRobert Mustacchi 		    name);
1069*56566d3aSRobert Mustacchi 		return (false);
1070*56566d3aSRobert Mustacchi 	}
1071*56566d3aSRobert Mustacchi 
1072*56566d3aSRobert Mustacchi 	return (true);
1073*56566d3aSRobert Mustacchi }
1074*56566d3aSRobert Mustacchi 
1075*56566d3aSRobert Mustacchi /*
1076*56566d3aSRobert Mustacchi  * Set up a field to print an ASCII string and error if the embedded information
1077*56566d3aSRobert Mustacchi  * is not useful.
1078*56566d3aSRobert Mustacchi  */
1079*56566d3aSRobert Mustacchi static bool
ocp_vul_telstr_field_str(nvmeadm_field_t * field,uint16_t len0,uint64_t off_dw,uint64_t ascii_start,uint64_t ascii_len)1080*56566d3aSRobert Mustacchi ocp_vul_telstr_field_str(nvmeadm_field_t *field, uint16_t len0, uint64_t off_dw,
1081*56566d3aSRobert Mustacchi     uint64_t ascii_start, uint64_t ascii_len)
1082*56566d3aSRobert Mustacchi {
1083*56566d3aSRobert Mustacchi 	const uint64_t max_dw = UINT64_MAX / sizeof (uint32_t);
1084*56566d3aSRobert Mustacchi 
1085*56566d3aSRobert Mustacchi 	(void) memset(field, 0, sizeof (nvmeadm_field_t));
1086*56566d3aSRobert Mustacchi 
1087*56566d3aSRobert Mustacchi 	if (off_dw > max_dw) {
1088*56566d3aSRobert Mustacchi 		warnx("telemetry log ASCII string offset 0x%" PRIx64 " is "
1089*56566d3aSRobert Mustacchi 		    "not representable in a 64-bit quantity", off_dw);
1090*56566d3aSRobert Mustacchi 		return (false);
1091*56566d3aSRobert Mustacchi 	}
1092*56566d3aSRobert Mustacchi 
1093*56566d3aSRobert Mustacchi 	const uint64_t off = off_dw << 2;
1094*56566d3aSRobert Mustacchi 	const uint64_t len = len0 + 1;
1095*56566d3aSRobert Mustacchi 	if (len > UINT64_MAX - off) {
1096*56566d3aSRobert Mustacchi 		warnx("telemetry log ASCII string would overflow a 64-bit "
1097*56566d3aSRobert Mustacchi 		    "quantity: offset 0x%" PRIx64 ", length: %" PRIu64,
1098*56566d3aSRobert Mustacchi 		    off, len);
1099*56566d3aSRobert Mustacchi 		return (false);
1100*56566d3aSRobert Mustacchi 	}
1101*56566d3aSRobert Mustacchi 
1102*56566d3aSRobert Mustacchi 	if (off + len > ascii_start + ascii_len) {
1103*56566d3aSRobert Mustacchi 		warnx("telemetry log ASCII string exceeds ASCII table");
1104*56566d3aSRobert Mustacchi 		return (false);
1105*56566d3aSRobert Mustacchi 	}
1106*56566d3aSRobert Mustacchi 
1107*56566d3aSRobert Mustacchi 	field->nf_len = len;
1108*56566d3aSRobert Mustacchi 	field->nf_off = off + ascii_start;
1109*56566d3aSRobert Mustacchi 	field->nf_short = "str";
1110*56566d3aSRobert Mustacchi 	field->nf_desc = "String";
1111*56566d3aSRobert Mustacchi 	/*
1112*56566d3aSRobert Mustacchi 	 * Vendors are inconsistent as to whether the string table is padded
1113*56566d3aSRobert Mustacchi 	 * with zeros or spaces. Use ASCIIZ here to account for both.
1114*56566d3aSRobert Mustacchi 	 */
1115*56566d3aSRobert Mustacchi 	field->nf_type = NVMEADM_FT_ASCIIZ;
1116*56566d3aSRobert Mustacchi 
1117*56566d3aSRobert Mustacchi 	return (true);
1118*56566d3aSRobert Mustacchi }
1119*56566d3aSRobert Mustacchi 
1120*56566d3aSRobert Mustacchi /*
1121*56566d3aSRobert Mustacchi  * The telemetry string table is comprised of a fixed section and then a number
1122*56566d3aSRobert Mustacchi  * of variable sections that point into the ASCII table, somewhat analogous to
1123*56566d3aSRobert Mustacchi  * an ELF string table. There is no good way to see where the various strings
1124*56566d3aSRobert Mustacchi  * begin and end in the ASCII table. There is no strict separator between
1125*56566d3aSRobert Mustacchi  * entries. Entries are space padded to the next u32 aligned point generally;
1126*56566d3aSRobert Mustacchi  * however, the presence or lack of spaces doesn't tell us where something
1127*56566d3aSRobert Mustacchi  * begins or ends.
1128*56566d3aSRobert Mustacchi  *
1129*56566d3aSRobert Mustacchi  * As such, we manually drive this and relate the ASCII strings to the
1130*56566d3aSRobert Mustacchi  * corresponding other tables that we encounter. This isn't the most eloquent;
1131*56566d3aSRobert Mustacchi  * however, there's no other good way to do display this programmatically.
1132*56566d3aSRobert Mustacchi  */
1133*56566d3aSRobert Mustacchi static bool
ocp_vul_telstr_drive(nvmeadm_field_print_t * print,const void * data,size_t len)1134*56566d3aSRobert Mustacchi ocp_vul_telstr_drive(nvmeadm_field_print_t *print, const void *data, size_t len)
1135*56566d3aSRobert Mustacchi {
1136*56566d3aSRobert Mustacchi 	const ocp_vul_telstr_t *telstr = data;
1137*56566d3aSRobert Mustacchi 	bool ret = true;
1138*56566d3aSRobert Mustacchi 
1139*56566d3aSRobert Mustacchi 	print->fp_header = "Telemetry String Header";
1140*56566d3aSRobert Mustacchi 	print->fp_fields = ocp_vul_telstr_fields;
1141*56566d3aSRobert Mustacchi 	print->fp_nfields = ARRAY_SIZE(ocp_vul_telstr_fields);
1142*56566d3aSRobert Mustacchi 	print->fp_base = "tsh";
1143*56566d3aSRobert Mustacchi 	print->fp_data = data;
1144*56566d3aSRobert Mustacchi 	print->fp_dlen = len;
1145*56566d3aSRobert Mustacchi 	print->fp_off = 0;
1146*56566d3aSRobert Mustacchi 	nvmeadm_field_print(print);
1147*56566d3aSRobert Mustacchi 
1148*56566d3aSRobert Mustacchi 	/*
1149*56566d3aSRobert Mustacchi 	 * First take care of the 16 FIFOs. If a FIFO has a totally zero string,
1150*56566d3aSRobert Mustacchi 	 * then we should ignore it. This is the last data entry that we're
1151*56566d3aSRobert Mustacchi 	 * guaranteed we have space for. Everything else after this needs to be
1152*56566d3aSRobert Mustacchi 	 * checked for paranoia and consistency.
1153*56566d3aSRobert Mustacchi 	 */
1154*56566d3aSRobert Mustacchi 	for (size_t i = 0; i < 16; i++) {
1155*56566d3aSRobert Mustacchi 		char shrt[32], desc[128];
1156*56566d3aSRobert Mustacchi 		nvmeadm_field_t field;
1157*56566d3aSRobert Mustacchi 		const uint8_t empty[16] = { 0 };
1158*56566d3aSRobert Mustacchi 
1159*56566d3aSRobert Mustacchi 		(void) snprintf(shrt, sizeof (shrt), "fifo%zu", i);
1160*56566d3aSRobert Mustacchi 		(void) snprintf(desc, sizeof (desc), "FIFO %zu", i);
1161*56566d3aSRobert Mustacchi 		(void) memset(&field, 0, sizeof (nvmeadm_field_t));
1162*56566d3aSRobert Mustacchi 		field.nf_len = sizeof (((ocp_vul_telstr_t *)NULL)->ots_fifo0);
1163*56566d3aSRobert Mustacchi 		field.nf_off = offsetof(ocp_vul_telstr_t, ots_fifo0) +
1164*56566d3aSRobert Mustacchi 		    i * field.nf_len;
1165*56566d3aSRobert Mustacchi 		field.nf_short = shrt;
1166*56566d3aSRobert Mustacchi 		field.nf_desc = desc;
1167*56566d3aSRobert Mustacchi 		field.nf_type = NVMEADM_FT_ASCIIZ;
1168*56566d3aSRobert Mustacchi 
1169*56566d3aSRobert Mustacchi 		if (memcmp(data + field.nf_off, empty, sizeof (empty)) == 0) {
1170*56566d3aSRobert Mustacchi 			continue;
1171*56566d3aSRobert Mustacchi 		}
1172*56566d3aSRobert Mustacchi 
1173*56566d3aSRobert Mustacchi 		print->fp_header = NULL;
1174*56566d3aSRobert Mustacchi 		print->fp_fields = &field;
1175*56566d3aSRobert Mustacchi 		print->fp_nfields = 1;
1176*56566d3aSRobert Mustacchi 		nvmeadm_field_print(print);
1177*56566d3aSRobert Mustacchi 	}
1178*56566d3aSRobert Mustacchi 
1179*56566d3aSRobert Mustacchi 	/*
1180*56566d3aSRobert Mustacchi 	 * Sanity check that the rest of this makes sense. In particular, this
1181*56566d3aSRobert Mustacchi 	 * is supposed to be ordered SITS, ESTS, VUETS, ASCTS. Make sure these
1182*56566d3aSRobert Mustacchi 	 * don't overlap, that the offsets don't cause an overflow when we
1183*56566d3aSRobert Mustacchi 	 * expand them, etc.
1184*56566d3aSRobert Mustacchi 	 */
1185*56566d3aSRobert Mustacchi 	if (!ocp_vul_telstr_sanity("sit", telstr->ots_sits, telstr->ots_sitz,
1186*56566d3aSRobert Mustacchi 	    len) ||
1187*56566d3aSRobert Mustacchi 	    !ocp_vul_telstr_sanity("est", telstr->ots_ests, telstr->ots_estz,
1188*56566d3aSRobert Mustacchi 	    len) ||
1189*56566d3aSRobert Mustacchi 	    !ocp_vul_telstr_sanity("vuest", telstr->ots_vuests,
1190*56566d3aSRobert Mustacchi 	    telstr->ots_vuestz, len) ||
1191*56566d3aSRobert Mustacchi 	    !ocp_vul_telstr_sanity("asct", telstr->ots_ascts, telstr->ots_asctz,
1192*56566d3aSRobert Mustacchi 	    len)) {
1193*56566d3aSRobert Mustacchi 		return (false);
1194*56566d3aSRobert Mustacchi 	}
1195*56566d3aSRobert Mustacchi 
1196*56566d3aSRobert Mustacchi 	const uint64_t sit_start = telstr->ots_sits << 2;
1197*56566d3aSRobert Mustacchi 	const uint64_t sit_len = telstr->ots_sitz << 2;
1198*56566d3aSRobert Mustacchi 	const uint64_t est_start = telstr->ots_ests << 2;
1199*56566d3aSRobert Mustacchi 	const uint64_t est_len = telstr->ots_estz << 2;
1200*56566d3aSRobert Mustacchi 	const uint64_t vu_start = telstr->ots_vuests << 2;
1201*56566d3aSRobert Mustacchi 	const uint64_t vu_len = telstr->ots_vuestz << 2;
1202*56566d3aSRobert Mustacchi 	const uint64_t ascii_start = telstr->ots_ascts << 2;
1203*56566d3aSRobert Mustacchi 	const uint64_t ascii_len = telstr->ots_asctz << 2;
1204*56566d3aSRobert Mustacchi 
1205*56566d3aSRobert Mustacchi 	if (sit_start != offsetof(ocp_vul_telstr_t, ots_data)) {
1206*56566d3aSRobert Mustacchi 		warnx("invalid telemetry string table: SIT table starts at "
1207*56566d3aSRobert Mustacchi 		    "unexpected offset 0x%" PRIx64, sit_start);
1208*56566d3aSRobert Mustacchi 		return (false);
1209*56566d3aSRobert Mustacchi 	}
1210*56566d3aSRobert Mustacchi 
1211*56566d3aSRobert Mustacchi 	if (est_start < sit_start + sit_len) {
1212*56566d3aSRobert Mustacchi 		warnx("invalid telemetry string table: EST table starts before "
1213*56566d3aSRobert Mustacchi 		    "SIT table ends");
1214*56566d3aSRobert Mustacchi 		return (false);
1215*56566d3aSRobert Mustacchi 	}
1216*56566d3aSRobert Mustacchi 
1217*56566d3aSRobert Mustacchi 	if (vu_start < est_start + est_len) {
1218*56566d3aSRobert Mustacchi 		warnx("invalid telemetry string table: VUEST table starts "
1219*56566d3aSRobert Mustacchi 		    "before EST table ends");
1220*56566d3aSRobert Mustacchi 		return (false);
1221*56566d3aSRobert Mustacchi 	}
1222*56566d3aSRobert Mustacchi 
1223*56566d3aSRobert Mustacchi 	if (ascii_start < vu_start + vu_len) {
1224*56566d3aSRobert Mustacchi 		warnx("invalid telemetry string table: ASCT table starts "
1225*56566d3aSRobert Mustacchi 		    "before VUEST table ends");
1226*56566d3aSRobert Mustacchi 		return (false);
1227*56566d3aSRobert Mustacchi 	}
1228*56566d3aSRobert Mustacchi 
1229*56566d3aSRobert Mustacchi 	print->fp_header = "Statistic Identifier Table";
1230*56566d3aSRobert Mustacchi 	print->fp_base = "sit";
1231*56566d3aSRobert Mustacchi 	const uint64_t sit_nents = sit_len / sizeof (ocp_vul_telstr_sit_t);
1232*56566d3aSRobert Mustacchi 	for (uint64_t i = 0; i < sit_nents; i++) {
1233*56566d3aSRobert Mustacchi 		char shrt[32], desc[128];
1234*56566d3aSRobert Mustacchi 		const size_t off = sit_start + i *
1235*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_sit_t);
1236*56566d3aSRobert Mustacchi 		const ocp_vul_telstr_sit_t *sit = data + off;
1237*56566d3aSRobert Mustacchi 		nvmeadm_field_t cont;
1238*56566d3aSRobert Mustacchi 		nvmeadm_field_t fields[ARRAY_SIZE(ocp_vul_telstr_sit_fields) +
1239*56566d3aSRobert Mustacchi 		    1];
1240*56566d3aSRobert Mustacchi 
1241*56566d3aSRobert Mustacchi 		(void) memcpy(fields, ocp_vul_telstr_sit_fields,
1242*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_sit_fields));
1243*56566d3aSRobert Mustacchi 		if (!ocp_vul_telstr_field_str(&fields[ARRAY_SIZE(fields) - 1],
1244*56566d3aSRobert Mustacchi 		    sit->ocp_sit_len, sit->ocp_sit_off, ascii_start,
1245*56566d3aSRobert Mustacchi 		    ascii_len)) {
1246*56566d3aSRobert Mustacchi 			ret = false;
1247*56566d3aSRobert Mustacchi 			continue;
1248*56566d3aSRobert Mustacchi 		}
1249*56566d3aSRobert Mustacchi 
1250*56566d3aSRobert Mustacchi 		for (size_t f = 0; f < ARRAY_SIZE(fields) - 1; f++) {
1251*56566d3aSRobert Mustacchi 			fields[f].nf_off += off;
1252*56566d3aSRobert Mustacchi 		}
1253*56566d3aSRobert Mustacchi 
1254*56566d3aSRobert Mustacchi 		(void) snprintf(shrt, sizeof (shrt), "%" PRIu64, i);
1255*56566d3aSRobert Mustacchi 		(void) snprintf(desc, sizeof (desc), "SIT Entry %" PRIu64, i);
1256*56566d3aSRobert Mustacchi 		(void) memset(&cont, 0, sizeof (nvmeadm_field_t));
1257*56566d3aSRobert Mustacchi 		cont.nf_off = 0;
1258*56566d3aSRobert Mustacchi 		cont.nf_len = sizeof (ocp_vul_telstr_sit_t);
1259*56566d3aSRobert Mustacchi 		cont.nf_short = shrt;
1260*56566d3aSRobert Mustacchi 		cont.nf_desc = desc;
1261*56566d3aSRobert Mustacchi 		cont.nf_type = NVMEADM_FT_CONTAINER;
1262*56566d3aSRobert Mustacchi 		cont.nf_fields = fields;
1263*56566d3aSRobert Mustacchi 		cont.nf_nfields = ARRAY_SIZE(fields);
1264*56566d3aSRobert Mustacchi 
1265*56566d3aSRobert Mustacchi 		if (i > 0) {
1266*56566d3aSRobert Mustacchi 			print->fp_header = NULL;
1267*56566d3aSRobert Mustacchi 		}
1268*56566d3aSRobert Mustacchi 		print->fp_fields = &cont;
1269*56566d3aSRobert Mustacchi 		print->fp_nfields = 1;
1270*56566d3aSRobert Mustacchi 
1271*56566d3aSRobert Mustacchi 		nvmeadm_field_print(print);
1272*56566d3aSRobert Mustacchi 
1273*56566d3aSRobert Mustacchi 	}
1274*56566d3aSRobert Mustacchi 
1275*56566d3aSRobert Mustacchi 	print->fp_header = "Event Identifier Table";
1276*56566d3aSRobert Mustacchi 	print->fp_base = "est";
1277*56566d3aSRobert Mustacchi 	const uint64_t est_nents = est_len / sizeof (ocp_vul_telstr_est_t);
1278*56566d3aSRobert Mustacchi 	for (uint64_t i = 0; i < est_nents; i++) {
1279*56566d3aSRobert Mustacchi 		char shrt[32], desc[128];
1280*56566d3aSRobert Mustacchi 		const size_t off = est_start + i *
1281*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_est_t);
1282*56566d3aSRobert Mustacchi 		const ocp_vul_telstr_est_t *est = data + off;
1283*56566d3aSRobert Mustacchi 		nvmeadm_field_t cont;
1284*56566d3aSRobert Mustacchi 		nvmeadm_field_t fields[ARRAY_SIZE(ocp_vul_telstr_est_fields) +
1285*56566d3aSRobert Mustacchi 		    1];
1286*56566d3aSRobert Mustacchi 
1287*56566d3aSRobert Mustacchi 		(void) memcpy(fields, ocp_vul_telstr_est_fields,
1288*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_est_fields));
1289*56566d3aSRobert Mustacchi 		if (!ocp_vul_telstr_field_str(&fields[ARRAY_SIZE(fields) - 1],
1290*56566d3aSRobert Mustacchi 		    est->ocp_est_len, est->ocp_est_off, ascii_start,
1291*56566d3aSRobert Mustacchi 		    ascii_len)) {
1292*56566d3aSRobert Mustacchi 			ret = false;
1293*56566d3aSRobert Mustacchi 			continue;
1294*56566d3aSRobert Mustacchi 		}
1295*56566d3aSRobert Mustacchi 
1296*56566d3aSRobert Mustacchi 		for (size_t f = 0; f < ARRAY_SIZE(fields) - 1; f++) {
1297*56566d3aSRobert Mustacchi 			fields[f].nf_off += off;
1298*56566d3aSRobert Mustacchi 		}
1299*56566d3aSRobert Mustacchi 
1300*56566d3aSRobert Mustacchi 		(void) snprintf(shrt, sizeof (shrt), "%" PRIu64, i);
1301*56566d3aSRobert Mustacchi 		(void) snprintf(desc, sizeof (desc), "EST Entry %" PRIu64, i);
1302*56566d3aSRobert Mustacchi 		(void) memset(&cont, 0, sizeof (nvmeadm_field_t));
1303*56566d3aSRobert Mustacchi 		cont.nf_off = 0;
1304*56566d3aSRobert Mustacchi 		cont.nf_len = sizeof (ocp_vul_telstr_est_t);
1305*56566d3aSRobert Mustacchi 		cont.nf_short = shrt;
1306*56566d3aSRobert Mustacchi 		cont.nf_desc = desc;
1307*56566d3aSRobert Mustacchi 		cont.nf_type = NVMEADM_FT_CONTAINER;
1308*56566d3aSRobert Mustacchi 		cont.nf_fields = fields;
1309*56566d3aSRobert Mustacchi 		cont.nf_nfields = ARRAY_SIZE(fields);
1310*56566d3aSRobert Mustacchi 
1311*56566d3aSRobert Mustacchi 		if (i > 0) {
1312*56566d3aSRobert Mustacchi 			print->fp_header = NULL;
1313*56566d3aSRobert Mustacchi 		}
1314*56566d3aSRobert Mustacchi 		print->fp_fields = &cont;
1315*56566d3aSRobert Mustacchi 		print->fp_nfields = 1;
1316*56566d3aSRobert Mustacchi 
1317*56566d3aSRobert Mustacchi 		nvmeadm_field_print(print);
1318*56566d3aSRobert Mustacchi 	}
1319*56566d3aSRobert Mustacchi 
1320*56566d3aSRobert Mustacchi 	print->fp_header = "Vendor Unique Event Identifier Table";
1321*56566d3aSRobert Mustacchi 	print->fp_base = "vuest";
1322*56566d3aSRobert Mustacchi 	const uint64_t vuest_nents = vu_len / sizeof (ocp_vul_telstr_vuest_t);
1323*56566d3aSRobert Mustacchi 	for (uint64_t i = 0; i < vuest_nents; i++) {
1324*56566d3aSRobert Mustacchi 		char shrt[32], desc[128];
1325*56566d3aSRobert Mustacchi 		const size_t off = vu_start + i *
1326*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_vuest_t);
1327*56566d3aSRobert Mustacchi 		const ocp_vul_telstr_vuest_t *vuest = data + off;
1328*56566d3aSRobert Mustacchi 		nvmeadm_field_t cont;
1329*56566d3aSRobert Mustacchi 		nvmeadm_field_t fields[ARRAY_SIZE(ocp_vul_telstr_est_fields) +
1330*56566d3aSRobert Mustacchi 		    1];
1331*56566d3aSRobert Mustacchi 
1332*56566d3aSRobert Mustacchi 		(void) memcpy(fields, ocp_vul_telstr_est_fields,
1333*56566d3aSRobert Mustacchi 		    sizeof (ocp_vul_telstr_est_fields));
1334*56566d3aSRobert Mustacchi 		if (!ocp_vul_telstr_field_str(&fields[ARRAY_SIZE(fields) - 1],
1335*56566d3aSRobert Mustacchi 		    vuest->ocp_vuest_len, vuest->ocp_vuest_off, ascii_start,
1336*56566d3aSRobert Mustacchi 		    ascii_len)) {
1337*56566d3aSRobert Mustacchi 			ret = false;
1338*56566d3aSRobert Mustacchi 			continue;
1339*56566d3aSRobert Mustacchi 		}
1340*56566d3aSRobert Mustacchi 
1341*56566d3aSRobert Mustacchi 		for (size_t f = 0; f < ARRAY_SIZE(fields) - 1; f++) {
1342*56566d3aSRobert Mustacchi 			fields[f].nf_off += off;
1343*56566d3aSRobert Mustacchi 		}
1344*56566d3aSRobert Mustacchi 
1345*56566d3aSRobert Mustacchi 		(void) snprintf(shrt, sizeof (shrt), "%" PRIu64, i);
1346*56566d3aSRobert Mustacchi 		(void) snprintf(desc, sizeof (desc), "VUEST Entry %" PRIu64, i);
1347*56566d3aSRobert Mustacchi 		(void) memset(&cont, 0, sizeof (nvmeadm_field_t));
1348*56566d3aSRobert Mustacchi 		cont.nf_off = 0;
1349*56566d3aSRobert Mustacchi 		cont.nf_len = sizeof (ocp_vul_telstr_vuest_t);
1350*56566d3aSRobert Mustacchi 		cont.nf_short = shrt;
1351*56566d3aSRobert Mustacchi 		cont.nf_desc = desc;
1352*56566d3aSRobert Mustacchi 		cont.nf_type = NVMEADM_FT_CONTAINER;
1353*56566d3aSRobert Mustacchi 		cont.nf_fields = fields;
1354*56566d3aSRobert Mustacchi 		cont.nf_nfields = ARRAY_SIZE(fields);
1355*56566d3aSRobert Mustacchi 
1356*56566d3aSRobert Mustacchi 		if (i > 0) {
1357*56566d3aSRobert Mustacchi 			print->fp_header = NULL;
1358*56566d3aSRobert Mustacchi 		}
1359*56566d3aSRobert Mustacchi 		print->fp_fields = &cont;
1360*56566d3aSRobert Mustacchi 		print->fp_nfields = 1;
1361*56566d3aSRobert Mustacchi 
1362*56566d3aSRobert Mustacchi 		nvmeadm_field_print(print);
1363*56566d3aSRobert Mustacchi 	}
1364*56566d3aSRobert Mustacchi 
1365*56566d3aSRobert Mustacchi 	return (ret);
1366*56566d3aSRobert Mustacchi }
1367*56566d3aSRobert Mustacchi 
1368*56566d3aSRobert Mustacchi const nvmeadm_log_field_info_t ocp_vul_telstr_field_info = {
1369*56566d3aSRobert Mustacchi 	.nlfi_log = "ocp/telstr",
1370*56566d3aSRobert Mustacchi 	.nlfi_min = sizeof (ocp_vul_telstr_t),
1371*56566d3aSRobert Mustacchi 	.nlfi_getrev = ocp_vul_telstr_getvers,
1372*56566d3aSRobert Mustacchi 	.nlfi_drive = ocp_vul_telstr_drive
1373*56566d3aSRobert Mustacchi };
1374