]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_panicinfo.c
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <sys/param.h>
24 #include <sys/fcntl.h>
25 #include <sys/malloc.h>
27 #include <sys/sysctl.h>
28 #include <sys/vnode.h>
30 #include <sys/systm.h>
32 #include <mach/mach_types.h>
33 #include <mach/kern_return.h>
34 #include <kern/kern_types.h>
35 #include <vm/vm_kern.h>
38 /* prototypes not exported by osfmk/console. */
39 extern void panic_dialog_test( void );
40 extern int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
41 extern void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
43 /* make the compiler happy */
44 extern int sysctl_dopanicinfo(int *, u_int
, user_addr_t
, size_t *, user_addr_t
, size_t, struct proc
*);
47 #define PANIC_IMAGE_SIZE_LIMIT (32 * 4096) /* 128K - Maximum amount of memory consumed for the panic UI */
48 #define KERN_PANICINFO_TEST (KERN_PANICINFO_IMAGE+2) /* Allow the panic UI to be tested by root without causing a panic */
51 static int image_size_limit
= PANIC_IMAGE_SIZE_LIMIT
;
53 __private_extern__
int
54 sysctl_dopanicinfo(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
64 vm_offset_t newimage
= (vm_offset_t
)NULL
;
66 unsigned char * prev_image_ptr
;
67 unsigned int prev_image_size
;
70 /* all sysctl names at this level are terminal */
72 return (ENOTDIR
); /* overloaded */
74 if ( (error
= proc_suser(p
)) ) /* must be super user to muck with image */
81 case KERN_PANICINFO_TEST
:
86 case KERN_PANICINFO_MAXSIZE
:
88 /* return the image size limits */
91 newp
= USER_ADDR_NULL
;
93 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &image_size_limit
);
97 case KERN_PANICINFO_IMAGE
:
99 /* If we have a new image, allocate wired kernel memory and copy it in from user space */
100 if ( newp
!= USER_ADDR_NULL
) {
102 /* check the length of the incoming image before allocating space for it. */
103 if ( newlen
> (size_t)image_size_limit
)
106 /* allocate some kernel wired memory for the new image */
107 kret
= kmem_alloc(kernel_map
, &newimage
, (vm_size_t
)round_page_32(newlen
));
109 if (kret
!= KERN_SUCCESS
) {
115 case KERN_RESOURCE_SHORTAGE
:
118 case KERN_PROTECTION_FAILURE
:
126 /* copy the image in from user space */
127 if ( (error
= copyin(newp
, (char *) newimage
, newlen
)) )
130 } else { /* setup to make the default image active */
132 newimage
= (vm_offset_t
)NULL
;
136 /* get the current image location and size */
137 panic_dialog_get_image( &prev_image_ptr
, &prev_image_size
);
139 /* did the caller request a copy of the previous image ? */
140 if ( oldp
!= USER_ADDR_NULL
) {
141 if ( *oldlenp
< prev_image_size
) {
146 /* copy the image to user space or zero the size if the default image is active */
147 if ( prev_image_ptr
!= NULL
) {
148 if ( (error
= copyout( prev_image_ptr
, oldp
, prev_image_size
)) )
151 *oldlenp
= prev_image_size
;
153 else /* tell the user that the default image is active */
157 /* Make the new image active, or reactivate the default image.
158 But, handle the special case of asking for the current image
159 without changing the current image.
162 if ( !(oldp
&& newp
== USER_ADDR_NULL
) ) {
163 if ( (error
= panic_dialog_set_image( (unsigned char *) newimage
, newlen
)) )
166 /* free the wired memory used by the previous image */
167 if ( prev_image_ptr
!= NULL
) {
168 (void)kmem_free(kernel_map
, (vm_offset_t
) prev_image_ptr
, (vm_size_t
)round_page_32(prev_image_size
));
169 printf("Panic UI memory freed (%d)\n", round_page_32(prev_image_size
));
176 if ( newimage
!= (vm_offset_t
)NULL
)
177 (void)kmem_free(kernel_map
, newimage
, (vm_size_t
)round_page_32(newlen
));