2 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/fcntl.h>
31 #include <sys/malloc.h>
33 #include <sys/sysctl.h>
34 #include <sys/vnode.h>
36 #include <sys/systm.h>
38 #include <mach/mach_types.h>
39 #include <mach/kern_return.h>
40 #include <kern/kern_types.h>
41 #include <vm/vm_kern.h>
44 /* prototypes not exported by osfmk/console. */
45 extern void panic_dialog_test( void );
46 extern void noroot_icon_test(void);
47 extern int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
48 extern void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
50 /* make the compiler happy */
51 static int sysctl_dopanicinfo SYSCTL_HANDLER_ARGS
;
54 #define PANIC_IMAGE_SIZE_LIMIT (32 * 4096) /* 128K - Maximum amount of memory consumed for the panic UI */
57 static int image_size_limit
= PANIC_IMAGE_SIZE_LIMIT
;
59 /* XXX Should be STATIC for dtrace debugging.. */
61 sysctl_dopanicinfo SYSCTL_HANDLER_ARGS
63 __unused
int cmd
= oidp
->oid_arg2
; /* subcommand*/
64 int *name
= arg1
; /* oid element argument vector */
65 int namelen
= arg2
; /* number of oid element arguments */
66 user_addr_t oldp
= req
->oldptr
; /* user buffer copy out address */
67 size_t *oldlenp
= &req
->oldlen
; /* user buffer copy out size */
68 user_addr_t newp
= req
->newptr
; /* user buffer copy in address */
69 size_t newlen
= req
->newlen
; /* user buffer copy in size */
71 proc_t p
= current_proc();
73 vm_offset_t newimage
= (vm_offset_t
)NULL
;
75 unsigned char * prev_image_ptr
;
76 unsigned int prev_image_size
;
78 /* all sysctl names at this level are terminal */
80 return (ENOTDIR
); /* overloaded */
82 /* must be super user to muck with image */
83 if ( (error
= proc_suser(p
)) )
90 case KERN_PANICINFO_TEST
:
95 case KERN_PANICINFO_NOROOT_TEST
:
96 printf("Testing noroot icon \n");
101 case KERN_PANICINFO_MAXSIZE
:
103 /* return the image size limits */
106 newp
= USER_ADDR_NULL
;
108 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &image_size_limit
);
112 case KERN_PANICINFO_IMAGE
:
114 /* If we have a new image, allocate wired kernel memory and copy it in from user space */
115 if ( newp
!= USER_ADDR_NULL
) {
117 /* check the length of the incoming image before allocating space for it. */
118 if ( newlen
> (size_t)image_size_limit
) {
123 /* allocate some kernel wired memory for the new image */
124 kret
= kmem_alloc(kernel_map
, &newimage
, (vm_size_t
)round_page(newlen
));
126 if (kret
!= KERN_SUCCESS
) {
132 case KERN_RESOURCE_SHORTAGE
:
135 case KERN_PROTECTION_FAILURE
:
142 /* copy the image in from user space */
143 if ( (error
= copyin(newp
, (char *) newimage
, newlen
)) )
146 } else { /* setup to make the default image active */
148 newimage
= (vm_offset_t
)NULL
;
152 /* get the current image location and size */
153 panic_dialog_get_image( &prev_image_ptr
, &prev_image_size
);
155 /* did the caller request a copy of the previous image ? */
156 if ( oldp
!= USER_ADDR_NULL
) {
157 if ( *oldlenp
< prev_image_size
) {
162 /* copy the image to user space or zero the size if the default image is active */
163 if ( prev_image_ptr
!= NULL
) {
164 if ( (error
= copyout( prev_image_ptr
, oldp
, prev_image_size
)) )
167 *oldlenp
= prev_image_size
;
169 else /* tell the user that the default image is active */
173 /* Make the new image active, or reactivate the default image.
174 But, handle the special case of asking for the current image
175 without changing the current image.
178 if ( !(oldp
&& newp
== USER_ADDR_NULL
) ) {
179 if ( (error
= panic_dialog_set_image( (unsigned char *) newimage
, newlen
)) )
182 /* free the wired memory used by the previous image */
183 if ( prev_image_ptr
!= NULL
) {
184 (void)kmem_free(kernel_map
, (vm_offset_t
) prev_image_ptr
, (vm_size_t
)round_page(prev_image_size
));
185 printf("Panic UI memory freed (%p)\n", (void *)round_page(prev_image_size
));
192 if ( newimage
!= (vm_offset_t
)NULL
)
193 (void)kmem_free(kernel_map
, newimage
, (vm_size_t
)round_page(newlen
));
198 /* adjust index so we return the right required/consumed amount */
200 req
->oldidx
+= req
->oldlen
;
204 SYSCTL_PROC(_kern
, KERN_PANICINFO
, panicinfo
, CTLTYPE_NODE
|CTLFLAG_RW
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
,
205 0, /* Pointer argument (arg1) */
206 0, /* Integer argument (arg2) */
207 sysctl_dopanicinfo
, /* Handler function */
208 NULL
, /* Data pointer */