1203181Smarcel/*- 2203181Smarcel * Copyright (c) 2010 Marcel Moolenaar 3203181Smarcel * All rights reserved. 4203181Smarcel * 5203181Smarcel * Redistribution and use in source and binary forms, with or without 6203181Smarcel * modification, are permitted provided that the following conditions 7203181Smarcel * are met: 8203181Smarcel * 1. Redistributions of source code must retain the above copyright 9203181Smarcel * notice, this list of conditions and the following disclaimer. 10203181Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11203181Smarcel * notice, this list of conditions and the following disclaimer in the 12203181Smarcel * documentation and/or other materials provided with the distribution. 13203181Smarcel * 14203181Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15203181Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16203181Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17203181Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18203181Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19203181Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20203181Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21203181Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22203181Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23203181Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24203181Smarcel * SUCH DAMAGE. 25203181Smarcel */ 26203181Smarcel 27203181Smarcel#include <sys/cdefs.h> 28203181Smarcel__FBSDID("$FreeBSD$"); 29203181Smarcel 30203181Smarcel#include <sys/ioctl.h> 31203181Smarcel#include <sys/types.h> 32203181Smarcel#include <fcntl.h> 33203181Smarcel#include <stddef.h> 34203181Smarcel#include <stdlib.h> 35203181Smarcel#include <string.h> 36203181Smarcel#include <unistd.h> 37203181Smarcel 38203181Smarcel#include "libefi_int.h" 39203181Smarcel 40203181Smarcelstatic int __iofd = -1; 41203181Smarcel 42203181Smarcelstatic void 43203181Smarceliodev_fd_close(void) 44203181Smarcel{ 45203181Smarcel 46203181Smarcel close(__iofd); 47203181Smarcel} 48203181Smarcel 49203181Smarcelstatic int 50203181Smarceliodev_fd(int *fd) 51203181Smarcel{ 52203181Smarcel 53203181Smarcel *fd = __iofd; 54203181Smarcel if (__iofd != -1) 55203181Smarcel return (0); 56203181Smarcel 57203181Smarcel __iofd = open("/dev/io", O_RDWR); 58203181Smarcel if (__iofd == -1) 59203181Smarcel return (errno); 60203181Smarcel 61203181Smarcel atexit(iodev_fd_close); 62203181Smarcel *fd = __iofd; 63203181Smarcel return (0); 64203181Smarcel} 65203181Smarcel 66203181Smarcelint 67203181Smarcellibefi_ucs2_to_utf8(u_short *nm, size_t *szp, char *name) 68203181Smarcel{ 69203181Smarcel size_t len, sz; 70203181Smarcel u_short c; 71203181Smarcel 72203181Smarcel len = 0; 73203181Smarcel sz = *szp; 74203181Smarcel while (*nm) { 75203181Smarcel c = *nm++; 76203181Smarcel if (c > 0x7ff) { 77203181Smarcel if (len++ < sz) 78203181Smarcel *name++ = 0xE0 | (c >> 12); 79203181Smarcel if (len++ < sz) 80203181Smarcel *name++ = 0x80 | ((c >> 6) & 0x3f); 81203181Smarcel if (len++ < sz) 82203181Smarcel *name++ = 0x80 | (c & 0x3f); 83203181Smarcel } else if (c > 0x7f) { 84203181Smarcel if (len++ < sz) 85203181Smarcel *name++ = 0xC0 | ((c >> 6) & 0x1f); 86203181Smarcel if (len++ < sz) 87203181Smarcel *name++ = 0x80 | (c & 0x3f); 88203181Smarcel } else { 89203181Smarcel if (len++ < sz) 90203181Smarcel *name++ = (c & 0x7f); 91203181Smarcel } 92203181Smarcel } 93203181Smarcel if (len++ < sz) 94203181Smarcel *name++ = 0; 95203181Smarcel 96203181Smarcel *szp = len; 97203181Smarcel return ((len <= sz) ? 0 : EOVERFLOW); 98203181Smarcel} 99203181Smarcel 100203181Smarcelint 101203181Smarcellibefi_utf8_to_ucs2(char *name, size_t *szp, u_short **nmp) 102203181Smarcel{ 103203181Smarcel u_short *nm; 104203181Smarcel size_t sz; 105203181Smarcel uint32_t ucs4; 106203181Smarcel int c, bytes; 107203181Smarcel 108203181Smarcel *szp = sz = (*szp == 0) ? strlen(name) * 2 + 2 : *szp; 109203181Smarcel *nmp = nm = malloc(sz); 110203181Smarcel 111203181Smarcel ucs4 = 0; 112203181Smarcel bytes = 0; 113203181Smarcel while (sz > 1 && *name != '\0') { 114203181Smarcel c = *name++; 115203181Smarcel /* 116203181Smarcel * Conditionalize on the two major character types: 117203181Smarcel * initial and followup characters. 118203181Smarcel */ 119203181Smarcel if ((c & 0xc0) != 0x80) { 120203181Smarcel /* Initial characters. */ 121203181Smarcel if (bytes != 0) { 122203181Smarcel free(nm); 123203181Smarcel return (EILSEQ); 124203181Smarcel } 125203181Smarcel if ((c & 0xf8) == 0xf0) { 126203181Smarcel ucs4 = c & 0x07; 127203181Smarcel bytes = 3; 128203181Smarcel } else if ((c & 0xf0) == 0xe0) { 129203181Smarcel ucs4 = c & 0x0f; 130203181Smarcel bytes = 2; 131203181Smarcel } else if ((c & 0xe0) == 0xc0) { 132203181Smarcel ucs4 = c & 0x1f; 133203181Smarcel bytes = 1; 134203181Smarcel } else { 135203181Smarcel ucs4 = c & 0x7f; 136203181Smarcel bytes = 0; 137203181Smarcel } 138203181Smarcel } else { 139203181Smarcel /* Followup characters. */ 140203181Smarcel if (bytes > 0) { 141203181Smarcel ucs4 = (ucs4 << 6) + (c & 0x3f); 142203181Smarcel bytes--; 143203181Smarcel } else if (bytes == 0) { 144203181Smarcel free(nm); 145203181Smarcel return (EILSEQ); 146203181Smarcel } 147203181Smarcel } 148203181Smarcel if (bytes == 0) { 149203181Smarcel if (ucs4 > 0xffff) { 150203181Smarcel free(nm); 151203181Smarcel return (EILSEQ); 152203181Smarcel } 153203181Smarcel *nm++ = (u_short)ucs4; 154203181Smarcel sz -= 2; 155203181Smarcel } 156203181Smarcel } 157203181Smarcel if (sz < 2) { 158203181Smarcel free(nm); 159203181Smarcel return (EDOOFUS); 160203181Smarcel } 161203181Smarcel *nm = 0; 162203181Smarcel return (0); 163203181Smarcel} 164203181Smarcel 165203181Smarcelint 166203181Smarcellibefi_efivar(struct iodev_efivar_req *req) 167203181Smarcel{ 168203181Smarcel int error, fd; 169203181Smarcel 170203181Smarcel error = iodev_fd(&fd); 171203181Smarcel if (!error) 172203181Smarcel error = (ioctl(fd, IODEV_EFIVAR, req) == -1) ? errno : 0; 173203181Smarcel if (!error) 174203181Smarcel error = req->result; 175203181Smarcel return (error); 176203181Smarcel} 177