]> git.saurik.com Git - apple/xnu.git/blobdiff - pexpert/arm/pe_init.c
xnu-6153.101.6.tar.gz
[apple/xnu.git] / pexpert / arm / pe_init.c
index 8accd174306e17fabfaa89710b8db034f5582edd..fda4a4dbbe3eb3df1f2a01ced8fa3536171f602e 100644 (file)
 #include <kern/debug.h>
 #include <libkern/section_keywords.h>
 
+#if defined __arm__
+#include <pexpert/arm/board_config.h>
+#elif defined __arm64__
+#include <pexpert/arm64/board_config.h>
+#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 **)&reg_prop, &size))
+       if (kSuccess != DTGetProperty(entry, "reg", (void **)&reg_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");
 }