]> git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/pe_init.c
xnu-201.42.3.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/debug.h>
34
35 #include "fakePPCStructs.h"
36 #include "fakePPCDeviceTree.h"
37
38 /* extern references */
39 extern void pe_identify_machine(void * args);
40 extern void initialize_screen(void *, unsigned int);
41
42 /* Local references */
43 static vm_offset_t mapframebuffer(caddr_t,int);
44 static vm_offset_t PE_fb_vaddr = 0;
45 static int PE_fb_mode = TEXT_MODE;
46 static KERNBOOTSTRUCT * PE_kbp = 0;
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 void * desc;
110 unsigned char * data;
111 unsigned char * clut;
112
113 typedef struct {
114 char name[32];
115 unsigned long length;
116 unsigned long value[2];
117 } DriversPackageProp;
118
119 /*
120 * Update the fake device tree with the driver information provided by
121 * the booter.
122 */
123
124 gDriversProp.length = PE_kbp->numBootDrivers * sizeof(DriversPackageProp);
125 gMemoryMapNode.length = 2 * sizeof(long);
126
127 dt = (long *) createdt( fakePPCDeviceTree,
128 &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength );
129
130 if ( dt )
131 {
132 DriversPackageProp * prop = (DriversPackageProp *) gDriversProp.address;
133 int i;
134
135 /* Copy driver info in kernBootStruct to fake device tree */
136
137 for ( i = 0; i < PE_kbp->numBootDrivers; i++, prop++ )
138 {
139 switch ( PE_kbp->driverConfig[i].type )
140 {
141 case kBootDriverTypeKEXT:
142 sprintf(prop->name, "Driver-%lx", PE_kbp->driverConfig[i].address);
143 break;
144
145 case kBootDriverTypeMKEXT:
146 sprintf(prop->name, "DriversPackage-%lx", PE_kbp->driverConfig[i].address);
147 break;
148
149 default:
150 sprintf(prop->name, "DriverBogus-%lx", PE_kbp->driverConfig[i].address);
151 break;
152 }
153 prop->length = sizeof(prop->value);
154 prop->value[0] = PE_kbp->driverConfig[i].address;
155 prop->value[1] = PE_kbp->driverConfig[i].size;
156 }
157
158 *gMemoryMapNode.address = PE_kbp->numBootDrivers + 1;
159 }
160
161 /* Setup powermac_info and powermac_machine_info structures */
162
163 ((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeP = (unsigned long *) dt;
164 ((boot_args*)PE_state.fakePPCBootArgs)->topOfKernelData = (unsigned int) kalloc(0x2000);
165
166 /*
167 * Setup the OpenFirmware Device Tree routines
168 * so the console can be found and the right I/O space
169 * can be used..
170 */
171 DTInit(dt);
172
173 /*
174 * Initialize the spinning wheel (progress indicator).
175 */
176 clut = appleClut8;
177 desc = &default_progress;
178 data = default_progress_data;
179
180 vc_progress_initialize( desc, data, clut );
181
182 PE_initialize_console( (PE_Video *) 0, kPEAcquireScreen );
183
184 (void) StartIOKit( (void*)dt, (void*)PE_state.fakePPCBootArgs, 0, 0);
185 }
186
187 void PE_init_platform(boolean_t vm_initialized, void * args)
188 {
189 if (PE_state.initialized == FALSE)
190 {
191 extern unsigned int halt_in_debugger, disableDebugOuput;
192 unsigned int debug_arg;
193
194 PE_kbp = (KERNBOOTSTRUCT *) args;
195
196 PE_state.initialized = TRUE;
197 PE_state.bootArgs = args;
198 PE_state.video.v_baseAddr = PE_kbp->video.v_baseAddr;
199 PE_state.video.v_rowBytes = PE_kbp->video.v_rowBytes;
200 PE_state.video.v_height = PE_kbp->video.v_height;
201 PE_state.video.v_width = PE_kbp->video.v_width;
202 PE_state.video.v_depth = PE_kbp->video.v_depth;
203 PE_state.video.v_display = PE_kbp->video.v_display;
204 PE_fb_mode = PE_kbp->graphicsMode;
205 PE_state.fakePPCBootArgs = (boot_args *)&fakePPCBootArgs;
206 ((boot_args *)PE_state.fakePPCBootArgs)->machineType = 386;
207
208 if (PE_fb_mode == TEXT_MODE)
209 {
210 /* Force a text display if the booter did not setup a
211 * VESA frame buffer.
212 */
213 PE_state.video.v_display = 0;
214 }
215
216 /*
217 * If DB_HALT flag is set, then cause a breakpoint to the debugger
218 * immediately after the kernel debugger has been initialized.
219 *
220 * If DB_PRT flag is set, then enable debugger printf.
221 */
222 disableDebugOuput = TRUE; /* FIXME: override osfmk/i386/AT386/model_dep.c */
223
224 if (PE_parse_boot_arg("debug", &debug_arg)) {
225 if (debug_arg & DB_HALT) halt_in_debugger = 1;
226 if (debug_arg & DB_PRT) disableDebugOuput = FALSE;
227 }
228 }
229
230 if (!vm_initialized)
231 {
232 /* Hack! FIXME.. */
233 outb(0x21, 0xff); /* Maskout all interrupts Pic1 */
234 outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */
235
236 pe_identify_machine(args);
237 }
238 else
239 {
240 pe_init_debug();
241
242 PE_create_console();
243 }
244 }
245
246 void PE_create_console( void )
247 {
248 if ( (PE_fb_vaddr == 0) && (PE_state.video.v_baseAddr != 0) )
249 {
250 PE_fb_vaddr = mapframebuffer((caddr_t) PE_state.video.v_baseAddr,
251 (PE_fb_mode == TEXT_MODE) ?
252 /* text mode */ PE_state.video.v_rowBytes :
253 /* grfx mode */ PE_state.video.v_rowBytes *
254 PE_state.video.v_height);
255 }
256
257 if (PE_state.video.v_display)
258 PE_initialize_console( &PE_state.video, kPEGraphicsMode );
259 else
260 PE_initialize_console( &PE_state.video, kPETextMode );
261 }
262
263 int PE_current_console( PE_Video * info )
264 {
265 *info = PE_state.video;
266
267 if ( PE_fb_mode == TEXT_MODE )
268 {
269 /*
270 * FIXME: Prevent the IOBootFrameBuffer from starting up
271 * when we are in Text mode.
272 */
273 info->v_baseAddr = 0;
274
275 /*
276 * Scale the size of the text screen from characters
277 * to pixels.
278 */
279 info->v_width *= 8; // CHARWIDTH
280 info->v_height *= 16; // CHARHEIGHT
281 }
282
283 return (0);
284 }
285
286 void PE_display_icon( unsigned int flags,
287 const char * name )
288 {
289 }
290
291 extern boolean_t PE_get_hotkey( unsigned char key )
292 {
293 return (FALSE);
294 }
295
296 static timebase_callback_func gTimebaseCallback;
297
298 void PE_register_timebase_callback(timebase_callback_func callback)
299 {
300 gTimebaseCallback = callback;
301
302 PE_call_timebase_callback();
303 }
304
305 void PE_call_timebase_callback(void)
306 {
307 struct timebase_freq_t timebase_freq;
308 unsigned long num, den, cnt;
309
310 num = gPEClockFrequencyInfo.bus_clock_rate_num * gPEClockFrequencyInfo.bus_to_dec_rate_num;
311 den = gPEClockFrequencyInfo.bus_clock_rate_den * gPEClockFrequencyInfo.bus_to_dec_rate_den;
312
313 cnt = 2;
314 while (cnt <= den) {
315 if ((num % cnt) || (den % cnt)) {
316 cnt++;
317 continue;
318 }
319
320 num /= cnt;
321 den /= cnt;
322 }
323
324 timebase_freq.timebase_num = num;
325 timebase_freq.timebase_den = den;
326
327 if (gTimebaseCallback) gTimebaseCallback(&timebase_freq);
328 }
329
330 /*
331 * map the framebuffer into kernel vm and return the (virtual)
332 * address.
333 */
334 static vm_offset_t
335 mapframebuffer( caddr_t physaddr, /* start of framebuffer */
336 int length) /* num bytes to map */
337 {
338 vm_offset_t vmaddr;
339
340 if (physaddr != (caddr_t)trunc_page(physaddr))
341 panic("Framebuffer not on page boundary");
342
343 vmaddr = io_map((vm_offset_t)physaddr, length);
344 if (vmaddr == 0)
345 panic("can't alloc VM for framebuffer");
346
347 return vmaddr;
348 }
349
350 /*
351 * The default (non-functional) PE_poll_input handler.
352 */
353 static int
354 PE_stub_poll_input(unsigned int options, char * c)
355 {
356 *c = 0xff;
357 return 1; /* 0 for success, 1 for unsupported */
358 }
359
360 /*
361 * Called by the kernel debugger to poll for keyboard input.
362 * Keyboard drivers may replace the default stub function
363 * with their polled-mode input function.
364 */
365 int (*PE_poll_input)(unsigned int options, char * c)
366 = PE_stub_poll_input;