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