1 /* $NetBSD: efiio.c,v 1.4 2025/03/30 14:36:48 riastradh Exp $ */ 2 3 /* 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 14 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 #ifndef lint 28 __RCSID("$NetBSD: efiio.c,v 1.4 2025/03/30 14:36:48 riastradh Exp $"); 29 #endif /* not lint */ 30 31 #include <sys/efiio.h> 32 #include <sys/ioctl.h> 33 34 #include <assert.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <stdbool.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <util.h> 41 42 #include "defs.h" 43 #include "efiio.h" 44 #include "utils.h" 45 46 //****************************************************** 47 // Variable Attributes 48 //****************************************************** 49 #if 0 /* see sys/efiio.h */ 50 struct efi_var_ioc { 51 uint16_t * name; /* vendor's variable name */ 52 size_t namesize; /* size in bytes of the name buffer */ 53 struct uuid vendor; /* unique identifier for vendor */ 54 uint32_t attrib; /* variable attribute bitmask */ 55 void * data; /* buffer containing variable data */ 56 size_t datasize; /* size in bytes of the data buffer */ 57 }; 58 #endif 59 60 static int 61 xioctl(int fd, unsigned long request, void *buf) 62 { 63 int rv; 64 65 rv = ioctl(fd, request, buf); 66 if (rv == -1 && errno != ENOENT) 67 err(EXIT_FAILURE, "%s: ioctl", __func__); 68 return rv; 69 } 70 71 PUBLIC int 72 set_variable(int fd, struct efi_var_ioc *ev) 73 { 74 75 return ioctl(fd, EFIIOC_VAR_SET, ev); 76 } 77 78 static inline int 79 get_variable_core(int fd, struct efi_var_ioc *ev) 80 { 81 82 if (xioctl(fd, EFIIOC_VAR_GET, ev) == -1) 83 return -1; 84 85 ev->data = emalloc(ev->datasize); 86 xioctl(fd, EFIIOC_VAR_GET, ev); 87 return 0; 88 } 89 90 PUBLIC struct efi_var_ioc 91 get_variable(int fd, const char *name, struct uuid *vendor, 92 uint32_t attrib) 93 { 94 struct efi_var_ioc ev; 95 96 efi_var_init(&ev, name, vendor, attrib); 97 get_variable_core(fd, &ev); 98 99 return ev; 100 } 101 102 PUBLIC struct efi_var_ioc * 103 get_next_variable(int fd, struct efi_var_ioc *ev) 104 { 105 int rv; 106 107 rv = ioctl(fd, EFIIOC_VAR_NEXT, ev); 108 if (rv == -1 && errno != ENOENT) 109 err(EXIT_FAILURE, "%s: ioctl", __func__); 110 return ev; 111 } 112 113 PUBLIC void * 114 get_table(int fd, struct uuid *uuid, size_t *buflen) 115 { 116 struct efi_get_table_ioc egt; 117 118 memset(&egt, 0, sizeof(egt)); 119 memcpy(&egt.uuid, uuid, sizeof(egt.uuid)); 120 121 xioctl(fd, EFIIOC_GET_TABLE, &egt); 122 egt.buf = ecalloc(egt.table_len, 1); 123 egt.buf_len = egt.table_len; 124 125 xioctl(fd, EFIIOC_GET_TABLE, &egt); 126 *buflen = egt.table_len; 127 return egt.buf; 128 } 129 130 PUBLIC size_t 131 get_variable_info(int fd, bool (*choose)(struct efi_var_ioc *, void *), 132 int (*fn)(struct efi_var_ioc *ev, void *), void *arg) 133 { 134 struct efi_var_ioc ev; 135 size_t cnt; 136 int rv; 137 138 assert(fn != NULL); 139 assert(arg != NULL); 140 141 memset(&ev, 0, sizeof(ev)); 142 143 ev.name = ecalloc(EFI_VARNAME_MAXBYTES, 1); 144 cnt = 0; 145 for (;;) { 146 ev.namesize = EFI_VARNAME_MAXBYTES; 147 if (ioctl(fd, EFIIOC_VAR_NEXT, &ev) == -1) { 148 char *buf; 149 150 if (errno == ENOENT) 151 break; 152 153 /* XXX: ev is likely to be zero */ 154 buf = ucs2_to_utf8(ev.name, ev.namesize, NULL, NULL); 155 err(EXIT_FAILURE, "%s: '%s'", __func__, buf); 156 } 157 158 if (choose != NULL && !choose(&ev, arg)) 159 continue; 160 161 rv = get_variable_core(fd, &ev); 162 assert(rv == 0); 163 if (rv == -1) 164 err(EXIT_FAILURE, "get_variable_core"); 165 166 cnt++; 167 fn(&ev, arg); 168 169 free(ev.data); 170 } 171 free(ev.name); 172 return cnt; 173 } 174