xref: /freebsd/stand/common/misc.c (revision 3e15b01d)
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 <string.h>
28ca987d46SWarner Losh #include <stand.h>
29ca987d46SWarner Losh #include <bootstrap.h>
30ca987d46SWarner Losh 
31ca987d46SWarner Losh /*
32ca987d46SWarner Losh  * Concatenate the (argc) elements of (argv) into a single string, and return
33ca987d46SWarner Losh  * a copy of same.
34ca987d46SWarner Losh  */
35ca987d46SWarner Losh char *
unargv(int argc,char * argv[])36ca987d46SWarner Losh unargv(int argc, char *argv[])
37ca987d46SWarner Losh {
38ca987d46SWarner Losh     size_t	hlong;
39ca987d46SWarner Losh     int		i;
40ca987d46SWarner Losh     char	*cp;
41ca987d46SWarner Losh 
42ca987d46SWarner Losh     for (i = 0, hlong = 0; i < argc; i++)
43ca987d46SWarner Losh 	hlong += strlen(argv[i]) + 2;
44ca987d46SWarner Losh 
45ca987d46SWarner Losh     if(hlong == 0)
46ca987d46SWarner Losh 	return(NULL);
47ca987d46SWarner Losh 
48ca987d46SWarner Losh     cp = malloc(hlong);
49ca987d46SWarner Losh     cp[0] = 0;
50ca987d46SWarner Losh     for (i = 0; i < argc; i++) {
51ca987d46SWarner Losh 	strcat(cp, argv[i]);
52ca987d46SWarner Losh 	if (i < (argc - 1))
53ca987d46SWarner Losh 	  strcat(cp, " ");
54ca987d46SWarner Losh     }
55ca987d46SWarner Losh 
56ca987d46SWarner Losh     return(cp);
57ca987d46SWarner Losh }
58ca987d46SWarner Losh 
59ca987d46SWarner Losh /*
60ca987d46SWarner Losh  * Get the length of a string in kernel space
61ca987d46SWarner Losh  */
62ca987d46SWarner Losh size_t
strlenout(vm_offset_t src)63ca987d46SWarner Losh strlenout(vm_offset_t src)
64ca987d46SWarner Losh {
65ca987d46SWarner Losh     char	c;
66ca987d46SWarner Losh     size_t	len;
67ca987d46SWarner Losh 
68ca987d46SWarner Losh     for (len = 0; ; len++) {
69ca987d46SWarner Losh 	archsw.arch_copyout(src++, &c, 1);
70ca987d46SWarner Losh 	if (c == 0)
71ca987d46SWarner Losh 	    break;
72ca987d46SWarner Losh     }
73ca987d46SWarner Losh     return(len);
74ca987d46SWarner Losh }
75ca987d46SWarner Losh 
76ca987d46SWarner Losh /*
77ca987d46SWarner Losh  * Make a duplicate copy of a string in kernel space
78ca987d46SWarner Losh  */
79ca987d46SWarner Losh char *
strdupout(vm_offset_t str)80ca987d46SWarner Losh strdupout(vm_offset_t str)
81ca987d46SWarner Losh {
82ca987d46SWarner Losh     char	*result, *cp;
83ca987d46SWarner Losh 
84ca987d46SWarner Losh     result = malloc(strlenout(str) + 1);
85ca987d46SWarner Losh     for (cp = result; ;cp++) {
86ca987d46SWarner Losh 	archsw.arch_copyout(str++, cp, 1);
87ca987d46SWarner Losh 	if (*cp == 0)
88ca987d46SWarner Losh 	    break;
89ca987d46SWarner Losh     }
90ca987d46SWarner Losh     return(result);
91ca987d46SWarner Losh }
92ca987d46SWarner Losh 
93ca987d46SWarner Losh /* Zero a region in kernel space. */
94ca987d46SWarner Losh void
kern_bzero(vm_offset_t dest,size_t len)95ca987d46SWarner Losh kern_bzero(vm_offset_t dest, size_t len)
96ca987d46SWarner Losh {
97ca987d46SWarner Losh 	char buf[256];
98ca987d46SWarner Losh 	size_t chunk, resid;
99ca987d46SWarner Losh 
100ca987d46SWarner Losh 	bzero(buf, sizeof(buf));
101ca987d46SWarner Losh 	resid = len;
102ca987d46SWarner Losh 	while (resid > 0) {
103ca987d46SWarner Losh 		chunk = min(sizeof(buf), resid);
104ca987d46SWarner Losh 		archsw.arch_copyin(buf, dest, chunk);
105ca987d46SWarner Losh 		resid -= chunk;
106ca987d46SWarner Losh 		dest += chunk;
107ca987d46SWarner Losh 	}
108ca987d46SWarner Losh }
109ca987d46SWarner Losh 
110ca987d46SWarner Losh /*
111ca987d46SWarner Losh  * Read the specified part of a file to kernel space.  Unlike regular
112ca987d46SWarner Losh  * pread, the file pointer is advanced to the end of the read data,
113ca987d46SWarner Losh  * and it just returns 0 if successful.
114ca987d46SWarner Losh  */
115ca987d46SWarner Losh int
kern_pread(readin_handle_t fd,vm_offset_t dest,size_t len,off_t off)116afc571b1SSimon J. Gerraty kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off)
117ca987d46SWarner Losh {
118ca987d46SWarner Losh 
119afc571b1SSimon J. Gerraty 	if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
120ca987d46SWarner Losh #ifdef DEBUG
121ca987d46SWarner Losh 		printf("\nlseek failed\n");
122ca987d46SWarner Losh #endif
123ca987d46SWarner Losh 		return (-1);
124ca987d46SWarner Losh 	}
125ca987d46SWarner Losh 	if ((size_t)archsw.arch_readin(fd, dest, len) != len) {
126ca987d46SWarner Losh #ifdef DEBUG
127ca987d46SWarner Losh 		printf("\nreadin failed\n");
128ca987d46SWarner Losh #endif
129ca987d46SWarner Losh 		return (-1);
130ca987d46SWarner Losh 	}
131ca987d46SWarner Losh 	return (0);
132ca987d46SWarner Losh }
133ca987d46SWarner Losh 
134ca987d46SWarner Losh /*
135ca987d46SWarner Losh  * Read the specified part of a file to a malloced buffer.  The file
136ca987d46SWarner Losh  * pointer is advanced to the end of the read data.
137ca987d46SWarner Losh  */
138f9a20b8fSWarner Losh /* coverity[ -tainted_data_return ] */
139ca987d46SWarner Losh void *
alloc_pread(readin_handle_t fd,off_t off,size_t len)140afc571b1SSimon J. Gerraty alloc_pread(readin_handle_t fd, off_t off, size_t len)
141ca987d46SWarner Losh {
142ca987d46SWarner Losh 	void *buf;
143ca987d46SWarner Losh 
144ca987d46SWarner Losh 	buf = malloc(len);
145ca987d46SWarner Losh 	if (buf == NULL) {
146ca987d46SWarner Losh #ifdef DEBUG
147ca987d46SWarner Losh 		printf("\nmalloc(%d) failed\n", (int)len);
148ca987d46SWarner Losh #endif
14991e69716SToomas Soome 		errno = ENOMEM;
150ca987d46SWarner Losh 		return (NULL);
151ca987d46SWarner Losh 	}
152afc571b1SSimon J. Gerraty 	if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
153ca987d46SWarner Losh #ifdef DEBUG
154ca987d46SWarner Losh 		printf("\nlseek failed\n");
155ca987d46SWarner Losh #endif
156ca987d46SWarner Losh 		free(buf);
157ca987d46SWarner Losh 		return (NULL);
158ca987d46SWarner Losh 	}
159afc571b1SSimon J. Gerraty 	if ((size_t)VECTX_READ(fd, buf, len) != len) {
160ca987d46SWarner Losh #ifdef DEBUG
161ca987d46SWarner Losh 		printf("\nread failed\n");
162ca987d46SWarner Losh #endif
163ca987d46SWarner Losh 		free(buf);
164ca987d46SWarner Losh 		return (NULL);
165ca987d46SWarner Losh 	}
166ca987d46SWarner Losh 	return (buf);
167ca987d46SWarner Losh }
168ca987d46SWarner Losh 
169b4cb3fe0SToomas Soome /*
170b4cb3fe0SToomas Soome  * mount new rootfs and unmount old, set "currdev" environment variable.
171b4cb3fe0SToomas Soome  */
mount_currdev(struct env_var * ev,int flags,const void * value)172b4cb3fe0SToomas Soome int mount_currdev(struct env_var *ev, int flags, const void *value)
173b4cb3fe0SToomas Soome {
174b4cb3fe0SToomas Soome 	int rv;
175b4cb3fe0SToomas Soome 
176b4cb3fe0SToomas Soome 	/* mount new rootfs */
177b4cb3fe0SToomas Soome 	rv = mount(value, "/", 0, NULL);
178b4cb3fe0SToomas Soome 	if (rv == 0) {
179b4cb3fe0SToomas Soome 		/*
180b4cb3fe0SToomas Soome 		 * Note we unmount any previously mounted fs only after
181b4cb3fe0SToomas Soome 		 * successfully mounting the new because we do not want to
182b4cb3fe0SToomas Soome 		 * end up with unmounted rootfs.
183b4cb3fe0SToomas Soome 		 */
184b4cb3fe0SToomas Soome 		if (ev->ev_value != NULL)
185b4cb3fe0SToomas Soome 			unmount(ev->ev_value, 0);
186b4cb3fe0SToomas Soome 		env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
187b4cb3fe0SToomas Soome 	}
188b4cb3fe0SToomas Soome 	return (rv);
189b4cb3fe0SToomas Soome }
1901c1783d6SWarner Losh 
1911c1783d6SWarner Losh /*
1921c1783d6SWarner Losh  * Set currdev to suit the value being supplied in (value)
1931c1783d6SWarner Losh  */
1941c1783d6SWarner Losh int
gen_setcurrdev(struct env_var * ev,int flags,const void * value)1951c1783d6SWarner Losh gen_setcurrdev(struct env_var *ev, int flags, const void *value)
1961c1783d6SWarner Losh {
1971c1783d6SWarner Losh 	struct devdesc *ncurr;
1981c1783d6SWarner Losh 	int rv;
1991c1783d6SWarner Losh 
2001c1783d6SWarner Losh 	if ((rv = devparse(&ncurr, value, NULL)) != 0)
2011c1783d6SWarner Losh 		return (rv);
2021c1783d6SWarner Losh 	free(ncurr);
2031c1783d6SWarner Losh 
2041c1783d6SWarner Losh 	return (mount_currdev(ev, flags, value));
2051c1783d6SWarner Losh }
206ad70f2e2SWarner Losh 
207ad70f2e2SWarner Losh /*
208ad70f2e2SWarner Losh  * Wrapper to set currdev and loaddev at the same time.
209ad70f2e2SWarner Losh  */
210ad70f2e2SWarner Losh void
set_currdev(const char * devname)211ad70f2e2SWarner Losh set_currdev(const char *devname)
212ad70f2e2SWarner Losh {
213ad70f2e2SWarner Losh 
214ad70f2e2SWarner Losh 	env_setenv("currdev", EV_VOLATILE, devname, gen_setcurrdev,
215ad70f2e2SWarner Losh 	    env_nounset);
216ad70f2e2SWarner Losh 	/*
217ad70f2e2SWarner Losh 	 * Don't execute hook here; the loaddev hook makes it immutable
218ad70f2e2SWarner Losh 	 * once we've determined what the proper currdev is.
219ad70f2e2SWarner Losh 	 */
220ad70f2e2SWarner Losh 	env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
221ad70f2e2SWarner Losh 	    env_nounset);
222ad70f2e2SWarner Losh }
223