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