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 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 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 * 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 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 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 * 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 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 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 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 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 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