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 *
unargv(int argc,char * argv[])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 cp[0] = 0;
55 for (i = 0; i < argc; i++) {
56 strcat(cp, argv[i]);
57 if (i < (argc - 1))
58 strcat(cp, " ");
59 }
60
61 return(cp);
62 }
63
64 /*
65 * Get the length of a string in kernel space
66 */
67 size_t
strlenout(vm_offset_t src)68 strlenout(vm_offset_t src)
69 {
70 char c;
71 size_t len;
72
73 for (len = 0; ; len++) {
74 archsw.arch_copyout(src++, &c, 1);
75 if (c == 0)
76 break;
77 }
78 return(len);
79 }
80
81 /*
82 * Make a duplicate copy of a string in kernel space
83 */
84 char *
strdupout(vm_offset_t str)85 strdupout(vm_offset_t str)
86 {
87 char *result, *cp;
88
89 result = malloc(strlenout(str) + 1);
90 for (cp = result; ;cp++) {
91 archsw.arch_copyout(str++, cp, 1);
92 if (*cp == 0)
93 break;
94 }
95 return(result);
96 }
97
98 /* Zero a region in kernel space. */
99 void
kern_bzero(vm_offset_t dest,size_t len)100 kern_bzero(vm_offset_t dest, size_t len)
101 {
102 char buf[256];
103 size_t chunk, resid;
104
105 bzero(buf, sizeof(buf));
106 resid = len;
107 while (resid > 0) {
108 chunk = min(sizeof(buf), resid);
109 archsw.arch_copyin(buf, dest, chunk);
110 resid -= chunk;
111 dest += chunk;
112 }
113 }
114
115 /*
116 * Read the specified part of a file to kernel space. Unlike regular
117 * pread, the file pointer is advanced to the end of the read data,
118 * and it just returns 0 if successful.
119 */
120 int
kern_pread(int fd,vm_offset_t dest,size_t len,off_t off)121 kern_pread(int fd, vm_offset_t dest, size_t len, off_t off)
122 {
123
124 if (lseek(fd, off, SEEK_SET) == -1) {
125 #ifdef DEBUG
126 printf("\nlseek failed\n");
127 #endif
128 return (-1);
129 }
130 if ((size_t)archsw.arch_readin(fd, dest, len) != len) {
131 #ifdef DEBUG
132 printf("\nreadin failed\n");
133 #endif
134 return (-1);
135 }
136 return (0);
137 }
138
139 /*
140 * Read the specified part of a file to a malloced buffer. The file
141 * pointer is advanced to the end of the read data.
142 */
143 void *
alloc_pread(int fd,off_t off,size_t len)144 alloc_pread(int fd, off_t off, size_t len)
145 {
146 void *buf;
147
148 buf = malloc(len);
149 if (buf == NULL) {
150 #ifdef DEBUG
151 printf("\nmalloc(%d) failed\n", (int)len);
152 #endif
153 return (NULL);
154 }
155 if (lseek(fd, off, SEEK_SET) == -1) {
156 #ifdef DEBUG
157 printf("\nlseek failed\n");
158 #endif
159 free(buf);
160 return (NULL);
161 }
162 if ((size_t)read(fd, buf, len) != len) {
163 #ifdef DEBUG
164 printf("\nread failed\n");
165 #endif
166 free(buf);
167 return (NULL);
168 }
169 return (buf);
170 }
171
172 /*
173 * Display a region in traditional hexdump format.
174 */
175 void
hexdump(caddr_t region,size_t len)176 hexdump(caddr_t region, size_t len)
177 {
178 caddr_t line;
179 int x, c;
180 char lbuf[80];
181 #define emit(fmt, args...) {sprintf(lbuf, fmt , ## args); pager_output(lbuf);}
182
183 pager_open();
184 for (line = region; line < (region + len); line += 16) {
185 emit("%08lx ", (long) line);
186
187 for (x = 0; x < 16; x++) {
188 if ((line + x) < (region + len)) {
189 emit("%02x ", *(u_int8_t *)(line + x));
190 } else {
191 emit("-- ");
192 }
193 if (x == 7)
194 emit(" ");
195 }
196 emit(" |");
197 for (x = 0; x < 16; x++) {
198 if ((line + x) < (region + len)) {
199 c = *(u_int8_t *)(line + x);
200 if ((c < ' ') || (c > '~')) /* !isprint(c) */
201 c = '.';
202 emit("%c", c);
203 } else {
204 emit(" ");
205 }
206 }
207 emit("|\n");
208 }
209 pager_close();
210 }
211
212 void
dev_cleanup(void)213 dev_cleanup(void)
214 {
215 int i;
216
217 /* Call cleanup routines */
218 for (i = 0; devsw[i] != NULL; ++i)
219 if (devsw[i]->dv_cleanup != NULL)
220 (devsw[i]->dv_cleanup)();
221 }
222
223 #ifndef BOOT2
224 /*
225 * outb ( port# c -- )
226 * Store a byte to I/O port number port#
227 */
228 static void
ficlOutb(ficlVm * pVM)229 ficlOutb(ficlVm *pVM)
230 {
231 uint8_t c;
232 uint32_t port;
233
234 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
235 c = ficlStackPopInteger(ficlVmGetDataStack(pVM));
236 outb(port, c);
237 }
238
239 /*
240 * inb ( port# -- c )
241 * Fetch a byte from I/O port number port#
242 */
243 static void
ficlInb(ficlVm * pVM)244 ficlInb(ficlVm *pVM)
245 {
246 uint8_t c;
247 uint32_t port;
248
249 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
250 c = inb(port);
251 ficlStackPushInteger(ficlVmGetDataStack(pVM), c);
252 }
253
254 static void
ficlCompileCpufunc(ficlSystem * pSys)255 ficlCompileCpufunc(ficlSystem *pSys)
256 {
257 ficlDictionary *dp = ficlSystemGetDictionary(pSys);
258
259 FICL_SYSTEM_ASSERT(pSys, dp);
260
261 (void) ficlDictionarySetPrimitive(dp, "outb", ficlOutb,
262 FICL_WORD_DEFAULT);
263 (void) ficlDictionarySetPrimitive(dp, "inb", ficlInb,
264 FICL_WORD_DEFAULT);
265 }
266
267 FICL_COMPILE_SET(ficlCompileCpufunc);
268 #endif
269