]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/bsd_stubs.c
xnu-4903.231.4.tar.gz
[apple/xnu.git] / bsd / kern / bsd_stubs.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
3e170ce0 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
3e170ce0 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
3e170ce0 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
3e170ce0 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28#include <sys/time.h>
29#include <kern/task.h>
30#include <kern/thread.h>
31#include <mach/mach_types.h>
32#include <mach/vm_prot.h>
33#include <vm/vm_kern.h>
6d2010ae 34#include <sys/stat.h>
1c79356b
A
35#include <vm/vm_map.h>
36#include <sys/systm.h>
6d2010ae 37#include <kern/assert.h>
1c79356b 38#include <sys/conf.h>
91447636 39#include <sys/proc_internal.h>
3e170ce0 40#include <sys/buf.h> /* for SET */
b0d623f7 41#include <sys/kernel.h>
0b4e3aa0 42#include <sys/user.h>
0c530ab8
A
43#include <sys/sysent.h>
44#include <sys/sysproto.h>
1c79356b 45
2d21ac55
A
46/* XXX these should be in a common header somwhere, but aren't */
47extern int chrtoblk_set(int, int);
cc8bc92a 48extern vm_offset_t kmem_mb_alloc(vm_map_t, int, int, kern_return_t *);
2d21ac55
A
49
50/* XXX most of these just exist to export; there's no good header for them*/
3e170ce0 51void pcb_synch(void);
2d21ac55 52
3e170ce0 53TAILQ_HEAD(, devsw_lock) devsw_locks;
6d2010ae 54lck_mtx_t devsw_lock_list_mtx;
3e170ce0 55lck_grp_t * devsw_lock_grp;
2d21ac55 56
1c79356b 57/* Just to satisfy pstat command */
3e170ce0 58int dmmin, dmmax, dmtext;
1c79356b 59
91447636 60vm_offset_t
cc8bc92a 61kmem_mb_alloc(vm_map_t mbmap, int size, int physContig, kern_return_t *err)
1c79356b 62{
3e170ce0 63 vm_offset_t addr = 0;
b0d623f7
A
64 kern_return_t kr = KERN_SUCCESS;
65
3e170ce0 66 if (!physContig)
5c9f4661 67 kr = kernel_memory_allocate(mbmap, &addr, size, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
1c79356b 68 else
5c9f4661 69 kr = kmem_alloc_contig(mbmap, &addr, size, PAGE_MASK, 0xfffff, 0, KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
b0d623f7 70
3e170ce0 71 if (kr != KERN_SUCCESS)
b0d623f7 72 addr = 0;
cc8bc92a
A
73 if (err)
74 *err = kr;
b0d623f7
A
75
76 return addr;
1c79356b
A
77}
78
91447636
A
79/*
80 * XXX this function only exists to be exported and do nothing.
81 */
82void
83pcb_synch(void)
84{
85}
1c79356b
A
86
87struct proc *
88current_proc(void)
89{
90 /* Never returns a NULL */
0b4e3aa0 91 struct uthread * ut;
3e170ce0 92 struct proc * p;
2d21ac55 93 thread_t thread = current_thread();
0b4e3aa0 94
3e170ce0
A
95 ut = (struct uthread *)get_bsdthread_info(thread);
96 if (ut && (ut->uu_flag & UT_VFORK) && ut->uu_proc) {
0b4e3aa0 97 p = ut->uu_proc;
3e170ce0 98 if ((p->p_lflag & P_LINVFORK) == 0)
0b4e3aa0 99 panic("returning child proc not under vfork");
3e170ce0 100 if (p->p_vforkact != (void *)thread)
0b4e3aa0 101 panic("returning child proc which is not cur_act");
3e170ce0 102 return (p);
0b4e3aa0
A
103 }
104
105 p = (struct proc *)get_bsdtask_info(current_task());
106
1c79356b 107 if (p == NULL)
0b4e3aa0
A
108 return (kernproc);
109
1c79356b
A
110 return (p);
111}
112
113/* Device switch add delete routines */
114
1c79356b
A
115struct bdevsw nobdev = NO_BDEVICE;
116struct cdevsw nocdev = NO_CDEVICE;
3e170ce0 117/*
1c79356b
A
118 * if index is -1, return a free slot if avaliable
119 * else see whether the index is free
120 * return the major number that is free else -1
121 *
316670eb
A
122 * if index is negative, we start
123 * looking for a free slot at the absolute value of index,
124 * instead of starting at 0
1c79356b
A
125 */
126int
127bdevsw_isfree(int index)
128{
3e170ce0 129 struct bdevsw * devsw;
316670eb
A
130
131 if (index < 0) {
3e170ce0
A
132 if (index == -1)
133 index = 1; /* start at 1 to avoid collision with volfs (Radar 2842228) */
134 else
135 index = -index; /* start at least this far up in the table */
136 devsw = &bdevsw[index];
137 for (; index < nblkdev; index++, devsw++) {
138 if (memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) == 0)
139 break;
140 }
1c79356b 141 }
3e170ce0
A
142
143 if (index < 0 || index >= nblkdev)
144 return (-1);
145
316670eb 146 devsw = &bdevsw[index];
3e170ce0
A
147 if ((memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) != 0)) {
148 return (-1);
1c79356b 149 }
3e170ce0 150 return (index);
1c79356b
A
151}
152
3e170ce0 153/*
1c79356b
A
154 * if index is -1, find a free slot to add
155 * else see whether the slot is free
156 * return the major number that is used else -1
316670eb
A
157 *
158 * if index is negative, we start
159 * looking for a free slot at the absolute value of index,
160 * instead of starting at 0
1c79356b
A
161 */
162int
3e170ce0 163bdevsw_add(int index, struct bdevsw * bsw)
1c79356b 164{
39037602 165 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb
A
166 index = bdevsw_isfree(index);
167 if (index < 0) {
39037602
A
168 index = -1;
169 } else {
170 bdevsw[index] = *bsw;
1c79356b 171 }
39037602 172 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 173 return (index);
1c79356b 174}
316670eb 175/*
1c79356b
A
176 * if the slot has the same bsw, then remove
177 * else -1
178 */
179int
3e170ce0 180bdevsw_remove(int index, struct bdevsw * bsw)
1c79356b 181{
3e170ce0
A
182 struct bdevsw * devsw;
183
184 if (index < 0 || index >= nblkdev)
185 return (-1);
1c79356b
A
186
187 devsw = &bdevsw[index];
39037602 188 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 189 if ((memcmp((char *)devsw, (char *)bsw, sizeof(struct bdevsw)) != 0)) {
39037602
A
190 index = -1;
191 } else {
192 bdevsw[index] = nobdev;
1c79356b 193 }
39037602 194 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 195 return (index);
1c79356b
A
196}
197
3e170ce0 198/*
1c79356b
A
199 * if index is -1, return a free slot if avaliable
200 * else see whether the index is free
201 * return the major number that is free else -1
316670eb
A
202 *
203 * if index is negative, we start
204 * looking for a free slot at the absolute value of index,
205 * instead of starting at 0
1c79356b
A
206 */
207int
208cdevsw_isfree(int index)
209{
3e170ce0 210 struct cdevsw * devsw;
1c79356b 211
316670eb 212 if (index < 0) {
3e170ce0
A
213 if (index == -1)
214 index = 0;
215 else
216 index = -index; /* start at least this far up in the table */
217 devsw = &cdevsw[index];
218 for (; index < nchrdev; index++, devsw++) {
219 if (memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) == 0)
220 break;
221 }
1c79356b 222 }
3e170ce0
A
223
224 if (index < 0 || index >= nchrdev)
225 return (-1);
226
1c79356b 227 devsw = &cdevsw[index];
3e170ce0
A
228 if ((memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) != 0)) {
229 return (-1);
1c79356b 230 }
3e170ce0 231 return (index);
1c79356b
A
232}
233
3e170ce0 234/*
1c79356b
A
235 * if index is -1, find a free slot to add
236 * else see whether the slot is free
237 * return the major number that is used else -1
2d21ac55 238 *
316670eb
A
239 * if index is negative, we start
240 * looking for a free slot at the absolute value of index,
241 * instead of starting at 0
242 *
2d21ac55
A
243 * NOTE: In practice, -1 is unusable, since there are kernel internal
244 * devices that call this function with absolute index values,
245 * which will stomp on free-slot based assignments that happen
316670eb 246 * before them. -24 is currently a safe starting point.
1c79356b
A
247 */
248int
3e170ce0 249cdevsw_add(int index, struct cdevsw * csw)
1c79356b 250{
39037602 251 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb 252 index = cdevsw_isfree(index);
2d21ac55 253 if (index < 0) {
39037602
A
254 index = -1;
255 } else {
256 cdevsw[index] = *csw;
1c79356b 257 }
39037602 258 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 259 return (index);
1c79356b
A
260}
261/*
316670eb 262 * if the slot has the same csw, then remove
1c79356b
A
263 * else -1
264 */
265int
3e170ce0 266cdevsw_remove(int index, struct cdevsw * csw)
1c79356b 267{
3e170ce0
A
268 struct cdevsw * devsw;
269
270 if (index < 0 || index >= nchrdev)
271 return (-1);
1c79356b
A
272
273 devsw = &cdevsw[index];
39037602 274 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 275 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
39037602
A
276 index = -1;
277 } else {
278 cdevsw[index] = nocdev;
279 cdevsw_flags[index] = 0;
1c79356b 280 }
39037602 281 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 282 return (index);
1c79356b
A
283}
284
9bccf70c
A
285static int
286cdev_set_bdev(int cdev, int bdev)
287{
9bccf70c
A
288 return (chrtoblk_set(cdev, bdev));
289}
290
3e170ce0 291int
9bccf70c
A
292cdevsw_add_with_bdev(int index, struct cdevsw * csw, int bdev)
293{
294 index = cdevsw_add(index, csw);
295 if (index < 0) {
296 return (index);
297 }
298 if (cdev_set_bdev(index, bdev) < 0) {
299 cdevsw_remove(index, csw);
300 return (-1);
301 }
302 return (index);
303}
304
6d2010ae 305int
5ba3f43e 306cdevsw_setkqueueok(int maj, struct cdevsw * csw, int extra_flags)
6d2010ae 307{
3e170ce0 308 struct cdevsw * devsw;
6d2010ae
A
309 uint64_t flags = CDEVSW_SELECT_KQUEUE;
310
5ba3f43e
A
311 if (maj < 0 || maj >= nchrdev) {
312 return -1;
313 }
3e170ce0 314
5ba3f43e 315 devsw = &cdevsw[maj];
3e170ce0 316 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
5ba3f43e 317 return -1;
6d2010ae
A
318 }
319
5ba3f43e 320 flags |= extra_flags;
6d2010ae 321
5ba3f43e 322 cdevsw_flags[maj] = flags;
6d2010ae
A
323 return 0;
324}
325
3e170ce0 326#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
2d21ac55 327
b0d623f7
A
328/*
329 * Copy the "hostname" variable into a caller-provided buffer
330 * Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
3e170ce0 331 * On success, "len" will be set to the number of characters preceding
b0d623f7
A
332 * the NULL character in the hostname.
333 */
334int
3e170ce0 335bsd_hostname(char * buf, int bufsize, int * len)
b0d623f7
A
336{
337 /*
3e170ce0 338 * "hostname" is null-terminated, and "hostnamelen" is equivalent to strlen(hostname).
b0d623f7
A
339 */
340 if (hostnamelen < bufsize) {
341 strlcpy(buf, hostname, bufsize);
342 *len = hostnamelen;
343 return 0;
344 } else {
345 return ENAMETOOLONG;
3e170ce0 346 }
b0d623f7
A
347}
348
6d2010ae
A
349void
350devsw_lock(dev_t dev, int mode)
351{
352 devsw_lock_t newlock, tmplock;
353 int res;
354
3e170ce0 355 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
356 assert(mode == S_IFCHR || mode == S_IFBLK);
357
358 MALLOC(newlock, devsw_lock_t, sizeof(struct devsw_lock), M_TEMP, M_WAITOK | M_ZERO);
359 newlock->dl_dev = dev;
360 newlock->dl_thread = current_thread();
361 newlock->dl_mode = mode;
3e170ce0 362
6d2010ae
A
363 lck_mtx_lock_spin(&devsw_lock_list_mtx);
364retry:
3e170ce0
A
365 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
366 {
6d2010ae 367 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
3e170ce0 368 res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
6d2010ae
A
369 assert(res == 0);
370 goto retry;
371 }
372 }
373
374 TAILQ_INSERT_TAIL(&devsw_locks, newlock, dl_list);
375 lck_mtx_unlock(&devsw_lock_list_mtx);
6d2010ae
A
376}
377void
378devsw_unlock(dev_t dev, int mode)
379{
380 devsw_lock_t tmplock;
381
3e170ce0 382 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
383
384 lck_mtx_lock_spin(&devsw_lock_list_mtx);
385
3e170ce0
A
386 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
387 {
388 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
6d2010ae
A
389 break;
390 }
391 }
392
393 if (tmplock == NULL) {
394 panic("Trying to unlock, and couldn't find lock.");
395 }
396
397 if (tmplock->dl_thread != current_thread()) {
398 panic("Trying to unlock, but I don't hold the lock.");
399 }
400
401 wakeup(tmplock);
402 TAILQ_REMOVE(&devsw_locks, tmplock, dl_list);
3e170ce0 403
6d2010ae 404 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 405
6d2010ae
A
406 FREE(tmplock, M_TEMP);
407}
408
409void
410devsw_init()
411{
412 devsw_lock_grp = lck_grp_alloc_init("devsw", NULL);
413 assert(devsw_lock_grp != NULL);
414
415 lck_mtx_init(&devsw_lock_list_mtx, devsw_lock_grp, NULL);
416 TAILQ_INIT(&devsw_locks);
417}