X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/5ba3f43ea354af8ad55bea84372a2bc834d8757c..ea3f04195ba4a5034c9c8e9b726d4f7ce96f1832:/pexpert/arm/pe_init.c diff --git a/pexpert/arm/pe_init.c b/pexpert/arm/pe_init.c index 8accd1743..fda4a4dbb 100644 --- a/pexpert/arm/pe_init.c +++ b/pexpert/arm/pe_init.c @@ -17,26 +17,33 @@ #include #include +#if defined __arm__ +#include +#elif defined __arm64__ +#include +#endif + + /* extern references */ extern void pe_identify_machine(boot_args *bootArgs); /* static references */ -static void pe_prepare_images(void); +static void pe_prepare_images(void); /* private globals */ -PE_state_t PE_state; +SECURITY_READ_ONLY_LATE(PE_state_t) PE_state; #define FW_VERS_LEN 128 char firmware_version[FW_VERS_LEN]; /* * This variable is only modified once, when the BSP starts executing. We put it in __TEXT - * as page protections on kernel text early in startup are read-write. The kernel is - * locked down later in start-up, said mappings become RO and thus this + * as page protections on kernel text early in startup are read-write. The kernel is + * locked down later in start-up, said mappings become RO and thus this * variable becomes immutable. * * See osfmk/arm/arm_vm_init.c for more information. */ -SECURITY_READ_ONLY_SPECIAL_SECTION(volatile uint32_t, "__TEXT,__const") debug_enabled = FALSE; +SECURITY_READ_ONLY_SPECIAL_SECTION(volatile uint32_t, "__TEXT,__const") debug_enabled = FALSE; uint8_t gPlatformECID[8]; uint32_t gPlatformMemoryID; @@ -52,6 +59,17 @@ vm_offset_t gPanicBase; unsigned int gPanicSize; struct embedded_panic_header *panic_info = NULL; +#if (DEVELOPMENT || DEBUG) && defined(XNU_TARGET_OS_BRIDGE) +/* + * On DEVELOPMENT bridgeOS, we map the x86 panic region + * so we can include this data in bridgeOS corefiles + */ +uint64_t macos_panic_base = 0; +unsigned int macos_panic_size = 0; + +struct macos_panic_header *mac_panic_header = NULL; +#endif + /* Maximum size of panic log excluding headers, in bytes */ static unsigned int panic_text_len; @@ -60,39 +78,73 @@ static boolean_t panic_console_available = FALSE; extern uint32_t crc32(uint32_t crc, const void *buf, size_t size); +void PE_slide_devicetree(vm_offset_t); + static void check_for_panic_log(void) { +#ifdef PLATFORM_PANIC_LOG_PADDR + gPanicBase = ml_io_map_wcomb(PLATFORM_PANIC_LOG_PADDR, PLATFORM_PANIC_LOG_SIZE); + panic_text_len = PLATFORM_PANIC_LOG_SIZE - sizeof(struct embedded_panic_header); + gPanicSize = PLATFORM_PANIC_LOG_SIZE; +#else DTEntry entry, chosen; unsigned int size; uintptr_t *reg_prop; uint32_t *panic_region_length; /* - * Find the vram node in the device tree + * DT properties for the panic region are populated by UpdateDeviceTree() in iBoot: + * + * chosen { + * embedded-panic-log-size = <0x00080000>; + * [a bunch of other stuff] + * }; + * + * pram { + * reg = <0x00000008_fbc48000 0x00000000_000b4000>; + * }; + * + * reg[0] is the physical address + * reg[1] is the size of iBoot's kMemoryRegion_Panic (not used) + * embedded-panic-log-size is the maximum amount of data to store in the buffer */ - if (kSuccess != DTLookupEntry(0, "pram", &entry)) + if (kSuccess != DTLookupEntry(0, "pram", &entry)) { return; + } - if (kSuccess != DTGetProperty(entry, "reg", (void **)®_prop, &size)) + if (kSuccess != DTGetProperty(entry, "reg", (void **)®_prop, &size)) { return; + } - if (kSuccess != DTLookupEntry(0, "/chosen", &chosen)) + if (kSuccess != DTLookupEntry(0, "/chosen", &chosen)) { return; + } - if (kSuccess != DTGetProperty(chosen, "embedded-panic-log-size", (void **) &panic_region_length, &size)) + if (kSuccess != DTGetProperty(chosen, "embedded-panic-log-size", (void **) &panic_region_length, &size)) { return; + } - /* - * Map the first page of VRAM into the kernel for use in case of - * panic - */ - /* Note: map as normal memory. */ gPanicBase = ml_io_map_wcomb(reg_prop[0], panic_region_length[0]); /* Deduct the size of the panic header from the panic region size */ panic_text_len = panic_region_length[0] - sizeof(struct embedded_panic_header); gPanicSize = panic_region_length[0]; + +#if DEVELOPMENT && defined(XNU_TARGET_OS_BRIDGE) + if (PE_consistent_debug_enabled()) { + uint64_t macos_panic_physbase = 0; + uint64_t macos_panic_physlen = 0; + /* Populate the macOS panic region data if it's present in consistent debug */ + if (PE_consistent_debug_lookup_entry(kDbgIdMacOSPanicRegion, &macos_panic_physbase, &macos_panic_physlen)) { + macos_panic_base = ml_io_map_with_prot(macos_panic_physbase, macos_panic_physlen, VM_PROT_READ); + mac_panic_header = (struct macos_panic_header *) ((void *) macos_panic_base); + macos_panic_size = macos_panic_physlen; + } + } +#endif /* DEVELOPMENT && defined(XNU_TARGET_OS_BRIDGE) */ + +#endif panic_info = (struct embedded_panic_header *)gPanicBase; /* Check if a shared memory console is running in the panic buffer */ @@ -122,10 +174,11 @@ PE_initialize_console(PE_Video * info, int op) { static int last_console = -1; - if (info && (info != &PE_state.video)) info->v_scale = PE_state.video.v_scale; + if (info && (info != &PE_state.video)) { + info->v_scale = PE_state.video.v_scale; + } switch (op) { - case kPEDisableScreen: initialize_screen(info, op); last_console = switch_to_serial_console(); @@ -134,11 +187,13 @@ PE_initialize_console(PE_Video * info, int op) case kPEEnableScreen: initialize_screen(info, op); - if (info) + if (info) { PE_state.video = *info; + } kprintf("kPEEnableScreen %d\n", last_console); - if (last_console != -1) + if (last_console != -1) { switch_to_old_console(last_console); + } break; case kPEReleaseScreen: @@ -150,10 +205,10 @@ PE_initialize_console(PE_Video * info, int op) default_progress.dx = 0; default_progress.dy = 0; vc_progress_initialize(&default_progress, - default_progress_data1x, - default_progress_data2x, - default_progress_data3x, - (unsigned char *) appleClut8); + default_progress_data1x, + default_progress_data2x, + default_progress_data3x, + (unsigned char *) appleClut8); vc_progress_initialized = TRUE; } initialize_screen(info, op); @@ -170,16 +225,16 @@ PE_initialize_console(PE_Video * info, int op) void PE_init_iokit(void) { - DTEntry entry; - unsigned int size, scale; - unsigned long display_size; - void **map; - unsigned int show_progress; - int *delta, image_size, flip; - uint32_t start_time_value = 0; - uint32_t debug_wait_start_value = 0; - uint32_t load_kernel_start_value = 0; - uint32_t populate_registry_time_value = 0; + DTEntry entry; + unsigned int size, scale; + unsigned long display_size; + void **map; + unsigned int show_progress; + int *delta, image_size, flip; + uint32_t start_time_value = 0; + uint32_t debug_wait_start_value = 0; + uint32_t load_kernel_start_value = 0; + uint32_t populate_registry_time_value = 0; PE_init_kprintf(TRUE); PE_init_printf(TRUE); @@ -187,14 +242,13 @@ PE_init_iokit(void) printf("iBoot version: %s\n", firmware_version); if (kSuccess == DTLookupEntry(0, "/chosen/memory-map", &entry)) { - boot_progress_element *bootPict; - if (kSuccess == DTGetProperty(entry, "BootCLUT", (void **) &map, &size)) + if (kSuccess == DTGetProperty(entry, "BootCLUT", (void **) &map, &size)) { bcopy(map[0], appleClut8, sizeof(appleClut8)); + } if (kSuccess == DTGetProperty(entry, "Pict-FailedBoot", (void **) &map, &size)) { - bootPict = (boot_progress_element *) map[0]; default_noroot.width = bootPict->width; default_noroot.height = bootPict->height; @@ -209,12 +263,12 @@ PE_init_iokit(void) scale = PE_state.video.v_scale; flip = 1; - if (PE_parse_boot_argn("-progress", &show_progress, sizeof (show_progress)) && show_progress) { + if (PE_parse_boot_argn("-progress", &show_progress, sizeof(show_progress)) && show_progress) { /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */ switch (PE_state.video.v_rotate) { - case 2: + case 2: flip = -1; - /* fall through */ + /* fall through */ case 0: display_size = PE_state.video.v_height; image_size = default_progress.height; @@ -222,7 +276,7 @@ PE_init_iokit(void) break; case 1: flip = -1; - /* fall through */ + /* fall through */ case 3: default: display_size = PE_state.video.v_width; @@ -240,10 +294,10 @@ PE_init_iokit(void) PE_get_default("progress-dy", &default_progress.dy, sizeof(default_progress.dy)); vc_progress_initialize(&default_progress, - default_progress_data1x, - default_progress_data2x, - default_progress_data3x, - (unsigned char *) appleClut8); + default_progress_data1x, + default_progress_data2x, + default_progress_data3x, + (unsigned char *) appleClut8); vc_progress_initialized = TRUE; } @@ -253,23 +307,27 @@ PE_init_iokit(void) uint32_t * value_ptr; if (kSuccess == DTGetProperty(entry, "start-time", (void **)&value_ptr, &size)) { - if (size == sizeof(start_time_value)) + if (size == sizeof(start_time_value)) { start_time_value = *value_ptr; + } } if (kSuccess == DTGetProperty(entry, "debug-wait-start", (void **)&value_ptr, &size)) { - if (size == sizeof(debug_wait_start_value)) + if (size == sizeof(debug_wait_start_value)) { debug_wait_start_value = *value_ptr; + } } if (kSuccess == DTGetProperty(entry, "load-kernel-start", (void **)&value_ptr, &size)) { - if (size == sizeof(load_kernel_start_value)) + if (size == sizeof(load_kernel_start_value)) { load_kernel_start_value = *value_ptr; + } } if (kSuccess == DTGetProperty(entry, "populate-registry-time", (void **)&value_ptr, &size)) { - if (size == sizeof(populate_registry_time_value)) + if (size == sizeof(populate_registry_time_value)) { populate_registry_time_value = *value_ptr; + } } } @@ -279,11 +337,19 @@ PE_init_iokit(void) StartIOKit(PE_state.deviceTreeHead, PE_state.bootArgs, (void *) 0, (void *) 0); } +void +PE_slide_devicetree(vm_offset_t slide) +{ + assert(PE_state.initialized); + PE_state.deviceTreeHead += slide; + DTInit(PE_state.deviceTreeHead); +} + void PE_init_platform(boolean_t vm_initialized, void *args) { DTEntry entry; - unsigned int size; + unsigned int size; void **prop; boot_args *boot_args_ptr = (boot_args *) args; @@ -317,26 +383,28 @@ PE_init_platform(boolean_t vm_initialized, void *args) if (!vm_initialized) { if (kSuccess == (DTFindEntry("name", "device-tree", &entry))) { if (kSuccess == DTGetProperty(entry, "target-type", - (void **)&prop, &size)) { - if (size > sizeof(gTargetTypeBuffer)) + (void **)&prop, &size)) { + if (size > sizeof(gTargetTypeBuffer)) { size = sizeof(gTargetTypeBuffer); - bcopy(prop,gTargetTypeBuffer,size); - gTargetTypeBuffer[size-1]='\0'; + } + bcopy(prop, gTargetTypeBuffer, size); + gTargetTypeBuffer[size - 1] = '\0'; } } if (kSuccess == (DTFindEntry("name", "device-tree", &entry))) { if (kSuccess == DTGetProperty(entry, "model", - (void **)&prop, &size)) { - if (size > sizeof(gModelTypeBuffer)) + (void **)&prop, &size)) { + if (size > sizeof(gModelTypeBuffer)) { size = sizeof(gModelTypeBuffer); - bcopy(prop,gModelTypeBuffer,size); - gModelTypeBuffer[size-1]='\0'; + } + bcopy(prop, gModelTypeBuffer, size); + gModelTypeBuffer[size - 1] = '\0'; } } if (kSuccess == DTLookupEntry(NULL, "/chosen", &entry)) { if (kSuccess == DTGetProperty(entry, "debug-enabled", - (void **) &prop, &size)) { - /* + (void **) &prop, &size)) { + /* * We purposefully modify a constified variable as * it will get locked down by a trusted monitor or * via page table mappings. We don't want people easily @@ -345,29 +413,33 @@ PE_init_platform(boolean_t vm_initialized, void *args) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcast-qual" boolean_t *modify_debug_enabled = (boolean_t *) &debug_enabled; - if (size > sizeof(uint32_t)) + if (size > sizeof(uint32_t)) { size = sizeof(uint32_t); + } bcopy(prop, modify_debug_enabled, size); #pragma clang diagnostic pop } if (kSuccess == DTGetProperty(entry, "firmware-version", - (void **) &prop, &size)) { - if (size > sizeof(firmware_version)) + (void **) &prop, &size)) { + if (size > sizeof(firmware_version)) { size = sizeof(firmware_version); + } bcopy(prop, firmware_version, size); firmware_version[size - 1] = '\0'; } if (kSuccess == DTGetProperty(entry, "unique-chip-id", - (void **) &prop, &size)) { - if (size > sizeof(gPlatformECID)) + (void **) &prop, &size)) { + if (size > sizeof(gPlatformECID)) { size = sizeof(gPlatformECID); - bcopy(prop,gPlatformECID,size); + } + bcopy(prop, gPlatformECID, size); } if (kSuccess == DTGetProperty(entry, "dram-vendor-id", - (void **) &prop, &size)) { - if (size > sizeof(gPlatformMemoryID)) + (void **) &prop, &size)) { + if (size > sizeof(gPlatformMemoryID)) { size = sizeof(gPlatformMemoryID); - bcopy(prop,&gPlatformMemoryID,size); + } + bcopy(prop, &gPlatformMemoryID, size); } } pe_init_debug(); @@ -383,30 +455,32 @@ PE_create_console(void) */ check_for_panic_log(); - if (PE_state.video.v_display) + if (PE_state.video.v_display) { PE_initialize_console(&PE_state.video, kPEGraphicsMode); - else + } else { PE_initialize_console(&PE_state.video, kPETextMode); + } } int PE_current_console(PE_Video * info) { *info = PE_state.video; - return (0); + return 0; } void PE_display_icon(__unused unsigned int flags, __unused const char *name) { - if (default_noroot_data) + if (default_noroot_data) { vc_display_icon(&default_noroot, default_noroot_data); + } } extern boolean_t PE_get_hotkey(__unused unsigned char key) { - return (FALSE); + return FALSE; } static timebase_callback_func gTimebaseCallback; @@ -427,27 +501,21 @@ PE_call_timebase_callback(void) timebase_freq.timebase_num = gPEClockFrequencyInfo.timebase_frequency_hz; timebase_freq.timebase_den = 1; - if (gTimebaseCallback) + if (gTimebaseCallback) { gTimebaseCallback(&timebase_freq); + } } /* * The default PE_poll_input handler. */ -static int +int PE_stub_poll_input(__unused unsigned int options, char *c) { *c = uart_getc(); - return 0; /* 0 for success, 1 for unsupported */ + return 0; /* 0 for success, 1 for unsupported */ } -/* - * Called by the kernel debugger to poll for keyboard input. - * Keyboard drivers may replace the default stub function - * with their polled-mode input function. - */ -int (*PE_poll_input) (unsigned int options, char *c) = PE_stub_poll_input; - /* * This routine will return 1 if you are running on a device with a variant * of iBoot that allows debugging. This is typically not the case on production @@ -460,12 +528,26 @@ uint32_t PE_i_can_has_debugger(uint32_t *debug_flags) { if (debug_flags) { - if (debug_enabled) - *debug_flags = debug_boot_arg; - else +#if DEVELOPMENT || DEBUG + assert(debug_boot_arg_inited); +#endif + if (debug_enabled) { + *debug_flags = debug_boot_arg; + } else { *debug_flags = 0; + } } - return (debug_enabled); + return debug_enabled; +} + +/* + * This routine returns TRUE if the device is configured + * with panic debugging enabled. + */ +boolean_t +PE_panic_debugging_enabled() +{ + return panicDebugging; } void @@ -485,12 +567,13 @@ PE_save_buffer_to_vram(unsigned char *buf, unsigned int *size) } *size = *size > panic_text_len ? panic_text_len : *size; - if (panic_info->eph_magic != EMBEDDED_PANIC_MAGIC) + if (panic_info->eph_magic != EMBEDDED_PANIC_MAGIC) { printf("Error!! Current Magic 0x%X, expected value 0x%x", panic_info->eph_magic, EMBEDDED_PANIC_MAGIC); + } /* CRC everything after the CRC itself - starting with the panic header version */ panic_info->eph_crc = crc32(0L, &panic_info->eph_version, (panic_text_len + - sizeof(struct embedded_panic_header) - offsetof(struct embedded_panic_header, eph_version))); + sizeof(struct embedded_panic_header) - offsetof(struct embedded_panic_header, eph_version))); } uint32_t @@ -506,8 +589,9 @@ PE_get_offset_into_panic_region(char *location) void PE_init_panicheader() { - if (!panic_info) + if (!panic_info) { return; + } bzero(panic_info, sizeof(struct embedded_panic_header)); @@ -532,8 +616,9 @@ PE_init_panicheader() void PE_update_panicheader_nestedpanic() { - if (!panic_info) + if (!panic_info) { return; + } /* * If the panic log offset is not set, re-init the panic header @@ -559,7 +644,7 @@ PE_update_panicheader_nestedpanic() /* If this assert fires, it's likely indicative of corruption in the panic region */ assert(((panic_info->eph_stackshot_offset == 0) && (panic_info->eph_stackshot_len == 0)) || - ((panic_info->eph_stackshot_offset != 0) && (panic_info->eph_stackshot_len != 0))); + ((panic_info->eph_stackshot_offset != 0) && (panic_info->eph_stackshot_len != 0))); /* * If we haven't set up the other log yet, set the beginning of the other log @@ -581,7 +666,7 @@ PE_reboot_on_panic(void) uint32_t debug_flags; if (PE_i_can_has_debugger(&debug_flags) - && (debug_flags & DB_NMI)) { + && (debug_flags & DB_NMI)) { /* kernel debugging is active */ return FALSE; } else { @@ -601,8 +686,9 @@ PE_sync_panic_buffers(void) * be discarded on reset. If we can make sure the lines are flushed to L3/DRAM, * the platform reset handler will flush any L3. */ - if (gPanicBase) + if (gPanicBase) { CleanPoC_DcacheRegion_Force(gPanicBase, gPanicSize); + } } static void @@ -657,5 +743,5 @@ void PE_mark_hwaccess(uint64_t thread) { last_hwaccess_thread = thread; - asm volatile("dmb ish"); + asm volatile ("dmb ish"); }