]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_panicinfo.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / bsd / kern / kern_panicinfo.c
CommitLineData
9bccf70c
A
1/*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
9bccf70c 5 *
8ad349bb
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
9bccf70c
A
29 */
30
31#include <sys/param.h>
32#include <sys/fcntl.h>
33#include <sys/malloc.h>
9bccf70c 34#include <sys/proc.h>
9bccf70c
A
35#include <sys/sysctl.h>
36#include <sys/vnode.h>
37#include <sys/vm.h>
91447636 38#include <sys/systm.h>
9bccf70c 39
91447636 40#include <mach/mach_types.h>
9bccf70c 41#include <mach/kern_return.h>
91447636
A
42#include <kern/kern_types.h>
43#include <vm/vm_kern.h>
9bccf70c 44
9bccf70c 45
91447636
A
46/* prototypes not exported by osfmk/console. */
47extern void panic_dialog_test( void );
48extern int panic_dialog_set_image( const unsigned char * ptr, unsigned int size );
49extern void panic_dialog_get_image( unsigned char ** ptr, unsigned int * size );
9bccf70c 50
91447636
A
51/* make the compiler happy */
52extern int sysctl_dopanicinfo(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, struct proc *);
9bccf70c 53
9bccf70c 54
91447636
A
55#define PANIC_IMAGE_SIZE_LIMIT (32 * 4096) /* 128K - Maximum amount of memory consumed for the panic UI */
56#define KERN_PANICINFO_TEST (KERN_PANICINFO_IMAGE+2) /* Allow the panic UI to be tested by root without causing a panic */
9bccf70c 57
91447636
A
58/* Local data */
59static int image_size_limit = PANIC_IMAGE_SIZE_LIMIT;
9bccf70c
A
60
61__private_extern__ int
62sysctl_dopanicinfo(name, namelen, oldp, oldlenp, newp, newlen, p)
63 int *name;
64 u_int namelen;
91447636 65 user_addr_t oldp;
9bccf70c 66 size_t *oldlenp;
91447636 67 user_addr_t newp;
9bccf70c
A
68 size_t newlen;
69 struct proc *p;
70{
71 int error = 0;
91447636
A
72 vm_offset_t newimage = (vm_offset_t )NULL;
73 kern_return_t kret;
74 unsigned char * prev_image_ptr;
75 unsigned int prev_image_size;
76
9bccf70c
A
77
78 /* all sysctl names at this level are terminal */
79 if (namelen != 1)
80 return (ENOTDIR); /* overloaded */
81
91447636
A
82 if ( (error = proc_suser(p)) ) /* must be super user to muck with image */
83 return (error);
84
9bccf70c
A
85 switch (name[0]) {
86 default:
91447636
A
87 return (ENOTSUP);
88
89 case KERN_PANICINFO_TEST:
90
91 panic_dialog_test();
92 return (0);
93
9bccf70c 94 case KERN_PANICINFO_MAXSIZE:
91447636
A
95
96 /* return the image size limits */
97
98 newlen = 0;
99 newp = USER_ADDR_NULL;
100
101 error = sysctl_int(oldp, oldlenp, newp, newlen, &image_size_limit);
102
9bccf70c
A
103 return (error);
104
91447636
A
105 case KERN_PANICINFO_IMAGE:
106
107 /* If we have a new image, allocate wired kernel memory and copy it in from user space */
108 if ( newp != USER_ADDR_NULL ) {
109
110 /* check the length of the incoming image before allocating space for it. */
111 if ( newlen > (size_t)image_size_limit )
112 return (ENOMEM);
113
114 /* allocate some kernel wired memory for the new image */
115 kret = kmem_alloc(kernel_map, &newimage, (vm_size_t)round_page_32(newlen));
116
117 if (kret != KERN_SUCCESS) {
118 switch (kret) {
119 default:
120 error = EINVAL;
121 break;
122 case KERN_NO_SPACE:
123 case KERN_RESOURCE_SHORTAGE:
124 error = ENOMEM;
125 break;
126 case KERN_PROTECTION_FAILURE:
127 error = EPERM;
128 break;
129 }
130
131 return (error);
132 }
133
134 /* copy the image in from user space */
135 if ( (error = copyin(newp, (char *) newimage, newlen)) )
9bccf70c
A
136 goto errout;
137
91447636
A
138 } else { /* setup to make the default image active */
139
140 newimage = (vm_offset_t )NULL;
141 newlen = 0;
142 }
143
144 /* get the current image location and size */
145 panic_dialog_get_image( &prev_image_ptr, &prev_image_size );
146
147 /* did the caller request a copy of the previous image ? */
148 if ( oldp != USER_ADDR_NULL ) {
149 if ( *oldlenp < prev_image_size ) {
150 error = ERANGE;
151 goto errout;
9bccf70c
A
152 }
153
91447636
A
154 /* copy the image to user space or zero the size if the default image is active */
155 if ( prev_image_ptr != NULL ) {
156 if ( (error = copyout( prev_image_ptr, oldp, prev_image_size )) )
157 goto errout;
9bccf70c 158
91447636
A
159 *oldlenp = prev_image_size;
160 }
161 else /* tell the user that the default image is active */
162 *oldlenp = 0;
163 }
9bccf70c 164
91447636
A
165 /* Make the new image active, or reactivate the default image.
166 But, handle the special case of asking for the current image
167 without changing the current image.
168 */
9bccf70c 169
91447636
A
170 if ( !(oldp && newp == USER_ADDR_NULL) ) {
171 if ( (error = panic_dialog_set_image( (unsigned char *) newimage, newlen )) )
172 goto errout;
9bccf70c 173
91447636
A
174 /* free the wired memory used by the previous image */
175 if ( prev_image_ptr != NULL ) {
176 (void)kmem_free(kernel_map, (vm_offset_t) prev_image_ptr, (vm_size_t)round_page_32(prev_image_size));
177 printf("Panic UI memory freed (%d)\n", round_page_32(prev_image_size));
178 }
9bccf70c 179 }
91447636
A
180
181 return (0);
182
9bccf70c 183errout:
91447636
A
184 if ( newimage != (vm_offset_t )NULL )
185 (void)kmem_free(kernel_map, newimage, (vm_size_t)round_page_32(newlen));
186
9bccf70c
A
187 return (error);
188 }
189}