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)
53typedef void *cpu_id_t;
54#else
55typedef void *cpu_id_t;
56#endif
57
58#if XNU_KERNEL_PRIVATE
59#if defined(__arm__) || defined(__arm64__)
60extern struct embedded_panic_header *panic_info;
61extern vm_offset_t gPanicBase;
62extern 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 */
68void PE_update_panic_crc(
69 unsigned char *,
70 unsigned int *);
71
72#else /* defined(__arm__) || defined(__arm64__) */
73extern struct macos_panic_header *panic_info;
74#endif /* defined(__arm__) || defined(__arm64__) */
75#endif /* XNU_KERNEL_PRIVATE */
76
77extern void lpss_uart_enable(boolean_t on_off);
78
79void PE_enter_debugger(
80 const char *cause);
81
82void 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 */
91uint32_t PE_get_random_seed(
92 unsigned char * dst_random_seed,
93 uint32_t request_size);
94
95uint32_t PE_i_can_has_debugger(
96 uint32_t *);
97
98int PE_stub_poll_input(unsigned int options, char *c);
99
100#if defined(__arm__) || defined(__arm64__)
101boolean_t PE_panic_debugging_enabled(void);
102
103void 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 */
112boolean_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 */
117uint32_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 */
121void PE_init_panicheader(
122 void);
123
124/* Updates the panic header during a nested panic */
125void PE_update_panicheader_nestedpanic(
126 void);
127
128/* Invokes AppleARMIO::handlePlatformError() if present */
129bool 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
145extern uint32_t PE_i_can_has_kernel_configuration(void);
146
147#endif /* KERNEL_PRIVATE */
148
149extern int32_t gPESerialBaud;
150
151extern uint8_t gPlatformECID[8];
152
153extern uint32_t gPlatformMemoryID;
154
155unsigned int PE_init_taproot(vm_offset_t *taddr);
156
157extern void (*PE_kputc)(char c);
158
159void PE_init_printf(
160 boolean_t vm_initialized);
161
162extern 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 */
172void 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 */
184void PE_lockdown_iokit(
185 void);
186
187struct 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
215extern int debug_cpu_performance_degradation_factor;
216
217typedef struct clock_frequency_info_t clock_frequency_info_t;
218
219extern clock_frequency_info_t gPEClockFrequencyInfo;
220
221struct timebase_freq_t {
222 unsigned long timebase_num;
223 unsigned long timebase_den;
224};
225
226typedef void (*timebase_callback_func)(struct timebase_freq_t *timebase_freq);
227
228void PE_register_timebase_callback(timebase_callback_func callback);
229
230void PE_call_timebase_callback(void);
231
232#ifdef KERNEL
233void PE_install_interrupt_handler(
234 void *nub, int source,
235 void *target, IOInterruptHandler handler, void *refCon);
236#endif
237
238extern bool disable_serial_output;
239extern bool disable_kprintf_output;
240
241#ifndef _FN_KPRINTF
242#define _FN_KPRINTF
243void kprintf(const char *fmt, ...) __printflike(1, 2);
244#endif
245
246#if KERNEL_PRIVATE
247void _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
258void init_display_putc(unsigned char *baseaddr, int rowbytes, int height);
259void display_putc(char c);
260
261enum {
262 kPEReadTOD,
263 kPEWriteTOD
264};
265
266enum {
267 kPEWaitForInput = 0x00000001,
268 kPERawInput = 0x00000002
269};
270
271/* Private Stuff - eventually put in pexpertprivate.h */
272enum {
273 kDebugTypeNone = 0,
274 kDebugTypeDisplay = 1,
275 kDebugTypeSerial = 2
276};
277
278/* Scale factor values for PE_Video.v_scale */
279enum {
280 kPEScaleFactorUnknown = 0,
281 kPEScaleFactor1x = 1,
282 kPEScaleFactor2x = 2
283};
284
285struct 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
305typedef struct PE_Video PE_Video;
306
307extern void initialize_screen(PE_Video *, unsigned int);
308
309extern void dim_screen(void);
310
311extern int PE_current_console(
312 PE_Video *info);
313
314extern void PE_create_console(
315 void);
316
317extern 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
331extern void PE_display_icon( unsigned int flags,
332 const char * name );
333
334typedef 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
342extern PE_state_t PE_state;
343
344extern char * PE_boot_args(
345 void);
346
347extern boolean_t PE_parse_boot_argn(
348 const char *arg_string,
349 void *arg_ptr,
350 int max_arg);
351
352extern boolean_t PE_boot_arg_uint64_eq(const char *arg_string, uint64_t value);
353
354#if XNU_KERNEL_PRIVATE
355extern 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
361extern 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
372enum {
373 kPEOptionKey = 0x3a,
374 kPECommandKey = 0x37,
375 kPEControlKey = 0x36,
376 kPEShiftKey = 0x38
377};
378
379extern boolean_t PE_get_hotkey(
380 unsigned char key);
381
382extern kern_return_t PE_cpu_start(
383 cpu_id_t target,
384 vm_offset_t start_paddr,
385 vm_offset_t arg_paddr);
386
387extern void PE_cpu_halt(
388 cpu_id_t target);
389
390extern bool PE_cpu_down(
391 cpu_id_t target);
392
393extern void PE_cpu_signal(
394 cpu_id_t source,
395 cpu_id_t target);
396
397extern void PE_cpu_signal_deferred(
398 cpu_id_t source,
399 cpu_id_t target);
400
401extern void PE_cpu_signal_cancel(
402 cpu_id_t source,
403 cpu_id_t target);
404
405extern void PE_cpu_machine_init(
406 cpu_id_t target,
407 boolean_t bootb);
408
409extern void PE_cpu_machine_quiesce(
410 cpu_id_t target);
411
412extern void pe_init_debug(void);
413
414extern boolean_t PE_imgsrc_mount_supported(void);
415
416extern void PE_panic_hook(const char *str);
417
418extern void PE_init_cpu(void);
419
420extern void PE_handle_ext_interrupt(void);
421
422extern void PE_cpu_power_enable(int cpu_id);
423
424extern 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 */
427extern bool PE_cpu_power_check_kdp(int cpu_id);
428
429extern void PE_singlestep_hook(void);
430
431#if defined(__arm__) || defined(__arm64__)
432typedef void (*perfmon_interrupt_handler_func)(cpu_id_t source);
433extern kern_return_t PE_cpu_perfmon_interrupt_install_handler(perfmon_interrupt_handler_func handler);
434extern 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});
445extern panic_trace_t panic_trace;
446
447extern void PE_arm_debug_enable_trace(bool should_kprintf);
448extern void (*PE_arm_debug_panic_hook)(const char *str);
449#else
450extern void(*const PE_arm_debug_panic_hook)(const char *str);
451#endif
452#endif
453
454
455typedef 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
464typedef 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 */
474extern void PE_set_kc_header(kc_kind_t type, kernel_mach_header_t *header, uintptr_t slide);
475void PE_reset_kc_header(kc_kind_t type);
476/* set both lowest VA (base) and mach-o header for a given KC type */
477extern void PE_set_kc_header_and_base(kc_kind_t type, kernel_mach_header_t *header, void *base, uintptr_t slide);
478/* The highest non-LINKEDIT virtual address */
479extern vm_offset_t kc_highest_nonlinkedit_vmaddr;
480/* whether this is an srd enabled device */
481extern 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 */
484extern void *PE_get_kc_header(kc_kind_t type);
485/* returns a pointer to the lowest VA of of the KC of the given type */
486extern 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 */
488extern const void * const*PE_get_kc_base_pointers(void);
489/* returns the slide for the kext collection */
490extern uintptr_t PE_get_kc_slide(kc_kind_t type);
491/* quickly accesss the format of the primary kc */
492extern bool PE_get_primary_kc_format(kc_format_t *type);
493/* gets format of KC of the given type */
494extern bool PE_get_kc_format(kc_kind_t type, kc_format_t *format);
495/* set vnode ptr for kc fileset */
496extern void PE_set_kc_vp(kc_kind_t type, void *vp);
497/* quickly set vnode ptr for kc fileset */
498void * PE_get_kc_vp(kc_kind_t type);
499/* drop reference to kc fileset vnodes */
500void PE_reset_all_kc_vp(void);
501
502#if KERNEL_PRIVATE
503#if defined(__arm64__)
504extern uint8_t PE_smc_stashed_x86_power_state;
505extern uint8_t PE_smc_stashed_x86_efi_boot_state;
506extern uint8_t PE_smc_stashed_x86_system_state;
507extern uint8_t PE_smc_stashed_x86_shutdown_cause;
508extern uint64_t PE_smc_stashed_x86_prev_power_transitions;
509extern uint32_t PE_pcie_stashed_link_state;
510extern uint64_t PE_nvram_stashed_x86_macos_slide;
511#endif
512
513boolean_t PE_reboot_on_panic(void);
514void PE_sync_panic_buffers(void);
515
516typedef 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
523extern vm_size_t PE_init_socd_client(void);
524extern 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