1/* 2 * Copyright (c) 2000-2006 Apple Computer, 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/* 29 * file: pe_init.c 30 * i386 platform expert initialization. 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 44#include "boot_images.h" 45 46/* extern references */ 47extern void pe_identify_machine(void * args); 48 49/* private globals */ 50PE_state_t PE_state; 51 52/* Clock Frequency Info */ 53clock_frequency_info_t gPEClockFrequencyInfo; 54 55void *gPEEFISystemTable; 56void *gPEEFIRuntimeServices; 57 58static boot_icon_element* norootIcon_lzss; 59static const uint8_t* norootClut_lzss; 60 61int PE_initialize_console( PE_Video * info, int op ) 62{ 63 static int last_console = -1; 64 65 if (info) { 66 info->v_offset = 0; 67 info->v_length = 0; 68 info->v_display = GRAPHICS_MODE; 69 } 70 71 switch ( op ) { 72 73 case kPEDisableScreen: 74 initialize_screen(info, op); 75 kprintf("kPEDisableScreen %d\n", last_console); 76 if (!console_is_serial()) 77 last_console = switch_to_serial_console(); 78 break; 79 80 case kPEEnableScreen: 81 initialize_screen(info, op); 82 if (info) PE_state.video = *info; 83 kprintf("kPEEnableScreen %d\n", last_console); 84 if( last_console != -1) 85 switch_to_old_console( last_console); 86 break; 87 88 case kPEBaseAddressChange: 89 if (info) PE_state.video = *info; 90 /* fall thru */ 91 92 default: 93 initialize_screen(info, op); 94 break; 95 } 96 97 return 0; 98} 99 100void PE_init_iokit(void) 101{ 102 enum { kMaxBootVar = 128 }; 103 104 typedef struct { 105 char name[32]; 106 unsigned long length; 107 unsigned long value[2]; 108 } DriversPackageProp; 109 110 boolean_t bootClutInitialized = FALSE; 111 boolean_t noroot_rle_Initialized = FALSE; 112 113 DTEntry entry; 114 unsigned int size; 115 uint32_t *map; 116 boot_progress_element *bootPict; 117 118 norootIcon_lzss = NULL; 119 norootClut_lzss = NULL; 120 121 PE_init_kprintf(TRUE); 122 PE_init_printf(TRUE); 123 124 kprintf("Kernel boot args: '%s'\n", PE_boot_args()); 125 126 /* 127 * Fetch the CLUT and the noroot image. 128 */ 129 130 if( kSuccess == DTLookupEntry(NULL, "/chosen/memory-map", &entry)) { 131 if( kSuccess == DTGetProperty(entry, "BootCLUT", (void **) &map, &size)) { 132 if (sizeof(appleClut8) <= map[1]) { 133 bcopy( (void *)ml_static_ptovirt(map[0]), appleClut8, sizeof(appleClut8) ); 134 bootClutInitialized = TRUE; 135 } 136 } 137 138 if( kSuccess == DTGetProperty(entry, "Pict-FailedBoot", (void **) &map, &size)) { 139 bootPict = (boot_progress_element *) ml_static_ptovirt(map[0]); 140 default_noroot.width = bootPict->width; 141 default_noroot.height = bootPict->height; 142 default_noroot.dx = 0; 143 default_noroot.dy = bootPict->yOffset; 144 default_noroot_data = &bootPict->data[0]; 145 noroot_rle_Initialized = TRUE; 146 } 147 148 if( kSuccess == DTGetProperty(entry, "FailedCLUT", (void **) &map, &size)) { 149 norootClut_lzss = (uint8_t*) ml_static_ptovirt(map[0]); 150 } 151 152 if( kSuccess == DTGetProperty(entry, "FailedImage", (void **) &map, &size)) { 153 norootIcon_lzss = (boot_icon_element *) ml_static_ptovirt(map[0]); 154 if (norootClut_lzss == NULL) { 155 printf("ERROR: No FailedCLUT provided for noroot icon!\n"); 156 } 157 } 158 } 159 160 if (!bootClutInitialized) { 161 bcopy( (void *) (uintptr_t) bootClut, (void *) appleClut8, sizeof(appleClut8) ); 162 } 163 164 if (!noroot_rle_Initialized) { 165 default_noroot.width = kFailedBootWidth; 166 default_noroot.height = kFailedBootHeight; 167 default_noroot.dx = 0; 168 default_noroot.dy = kFailedBootOffset; 169 default_noroot_data = failedBootPict; 170 } 171 172 /* 173 * Initialize the spinning wheel (progress indicator). 174 */ 175 vc_progress_initialize(&default_progress, 176 default_progress_data1x, 177 default_progress_data2x, 178 default_progress_data3x, 179 (unsigned char *) appleClut8); 180 181 (void) StartIOKit( PE_state.deviceTreeHead, PE_state.bootArgs, gPEEFIRuntimeServices, NULL); 182} 183 184void PE_init_platform(boolean_t vm_initialized, void * _args) 185{ 186 boot_args *args = (boot_args *)_args; 187 188 if (PE_state.initialized == FALSE) { 189 PE_state.initialized = TRUE; 190 191 // New EFI-style 192 PE_state.bootArgs = _args; 193 PE_state.deviceTreeHead = (void *) ml_static_ptovirt(args->deviceTreeP); 194 PE_state.video.v_baseAddr = args->Video.v_baseAddr; // remains physical address 195 PE_state.video.v_rowBytes = args->Video.v_rowBytes; 196 PE_state.video.v_width = args->Video.v_width; 197 PE_state.video.v_height = args->Video.v_height; 198 PE_state.video.v_depth = args->Video.v_depth; 199 PE_state.video.v_display = args->Video.v_display; 200 strlcpy(PE_state.video.v_pixelFormat, "PPPPPPPP", 201 sizeof(PE_state.video.v_pixelFormat)); 202 203#ifdef kBootArgsFlagHiDPI 204 if (args->flags & kBootArgsFlagHiDPI) 205 PE_state.video.v_scale = kPEScaleFactor2x; 206 else 207 PE_state.video.v_scale = kPEScaleFactor1x; 208#else 209 PE_state.video.v_scale = kPEScaleFactor1x; 210#endif 211 } 212 213 if (!vm_initialized) { 214 215 if (PE_state.deviceTreeHead) { 216 DTInit(PE_state.deviceTreeHead); 217 } 218 219 pe_identify_machine(args); 220 } else { 221 pe_init_debug(); 222 } 223 224} 225 226void PE_create_console( void ) 227{ 228 if ( PE_state.video.v_display == GRAPHICS_MODE ) 229 PE_initialize_console( &PE_state.video, kPEGraphicsMode ); 230 else 231 PE_initialize_console( &PE_state.video, kPETextMode ); 232} 233 234int PE_current_console( PE_Video * info ) 235{ 236 *info = PE_state.video; 237 238 return (0); 239} 240 241void PE_display_icon( __unused unsigned int flags, __unused const char * name ) 242{ 243 if ( norootIcon_lzss && norootClut_lzss ) { 244 uint32_t width = norootIcon_lzss->width; 245 uint32_t height = norootIcon_lzss->height; 246 uint32_t x = ((PE_state.video.v_width - width) / 2); 247 uint32_t y = ((PE_state.video.v_height - height) / 2) + norootIcon_lzss->y_offset_from_center; 248 249 vc_display_lzss_icon(x, y, width, height, 250 &norootIcon_lzss->data[0], 251 norootIcon_lzss->data_size, 252 norootClut_lzss); 253 } 254 else if ( default_noroot_data ) { 255 vc_display_icon( &default_noroot, default_noroot_data ); 256 } else { 257 printf("ERROR: No data found for noroot icon!\n"); 258 } 259} 260 261boolean_t 262PE_get_hotkey(__unused unsigned char key) 263{ 264 return (FALSE); 265} 266 267static timebase_callback_func gTimebaseCallback; 268 269void PE_register_timebase_callback(timebase_callback_func callback) 270{ 271 gTimebaseCallback = callback; 272 273 PE_call_timebase_callback(); 274} 275 276void PE_call_timebase_callback(void) 277{ 278 struct timebase_freq_t timebase_freq; 279 unsigned long num, den, cnt; 280 281 num = gPEClockFrequencyInfo.bus_clock_rate_num * gPEClockFrequencyInfo.bus_to_dec_rate_num; 282 den = gPEClockFrequencyInfo.bus_clock_rate_den * gPEClockFrequencyInfo.bus_to_dec_rate_den; 283 284 cnt = 2; 285 while (cnt <= den) { 286 if ((num % cnt) || (den % cnt)) { 287 cnt++; 288 continue; 289 } 290 291 num /= cnt; 292 den /= cnt; 293 } 294 295 timebase_freq.timebase_num = num; 296 timebase_freq.timebase_den = den; 297 298 if (gTimebaseCallback) gTimebaseCallback(&timebase_freq); 299} 300 301/* 302 * The default (non-functional) PE_poll_input handler. 303 */ 304static int 305PE_stub_poll_input(__unused unsigned int options, char * c) 306{ 307 *c = 0xff; 308 return 1; /* 0 for success, 1 for unsupported */ 309} 310 311/* 312 * Called by the kernel debugger to poll for keyboard input. 313 * Keyboard drivers may replace the default stub function 314 * with their polled-mode input function. 315 */ 316int (*PE_poll_input)(unsigned int options, char * c) 317 = PE_stub_poll_input; 318 319boolean_t 320PE_reboot_on_panic(void) 321{ 322 boot_args *args = (boot_args *)PE_state.bootArgs; 323 324 if (args->flags & kBootArgsFlagRebootOnPanic) 325 return TRUE; 326 else 327 return FALSE; 328} 329