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 }
206*ad70f2e2SWarner Losh
207*ad70f2e2SWarner Losh /*
208*ad70f2e2SWarner Losh * Wrapper to set currdev and loaddev at the same time.
209*ad70f2e2SWarner Losh */
210*ad70f2e2SWarner Losh void
set_currdev(const char * devname)211*ad70f2e2SWarner Losh set_currdev(const char *devname)
212*ad70f2e2SWarner Losh {
213*ad70f2e2SWarner Losh
214*ad70f2e2SWarner Losh env_setenv("currdev", EV_VOLATILE, devname, gen_setcurrdev,
215*ad70f2e2SWarner Losh env_nounset);
216*ad70f2e2SWarner Losh /*
217*ad70f2e2SWarner Losh * Don't execute hook here; the loaddev hook makes it immutable
218*ad70f2e2SWarner Losh * once we've determined what the proper currdev is.
219*ad70f2e2SWarner Losh */
220*ad70f2e2SWarner Losh env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
221*ad70f2e2SWarner Losh env_nounset);
222*ad70f2e2SWarner Losh }
223