Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/bhnd/nvram/bhnd_nvram_plist.c
39536 views
1
/*-
2
* Copyright (c) 2015-2016 Landon Fuller <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer,
10
* without modification.
11
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
12
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13
* redistribution must be conditioned upon including a substantially
14
* similar Disclaimer requirement for further binary redistribution.
15
*
16
* NO WARRANTY
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27
* THE POSSIBILITY OF SUCH DAMAGES.
28
*/
29
30
#include <sys/param.h>
31
#include <sys/hash.h>
32
33
#ifdef _KERNEL
34
35
#include <sys/systm.h>
36
37
#else /* !_KERNEL */
38
39
#include <errno.h>
40
#include <stdint.h>
41
#include <stdlib.h>
42
#include <string.h>
43
44
#endif /* _KERNEL */
45
46
#include "bhnd_nvram_plistvar.h"
47
#include "bhnd_nvram_private.h"
48
49
static bhnd_nvram_plist_entry *bhnd_nvram_plist_get_entry(
50
bhnd_nvram_plist *plist, const char *name);
51
52
/**
53
* Allocate and initialize a new, empty property list.
54
*
55
* The caller is responsible for releasing the returned property value
56
* via bhnd_nvram_plist_release().
57
*
58
* @retval non-NULL success
59
* @retval NULL if allocation fails.
60
*/
61
bhnd_nvram_plist *
62
bhnd_nvram_plist_new(void)
63
{
64
bhnd_nvram_plist *plist;
65
66
plist = bhnd_nv_calloc(1, sizeof(*plist));
67
if (plist == NULL)
68
return NULL;
69
70
/* Implicit caller-owned reference */
71
plist->refs = 1;
72
73
/* Initialize entry list */
74
plist->num_entries = 0;
75
TAILQ_INIT(&plist->entries);
76
77
/* Initialize entry hash table */
78
for (size_t i = 0; i < nitems(plist->names); i++)
79
LIST_INIT(&plist->names[i]);
80
81
return (plist);
82
}
83
84
/**
85
* Retain a reference and return @p plist to the caller.
86
*
87
* The caller is responsible for releasing their reference ownership via
88
* bhnd_nvram_plist_release().
89
*
90
* @param plist The property list to be retained.
91
*/
92
bhnd_nvram_plist *
93
bhnd_nvram_plist_retain(bhnd_nvram_plist *plist)
94
{
95
BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released"));
96
97
refcount_acquire(&plist->refs);
98
return (plist);
99
}
100
101
/**
102
* Release a reference to @p plist.
103
*
104
* If this is the last reference, all associated resources will be freed.
105
*
106
* @param plist The property list to be released.
107
*/
108
void
109
bhnd_nvram_plist_release(bhnd_nvram_plist *plist)
110
{
111
bhnd_nvram_plist_entry *ple, *ple_next;
112
113
BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released"));
114
115
/* Drop reference */
116
if (!refcount_release(&plist->refs))
117
return;
118
119
/* Free all property entries */
120
TAILQ_FOREACH_SAFE(ple, &plist->entries, pl_link, ple_next) {
121
bhnd_nvram_prop_release(ple->prop);
122
bhnd_nv_free(ple);
123
}
124
125
/* Free plist instance */
126
bhnd_nv_free(plist);
127
}
128
129
/**
130
* Return a shallow copy of @p plist.
131
*
132
* The caller is responsible for releasing the returned property value
133
* via bhnd_nvram_plist_release().
134
*
135
* @retval non-NULL success
136
* @retval NULL if allocation fails.
137
*/
138
bhnd_nvram_plist *
139
bhnd_nvram_plist_copy(bhnd_nvram_plist *plist)
140
{
141
bhnd_nvram_plist *copy;
142
bhnd_nvram_prop *prop;
143
int error;
144
145
/* Allocate new, empty plist */
146
if ((copy = bhnd_nvram_plist_new()) == NULL)
147
return (NULL);
148
149
/* Append all properties */
150
prop = NULL;
151
while ((prop = bhnd_nvram_plist_next(plist, prop)) != NULL) {
152
error = bhnd_nvram_plist_append(copy, prop);
153
if (error) {
154
if (error != ENOMEM) {
155
BHND_NV_LOG("error copying property: %d\n",
156
error);
157
}
158
159
bhnd_nvram_plist_release(copy);
160
return (NULL);
161
}
162
}
163
164
/* Return ownership of the copy to our caller */
165
return (copy);
166
}
167
168
/**
169
* Return the number of properties in @p plist.
170
*/
171
size_t
172
bhnd_nvram_plist_count(bhnd_nvram_plist *plist)
173
{
174
return (plist->num_entries);
175
}
176
177
/**
178
* Return true if @p plist contains a property name @p name, false otherwise.
179
*
180
* @param plist The property list to be queried.
181
* @param name The property name to be queried.
182
*/
183
bool
184
bhnd_nvram_plist_contains(bhnd_nvram_plist *plist, const char *name)
185
{
186
if (bhnd_nvram_plist_get_entry(plist, name) != NULL)
187
return (true);
188
189
return (false);
190
}
191
192
/**
193
* Replace the current property value for a property matching the name
194
* of @p prop, maintaining the property's current order in @p plist.
195
*
196
* If a matching property is not found in @p plist, @p prop will instead be
197
* appended.
198
*
199
* @param plist The property list to be modified.
200
* @param prop The replacement property.
201
*
202
* @retval 0 success
203
* @retval ENOMEM if allocation fails.
204
* @retval non-zero if modifying @p plist otherwise fails, a regular unix
205
* error code will be returned.
206
*/
207
int
208
bhnd_nvram_plist_replace(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
209
{
210
bhnd_nvram_plist_entry *entry;
211
212
/* Fetch current entry */
213
entry = bhnd_nvram_plist_get_entry(plist, prop->name);
214
if (entry == NULL) {
215
/* Not found -- append property instead */
216
return (bhnd_nvram_plist_append(plist, prop));
217
}
218
219
/* Replace the current entry's property reference */
220
bhnd_nvram_prop_release(entry->prop);
221
entry->prop = bhnd_nvram_prop_retain(prop);
222
223
return (0);
224
}
225
226
/**
227
* Replace the current property value for a property matching @p name,
228
* maintaining the property's order in @p plist.
229
*
230
* If @p name is not found in @p plist, a new property will be appended.
231
*
232
* @param plist The property list to be modified.
233
* @param name The name of the property to be replaced.
234
* @param val The replacement value for @p name.
235
*
236
* @retval 0 success
237
* @retval ENOMEM if allocation fails.
238
* @retval non-zero if modifying @p plist otherwise fails, a regular unix
239
* error code will be returned.
240
*/
241
int
242
bhnd_nvram_plist_replace_val(bhnd_nvram_plist *plist, const char *name,
243
bhnd_nvram_val *val)
244
{
245
bhnd_nvram_prop *prop;
246
int error;
247
248
/* Construct a new property instance for the name and value */
249
if ((prop = bhnd_nvram_prop_new(name, val)) == NULL)
250
return (ENOMEM);
251
252
/* Attempt replace */
253
error = bhnd_nvram_plist_replace(plist, prop);
254
bhnd_nvram_prop_release(prop);
255
256
return (error);
257
}
258
259
/**
260
* Replace the current property value for a property matching @p name, copying
261
* the new property value from the given @p inp buffer of @p itype and @p ilen.
262
*
263
* The current property order of @p name in @p plist will be maintained.
264
*
265
* If @p name is not found in @p plist, a new property will be appended.
266
*
267
* @param plist The property list to be modified.
268
* @param name The name of the property to be replaced.
269
* @param inp Input buffer.
270
* @param ilen Input buffer length.
271
* @param itype Input buffer type.
272
*
273
* @retval 0 success
274
* @retval ENOMEM if allocation fails.
275
* @retval non-zero if modifying @p plist otherwise fails, a regular unix
276
* error code will be returned.
277
*/
278
int
279
bhnd_nvram_plist_replace_bytes(bhnd_nvram_plist *plist, const char *name,
280
const void *inp, size_t ilen, bhnd_nvram_type itype)
281
{
282
bhnd_nvram_prop *prop;
283
int error;
284
285
if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL)
286
return (ENOMEM);
287
288
error = bhnd_nvram_plist_replace(plist, prop);
289
bhnd_nvram_prop_release(prop);
290
291
return (error);
292
}
293
294
/**
295
* Replace the current property value for a property matching @p name, copying
296
* the new property value from @p val.
297
*
298
* The current property order of @p name in @p plist will be maintained.
299
*
300
* If @p name is not found in @p plist, a new property will be appended.
301
*
302
* @param plist The property list to be modified.
303
* @param name The name of the property to be replaced.
304
* @param val The property's replacement string value.
305
*
306
* @retval 0 success
307
* @retval ENOMEM if allocation fails.
308
* @retval non-zero if modifying @p plist otherwise fails, a regular unix
309
* error code will be returned.
310
*/
311
int
312
bhnd_nvram_plist_replace_string(bhnd_nvram_plist *plist, const char *name,
313
const char *val)
314
{
315
return (bhnd_nvram_plist_replace_bytes(plist, name, val, strlen(val)+1,
316
BHND_NVRAM_TYPE_STRING));
317
}
318
319
/**
320
* Remove the property entry for the property @p name, if any.
321
*
322
* @param plist The property list to be modified.
323
* @param name The name of the property to be removed.
324
*/
325
void
326
bhnd_nvram_plist_remove(bhnd_nvram_plist *plist, const char *name)
327
{
328
bhnd_nvram_plist_entry *entry;
329
330
/* Fetch entry */
331
entry = bhnd_nvram_plist_get_entry(plist, name);
332
if (entry == NULL)
333
return;
334
335
/* Remove from entry list and hash table */
336
TAILQ_REMOVE(&plist->entries, entry, pl_link);
337
LIST_REMOVE(entry, pl_hash_link);
338
339
/* Free plist entry */
340
bhnd_nvram_prop_release(entry->prop);
341
bhnd_nv_free(entry);
342
343
/* Decrement entry count */
344
BHND_NV_ASSERT(plist->num_entries > 0, ("entry count over-release"));
345
plist->num_entries--;
346
}
347
348
/**
349
* Fetch the property list entry for @p name, if any.
350
*
351
* @param plist The property list to be queried.
352
* @param name The property name to be queried.
353
*
354
* @retval non-NULL if @p name is found.
355
* @retval NULL if @p name is not found.
356
*/
357
static bhnd_nvram_plist_entry *
358
bhnd_nvram_plist_get_entry(bhnd_nvram_plist *plist, const char *name)
359
{
360
bhnd_nvram_plist_entry_list *hash_list;
361
bhnd_nvram_plist_entry *entry;
362
uint32_t h;
363
364
h = hash32_str(name, HASHINIT);
365
hash_list = &plist->names[h % nitems(plist->names)];
366
367
LIST_FOREACH(entry, hash_list, pl_hash_link) {
368
if (strcmp(entry->prop->name, name) == 0)
369
return (entry);
370
};
371
372
/* Not found */
373
return (NULL);
374
}
375
376
/**
377
* Append all properties from @p tail to @p plist.
378
*
379
* @param plist The property list to be modified.
380
* @param tail The property list to append.
381
*
382
* @retval 0 success
383
* @retval ENOMEM if allocation fails.
384
* @retval EEXIST an existing property from @p tail was found in @p plist.
385
*/
386
int
387
bhnd_nvram_plist_append_list(bhnd_nvram_plist *plist, bhnd_nvram_plist *tail)
388
{
389
bhnd_nvram_prop *p;
390
int error;
391
392
p = NULL;
393
while ((p = bhnd_nvram_plist_next(tail, p)) != NULL) {
394
if ((error = bhnd_nvram_plist_append(plist, p)))
395
return (error);
396
}
397
398
return (0);
399
}
400
401
/**
402
* Append @p prop to @p plist.
403
*
404
* @param plist The property list to be modified.
405
* @param prop The property to append.
406
*
407
* @retval 0 success
408
* @retval ENOMEM if allocation fails.
409
* @retval EEXIST an existing property with @p name was found in @p plist.
410
*/
411
int
412
bhnd_nvram_plist_append(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
413
{
414
bhnd_nvram_plist_entry_list *hash_list;
415
bhnd_nvram_plist_entry *entry;
416
uint32_t h;
417
418
if (bhnd_nvram_plist_contains(plist, prop->name))
419
return (EEXIST);
420
421
/* Have we hit the maximum representable entry count? */
422
if (plist->num_entries == SIZE_MAX)
423
return (ENOMEM);
424
425
/* Allocate new entry */
426
entry = bhnd_nv_malloc(sizeof(*entry));
427
if (entry == NULL)
428
return (ENOMEM);
429
430
entry->prop = bhnd_nvram_prop_retain(prop);
431
432
/* Append to entry list */
433
TAILQ_INSERT_TAIL(&plist->entries, entry, pl_link);
434
435
/* Add to name-based hash table */
436
h = hash32_str(prop->name, HASHINIT);
437
hash_list = &plist->names[h % nitems(plist->names)];
438
LIST_INSERT_HEAD(hash_list, entry, pl_hash_link);
439
440
/* Increment entry count */
441
plist->num_entries++;
442
443
return (0);
444
}
445
446
/**
447
* Append a new property to @p plist with @p name and @p val.
448
*
449
* @param plist The property list to be modified.
450
* @param name The name of the property to be appended.
451
* @param val The value of the property to be appended.
452
*
453
* @retval 0 success
454
* @retval ENOMEM if allocation fails.
455
* @retval EEXIST an existing property with @p name was found in @p plist.
456
*/
457
int
458
bhnd_nvram_plist_append_val(bhnd_nvram_plist *plist, const char *name,
459
bhnd_nvram_val *val)
460
{
461
bhnd_nvram_prop *prop;
462
int error;
463
464
if ((prop = bhnd_nvram_prop_new(name, val)) == NULL)
465
return (ENOMEM);
466
467
error = bhnd_nvram_plist_append(plist, prop);
468
bhnd_nvram_prop_release(prop);
469
470
return (error);
471
}
472
473
/**
474
* Append a new property to @p plist, copying the property value from the
475
* given @p inp buffer of @p itype and @p ilen.
476
*
477
* @param plist The property list to be modified.
478
* @param name The name of the property to be appended.
479
* @param inp Input buffer.
480
* @param ilen Input buffer length.
481
* @param itype Input buffer type.
482
*
483
* @retval 0 success
484
* @retval ENOMEM if allocation fails.
485
* @retval EEXIST an existing property with @p name was found in @p plist.
486
*/
487
int
488
bhnd_nvram_plist_append_bytes(bhnd_nvram_plist *plist, const char *name,
489
const void *inp, size_t ilen, bhnd_nvram_type itype)
490
{
491
bhnd_nvram_prop *prop;
492
int error;
493
494
if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL)
495
return (ENOMEM);
496
497
error = bhnd_nvram_plist_append(plist, prop);
498
bhnd_nvram_prop_release(prop);
499
500
return (error);
501
}
502
503
/**
504
* Append a new string property to @p plist, copying the property value from
505
* @p val.
506
*
507
* @param plist The property list to be modified.
508
* @param name The name of the property to be appended.
509
* @param val The new property's string value.
510
*
511
* @retval 0 success
512
* @retval ENOMEM if allocation fails.
513
* @retval EEXIST an existing property with @p name was found in @p plist.
514
*/
515
int
516
bhnd_nvram_plist_append_string(bhnd_nvram_plist *plist, const char *name,
517
const char *val)
518
{
519
return (bhnd_nvram_plist_append_bytes(plist, name, val, strlen(val)+1,
520
BHND_NVRAM_TYPE_STRING));
521
}
522
523
/**
524
* Iterate over all properties in @p plist.
525
*
526
* @param plist The property list to be iterated.
527
* @param prop A property in @p plist, or NULL to return the first
528
* property in @p plist.
529
*
530
* @retval non-NULL A borrowed reference to the next property in @p plist.
531
* @retval NULL If the end of the property list is reached or @p prop
532
* is not found in @p plist.
533
*/
534
bhnd_nvram_prop *
535
bhnd_nvram_plist_next(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
536
{
537
bhnd_nvram_plist_entry *entry;
538
539
if (prop == NULL) {
540
if ((entry = TAILQ_FIRST(&plist->entries)) == NULL)
541
return (NULL);
542
543
return (entry->prop);
544
}
545
546
/* Look up previous property entry by name */
547
if ((entry = bhnd_nvram_plist_get_entry(plist, prop->name)) == NULL)
548
return (NULL);
549
550
/* The property instance must be identical */
551
if (entry->prop != prop)
552
return (NULL);
553
554
/* Fetch next entry */
555
if ((entry = TAILQ_NEXT(entry, pl_link)) == NULL)
556
return (NULL);
557
558
return (entry->prop);
559
}
560
561
/**
562
* Return a borrowed reference to a named property, or NULL if @p name is
563
* not found in @p plist.
564
*
565
* @param plist The property list to be queried.
566
* @param name The name of the property to be returned.
567
*
568
* @retval non-NULL if @p name is found.
569
* @retval NULL if @p name is not found.
570
*/
571
bhnd_nvram_prop *
572
bhnd_nvram_plist_get_prop(bhnd_nvram_plist *plist, const char *name)
573
{
574
bhnd_nvram_plist_entry *entry;
575
576
if ((entry = bhnd_nvram_plist_get_entry(plist, name)) == NULL)
577
return (NULL);
578
579
return (entry->prop);
580
}
581
582
/**
583
* Return a borrowed reference to the named property's value, or NULL if
584
* @p name is not found in @p plist.
585
*
586
* @param plist The property list to be queried.
587
* @param name The name of the property to be returned.
588
*
589
* @retval non-NULL if @p name is found.
590
* @retval NULL if @p name is not found.
591
*/
592
bhnd_nvram_val *
593
bhnd_nvram_plist_get_val(bhnd_nvram_plist *plist, const char *name)
594
{
595
bhnd_nvram_prop *prop;
596
597
if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL)
598
return (NULL);
599
600
return (bhnd_nvram_prop_val(prop));
601
}
602
603
/**
604
* Attempt to encode a named property's value as @p otype, writing the result
605
* to @p outp.
606
*
607
* @param plist The property list to be queried.
608
* @param name The name of the property value to be returned.
609
* @param[out] outp On success, the value will be written to this
610
* buffer. This argment may be NULL if the value is
611
* not desired.
612
* @param[in,out] olen The capacity of @p outp. On success, will be set
613
* to the actual size of the requested value.
614
* @param otype The data type to be written to @p outp.
615
*
616
* @retval 0 success
617
* @retval ENOENT If @p name is not found in @p plist.
618
* @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
619
* is too small to hold the encoded value.
620
* @retval EFTYPE If value coercion from @p prop to @p otype is
621
* impossible.
622
* @retval ERANGE If value coercion would overflow (or underflow) the
623
* a @p otype representation.
624
*/
625
int
626
bhnd_nvram_plist_get_encoded(bhnd_nvram_plist *plist, const char *name,
627
void *outp, size_t olen, bhnd_nvram_type otype)
628
{
629
bhnd_nvram_prop *prop;
630
631
if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL)
632
return (ENOENT);
633
634
return (bhnd_nvram_prop_encode(prop, outp, &olen, otype));
635
}
636
637
/**
638
* Return the character representation of a named property's value.
639
*
640
* @param plist The property list to be queried.
641
* @param name The name of the property value to be returned.
642
* @param[out] val On success, the character value of @p name.
643
*
644
* @retval 0 success
645
* @retval ENOENT If @p name is not found in @p plist.
646
* @retval EFTYPE If coercion of the property's value to @p val.
647
* @retval ERANGE If coercion of the property's value would overflow
648
* (or underflow) @p val.
649
*/
650
int
651
bhnd_nvram_plist_get_char(bhnd_nvram_plist *plist, const char *name,
652
u_char *val)
653
{
654
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
655
BHND_NVRAM_TYPE_CHAR));
656
}
657
658
/**
659
* Return the uint8 representation of a named property's value.
660
*
661
* @param plist The property list to be queried.
662
* @param name The name of the property value to be returned.
663
* @param[out] val On success, the uint8 value of @p name.
664
*
665
* @retval 0 success
666
* @retval ENOENT If @p name is not found in @p plist.
667
* @retval EFTYPE If coercion of the property's value to @p val.
668
* @retval ERANGE If coercion of the property's value would overflow
669
* (or underflow) @p val.
670
*/
671
int
672
bhnd_nvram_plist_get_uint8(bhnd_nvram_plist *plist, const char *name,
673
uint8_t *val)
674
{
675
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
676
BHND_NVRAM_TYPE_UINT8));
677
}
678
679
/**
680
* Return the uint16 representation of a named property's value.
681
*
682
* @param plist The property list to be queried.
683
* @param name The name of the property value to be returned.
684
* @param[out] val On success, the uint16 value of @p name.
685
*
686
* @retval 0 success
687
* @retval ENOENT If @p name is not found in @p plist.
688
* @retval EFTYPE If coercion of the property's value to @p val.
689
* @retval ERANGE If coercion of the property's value would overflow
690
* (or underflow) @p val.
691
*/
692
int
693
bhnd_nvram_plist_get_uint16(bhnd_nvram_plist *plist, const char *name,
694
uint16_t *val)
695
{
696
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
697
BHND_NVRAM_TYPE_UINT16));
698
}
699
700
/**
701
* Return the uint32 representation of a named property's value.
702
*
703
* @param plist The property list to be queried.
704
* @param name The name of the property value to be returned.
705
* @param[out] val On success, the uint32 value of @p name.
706
*
707
* @retval 0 success
708
* @retval ENOENT If @p name is not found in @p plist.
709
* @retval EFTYPE If coercion of the property's value to @p val.
710
* @retval ERANGE If coercion of the property's value would overflow
711
* (or underflow) @p val.
712
*/
713
int
714
bhnd_nvram_plist_get_uint32(bhnd_nvram_plist *plist, const char *name,
715
uint32_t *val)
716
{
717
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
718
BHND_NVRAM_TYPE_UINT32));
719
}
720
721
/**
722
* Return the uint64 representation of a named property's value.
723
*
724
* @param plist The property list to be queried.
725
* @param name The name of the property value to be returned.
726
* @param[out] val On success, the uint64 value of @p name.
727
*
728
* @retval 0 success
729
* @retval ENOENT If @p name is not found in @p plist.
730
* @retval EFTYPE If coercion of the property's value to @p val.
731
* @retval ERANGE If coercion of the property's value would overflow
732
* (or underflow) @p val.
733
*/
734
int
735
bhnd_nvram_plist_get_uint64(bhnd_nvram_plist *plist, const char *name,
736
uint64_t *val)
737
{
738
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
739
BHND_NVRAM_TYPE_UINT64));
740
}
741
742
/**
743
* Return the boolean representation of a named property's value.
744
*
745
* @param plist The property list to be queried.
746
* @param name The name of the property value to be returned.
747
* @param[out] val On success, the boolean value of @p name.
748
*
749
* @retval 0 success
750
* @retval ENOENT If @p name is not found in @p plist.
751
* @retval EFTYPE If coercion of the property's value to @p val.
752
* @retval ERANGE If coercion of the property's value would overflow
753
* (or underflow) @p val.
754
*/
755
int
756
bhnd_nvram_plist_get_bool(bhnd_nvram_plist *plist, const char *name,
757
bool *val)
758
{
759
return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
760
BHND_NVRAM_TYPE_BOOL));
761
}
762
763
/**
764
* Allocate and initialize a new property value.
765
*
766
* The caller is responsible for releasing the returned property value
767
* via bhnd_nvram_prop_release().
768
*
769
* @param name Property name.
770
* @param val Property value.
771
*
772
* @retval non-NULL success
773
* @retval NULL if allocation fails.
774
*/
775
struct bhnd_nvram_prop *
776
bhnd_nvram_prop_new(const char *name, bhnd_nvram_val *val)
777
{
778
struct bhnd_nvram_prop *prop;
779
780
prop = bhnd_nv_calloc(1, sizeof(*prop));
781
if (prop == NULL)
782
return NULL;
783
784
/* Implicit caller-owned reference */
785
prop->refs = 1;
786
787
if ((prop->name = bhnd_nv_strdup(name)) == NULL)
788
goto failed;
789
790
if ((prop->val = bhnd_nvram_val_copy(val)) == NULL)
791
goto failed;
792
793
return (prop);
794
795
failed:
796
if (prop->name != NULL)
797
bhnd_nv_free(prop->name);
798
799
if (prop->val != NULL)
800
bhnd_nvram_val_release(prop->val);
801
802
bhnd_nv_free(prop);
803
return (NULL);
804
}
805
806
/**
807
* Allocate a new property value and attempt to initialize its value from
808
* the given @p inp buffer of @p itype and @p ilen.
809
*
810
* The caller is responsible for releasing the returned property value
811
* via bhnd_nvram_prop_release().
812
*
813
* @param name Property name.
814
* @param inp Input buffer.
815
* @param ilen Input buffer length.
816
* @param itype Input buffer type.
817
*
818
* @retval non-NULL success
819
* @retval NULL if allocation or initialization fails.
820
*/
821
bhnd_nvram_prop *
822
bhnd_nvram_prop_bytes_new(const char *name, const void *inp, size_t ilen,
823
bhnd_nvram_type itype)
824
{
825
bhnd_nvram_prop *prop;
826
bhnd_nvram_val *val;
827
int error;
828
829
/* Construct new value instance */
830
error = bhnd_nvram_val_new(&val, NULL, inp, ilen, itype,
831
BHND_NVRAM_VAL_DYNAMIC);
832
if (error) {
833
if (error != ENOMEM) {
834
BHND_NV_LOG("invalid input data; initialization "
835
"failed: %d\n", error);
836
}
837
838
return (NULL);
839
}
840
841
/* Delegate to default implementation */
842
prop = bhnd_nvram_prop_new(name, val);
843
844
/* Clean up */
845
bhnd_nvram_val_release(val);
846
return (prop);
847
}
848
849
/**
850
* Retain a reference and return @p prop to the caller.
851
*
852
* The caller is responsible for releasing their reference ownership via
853
* bhnd_nvram_prop_release().
854
*
855
* @param prop The property to be retained.
856
*/
857
bhnd_nvram_prop *
858
bhnd_nvram_prop_retain(bhnd_nvram_prop *prop)
859
{
860
BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released"));
861
862
refcount_acquire(&prop->refs);
863
return (prop);
864
}
865
866
/**
867
* Release a reference to @p prop.
868
*
869
* If this is the last reference, all associated resources will be freed.
870
*
871
* @param prop The property to be released.
872
*/
873
void
874
bhnd_nvram_prop_release(bhnd_nvram_prop *prop)
875
{
876
BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released"));
877
878
/* Drop reference */
879
if (!refcount_release(&prop->refs))
880
return;
881
882
/* Free property data */
883
bhnd_nvram_val_release(prop->val);
884
bhnd_nv_free(prop->name);
885
bhnd_nv_free(prop);
886
}
887
888
/**
889
* Return a borrowed reference to the property's name.
890
*
891
* @param prop The property to query.
892
*/
893
const char *
894
bhnd_nvram_prop_name(bhnd_nvram_prop *prop)
895
{
896
return (prop->name);
897
}
898
899
/**
900
* Return a borrowed reference to the property's value.
901
*
902
* @param prop The property to query.
903
*/
904
bhnd_nvram_val *
905
bhnd_nvram_prop_val(bhnd_nvram_prop *prop)
906
{
907
return (prop->val);
908
}
909
910
/**
911
* Return the property's value type.
912
*
913
* @param prop The property to query.
914
*/
915
bhnd_nvram_type
916
bhnd_nvram_prop_type(bhnd_nvram_prop *prop)
917
{
918
return (bhnd_nvram_val_type(prop->val));
919
}
920
921
/**
922
* Return true if @p prop has a NULL value type (BHND_NVRAM_TYPE_NULL), false
923
* otherwise.
924
*
925
* @param prop The property to query.
926
*/
927
bool
928
bhnd_nvram_prop_is_null(bhnd_nvram_prop *prop)
929
{
930
return (bhnd_nvram_prop_type(prop) == BHND_NVRAM_TYPE_NULL);
931
}
932
933
/**
934
* Return a borrowed reference to the property's internal value representation.
935
*
936
* @param prop The property to query.
937
* @param[out] olen The returned data's size, in bytes.
938
* @param[out] otype The returned data's type.
939
*/
940
const void *
941
bhnd_nvram_prop_bytes(bhnd_nvram_prop *prop, size_t *olen,
942
bhnd_nvram_type *otype)
943
{
944
const void *bytes;
945
946
bytes = bhnd_nvram_val_bytes(prop->val, olen, otype);
947
BHND_NV_ASSERT(*otype == bhnd_nvram_prop_type(prop), ("type mismatch"));
948
949
return (bytes);
950
}
951
952
/**
953
* Attempt to encode the property's value as @p otype, writing the result
954
* to @p outp.
955
*
956
* @param prop The property to be encoded.
957
* @param[out] outp On success, the value will be written to this
958
* buffer. This argment may be NULL if the value is
959
* not desired.
960
* @param[in,out] olen The capacity of @p outp. On success, will be set
961
* to the actual size of the requested value.
962
* @param otype The data type to be written to @p outp.
963
*
964
* @retval 0 success
965
* @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
966
* is too small to hold the encoded value.
967
* @retval EFTYPE If value coercion from @p prop to @p otype is
968
* impossible.
969
* @retval ERANGE If value coercion would overflow (or underflow) the
970
* a @p otype representation.
971
*/
972
int
973
bhnd_nvram_prop_encode(bhnd_nvram_prop *prop, void *outp, size_t *olen,
974
bhnd_nvram_type otype)
975
{
976
return (bhnd_nvram_val_encode(prop->val, outp, olen, otype));
977
}
978
979