1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org> 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/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 34 #ifdef _KERNEL 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 39 #include <machine/_inttypes.h> 40 41 #else /* !_KERNEL */ 42 43 #include <errno.h> 44 #include <stdint.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #endif /* _KERNEL */ 49 50 #include "bhnd_nvram_private.h" 51 #include "bhnd_nvram_io.h" 52 53 #include "bhnd_nvram_datavar.h" 54 #include "bhnd_nvram_data.h" 55 56 /** 57 * Return a human-readable description for the given NVRAM data class. 58 * 59 * @param cls The NVRAM class. 60 */ 61 const char * 62 bhnd_nvram_data_class_desc(bhnd_nvram_data_class *cls) 63 { 64 return (cls->desc); 65 } 66 67 /** 68 * Return the class-level capability flags (@see BHND_NVRAM_DATA_CAP_*) for 69 * of @p cls. 70 * 71 * @param cls The NVRAM class. 72 */ 73 uint32_t 74 bhnd_nvram_data_class_caps(bhnd_nvram_data_class *cls) 75 { 76 return (cls->caps); 77 } 78 79 /** 80 * Serialize all NVRAM properties in @p plist using @p cls's NVRAM data 81 * format, writing the result to @p outp. 82 * 83 * @param cls The NVRAM data class to be used to perform 84 * serialization. 85 * @param props The raw property values to be serialized to 86 * @p outp, in serialization order. 87 * @param options Serialization options for @p cls, or NULL. 88 * @param[out] outp On success, the serialed NVRAM data will be 89 * written to this buffer. This argment may be 90 * NULL if the value is not desired. 91 * @param[in,out] olen The capacity of @p buf. On success, will be set 92 * to the actual length of the serialized data. 93 * 94 * @retval 0 success 95 * 96 * @retval ENOMEM If @p outp is non-NULL and a buffer of @p olen is too 97 * small to hold the serialized data. 98 * @retval EINVAL If a property value required by @p cls is not found in 99 * @p plist. 100 * @retval EFTYPE If a property value in @p plist cannot be represented 101 * as the data type required by @p cls. 102 * @retval ERANGE If a property value in @p plist would would overflow 103 * (or underflow) the data type required by @p cls. 104 * @retval non-zero If serialization otherwise fails, a regular unix error 105 * code will be returned. 106 */ 107 int 108 bhnd_nvram_data_serialize(bhnd_nvram_data_class *cls, 109 bhnd_nvram_plist *props, bhnd_nvram_plist *options, void *outp, 110 size_t *olen) 111 { 112 return (cls->op_serialize(cls, props, options, outp, olen)); 113 } 114 115 /** 116 * Probe to see if this NVRAM data class class supports the data mapped by the 117 * given I/O context, returning a BHND_NVRAM_DATA_PROBE probe result. 118 * 119 * @param cls The NVRAM class. 120 * @param io An I/O context mapping the NVRAM data. 121 * 122 * @retval 0 if this is the only possible NVRAM data class for @p io. 123 * @retval negative if the probe succeeds, a negative value should be returned; 124 * the class returning the highest negative value should be selected to handle 125 * NVRAM parsing. 126 * @retval ENXIO If the NVRAM format is not handled by @p cls. 127 * @retval positive if an error occurs during probing, a regular unix error 128 * code should be returned. 129 */ 130 int 131 bhnd_nvram_data_probe(bhnd_nvram_data_class *cls, struct bhnd_nvram_io *io) 132 { 133 return (cls->op_probe(io)); 134 } 135 136 /** 137 * Probe to see if an NVRAM data class in @p classes supports parsing 138 * of the data mapped by @p io, returning the parsed data in @p data. 139 * 140 * The caller is responsible for deallocating the returned instance via 141 * bhnd_nvram_data_release(). 142 * 143 * @param[out] data On success, the parsed NVRAM data instance. 144 * @param io An I/O context mapping the NVRAM data to be copied and parsed. 145 * @param classes An array of NVRAM data classes to be probed, or NULL to 146 * probe the default supported set. 147 * @param num_classes The number of NVRAM data classes in @p classes. 148 * 149 * @retval 0 success 150 * @retval ENXIO if no class is found capable of parsing @p io. 151 * @retval non-zero if an error otherwise occurs during allocation, 152 * initialization, or parsing of the NVRAM data, a regular unix error code 153 * will be returned. 154 */ 155 int 156 bhnd_nvram_data_probe_classes(struct bhnd_nvram_data **data, 157 struct bhnd_nvram_io *io, bhnd_nvram_data_class *classes[], 158 size_t num_classes) 159 { 160 bhnd_nvram_data_class *cls; 161 int error, prio, result; 162 163 cls = NULL; 164 prio = 0; 165 *data = NULL; 166 167 /* If class array is NULL, default to our linker set */ 168 if (classes == NULL) { 169 classes = SET_BEGIN(bhnd_nvram_data_class_set); 170 num_classes = SET_COUNT(bhnd_nvram_data_class_set); 171 } 172 173 /* Try to find the best data class capable of parsing io */ 174 for (size_t i = 0; i < num_classes; i++) { 175 bhnd_nvram_data_class *next_cls; 176 177 next_cls = classes[i]; 178 179 /* Try to probe */ 180 result = bhnd_nvram_data_probe(next_cls, io); 181 182 /* The parser did not match if an error was returned */ 183 if (result > 0) 184 continue; 185 186 /* Lower priority than previous match; keep 187 * searching */ 188 if (cls != NULL && result <= prio) 189 continue; 190 191 /* Drop any previously parsed data */ 192 if (*data != NULL) { 193 bhnd_nvram_data_release(*data); 194 *data = NULL; 195 } 196 197 /* If this is a 'maybe' match, attempt actual parsing to 198 * verify that this does in fact match */ 199 if (result <= BHND_NVRAM_DATA_PROBE_MAYBE) { 200 /* If parsing fails, keep searching */ 201 error = bhnd_nvram_data_new(next_cls, data, io); 202 if (error) 203 continue; 204 } 205 206 /* Record best new match */ 207 prio = result; 208 cls = next_cls; 209 210 211 /* Terminate search immediately on 212 * BHND_NVRAM_DATA_PROBE_SPECIFIC */ 213 if (result == BHND_NVRAM_DATA_PROBE_SPECIFIC) 214 break; 215 } 216 217 /* If no match, return error */ 218 if (cls == NULL) 219 return (ENXIO); 220 221 /* If the NVRAM data was not parsed above, do so now */ 222 if (*data == NULL) { 223 if ((error = bhnd_nvram_data_new(cls, data, io))) 224 return (error); 225 } 226 227 return (0); 228 } 229 230 /** 231 * Read a variable directly from @p io and decode as @p type. 232 * 233 * This may be used to perform reading of NVRAM variables during the very 234 * early boot process, prior to the availability of the kernel allocator. 235 * 236 * @param cls An NVRAM class capable of parsing @p io. 237 * @param io NVRAM data to be parsed. 238 * @param name The raw name of the variable to be fetched, 239 * including any device path (/pci/1/1/varname) or 240 * alias prefix (0:varname). 241 * @param[out] buf On success, the requested value will be written 242 * to this buffer. This argment may be NULL if 243 * the value is not desired. 244 * @param[in,out] len The capacity of @p buf. On success, will be set 245 * to the actual size of the requested value. 246 * @param type The data type to be written to @p buf. 247 * 248 * @retval 0 success 249 * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too 250 * small to hold the requested value. 251 * @retval ENOENT If @p name is not found in @p io. 252 * @retval EFTYPE If the variable data cannot be coerced to @p type. 253 * @retval ERANGE If value coercion would overflow @p type. 254 * @retval non-zero If parsing @p io otherwise fails, a regular unix error 255 * code will be returned. 256 */ 257 int 258 bhnd_nvram_data_getvar_direct(bhnd_nvram_data_class *cls, 259 struct bhnd_nvram_io *io, const char *name, void *buf, size_t *len, 260 bhnd_nvram_type type) 261 { 262 return (cls->op_getvar_direct(io, name, buf, len, type)); 263 } 264 265 /** 266 * Allocate and initialize a new instance of data class @p cls, copying and 267 * parsing NVRAM data from @p io. 268 * 269 * The caller is responsible for releasing the returned parser instance 270 * reference via bhnd_nvram_data_release(). 271 * 272 * @param cls If non-NULL, the data class to be allocated. If NULL, 273 * bhnd_nvram_data_probe_classes() will be used to determine the data format. 274 * @param[out] nv On success, a pointer to the newly allocated NVRAM data instance. 275 * @param io An I/O context mapping the NVRAM data to be copied and parsed. 276 * 277 * @retval 0 success 278 * @retval non-zero if an error occurs during allocation or initialization, a 279 * regular unix error code will be returned. 280 */ 281 int 282 bhnd_nvram_data_new(bhnd_nvram_data_class *cls, struct bhnd_nvram_data **nv, 283 struct bhnd_nvram_io *io) 284 { 285 struct bhnd_nvram_data *data; 286 int error; 287 288 /* If NULL, try to identify the appropriate class */ 289 if (cls == NULL) 290 return (bhnd_nvram_data_probe_classes(nv, io, NULL, 0)); 291 292 /* Allocate new instance */ 293 BHND_NV_ASSERT(sizeof(struct bhnd_nvram_data) <= cls->size, 294 ("instance size %zu less than minimum %zu", cls->size, 295 sizeof(struct bhnd_nvram_data))); 296 297 data = bhnd_nv_calloc(1, cls->size); 298 data->cls = cls; 299 refcount_init(&data->refs, 1); 300 301 /* Let the class handle initialization */ 302 if ((error = cls->op_new(data, io))) { 303 bhnd_nv_free(data); 304 return (error); 305 } 306 307 *nv = data; 308 return (0); 309 } 310 311 /** 312 * Retain and return a reference to the given data instance. 313 * 314 * @param nv The reference to be retained. 315 */ 316 struct bhnd_nvram_data * 317 bhnd_nvram_data_retain(struct bhnd_nvram_data *nv) 318 { 319 refcount_acquire(&nv->refs); 320 return (nv); 321 } 322 323 /** 324 * Release a reference to the given data instance. 325 * 326 * If this is the last reference, the data instance and its associated 327 * resources will be freed. 328 * 329 * @param nv The reference to be released. 330 */ 331 void 332 bhnd_nvram_data_release(struct bhnd_nvram_data *nv) 333 { 334 if (!refcount_release(&nv->refs)) 335 return; 336 337 /* Free any internal resources */ 338 nv->cls->op_free(nv); 339 340 /* Free the instance allocation */ 341 bhnd_nv_free(nv); 342 } 343 344 /** 345 * Return a pointer to @p nv's data class. 346 * 347 * @param nv The NVRAM data instance to be queried. 348 */ 349 bhnd_nvram_data_class * 350 bhnd_nvram_data_get_class(struct bhnd_nvram_data *nv) 351 { 352 return (nv->cls); 353 } 354 355 /** 356 * Return the number of variables in @p nv. 357 * 358 * @param nv The NVRAM data to be queried. 359 */ 360 size_t 361 bhnd_nvram_data_count(struct bhnd_nvram_data *nv) 362 { 363 return (nv->cls->op_count(nv)); 364 } 365 366 /** 367 * Return a borrowed reference to the serialization options for @p nv, 368 * suitable for use with bhnd_nvram_data_serialize(), or NULL if none. 369 * 370 * @param nv The NVRAM data to be queried. 371 */ 372 bhnd_nvram_plist * 373 bhnd_nvram_data_options(struct bhnd_nvram_data *nv) 374 { 375 return (nv->cls->op_options(nv)); 376 } 377 378 /** 379 * Return the capability flags (@see BHND_NVRAM_DATA_CAP_*) for @p nv. 380 * 381 * @param nv The NVRAM data to be queried. 382 */ 383 uint32_t 384 bhnd_nvram_data_caps(struct bhnd_nvram_data *nv) 385 { 386 return (nv->cls->op_caps(nv)); 387 } 388 389 /** 390 * Iterate over @p nv, returning the names of subsequent variables. 391 * 392 * @param nv The NVRAM data to be iterated. 393 * @param[in,out] cookiep A pointer to a cookiep value previously returned 394 * by bhnd_nvram_data_next(), or a NULL value to 395 * begin iteration. 396 * 397 * @return Returns the next variable name, or NULL if there are no more 398 * variables defined in @p nv. 399 */ 400 const char * 401 bhnd_nvram_data_next(struct bhnd_nvram_data *nv, void **cookiep) 402 { 403 const char *name; 404 #ifdef BHND_NV_INVARIANTS 405 void *prev = *cookiep; 406 #endif 407 408 /* Fetch next */ 409 if ((name = nv->cls->op_next(nv, cookiep)) == NULL) 410 return (NULL); 411 412 /* Enforce precedence ordering invariant between bhnd_nvram_data_next() 413 * and bhnd_nvram_data_getvar_order() */ 414 #ifdef BHND_NV_INVARIANTS 415 if (prev != NULL && 416 bhnd_nvram_data_getvar_order(nv, prev, *cookiep) > 0) 417 { 418 BHND_NV_PANIC("%s: returned out-of-order entry", __FUNCTION__); 419 } 420 #endif 421 422 return (name); 423 } 424 425 /** 426 * Search @p nv for a named variable, returning the variable's opaque reference 427 * if found, or NULL if unavailable. 428 * 429 * The BHND_NVRAM_DATA_CAP_INDEXED capability flag will be returned by 430 * bhnd_nvram_data_caps() if @p nv supports effecient name-based 431 * lookups. 432 * 433 * @param nv The NVRAM data to search. 434 * @param name The name to search for. 435 * 436 * @retval non-NULL If @p name is found, the opaque cookie value will be 437 * returned. 438 * @retval NULL If @p name is not found. 439 */ 440 void * 441 bhnd_nvram_data_find(struct bhnd_nvram_data *nv, const char *name) 442 { 443 return (nv->cls->op_find(nv, name)); 444 } 445 446 /** 447 * A generic implementation of bhnd_nvram_data_find(). 448 * 449 * This implementation will use bhnd_nvram_data_next() to perform a 450 * simple O(n) case-insensitve search for @p name. 451 */ 452 void * 453 bhnd_nvram_data_generic_find(struct bhnd_nvram_data *nv, const char *name) 454 { 455 const char *next; 456 void *cookiep; 457 458 cookiep = NULL; 459 while ((next = bhnd_nvram_data_next(nv, &cookiep))) { 460 if (strcmp(name, next) == 0) 461 return (cookiep); 462 } 463 464 /* Not found */ 465 return (NULL); 466 } 467 468 /** 469 * Compare the declaration order of two NVRAM variables. 470 * 471 * Variable declaration order is used to determine the current order of 472 * the variables in the source data, as well as to determine the precedence 473 * of variable declarations in data sources that define duplicate names. 474 * 475 * The comparison order will match the order of variables returned via 476 * bhnd_nvstore_path_data_next(). 477 * 478 * @param nv The NVRAM data. 479 * @param cookiep1 An NVRAM variable cookie previously 480 * returned via bhnd_nvram_data_next() or 481 * bhnd_nvram_data_find(). 482 * @param cookiep2 An NVRAM variable cookie previously 483 * returned via bhnd_nvram_data_next() or 484 * bhnd_nvram_data_find(). 485 * 486 * @retval <= -1 If @p cookiep1 has an earlier declaration order than 487 * @p cookiep2. 488 * @retval 0 If @p cookiep1 and @p cookiep2 are identical. 489 * @retval >= 1 If @p cookiep has a later declaration order than 490 * @p cookiep2. 491 */ 492 int 493 bhnd_nvram_data_getvar_order(struct bhnd_nvram_data *nv, void *cookiep1, 494 void *cookiep2) 495 { 496 return (nv->cls->op_getvar_order(nv, cookiep1, cookiep2)); 497 } 498 499 /** 500 * Read a variable and decode as @p type. 501 * 502 * @param nv The NVRAM data. 503 * @param cookiep An NVRAM variable cookie previously returned 504 * via bhnd_nvram_data_next() or 505 * bhnd_nvram_data_find(). 506 * @param[out] buf On success, the requested value will be written 507 * to this buffer. This argment may be NULL if 508 * the value is not desired. 509 * @param[in,out] len The capacity of @p buf. On success, will be set 510 * to the actual size of the requested value. 511 * @param type The data type to be written to @p buf. 512 * 513 * @retval 0 success 514 * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too 515 * small to hold the requested value. 516 * @retval EFTYPE If the variable data cannot be coerced to @p type. 517 * @retval ERANGE If value coercion would overflow @p type. 518 */ 519 int 520 bhnd_nvram_data_getvar(struct bhnd_nvram_data *nv, void *cookiep, void *buf, 521 size_t *len, bhnd_nvram_type type) 522 { 523 return (nv->cls->op_getvar(nv, cookiep, buf, len, type)); 524 } 525 526 /* 527 * Common bhnd_nvram_data_getvar_ptr() wrapper used by 528 * bhnd_nvram_data_generic_rp_getvar() and 529 * bhnd_nvram_data_generic_rp_copy_val(). 530 * 531 * If a variable definition for the requested variable is found via 532 * bhnd_nvram_find_vardefn(), the definition will be used to populate fmt. 533 */ 534 static const void * 535 bhnd_nvram_data_getvar_ptr_info(struct bhnd_nvram_data *nv, void *cookiep, 536 size_t *len, bhnd_nvram_type *type, const bhnd_nvram_val_fmt **fmt) 537 { 538 const struct bhnd_nvram_vardefn *vdefn; 539 const char *name; 540 const void *vptr; 541 542 BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR, 543 ("instance does not advertise READ_PTR support")); 544 545 /* Fetch pointer to variable data */ 546 vptr = bhnd_nvram_data_getvar_ptr(nv, cookiep, len, type); 547 if (vptr == NULL) 548 return (NULL); 549 550 /* Select a default value format implementation */ 551 552 553 /* Fetch the reference variable name */ 554 name = bhnd_nvram_data_getvar_name(nv, cookiep); 555 556 /* Trim path prefix, if any; the Broadcom NVRAM format assumes a global 557 * namespace for all variable definitions */ 558 if (bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_DEVPATHS) 559 name = bhnd_nvram_trim_path_name(name); 560 561 /* Check the variable definition table for a matching entry; if 562 * it exists, use it to populate the value format. */ 563 vdefn = bhnd_nvram_find_vardefn(name); 564 if (vdefn != NULL) { 565 BHND_NV_ASSERT(vdefn->fmt != NULL, 566 ("NULL format for %s", name)); 567 *fmt = vdefn->fmt; 568 } else if (*type == BHND_NVRAM_TYPE_STRING) { 569 /* Default to Broadcom-specific string interpretation */ 570 *fmt = &bhnd_nvram_val_bcm_string_fmt; 571 } else { 572 /* Fall back on native formatting */ 573 *fmt = bhnd_nvram_val_default_fmt(*type); 574 } 575 576 return (vptr); 577 } 578 579 /** 580 * A generic implementation of bhnd_nvram_data_getvar(). 581 * 582 * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch 583 * a pointer to the variable data and perform data coercion on behalf 584 * of the caller. 585 * 586 * If a variable definition for the requested variable is available via 587 * bhnd_nvram_find_vardefn(), the definition will be used to provide a 588 * formatting instance to bhnd_nvram_val_init(). 589 */ 590 int 591 bhnd_nvram_data_generic_rp_getvar(struct bhnd_nvram_data *nv, void *cookiep, 592 void *outp, size_t *olen, bhnd_nvram_type otype) 593 { 594 bhnd_nvram_val val; 595 const bhnd_nvram_val_fmt *fmt; 596 const void *vptr; 597 bhnd_nvram_type vtype; 598 size_t vlen; 599 int error; 600 601 BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR, 602 ("instance does not advertise READ_PTR support")); 603 604 /* Fetch variable data and value format*/ 605 vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype, 606 &fmt); 607 if (vptr == NULL) 608 return (EINVAL); 609 610 /* Attempt value coercion */ 611 error = bhnd_nvram_val_init(&val, fmt, vptr, vlen, vtype, 612 BHND_NVRAM_VAL_BORROW_DATA); 613 if (error) 614 return (error); 615 616 error = bhnd_nvram_val_encode(&val, outp, olen, otype); 617 618 /* Clean up */ 619 bhnd_nvram_val_release(&val); 620 return (error); 621 } 622 623 /** 624 * Return a caller-owned copy of an NVRAM entry's variable data. 625 * 626 * The caller is responsible for deallocating the returned value via 627 * bhnd_nvram_val_release(). 628 * 629 * @param nv The NVRAM data. 630 * @param cookiep An NVRAM variable cookie previously returned 631 * via bhnd_nvram_data_next() or bhnd_nvram_data_find(). 632 * @param[out] value On success, the caller-owned value instance. 633 * 634 * @retval 0 success 635 * @retval ENOMEM If allocation fails. 636 * @retval non-zero If initialization of the value otherwise fails, a 637 * regular unix error code will be returned. 638 */ 639 int 640 bhnd_nvram_data_copy_val(struct bhnd_nvram_data *nv, void *cookiep, 641 bhnd_nvram_val **value) 642 { 643 return (nv->cls->op_copy_val(nv, cookiep, value)); 644 } 645 646 /** 647 * A generic implementation of bhnd_nvram_data_copy_val(). 648 * 649 * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch 650 * a pointer to the variable data and perform data coercion on behalf 651 * of the caller. 652 * 653 * If a variable definition for the requested variable is available via 654 * bhnd_nvram_find_vardefn(), the definition will be used to provide a 655 * formatting instance to bhnd_nvram_val_init(). 656 */ 657 int 658 bhnd_nvram_data_generic_rp_copy_val(struct bhnd_nvram_data *nv, 659 void *cookiep, bhnd_nvram_val **value) 660 { 661 const bhnd_nvram_val_fmt *fmt; 662 const void *vptr; 663 bhnd_nvram_type vtype; 664 size_t vlen; 665 666 BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR, 667 ("instance does not advertise READ_PTR support")); 668 669 /* Fetch variable data and value format*/ 670 vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype, 671 &fmt); 672 if (vptr == NULL) 673 return (EINVAL); 674 675 /* Allocate and return the new value instance */ 676 return (bhnd_nvram_val_new(value, fmt, vptr, vlen, vtype, 677 BHND_NVRAM_VAL_DYNAMIC)); 678 } 679 680 /** 681 * If available and supported by the NVRAM data instance, return a reference 682 * to the internal buffer containing an entry's variable data, 683 * 684 * Note that string values may not be NUL terminated. 685 * 686 * @param nv The NVRAM data. 687 * @param cookiep An NVRAM variable cookie previously returned 688 * via bhnd_nvram_data_next() or 689 * bhnd_nvram_data_find(). 690 * @param[out] len On success, will be set to the actual size of 691 * the requested value. 692 * @param[out] type The data type of the entry data. 693 * 694 * @retval non-NULL success 695 * @retval NULL if direct data access is unsupported by @p nv, or 696 * unavailable for @p cookiep. 697 */ 698 const void * 699 bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data *nv, void *cookiep, 700 size_t *len, bhnd_nvram_type *type) 701 { 702 return (nv->cls->op_getvar_ptr(nv, cookiep, len, type)); 703 } 704 705 706 /** 707 * Return the variable name associated with a given @p cookiep. 708 * @param nv The NVRAM data to be iterated. 709 * @param[in,out] cookiep A pointer to a cookiep value previously returned 710 * via bhnd_nvram_data_next() or 711 * bhnd_nvram_data_find(). 712 * 713 * @return Returns the variable's name. 714 */ 715 const char * 716 bhnd_nvram_data_getvar_name(struct bhnd_nvram_data *nv, void *cookiep) 717 { 718 return (nv->cls->op_getvar_name(nv, cookiep)); 719 } 720 721 /** 722 * Filter a request to set variable @p name with @p value. 723 * 724 * On success, the caller owns a reference to @p result, and must release 725 * any held resources via bhnd_nvram_val_release(). 726 * 727 * @param nv The NVRAM data instance. 728 * @param name The name of the variable to be set. 729 * @param value The proposed value to be set. 730 * @param[out] result On success, a caller-owned reference to the filtered 731 * value to be set. 732 * 733 * @retval 0 success 734 * @retval ENOENT if @p name is unrecognized by @p nv. 735 * @retval EINVAL if @p name is read-only. 736 * @retval EINVAL if @p value cannot be converted to the required value 737 * type. 738 */ 739 int 740 bhnd_nvram_data_filter_setvar(struct bhnd_nvram_data *nv, const char *name, 741 bhnd_nvram_val *value, bhnd_nvram_val **result) 742 { 743 return (nv->cls->op_filter_setvar(nv, name, value, result)); 744 } 745 746 /** 747 * Filter a request to delete variable @p name. 748 * 749 * @param nv The NVRAM data instance. 750 * @param name The name of the variable to be deleted. 751 * 752 * @retval 0 success 753 * @retval ENOENT if @p name is unrecognized by @p nv. 754 * @retval EINVAL if @p name is read-only. 755 */ 756 int 757 bhnd_nvram_data_filter_unsetvar(struct bhnd_nvram_data *nv, const char *name) 758 { 759 return (nv->cls->op_filter_unsetvar(nv, name)); 760 } 761