1/* 2 * Copyright 2013, winocm. <winocm@icloud.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright notice, this 12 * list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * If you are going to use this software in any form that does not involve 16 * releasing the source to this project or improving it, let me know beforehand. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * Platform expert initialization module. 31 */ 32 33#include <sys/types.h> 34#include <mach/vm_param.h> 35#include <machine/machine_routines.h> 36#include <pexpert/protos.h> 37#include <pexpert/pexpert.h> 38#include <pexpert/boot.h> 39#include <pexpert/device_tree.h> 40#include <pexpert/pe_images.h> 41#include <kern/sched_prim.h> 42#include <kern/debug.h> 43#include "boot_images.h" 44 45/* private globals */ 46PE_state_t PE_state; 47 48char firmware_version[32]; 49int pe_initialized = 0; 50 51extern uint32_t debug_enabled; 52extern void pe_identify_machine(void *args); 53 54boot_args *BootArgs; 55 56int PE_initialize_console( PE_Video * info, int op ) 57{ 58 static int last_console = -1; 59 60 if (info) { 61 info->v_offset = 0; 62 info->v_length = 0; 63 info->v_display = GRAPHICS_MODE; 64 } 65 66 switch ( op ) { 67 68 case kPEDisableScreen: 69 initialize_screen(info, op); 70 kprintf("kPEDisableScreen %d\n", last_console); 71 if (!console_is_serial()) 72 last_console = switch_to_serial_console(); 73 break; 74 75 case kPEEnableScreen: 76 initialize_screen(info, op); 77 if (info) PE_state.video = *info; 78 kprintf("kPEEnableScreen %d\n", last_console); 79 if( last_console != -1) 80 switch_to_old_console( last_console); 81 break; 82 83 case kPEBaseAddressChange: 84 if (info) PE_state.video = *info; 85 /* fall thru */ 86 87 default: 88 initialize_screen(info, op); 89 break; 90 } 91 92 return 0; 93} 94 95static void null_putc(int c) 96{ 97 return; 98} 99 100/** 101 * PE_init_platform 102 * 103 * Initialize the platform expert for ARM. 104 */ 105void PE_init_platform(boolean_t vm_initialized, void *_args) 106{ 107 boot_args *args = (boot_args *) _args; 108 109 if (PE_state.initialized == FALSE) { 110 PE_early_puts("PE_init_platform: My name is Macintosh.\n"); 111 PE_early_puts("PE_init_platform: Initializing for the first time.\n"); 112 113 PE_state.initialized = TRUE; 114 PE_state.bootArgs = _args; 115 PE_state.deviceTreeHead = args->deviceTreeP; 116 117 PE_state.video.v_baseAddr = args->Video.v_baseAddr; 118 PE_state.video.v_rowBytes = args->Video.v_rowBytes; 119 PE_state.video.v_width = args->Video.v_width; 120 PE_state.video.v_height = args->Video.v_height; 121 PE_state.video.v_depth = args->Video.v_depth; 122 PE_state.video.v_display = args->Video.v_display; 123 124 strncpy(PE_state.video.v_pixelFormat, "PPPPPPPP", 8); 125 126 BootArgs = args; 127 } 128 129 if (!vm_initialized) { 130 /* 131 * Initialize the device tree crap. 132 */ 133 PE_early_puts("PE_init_platform: Initializing device tree\n"); 134 DTInit(PE_state.deviceTreeHead); 135 136 PE_early_puts("PE_init_platform: Calling pe_identify_machine\n"); 137 pe_identify_machine(NULL); 138 } else { 139 DTEntry entry; 140 char *fversion, map; 141 unsigned int size; 142 143 pe_initialized = 1; 144 145 kprintf("PE_init_platform: It sure is great to get out of that bag.\n"); 146 PE_init_SocSupport(); 147 148 /* 149 * Reset kputc. 150 */ 151 PE_kputc = gPESocDispatch.uart_putc; 152 unsigned int boot_arg; 153 154 if (PE_parse_boot_argn("kprintf", &boot_arg, sizeof(boot_arg))) 155 PE_kputc = cnputc; 156 157 if (PE_parse_boot_argn("silence_kprintf", &boot_arg, sizeof(boot_arg))) 158 PE_kputc = null_putc; 159 160 /* 161 * XXX: Real iOS kernel does iBoot/debug-enabled init after the DTInit call. 162 */ 163 if (kSuccess == DTLookupEntry(NULL, "/chosen", &entry)) { 164 /* 165 * What's the iBoot version on this bad boy? 166 */ 167 if (kSuccess == DTGetProperty(entry, "firmware-version", (void **) &fversion, &size)) { 168 if (fversion && (strlen(fversion) <= 32)) { 169 ovbcopy((void *) fversion, (void *) firmware_version, strlen(fversion)); 170 } 171 } 172 /* 173 * Is the SoC debug-enabled? 174 */ 175 if (kSuccess == DTGetProperty(entry, "debug-enabled", (void **) &map, &size)) { 176 debug_enabled = 1; 177 } 178 } 179 180 pe_arm_init_interrupts(NULL); 181 } 182} 183 184/** 185 * PE_init_iokit 186 * 187 * Start IOKit and also set up the video console. 188 */ 189void PE_init_iokit(void) 190{ 191 enum { kMaxBootVar = 128 }; 192 193 typedef struct { 194 char name[32]; 195 unsigned long length; 196 unsigned long value[2]; 197 } DriversPackageProp; 198 199 boolean_t bootClutInitialized = FALSE; 200 boolean_t norootInitialized = FALSE; 201 202 DTEntry entry; 203 unsigned int size; 204 uint32_t *map; 205 boot_progress_element *bootPict; 206 207 kprintf("Kernel boot args: '%s'\n", PE_boot_args()); 208 209 /* 210 * Fetch the CLUT and the noroot image. 211 */ 212 if (kSuccess == DTLookupEntry(NULL, "/chosen/memory-map", &entry)) { 213 if (kSuccess == DTGetProperty(entry, "BootCLUT", (void **) &map, &size)) { 214 if (sizeof(appleClut8) <= map[1]) { 215 bcopy((void *) (map[0]), appleClut8, sizeof(appleClut8)); 216 bootClutInitialized = TRUE; 217 } 218 } 219 } 220 221 if (!bootClutInitialized) { 222 bcopy((void *) (uintptr_t) bootClut, (void *) appleClut8, sizeof(appleClut8)); 223 } 224 225 if (!norootInitialized) { 226 default_noroot.width = kFailedBootWidth; 227 default_noroot.height = kFailedBootHeight; 228 default_noroot.dx = 0; 229 default_noroot.dy = kFailedBootOffset; 230 default_noroot_data = failedBootPict; 231 } 232 233 /* 234 * Initialize the panic UI 235 */ 236 panic_ui_initialize((unsigned char *) appleClut8); 237 238 /* 239 * Initialize the spinning wheel (progress indicator). 240 */ 241 vc_progress_initialize(&default_progress, default_progress_data1x, default_progress_data2x, (unsigned char *) appleClut8); 242 243 printf("iBoot version: %s\n", firmware_version); 244 245 kprintf("PE_init_iokit: starting IOKit now!\n"); 246 247 PE_init_printf(TRUE); 248 249 StartIOKit(PE_state.deviceTreeHead, PE_state.bootArgs, (void *) 0, (void *) 0); 250} 251 252/** 253 * PE_current_console 254 * 255 * Get video console information 256 */ 257int PE_current_console(PE_Video * info) 258{ 259 *info = PE_state.video; 260 261 return 0; 262} 263 264/* Stub. */ 265void PE_display_icon(__unused unsigned int flags, __unused const char *name) 266{ 267 if (default_noroot_data) 268 vc_display_icon(&default_noroot, default_noroot_data); 269} 270 271boolean_t PE_reboot_on_panic(void) 272{ 273 /* 274 * Enable reboot-on-panic 275 */ 276 char tempbuf[16]; 277 278 if (PE_parse_boot_argn("-panic-reboot", tempbuf, sizeof(tempbuf))) { 279 return TRUE; 280 } else { 281 return FALSE; 282 } 283} 284