1 | /* |
2 | * Copyright (c) 2000-2019 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
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. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
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. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | #ifndef _PEXPERT_PEXPERT_H_ |
29 | #define _PEXPERT_PEXPERT_H_ |
30 | |
31 | #include <sys/cdefs.h> |
32 | |
33 | #ifdef KERNEL |
34 | #include <IOKit/IOInterrupts.h> |
35 | #include <kern/kern_types.h> |
36 | #endif |
37 | |
38 | #if XNU_KERNEL_PRIVATE |
39 | #include <libkern/kernel_mach_header.h> |
40 | #endif |
41 | |
42 | __BEGIN_DECLS |
43 | #include <mach/boolean.h> |
44 | #include <mach/kern_return.h> |
45 | #include <mach/machine/vm_types.h> |
46 | |
47 | #ifdef PEXPERT_KERNEL_PRIVATE |
48 | #include <pexpert/protos.h> |
49 | #endif |
50 | #include <pexpert/boot.h> |
51 | |
52 | #if defined(PEXPERT_KERNEL_PRIVATE) || defined(IOKIT_KERNEL_PRIVATE) |
53 | typedef void *cpu_id_t; |
54 | #else |
55 | typedef void *cpu_id_t; |
56 | #endif |
57 | |
58 | #if XNU_KERNEL_PRIVATE |
59 | #if defined(__arm__) || defined(__arm64__) |
60 | extern struct embedded_panic_header *panic_info; |
61 | extern vm_offset_t gPanicBase; |
62 | extern unsigned int gPanicSize; |
63 | |
64 | /* |
65 | * If invoked with NULL first argument, return the max buffer size that can |
66 | * be saved in the second argument |
67 | */ |
68 | void PE_update_panic_crc( |
69 | unsigned char *, |
70 | unsigned int *); |
71 | |
72 | #else /* defined(__arm__) || defined(__arm64__) */ |
73 | extern struct macos_panic_header *panic_info; |
74 | #endif /* defined(__arm__) || defined(__arm64__) */ |
75 | #endif /* XNU_KERNEL_PRIVATE */ |
76 | |
77 | extern void lpss_uart_enable(boolean_t on_off); |
78 | |
79 | void PE_enter_debugger( |
80 | const char *cause); |
81 | |
82 | void PE_init_platform( |
83 | boolean_t vm_initialized, |
84 | void *args); |
85 | |
86 | /* |
87 | * Copies the requested number of bytes from the "random-seed" property in |
88 | * the device tree, and zeros the corresponding bytes in the device tree. |
89 | * Returns the number of bytes actually copied. |
90 | */ |
91 | uint32_t PE_get_random_seed( |
92 | unsigned char * dst_random_seed, |
93 | uint32_t request_size); |
94 | |
95 | uint32_t PE_i_can_has_debugger( |
96 | uint32_t *); |
97 | |
98 | int PE_stub_poll_input(unsigned int options, char *c); |
99 | |
100 | #if defined(__arm__) || defined(__arm64__) |
101 | boolean_t PE_panic_debugging_enabled(void); |
102 | |
103 | void PE_mark_hwaccess(uint64_t thread); |
104 | |
105 | #if XNU_KERNEL_PRIVATE |
106 | /* |
107 | * Return whether the boot CPU has gotten far enough to initialize the |
108 | * debug and trace infrastructure; this indicates whether it's safe to |
109 | * take the full path through the debugger on a panic(), or whether we |
110 | * need to take a restricted path and spin forever. |
111 | */ |
112 | boolean_t PE_arm_debug_and_trace_initialized(void); |
113 | #endif /* XNU_KERNEL_PRIVATE */ |
114 | #endif /* defined(__arm__) || defined(__arm64__) */ |
115 | |
116 | /* Return the offset of the specified address into the panic region */ |
117 | uint32_t PE_get_offset_into_panic_region( |
118 | char *location); |
119 | |
120 | /* Zeroes the panic header, sets the panic magic and initializes the header to be used */ |
121 | void ( |
122 | void); |
123 | |
124 | /* Updates the panic header during a nested panic */ |
125 | void ( |
126 | void); |
127 | |
128 | /* Invokes AppleARMIO::handlePlatformError() if present */ |
129 | bool PE_handle_platform_error( |
130 | vm_offset_t far); |
131 | |
132 | #if KERNEL_PRIVATE |
133 | |
134 | /* |
135 | * Kexts should consult this bitmask to change behavior, since the kernel |
136 | * may be configured as RELEASE but have MACH_ASSERT enabled, or boot args |
137 | * may have changed the kernel behavior for statistics and kexts should |
138 | * participate similarly |
139 | */ |
140 | |
141 | #define kPEICanHasAssertions 0x00000001 /* Exceptional conditions should panic() instead of printf() */ |
142 | #define kPEICanHasStatistics 0x00000002 /* Gather expensive statistics (that don't otherwise change behavior */ |
143 | #define kPEICanHasDiagnosticAPI 0x00000004 /* Vend API to userspace or kexts that introspect kernel state */ |
144 | |
145 | extern uint32_t PE_i_can_has_kernel_configuration(void); |
146 | |
147 | #endif /* KERNEL_PRIVATE */ |
148 | |
149 | extern int32_t gPESerialBaud; |
150 | |
151 | extern uint8_t gPlatformECID[8]; |
152 | |
153 | extern uint32_t gPlatformMemoryID; |
154 | |
155 | unsigned int PE_init_taproot(vm_offset_t *taddr); |
156 | |
157 | extern void (*PE_kputc)(char c); |
158 | |
159 | void PE_init_printf( |
160 | boolean_t vm_initialized); |
161 | |
162 | extern void (*PE_putc)(char c); |
163 | |
164 | /* |
165 | * Perform pre-lockdown IOKit initialization. |
166 | * This is guaranteed to execute prior to machine_lockdown(). |
167 | * The precise operations performed by this function depend upon |
168 | * the security model employed by the platform, but in general this |
169 | * function should be expected to at least perform basic C++ runtime |
170 | * and I/O registry initialization. |
171 | */ |
172 | void PE_init_iokit( |
173 | void); |
174 | |
175 | /* |
176 | * Perform post-lockdown IOKit initialization. |
177 | * This is guaranteed to execute after machine_lockdown(). |
178 | * The precise operations performed by this function depend upon |
179 | * the security model employed by the platform. For example, if |
180 | * the platform treats machine_lockdown() as a strict security |
181 | * checkpoint, general-purpose IOKit matching may not begin until |
182 | * this function is called. |
183 | */ |
184 | void PE_lockdown_iokit( |
185 | void); |
186 | |
187 | struct clock_frequency_info_t { |
188 | unsigned long bus_clock_rate_hz; |
189 | unsigned long cpu_clock_rate_hz; |
190 | unsigned long dec_clock_rate_hz; |
191 | unsigned long bus_clock_rate_num; |
192 | unsigned long bus_clock_rate_den; |
193 | unsigned long bus_to_cpu_rate_num; |
194 | unsigned long bus_to_cpu_rate_den; |
195 | unsigned long bus_to_dec_rate_num; |
196 | unsigned long bus_to_dec_rate_den; |
197 | unsigned long timebase_frequency_hz; |
198 | unsigned long timebase_frequency_num; |
199 | unsigned long timebase_frequency_den; |
200 | unsigned long long bus_frequency_hz; |
201 | unsigned long long bus_frequency_min_hz; |
202 | unsigned long long bus_frequency_max_hz; |
203 | unsigned long long cpu_frequency_hz; |
204 | unsigned long long cpu_frequency_min_hz; |
205 | unsigned long long cpu_frequency_max_hz; |
206 | unsigned long long prf_frequency_hz; |
207 | unsigned long long prf_frequency_min_hz; |
208 | unsigned long long prf_frequency_max_hz; |
209 | unsigned long long mem_frequency_hz; |
210 | unsigned long long mem_frequency_min_hz; |
211 | unsigned long long mem_frequency_max_hz; |
212 | unsigned long long fix_frequency_hz; |
213 | }; |
214 | |
215 | extern int debug_cpu_performance_degradation_factor; |
216 | |
217 | typedef struct clock_frequency_info_t clock_frequency_info_t; |
218 | |
219 | extern clock_frequency_info_t gPEClockFrequencyInfo; |
220 | |
221 | struct timebase_freq_t { |
222 | unsigned long timebase_num; |
223 | unsigned long timebase_den; |
224 | }; |
225 | |
226 | typedef void (*timebase_callback_func)(struct timebase_freq_t *timebase_freq); |
227 | |
228 | void PE_register_timebase_callback(timebase_callback_func callback); |
229 | |
230 | void PE_call_timebase_callback(void); |
231 | |
232 | #ifdef KERNEL |
233 | void PE_install_interrupt_handler( |
234 | void *nub, int source, |
235 | void *target, IOInterruptHandler handler, void *refCon); |
236 | #endif |
237 | |
238 | extern bool disable_serial_output; |
239 | extern bool disable_kprintf_output; |
240 | |
241 | #ifndef _FN_KPRINTF |
242 | #define _FN_KPRINTF |
243 | void kprintf(const char *fmt, ...) __printflike(1, 2); |
244 | #endif |
245 | |
246 | #if KERNEL_PRIVATE |
247 | void _consume_kprintf_args(int, ...); |
248 | #endif |
249 | |
250 | #if CONFIG_NO_KPRINTF_STRINGS |
251 | #if KERNEL_PRIVATE |
252 | #define kprintf(x, ...) _consume_kprintf_args( 0, ## __VA_ARGS__ ) |
253 | #else |
254 | #define kprintf(x, ...) do {} while (0) |
255 | #endif |
256 | #endif |
257 | |
258 | void init_display_putc(unsigned char *baseaddr, int rowbytes, int height); |
259 | void display_putc(char c); |
260 | |
261 | enum { |
262 | kPEReadTOD, |
263 | kPEWriteTOD |
264 | }; |
265 | |
266 | enum { |
267 | kPEWaitForInput = 0x00000001, |
268 | kPERawInput = 0x00000002 |
269 | }; |
270 | |
271 | /* Private Stuff - eventually put in pexpertprivate.h */ |
272 | enum { |
273 | kDebugTypeNone = 0, |
274 | kDebugTypeDisplay = 1, |
275 | kDebugTypeSerial = 2 |
276 | }; |
277 | |
278 | /* Scale factor values for PE_Video.v_scale */ |
279 | enum { |
280 | kPEScaleFactorUnknown = 0, |
281 | kPEScaleFactor1x = 1, |
282 | kPEScaleFactor2x = 2 |
283 | }; |
284 | |
285 | struct PE_Video { |
286 | unsigned long v_baseAddr; /* Base address of video memory */ |
287 | unsigned long v_rowBytes; /* Number of bytes per pixel row */ |
288 | unsigned long v_width; /* Width */ |
289 | unsigned long v_height; /* Height */ |
290 | unsigned long v_depth; /* Pixel Depth */ |
291 | unsigned long v_display; /* Text or Graphics */ |
292 | char v_pixelFormat[64]; |
293 | unsigned long v_offset; /* offset into video memory to start at */ |
294 | unsigned long v_length; /* length of video memory (0 for v_rowBytes * v_height) */ |
295 | unsigned char v_rotate; /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */ |
296 | unsigned char v_scale; /* Scale Factor for both X & Y */ |
297 | char reserved1[2]; |
298 | #ifdef __LP64__ |
299 | long reserved2; |
300 | #else |
301 | long v_baseAddrHigh; |
302 | #endif |
303 | }; |
304 | |
305 | typedef struct PE_Video PE_Video; |
306 | |
307 | extern void initialize_screen(PE_Video *, unsigned int); |
308 | |
309 | extern void dim_screen(void); |
310 | |
311 | extern int PE_current_console( |
312 | PE_Video *info); |
313 | |
314 | extern void PE_create_console( |
315 | void); |
316 | |
317 | extern int PE_initialize_console( |
318 | PE_Video *newInfo, |
319 | int op); |
320 | |
321 | #define kPEGraphicsMode 1 |
322 | #define kPETextMode 2 |
323 | #define kPETextScreen 3 |
324 | #define kPEAcquireScreen 4 |
325 | #define kPEReleaseScreen 5 |
326 | #define kPEEnableScreen 6 |
327 | #define kPEDisableScreen 7 |
328 | #define kPEBaseAddressChange 8 |
329 | #define kPERefreshBootGraphics 9 |
330 | |
331 | extern void PE_display_icon( unsigned int flags, |
332 | const char * name ); |
333 | |
334 | typedef struct PE_state { |
335 | boolean_t initialized; |
336 | PE_Video video; |
337 | void *deviceTreeHead; |
338 | void *bootArgs; |
339 | vm_size_t deviceTreeSize; |
340 | } PE_state_t; |
341 | |
342 | extern PE_state_t PE_state; |
343 | |
344 | extern char * PE_boot_args( |
345 | void); |
346 | |
347 | extern boolean_t PE_parse_boot_argn( |
348 | const char *arg_string, |
349 | void *arg_ptr, |
350 | int max_arg); |
351 | |
352 | extern boolean_t PE_boot_arg_uint64_eq(const char *arg_string, uint64_t value); |
353 | |
354 | #if XNU_KERNEL_PRIVATE |
355 | extern boolean_t PE_parse_boot_arg_str( |
356 | const char *arg_string, |
357 | char * arg_ptr, |
358 | int size); |
359 | #endif /* XNU_KERNEL_PRIVATE */ |
360 | |
361 | extern boolean_t PE_get_default( |
362 | const char *property_name, |
363 | void *property_ptr, |
364 | unsigned int max_property); |
365 | |
366 | #define PE_default_value(_key, _variable, _default) \ |
367 | do { \ |
368 | if (!PE_get_default((_key), &(_variable), sizeof(_variable))) \ |
369 | _variable = _default; \ |
370 | } while(0) |
371 | |
372 | enum { |
373 | kPEOptionKey = 0x3a, |
374 | kPECommandKey = 0x37, |
375 | kPEControlKey = 0x36, |
376 | kPEShiftKey = 0x38 |
377 | }; |
378 | |
379 | extern boolean_t PE_get_hotkey( |
380 | unsigned char key); |
381 | |
382 | extern kern_return_t PE_cpu_start( |
383 | cpu_id_t target, |
384 | vm_offset_t start_paddr, |
385 | vm_offset_t arg_paddr); |
386 | |
387 | extern void PE_cpu_halt( |
388 | cpu_id_t target); |
389 | |
390 | extern bool PE_cpu_down( |
391 | cpu_id_t target); |
392 | |
393 | extern void PE_cpu_signal( |
394 | cpu_id_t source, |
395 | cpu_id_t target); |
396 | |
397 | extern void PE_cpu_signal_deferred( |
398 | cpu_id_t source, |
399 | cpu_id_t target); |
400 | |
401 | extern void PE_cpu_signal_cancel( |
402 | cpu_id_t source, |
403 | cpu_id_t target); |
404 | |
405 | extern void PE_cpu_machine_init( |
406 | cpu_id_t target, |
407 | boolean_t bootb); |
408 | |
409 | extern void PE_cpu_machine_quiesce( |
410 | cpu_id_t target); |
411 | |
412 | extern void pe_init_debug(void); |
413 | |
414 | extern boolean_t PE_imgsrc_mount_supported(void); |
415 | |
416 | extern void PE_panic_hook(const char *str); |
417 | |
418 | extern void PE_init_cpu(void); |
419 | |
420 | extern void PE_handle_ext_interrupt(void); |
421 | |
422 | extern void PE_cpu_power_enable(int cpu_id); |
423 | |
424 | extern void PE_cpu_power_disable(int cpu_id); |
425 | |
426 | /* This has no locking to prevent races, so it is only used in the panic path */ |
427 | extern bool PE_cpu_power_check_kdp(int cpu_id); |
428 | |
429 | extern void PE_singlestep_hook(void); |
430 | |
431 | #if defined(__arm__) || defined(__arm64__) |
432 | typedef void (*perfmon_interrupt_handler_func)(cpu_id_t source); |
433 | extern kern_return_t PE_cpu_perfmon_interrupt_install_handler(perfmon_interrupt_handler_func handler); |
434 | extern void PE_cpu_perfmon_interrupt_enable(cpu_id_t target, boolean_t enable); |
435 | |
436 | #if DEVELOPMENT || DEBUG |
437 | /* panic_trace boot-arg modes */ |
438 | __options_decl(panic_trace_t, uint32_t, { |
439 | panic_trace_disabled = 0x00000000, |
440 | panic_trace_unused = 0x00000001, |
441 | panic_trace_enabled = 0x00000002, |
442 | panic_trace_alt_enabled = 0x00000010, |
443 | panic_trace_partial_policy = 0x00000020, |
444 | }); |
445 | extern panic_trace_t panic_trace; |
446 | |
447 | extern void PE_arm_debug_enable_trace(bool should_kprintf); |
448 | extern void (*PE_arm_debug_panic_hook)(const char *str); |
449 | #else |
450 | extern void(*const PE_arm_debug_panic_hook)(const char *str); |
451 | #endif |
452 | #endif |
453 | |
454 | |
455 | typedef enum kc_kind { |
456 | KCKindNone = -1, |
457 | KCKindUnknown = 0, |
458 | KCKindPrimary = 1, |
459 | KCKindPageable = 2, |
460 | KCKindAuxiliary = 3, |
461 | KCNumKinds = 4, |
462 | } kc_kind_t; |
463 | |
464 | typedef enum kc_format { |
465 | KCFormatUnknown = 0, |
466 | KCFormatStatic = 1, |
467 | KCFormatDynamic = 2, |
468 | KCFormatFileset = 3, |
469 | KCFormatKCGEN = 4, |
470 | } kc_format_t; |
471 | |
472 | #if XNU_KERNEL_PRIVATE |
473 | /* set the mach-o header for a given KC type */ |
474 | extern void (kc_kind_t type, kernel_mach_header_t *, uintptr_t slide); |
475 | void (kc_kind_t type); |
476 | /* set both lowest VA (base) and mach-o header for a given KC type */ |
477 | extern void PE_set_kc_header_and_base(kc_kind_t type, kernel_mach_header_t *, void *base, uintptr_t slide); |
478 | /* The highest non-LINKEDIT virtual address */ |
479 | extern vm_offset_t kc_highest_nonlinkedit_vmaddr; |
480 | /* whether this is an srd enabled device */ |
481 | extern uint32_t PE_srd_fused; |
482 | #endif |
483 | /* returns a pointer to the mach-o header for a give KC type, returns NULL if nothing's been set */ |
484 | extern void *(kc_kind_t type); |
485 | /* returns a pointer to the lowest VA of of the KC of the given type */ |
486 | extern void *PE_get_kc_baseaddress(kc_kind_t type); |
487 | /* returns an array of length KCNumKinds of the lowest VAs of each KC type - members could be NULL */ |
488 | extern const void * const*PE_get_kc_base_pointers(void); |
489 | /* returns the slide for the kext collection */ |
490 | extern uintptr_t PE_get_kc_slide(kc_kind_t type); |
491 | /* quickly accesss the format of the primary kc */ |
492 | extern bool PE_get_primary_kc_format(kc_format_t *type); |
493 | /* gets format of KC of the given type */ |
494 | extern bool PE_get_kc_format(kc_kind_t type, kc_format_t *format); |
495 | /* set vnode ptr for kc fileset */ |
496 | extern void PE_set_kc_vp(kc_kind_t type, void *vp); |
497 | /* quickly set vnode ptr for kc fileset */ |
498 | void * PE_get_kc_vp(kc_kind_t type); |
499 | /* drop reference to kc fileset vnodes */ |
500 | void PE_reset_all_kc_vp(void); |
501 | |
502 | #if KERNEL_PRIVATE |
503 | #if defined(__arm64__) |
504 | extern uint8_t PE_smc_stashed_x86_power_state; |
505 | extern uint8_t PE_smc_stashed_x86_efi_boot_state; |
506 | extern uint8_t PE_smc_stashed_x86_system_state; |
507 | extern uint8_t PE_smc_stashed_x86_shutdown_cause; |
508 | extern uint64_t PE_smc_stashed_x86_prev_power_transitions; |
509 | extern uint32_t PE_pcie_stashed_link_state; |
510 | extern uint64_t PE_nvram_stashed_x86_macos_slide; |
511 | #endif |
512 | |
513 | boolean_t PE_reboot_on_panic(void); |
514 | void PE_sync_panic_buffers(void); |
515 | |
516 | typedef struct PE_panic_save_context { |
517 | void *psc_buffer; |
518 | uint32_t psc_offset; |
519 | uint32_t psc_length; |
520 | } PE_panic_save_context_t; |
521 | #endif |
522 | |
523 | extern vm_size_t PE_init_socd_client(void); |
524 | extern void PE_write_socd_client_buffer(vm_offset_t offset, const void *buff, vm_size_t size); |
525 | |
526 | __END_DECLS |
527 | |
528 | #endif /* _PEXPERT_PEXPERT_H_ */ |
529 | |