]> git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/pe_init.c
4c22bf8e83ea7a4277627442cbcecc28d52d6761
[apple/xnu.git] / pexpert / i386 / pe_init.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * file: pe_init.c
32 * i386 platform expert initialization.
33 */
34 #include <sys/types.h>
35 #include <mach/vm_param.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
43 #include "fakePPCStructs.h"
44 #include "fakePPCDeviceTree.h"
45 #include "boot_images.h"
46
47 /* extern references */
48 extern void pe_identify_machine(void * args);
49 extern void initialize_screen(void *, unsigned int);
50
51 /* Local references */
52 static int PE_fb_mode = TEXT_MODE;
53
54 /* private globals */
55 PE_state_t PE_state;
56 dt_data gMemoryMapNode;
57 dt_data gDriversProp;
58 dt_data gRootpathProp;
59 dt_data gCompatibleProp;
60
61 /* Clock Frequency Info */
62 clock_frequency_info_t gPEClockFrequencyInfo;
63
64 int PE_initialize_console( PE_Video * info, int op )
65 {
66 static int last_console = -1;
67 Boot_Video bootInfo;
68 Boot_Video * bInfo;
69
70 /*
71 * Refuse changes from outside pexpert.
72 * The video mode setup by the booter cannot be changed.
73 */
74 if ( info )
75 {
76 bootInfo.v_baseAddr = info->v_baseAddr;
77 bootInfo.v_rowBytes = info->v_rowBytes;
78 bootInfo.v_width = info->v_width;
79 bootInfo.v_height = info->v_height;
80 bootInfo.v_depth = info->v_depth;
81 bInfo = &bootInfo;
82 if (info == &PE_state.video) {
83 bootInfo.v_display = PE_fb_mode;
84 } else {
85 bootInfo.v_display = GRAPHICS_MODE;
86 }
87 }
88 else
89 bInfo = 0;
90
91 switch ( op ) {
92
93 case kPEDisableScreen:
94 initialize_screen((void *) bInfo, op);
95 #ifdef FIXME
96 last_console = switch_to_serial_console();
97 #endif
98 kprintf("kPEDisableScreen %d\n", last_console);
99 break;
100
101 case kPEEnableScreen:
102 initialize_screen((void *) bInfo, op);
103 kprintf("kPEEnableScreen %d\n", last_console);
104 #ifdef FIXME
105 if( last_console != -1)
106 switch_to_old_console( last_console);
107 #endif
108 break;
109
110 default:
111 initialize_screen((void *) bInfo, op);
112 break;
113 }
114
115 return 0;
116 }
117
118 void PE_init_iokit(void)
119 {
120 long * dt;
121 int i;
122 KernelBootArgs_t *kap = (KernelBootArgs_t *)PE_state.bootArgs;
123 enum { kMaxBootVar = 128 };
124 char *rdValue, *platformValue;
125
126 typedef struct {
127 char name[32];
128 unsigned long length;
129 unsigned long value[2];
130 } DriversPackageProp;
131
132 PE_init_kprintf(TRUE);
133 PE_init_printf(TRUE);
134
135 /*
136 * Update the fake device tree with the driver information provided by
137 * the booter.
138 */
139
140 gDriversProp.length = kap->numBootDrivers * sizeof(DriversPackageProp);
141 gMemoryMapNode.length = 2 * sizeof(long);
142
143 rdValue = kalloc(kMaxBootVar);
144 if ( PE_parse_boot_arg("rd", rdValue) ) {
145 if (*rdValue == '*') {
146 gRootpathProp.address = (rdValue + 1);
147 } else {
148 gRootpathProp.address = rdValue;
149 }
150 strcat(rdValue, ",");
151 } else {
152 gRootpathProp.address = rdValue;
153 rdValue[0] = '\0';
154 }
155 strcat(rdValue, kap->bootFile);
156 gRootpathProp.length = strlen(rdValue) + 1;
157
158 platformValue = kalloc(kMaxBootVar);
159 if ( ! PE_parse_boot_arg("platform", platformValue) ) {
160 strcpy(platformValue, kDefaultPlatformName);
161 }
162 gCompatibleProp.address = platformValue;
163 gCompatibleProp.length = strlen(platformValue) + 1;
164
165 dt = (long *) createdt( fakePPCDeviceTree,
166 &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength );
167
168 kfree(rdValue, kMaxBootVar);
169 kfree(platformValue, kMaxBootVar);
170
171
172 if ( dt )
173 {
174 DriversPackageProp * prop = (DriversPackageProp *) gDriversProp.address;
175
176 /* Copy driver info in kernBootStruct to fake device tree */
177
178 for ( i = 0; i < kap->numBootDrivers; i++, prop++ )
179 {
180 switch ( kap->driverConfig[i].type )
181 {
182 case kBootDriverTypeKEXT:
183 sprintf(prop->name, "Driver-%lx", kap->driverConfig[i].address);
184 break;
185
186 case kBootDriverTypeMKEXT:
187 sprintf(prop->name, "DriversPackage-%lx", kap->driverConfig[i].address);
188 break;
189
190 default:
191 sprintf(prop->name, "DriverBogus-%lx", kap->driverConfig[i].address);
192 break;
193 }
194 prop->length = sizeof(prop->value);
195 prop->value[0] = kap->driverConfig[i].address;
196 prop->value[1] = kap->driverConfig[i].size;
197 }
198
199 *((long *)gMemoryMapNode.address) = kap->numBootDrivers + 1;
200 }
201
202 /* Setup powermac_info and powermac_machine_info structures */
203
204 ((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeP = (unsigned long *) dt;
205 ((boot_args*)PE_state.fakePPCBootArgs)->topOfKernelData = (unsigned long) kalloc(0x2000);
206
207 /*
208 * Setup the OpenFirmware Device Tree routines
209 * so the console can be found and the right I/O space
210 * can be used..
211 */
212 DTInit(dt);
213
214 /*
215 * Fetch the CLUT and the noroot image.
216 */
217 bcopy( (void *) (uintptr_t) bootClut, (void *) appleClut8, sizeof(appleClut8) );
218
219 default_noroot.width = kFailedBootWidth;
220 default_noroot.height = kFailedBootHeight;
221 default_noroot.dx = 0;
222 default_noroot.dy = kFailedBootOffset;
223 default_noroot_data = failedBootPict;
224
225 /*
226 * Initialize the panic UI
227 */
228 panic_ui_initialize( (unsigned char *) appleClut8 );
229
230 /*
231 * Initialize the spinning wheel (progress indicator).
232 */
233 vc_progress_initialize( &default_progress, default_progress_data,
234 (unsigned char *) appleClut8 );
235
236 (void) StartIOKit( (void*)dt, PE_state.bootArgs, 0, 0);
237 }
238
239 void PE_init_platform(boolean_t vm_initialized, void * args)
240 {
241 if (PE_state.initialized == FALSE)
242 {
243 KernelBootArgs_t *kap = (KernelBootArgs_t *) args;
244
245 PE_state.initialized = TRUE;
246 PE_state.bootArgs = args;
247 PE_state.video.v_baseAddr = kap->video.v_baseAddr;
248 PE_state.video.v_rowBytes = kap->video.v_rowBytes;
249 PE_state.video.v_height = kap->video.v_height;
250 PE_state.video.v_width = kap->video.v_width;
251 PE_state.video.v_depth = kap->video.v_depth;
252 PE_state.video.v_display = kap->video.v_display;
253 PE_fb_mode = kap->graphicsMode;
254 PE_state.fakePPCBootArgs = (boot_args *)&fakePPCBootArgs;
255 ((boot_args *)PE_state.fakePPCBootArgs)->machineType = 386;
256
257 if (PE_fb_mode == TEXT_MODE)
258 {
259 /* Force a text display if the booter did not setup a
260 * VESA frame buffer.
261 */
262 PE_state.video.v_display = 0;
263 }
264 }
265
266 if (!vm_initialized)
267 {
268 /* Hack! FIXME.. */
269 outb(0x21, 0xff); /* Maskout all interrupts Pic1 */
270 outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */
271
272 pe_identify_machine(args);
273 }
274 else
275 {
276 pe_init_debug();
277 }
278 }
279
280 void PE_create_console( void )
281 {
282 if ( PE_state.video.v_display )
283 PE_initialize_console( &PE_state.video, kPEGraphicsMode );
284 else
285 PE_initialize_console( &PE_state.video, kPETextMode );
286 }
287
288 int PE_current_console( PE_Video * info )
289 {
290 *info = PE_state.video;
291
292 if ( PE_fb_mode == TEXT_MODE )
293 {
294 /*
295 * FIXME: Prevent the IOBootFrameBuffer from starting up
296 * when we are in Text mode.
297 */
298 info->v_baseAddr = 0;
299
300 /*
301 * Scale the size of the text screen from characters
302 * to pixels.
303 */
304 info->v_width *= 8; // CHARWIDTH
305 info->v_height *= 16; // CHARHEIGHT
306 }
307
308 return (0);
309 }
310
311 void PE_display_icon( __unused unsigned int flags, __unused const char * name )
312 {
313 if ( default_noroot_data )
314 vc_display_icon( &default_noroot, default_noroot_data );
315 }
316
317 extern boolean_t PE_get_hotkey( __unused unsigned char key )
318 {
319 return (FALSE);
320 }
321
322 static timebase_callback_func gTimebaseCallback;
323
324 void PE_register_timebase_callback(timebase_callback_func callback)
325 {
326 gTimebaseCallback = callback;
327
328 PE_call_timebase_callback();
329 }
330
331 void PE_call_timebase_callback(void)
332 {
333 struct timebase_freq_t timebase_freq;
334 unsigned long num, den, cnt;
335
336 num = gPEClockFrequencyInfo.bus_clock_rate_num * gPEClockFrequencyInfo.bus_to_dec_rate_num;
337 den = gPEClockFrequencyInfo.bus_clock_rate_den * gPEClockFrequencyInfo.bus_to_dec_rate_den;
338
339 cnt = 2;
340 while (cnt <= den) {
341 if ((num % cnt) || (den % cnt)) {
342 cnt++;
343 continue;
344 }
345
346 num /= cnt;
347 den /= cnt;
348 }
349
350 timebase_freq.timebase_num = num;
351 timebase_freq.timebase_den = den;
352
353 if (gTimebaseCallback) gTimebaseCallback(&timebase_freq);
354 }
355
356 /*
357 * The default (non-functional) PE_poll_input handler.
358 */
359 static int
360 PE_stub_poll_input(__unused unsigned int options, char * c)
361 {
362 *c = 0xff;
363 return 1; /* 0 for success, 1 for unsupported */
364 }
365
366 /*
367 * Called by the kernel debugger to poll for keyboard input.
368 * Keyboard drivers may replace the default stub function
369 * with their polled-mode input function.
370 */
371 int (*PE_poll_input)(unsigned int options, char * c)
372 = PE_stub_poll_input;
373
374
375