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