1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 /*
17  * NVMe Firmware unit tests covering both download and activate, support, and
18  * related.
19  */
20 
21 #include <stdlib.h>
22 #include <sys/sysmacros.h>
23 #include <err.h>
24 
25 #include "nvme_unit.h"
26 
27 /*
28  * The offset and length change depending on the granularity.
29  */
30 static const nvme_unit_field_test_t firmware_field_tests[] = { {
31 	.nu_desc = "invalid fw load numd 4K gran (1)",
32 	.nu_fields = nvme_fw_load_fields,
33 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
34 	.nu_data = &nvme_ctrl_base_1v0,
35 	.nu_value = 0x0,
36 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
37 }, {
38 	.nu_desc = "invalid fw load numd 4K gran (2)",
39 	.nu_fields = nvme_fw_load_fields,
40 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
41 	.nu_data = &nvme_ctrl_base_1v0,
42 	.nu_value = 0x400000000,
43 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
44 }, {
45 	.nu_desc = "invalid fw load numd 4K gran (3)",
46 	.nu_fields = nvme_fw_load_fields,
47 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
48 	.nu_data = &nvme_ctrl_base_1v0,
49 	.nu_value = 0x1001,
50 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
51 }, {
52 	.nu_desc = "invalid fw load numd 4K gran (4)",
53 	.nu_fields = nvme_fw_load_fields,
54 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
55 	.nu_data = &nvme_ctrl_base_1v0,
56 	.nu_value = 0xfff,
57 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
58 }, {
59 	.nu_desc = "valid fw load numd 4K gran (1)",
60 	.nu_fields = nvme_fw_load_fields,
61 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
62 	.nu_data = &nvme_ctrl_base_1v0,
63 	.nu_value = 0x1000,
64 	.nu_ret = NVME_FIELD_ERR_OK
65 }, {
66 	.nu_desc = "valid fw load numd 4K gran (2)",
67 	.nu_fields = nvme_fw_load_fields,
68 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
69 	.nu_data = &nvme_ctrl_base_1v0,
70 	.nu_value = 0x1000000,
71 	.nu_ret = NVME_FIELD_ERR_OK
72 }, {
73 	.nu_desc = "valid fw load numd 4K gran (3)",
74 	.nu_fields = nvme_fw_load_fields,
75 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
76 	.nu_data = &nvme_ctrl_base_1v0,
77 	.nu_value = 0x43000,
78 	.nu_ret = NVME_FIELD_ERR_OK
79 }, {
80 	.nu_desc = "invalid fw load offset 4K gran (1)",
81 	.nu_fields = nvme_fw_load_fields,
82 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
83 	.nu_data = &nvme_ctrl_base_1v0,
84 	.nu_value = 0x1,
85 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
86 }, {
87 	.nu_desc = "invalid fw load offset 4K gran (2)",
88 	.nu_fields = nvme_fw_load_fields,
89 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
90 	.nu_data = &nvme_ctrl_base_1v0,
91 	.nu_value = 0x400000000,
92 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
93 }, {
94 	.nu_desc = "invalid fw load offset 4K gran (3)",
95 	.nu_fields = nvme_fw_load_fields,
96 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
97 	.nu_data = &nvme_ctrl_base_1v0,
98 	.nu_value = 0x1001,
99 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
100 }, {
101 	.nu_desc = "invalid fw load offset 4K gran (4)",
102 	.nu_fields = nvme_fw_load_fields,
103 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
104 	.nu_data = &nvme_ctrl_base_1v0,
105 	.nu_value = 0xfff,
106 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
107 }, {
108 	.nu_desc = "valid fw load offset 4K gran (1)",
109 	.nu_fields = nvme_fw_load_fields,
110 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
111 	.nu_data = &nvme_ctrl_base_1v0,
112 	.nu_value = 0x1000,
113 	.nu_ret = NVME_FIELD_ERR_OK
114 }, {
115 	.nu_desc = "valid fw load offset 4K gran (2)",
116 	.nu_fields = nvme_fw_load_fields,
117 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
118 	.nu_data = &nvme_ctrl_base_1v0,
119 	.nu_value = 0x1000000,
120 	.nu_ret = NVME_FIELD_ERR_OK
121 }, {
122 	.nu_desc = "valid fw load offset 4K gran (3)",
123 	.nu_fields = nvme_fw_load_fields,
124 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
125 	.nu_data = &nvme_ctrl_base_1v0,
126 	.nu_value = 0x43000,
127 	.nu_ret = NVME_FIELD_ERR_OK
128 }, {
129 	.nu_desc = "valid fw load offset 4K gran (4)",
130 	.nu_fields = nvme_fw_load_fields,
131 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
132 	.nu_data = &nvme_ctrl_base_1v0,
133 	.nu_value = 0x0,
134 	.nu_ret = NVME_FIELD_ERR_OK
135 }, {
136 	.nu_desc = "invalid fw load numd no gran (1)",
137 	.nu_fields = nvme_fw_load_fields,
138 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
139 	.nu_data = &nvme_ctrl_nogran_1v3,
140 	.nu_value = 0x0,
141 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
142 }, {
143 	.nu_desc = "invalid fw load numd no gran (2)",
144 	.nu_fields = nvme_fw_load_fields,
145 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
146 	.nu_data = &nvme_ctrl_nogran_1v3,
147 	.nu_value = 0x400000000,
148 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
149 }, {
150 	.nu_desc = "invalid fw load numd no gran (3)",
151 	.nu_fields = nvme_fw_load_fields,
152 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
153 	.nu_data = &nvme_ctrl_nogran_1v3,
154 	.nu_value = 0x1001,
155 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
156 }, {
157 	.nu_desc = "invalid fw load numd no gran (4)",
158 	.nu_fields = nvme_fw_load_fields,
159 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
160 	.nu_data = &nvme_ctrl_nogran_1v3,
161 	.nu_value = 0xfff,
162 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
163 }, {
164 	.nu_desc = "valid fw load numd no gran (1)",
165 	.nu_fields = nvme_fw_load_fields,
166 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
167 	.nu_data = &nvme_ctrl_nogran_1v3,
168 	.nu_value = 0x24,
169 	.nu_ret = NVME_FIELD_ERR_OK
170 }, {
171 	.nu_desc = "valid fw load numd no gran (2)",
172 	.nu_fields = nvme_fw_load_fields,
173 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
174 	.nu_data = &nvme_ctrl_nogran_1v3,
175 	.nu_value = 0x280,
176 	.nu_ret = NVME_FIELD_ERR_OK
177 }, {
178 	.nu_desc = "valid fw load numd no gran (3)",
179 	.nu_fields = nvme_fw_load_fields,
180 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
181 	.nu_data = &nvme_ctrl_nogran_1v3,
182 	.nu_value = 0x43000,
183 	.nu_ret = NVME_FIELD_ERR_OK
184 }, {
185 	.nu_desc = "invalid fw load offset no gran (1)",
186 	.nu_fields = nvme_fw_load_fields,
187 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
188 	.nu_data = &nvme_ctrl_nogran_1v3,
189 	.nu_value = 0x1,
190 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
191 }, {
192 	.nu_desc = "invalid fw load offset no gran (2)",
193 	.nu_fields = nvme_fw_load_fields,
194 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
195 	.nu_data = &nvme_ctrl_nogran_1v3,
196 	.nu_value = 0x400000000,
197 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
198 }, {
199 	.nu_desc = "invalid fw load offset no gran (3)",
200 	.nu_fields = nvme_fw_load_fields,
201 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
202 	.nu_data = &nvme_ctrl_nogran_1v3,
203 	.nu_value = 0x77,
204 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
205 }, {
206 	.nu_desc = "invalid fw load offset no gran (4)",
207 	.nu_fields = nvme_fw_load_fields,
208 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
209 	.nu_data = &nvme_ctrl_nogran_1v3,
210 	.nu_value = 0x79,
211 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
212 }, {
213 	.nu_desc = "valid fw load offset no gran (1)",
214 	.nu_fields = nvme_fw_load_fields,
215 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
216 	.nu_data = &nvme_ctrl_nogran_1v3,
217 	.nu_value = 0x4,
218 	.nu_ret = NVME_FIELD_ERR_OK
219 }, {
220 	.nu_desc = "valid fw load offset no gran (2)",
221 	.nu_fields = nvme_fw_load_fields,
222 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
223 	.nu_data = &nvme_ctrl_nogran_1v3,
224 	.nu_value = 0x78,
225 	.nu_ret = NVME_FIELD_ERR_OK
226 }, {
227 	.nu_desc = "valid fw load offset no gran (3)",
228 	.nu_fields = nvme_fw_load_fields,
229 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
230 	.nu_data = &nvme_ctrl_nogran_1v3,
231 	.nu_value = 0x4300c,
232 	.nu_ret = NVME_FIELD_ERR_OK
233 }, {
234 	.nu_desc = "valid fw load offset no gran (4)",
235 	.nu_fields = nvme_fw_load_fields,
236 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
237 	.nu_data = &nvme_ctrl_nogran_1v3,
238 	.nu_value = 0x0,
239 	.nu_ret = NVME_FIELD_ERR_OK
240 }, {
241 	.nu_desc = "invalid fw load numd 8k gran (1)",
242 	.nu_fields = nvme_fw_load_fields,
243 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
244 	.nu_data = &nvme_ctrl_8kgran_1v3,
245 	.nu_value = 0x0,
246 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
247 }, {
248 	.nu_desc = "invalid fw load numd 8k gran (2)",
249 	.nu_fields = nvme_fw_load_fields,
250 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
251 	.nu_data = &nvme_ctrl_8kgran_1v3,
252 	.nu_value = 0x400000000,
253 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
254 }, {
255 	.nu_desc = "invalid fw load numd 8k gran (3)",
256 	.nu_fields = nvme_fw_load_fields,
257 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
258 	.nu_data = &nvme_ctrl_8kgran_1v3,
259 	.nu_value = 0x1000,
260 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
261 }, {
262 	.nu_desc = "invalid fw load numd 8k gran (4)",
263 	.nu_fields = nvme_fw_load_fields,
264 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
265 	.nu_data = &nvme_ctrl_8kgran_1v3,
266 	.nu_value = 0x4004,
267 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
268 }, {
269 	.nu_desc = "valid fw load numd 8k gran (1)",
270 	.nu_fields = nvme_fw_load_fields,
271 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
272 	.nu_data = &nvme_ctrl_8kgran_1v3,
273 	.nu_value = 0x2000,
274 	.nu_ret = NVME_FIELD_ERR_OK
275 }, {
276 	.nu_desc = "valid fw load numd 8k gran (2)",
277 	.nu_fields = nvme_fw_load_fields,
278 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
279 	.nu_data = &nvme_ctrl_8kgran_1v3,
280 	.nu_value = 0x88000,
281 	.nu_ret = NVME_FIELD_ERR_OK
282 }, {
283 	.nu_desc = "valid fw load numd 8k gran (3)",
284 	.nu_fields = nvme_fw_load_fields,
285 	.nu_index = NVME_FW_LOAD_REQ_FIELD_NUMD,
286 	.nu_data = &nvme_ctrl_8kgran_1v3,
287 	.nu_value = 0x42000,
288 	.nu_ret = NVME_FIELD_ERR_OK
289 }, {
290 	.nu_desc = "invalid fw load offset 8k gran (1)",
291 	.nu_fields = nvme_fw_load_fields,
292 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
293 	.nu_data = &nvme_ctrl_8kgran_1v3,
294 	.nu_value = 0x1,
295 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
296 }, {
297 	.nu_desc = "invalid fw load offset 8k gran (2)",
298 	.nu_fields = nvme_fw_load_fields,
299 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
300 	.nu_data = &nvme_ctrl_8kgran_1v3,
301 	.nu_value = 0x400000000,
302 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
303 }, {
304 	.nu_desc = "invalid fw load offset 8k gran (3)",
305 	.nu_fields = nvme_fw_load_fields,
306 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
307 	.nu_data = &nvme_ctrl_8kgran_1v3,
308 	.nu_value = 0x77,
309 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
310 }, {
311 	.nu_desc = "invalid fw load offset 8k gran (4)",
312 	.nu_fields = nvme_fw_load_fields,
313 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
314 	.nu_data = &nvme_ctrl_8kgran_1v3,
315 	.nu_value = 0x79,
316 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
317 }, {
318 	.nu_desc = "valid fw load offset 8k gran (1)",
319 	.nu_fields = nvme_fw_load_fields,
320 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
321 	.nu_data = &nvme_ctrl_8kgran_1v3,
322 	.nu_value = 0x2000,
323 	.nu_ret = NVME_FIELD_ERR_OK
324 }, {
325 	.nu_desc = "valid fw load offset 8k gran (2)",
326 	.nu_fields = nvme_fw_load_fields,
327 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
328 	.nu_data = &nvme_ctrl_8kgran_1v3,
329 	.nu_value = 0x3cc2000,
330 	.nu_ret = NVME_FIELD_ERR_OK
331 }, {
332 	.nu_desc = "valid fw load offset 8k gran (3)",
333 	.nu_fields = nvme_fw_load_fields,
334 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
335 	.nu_data = &nvme_ctrl_8kgran_1v3,
336 	.nu_value = 0x18000,
337 	.nu_ret = NVME_FIELD_ERR_OK
338 }, {
339 	.nu_desc = "valid fw load offset 8k gran (4)",
340 	.nu_fields = nvme_fw_load_fields,
341 	.nu_index = NVME_FW_LOAD_REQ_FIELD_OFFSET,
342 	.nu_data = &nvme_ctrl_8kgran_1v3,
343 	.nu_value = 0x0,
344 	.nu_ret = NVME_FIELD_ERR_OK
345 }, {
346 	.nu_desc = "invalid fw slot (1 slot) (1)",
347 	.nu_fields = nvme_fw_commit_fields,
348 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
349 	.nu_data = &nvme_ctrl_base_1v0,
350 	.nu_value = 0x0,
351 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
352 }, {
353 	.nu_desc = "invalid fw slot (1 slot) (2)",
354 	.nu_fields = nvme_fw_commit_fields,
355 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
356 	.nu_data = &nvme_ctrl_base_1v0,
357 	.nu_value = 0x2,
358 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
359 }, {
360 	.nu_desc = "invalid fw slot (7 slot) (1)",
361 	.nu_fields = nvme_fw_commit_fields,
362 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
363 	.nu_data = &nvme_ctrl_8kgran_1v3,
364 	.nu_value = 0x0,
365 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
366 }, {
367 	.nu_desc = "invalid fw slot (7 slot) (1)",
368 	.nu_fields = nvme_fw_commit_fields,
369 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
370 	.nu_data = &nvme_ctrl_8kgran_1v3,
371 	.nu_value = 0x8,
372 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
373 }, {
374 	.nu_desc = "invalid fw slot (7 slot) (2)",
375 	.nu_fields = nvme_fw_commit_fields,
376 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
377 	.nu_data = &nvme_ctrl_8kgran_1v3,
378 	.nu_value = 0x23,
379 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
380 }, {
381 	.nu_desc = "invalid fw slot (3 slot) (1)",
382 	.nu_fields = nvme_fw_commit_fields,
383 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
384 	.nu_data = &nvme_ctrl_nogran_1v3,
385 	.nu_value = 0x4,
386 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
387 }, {
388 	.nu_desc = "valid fw slot (1 slot) (1)",
389 	.nu_fields = nvme_fw_commit_fields,
390 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
391 	.nu_data = &nvme_ctrl_base_1v0,
392 	.nu_value = 0x1,
393 	.nu_ret = NVME_FIELD_ERR_OK
394 }, {
395 	.nu_desc = "valid fw slot (7 slot) (1)",
396 	.nu_fields = nvme_fw_commit_fields,
397 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
398 	.nu_data = &nvme_ctrl_8kgran_1v3,
399 	.nu_value = 0x7,
400 	.nu_ret = NVME_FIELD_ERR_OK
401 }, {
402 	.nu_desc = "valid fw slot (7 slot) (2)",
403 	.nu_fields = nvme_fw_commit_fields,
404 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
405 	.nu_data = &nvme_ctrl_8kgran_1v3,
406 	.nu_value = 0x4,
407 	.nu_ret = NVME_FIELD_ERR_OK
408 }, {
409 	.nu_desc = "valid fw slot (3 slot) (1)",
410 	.nu_fields = nvme_fw_commit_fields,
411 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
412 	.nu_data = &nvme_ctrl_nogran_1v3,
413 	.nu_value = 0x3,
414 	.nu_ret = NVME_FIELD_ERR_OK
415 }, {
416 	.nu_desc = "valid fw slot (3 slot) (2)",
417 	.nu_fields = nvme_fw_commit_fields,
418 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
419 	.nu_data = &nvme_ctrl_nogran_1v3,
420 	.nu_value = 0x1,
421 	.nu_ret = NVME_FIELD_ERR_OK
422 }, {
423 	.nu_desc = "invalid fw action (1.0) (1)",
424 	.nu_fields = nvme_fw_commit_fields,
425 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
426 	.nu_data = &nvme_ctrl_base_1v0,
427 	.nu_value = NVME_FWC_ACTIVATE_IMMED,
428 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
429 }, {
430 	.nu_desc = "invalid fw action (1.0) (2)",
431 	.nu_fields = nvme_fw_commit_fields,
432 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_SLOT,
433 	.nu_data = &nvme_ctrl_base_1v0,
434 	.nu_value = 0x23,
435 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
436 }, {
437 	.nu_desc = "valid fw action (1.0) (1)",
438 	.nu_fields = nvme_fw_commit_fields,
439 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_ACT,
440 	.nu_data = &nvme_ctrl_base_1v0,
441 	.nu_value = 0x0,
442 	.nu_ret = NVME_FIELD_ERR_OK
443 }, {
444 	.nu_desc = "valid fw action (1.0) (2)",
445 	.nu_fields = nvme_fw_commit_fields,
446 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_ACT,
447 	.nu_data = &nvme_ctrl_base_1v0,
448 	.nu_value = 0x2,
449 	.nu_ret = NVME_FIELD_ERR_OK
450 }, {
451 	.nu_desc = "valid fw action (1.3)",
452 	.nu_fields = nvme_fw_commit_fields,
453 	.nu_index = NVME_FW_COMMIT_REQ_FIELD_ACT,
454 	.nu_data = &nvme_ctrl_nogran_1v3,
455 	.nu_value = NVME_FWC_ACTIVATE_IMMED,
456 	.nu_ret = NVME_FIELD_ERR_OK
457 } };
458 
459 int
460 main(void)
461 {
462 	int ret = EXIT_SUCCESS;
463 
464 	if (!nvme_unit_field_test(firmware_field_tests,
465 	    ARRAY_SIZE(firmware_field_tests))) {
466 		ret = EXIT_FAILURE;
467 	}
468 
469 	if (nvme_fw_cmds_supported(&nvme_ctrl_nocmds_1v0)) {
470 		warnx("TEST FAILED: erroneously found firmware command "
471 		    "support on a controller without it");
472 		ret = EXIT_FAILURE;
473 	} else {
474 		(void) printf("TEST PASSED: successfully determined controller "
475 		    "doesn't support firmware commands\n");
476 	}
477 
478 	if (!nvme_fw_cmds_supported(&nvme_ctrl_base_1v0)) {
479 		warnx("TEST FAILED: erroneously found firmware commands aren't "
480 		    "supported on a controller that should advertise it");
481 		ret = EXIT_FAILURE;
482 	} else {
483 		(void) printf("TEST PASSED: successfully determined controller "
484 		    "supports firmware commands\n");
485 	}
486 
487 	if (ret == EXIT_SUCCESS) {
488 		(void) printf("All tests passed successfully!\n");
489 	}
490 
491 	return (ret);
492 }
493