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