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