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 /*! 541 * @function PE_init_socd_client 542 * 543 * @brief 544 * Initialize the SOCD client mechanism, used for Xnu to contribute data to the SOCD buffers 545 * managed by the SMC in it's SRAM. 546 */ 547 extern vm_size_t PE_init_socd_client(void); 548 549 550 /*! 551 * @function PE_read_socd_client_buffer 552 * 553 * @brief 554 * read data from the SOCD client buffer in SMC SRAM. 555 */ 556 extern void PE_read_socd_client_buffer(vm_offset_t offset, void *out_buff, vm_size_t size); 557 558 /*! 559 * @function PE_write_socd_client_buffer 560 * 561 * @brief 562 * Write data to the SOCD client buffer in SMC SRAM 563 */ 564 extern void PE_write_socd_client_buffer(vm_offset_t offset, const void *in_buff, vm_size_t size); 565 566 __END_DECLS 567 568 #endif /* _PEXPERT_PEXPERT_H_ */ 569