]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/bsd_stubs.c
xnu-3789.1.32.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);
b0d623f7 48extern vm_offset_t kmem_mb_alloc(vm_map_t, int, int);
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
3e170ce0 61kmem_mb_alloc(vm_map_t mbmap, int size, int physContig)
1c79356b 62{
3e170ce0 63 vm_offset_t addr = 0;
b0d623f7
A
64 kern_return_t kr = KERN_SUCCESS;
65
3e170ce0
A
66 if (!physContig)
67 kr = kernel_memory_allocate(mbmap, &addr, size, 0, KMA_NOPAGEWAIT | KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
1c79356b 68 else
3e170ce0 69 kr = kmem_alloc_contig(mbmap, &addr, size, PAGE_MASK, 0xfffff, 0, KMA_NOPAGEWAIT | KMA_KOBJECT | KMA_LOMEM, VM_KERN_MEMORY_MBUF);
b0d623f7 70
3e170ce0 71 if (kr != KERN_SUCCESS)
b0d623f7
A
72 addr = 0;
73
74 return addr;
1c79356b
A
75}
76
91447636
A
77/*
78 * XXX this function only exists to be exported and do nothing.
79 */
80void
81pcb_synch(void)
82{
83}
1c79356b
A
84
85struct proc *
86current_proc(void)
87{
88 /* Never returns a NULL */
0b4e3aa0 89 struct uthread * ut;
3e170ce0 90 struct proc * p;
2d21ac55 91 thread_t thread = current_thread();
0b4e3aa0 92
3e170ce0
A
93 ut = (struct uthread *)get_bsdthread_info(thread);
94 if (ut && (ut->uu_flag & UT_VFORK) && ut->uu_proc) {
0b4e3aa0 95 p = ut->uu_proc;
3e170ce0 96 if ((p->p_lflag & P_LINVFORK) == 0)
0b4e3aa0 97 panic("returning child proc not under vfork");
3e170ce0 98 if (p->p_vforkact != (void *)thread)
0b4e3aa0 99 panic("returning child proc which is not cur_act");
3e170ce0 100 return (p);
0b4e3aa0
A
101 }
102
103 p = (struct proc *)get_bsdtask_info(current_task());
104
1c79356b 105 if (p == NULL)
0b4e3aa0
A
106 return (kernproc);
107
1c79356b
A
108 return (p);
109}
110
111/* Device switch add delete routines */
112
1c79356b
A
113struct bdevsw nobdev = NO_BDEVICE;
114struct cdevsw nocdev = NO_CDEVICE;
3e170ce0 115/*
1c79356b
A
116 * if index is -1, return a free slot if avaliable
117 * else see whether the index is free
118 * return the major number that is free else -1
119 *
316670eb
A
120 * if index is negative, we start
121 * looking for a free slot at the absolute value of index,
122 * instead of starting at 0
1c79356b
A
123 */
124int
125bdevsw_isfree(int index)
126{
3e170ce0 127 struct bdevsw * devsw;
316670eb
A
128
129 if (index < 0) {
3e170ce0
A
130 if (index == -1)
131 index = 1; /* start at 1 to avoid collision with volfs (Radar 2842228) */
132 else
133 index = -index; /* start at least this far up in the table */
134 devsw = &bdevsw[index];
135 for (; index < nblkdev; index++, devsw++) {
136 if (memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) == 0)
137 break;
138 }
1c79356b 139 }
3e170ce0
A
140
141 if (index < 0 || index >= nblkdev)
142 return (-1);
143
316670eb 144 devsw = &bdevsw[index];
3e170ce0
A
145 if ((memcmp((char *)devsw, (char *)&nobdev, sizeof(struct bdevsw)) != 0)) {
146 return (-1);
1c79356b 147 }
3e170ce0 148 return (index);
1c79356b
A
149}
150
3e170ce0 151/*
1c79356b
A
152 * if index is -1, find a free slot to add
153 * else see whether the slot is free
154 * return the major number that is used else -1
316670eb
A
155 *
156 * if index is negative, we start
157 * looking for a free slot at the absolute value of index,
158 * instead of starting at 0
1c79356b
A
159 */
160int
3e170ce0 161bdevsw_add(int index, struct bdevsw * bsw)
1c79356b 162{
39037602 163 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb
A
164 index = bdevsw_isfree(index);
165 if (index < 0) {
39037602
A
166 index = -1;
167 } else {
168 bdevsw[index] = *bsw;
1c79356b 169 }
39037602 170 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 171 return (index);
1c79356b 172}
316670eb 173/*
1c79356b
A
174 * if the slot has the same bsw, then remove
175 * else -1
176 */
177int
3e170ce0 178bdevsw_remove(int index, struct bdevsw * bsw)
1c79356b 179{
3e170ce0
A
180 struct bdevsw * devsw;
181
182 if (index < 0 || index >= nblkdev)
183 return (-1);
1c79356b
A
184
185 devsw = &bdevsw[index];
39037602 186 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 187 if ((memcmp((char *)devsw, (char *)bsw, sizeof(struct bdevsw)) != 0)) {
39037602
A
188 index = -1;
189 } else {
190 bdevsw[index] = nobdev;
1c79356b 191 }
39037602 192 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 193 return (index);
1c79356b
A
194}
195
3e170ce0 196/*
1c79356b
A
197 * if index is -1, return a free slot if avaliable
198 * else see whether the index is free
199 * return the major number that is free else -1
316670eb
A
200 *
201 * if index is negative, we start
202 * looking for a free slot at the absolute value of index,
203 * instead of starting at 0
1c79356b
A
204 */
205int
206cdevsw_isfree(int index)
207{
3e170ce0 208 struct cdevsw * devsw;
1c79356b 209
316670eb 210 if (index < 0) {
3e170ce0
A
211 if (index == -1)
212 index = 0;
213 else
214 index = -index; /* start at least this far up in the table */
215 devsw = &cdevsw[index];
216 for (; index < nchrdev; index++, devsw++) {
217 if (memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) == 0)
218 break;
219 }
1c79356b 220 }
3e170ce0
A
221
222 if (index < 0 || index >= nchrdev)
223 return (-1);
224
1c79356b 225 devsw = &cdevsw[index];
3e170ce0
A
226 if ((memcmp((char *)devsw, (char *)&nocdev, sizeof(struct cdevsw)) != 0)) {
227 return (-1);
1c79356b 228 }
3e170ce0 229 return (index);
1c79356b
A
230}
231
3e170ce0 232/*
1c79356b
A
233 * if index is -1, find a free slot to add
234 * else see whether the slot is free
235 * return the major number that is used else -1
2d21ac55 236 *
316670eb
A
237 * if index is negative, we start
238 * looking for a free slot at the absolute value of index,
239 * instead of starting at 0
240 *
2d21ac55
A
241 * NOTE: In practice, -1 is unusable, since there are kernel internal
242 * devices that call this function with absolute index values,
243 * which will stomp on free-slot based assignments that happen
316670eb 244 * before them. -24 is currently a safe starting point.
1c79356b
A
245 */
246int
3e170ce0 247cdevsw_add(int index, struct cdevsw * csw)
1c79356b 248{
39037602 249 lck_mtx_lock_spin(&devsw_lock_list_mtx);
316670eb 250 index = cdevsw_isfree(index);
2d21ac55 251 if (index < 0) {
39037602
A
252 index = -1;
253 } else {
254 cdevsw[index] = *csw;
1c79356b 255 }
39037602 256 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 257 return (index);
1c79356b
A
258}
259/*
316670eb 260 * if the slot has the same csw, then remove
1c79356b
A
261 * else -1
262 */
263int
3e170ce0 264cdevsw_remove(int index, struct cdevsw * csw)
1c79356b 265{
3e170ce0
A
266 struct cdevsw * devsw;
267
268 if (index < 0 || index >= nchrdev)
269 return (-1);
1c79356b
A
270
271 devsw = &cdevsw[index];
39037602 272 lck_mtx_lock_spin(&devsw_lock_list_mtx);
3e170ce0 273 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
39037602
A
274 index = -1;
275 } else {
276 cdevsw[index] = nocdev;
277 cdevsw_flags[index] = 0;
1c79356b 278 }
39037602 279 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 280 return (index);
1c79356b
A
281}
282
9bccf70c
A
283static int
284cdev_set_bdev(int cdev, int bdev)
285{
9bccf70c
A
286 return (chrtoblk_set(cdev, bdev));
287}
288
3e170ce0 289int
9bccf70c
A
290cdevsw_add_with_bdev(int index, struct cdevsw * csw, int bdev)
291{
292 index = cdevsw_add(index, csw);
293 if (index < 0) {
294 return (index);
295 }
296 if (cdev_set_bdev(index, bdev) < 0) {
297 cdevsw_remove(index, csw);
298 return (-1);
299 }
300 return (index);
301}
302
6d2010ae 303int
3e170ce0 304cdevsw_setkqueueok(int index, struct cdevsw * csw, int use_offset)
6d2010ae 305{
3e170ce0 306 struct cdevsw * devsw;
6d2010ae
A
307 uint64_t flags = CDEVSW_SELECT_KQUEUE;
308
3e170ce0
A
309 if (index < 0 || index >= nchrdev)
310 return (-1);
311
6d2010ae 312 devsw = &cdevsw[index];
3e170ce0
A
313 if ((memcmp((char *)devsw, (char *)csw, sizeof(struct cdevsw)) != 0)) {
314 return (-1);
6d2010ae
A
315 }
316
317 if (use_offset) {
318 flags |= CDEVSW_USE_OFFSET;
319 }
320
321 cdevsw_flags[index] = flags;
322 return 0;
323}
324
3e170ce0 325#include <pexpert/pexpert.h> /* for PE_parse_boot_arg */
2d21ac55 326
b0d623f7
A
327/*
328 * Copy the "hostname" variable into a caller-provided buffer
329 * Returns: 0 for success, ENAMETOOLONG for insufficient buffer space.
3e170ce0 330 * On success, "len" will be set to the number of characters preceding
b0d623f7
A
331 * the NULL character in the hostname.
332 */
333int
3e170ce0 334bsd_hostname(char * buf, int bufsize, int * len)
b0d623f7
A
335{
336 /*
3e170ce0 337 * "hostname" is null-terminated, and "hostnamelen" is equivalent to strlen(hostname).
b0d623f7
A
338 */
339 if (hostnamelen < bufsize) {
340 strlcpy(buf, hostname, bufsize);
341 *len = hostnamelen;
342 return 0;
343 } else {
344 return ENAMETOOLONG;
3e170ce0 345 }
b0d623f7
A
346}
347
6d2010ae
A
348void
349devsw_lock(dev_t dev, int mode)
350{
351 devsw_lock_t newlock, tmplock;
352 int res;
353
3e170ce0 354 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
355 assert(mode == S_IFCHR || mode == S_IFBLK);
356
357 MALLOC(newlock, devsw_lock_t, sizeof(struct devsw_lock), M_TEMP, M_WAITOK | M_ZERO);
358 newlock->dl_dev = dev;
359 newlock->dl_thread = current_thread();
360 newlock->dl_mode = mode;
3e170ce0 361
6d2010ae
A
362 lck_mtx_lock_spin(&devsw_lock_list_mtx);
363retry:
3e170ce0
A
364 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
365 {
6d2010ae 366 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
3e170ce0 367 res = msleep(tmplock, &devsw_lock_list_mtx, PVFS, "devsw_lock", NULL);
6d2010ae
A
368 assert(res == 0);
369 goto retry;
370 }
371 }
372
373 TAILQ_INSERT_TAIL(&devsw_locks, newlock, dl_list);
374 lck_mtx_unlock(&devsw_lock_list_mtx);
6d2010ae
A
375}
376void
377devsw_unlock(dev_t dev, int mode)
378{
379 devsw_lock_t tmplock;
380
3e170ce0 381 assert(0 <= major(dev) && major(dev) < nchrdev);
6d2010ae
A
382
383 lck_mtx_lock_spin(&devsw_lock_list_mtx);
384
3e170ce0
A
385 TAILQ_FOREACH(tmplock, &devsw_locks, dl_list)
386 {
387 if (tmplock->dl_dev == dev && tmplock->dl_mode == mode) {
6d2010ae
A
388 break;
389 }
390 }
391
392 if (tmplock == NULL) {
393 panic("Trying to unlock, and couldn't find lock.");
394 }
395
396 if (tmplock->dl_thread != current_thread()) {
397 panic("Trying to unlock, but I don't hold the lock.");
398 }
399
400 wakeup(tmplock);
401 TAILQ_REMOVE(&devsw_locks, tmplock, dl_list);
3e170ce0 402
6d2010ae 403 lck_mtx_unlock(&devsw_lock_list_mtx);
3e170ce0 404
6d2010ae
A
405 FREE(tmplock, M_TEMP);
406}
407
408void
409devsw_init()
410{
411 devsw_lock_grp = lck_grp_alloc_init("devsw", NULL);
412 assert(devsw_lock_grp != NULL);
413
414 lck_mtx_init(&devsw_lock_list_mtx, devsw_lock_grp, NULL);
415 TAILQ_INIT(&devsw_locks);
416}