xref: /freebsd/stand/common/misc.c (revision afc571b1a6fb341b0e3f603d4f3a2538093e91f5)
1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3ca987d46SWarner Losh  * All rights reserved.
4ca987d46SWarner Losh  *
5ca987d46SWarner Losh  * Redistribution and use in source and binary forms, with or without
6ca987d46SWarner Losh  * modification, are permitted provided that the following conditions
7ca987d46SWarner Losh  * are met:
8ca987d46SWarner Losh  * 1. Redistributions of source code must retain the above copyright
9ca987d46SWarner Losh  *    notice, this list of conditions and the following disclaimer.
10ca987d46SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
11ca987d46SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
12ca987d46SWarner Losh  *    documentation and/or other materials provided with the distribution.
13ca987d46SWarner Losh  *
14ca987d46SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ca987d46SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ca987d46SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ca987d46SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ca987d46SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ca987d46SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ca987d46SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ca987d46SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ca987d46SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ca987d46SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ca987d46SWarner Losh  * SUCH DAMAGE.
25ca987d46SWarner Losh  */
26ca987d46SWarner Losh 
27ca987d46SWarner Losh #include <sys/cdefs.h>
28ca987d46SWarner Losh __FBSDID("$FreeBSD$");
29ca987d46SWarner Losh 
30ca987d46SWarner Losh #include <string.h>
31ca987d46SWarner Losh #include <stand.h>
32ca987d46SWarner Losh #include <bootstrap.h>
33ca987d46SWarner Losh 
34ca987d46SWarner Losh /*
35ca987d46SWarner Losh  * Concatenate the (argc) elements of (argv) into a single string, and return
36ca987d46SWarner Losh  * a copy of same.
37ca987d46SWarner Losh  */
38ca987d46SWarner Losh char *
39ca987d46SWarner Losh unargv(int argc, char *argv[])
40ca987d46SWarner Losh {
41ca987d46SWarner Losh     size_t	hlong;
42ca987d46SWarner Losh     int		i;
43ca987d46SWarner Losh     char	*cp;
44ca987d46SWarner Losh 
45ca987d46SWarner Losh     for (i = 0, hlong = 0; i < argc; i++)
46ca987d46SWarner Losh 	hlong += strlen(argv[i]) + 2;
47ca987d46SWarner Losh 
48ca987d46SWarner Losh     if(hlong == 0)
49ca987d46SWarner Losh 	return(NULL);
50ca987d46SWarner Losh 
51ca987d46SWarner Losh     cp = malloc(hlong);
52ca987d46SWarner Losh     cp[0] = 0;
53ca987d46SWarner Losh     for (i = 0; i < argc; i++) {
54ca987d46SWarner Losh 	strcat(cp, argv[i]);
55ca987d46SWarner Losh 	if (i < (argc - 1))
56ca987d46SWarner Losh 	  strcat(cp, " ");
57ca987d46SWarner Losh     }
58ca987d46SWarner Losh 
59ca987d46SWarner Losh     return(cp);
60ca987d46SWarner Losh }
61ca987d46SWarner Losh 
62ca987d46SWarner Losh /*
63ca987d46SWarner Losh  * Get the length of a string in kernel space
64ca987d46SWarner Losh  */
65ca987d46SWarner Losh size_t
66ca987d46SWarner Losh strlenout(vm_offset_t src)
67ca987d46SWarner Losh {
68ca987d46SWarner Losh     char	c;
69ca987d46SWarner Losh     size_t	len;
70ca987d46SWarner Losh 
71ca987d46SWarner Losh     for (len = 0; ; len++) {
72ca987d46SWarner Losh 	archsw.arch_copyout(src++, &c, 1);
73ca987d46SWarner Losh 	if (c == 0)
74ca987d46SWarner Losh 	    break;
75ca987d46SWarner Losh     }
76ca987d46SWarner Losh     return(len);
77ca987d46SWarner Losh }
78ca987d46SWarner Losh 
79ca987d46SWarner Losh /*
80ca987d46SWarner Losh  * Make a duplicate copy of a string in kernel space
81ca987d46SWarner Losh  */
82ca987d46SWarner Losh char *
83ca987d46SWarner Losh strdupout(vm_offset_t str)
84ca987d46SWarner Losh {
85ca987d46SWarner Losh     char	*result, *cp;
86ca987d46SWarner Losh 
87ca987d46SWarner Losh     result = malloc(strlenout(str) + 1);
88ca987d46SWarner Losh     for (cp = result; ;cp++) {
89ca987d46SWarner Losh 	archsw.arch_copyout(str++, cp, 1);
90ca987d46SWarner Losh 	if (*cp == 0)
91ca987d46SWarner Losh 	    break;
92ca987d46SWarner Losh     }
93ca987d46SWarner Losh     return(result);
94ca987d46SWarner Losh }
95ca987d46SWarner Losh 
96ca987d46SWarner Losh /* Zero a region in kernel space. */
97ca987d46SWarner Losh void
98ca987d46SWarner Losh kern_bzero(vm_offset_t dest, size_t len)
99ca987d46SWarner Losh {
100ca987d46SWarner Losh 	char buf[256];
101ca987d46SWarner Losh 	size_t chunk, resid;
102ca987d46SWarner Losh 
103ca987d46SWarner Losh 	bzero(buf, sizeof(buf));
104ca987d46SWarner Losh 	resid = len;
105ca987d46SWarner Losh 	while (resid > 0) {
106ca987d46SWarner Losh 		chunk = min(sizeof(buf), resid);
107ca987d46SWarner Losh 		archsw.arch_copyin(buf, dest, chunk);
108ca987d46SWarner Losh 		resid -= chunk;
109ca987d46SWarner Losh 		dest += chunk;
110ca987d46SWarner Losh 	}
111ca987d46SWarner Losh }
112ca987d46SWarner Losh 
113ca987d46SWarner Losh /*
114ca987d46SWarner Losh  * Read the specified part of a file to kernel space.  Unlike regular
115ca987d46SWarner Losh  * pread, the file pointer is advanced to the end of the read data,
116ca987d46SWarner Losh  * and it just returns 0 if successful.
117ca987d46SWarner Losh  */
118ca987d46SWarner Losh int
119*afc571b1SSimon J. Gerraty kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off)
120ca987d46SWarner Losh {
121ca987d46SWarner Losh 
122*afc571b1SSimon J. Gerraty 	if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
123ca987d46SWarner Losh #ifdef DEBUG
124ca987d46SWarner Losh 		printf("\nlseek failed\n");
125ca987d46SWarner Losh #endif
126ca987d46SWarner Losh 		return (-1);
127ca987d46SWarner Losh 	}
128ca987d46SWarner Losh 	if ((size_t)archsw.arch_readin(fd, dest, len) != len) {
129ca987d46SWarner Losh #ifdef DEBUG
130ca987d46SWarner Losh 		printf("\nreadin failed\n");
131ca987d46SWarner Losh #endif
132ca987d46SWarner Losh 		return (-1);
133ca987d46SWarner Losh 	}
134ca987d46SWarner Losh 	return (0);
135ca987d46SWarner Losh }
136ca987d46SWarner Losh 
137ca987d46SWarner Losh /*
138ca987d46SWarner Losh  * Read the specified part of a file to a malloced buffer.  The file
139ca987d46SWarner Losh  * pointer is advanced to the end of the read data.
140ca987d46SWarner Losh  */
141f9a20b8fSWarner Losh /* coverity[ -tainted_data_return ] */
142ca987d46SWarner Losh void *
143*afc571b1SSimon J. Gerraty alloc_pread(readin_handle_t fd, off_t off, size_t len)
144ca987d46SWarner Losh {
145ca987d46SWarner Losh 	void *buf;
146ca987d46SWarner Losh 
147ca987d46SWarner Losh 	buf = malloc(len);
148ca987d46SWarner Losh 	if (buf == NULL) {
149ca987d46SWarner Losh #ifdef DEBUG
150ca987d46SWarner Losh 		printf("\nmalloc(%d) failed\n", (int)len);
151ca987d46SWarner Losh #endif
15291e69716SToomas Soome 		errno = ENOMEM;
153ca987d46SWarner Losh 		return (NULL);
154ca987d46SWarner Losh 	}
155*afc571b1SSimon J. Gerraty 	if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
156ca987d46SWarner Losh #ifdef DEBUG
157ca987d46SWarner Losh 		printf("\nlseek failed\n");
158ca987d46SWarner Losh #endif
159ca987d46SWarner Losh 		free(buf);
160ca987d46SWarner Losh 		return (NULL);
161ca987d46SWarner Losh 	}
162*afc571b1SSimon J. Gerraty 	if ((size_t)VECTX_READ(fd, buf, len) != len) {
163ca987d46SWarner Losh #ifdef DEBUG
164ca987d46SWarner Losh 		printf("\nread failed\n");
165ca987d46SWarner Losh #endif
166ca987d46SWarner Losh 		free(buf);
167ca987d46SWarner Losh 		return (NULL);
168ca987d46SWarner Losh 	}
169ca987d46SWarner Losh 	return (buf);
170ca987d46SWarner Losh }
171ca987d46SWarner Losh 
172ca987d46SWarner Losh /*
173ca987d46SWarner Losh  * Display a region in traditional hexdump format.
174ca987d46SWarner Losh  */
175ca987d46SWarner Losh void
176ca987d46SWarner Losh hexdump(caddr_t region, size_t len)
177ca987d46SWarner Losh {
178ca987d46SWarner Losh     caddr_t	line;
179ca987d46SWarner Losh     int		x, c;
180ca987d46SWarner Losh     char	lbuf[80];
181ca987d46SWarner Losh #define emit(fmt, args...)	{sprintf(lbuf, fmt , ## args); pager_output(lbuf);}
182ca987d46SWarner Losh 
183ca987d46SWarner Losh     pager_open();
184ca987d46SWarner Losh     for (line = region; line < (region + len); line += 16) {
185ca987d46SWarner Losh 	emit("%08lx  ", (long) line);
186ca987d46SWarner Losh 
187ca987d46SWarner Losh 	for (x = 0; x < 16; x++) {
188ca987d46SWarner Losh 	    if ((line + x) < (region + len)) {
18956e53cb8SWarner Losh 		emit("%02x ", *(uint8_t *)(line + x));
190ca987d46SWarner Losh 	    } else {
191ca987d46SWarner Losh 		emit("-- ");
192ca987d46SWarner Losh 	    }
193ca987d46SWarner Losh 	    if (x == 7)
194ca987d46SWarner Losh 		emit(" ");
195ca987d46SWarner Losh 	}
196ca987d46SWarner Losh 	emit(" |");
197ca987d46SWarner Losh 	for (x = 0; x < 16; x++) {
198ca987d46SWarner Losh 	    if ((line + x) < (region + len)) {
19956e53cb8SWarner Losh 		c = *(uint8_t *)(line + x);
200ca987d46SWarner Losh 		if ((c < ' ') || (c > '~'))	/* !isprint(c) */
201ca987d46SWarner Losh 		    c = '.';
202ca987d46SWarner Losh 		emit("%c", c);
203ca987d46SWarner Losh 	    } else {
204ca987d46SWarner Losh 		emit(" ");
205ca987d46SWarner Losh 	    }
206ca987d46SWarner Losh 	}
207ca987d46SWarner Losh 	emit("|\n");
208ca987d46SWarner Losh     }
209ca987d46SWarner Losh     pager_close();
210ca987d46SWarner Losh }
211ca987d46SWarner Losh 
212ca987d46SWarner Losh void
213ca987d46SWarner Losh dev_cleanup(void)
214ca987d46SWarner Losh {
215ca987d46SWarner Losh     int		i;
216ca987d46SWarner Losh 
217ca987d46SWarner Losh     /* Call cleanup routines */
218ca987d46SWarner Losh     for (i = 0; devsw[i] != NULL; ++i)
219ca987d46SWarner Losh 	if (devsw[i]->dv_cleanup != NULL)
220ca987d46SWarner Losh 	    (devsw[i]->dv_cleanup)();
221ca987d46SWarner Losh }
222