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