Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/common/misc.c
34677 views
1
/*-
2
* Copyright (c) 1998 Michael Smith <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <string.h>
28
#include <stand.h>
29
#include <bootstrap.h>
30
31
/*
32
* Concatenate the (argc) elements of (argv) into a single string, and return
33
* a copy of same.
34
*/
35
char *
36
unargv(int argc, char *argv[])
37
{
38
size_t hlong;
39
int i;
40
char *cp;
41
42
for (i = 0, hlong = 0; i < argc; i++)
43
hlong += strlen(argv[i]) + 2;
44
45
if(hlong == 0)
46
return(NULL);
47
48
cp = malloc(hlong);
49
cp[0] = 0;
50
for (i = 0; i < argc; i++) {
51
strcat(cp, argv[i]);
52
if (i < (argc - 1))
53
strcat(cp, " ");
54
}
55
56
return(cp);
57
}
58
59
/*
60
* Get the length of a string in kernel space
61
*/
62
size_t
63
strlenout(vm_offset_t src)
64
{
65
char c;
66
size_t len;
67
68
for (len = 0; ; len++) {
69
archsw.arch_copyout(src++, &c, 1);
70
if (c == 0)
71
break;
72
}
73
return(len);
74
}
75
76
/*
77
* Make a duplicate copy of a string in kernel space
78
*/
79
char *
80
strdupout(vm_offset_t str)
81
{
82
char *result, *cp;
83
84
result = malloc(strlenout(str) + 1);
85
for (cp = result; ;cp++) {
86
archsw.arch_copyout(str++, cp, 1);
87
if (*cp == 0)
88
break;
89
}
90
return(result);
91
}
92
93
/* Zero a region in kernel space. */
94
void
95
kern_bzero(vm_offset_t dest, size_t len)
96
{
97
char buf[256];
98
size_t chunk, resid;
99
100
bzero(buf, sizeof(buf));
101
resid = len;
102
while (resid > 0) {
103
chunk = min(sizeof(buf), resid);
104
archsw.arch_copyin(buf, dest, chunk);
105
resid -= chunk;
106
dest += chunk;
107
}
108
}
109
110
/*
111
* Read the specified part of a file to kernel space. Unlike regular
112
* pread, the file pointer is advanced to the end of the read data,
113
* and it just returns 0 if successful.
114
*/
115
int
116
kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off)
117
{
118
119
if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
120
#ifdef DEBUG
121
printf("\nlseek failed\n");
122
#endif
123
return (-1);
124
}
125
if ((size_t)archsw.arch_readin(fd, dest, len) != len) {
126
#ifdef DEBUG
127
printf("\nreadin failed\n");
128
#endif
129
return (-1);
130
}
131
return (0);
132
}
133
134
/*
135
* Read the specified part of a file to a malloced buffer. The file
136
* pointer is advanced to the end of the read data.
137
*/
138
/* coverity[ -tainted_data_return ] */
139
void *
140
alloc_pread(readin_handle_t fd, off_t off, size_t len)
141
{
142
void *buf;
143
144
buf = malloc(len);
145
if (buf == NULL) {
146
#ifdef DEBUG
147
printf("\nmalloc(%d) failed\n", (int)len);
148
#endif
149
errno = ENOMEM;
150
return (NULL);
151
}
152
if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
153
#ifdef DEBUG
154
printf("\nlseek failed\n");
155
#endif
156
free(buf);
157
return (NULL);
158
}
159
if ((size_t)VECTX_READ(fd, buf, len) != len) {
160
#ifdef DEBUG
161
printf("\nread failed\n");
162
#endif
163
free(buf);
164
return (NULL);
165
}
166
return (buf);
167
}
168
169
/*
170
* mount new rootfs and unmount old, set "currdev" environment variable.
171
*/
172
int mount_currdev(struct env_var *ev, int flags, const void *value)
173
{
174
int rv;
175
176
/* mount new rootfs */
177
rv = mount(value, "/", 0, NULL);
178
if (rv == 0) {
179
/*
180
* Note we unmount any previously mounted fs only after
181
* successfully mounting the new because we do not want to
182
* end up with unmounted rootfs.
183
*/
184
if (ev->ev_value != NULL)
185
unmount(ev->ev_value, 0);
186
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
187
}
188
return (rv);
189
}
190
191
/*
192
* Set currdev to suit the value being supplied in (value)
193
*/
194
int
195
gen_setcurrdev(struct env_var *ev, int flags, const void *value)
196
{
197
struct devdesc *ncurr;
198
int rv;
199
200
if ((rv = devparse(&ncurr, value, NULL)) != 0)
201
return (rv);
202
free(ncurr);
203
204
return (mount_currdev(ev, flags, value));
205
}
206
207
/*
208
* Wrapper to set currdev and loaddev at the same time.
209
*/
210
void
211
set_currdev(const char *devname)
212
{
213
214
env_setenv("currdev", EV_VOLATILE, devname, gen_setcurrdev,
215
env_nounset);
216
/*
217
* Don't execute hook here; the loaddev hook makes it immutable
218
* once we've determined what the proper currdev is.
219
*/
220
env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
221
env_nounset);
222
}
223
224
#ifndef LOADER_NET_SUPPORT
225
/*
226
* This api is normally provided by dev_net.c
227
* This stub keeps libsa happy when LOADER_NET_SUPPORT
228
* is not enabled.
229
*/
230
bool
231
is_tftp(void)
232
{
233
return false;
234
}
235
#endif
236
237