diff options
Diffstat (limited to 'usr/src/cmd/eeprom/i386/benv.c')
| -rw-r--r-- | usr/src/cmd/eeprom/i386/benv.c | 278 |
1 files changed, 271 insertions, 7 deletions
diff --git a/usr/src/cmd/eeprom/i386/benv.c b/usr/src/cmd/eeprom/i386/benv.c index 0e3a89f0b7..697bcd9a19 100644 --- a/usr/src/cmd/eeprom/i386/benv.c +++ b/usr/src/cmd/eeprom/i386/benv.c @@ -27,10 +27,12 @@ #include "benv.h" #include <ctype.h> #include <stdarg.h> +#include <stdbool.h> #include <sys/mman.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> +#include <libzfsbootenv.h> /* * Usage: % eeprom [-v] [-f prom_dev] [-] @@ -671,33 +673,295 @@ get_line(void) return (NULL); } +static int +add_pair(const char *name, const char *nvlist, const char *key, + const char *type, const char *value) +{ + void *data, *nv; + size_t size; + int rv; + char *end; + + rv = lzbe_nvlist_get(name, nvlist, &nv); + if (rv != 0) + return (rv); + + data = NULL; + rv = EINVAL; + if (strcmp(type, "DATA_TYPE_STRING") == 0) { + data = (void *)(uintptr_t)value; + size = strlen(data) + 1; + rv = lzbe_add_pair(nv, key, type, data, size); + } else if (strcmp(type, "DATA_TYPE_UINT64") == 0) { + uint64_t v; + + v = strtoull(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_INT64") == 0) { + int64_t v; + + v = strtoll(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_UINT32") == 0) { + u_longlong_t lv; + uint32_t v; + + lv = strtoull(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv > UINT32_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_INT32") == 0) { + longlong_t lv; + int32_t v; + + lv = strtoll(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv < INT32_MIN || lv > INT32_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_UINT16") == 0) { + uint32_t lv; + uint16_t v; + + lv = strtoul(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv > UINT16_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_INT16") == 0) { + int32_t lv; + int16_t v; + + v = strtol(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv < INT16_MIN || lv > INT16_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_UINT8") == 0) { + uint32_t lv; + uint8_t v; + + lv = strtoul(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv > UINT8_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_INT8") == 0) { + int32_t lv; + int8_t v; + + lv = strtol(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv < INT8_MIN || lv > INT8_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_BYTE") == 0) { + uint32_t lv; + uint8_t v; + + lv = strtoul(value, &end, 0); + if (errno != 0 || *end != '\0') + goto done; + if (lv > UINT8_MAX) + goto done; + v = lv; + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } else if (strcmp(type, "DATA_TYPE_BOOLEAN_VALUE") == 0) { + int32_t v; + + v = strtol(value, &end, 0); + if (errno != 0 || *end != '\0') { + if (strcasecmp(value, "YES") == 0) + v = 1; + else if (strcasecmp(value, "NO") == 0) + v = 0; + else if (strcasecmp(value, "true") == 0) + v = 1; + else if (strcasecmp(value, "false") == 0) + v = 0; + else goto done; + } + size = sizeof (v); + rv = lzbe_add_pair(nv, key, type, &v, size); + } + + if (rv == 0) + rv = lzbe_nvlist_set(name, nvlist, nv); + +done: + lzbe_nvlist_free(nv); + return (rv); +} + +static int +delete_pair(const char *name, const char *nvlist, const char *key) +{ + void *nv; + int rv; + + rv = lzbe_nvlist_get(name, nvlist, &nv); + if (rv == 0) + rv = lzbe_remove_pair(nv, key); + + if (rv == 0) + rv = lzbe_nvlist_set(name, nvlist, nv); + + lzbe_nvlist_free(nv); + return (rv); +} + +static int +usage(char *name) +{ + char *usage = "Usage: %s [-v] [-f prom-device]" + " [variable[=value] ...]\n" + "%s [-z pool] [-d key] [-k key -t type -v value] [-p]\n" + "%s [-z pool] -n nvlist [-d key] [-k key -t type -v value] [-p]\n"; + + return (_error(NO_PERROR, usage, name, name, name)); +} + int main(int argc, char **argv) { int c; int updates = 0; - char *usage = "Usage: %s [-v] [-f prom-device]" - " [variable[=value] ...]"; eplist_t *elist; benv_des_t *bd; char *file = NULL; + bool bootenv, bootenv_print, bootenv_delete; + char *name, *key, *type, *nvlist, *value; + lzbe_flags_t flag = lzbe_add; + + nvlist = NULL; + name = "rpool"; + key = NULL; + type = NULL; + value = NULL; + bootenv = false; + bootenv_print = false; + bootenv_delete = false; setpname(argv[0]); - while ((c = getopt(argc, argv, "f:Itv")) != -1) + while ((c = getopt(argc, argv, "bd:f:k:n:prt:v:z:")) != -1) switch (c) { - case 'v': - verbose++; + case 'b': + bootenv = true; + break; + case 'd': + if (bootenv) { + bootenv_delete = true; + key = optarg; + } else { + exit(usage(argv[0])); + } break; case 'f': file = optarg; break; + case 'k': + if (bootenv) + key = optarg; + else + exit(usage(argv[0])); + break; + case 'n': + if (bootenv) + nvlist = optarg; + else + exit(usage(argv[0])); + break; + case 'p': + if (bootenv) + bootenv_print = true; + else + exit(usage(argv[0])); + break; + case 'r': + if (bootenv) + flag = lzbe_replace; + else + exit(usage(argv[0])); + break; case 't': - test++; + if (bootenv) + type = optarg; + else + test++; + break; + case 'v': + if (bootenv) + value = optarg; + else + verbose++; + break; + case 'z': + if (bootenv) + name = optarg; + else + exit(usage(argv[0])); break; default: - exit(_error(NO_PERROR, usage, argv[0])); + exit(usage(argv[0])); + } + + argc -= optind; + argv += optind; + + if (bootenv) { + int rv = 0; + + if (argc == 1) + value = argv[0]; + + if (bootenv_print) + return (lzbe_bootenv_print(name, nvlist, stdout)); + + if (key != NULL || value != NULL) { + if (type == NULL) + type = "DATA_TYPE_STRING"; + + if (bootenv_delete) + rv = delete_pair(name, nvlist, key); + else if (key == NULL) + rv = lzbe_set_boot_device(name, flag, value); + else + rv = add_pair(name, nvlist, key, type, value); + + if (rv == 0) + printf("zfs bootenv is successfully written\n"); + else + printf("error: %s\n", strerror(rv)); } + return (rv); + } (void) uname(&uts_buf); bd = new_bd(); |
