misc.c revision 1.4
1/*	$NetBSD: misc.c,v 1.4 2009/03/18 16:00:12 cegger Exp $	*/
2
3/*-
4 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30/* __FBSDID("$FreeBSD: src/sys/boot/common/misc.c,v 1.8.4.1 2004/09/03 19:25:40 iedowse Exp $"); */
31
32#include <lib/libsa/stand.h>
33#include <bootstrap.h>
34
35/*
36 * Concatenate the (argc) elements of (argv) into a single string, and return
37 * a copy of same.
38 */
39char *
40unargv(int argc, char *argv[])
41{
42    size_t	hlong;
43    int		i;
44    char	*cp;
45
46    for (hlong = 0, i = 0, hlong = 0; i < argc; i++)
47	hlong += strlen(argv[i]) + 2;
48
49    if(hlong == 0)
50	return(NULL);
51
52    cp = alloc(hlong);
53    cp[0] = 0;
54    for (i = 0; i < argc; i++) {
55	strcat(cp, argv[i]);
56	if (i < (argc - 1))
57	  strcat(cp, " ");
58    }
59
60    return(cp);
61}
62
63/*
64 * Get the length of a string in kernel space
65 */
66size_t
67strlenout(vaddr_t src)
68{
69    char	c;
70    size_t	len;
71
72    for (len = 0; ; len++) {
73	archsw.arch_copyout(src++, &c, 1);
74	if (c == 0)
75	    break;
76    }
77    return(len);
78}
79
80/*
81 * Make a duplicate copy of a string in kernel space
82 */
83char *
84strdupout(vaddr_t str)
85{
86    char	*result, *cp;
87
88    result = alloc(strlenout(str) + 1);
89    for (cp = result; ;cp++) {
90	archsw.arch_copyout(str++, cp, 1);
91	if (*cp == 0)
92	    break;
93    }
94    return(result);
95}
96
97/* Zero a region in kernel space. */
98void
99kern_bzero(vaddr_t dest, size_t len)
100{
101	char buf[256];
102	size_t chunk, resid;
103
104	memset(buf, 0, sizeof(buf));
105	resid = len;
106	while (resid > 0) {
107		chunk = min(sizeof(buf), resid);
108		archsw.arch_copyin(buf, dest, chunk);
109		resid -= chunk;
110		dest += chunk;
111	}
112}
113
114/*
115 * Read the specified part of a file to kernel space.  Unlike regular
116 * pread, the file pointer is advanced to the end of the read data,
117 * and it just returns 0 if successful.
118 */
119int
120kern_pread(int fd, vaddr_t dest, size_t len, off_t off)
121{
122	ssize_t nread;
123
124	if (lseek(fd, off, SEEK_SET) == -1) {
125		printf("\nlseek failed\n");
126		return (-1);
127	}
128	nread = archsw.arch_readin(fd, dest, len);
129	if (nread != len) {
130		printf("\nreadin failed\n");
131		return (-1);
132	}
133	return (0);
134}
135
136/*
137 * Read the specified part of a file to a malloced buffer.  The file
138 * pointer is advanced to the end of the read data.
139 */
140void *
141alloc_pread(int fd, off_t off, size_t len)
142{
143	void *buf;
144	ssize_t nread;
145
146	buf = alloc(len);
147	if (buf == NULL) {
148		printf("\nalloc(%d) failed\n", (int)len);
149		return (NULL);
150	}
151	if (lseek(fd, off, SEEK_SET) == -1) {
152		printf("\nlseek failed\n");
153		free(buf);
154		return (NULL);
155	}
156	nread = read(fd, buf, len);
157	if (nread != len) {
158		printf("\nread failed\n");
159		free(buf);
160		return (NULL);
161	}
162	return (buf);
163}
164
165/*
166 * Display a region in traditional hexdump format.
167 */
168void
169hexdump(void *region, size_t len)
170{
171    void *	line;
172    int		x, c;
173    char	lbuf[80];
174#define emit(fmt, args...)	{sprintf(lbuf, fmt , ## args); pager_output(lbuf);}
175
176    pager_open();
177    for (line = region; line < (region + len); line += 16) {
178	emit("%08lx  ", (long) line);
179
180	for (x = 0; x < 16; x++) {
181	    if ((line + x) < (region + len)) {
182		emit("%02x ", *(u_int8_t *)(line + x));
183	    } else {
184		emit("-- ");
185	    }
186	    if (x == 7)
187		emit(" ");
188	}
189	emit(" |");
190	for (x = 0; x < 16; x++) {
191	    if ((line + x) < (region + len)) {
192		c = *(u_int8_t *)(line + x);
193		if ((c < ' ') || (c > '~'))	/* !isprint(c) */
194		    c = '.';
195		emit("%c", c);
196	    } else {
197		emit(" ");
198	    }
199	}
200	emit("|\n");
201    }
202    pager_close();
203}
204
205void
206dev_cleanup(void)
207{
208
209}
210