xref: /illumos-gate/usr/src/boot/common/misc.c (revision f5dea17da1821c9d194d54c22dbba32decd0e68c)
1 /*-
2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 #include <string.h>
29 #include <stand.h>
30 #include <bootstrap.h>
31 #ifndef BOOT2
32 #include <machine/cpufunc.h>
33 #include "ficl.h"
34 #endif
35 
36 /*
37  * Concatenate the (argc) elements of (argv) into a single string, and return
38  * a copy of same.
39  */
40 char *
41 unargv(int argc, char *argv[])
42 {
43 	size_t	hlong;
44 	int	i;
45 	char	*cp;
46 
47 	for (i = 0, hlong = 0; i < argc; i++)
48 		hlong += strlen(argv[i]) + 2;
49 
50 	if (hlong == 0)
51 		return (NULL);
52 
53 	cp = malloc(hlong);
54 	if (cp != NULL) {
55 		cp[0] = 0;
56 		for (i = 0; i < argc; i++) {
57 			(void) strcat(cp, argv[i]);
58 			if (i < (argc - 1))
59 				(void) strcat(cp, " ");
60 		}
61 	}
62 
63 	return (cp);
64 }
65 
66 /*
67  * Get the length of a string in kernel space
68  */
69 size_t
70 strlenout(vm_offset_t src)
71 {
72 	char	c;
73 	size_t	len;
74 
75 	for (len = 0; ; len++) {
76 		(void) archsw.arch_copyout(src++, &c, 1);
77 		if (c == 0)
78 			break;
79 	}
80 	return (len);
81 }
82 
83 /*
84  * Make a duplicate copy of a string in kernel space
85  */
86 char *
87 strdupout(vm_offset_t str)
88 {
89 	char	*result, *cp;
90 
91 	result = malloc(strlenout(str) + 1);
92 	for (cp = result; ; cp++) {
93 		(void) archsw.arch_copyout(str++, cp, 1);
94 		if (*cp == 0)
95 			break;
96 	}
97 	return (result);
98 }
99 
100 /* Zero a region in kernel space. */
101 void
102 kern_bzero(vm_offset_t dest, size_t len)
103 {
104 	char buf[256];
105 	size_t chunk, resid;
106 
107 	bzero(buf, sizeof (buf));
108 	resid = len;
109 	while (resid > 0) {
110 		chunk = min(sizeof (buf), resid);
111 		(void) archsw.arch_copyin(buf, dest, chunk);
112 		resid -= chunk;
113 		dest += chunk;
114 	}
115 }
116 
117 /*
118  * Read the specified part of a file to kernel space.  Unlike regular
119  * pread, the file pointer is advanced to the end of the read data,
120  * and it just returns 0 if successful.
121  */
122 int
123 kern_pread(int fd, vm_offset_t dest, size_t len, off_t off)
124 {
125 
126 	if (lseek(fd, off, SEEK_SET) == -1) {
127 #ifdef DEBUG
128 		printf("\nlseek failed\n");
129 #endif
130 		return (-1);
131 	}
132 	if ((size_t)archsw.arch_readin(fd, dest, len) != len) {
133 #ifdef DEBUG
134 		printf("\nreadin failed\n");
135 #endif
136 		return (-1);
137 	}
138 	return (0);
139 }
140 
141 /*
142  * Read the specified part of a file to a malloced buffer.  The file
143  * pointer is advanced to the end of the read data.
144  */
145 void *
146 alloc_pread(int fd, off_t off, size_t len)
147 {
148 	void *buf;
149 
150 	buf = malloc(len);
151 	if (buf == NULL) {
152 #ifdef DEBUG
153 		printf("\nmalloc(%d) failed\n", (int)len);
154 #endif
155 		return (NULL);
156 	}
157 	if (lseek(fd, off, SEEK_SET) == -1) {
158 #ifdef DEBUG
159 		printf("\nlseek failed\n");
160 #endif
161 		free(buf);
162 		return (NULL);
163 	}
164 	if ((size_t)read(fd, buf, len) != len) {
165 #ifdef DEBUG
166 		printf("\nread failed\n");
167 #endif
168 		free(buf);
169 		return (NULL);
170 	}
171 	return (buf);
172 }
173 
174 /*
175  * Display a region in traditional hexdump format.
176  */
177 void
178 hexdump(caddr_t region, size_t len)
179 {
180 	caddr_t	line;
181 	int	x, c;
182 	char	lbuf[80];
183 #define	emit(fmt, args...)						\
184 	{								\
185 		(void) snprintf(lbuf, sizeof (lbuf), fmt, ## args);	\
186 		if (pager_output(lbuf))					\
187 			goto out;					\
188 	}
189 
190 	pager_open();
191 	for (line = region; line < (region + len); line += 16) {
192 		emit("%08lx  ", (long)line);
193 
194 		for (x = 0; x < 16; x++) {
195 			if ((line + x) < (region + len)) {
196 				emit("%02x ", *(uint8_t *)(line + x));
197 			} else {
198 				emit("-- ");
199 			}
200 			if (x == 7)
201 				emit(" ");
202 		}
203 		emit(" |");
204 		for (x = 0; x < 16; x++) {
205 			if ((line + x) < (region + len)) {
206 				c = *(uint8_t *)(line + x);
207 				if ((c < ' ') || (c > '~')) /* !isprint(c) */
208 					c = '.';
209 				emit("%c", c);
210 			} else {
211 				emit(" ");
212 			}
213 		}
214 		emit("|\n");
215 	}
216 out:
217 	pager_close();
218 }
219 
220 void
221 dev_cleanup(void)
222 {
223 	int		i;
224 
225 	/* Call cleanup routines */
226 	for (i = 0; devsw[i] != NULL; ++i)
227 		if (devsw[i]->dv_cleanup != NULL)
228 			(devsw[i]->dv_cleanup)();
229 }
230 
231 #ifndef BOOT2
232 /*
233  * outb ( port# c -- )
234  * Store a byte to I/O port number port#
235  */
236 static void
237 ficlOutb(ficlVm *pVM)
238 {
239 	uint8_t c;
240 	uint32_t port;
241 
242 	port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
243 	c = ficlStackPopInteger(ficlVmGetDataStack(pVM));
244 	outb(port, c);
245 }
246 
247 /*
248  * inb ( port# -- c )
249  * Fetch a byte from I/O port number port#
250  */
251 static void
252 ficlInb(ficlVm *pVM)
253 {
254 	uint8_t c;
255 	uint32_t port;
256 
257 	port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
258 	c = inb(port);
259 	ficlStackPushInteger(ficlVmGetDataStack(pVM), c);
260 }
261 
262 static void
263 ficlCompileCpufunc(ficlSystem *pSys)
264 {
265 	ficlDictionary *dp = ficlSystemGetDictionary(pSys);
266 
267 	FICL_SYSTEM_ASSERT(pSys, dp);
268 
269 	(void) ficlDictionarySetPrimitive(dp, "outb", ficlOutb,
270 	    FICL_WORD_DEFAULT);
271 	(void) ficlDictionarySetPrimitive(dp, "inb", ficlInb,
272 	    FICL_WORD_DEFAULT);
273 }
274 
275 FICL_COMPILE_SET(ficlCompileCpufunc);
276 #endif
277