/* $NetBSD: efienv.c,v 1.4 2019/04/21 22:30:41 thorpej Exp $ */ /*- * Copyright (c) 2019 Jason R. Thorpe * Copyright (c) 2018 Jared McNeill * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "efiboot.h" #include "efienv.h" #define EFIBOOT_VENDOR_GUID \ { 0x97cde9bd, 0xac88, 0x4cf9, { 0x84, 0x86, 0x01, 0x33, 0x0f, 0xe1, 0x95, 0xd4 } } static EFI_GUID EfibootVendorGuid = EFIBOOT_VENDOR_GUID; void efi_env_from_efibootplist(void) { /* * We support pre-loading the EFI environment from efiboot.plist * using the following schema: * * environment-variables * * varname1 * value_for_varname1 * varname2 * value_for_varname2 * * * Only string values are supported. */ prop_dictionary_t environment; prop_dictionary_keysym_t key; prop_string_t value; prop_object_iterator_t iter; const char *env_key; char *env_value; environment = prop_dictionary_get(efibootplist, "environment-variables"); if (environment == NULL) return; iter = prop_dictionary_iterator(environment); if (iter == NULL) goto failed; while ((key = prop_object_iterator_next(iter)) != NULL) { value = prop_dictionary_get_keysym(environment, key); if (value == NULL) { printf("boot: env: failed to get value for '%s'\n", prop_dictionary_keysym_cstring_nocopy(key)); continue; } if (prop_object_type(value) != PROP_TYPE_STRING) { printf("boot: env: value for '%s' is not a string\n", prop_dictionary_keysym_cstring_nocopy(key)); continue; } /* XXX __UNCONST because gnuefi */ env_key = prop_dictionary_keysym_cstring_nocopy(key);; env_value = __UNCONST(prop_string_cstring_nocopy(value));; #ifdef EFIBOOT_DEBUG printf(">> efiboot.plist env: '%s' = '%s'\n", env_key, env_value); #endif efi_env_set(env_key, env_value); } prop_object_iterator_release(iter); return; failed: printf("boot: failed to load environment from efiboot.plist"); } void efi_env_set(const char *key, char *val) { EFI_STATUS status; CHAR16 *ukey; size_t len; ukey = NULL; utf8_to_ucs2(key, &ukey, &len); status = LibSetNVVariable(ukey, &EfibootVendorGuid, strlen(val) + 1, val); FreePool(ukey); if (EFI_ERROR(status)) printf("env: failed to set variable '%s': %#lx\n", key, (u_long)status); } char * efi_env_get(const char *key) { CHAR16 *ukey; size_t len; char *ret; ukey = NULL; utf8_to_ucs2(key, &ukey, &len); ret = LibGetVariable(ukey, &EfibootVendorGuid); FreePool(ukey); return ret; } void efi_env_clear(const char *key) { CHAR16 *ukey; size_t len; ukey = NULL; utf8_to_ucs2(key, &ukey, &len); LibDeleteVariable(ukey, &EfibootVendorGuid); FreePool(ukey); } void efi_env_reset(void) { EFI_STATUS status; CHAR16 ukey[256]; EFI_GUID vendor; UINTN size; retry: ukey[0] = '\0'; vendor = NullGuid; for (;;) { size = sizeof(ukey); status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, ukey, &vendor); if (status != EFI_SUCCESS) break; if (CompareGuid(&vendor, &EfibootVendorGuid) == 0) { LibDeleteVariable(ukey, &vendor); goto retry; } } } void efi_env_print(void) { EFI_STATUS status; CHAR16 ukey[256]; EFI_GUID vendor; UINTN size; char *val; ukey[0] = '\0'; vendor = NullGuid; for (;;) { size = sizeof(ukey); status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, ukey, &vendor); if (status != EFI_SUCCESS) break; if (CompareGuid(&vendor, &EfibootVendorGuid) != 0) continue; Print(L"\"%s\" = ", ukey); val = LibGetVariable(ukey, &vendor); printf("\"%s\"\n", val); FreePool(val); } }