xref: /freebsd/stand/uboot/glue.c (revision 7c43148a)
19dc70af8SWarner Losh /*-
29dc70af8SWarner Losh  * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
39dc70af8SWarner Losh  * All rights reserved.
49dc70af8SWarner Losh  *
59dc70af8SWarner Losh  * Redistribution and use in source and binary forms, with or without
69dc70af8SWarner Losh  * modification, are permitted provided that the following conditions
79dc70af8SWarner Losh  * are met:
89dc70af8SWarner Losh  * 1. Redistributions of source code must retain the above copyright
99dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer.
109dc70af8SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
119dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
129dc70af8SWarner Losh  *    documentation and/or other materials provided with the distribution.
139dc70af8SWarner Losh  *
149dc70af8SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
159dc70af8SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
169dc70af8SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179dc70af8SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
189dc70af8SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199dc70af8SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
209dc70af8SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
219dc70af8SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
229dc70af8SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
239dc70af8SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
249dc70af8SWarner Losh  * SUCH DAMAGE.
259dc70af8SWarner Losh  */
269dc70af8SWarner Losh 
279dc70af8SWarner Losh #include <sys/types.h>
289dc70af8SWarner Losh 
299dc70af8SWarner Losh #include <zlib.h>
309dc70af8SWarner Losh #include <stand.h>
319dc70af8SWarner Losh #include "api_public.h"
329dc70af8SWarner Losh #include "glue.h"
339dc70af8SWarner Losh 
349dc70af8SWarner Losh #ifdef DEBUG
359dc70af8SWarner Losh #define	debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
369dc70af8SWarner Losh #else
379dc70af8SWarner Losh #define	debugf(fmt, args...)
389dc70af8SWarner Losh #endif
399dc70af8SWarner Losh 
409dc70af8SWarner Losh /* Some random address used by U-Boot. */
419dc70af8SWarner Losh extern long uboot_address;
429dc70af8SWarner Losh 
439dc70af8SWarner Losh static int
valid_sig(struct api_signature * sig)449dc70af8SWarner Losh valid_sig(struct api_signature *sig)
459dc70af8SWarner Losh {
469dc70af8SWarner Losh 	uint32_t checksum;
479dc70af8SWarner Losh 	struct api_signature s;
489dc70af8SWarner Losh 
499dc70af8SWarner Losh 	if (sig == NULL)
509dc70af8SWarner Losh 		return (0);
519dc70af8SWarner Losh 	/*
529dc70af8SWarner Losh 	 * Clear the checksum field (in the local copy) so as to calculate the
539dc70af8SWarner Losh 	 * CRC with the same initial contents as at the time when the sig was
549dc70af8SWarner Losh 	 * produced
559dc70af8SWarner Losh 	 */
569dc70af8SWarner Losh 	s = *sig;
579dc70af8SWarner Losh 	s.checksum = crc32(0, Z_NULL, 0);
589dc70af8SWarner Losh 
599dc70af8SWarner Losh 	checksum = crc32(s.checksum, (void *)&s, sizeof(struct api_signature));
609dc70af8SWarner Losh 
619dc70af8SWarner Losh 	if (checksum != sig->checksum)
629dc70af8SWarner Losh 		return (0);
639dc70af8SWarner Losh 
649dc70af8SWarner Losh 	return (1);
659dc70af8SWarner Losh }
669dc70af8SWarner Losh 
679dc70af8SWarner Losh /*
689dc70af8SWarner Losh  * Checks to see if API signature's address was given to us as a command line
699dc70af8SWarner Losh  * argument by U-Boot.
709dc70af8SWarner Losh  *
719dc70af8SWarner Losh  * returns 1/0 depending on found/not found result
729dc70af8SWarner Losh  */
739dc70af8SWarner Losh int
api_parse_cmdline_sig(int argc,char ** argv,struct api_signature ** sig)749dc70af8SWarner Losh api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig)
759dc70af8SWarner Losh {
769dc70af8SWarner Losh 	unsigned long api_address;
779dc70af8SWarner Losh 	int c;
789dc70af8SWarner Losh 
799dc70af8SWarner Losh 	api_address = 0;
809dc70af8SWarner Losh 	opterr = 0;
819dc70af8SWarner Losh 	optreset = 1;
829dc70af8SWarner Losh 	optind = 1;
839dc70af8SWarner Losh 
849dc70af8SWarner Losh 	while ((c = getopt (argc, argv, "a:")) != -1)
859dc70af8SWarner Losh 		switch (c) {
869dc70af8SWarner Losh 		case 'a':
879dc70af8SWarner Losh 			api_address = strtoul(optarg, NULL, 16);
889dc70af8SWarner Losh 			break;
899dc70af8SWarner Losh 		default:
909dc70af8SWarner Losh 			break;
919dc70af8SWarner Losh 		}
929dc70af8SWarner Losh 
939dc70af8SWarner Losh 	if (api_address != 0) {
949dc70af8SWarner Losh 		*sig = (struct api_signature *)api_address;
959dc70af8SWarner Losh 		if (valid_sig(*sig))
969dc70af8SWarner Losh 			return (1);
979dc70af8SWarner Losh 	}
989dc70af8SWarner Losh 
999dc70af8SWarner Losh 	return (0);
1009dc70af8SWarner Losh }
1019dc70af8SWarner Losh 
1029dc70af8SWarner Losh /*
1039dc70af8SWarner Losh  * Searches for the U-Boot API signature
1049dc70af8SWarner Losh  *
1059dc70af8SWarner Losh  * returns 1/0 depending on found/not found result
1069dc70af8SWarner Losh  */
1079dc70af8SWarner Losh int
api_search_sig(struct api_signature ** sig)1089dc70af8SWarner Losh api_search_sig(struct api_signature **sig)
1099dc70af8SWarner Losh {
1109dc70af8SWarner Losh 	unsigned char *sp, *spend;
1119dc70af8SWarner Losh 
1129dc70af8SWarner Losh 	if (sig == NULL)
1139dc70af8SWarner Losh 		return (0);
1149dc70af8SWarner Losh 
1159dc70af8SWarner Losh 	if (uboot_address == 0)
1169dc70af8SWarner Losh 		uboot_address = 255 * 1024 * 1024;
1179dc70af8SWarner Losh 
1189dc70af8SWarner Losh 	sp = (void *)(uboot_address & API_SIG_SEARCH_MASK);
1199dc70af8SWarner Losh 	spend = sp + API_SIG_SEARCH_LEN - API_SIG_MAGLEN;
1209dc70af8SWarner Losh 
1219dc70af8SWarner Losh 	while (sp < spend) {
1229dc70af8SWarner Losh 		if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
1239dc70af8SWarner Losh 			*sig = (struct api_signature *)sp;
1249dc70af8SWarner Losh 			if (valid_sig(*sig))
1259dc70af8SWarner Losh 				return (1);
1269dc70af8SWarner Losh 		}
1279dc70af8SWarner Losh 		sp += API_SIG_MAGLEN;
1289dc70af8SWarner Losh 	}
1299dc70af8SWarner Losh 
1309dc70af8SWarner Losh 	*sig = NULL;
1319dc70af8SWarner Losh 	return (0);
1329dc70af8SWarner Losh }
1339dc70af8SWarner Losh 
1349dc70af8SWarner Losh /****************************************
1359dc70af8SWarner Losh  *
1369dc70af8SWarner Losh  * console
1379dc70af8SWarner Losh  *
1389dc70af8SWarner Losh  ****************************************/
1399dc70af8SWarner Losh 
1409dc70af8SWarner Losh int
ub_getc(void)1419dc70af8SWarner Losh ub_getc(void)
1429dc70af8SWarner Losh {
1439dc70af8SWarner Losh 	int c;
1449dc70af8SWarner Losh 
1459dc70af8SWarner Losh 	if (!syscall(API_GETC, NULL, &c))
1469dc70af8SWarner Losh 		return (-1);
1479dc70af8SWarner Losh 
1489dc70af8SWarner Losh 	return (c);
1499dc70af8SWarner Losh }
1509dc70af8SWarner Losh 
1519dc70af8SWarner Losh int
ub_tstc(void)1529dc70af8SWarner Losh ub_tstc(void)
1539dc70af8SWarner Losh {
1549dc70af8SWarner Losh 	int t;
1559dc70af8SWarner Losh 
1569dc70af8SWarner Losh 	if (!syscall(API_TSTC, NULL, &t))
1579dc70af8SWarner Losh 		return (-1);
1589dc70af8SWarner Losh 
1599dc70af8SWarner Losh 	return (t);
1609dc70af8SWarner Losh }
1619dc70af8SWarner Losh 
1629dc70af8SWarner Losh void
ub_putc(const char c)1639dc70af8SWarner Losh ub_putc(const char c)
1649dc70af8SWarner Losh {
1659dc70af8SWarner Losh 
1669dc70af8SWarner Losh 	syscall(API_PUTC, NULL, &c);
1679dc70af8SWarner Losh }
1689dc70af8SWarner Losh 
1699dc70af8SWarner Losh void
ub_puts(const char * s)1709dc70af8SWarner Losh ub_puts(const char *s)
1719dc70af8SWarner Losh {
1729dc70af8SWarner Losh 
1739dc70af8SWarner Losh 	syscall(API_PUTS, NULL, s);
1749dc70af8SWarner Losh }
1759dc70af8SWarner Losh 
1769dc70af8SWarner Losh /****************************************
1779dc70af8SWarner Losh  *
1789dc70af8SWarner Losh  * system
1799dc70af8SWarner Losh  *
1809dc70af8SWarner Losh  ****************************************/
1819dc70af8SWarner Losh 
1829dc70af8SWarner Losh void
ub_reset(void)1839dc70af8SWarner Losh ub_reset(void)
1849dc70af8SWarner Losh {
1859dc70af8SWarner Losh 
1869dc70af8SWarner Losh 	syscall(API_RESET, NULL);
1879dc70af8SWarner Losh 	while (1);	/* fallback if API_RESET failed */
1889dc70af8SWarner Losh 	__unreachable();
1899dc70af8SWarner Losh }
1909dc70af8SWarner Losh 
1919dc70af8SWarner Losh static struct mem_region mr[UB_MAX_MR];
1929dc70af8SWarner Losh static struct sys_info si;
1939dc70af8SWarner Losh 
1949dc70af8SWarner Losh struct sys_info *
ub_get_sys_info(void)1959dc70af8SWarner Losh ub_get_sys_info(void)
1969dc70af8SWarner Losh {
1979dc70af8SWarner Losh 	int err = 0;
1989dc70af8SWarner Losh 
1999dc70af8SWarner Losh 	memset(&si, 0, sizeof(struct sys_info));
2009dc70af8SWarner Losh 	si.mr = mr;
2019dc70af8SWarner Losh 	si.mr_no = UB_MAX_MR;
2029dc70af8SWarner Losh 	memset(&mr, 0, sizeof(mr));
2039dc70af8SWarner Losh 
2049dc70af8SWarner Losh 	if (!syscall(API_GET_SYS_INFO, &err, &si))
2059dc70af8SWarner Losh 		return (NULL);
2069dc70af8SWarner Losh 
2079dc70af8SWarner Losh 	return ((err) ? NULL : &si);
2089dc70af8SWarner Losh }
2099dc70af8SWarner Losh 
2109dc70af8SWarner Losh /****************************************
2119dc70af8SWarner Losh  *
2129dc70af8SWarner Losh  * timing
2139dc70af8SWarner Losh  *
2149dc70af8SWarner Losh  ****************************************/
2159dc70af8SWarner Losh 
2169dc70af8SWarner Losh void
ub_udelay(unsigned long usec)2179dc70af8SWarner Losh ub_udelay(unsigned long usec)
2189dc70af8SWarner Losh {
2199dc70af8SWarner Losh 
2209dc70af8SWarner Losh 	syscall(API_UDELAY, NULL, &usec);
2219dc70af8SWarner Losh }
2229dc70af8SWarner Losh 
2239dc70af8SWarner Losh unsigned long
ub_get_timer(unsigned long base)2249dc70af8SWarner Losh ub_get_timer(unsigned long base)
2259dc70af8SWarner Losh {
2269dc70af8SWarner Losh 	unsigned long cur;
2279dc70af8SWarner Losh 
2289dc70af8SWarner Losh 	if (!syscall(API_GET_TIMER, NULL, &cur, &base))
2299dc70af8SWarner Losh 		return (0);
2309dc70af8SWarner Losh 
2319dc70af8SWarner Losh 	return (cur);
2329dc70af8SWarner Losh }
2339dc70af8SWarner Losh 
2349dc70af8SWarner Losh /****************************************************************************
2359dc70af8SWarner Losh  *
2369dc70af8SWarner Losh  * devices
2379dc70af8SWarner Losh  *
2389dc70af8SWarner Losh  * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
2399dc70af8SWarner Losh  *
2409dc70af8SWarner Losh  ***************************************************************************/
2419dc70af8SWarner Losh 
2429dc70af8SWarner Losh static struct device_info devices[UB_MAX_DEV];
2439dc70af8SWarner Losh 
2449dc70af8SWarner Losh struct device_info *
ub_dev_get(int i)2459dc70af8SWarner Losh ub_dev_get(int i)
2469dc70af8SWarner Losh {
2479dc70af8SWarner Losh 
2489dc70af8SWarner Losh 	return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
2499dc70af8SWarner Losh }
2509dc70af8SWarner Losh 
2519dc70af8SWarner Losh /*
2529dc70af8SWarner Losh  * Enumerates the devices: fills out device_info elements in the devices[]
2539dc70af8SWarner Losh  * array.
2549dc70af8SWarner Losh  *
2559dc70af8SWarner Losh  * returns:		number of devices found
2569dc70af8SWarner Losh  */
2579dc70af8SWarner Losh int
ub_dev_enum(void)2589dc70af8SWarner Losh ub_dev_enum(void)
2599dc70af8SWarner Losh {
2609dc70af8SWarner Losh 	struct device_info *di;
2619dc70af8SWarner Losh 	int n = 0;
2629dc70af8SWarner Losh 
2639dc70af8SWarner Losh 	memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
2649dc70af8SWarner Losh 	di = &devices[0];
2659dc70af8SWarner Losh 
2669dc70af8SWarner Losh 	if (!syscall(API_DEV_ENUM, NULL, di))
2679dc70af8SWarner Losh 		return (0);
2689dc70af8SWarner Losh 
2699dc70af8SWarner Losh 	while (di->cookie != NULL) {
2709dc70af8SWarner Losh 
2719dc70af8SWarner Losh 		if (++n >= UB_MAX_DEV)
2729dc70af8SWarner Losh 			break;
2739dc70af8SWarner Losh 
2749dc70af8SWarner Losh 		/* take another device_info */
2759dc70af8SWarner Losh 		di++;
2769dc70af8SWarner Losh 
2779dc70af8SWarner Losh 		/* pass on the previous cookie */
2789dc70af8SWarner Losh 		di->cookie = devices[n - 1].cookie;
2799dc70af8SWarner Losh 
2809dc70af8SWarner Losh 		if (!syscall(API_DEV_ENUM, NULL, di))
2819dc70af8SWarner Losh 			return (0);
2829dc70af8SWarner Losh 	}
2839dc70af8SWarner Losh 
2849dc70af8SWarner Losh 	return (n);
2859dc70af8SWarner Losh }
2869dc70af8SWarner Losh 
2879dc70af8SWarner Losh /*
2889dc70af8SWarner Losh  * handle:	0-based id of the device
2899dc70af8SWarner Losh  *
2909dc70af8SWarner Losh  * returns:	0 when OK, err otherwise
2919dc70af8SWarner Losh  */
2929dc70af8SWarner Losh int
ub_dev_open(int handle)2939dc70af8SWarner Losh ub_dev_open(int handle)
2949dc70af8SWarner Losh {
2959dc70af8SWarner Losh 	struct device_info *di;
2969dc70af8SWarner Losh 	int err = 0;
2979dc70af8SWarner Losh 
2989dc70af8SWarner Losh 	if (handle < 0 || handle >= UB_MAX_DEV)
2999dc70af8SWarner Losh 		return (API_EINVAL);
3009dc70af8SWarner Losh 
3019dc70af8SWarner Losh 	di = &devices[handle];
3029dc70af8SWarner Losh 	if (!syscall(API_DEV_OPEN, &err, di))
3039dc70af8SWarner Losh 		return (-1);
3049dc70af8SWarner Losh 
3059dc70af8SWarner Losh 	return (err);
3069dc70af8SWarner Losh }
3079dc70af8SWarner Losh 
3089dc70af8SWarner Losh int
ub_dev_close(int handle)3099dc70af8SWarner Losh ub_dev_close(int handle)
3109dc70af8SWarner Losh {
3119dc70af8SWarner Losh 	struct device_info *di;
3129dc70af8SWarner Losh 
3139dc70af8SWarner Losh 	if (handle < 0 || handle >= UB_MAX_DEV)
3149dc70af8SWarner Losh 		return (API_EINVAL);
3159dc70af8SWarner Losh 
3169dc70af8SWarner Losh 	di = &devices[handle];
3179dc70af8SWarner Losh 	if (!syscall(API_DEV_CLOSE, NULL, di))
3189dc70af8SWarner Losh 		return (-1);
3199dc70af8SWarner Losh 
3209dc70af8SWarner Losh 	return (0);
3219dc70af8SWarner Losh }
3229dc70af8SWarner Losh 
3239dc70af8SWarner Losh /*
3249dc70af8SWarner Losh  * Validates device for read/write, it has to:
3259dc70af8SWarner Losh  *
3269dc70af8SWarner Losh  * - have sane handle
3279dc70af8SWarner Losh  * - be opened
3289dc70af8SWarner Losh  *
3299dc70af8SWarner Losh  * returns:	0/1 accordingly
3309dc70af8SWarner Losh  */
3319dc70af8SWarner Losh static int
dev_valid(int handle)3329dc70af8SWarner Losh dev_valid(int handle)
3339dc70af8SWarner Losh {
3349dc70af8SWarner Losh 
3359dc70af8SWarner Losh 	if (handle < 0 || handle >= UB_MAX_DEV)
3369dc70af8SWarner Losh 		return (0);
3379dc70af8SWarner Losh 
3389dc70af8SWarner Losh 	if (devices[handle].state != DEV_STA_OPEN)
3399dc70af8SWarner Losh 		return (0);
3409dc70af8SWarner Losh 
3419dc70af8SWarner Losh 	return (1);
3429dc70af8SWarner Losh }
3439dc70af8SWarner Losh 
3449dc70af8SWarner Losh static int
dev_stor_valid(int handle)3459dc70af8SWarner Losh dev_stor_valid(int handle)
3469dc70af8SWarner Losh {
3479dc70af8SWarner Losh 
3489dc70af8SWarner Losh 	if (!dev_valid(handle))
3499dc70af8SWarner Losh 		return (0);
3509dc70af8SWarner Losh 
3519dc70af8SWarner Losh 	if (!(devices[handle].type & DEV_TYP_STOR))
3529dc70af8SWarner Losh 		return (0);
3539dc70af8SWarner Losh 
3549dc70af8SWarner Losh 	return (1);
3559dc70af8SWarner Losh }
3569dc70af8SWarner Losh 
3579dc70af8SWarner Losh int
ub_dev_read(int handle,void * buf,lbasize_t len,lbastart_t start,lbasize_t * rlen)3589dc70af8SWarner Losh ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
3599dc70af8SWarner Losh     lbasize_t *rlen)
3609dc70af8SWarner Losh {
3619dc70af8SWarner Losh 	struct device_info *di;
3629dc70af8SWarner Losh 	lbasize_t act_len;
3639dc70af8SWarner Losh 	int err = 0;
3649dc70af8SWarner Losh 
3659dc70af8SWarner Losh 	if (!dev_stor_valid(handle))
3669dc70af8SWarner Losh 		return (API_ENODEV);
3679dc70af8SWarner Losh 
3689dc70af8SWarner Losh 	di = &devices[handle];
3699dc70af8SWarner Losh 	if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
3709dc70af8SWarner Losh 		return (API_ESYSC);
3719dc70af8SWarner Losh 
3729dc70af8SWarner Losh 	if (!err && rlen)
3739dc70af8SWarner Losh 		*rlen = act_len;
3749dc70af8SWarner Losh 
3759dc70af8SWarner Losh 	return (err);
3769dc70af8SWarner Losh }
3779dc70af8SWarner Losh 
3789dc70af8SWarner Losh static int
dev_net_valid(int handle)3799dc70af8SWarner Losh dev_net_valid(int handle)
3809dc70af8SWarner Losh {
3819dc70af8SWarner Losh 
3829dc70af8SWarner Losh 	if (!dev_valid(handle))
3839dc70af8SWarner Losh 		return (0);
3849dc70af8SWarner Losh 
3859dc70af8SWarner Losh 	if (devices[handle].type != DEV_TYP_NET)
3869dc70af8SWarner Losh 		return (0);
3879dc70af8SWarner Losh 
3889dc70af8SWarner Losh 	return (1);
3899dc70af8SWarner Losh }
3909dc70af8SWarner Losh 
3919dc70af8SWarner Losh int
ub_dev_recv(int handle,void * buf,int len,int * rlen)3929dc70af8SWarner Losh ub_dev_recv(int handle, void *buf, int len, int *rlen)
3939dc70af8SWarner Losh {
3949dc70af8SWarner Losh 	struct device_info *di;
3959dc70af8SWarner Losh 	int err = 0, act_len;
3969dc70af8SWarner Losh 
3979dc70af8SWarner Losh 	if (!dev_net_valid(handle))
3989dc70af8SWarner Losh 		return (API_ENODEV);
3999dc70af8SWarner Losh 
4009dc70af8SWarner Losh 	di = &devices[handle];
4019dc70af8SWarner Losh 	if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
4029dc70af8SWarner Losh 		return (API_ESYSC);
4039dc70af8SWarner Losh 
4049dc70af8SWarner Losh 	if (!err)
4059dc70af8SWarner Losh 		*rlen = act_len;
4069dc70af8SWarner Losh 
4079dc70af8SWarner Losh 	return (err);
4089dc70af8SWarner Losh }
4099dc70af8SWarner Losh 
4109dc70af8SWarner Losh int
ub_dev_send(int handle,void * buf,int len)4119dc70af8SWarner Losh ub_dev_send(int handle, void *buf, int len)
4129dc70af8SWarner Losh {
4139dc70af8SWarner Losh 	struct device_info *di;
4149dc70af8SWarner Losh 	int err = 0;
4159dc70af8SWarner Losh 
4169dc70af8SWarner Losh 	if (!dev_net_valid(handle))
4179dc70af8SWarner Losh 		return (API_ENODEV);
4189dc70af8SWarner Losh 
4199dc70af8SWarner Losh 	di = &devices[handle];
4209dc70af8SWarner Losh 	if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
4219dc70af8SWarner Losh 		return (API_ESYSC);
4229dc70af8SWarner Losh 
4239dc70af8SWarner Losh 	return (err);
4249dc70af8SWarner Losh }
4259dc70af8SWarner Losh 
4269dc70af8SWarner Losh char *
ub_stor_type(int type)4279dc70af8SWarner Losh ub_stor_type(int type)
4289dc70af8SWarner Losh {
4299dc70af8SWarner Losh 
4309dc70af8SWarner Losh 	if (type & DT_STOR_IDE)
4319dc70af8SWarner Losh 		return ("IDE");
4329dc70af8SWarner Losh 
4339dc70af8SWarner Losh 	if (type & DT_STOR_SCSI)
4349dc70af8SWarner Losh 		return ("SCSI");
4359dc70af8SWarner Losh 
4369dc70af8SWarner Losh 	if (type & DT_STOR_USB)
4379dc70af8SWarner Losh 		return ("USB");
4389dc70af8SWarner Losh 
4399dc70af8SWarner Losh 	if (type & DT_STOR_MMC)
4409dc70af8SWarner Losh 		return ("MMC");
4419dc70af8SWarner Losh 
4429dc70af8SWarner Losh 	if (type & DT_STOR_SATA)
4439dc70af8SWarner Losh 		return ("SATA");
4449dc70af8SWarner Losh 
4459dc70af8SWarner Losh 	return ("Unknown");
4469dc70af8SWarner Losh }
4479dc70af8SWarner Losh 
4489dc70af8SWarner Losh char *
ub_mem_type(int flags)4499dc70af8SWarner Losh ub_mem_type(int flags)
4509dc70af8SWarner Losh {
4519dc70af8SWarner Losh 
4529dc70af8SWarner Losh 	switch (flags & 0x000F) {
4539dc70af8SWarner Losh 	case MR_ATTR_FLASH:
4549dc70af8SWarner Losh 		return ("FLASH");
4559dc70af8SWarner Losh 	case MR_ATTR_DRAM:
4569dc70af8SWarner Losh 		return ("DRAM");
4579dc70af8SWarner Losh 	case MR_ATTR_SRAM:
4589dc70af8SWarner Losh 		return ("SRAM");
4599dc70af8SWarner Losh 	default:
4609dc70af8SWarner Losh 		return ("Unknown");
4619dc70af8SWarner Losh 	}
4629dc70af8SWarner Losh }
4639dc70af8SWarner Losh 
4649dc70af8SWarner Losh void
ub_dump_di(int handle)4659dc70af8SWarner Losh ub_dump_di(int handle)
4669dc70af8SWarner Losh {
4679dc70af8SWarner Losh 	struct device_info *di = ub_dev_get(handle);
4689dc70af8SWarner Losh 	int i;
4699dc70af8SWarner Losh 
4709dc70af8SWarner Losh 	printf("device info (%d):\n", handle);
4719dc70af8SWarner Losh 	printf("  cookie\t= %p\n", di->cookie);
4729dc70af8SWarner Losh 	printf("  type\t\t= 0x%08x\n", di->type);
4739dc70af8SWarner Losh 
4749dc70af8SWarner Losh 	if (di->type == DEV_TYP_NET) {
4759dc70af8SWarner Losh 		printf("  hwaddr\t= ");
4769dc70af8SWarner Losh 		for (i = 0; i < 6; i++)
4779dc70af8SWarner Losh 			printf("%02x ", di->di_net.hwaddr[i]);
4789dc70af8SWarner Losh 
4799dc70af8SWarner Losh 		printf("\n");
4809dc70af8SWarner Losh 
4819dc70af8SWarner Losh 	} else if (di->type & DEV_TYP_STOR) {
4829dc70af8SWarner Losh 		printf("  type\t\t= %s\n", ub_stor_type(di->type));
4839dc70af8SWarner Losh 		printf("  blk size\t\t= %ld\n", di->di_stor.block_size);
4849dc70af8SWarner Losh 		printf("  blk count\t\t= %ld\n", di->di_stor.block_count);
4859dc70af8SWarner Losh 	}
4869dc70af8SWarner Losh }
4879dc70af8SWarner Losh 
4889dc70af8SWarner Losh void
ub_dump_si(struct sys_info * si)4899dc70af8SWarner Losh ub_dump_si(struct sys_info *si)
4909dc70af8SWarner Losh {
4919dc70af8SWarner Losh 	int i;
4929dc70af8SWarner Losh 
4939dc70af8SWarner Losh 	printf("sys info:\n");
4949dc70af8SWarner Losh 	printf("  clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000);
4959dc70af8SWarner Losh 	printf("  clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000);
4969dc70af8SWarner Losh 	printf("  bar\t\t= 0x%08lx\n", si->bar);
4979dc70af8SWarner Losh 
4989dc70af8SWarner Losh 	printf("---\n");
4999dc70af8SWarner Losh 	for (i = 0; i < si->mr_no; i++) {
5009dc70af8SWarner Losh 		if (si->mr[i].flags == 0)
5019dc70af8SWarner Losh 			break;
5029dc70af8SWarner Losh 
5039dc70af8SWarner Losh 		printf("  start\t= 0x%08lx\n", si->mr[i].start);
5049dc70af8SWarner Losh 		printf("  size\t= 0x%08lx\n", si->mr[i].size);
5059dc70af8SWarner Losh 		printf("  type\t= %s\n", ub_mem_type(si->mr[i].flags));
5069dc70af8SWarner Losh 		printf("---\n");
5079dc70af8SWarner Losh 	}
5089dc70af8SWarner Losh }
5099dc70af8SWarner Losh 
5109dc70af8SWarner Losh /****************************************
5119dc70af8SWarner Losh  *
5129dc70af8SWarner Losh  * env vars
5139dc70af8SWarner Losh  *
5149dc70af8SWarner Losh  ****************************************/
5159dc70af8SWarner Losh 
5169dc70af8SWarner Losh char *
ub_env_get(const char * name)5179dc70af8SWarner Losh ub_env_get(const char *name)
5189dc70af8SWarner Losh {
5199dc70af8SWarner Losh 	char *value;
5209dc70af8SWarner Losh 
5219dc70af8SWarner Losh 	if (!syscall(API_ENV_GET, NULL, name, &value))
5229dc70af8SWarner Losh 		return (NULL);
5239dc70af8SWarner Losh 
5249dc70af8SWarner Losh 	return (value);
5259dc70af8SWarner Losh }
5269dc70af8SWarner Losh 
5279dc70af8SWarner Losh void
ub_env_set(const char * name,char * value)5289dc70af8SWarner Losh ub_env_set(const char *name, char *value)
5299dc70af8SWarner Losh {
5309dc70af8SWarner Losh 
5319dc70af8SWarner Losh 	syscall(API_ENV_SET, NULL, name, value);
5329dc70af8SWarner Losh }
5339dc70af8SWarner Losh 
5349dc70af8SWarner Losh static char env_name[256];
5359dc70af8SWarner Losh 
5369dc70af8SWarner Losh const char *
ub_env_enum(const char * last)5379dc70af8SWarner Losh ub_env_enum(const char *last)
5389dc70af8SWarner Losh {
5399dc70af8SWarner Losh 	const char *env, *str;
5409dc70af8SWarner Losh 	int i;
5419dc70af8SWarner Losh 
5429dc70af8SWarner Losh 	/*
5439dc70af8SWarner Losh 	 * It's OK to pass only the name piece as last (and not the whole
5449dc70af8SWarner Losh 	 * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
5459dc70af8SWarner Losh 	 * internally, which handles such case
5469dc70af8SWarner Losh 	 */
5479dc70af8SWarner Losh 	env = NULL;
5489dc70af8SWarner Losh 	if (!syscall(API_ENV_ENUM, NULL, last, &env))
5499dc70af8SWarner Losh 		return (NULL);
5509dc70af8SWarner Losh 
5519dc70af8SWarner Losh 	if (env == NULL || last == env)
5529dc70af8SWarner Losh 		/* no more env. variables to enumerate */
5539dc70af8SWarner Losh 		return (NULL);
5549dc70af8SWarner Losh 
5559dc70af8SWarner Losh 	/* next enumerated env var */
5569dc70af8SWarner Losh 	memset(env_name, 0, 256);
5579dc70af8SWarner Losh 	for (i = 0, str = env; *str != '=' && *str != '\0';)
5589dc70af8SWarner Losh 		env_name[i++] = *str++;
5599dc70af8SWarner Losh 
5609dc70af8SWarner Losh 	env_name[i] = '\0';
5619dc70af8SWarner Losh 
5629dc70af8SWarner Losh 	return (env_name);
5639dc70af8SWarner Losh }
564