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