138465Smsmith/*- 238465Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 338465Smsmith * All rights reserved. 438465Smsmith * 538465Smsmith * Redistribution and use in source and binary forms, with or without 638465Smsmith * modification, are permitted provided that the following conditions 738465Smsmith * are met: 838465Smsmith * 1. Redistributions of source code must retain the above copyright 938465Smsmith * notice, this list of conditions and the following disclaimer. 1038465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1138465Smsmith * notice, this list of conditions and the following disclaimer in the 1238465Smsmith * documentation and/or other materials provided with the distribution. 1338465Smsmith * 1438465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738465Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438465Smsmith * SUCH DAMAGE. 2538465Smsmith */ 2638465Smsmith 27119483Sobrien#include <sys/cdefs.h> 28119483Sobrien__FBSDID("$FreeBSD: stable/11/stand/common/misc.c 332154 2018-04-06 21:37:25Z kevans $"); 29119483Sobrien 3038465Smsmith#include <string.h> 3138465Smsmith#include <stand.h> 3238764Smsmith#include <bootstrap.h> 3338465Smsmith 3438465Smsmith/* 3538465Smsmith * Concatenate the (argc) elements of (argv) into a single string, and return 3638465Smsmith * a copy of same. 3738465Smsmith */ 3838465Smsmithchar * 3938465Smsmithunargv(int argc, char *argv[]) 4038465Smsmith{ 4138465Smsmith size_t hlong; 4238465Smsmith int i; 4338465Smsmith char *cp; 4438465Smsmith 45181278Scperciva for (i = 0, hlong = 0; i < argc; i++) 4639968Smsmith hlong += strlen(argv[i]) + 2; 4738465Smsmith 4838465Smsmith if(hlong == 0) 4938465Smsmith return(NULL); 5038465Smsmith 5138465Smsmith cp = malloc(hlong); 5238465Smsmith cp[0] = 0; 5339968Smsmith for (i = 0; i < argc; i++) { 5438465Smsmith strcat(cp, argv[i]); 5539968Smsmith if (i < (argc - 1)) 5639968Smsmith strcat(cp, " "); 5739968Smsmith } 5839968Smsmith 5938465Smsmith return(cp); 6038465Smsmith} 6138465Smsmith 6238764Smsmith/* 6338764Smsmith * Get the length of a string in kernel space 6438764Smsmith */ 6538764Smsmithsize_t 6638764Smsmithstrlenout(vm_offset_t src) 6738764Smsmith{ 6838764Smsmith char c; 6938764Smsmith size_t len; 7038764Smsmith 7138764Smsmith for (len = 0; ; len++) { 7238764Smsmith archsw.arch_copyout(src++, &c, 1); 7338764Smsmith if (c == 0) 7438764Smsmith break; 7538764Smsmith } 7638764Smsmith return(len); 7738764Smsmith} 7838764Smsmith 7938764Smsmith/* 8038764Smsmith * Make a duplicate copy of a string in kernel space 8138764Smsmith */ 8238764Smsmithchar * 8338764Smsmithstrdupout(vm_offset_t str) 8438764Smsmith{ 8538764Smsmith char *result, *cp; 8638764Smsmith 8738764Smsmith result = malloc(strlenout(str) + 1); 8838764Smsmith for (cp = result; ;cp++) { 8938764Smsmith archsw.arch_copyout(str++, cp, 1); 9038764Smsmith if (*cp == 0) 9138764Smsmith break; 9238764Smsmith } 9338764Smsmith return(result); 9438764Smsmith} 9539472Smsmith 96134441Siedowse/* Zero a region in kernel space. */ 97134441Siedowsevoid 98134441Siedowsekern_bzero(vm_offset_t dest, size_t len) 99134441Siedowse{ 100134441Siedowse char buf[256]; 101134441Siedowse size_t chunk, resid; 102134441Siedowse 103134441Siedowse bzero(buf, sizeof(buf)); 104134441Siedowse resid = len; 105134441Siedowse while (resid > 0) { 106134441Siedowse chunk = min(sizeof(buf), resid); 107134441Siedowse archsw.arch_copyin(buf, dest, chunk); 108134441Siedowse resid -= chunk; 109134441Siedowse dest += chunk; 110134441Siedowse } 111134441Siedowse} 112134441Siedowse 11339472Smsmith/* 114134441Siedowse * Read the specified part of a file to kernel space. Unlike regular 115134441Siedowse * pread, the file pointer is advanced to the end of the read data, 116134441Siedowse * and it just returns 0 if successful. 117134441Siedowse */ 118134441Siedowseint 119134441Siedowsekern_pread(int fd, vm_offset_t dest, size_t len, off_t off) 120134441Siedowse{ 121134441Siedowse 122134441Siedowse if (lseek(fd, off, SEEK_SET) == -1) { 123274127Smarcel#ifdef DEBUG 124134441Siedowse printf("\nlseek failed\n"); 125274127Smarcel#endif 126134441Siedowse return (-1); 127134441Siedowse } 128293724Ssmh if ((size_t)archsw.arch_readin(fd, dest, len) != len) { 129274127Smarcel#ifdef DEBUG 130134441Siedowse printf("\nreadin failed\n"); 131274127Smarcel#endif 132134441Siedowse return (-1); 133134441Siedowse } 134134441Siedowse return (0); 135134441Siedowse} 136134441Siedowse 137134441Siedowse/* 138134441Siedowse * Read the specified part of a file to a malloced buffer. The file 139134441Siedowse * pointer is advanced to the end of the read data. 140134441Siedowse */ 141329183Skevans/* coverity[ -tainted_data_return ] */ 142134441Siedowsevoid * 143134441Siedowsealloc_pread(int fd, off_t off, size_t len) 144134441Siedowse{ 145134441Siedowse void *buf; 146134441Siedowse 147134441Siedowse buf = malloc(len); 148134441Siedowse if (buf == NULL) { 149274127Smarcel#ifdef DEBUG 150134441Siedowse printf("\nmalloc(%d) failed\n", (int)len); 151274127Smarcel#endif 152134441Siedowse return (NULL); 153134441Siedowse } 154134441Siedowse if (lseek(fd, off, SEEK_SET) == -1) { 155274127Smarcel#ifdef DEBUG 156134441Siedowse printf("\nlseek failed\n"); 157274127Smarcel#endif 158134441Siedowse free(buf); 159134441Siedowse return (NULL); 160134441Siedowse } 161293724Ssmh if ((size_t)read(fd, buf, len) != len) { 162274127Smarcel#ifdef DEBUG 163134441Siedowse printf("\nread failed\n"); 164274127Smarcel#endif 165134441Siedowse free(buf); 166134441Siedowse return (NULL); 167134441Siedowse } 168134441Siedowse return (buf); 169134441Siedowse} 170134441Siedowse 171134441Siedowse/* 17239472Smsmith * Display a region in traditional hexdump format. 17339472Smsmith */ 17439472Smsmithvoid 17539472Smsmithhexdump(caddr_t region, size_t len) 17639472Smsmith{ 17739472Smsmith caddr_t line; 17839472Smsmith int x, c; 17939472Smsmith char lbuf[80]; 18039472Smsmith#define emit(fmt, args...) {sprintf(lbuf, fmt , ## args); pager_output(lbuf);} 18139472Smsmith 18239472Smsmith pager_open(); 18339472Smsmith for (line = region; line < (region + len); line += 16) { 18439673Sdfr emit("%08lx ", (long) line); 18539472Smsmith 18639472Smsmith for (x = 0; x < 16; x++) { 18739472Smsmith if ((line + x) < (region + len)) { 188332154Skevans emit("%02x ", *(uint8_t *)(line + x)); 18939472Smsmith } else { 19039472Smsmith emit("-- "); 19139472Smsmith } 19239472Smsmith if (x == 7) 19339472Smsmith emit(" "); 19439472Smsmith } 19539472Smsmith emit(" |"); 19639472Smsmith for (x = 0; x < 16; x++) { 19739472Smsmith if ((line + x) < (region + len)) { 198332154Skevans c = *(uint8_t *)(line + x); 19939472Smsmith if ((c < ' ') || (c > '~')) /* !isprint(c) */ 20039472Smsmith c = '.'; 20139472Smsmith emit("%c", c); 20239472Smsmith } else { 20339472Smsmith emit(" "); 20439472Smsmith } 20539472Smsmith } 20639472Smsmith emit("|\n"); 20739472Smsmith } 20839472Smsmith pager_close(); 20939472Smsmith} 21061659Sps 21161659Spsvoid 21261659Spsdev_cleanup(void) 21361659Sps{ 21461659Sps int i; 21561659Sps 21661659Sps /* Call cleanup routines */ 21761659Sps for (i = 0; devsw[i] != NULL; ++i) 21861659Sps if (devsw[i]->dv_cleanup != NULL) 21961659Sps (devsw[i]->dv_cleanup)(); 22061659Sps} 221