env.c revision 329011
1300081Simp/* 2300081Simp * Copyright (c) 2015 Netflix, Inc. All Rights Reserved. 3300081Simp * 4300081Simp * Redistribution and use in source and binary forms, with or without 5300081Simp * modification, are permitted provided that the following conditions 6300081Simp * are met: 7300081Simp * 1. Redistributions of source code must retain the above copyright 8300081Simp * notice, this list of conditions and the following disclaimer. 9300081Simp * 2. Redistributions in binary form must reproduce the above copyright 10300081Simp * notice, this list of conditions and the following disclaimer in the 11300081Simp * documentation and/or other materials provided with the distribution. 12300081Simp * 13300081Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14300081Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15300081Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16300081Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17300081Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18300081Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19300081Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20300081Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21300081Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22300081Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23300081Simp * SUCH DAMAGE. 24300081Simp */ 25300081Simp 26300081Simp#include <sys/cdefs.h> 27300081Simp__FBSDID("$FreeBSD: stable/11/sys/boot/efi/libefi/env.c 329011 2018-02-08 02:50:47Z kevans $"); 28300081Simp 29329011Skevans#include <stand.h> 30329011Skevans#include <string.h> 31300081Simp#include <efi.h> 32300081Simp#include <efilib.h> 33329011Skevans#include <uuid.h> 34329011Skevans#include "bootstrap.h" 35329011Skevans#include "ficl.h" 36300081Simp 37329011Skevansint efi_variable_support = 1; 38329011Skevans 39300081Simp/* 40300081Simp * Simple wrappers to the underlying UEFI functions. 41300081Simp * See http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES 42300081Simp * for details. 43300081Simp */ 44300081SimpEFI_STATUS 45300081Simpefi_get_next_variable_name(UINTN *variable_name_size, CHAR16 *variable_name, EFI_GUID *vendor_guid) 46300081Simp{ 47300081Simp return RS->GetNextVariableName(variable_name_size, variable_name, vendor_guid); 48300081Simp} 49300081Simp 50300081SimpEFI_STATUS 51300081Simpefi_get_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid, UINT32 *attributes, UINTN *data_size, 52300081Simp void *data) 53300081Simp{ 54300081Simp return RS->GetVariable(variable_name, vendor_guid, attributes, data_size, data); 55300081Simp} 56300081Simp 57300081SimpEFI_STATUS 58300081Simpefi_set_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid, UINT32 attributes, UINTN data_size, 59300081Simp void *data) 60300081Simp{ 61300081Simp return RS->SetVariable(variable_name, vendor_guid, attributes, data_size, data); 62300081Simp} 63329011Skevans 64329011Skevans/* 65329011Skevans * FreeBSD's loader interaction words and extras 66329011Skevans * 67329011Skevans * efi-setenv ( value n name n guid n attr -- 0 | -1) 68329011Skevans * efi-getenv ( guid n addr n -- addr' n' | -1 ) 69329011Skevans * efi-unsetenv ( name n guid n'' -- ) 70329011Skevans */ 71329011Skevans 72329011Skevans/* 73329011Skevans * efi-setenv 74329011Skevans * efi-setenv ( value n name n guid n attr -- 0 | -1) 75329011Skevans * 76329011Skevans * Set environment variables using the SetVariable EFI runtime service. 77329011Skevans * 78329011Skevans * Value and guid are passed through in binary form (so guid needs to be 79329011Skevans * converted to binary form from its string form). Name is converted from 80329011Skevans * ASCII to CHAR16. Since ficl doesn't have support for internationalization, 81329011Skevans * there's no native CHAR16 interface provided. 82329011Skevans * 83329011Skevans * attr is an int in the bitmask of the following attributes for this variable. 84329011Skevans * 85329011Skevans * 1 Non volatile 86329011Skevans * 2 Boot service access 87329011Skevans * 4 Run time access 88329011Skevans * (corresponding to the same bits in the UEFI spec). 89329011Skevans */ 90329011Skevansvoid 91329011SkevansficlEfiSetenv(FICL_VM *pVM) 92329011Skevans{ 93329011Skevans#ifndef TESTMAIN 94329011Skevans char *value = NULL, *guid = NULL; 95329011Skevans CHAR16 *name = NULL; 96329011Skevans int i; 97329011Skevans#endif 98329011Skevans char *namep, *valuep, *guidp; 99329011Skevans int names, values, guids, attr; 100329011Skevans int status; 101329011Skevans uuid_t u; 102329011Skevans uint32_t ustatus; 103329011Skevans 104329011Skevans#if FICL_ROBUST > 1 105329011Skevans vmCheckStack(pVM, 6, 0); 106329011Skevans#endif 107329011Skevans attr = stackPopINT(pVM->pStack); 108329011Skevans guids = stackPopINT(pVM->pStack); 109329011Skevans guidp = (char*)stackPopPtr(pVM->pStack); 110329011Skevans names = stackPopINT(pVM->pStack); 111329011Skevans namep = (char*)stackPopPtr(pVM->pStack); 112329011Skevans values = stackPopINT(pVM->pStack); 113329011Skevans valuep = (char*)stackPopPtr(pVM->pStack); 114329011Skevans 115329011Skevans#ifndef TESTMAIN 116329011Skevans guid = (char*)ficlMalloc(guids); 117329011Skevans if (guid == NULL) 118329011Skevans vmThrowErr(pVM, "Error: out of memory"); 119329011Skevans memcpy(guid, guidp, guids); 120329011Skevans uuid_from_string(guid, &u, &ustatus); 121329011Skevans if (ustatus != uuid_s_ok) { 122329011Skevans stackPushINT(pVM->pStack, -1); 123329011Skevans goto out; 124329011Skevans } 125329011Skevans 126329011Skevans name = (CHAR16 *)ficlMalloc((names + 1) * sizeof(CHAR16)); 127329011Skevans if (name == NULL) 128329011Skevans vmThrowErr(pVM, "Error: out of memory"); 129329011Skevans for (i = 0; i < names; i++) 130329011Skevans name[i] = namep[i]; 131329011Skevans name[names] = (CHAR16)0; 132329011Skevans 133329011Skevans value = (char*)ficlMalloc(values + 1); 134329011Skevans if (value == NULL) 135329011Skevans vmThrowErr(pVM, "Error: out of memory"); 136329011Skevans memcpy(value, valuep, values); 137329011Skevans 138329011Skevans status = efi_set_variable(name, (EFI_GUID *)&u, attr, values, value); 139329011Skevans if (status == EFI_SUCCESS) 140329011Skevans stackPushINT(pVM->pStack, 0); 141329011Skevans else 142329011Skevans stackPushINT(pVM->pStack, -1); 143329011Skevansout: 144329011Skevans ficlFree(name); 145329011Skevans ficlFree(value); 146329011Skevans ficlFree(guid); 147329011Skevans#endif 148329011Skevans 149329011Skevans return; 150329011Skevans} 151329011Skevans 152329011Skevansvoid 153329011SkevansficlEfiGetenv(FICL_VM *pVM) 154329011Skevans{ 155329011Skevans#ifndef TESTMAIN 156329011Skevans char *name, *value; 157329011Skevans#endif 158329011Skevans char *namep; 159329011Skevans int names; 160329011Skevans 161329011Skevans#if FICL_ROBUST > 1 162329011Skevans vmCheckStack(pVM, 2, 2); 163329011Skevans#endif 164329011Skevans names = stackPopINT(pVM->pStack); 165329011Skevans namep = (char*) stackPopPtr(pVM->pStack); 166329011Skevans 167329011Skevans#ifndef TESTMAIN 168329011Skevans name = (char*) ficlMalloc(names+1); 169329011Skevans if (name == NULL) 170329011Skevans vmThrowErr(pVM, "Error: out of memory"); 171329011Skevans strncpy(name, namep, names); 172329011Skevans name[names] = '\0'; 173329011Skevans 174329011Skevans value = getenv(name); 175329011Skevans ficlFree(name); 176329011Skevans 177329011Skevans if(value != NULL) { 178329011Skevans stackPushPtr(pVM->pStack, value); 179329011Skevans stackPushINT(pVM->pStack, strlen(value)); 180329011Skevans } else 181329011Skevans#endif 182329011Skevans stackPushINT(pVM->pStack, -1); 183329011Skevans 184329011Skevans return; 185329011Skevans} 186329011Skevans 187329011Skevansvoid 188329011SkevansficlEfiUnsetenv(FICL_VM *pVM) 189329011Skevans{ 190329011Skevans#ifndef TESTMAIN 191329011Skevans char *name; 192329011Skevans#endif 193329011Skevans char *namep; 194329011Skevans int names; 195329011Skevans 196329011Skevans#if FICL_ROBUST > 1 197329011Skevans vmCheckStack(pVM, 2, 0); 198329011Skevans#endif 199329011Skevans names = stackPopINT(pVM->pStack); 200329011Skevans namep = (char*) stackPopPtr(pVM->pStack); 201329011Skevans 202329011Skevans#ifndef TESTMAIN 203329011Skevans name = (char*) ficlMalloc(names+1); 204329011Skevans if (name == NULL) 205329011Skevans vmThrowErr(pVM, "Error: out of memory"); 206329011Skevans strncpy(name, namep, names); 207329011Skevans name[names] = '\0'; 208329011Skevans 209329011Skevans unsetenv(name); 210329011Skevans ficlFree(name); 211329011Skevans#endif 212329011Skevans 213329011Skevans return; 214329011Skevans} 215329011Skevans 216329011Skevans/************************************************************************** 217329011Skevans** Add FreeBSD UEFI platform extensions into the system dictionary 218329011Skevans**************************************************************************/ 219329011Skevansvoid ficlEfiCompilePlatform(FICL_SYSTEM *pSys) 220329011Skevans{ 221329011Skevans FICL_DICT *dp = pSys->dp; 222329011Skevans assert (dp); 223329011Skevans 224329011Skevans dictAppendWord(dp, "efi-setenv", ficlEfiSetenv, FW_DEFAULT); 225329011Skevans dictAppendWord(dp, "efi-getenv", ficlEfiGetenv, FW_DEFAULT); 226329011Skevans dictAppendWord(dp, "efi-unsetenv", ficlEfiUnsetenv, FW_DEFAULT); 227329011Skevans 228329011Skevans /* Would like to export the EFI version, but this will do for now */ 229329011Skevans ficlSetEnv(pSys, "efi-boot", 1); 230329011Skevans 231329011Skevans return; 232329011Skevans} 233329011Skevans 234329011SkevansFICL_COMPILE_SET(ficlEfiCompilePlatform); 235