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