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$");
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	ssize_t nread;
122134441Siedowse
123134441Siedowse	if (lseek(fd, off, SEEK_SET) == -1) {
124134441Siedowse		printf("\nlseek failed\n");
125134441Siedowse		return (-1);
126134441Siedowse	}
127134441Siedowse	nread = archsw.arch_readin(fd, dest, len);
128134441Siedowse	if (nread != len) {
129134441Siedowse		printf("\nreadin failed\n");
130134441Siedowse		return (-1);
131134441Siedowse	}
132134441Siedowse	return (0);
133134441Siedowse}
134134441Siedowse
135134441Siedowse/*
136134441Siedowse * Read the specified part of a file to a malloced buffer.  The file
137134441Siedowse * pointer is advanced to the end of the read data.
138134441Siedowse */
139134441Siedowsevoid *
140134441Siedowsealloc_pread(int fd, off_t off, size_t len)
141134441Siedowse{
142134441Siedowse	void *buf;
143134441Siedowse	ssize_t nread;
144134441Siedowse
145134441Siedowse	buf = malloc(len);
146134441Siedowse	if (buf == NULL) {
147134441Siedowse		printf("\nmalloc(%d) failed\n", (int)len);
148134441Siedowse		return (NULL);
149134441Siedowse	}
150134441Siedowse	if (lseek(fd, off, SEEK_SET) == -1) {
151134441Siedowse		printf("\nlseek failed\n");
152134441Siedowse		free(buf);
153134441Siedowse		return (NULL);
154134441Siedowse	}
155134441Siedowse	nread = read(fd, buf, len);
156134441Siedowse	if (nread != len) {
157134441Siedowse		printf("\nread failed\n");
158134441Siedowse		free(buf);
159134441Siedowse		return (NULL);
160134441Siedowse	}
161134441Siedowse	return (buf);
162134441Siedowse}
163134441Siedowse
164134441Siedowse/*
16539472Smsmith * Display a region in traditional hexdump format.
16639472Smsmith */
16739472Smsmithvoid
16839472Smsmithhexdump(caddr_t region, size_t len)
16939472Smsmith{
17039472Smsmith    caddr_t	line;
17139472Smsmith    int		x, c;
17239472Smsmith    char	lbuf[80];
17339472Smsmith#define emit(fmt, args...)	{sprintf(lbuf, fmt , ## args); pager_output(lbuf);}
17439472Smsmith
17539472Smsmith    pager_open();
17639472Smsmith    for (line = region; line < (region + len); line += 16) {
17739673Sdfr	emit("%08lx  ", (long) line);
17839472Smsmith
17939472Smsmith	for (x = 0; x < 16; x++) {
18039472Smsmith	    if ((line + x) < (region + len)) {
18139472Smsmith		emit("%02x ", *(u_int8_t *)(line + x));
18239472Smsmith	    } else {
18339472Smsmith		emit("-- ");
18439472Smsmith	    }
18539472Smsmith	    if (x == 7)
18639472Smsmith		emit(" ");
18739472Smsmith	}
18839472Smsmith	emit(" |");
18939472Smsmith	for (x = 0; x < 16; x++) {
19039472Smsmith	    if ((line + x) < (region + len)) {
19139472Smsmith		c = *(u_int8_t *)(line + x);
19239472Smsmith		if ((c < ' ') || (c > '~'))	/* !isprint(c) */
19339472Smsmith		    c = '.';
19439472Smsmith		emit("%c", c);
19539472Smsmith	    } else {
19639472Smsmith		emit(" ");
19739472Smsmith	    }
19839472Smsmith	}
19939472Smsmith	emit("|\n");
20039472Smsmith    }
20139472Smsmith    pager_close();
20239472Smsmith}
20361659Sps
20461659Spsvoid
20561659Spsdev_cleanup(void)
20661659Sps{
20761659Sps    int		i;
20861659Sps
20961659Sps    /* Call cleanup routines */
21061659Sps    for (i = 0; devsw[i] != NULL; ++i)
21161659Sps	if (devsw[i]->dv_cleanup != NULL)
21261659Sps	    (devsw[i]->dv_cleanup)();
21361659Sps}
214