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