1105401Stmm/*- 2105401Stmm * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 3105401Stmm * All rights reserved. 4105401Stmm * 5105401Stmm * Redistribution and use in source and binary forms, with or without 6105401Stmm * modification, are permitted provided that the following conditions 7105401Stmm * are met: 8105401Stmm * 1. Redistributions of source code must retain the above copyright 9105401Stmm * notice, this list of conditions and the following disclaimer. 10105401Stmm * 2. Redistributions in binary form must reproduce the above copyright 11105401Stmm * notice, this list of conditions and the following disclaimer in the 12105401Stmm * documentation and/or other materials provided with the distribution. 13105401Stmm * 14105401Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15105401Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16105401Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17105401Stmm * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18105401Stmm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19105401Stmm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20105401Stmm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21105401Stmm * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22105401Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 23105401Stmm * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24105401Stmm */ 25105401Stmm 26105401Stmm#include <sys/cdefs.h> 27105401Stmm__FBSDID("$FreeBSD$"); 28105401Stmm 29105401Stmm#include <sys/types.h> 30105401Stmm#include <sys/ioctl.h> 31105401Stmm 32105401Stmm#include <dev/ofw/openfirmio.h> 33105401Stmm 34105401Stmm#include <err.h> 35105401Stmm#include <errno.h> 36105401Stmm#include <fcntl.h> 37105401Stmm#include <stdio.h> 38116212Stmm#include <stdlib.h> 39105401Stmm#include <string.h> 40129589Smarius#include <sysexits.h> 41105401Stmm#include <unistd.h> 42105401Stmm 43105401Stmm#include "pathnames.h" 44105401Stmm#include "ofw_util.h" 45105401Stmm 46105401Stmm#define OFW_IOCTL(fd, cmd, val) do { \ 47105401Stmm if (ioctl(fd, cmd, val) == -1) \ 48129589Smarius err(EX_IOERR, "ioctl(..., " #cmd ", ...) failed"); \ 49105401Stmm} while (0) 50105401Stmm 51105401Stmmint 52129589Smariusofw_open(int mode) 53105401Stmm{ 54105401Stmm int fd; 55105401Stmm 56129589Smarius if ((fd = open(PATH_DEV_OPENFIRM, mode)) == -1) 57129589Smarius err(EX_UNAVAILABLE, "could not open " PATH_DEV_OPENFIRM); 58105401Stmm return (fd); 59105401Stmm} 60105401Stmm 61105401Stmmvoid 62105401Stmmofw_close(int fd) 63105401Stmm{ 64105401Stmm 65105401Stmm close(fd); 66105401Stmm} 67105401Stmm 68105401Stmmphandle_t 69105401Stmmofw_root(int fd) 70105401Stmm{ 71105401Stmm 72105401Stmm return (ofw_peer(fd, 0)); 73105401Stmm} 74105401Stmm 75105401Stmmphandle_t 76129589Smariusofw_optnode(int fd) 77129589Smarius{ 78129589Smarius phandle_t rv; 79129589Smarius 80129589Smarius OFW_IOCTL(fd, OFIOCGETOPTNODE, &rv); 81129589Smarius return (rv); 82129589Smarius} 83129589Smarius 84129589Smariusphandle_t 85105401Stmmofw_peer(int fd, phandle_t node) 86105401Stmm{ 87105401Stmm phandle_t rv; 88105401Stmm 89105401Stmm rv = node; 90105401Stmm OFW_IOCTL(fd, OFIOCGETNEXT, &rv); 91105401Stmm return (rv); 92105401Stmm} 93105401Stmm 94105401Stmmphandle_t 95105401Stmmofw_child(int fd, phandle_t node) 96105401Stmm{ 97105401Stmm phandle_t rv; 98105401Stmm 99105401Stmm rv = node; 100105401Stmm OFW_IOCTL(fd, OFIOCGETCHILD, &rv); 101105401Stmm return (rv); 102105401Stmm} 103105401Stmm 104105401Stmmphandle_t 105129589Smariusofw_finddevice(int fd, const char *name) 106105401Stmm{ 107105401Stmm struct ofiocdesc d; 108105401Stmm 109105401Stmm d.of_nodeid = 0; 110105401Stmm d.of_namelen = strlen(name); 111105401Stmm d.of_name = name; 112105401Stmm d.of_buflen = 0; 113105401Stmm d.of_buf = NULL; 114105401Stmm if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) { 115105401Stmm if (errno == ENOENT) 116129589Smarius err(EX_UNAVAILABLE, "Node '%s' not found", name); 117105401Stmm else 118129589Smarius err(EX_IOERR, 119129589Smarius "ioctl(..., OFIOCFINDDEVICE, ...) failed"); 120105401Stmm } 121105401Stmm return (d.of_nodeid); 122105401Stmm} 123105401Stmm 124105401Stmmint 125105401Stmmofw_firstprop(int fd, phandle_t node, char *buf, int buflen) 126105401Stmm{ 127105401Stmm 128105401Stmm return (ofw_nextprop(fd, node, NULL, buf, buflen)); 129105401Stmm} 130105401Stmm 131105401Stmmint 132129589Smariusofw_nextprop(int fd, phandle_t node, const char *prev, char *buf, int buflen) 133105401Stmm{ 134105401Stmm struct ofiocdesc d; 135105401Stmm 136105401Stmm d.of_nodeid = node; 137105401Stmm d.of_namelen = prev != NULL ? strlen(prev) : 0; 138105401Stmm d.of_name = prev; 139105401Stmm d.of_buflen = buflen; 140105401Stmm d.of_buf = buf; 141105401Stmm if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) { 142105401Stmm if (errno == ENOENT) 143105401Stmm return (0); 144105401Stmm else 145129589Smarius err(EX_IOERR, "ioctl(..., OFIOCNEXTPROP, ...) failed"); 146105401Stmm } 147105401Stmm return (d.of_buflen); 148105401Stmm} 149105401Stmm 150116212Stmmstatic void * 151116212Stmmofw_malloc(int size) 152116212Stmm{ 153116212Stmm void *p; 154116212Stmm 155116212Stmm if ((p = malloc(size)) == NULL) 156129589Smarius err(EX_OSERR, "malloc() failed"); 157116212Stmm return (p); 158116212Stmm} 159116212Stmm 160105401Stmmint 161105401Stmmofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen) 162105401Stmm{ 163105401Stmm struct ofiocdesc d; 164105401Stmm 165105401Stmm d.of_nodeid = node; 166105401Stmm d.of_namelen = strlen(name); 167105401Stmm d.of_name = name; 168105401Stmm d.of_buflen = buflen; 169105401Stmm d.of_buf = buf; 170105401Stmm OFW_IOCTL(fd, OFIOCGET, &d); 171105401Stmm return (d.of_buflen); 172105401Stmm} 173105401Stmm 174116212Stmmint 175129589Smariusofw_setprop(int fd, phandle_t node, const char *name, const void *buf, 176129589Smarius int buflen) 177129589Smarius{ 178129589Smarius struct ofiocdesc d; 179129589Smarius 180129589Smarius d.of_nodeid = node; 181129589Smarius d.of_namelen = strlen(name); 182129589Smarius d.of_name = name; 183129589Smarius d.of_buflen = buflen; 184129589Smarius d.of_buf = ofw_malloc(buflen); 185129589Smarius memcpy(d.of_buf, buf, buflen); 186129589Smarius OFW_IOCTL(fd, OFIOCSET, &d); 187129589Smarius free(d.of_buf); 188129589Smarius return (d.of_buflen); 189129589Smarius} 190129589Smarius 191129589Smariusint 192116212Stmmofw_getproplen(int fd, phandle_t node, const char *name) 193116212Stmm{ 194116212Stmm struct ofiocdesc d; 195116212Stmm 196116212Stmm d.of_nodeid = node; 197116212Stmm d.of_namelen = strlen(name); 198116212Stmm d.of_name = name; 199116212Stmm OFW_IOCTL(fd, OFIOCGETPROPLEN, &d); 200116212Stmm return (d.of_buflen); 201116212Stmm} 202116212Stmm 203116212Stmmint 204116212Stmmofw_getprop_alloc(int fd, phandle_t node, const char *name, void **buf, 205116212Stmm int *buflen, int reserve) 206116212Stmm{ 207116212Stmm struct ofiocdesc d; 208116212Stmm int len, rv; 209116212Stmm 210116212Stmm do { 211116212Stmm len = ofw_getproplen(fd, node, name); 212116212Stmm if (len < 0) 213116212Stmm return (len); 214116212Stmm if (*buflen < len + reserve) { 215116212Stmm if (*buf != NULL) 216116212Stmm free(*buf); 217129589Smarius *buflen = len + reserve + OFIOCMAXVALUE; 218116212Stmm *buf = ofw_malloc(*buflen); 219116212Stmm } 220116212Stmm d.of_nodeid = node; 221116212Stmm d.of_namelen = strlen(name); 222116212Stmm d.of_name = name; 223116212Stmm d.of_buflen = *buflen - reserve; 224116212Stmm d.of_buf = *buf; 225116212Stmm rv = ioctl(fd, OFIOCGET, &d); 226116212Stmm } while (rv == -1 && errno == ENOMEM); 227116212Stmm if (rv == -1) 228129589Smarius err(EX_IOERR, "ioctl(..., OFIOCGET, ...) failed"); 229116212Stmm return (d.of_buflen); 230116212Stmm} 231