1*09fcda9fSToomas Soome /*
2*09fcda9fSToomas Soome * This file and its contents are supplied under the terms of the
3*09fcda9fSToomas Soome * Common Development and Distribution License ("CDDL"), version 1.0.
4*09fcda9fSToomas Soome * You may only use this file in accordance with the terms of version
5*09fcda9fSToomas Soome * 1.0 of the CDDL.
6*09fcda9fSToomas Soome *
7*09fcda9fSToomas Soome * A full copy of the text of the CDDL should have accompanied this
8*09fcda9fSToomas Soome * source. A copy of the CDDL is also available via the Internet at
9*09fcda9fSToomas Soome * http://www.illumos.org/license/CDDL.
10*09fcda9fSToomas Soome */
11*09fcda9fSToomas Soome /*
12*09fcda9fSToomas Soome * Copyright 2020 Toomas Soome <tsoome@me.com>
13*09fcda9fSToomas Soome */
14*09fcda9fSToomas Soome
15*09fcda9fSToomas Soome #include <sys/types.h>
16*09fcda9fSToomas Soome #include <sys/sysmacros.h>
17*09fcda9fSToomas Soome #include <string.h>
18*09fcda9fSToomas Soome #include <libzfs.h>
19*09fcda9fSToomas Soome #include <libzfsbootenv.h>
20*09fcda9fSToomas Soome #include <sys/zfs_bootenv.h>
21*09fcda9fSToomas Soome #include <sys/vdev_impl.h>
22*09fcda9fSToomas Soome
23*09fcda9fSToomas Soome /*
24*09fcda9fSToomas Soome * Get or create nvlist. If key is not NULL, get nvlist from bootenv,
25*09fcda9fSToomas Soome * otherwise return bootenv.
26*09fcda9fSToomas Soome */
27*09fcda9fSToomas Soome int
lzbe_nvlist_get(const char * pool,const char * key,void ** ptr)28*09fcda9fSToomas Soome lzbe_nvlist_get(const char *pool, const char *key, void **ptr)
29*09fcda9fSToomas Soome {
30*09fcda9fSToomas Soome libzfs_handle_t *hdl;
31*09fcda9fSToomas Soome zpool_handle_t *zphdl;
32*09fcda9fSToomas Soome nvlist_t *nv;
33*09fcda9fSToomas Soome int rv = -1;
34*09fcda9fSToomas Soome
35*09fcda9fSToomas Soome if (pool == NULL || *pool == '\0')
36*09fcda9fSToomas Soome return (rv);
37*09fcda9fSToomas Soome
38*09fcda9fSToomas Soome if ((hdl = libzfs_init()) == NULL) {
39*09fcda9fSToomas Soome return (rv);
40*09fcda9fSToomas Soome }
41*09fcda9fSToomas Soome
42*09fcda9fSToomas Soome zphdl = zpool_open(hdl, pool);
43*09fcda9fSToomas Soome if (zphdl == NULL) {
44*09fcda9fSToomas Soome libzfs_fini(hdl);
45*09fcda9fSToomas Soome return (rv);
46*09fcda9fSToomas Soome }
47*09fcda9fSToomas Soome
48*09fcda9fSToomas Soome rv = zpool_get_bootenv(zphdl, &nv);
49*09fcda9fSToomas Soome if (rv == 0) {
50*09fcda9fSToomas Soome nvlist_t *nvl, *dup;
51*09fcda9fSToomas Soome
52*09fcda9fSToomas Soome if (key != NULL) {
53*09fcda9fSToomas Soome rv = nvlist_lookup_nvlist(nv, key, &nvl);
54*09fcda9fSToomas Soome if (rv == 0) {
55*09fcda9fSToomas Soome rv = nvlist_dup(nvl, &dup, 0);
56*09fcda9fSToomas Soome nvlist_free(nv);
57*09fcda9fSToomas Soome if (rv == 0)
58*09fcda9fSToomas Soome nv = dup;
59*09fcda9fSToomas Soome else
60*09fcda9fSToomas Soome nv = NULL;
61*09fcda9fSToomas Soome } else {
62*09fcda9fSToomas Soome nvlist_free(nv);
63*09fcda9fSToomas Soome rv = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
64*09fcda9fSToomas Soome }
65*09fcda9fSToomas Soome }
66*09fcda9fSToomas Soome *ptr = nv;
67*09fcda9fSToomas Soome }
68*09fcda9fSToomas Soome
69*09fcda9fSToomas Soome zpool_close(zphdl);
70*09fcda9fSToomas Soome libzfs_fini(hdl);
71*09fcda9fSToomas Soome return (rv);
72*09fcda9fSToomas Soome }
73*09fcda9fSToomas Soome
74*09fcda9fSToomas Soome int
lzbe_nvlist_set(const char * pool,const char * key,void * ptr)75*09fcda9fSToomas Soome lzbe_nvlist_set(const char *pool, const char *key, void *ptr)
76*09fcda9fSToomas Soome {
77*09fcda9fSToomas Soome libzfs_handle_t *hdl;
78*09fcda9fSToomas Soome zpool_handle_t *zphdl;
79*09fcda9fSToomas Soome nvlist_t *nv;
80*09fcda9fSToomas Soome uint64_t version;
81*09fcda9fSToomas Soome int rv = -1;
82*09fcda9fSToomas Soome
83*09fcda9fSToomas Soome if (pool == NULL || *pool == '\0')
84*09fcda9fSToomas Soome return (rv);
85*09fcda9fSToomas Soome
86*09fcda9fSToomas Soome if ((hdl = libzfs_init()) == NULL) {
87*09fcda9fSToomas Soome return (rv);
88*09fcda9fSToomas Soome }
89*09fcda9fSToomas Soome
90*09fcda9fSToomas Soome zphdl = zpool_open(hdl, pool);
91*09fcda9fSToomas Soome if (zphdl == NULL) {
92*09fcda9fSToomas Soome libzfs_fini(hdl);
93*09fcda9fSToomas Soome return (rv);
94*09fcda9fSToomas Soome }
95*09fcda9fSToomas Soome
96*09fcda9fSToomas Soome if (key != NULL) {
97*09fcda9fSToomas Soome rv = zpool_get_bootenv(zphdl, &nv);
98*09fcda9fSToomas Soome if (rv == 0) {
99*09fcda9fSToomas Soome /*
100*09fcda9fSToomas Soome * We got the nvlist, check for version.
101*09fcda9fSToomas Soome * if version is missing or is not VB_NVLIST,
102*09fcda9fSToomas Soome * create new list.
103*09fcda9fSToomas Soome */
104*09fcda9fSToomas Soome rv = nvlist_lookup_uint64(nv, BOOTENV_VERSION,
105*09fcda9fSToomas Soome &version);
106*09fcda9fSToomas Soome if (rv != 0 || version != VB_NVLIST) {
107*09fcda9fSToomas Soome /* Drop this nvlist */
108*09fcda9fSToomas Soome fnvlist_free(nv);
109*09fcda9fSToomas Soome /* Create and prepare new nvlist */
110*09fcda9fSToomas Soome nv = fnvlist_alloc();
111*09fcda9fSToomas Soome fnvlist_add_uint64(nv, BOOTENV_VERSION,
112*09fcda9fSToomas Soome VB_NVLIST);
113*09fcda9fSToomas Soome }
114*09fcda9fSToomas Soome rv = nvlist_add_nvlist(nv, key, ptr);
115*09fcda9fSToomas Soome if (rv == 0)
116*09fcda9fSToomas Soome rv = zpool_set_bootenv(zphdl, nv);
117*09fcda9fSToomas Soome nvlist_free(nv);
118*09fcda9fSToomas Soome }
119*09fcda9fSToomas Soome } else {
120*09fcda9fSToomas Soome rv = zpool_set_bootenv(zphdl, ptr);
121*09fcda9fSToomas Soome }
122*09fcda9fSToomas Soome
123*09fcda9fSToomas Soome zpool_close(zphdl);
124*09fcda9fSToomas Soome libzfs_fini(hdl);
125*09fcda9fSToomas Soome return (rv);
126*09fcda9fSToomas Soome }
127*09fcda9fSToomas Soome
128*09fcda9fSToomas Soome /*
129*09fcda9fSToomas Soome * free nvlist we got via lzbe_nvlist_get()
130*09fcda9fSToomas Soome */
131*09fcda9fSToomas Soome void
lzbe_nvlist_free(void * ptr)132*09fcda9fSToomas Soome lzbe_nvlist_free(void *ptr)
133*09fcda9fSToomas Soome {
134*09fcda9fSToomas Soome nvlist_free(ptr);
135*09fcda9fSToomas Soome }
136*09fcda9fSToomas Soome
137*09fcda9fSToomas Soome static const char *typenames[] = {
138*09fcda9fSToomas Soome "DATA_TYPE_UNKNOWN",
139*09fcda9fSToomas Soome "DATA_TYPE_BOOLEAN",
140*09fcda9fSToomas Soome "DATA_TYPE_BYTE",
141*09fcda9fSToomas Soome "DATA_TYPE_INT16",
142*09fcda9fSToomas Soome "DATA_TYPE_UINT16",
143*09fcda9fSToomas Soome "DATA_TYPE_INT32",
144*09fcda9fSToomas Soome "DATA_TYPE_UINT32",
145*09fcda9fSToomas Soome "DATA_TYPE_INT64",
146*09fcda9fSToomas Soome "DATA_TYPE_UINT64",
147*09fcda9fSToomas Soome "DATA_TYPE_STRING",
148*09fcda9fSToomas Soome "DATA_TYPE_BYTE_ARRAY",
149*09fcda9fSToomas Soome "DATA_TYPE_INT16_ARRAY",
150*09fcda9fSToomas Soome "DATA_TYPE_UINT16_ARRAY",
151*09fcda9fSToomas Soome "DATA_TYPE_INT32_ARRAY",
152*09fcda9fSToomas Soome "DATA_TYPE_UINT32_ARRAY",
153*09fcda9fSToomas Soome "DATA_TYPE_INT64_ARRAY",
154*09fcda9fSToomas Soome "DATA_TYPE_UINT64_ARRAY",
155*09fcda9fSToomas Soome "DATA_TYPE_STRING_ARRAY",
156*09fcda9fSToomas Soome "DATA_TYPE_HRTIME",
157*09fcda9fSToomas Soome "DATA_TYPE_NVLIST",
158*09fcda9fSToomas Soome "DATA_TYPE_NVLIST_ARRAY",
159*09fcda9fSToomas Soome "DATA_TYPE_BOOLEAN_VALUE",
160*09fcda9fSToomas Soome "DATA_TYPE_INT8",
161*09fcda9fSToomas Soome "DATA_TYPE_UINT8",
162*09fcda9fSToomas Soome "DATA_TYPE_BOOLEAN_ARRAY",
163*09fcda9fSToomas Soome "DATA_TYPE_INT8_ARRAY",
164*09fcda9fSToomas Soome "DATA_TYPE_UINT8_ARRAY"
165*09fcda9fSToomas Soome };
166*09fcda9fSToomas Soome
167*09fcda9fSToomas Soome static int
nvpair_type_from_name(const char * name)168*09fcda9fSToomas Soome nvpair_type_from_name(const char *name)
169*09fcda9fSToomas Soome {
170*09fcda9fSToomas Soome unsigned i;
171*09fcda9fSToomas Soome
172*09fcda9fSToomas Soome for (i = 0; i < ARRAY_SIZE(typenames); i++) {
173*09fcda9fSToomas Soome if (strcmp(name, typenames[i]) == 0)
174*09fcda9fSToomas Soome return (i);
175*09fcda9fSToomas Soome }
176*09fcda9fSToomas Soome return (0);
177*09fcda9fSToomas Soome }
178*09fcda9fSToomas Soome
179*09fcda9fSToomas Soome /*
180*09fcda9fSToomas Soome * Add pair defined by key, type and value into nvlist.
181*09fcda9fSToomas Soome */
182*09fcda9fSToomas Soome int
lzbe_add_pair(void * ptr,const char * key,const char * type,void * value,size_t size)183*09fcda9fSToomas Soome lzbe_add_pair(void *ptr, const char *key, const char *type, void *value,
184*09fcda9fSToomas Soome size_t size)
185*09fcda9fSToomas Soome {
186*09fcda9fSToomas Soome nvlist_t *nv = ptr;
187*09fcda9fSToomas Soome data_type_t dt;
188*09fcda9fSToomas Soome int rv = 0;
189*09fcda9fSToomas Soome
190*09fcda9fSToomas Soome if (ptr == NULL || key == NULL || value == NULL)
191*09fcda9fSToomas Soome return (rv);
192*09fcda9fSToomas Soome
193*09fcda9fSToomas Soome if (type == NULL)
194*09fcda9fSToomas Soome type = "DATA_TYPE_STRING";
195*09fcda9fSToomas Soome dt = nvpair_type_from_name(type);
196*09fcda9fSToomas Soome if (dt == DATA_TYPE_UNKNOWN)
197*09fcda9fSToomas Soome return (EINVAL);
198*09fcda9fSToomas Soome
199*09fcda9fSToomas Soome switch (dt) {
200*09fcda9fSToomas Soome case DATA_TYPE_BYTE:
201*09fcda9fSToomas Soome if (size != sizeof (uint8_t)) {
202*09fcda9fSToomas Soome rv = EINVAL;
203*09fcda9fSToomas Soome break;
204*09fcda9fSToomas Soome }
205*09fcda9fSToomas Soome rv = nvlist_add_byte(nv, key, *(uint8_t *)value);
206*09fcda9fSToomas Soome break;
207*09fcda9fSToomas Soome
208*09fcda9fSToomas Soome case DATA_TYPE_INT16:
209*09fcda9fSToomas Soome if (size != sizeof (int16_t)) {
210*09fcda9fSToomas Soome rv = EINVAL;
211*09fcda9fSToomas Soome break;
212*09fcda9fSToomas Soome }
213*09fcda9fSToomas Soome rv = nvlist_add_int16(nv, key, *(int16_t *)value);
214*09fcda9fSToomas Soome break;
215*09fcda9fSToomas Soome
216*09fcda9fSToomas Soome case DATA_TYPE_UINT16:
217*09fcda9fSToomas Soome if (size != sizeof (uint16_t)) {
218*09fcda9fSToomas Soome rv = EINVAL;
219*09fcda9fSToomas Soome break;
220*09fcda9fSToomas Soome }
221*09fcda9fSToomas Soome rv = nvlist_add_uint16(nv, key, *(uint16_t *)value);
222*09fcda9fSToomas Soome break;
223*09fcda9fSToomas Soome
224*09fcda9fSToomas Soome case DATA_TYPE_INT32:
225*09fcda9fSToomas Soome if (size != sizeof (int32_t)) {
226*09fcda9fSToomas Soome rv = EINVAL;
227*09fcda9fSToomas Soome break;
228*09fcda9fSToomas Soome }
229*09fcda9fSToomas Soome rv = nvlist_add_int32(nv, key, *(int32_t *)value);
230*09fcda9fSToomas Soome break;
231*09fcda9fSToomas Soome
232*09fcda9fSToomas Soome case DATA_TYPE_UINT32:
233*09fcda9fSToomas Soome if (size != sizeof (uint32_t)) {
234*09fcda9fSToomas Soome rv = EINVAL;
235*09fcda9fSToomas Soome break;
236*09fcda9fSToomas Soome }
237*09fcda9fSToomas Soome rv = nvlist_add_uint32(nv, key, *(uint32_t *)value);
238*09fcda9fSToomas Soome break;
239*09fcda9fSToomas Soome
240*09fcda9fSToomas Soome case DATA_TYPE_INT64:
241*09fcda9fSToomas Soome if (size != sizeof (int64_t)) {
242*09fcda9fSToomas Soome rv = EINVAL;
243*09fcda9fSToomas Soome break;
244*09fcda9fSToomas Soome }
245*09fcda9fSToomas Soome rv = nvlist_add_int64(nv, key, *(int64_t *)value);
246*09fcda9fSToomas Soome break;
247*09fcda9fSToomas Soome
248*09fcda9fSToomas Soome case DATA_TYPE_UINT64:
249*09fcda9fSToomas Soome if (size != sizeof (uint64_t)) {
250*09fcda9fSToomas Soome rv = EINVAL;
251*09fcda9fSToomas Soome break;
252*09fcda9fSToomas Soome }
253*09fcda9fSToomas Soome rv = nvlist_add_uint64(nv, key, *(uint64_t *)value);
254*09fcda9fSToomas Soome break;
255*09fcda9fSToomas Soome
256*09fcda9fSToomas Soome case DATA_TYPE_STRING:
257*09fcda9fSToomas Soome rv = nvlist_add_string(nv, key, value);
258*09fcda9fSToomas Soome break;
259*09fcda9fSToomas Soome
260*09fcda9fSToomas Soome case DATA_TYPE_BYTE_ARRAY:
261*09fcda9fSToomas Soome rv = nvlist_add_byte_array(nv, key, value, size);
262*09fcda9fSToomas Soome break;
263*09fcda9fSToomas Soome
264*09fcda9fSToomas Soome case DATA_TYPE_INT16_ARRAY:
265*09fcda9fSToomas Soome rv = nvlist_add_int16_array(nv, key, value, size);
266*09fcda9fSToomas Soome break;
267*09fcda9fSToomas Soome
268*09fcda9fSToomas Soome case DATA_TYPE_UINT16_ARRAY:
269*09fcda9fSToomas Soome rv = nvlist_add_uint16_array(nv, key, value, size);
270*09fcda9fSToomas Soome break;
271*09fcda9fSToomas Soome
272*09fcda9fSToomas Soome case DATA_TYPE_INT32_ARRAY:
273*09fcda9fSToomas Soome rv = nvlist_add_int32_array(nv, key, value, size);
274*09fcda9fSToomas Soome break;
275*09fcda9fSToomas Soome
276*09fcda9fSToomas Soome case DATA_TYPE_UINT32_ARRAY:
277*09fcda9fSToomas Soome rv = nvlist_add_uint32_array(nv, key, value, size);
278*09fcda9fSToomas Soome break;
279*09fcda9fSToomas Soome
280*09fcda9fSToomas Soome case DATA_TYPE_INT64_ARRAY:
281*09fcda9fSToomas Soome rv = nvlist_add_int64_array(nv, key, value, size);
282*09fcda9fSToomas Soome break;
283*09fcda9fSToomas Soome
284*09fcda9fSToomas Soome case DATA_TYPE_UINT64_ARRAY:
285*09fcda9fSToomas Soome rv = nvlist_add_uint64_array(nv, key, value, size);
286*09fcda9fSToomas Soome break;
287*09fcda9fSToomas Soome
288*09fcda9fSToomas Soome case DATA_TYPE_STRING_ARRAY:
289*09fcda9fSToomas Soome rv = nvlist_add_string_array(nv, key, value, size);
290*09fcda9fSToomas Soome break;
291*09fcda9fSToomas Soome
292*09fcda9fSToomas Soome case DATA_TYPE_NVLIST:
293*09fcda9fSToomas Soome rv = nvlist_add_nvlist(nv, key, (nvlist_t *)value);
294*09fcda9fSToomas Soome break;
295*09fcda9fSToomas Soome
296*09fcda9fSToomas Soome case DATA_TYPE_NVLIST_ARRAY:
297*09fcda9fSToomas Soome rv = nvlist_add_nvlist_array(nv, key, value, size);
298*09fcda9fSToomas Soome break;
299*09fcda9fSToomas Soome
300*09fcda9fSToomas Soome case DATA_TYPE_BOOLEAN_VALUE:
301*09fcda9fSToomas Soome if (size != sizeof (boolean_t)) {
302*09fcda9fSToomas Soome rv = EINVAL;
303*09fcda9fSToomas Soome break;
304*09fcda9fSToomas Soome }
305*09fcda9fSToomas Soome rv = nvlist_add_boolean_value(nv, key, *(boolean_t *)value);
306*09fcda9fSToomas Soome break;
307*09fcda9fSToomas Soome
308*09fcda9fSToomas Soome case DATA_TYPE_INT8:
309*09fcda9fSToomas Soome if (size != sizeof (int8_t)) {
310*09fcda9fSToomas Soome rv = EINVAL;
311*09fcda9fSToomas Soome break;
312*09fcda9fSToomas Soome }
313*09fcda9fSToomas Soome rv = nvlist_add_int8(nv, key, *(int8_t *)value);
314*09fcda9fSToomas Soome break;
315*09fcda9fSToomas Soome
316*09fcda9fSToomas Soome case DATA_TYPE_UINT8:
317*09fcda9fSToomas Soome if (size != sizeof (uint8_t)) {
318*09fcda9fSToomas Soome rv = EINVAL;
319*09fcda9fSToomas Soome break;
320*09fcda9fSToomas Soome }
321*09fcda9fSToomas Soome rv = nvlist_add_uint8(nv, key, *(uint8_t *)value);
322*09fcda9fSToomas Soome break;
323*09fcda9fSToomas Soome
324*09fcda9fSToomas Soome case DATA_TYPE_BOOLEAN_ARRAY:
325*09fcda9fSToomas Soome rv = nvlist_add_boolean_array(nv, key, value, size);
326*09fcda9fSToomas Soome break;
327*09fcda9fSToomas Soome
328*09fcda9fSToomas Soome case DATA_TYPE_INT8_ARRAY:
329*09fcda9fSToomas Soome rv = nvlist_add_int8_array(nv, key, value, size);
330*09fcda9fSToomas Soome break;
331*09fcda9fSToomas Soome
332*09fcda9fSToomas Soome case DATA_TYPE_UINT8_ARRAY:
333*09fcda9fSToomas Soome rv = nvlist_add_uint8_array(nv, key, value, size);
334*09fcda9fSToomas Soome break;
335*09fcda9fSToomas Soome
336*09fcda9fSToomas Soome default:
337*09fcda9fSToomas Soome return (ENOTSUP);
338*09fcda9fSToomas Soome }
339*09fcda9fSToomas Soome
340*09fcda9fSToomas Soome return (rv);
341*09fcda9fSToomas Soome }
342*09fcda9fSToomas Soome
343*09fcda9fSToomas Soome int
lzbe_remove_pair(void * ptr,const char * key)344*09fcda9fSToomas Soome lzbe_remove_pair(void *ptr, const char *key)
345*09fcda9fSToomas Soome {
346*09fcda9fSToomas Soome
347*09fcda9fSToomas Soome return (nvlist_remove_all(ptr, key));
348*09fcda9fSToomas Soome }
349