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