Root/
Source at commit 1146 created 12 years 10 months ago. By azimutz, Sync with trunk (r1145). Add nVidia dev id's, 0DF4 for "GeForce GT 450M" (issue 99) and 1251 for "GeForce GTX 560M" (thanks to oSxFr33k for testing). | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2009 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "options.h"␊ |
8 | #include "graphic_utils.h"␊ |
9 | #include "ramdisk.h"␊ |
10 | #include "embedded.h"␊ |
11 | ␊ |
12 | #include "picopng.h"␊ |
13 | #include "gui.h"␊ |
14 | ␊ |
15 | #include "modules.h"␊ |
16 | ␊ |
17 | /* Kabyl: BooterLog */␊ |
18 | #define BOOTER_LOG_SIZE␉(64 * 1024)␊ |
19 | #define SAFE_LOG_SIZE␉80␊ |
20 | ␊ |
21 | ␊ |
22 | bool useGUI;␊ |
23 | ␊ |
24 | void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4);␊ |
25 | void GUI_ModulesLoaded_hook(void* arg1, void* arg2, void* arg3, void* arg4);␊ |
26 | ␊ |
27 | int GUI_getBootOptions(bool firstRun);␊ |
28 | ␊ |
29 | static void GUI_updateBootArgs( int key );␊ |
30 | void GUI_clearBootArgs(void);␊ |
31 | static void GUI_showBootPrompt(int row, bool visible);␊ |
32 | static void GUI_showMenu( const MenuItem * items, int count, int selection, int row, int height );␊ |
33 | static int GUI_updateMenu( int key, void ** paramPtr );␊ |
34 | static void GUI_showHelp(void);␊ |
35 | ␊ |
36 | int GUI_printf(const char * fmt, ...);␊ |
37 | int GUI_verbose(const char * fmt, ...);␊ |
38 | int GUI_error(const char * fmt, ...);␊ |
39 | void GUI_stop(const char * fmt, ...);␊ |
40 | ␊ |
41 | ␊ |
42 | /* console.c */␊ |
43 | struct putc_info {␊ |
44 | char * str;␊ |
45 | char * last_str;␊ |
46 | };␊ |
47 | void sputc(int c, struct putc_info * pi);␊ |
48 | extern char *msgbuf;␊ |
49 | extern char *cursor;␊ |
50 | ␊ |
51 | ␊ |
52 | ␊ |
53 | ␊ |
54 | char GUI_bootRescanPrompt[] =␊ |
55 | "Press Enter to start up Darwin/x86 with no options, or you can:\n"␊ |
56 | " Press F5 after you swapped the media. The drive will be rescanned.\n"␊ |
57 | " Type -v and press Enter to start up with diagnostic messages\n"␊ |
58 | " Type ? and press Enter to learn about advanced startup options\n\n"␊ |
59 | "boot: ";␊ |
60 | ␊ |
61 | ␊ |
62 | ␊ |
63 | /**␊ |
64 | ** The kernel is about to start, draw the boot graphics if we are not in␊ |
65 | ** verbose mode.␊ |
66 | **/␊ |
67 | void GUI_ExecKernel_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4)␊ |
68 | {␊ |
69 | ␉if(!gVerboseMode)␊ |
70 | ␉{␊ |
71 | ␉␉// Note: shouldn't be needed, but just in case␊ |
72 | ␉␉drawBootGraphics();␊ |
73 | ␉}␊ |
74 | ␉else if(!useGUI)␊ |
75 | ␉{␊ |
76 | ␉␉// When gui mode is enabled, this causes a flicker. Do this later, when the display is blanked out␊ |
77 | ␉␉setVideoMode( GRAPHICS_MODE, 0 );␊ |
78 | ␉}␉␊ |
79 | }␊ |
80 | ␊ |
81 | ␊ |
82 | /**␊ |
83 | ** A boot option has been selected, disable the graphical elements on screen.␊ |
84 | **/␊ |
85 | void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
86 | {␊ |
87 | ␉// Turn off any GUI elements␊ |
88 | ␉if( useGUI )␊ |
89 | ␉{␊ |
90 | ␉␉gui.devicelist.draw = false;␊ |
91 | ␉␉gui.bootprompt.draw = false;␊ |
92 | ␉␉gui.menu.draw = false;␊ |
93 | ␉␉gui.infobox.draw = false;␊ |
94 | ␉␉gui.logo.draw = false;␊ |
95 | ␉␉drawBackground();␊ |
96 | ␉␉//updateVRAM();␊ |
97 | ␊ |
98 | ␉␉if(!gVerboseMode)␊ |
99 | ␉␉{␊ |
100 | ␉␉␉// Disable outputs, they will still show in the boot log.␊ |
101 | ␉␉␉replace_function("_printf", &GUI_verbose);␊ |
102 | ␉␉}␊ |
103 | ␉␉␊ |
104 | ␉}␊ |
105 | }␊ |
106 | ␊ |
107 | void GUI_ModulesLoaded_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4)␊ |
108 | {␊ |
109 | ␉// Start the gui␊ |
110 | ␉useGUI = true;␊ |
111 | ␉// Override useGUI default␊ |
112 | ␉getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);␊ |
113 | ␉if (useGUI && initGUI())␊ |
114 | ␉{␊ |
115 | ␉␉// initGUI() returned with an error, disabling GUI.␊ |
116 | ␉␉useGUI = false;␊ |
117 | ␉}␊ |
118 | ␉else if(useGUI)␊ |
119 | ␉{␊ |
120 | ␉␉replace_function("_initGraphicsMode", &GUI_initGraphicsMode);␊ |
121 | ␉␉replace_function("_getBootOptions", &GUI_getBootOptions);␊ |
122 | ␉␉replace_function("_clearBootArgs", &GUI_clearBootArgs);␊ |
123 | ␉␉replace_function("_showHelp", &GUI_showHelp);␊ |
124 | ␉␉␊ |
125 | ␉␉replace_function("_printf", &GUI_printf);␊ |
126 | ␉␉replace_function("_verbose", &GUI_verbose);␊ |
127 | ␉␉replace_function("_error", &GUI_error);␊ |
128 | ␉␉replace_function("_stop", &GUI_stop);␊ |
129 | ␉␉␊ |
130 | ␉␉setVideoMode( GRAPHICS_MODE, 0 );␊ |
131 | ␉␉drawBackground();␊ |
132 | ␉␊ |
133 | ␉}␊ |
134 | ␉␊ |
135 | }␊ |
136 | ␊ |
137 | /**␊ |
138 | ** Module startup code. Replace console only print functions as well as␊ |
139 | ** replace various menu functions. Finaly, initialize the gui and hook␊ |
140 | ** into important events.␊ |
141 | **/␊ |
142 | void GUI_start()␊ |
143 | {␊ |
144 | ␉register_hook_callback("ExecKernel", &GUI_ExecKernel_hook);␊ |
145 | ␉register_hook_callback("PreBoot", &GUI_PreBoot_hook);␉␉␊ |
146 | ␉register_hook_callback("ModulesLoaded", &GUI_ModulesLoaded_hook);␊ |
147 | }␊ |
148 | ␊ |
149 | /**␊ |
150 | ** Overriden chameleon function. Draws the updated menu.␊ |
151 | **/␊ |
152 | static int GUI_updateMenu( int key, void ** paramPtr )␊ |
153 | {␊ |
154 | int moved = 0;␊ |
155 | ␉␊ |
156 | union {␊ |
157 | struct {␊ |
158 | unsigned int␊ |
159 | ␉␉␉selectionUp : 1,␊ |
160 | ␉␉␉selectionDown : 1,␊ |
161 | ␉␉␉scrollUp : 1,␊ |
162 | ␉␉␉scrollDown : 1;␊ |
163 | } f;␊ |
164 | unsigned int w;␊ |
165 | } draw = {{0}};␊ |
166 | ␉␊ |
167 | if ( gMenuItems == NULL )␊ |
168 | ␉␉return 0;␊ |
169 | ␉␊ |
170 | ␉if( bootArgs->Video.v_display == GRAPHICS_MODE )␊ |
171 | ␉{␊ |
172 | ␉␉int res;␊ |
173 | ␉␉␊ |
174 | ␉␉// set navigation keys for horizontal layout as defaults␊ |
175 | ␉␉int previous␉= 0x4B00;␉␉// left arrow␊ |
176 | ␉␉int subsequent␉= 0x4D00;␉␉// right arrow␊ |
177 | ␉␉int menu␉␉= 0x5000;␉␉// down arrow␊ |
178 | ␉␉␊ |
179 | ␉␉if ( gui.layout == VerticalLayout )␊ |
180 | ␉␉{␊ |
181 | ␉␉␉// set navigation keys for vertical layout␊ |
182 | ␉␉␉previous␉= 0x4800;␉␉// up arrow␊ |
183 | ␉␉␉subsequent␉= 0x5000;␉␉// down arrow␊ |
184 | ␉␉␉menu␉␉= 0x4B00;␉␉// right arrow␊ |
185 | ␉␉} ␊ |
186 | ␉␉␊ |
187 | ␉␉if ( key == previous )␊ |
188 | ␉␉{␊ |
189 | ␉␉␉if ( gMenuSelection > gMenuTop )␊ |
190 | ␉␉␉␉draw.f.selectionUp = 1;␊ |
191 | ␉␉␉else if ( gMenuTop > 0 )␊ |
192 | ␉␉␉␉draw.f.scrollDown = 1;␊ |
193 | ␉␉␉␊ |
194 | ␉␉}␊ |
195 | ␉␉␊ |
196 | ␉␉else if ( key == subsequent )␊ |
197 | ␉␉{␊ |
198 | ␉␉␉if ( gMenuSelection != gMenuBottom)␊ |
199 | ␉␉␉␉draw.f.selectionDown = 1;␊ |
200 | ␉␉␉else if ( gMenuBottom < ( gMenuItemCount - 1 ) )␊ |
201 | ␉␉␉␉draw.f.scrollUp = 1;␊ |
202 | ␉␉}␊ |
203 | ␉␉␊ |
204 | ␉␉else if ( key == menu )␊ |
205 | ␉␉{␊ |
206 | ␉␉␉if ( gui.menu.draw )␊ |
207 | ␉␉␉␉updateInfoMenu(key);␊ |
208 | ␉␉␉else␊ |
209 | ␉␉␉␉drawInfoMenu();␊ |
210 | ␉␉}␊ |
211 | ␉␉␊ |
212 | ␉␉else if ( gui.menu.draw )␊ |
213 | ␉␉{␊ |
214 | ␉␉␉res = updateInfoMenu(key);␊ |
215 | ␉␉␉␊ |
216 | ␉␉␉if ( res == CLOSE_INFO_MENU )␊ |
217 | ␉␉␉␉gui.menu.draw = false;␊ |
218 | ␉␉␉else␊ |
219 | ␉␉␉{␊ |
220 | ␉␉␉␉shouldboot = ( res != DO_NOT_BOOT );␊ |
221 | ␉␉␉␉␊ |
222 | ␉␉␉␉if ( shouldboot )␊ |
223 | ␉␉␉␉␉gui.menu.draw = false;␊ |
224 | ␉␉␉␉␊ |
225 | ␉␉␉␉switch (res)␊ |
226 | ␉␉␉␉{␊ |
227 | ␉␉␉␉␉case BOOT_NORMAL:␊ |
228 | ␉␉␉␉␉␉gVerboseMode = false;␊ |
229 | ␉␉␉␉␉␉gBootMode = kBootModeNormal;␊ |
230 | ␉␉␉␉␉␉break;␊ |
231 | ␉␉␉␉␉␉␊ |
232 | ␉␉␉␉␉case BOOT_VERBOSE:␊ |
233 | ␉␉␉␉␉␉gVerboseMode = true;␊ |
234 | ␉␉␉␉␉␉gBootMode = kBootModeNormal;␊ |
235 | ␉␉␉␉␉␉addBootArg(kVerboseModeFlag);␊ |
236 | ␉␉␉␉␉␉break;␊ |
237 | ␉␉␉␉␉␉␊ |
238 | ␉␉␉␉␉case BOOT_IGNORECACHE:␊ |
239 | ␉␉␉␉␉␉gVerboseMode = false;␊ |
240 | ␉␉␉␉␉␉gBootMode = kBootModeNormal;␊ |
241 | ␉␉␉␉␉␉addBootArg(kIgnoreCachesFlag);␊ |
242 | ␉␉␉␉␉␉break;␊ |
243 | ␉␉␉␉␉␉␊ |
244 | ␉␉␉␉␉case BOOT_SINGLEUSER:␊ |
245 | ␉␉␉␉␉␉gVerboseMode = true;␊ |
246 | ␉␉␉␉␉␉gBootMode = kBootModeNormal;␊ |
247 | ␉␉␉␉␉␉addBootArg(kSingleUserModeFlag);␊ |
248 | ␉␉␉␉␉␉break;␊ |
249 | ␉␉␉␉}␊ |
250 | ␉␉␉␉␊ |
251 | ␉␉␉}␊ |
252 | ␉␉␉␊ |
253 | ␉␉}␉␊ |
254 | ␉␉␊ |
255 | ␉} else {␊ |
256 | ␉␉switch ( key )␊ |
257 | ␉␉{␊ |
258 | ␉case 0x4800: // Up Arrow␊ |
259 | ␉␉␉␉if ( gMenuSelection != gMenuTop )␊ |
260 | ␉␉␉␉{␊ |
261 | ␉␉␉␉␉draw.f.selectionUp = 1;␊ |
262 | ␉␉␉␉}␊ |
263 | ␉␉␉␉else if ( gMenuTop > 0 )␊ |
264 | ␉␉␉␉{␊ |
265 | ␉␉␉␉␉draw.f.scrollDown = 1;␊ |
266 | ␉␉␉␉}␊ |
267 | ␉␉␉␉break;␊ |
268 | ␉␉␉␉␊ |
269 | ␉␉␉case 0x5000: // Down Arrow␊ |
270 | ␉␉␉␉if ( gMenuSelection != gMenuBottom )␊ |
271 | ␉␉␉␉{␊ |
272 | ␉␉␉␉␉draw.f.selectionDown = 1;␊ |
273 | ␉␉␉␉}␊ |
274 | ␉␉␉␉else if ( gMenuBottom < (gMenuItemCount - 1) ) ␊ |
275 | ␉␉␉␉{␊ |
276 | ␉␉␉␉␉draw.f.scrollUp = 1;␊ |
277 | ␉␉␉␉}␊ |
278 | ␉␉␉␉break;␊ |
279 | ␉␉}␊ |
280 | ␉}␊ |
281 | ␉␊ |
282 | if ( draw.w )␊ |
283 | {␊ |
284 | if ( draw.f.scrollUp )␊ |
285 | {␊ |
286 | scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);␊ |
287 | gMenuTop++; gMenuBottom++;␊ |
288 | ␉␉␉gMenuStart++; gMenuEnd++;␊ |
289 | draw.f.selectionDown = 1;␊ |
290 | }␊ |
291 | ␉␉␊ |
292 | if ( draw.f.scrollDown )␊ |
293 | {␊ |
294 | scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);␊ |
295 | gMenuTop--; gMenuBottom--;␊ |
296 | gMenuStart--; gMenuEnd--;␊ |
297 | draw.f.selectionUp = 1;␊ |
298 | }␊ |
299 | ␉␉␊ |
300 | if ( draw.f.selectionUp || draw.f.selectionDown )␊ |
301 | {␊ |
302 | ␉␉␉␊ |
303 | ␉␉␉CursorState cursorState;␊ |
304 | ␉␉␉␊ |
305 | ␉␉␉// Set cursor at current position, and clear inverse video.␊ |
306 | ␉␉␉␊ |
307 | ␉␉␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
308 | ␉␉␉{␊ |
309 | ␉␉␉␉changeCursor( 0, (gMenuRow + gMenuSelection - gMenuTop), kCursorTypeHidden, &cursorState );␊ |
310 | ␉␉␉␉printMenuItem( &gMenuItems[gMenuSelection], 0 );␊ |
311 | ␉␉␉}␊ |
312 | ␉␉␉␊ |
313 | ␉␉␉if ( draw.f.selectionUp )␊ |
314 | ␉␉␉{␊ |
315 | ␉␉␉␉gMenuSelection--;␊ |
316 | ␉␉␉␉if(( gMenuSelection - gMenuStart) == -1 )␊ |
317 | ␉␉␉␉{␊ |
318 | ␉␉␉␉␉gMenuStart--;␊ |
319 | ␉␉␉␉␉gMenuEnd--;␊ |
320 | ␉␉␉␉}␊ |
321 | ␉␉␉␉␊ |
322 | ␉␉␉} else {␊ |
323 | ␉␉␉␉gMenuSelection++;␊ |
324 | ␉␉␉␉if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 )␊ |
325 | ␉␉␉␉{␊ |
326 | ␉␉␉␉␉gMenuStart++;␊ |
327 | ␉␉␉␉␉gMenuEnd++;␊ |
328 | ␉␉␉␉}␊ |
329 | ␉␉␉}␊ |
330 | ␉␉␉␊ |
331 | ␉␉␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
332 | ␉␉␉{␊ |
333 | ␉␉␉␉moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );␊ |
334 | ␉␉␉␉printMenuItem( &gMenuItems[gMenuSelection], 1 );␊ |
335 | ␉␉␉␉restoreCursor( &cursorState );␊ |
336 | ␉␉␉␉␊ |
337 | ␉␉␉}␊ |
338 | ␉␉␉else␊ |
339 | ␉␉␉{␊ |
340 | ␉␉␉␉drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection);␊ |
341 | ␉␉␉}␊ |
342 | ␉␉␉␊ |
343 | ␉␉}␊ |
344 | ␉␉␊ |
345 | *paramPtr = gMenuItems[gMenuSelection].param; ␊ |
346 | moved = 1;␊ |
347 | }␊ |
348 | ␉␊ |
349 | ␉return moved;␊ |
350 | }␊ |
351 | ␊ |
352 | ␊ |
353 | static void GUI_showMenu( const MenuItem * items, int count,␊ |
354 | ␉␉␉␉␉␉ int selection, int row, int height )␊ |
355 | {␊ |
356 | int i;␊ |
357 | CursorState cursorState;␊ |
358 | ␉␊ |
359 | if ( items == NULL || count == 0 ) ␊ |
360 | ␉␉return;␊ |
361 | ␉␊ |
362 | // head and tail points to the start and the end of the list.␊ |
363 | // top and bottom points to the first and last visible items␊ |
364 | // in the menu window.␊ |
365 | ␉␊ |
366 | gMenuItems␉␉= items;␊ |
367 | gMenuRow␉␉= row;␊ |
368 | gMenuHeight␉␉= height;␊ |
369 | gMenuItemCount␉= count;␊ |
370 | gMenuTop␉␉= 0;␊ |
371 | gMenuBottom␉␉= min( count, height ) - 1;␊ |
372 | gMenuSelection␉= selection;␊ |
373 | ␉␊ |
374 | gMenuStart␉␉= 0;␊ |
375 | gMenuEnd␉ = min( count, gui.maxdevices ) - 1;␊ |
376 | ␉␊ |
377 | ␉// If the selected item is not visible, shift the list down.␊ |
378 | ␉␊ |
379 | if ( gMenuSelection > gMenuBottom )␊ |
380 | {␊ |
381 | gMenuTop += ( gMenuSelection - gMenuBottom );␊ |
382 | gMenuBottom = gMenuSelection;␊ |
383 | }␊ |
384 | ␉␊ |
385 | ␉if ( gMenuSelection > gMenuEnd )␊ |
386 | {␊ |
387 | ␉␉gMenuStart += ( gMenuSelection - gMenuEnd );␊ |
388 | gMenuEnd = gMenuSelection;␊ |
389 | }␊ |
390 | ␉␊ |
391 | ␉// Draw the visible items.␊ |
392 | ␉␊ |
393 | ␉if( bootArgs->Video.v_display == GRAPHICS_MODE )␊ |
394 | ␉{␊ |
395 | ␉␉drawDeviceList(gMenuStart, gMenuEnd, gMenuSelection);␊ |
396 | ␉}␊ |
397 | ␉else ␊ |
398 | ␉{␊ |
399 | ␉␉␊ |
400 | ␉␉changeCursor( 0, row, kCursorTypeHidden, &cursorState );␊ |
401 | ␉␉␊ |
402 | ␉␉for ( i = gMenuTop; i <= gMenuBottom; i++ )␊ |
403 | ␉␉{␊ |
404 | ␉␉␉printMenuItem( &items[i], (i == gMenuSelection) );␊ |
405 | ␉␉}␊ |
406 | ␉␉␊ |
407 | ␉␉restoreCursor( &cursorState );␊ |
408 | }␊ |
409 | }␊ |
410 | ␊ |
411 | ␊ |
412 | static void GUI_updateBootArgs( int key )␊ |
413 | {␊ |
414 | key &= kASCIIKeyMask;␊ |
415 | ␉␊ |
416 | switch ( key )␊ |
417 | {␊ |
418 | case kBackspaceKey:␊ |
419 | if ( gBootArgsPtr > gBootArgs )␊ |
420 | {␊ |
421 | int x, y, t;␊ |
422 | getCursorPositionAndType( &x, &y, &t );␊ |
423 | if ( x == 0 && y )␊ |
424 | {␊ |
425 | x = 80; y--;␊ |
426 | }␊ |
427 | if (x)␊ |
428 | ␉␉␉␉␉x--;␊ |
429 | ␉␉␉␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
430 | ␉␉␉␉{␊ |
431 | ␉␉␉␉␉setCursorPosition( x, y, 0 );␊ |
432 | ␉␉␉␉␉putca(' ', 0x07, 1);␊ |
433 | ␉␉␉␉} else␊ |
434 | ␉␉␉␉{␊ |
435 | ␉␉␉␉␉updateGraphicBootPrompt(kBackspaceKey);␊ |
436 | ␉␉␉␉}␊ |
437 | ␉␉␉␉␊ |
438 | ␉␉␉␉*gBootArgsPtr-- = '\0';␊ |
439 | ␉␉␉}␊ |
440 | ␊ |
441 | ␉␉␉break;␊ |
442 | ␉␉␉␊ |
443 | default:␊ |
444 | if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd)␊ |
445 | {␊ |
446 | ␉␉␉␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
447 | ␉␉␉␉{␊ |
448 | ␉␉␉␉␉putchar(key); // echo to screen␊ |
449 | ␉␉␉␉}␊ |
450 | ␉␉␉␉else␊ |
451 | ␉␉␉␉{␊ |
452 | ␉␉␉␉␉updateGraphicBootPrompt(key);␊ |
453 | ␉␉␉␉}␊ |
454 | ␉␉␉␉*gBootArgsPtr++ = key;␊ |
455 | ␉␉␉}␊ |
456 | ␊ |
457 | ␉␉␉break;␊ |
458 | }␊ |
459 | }␊ |
460 | ␊ |
461 | ␊ |
462 | static void GUI_showBootPrompt(int row, bool visible)␊ |
463 | {␊ |
464 | ␉extern char bootPrompt[];␊ |
465 | ␉␊ |
466 | ␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
467 | ␉{␊ |
468 | ␉␉changeCursor( 0, row, kCursorTypeUnderline, 0 ); ␊ |
469 | ␉␉clearScreenRows( row, kScreenLastRow );␊ |
470 | ␉}␊ |
471 | ␉␊ |
472 | ␉clearBootArgs();␊ |
473 | ␉␊ |
474 | ␉if (visible)␊ |
475 | ␉{␊ |
476 | ␉␉if (bootArgs->Video.v_display == VGA_TEXT_MODE) ␊ |
477 | ␉␉{␊ |
478 | ␉␉␉if (gEnableCDROMRescan)␊ |
479 | ␉␉␉{␊ |
480 | ␉␉␉␉printf( GUI_bootRescanPrompt );␊ |
481 | ␉␉␉} ␊ |
482 | ␉␉␉else␊ |
483 | ␉␉␉{␊ |
484 | ␉␉␉␉printf( bootPrompt );␊ |
485 | ␉␉␉}␊ |
486 | ␉␉}␊ |
487 | ␉} ␊ |
488 | ␉else␊ |
489 | ␉{␊ |
490 | ␉␉if (bootArgs->Video.v_display == GRAPHICS_MODE)␊ |
491 | ␉␉{␊ |
492 | ␉␉␉clearGraphicBootPrompt();␊ |
493 | ␉␉} ␊ |
494 | ␉␉else␊ |
495 | ␉␉{␊ |
496 | ␉␉␉printf("Press Enter to start up the foreign OS. ");␊ |
497 | ␉␉}␊ |
498 | ␉}␊ |
499 | }␊ |
500 | ␊ |
501 | ␊ |
502 | void GUI_clearBootArgs(void)␊ |
503 | {␊ |
504 | ␉gBootArgsPtr = gBootArgs;␊ |
505 | ␉memset(gBootArgs, '\0', BOOT_STRING_LEN);␊ |
506 | ␉␊ |
507 | ␉if (bootArgs->Video.v_display == GRAPHICS_MODE) ␊ |
508 | ␉{␊ |
509 | ␉␉clearGraphicBootPrompt();␊ |
510 | ␉}␊ |
511 | }␊ |
512 | ␊ |
513 | ␊ |
514 | int GUI_getBootOptions(bool firstRun)␊ |
515 | {␊ |
516 | ␉int i;␊ |
517 | ␉int key;␊ |
518 | ␉int nextRow;␊ |
519 | ␉int timeout;␊ |
520 | ␉int bvCount;␊ |
521 | ␉BVRef bvr;␊ |
522 | ␉BVRef menuBVR;␊ |
523 | ␉bool showPrompt, newShowPrompt, isCDROM;␊ |
524 | ␉␊ |
525 | ␉// Initialize default menu selection entry.␊ |
526 | ␉gBootVolume = menuBVR = selectBootVolume(bvChain);␊ |
527 | ␉␊ |
528 | ␉if (biosDevIsCDROM(gBIOSDev))␊ |
529 | ␉{␊ |
530 | ␉␉isCDROM = true;␊ |
531 | ␉} ␊ |
532 | ␉else␊ |
533 | ␉{␊ |
534 | ␉␉isCDROM = false;␊ |
535 | ␉}␊ |
536 | ␉␊ |
537 | ␉// ensure we're in graphics mode if gui is setup␊ |
538 | ␉if (gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
539 | ␉{␊ |
540 | ␉␉setVideoMode(GRAPHICS_MODE, 0);␊ |
541 | ␉}␊ |
542 | ␉␊ |
543 | ␉// Clear command line boot arguments␊ |
544 | ␉clearBootArgs();␊ |
545 | ␉␊ |
546 | ␉// Allow user to override default timeout.␊ |
547 | ␉if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->bootConfig))␊ |
548 | ␉{␊ |
549 | ␉␉/* If there is no timeout key in the file use the default timeout␊ |
550 | ␉␉ which is different for CDs vs. hard disks. However, if not booting␊ |
551 | ␉␉ a CD and no config file could be loaded set the timeout␊ |
552 | ␉␉ to zero which causes the menu to display immediately.␊ |
553 | ␉␉ This way, if no partitions can be found, that is the disk is unpartitioned␊ |
554 | ␉␉ or simply cannot be read) then an empty menu is displayed.␊ |
555 | ␉␉ If some partitions are found, for example a Windows partition, then␊ |
556 | ␉␉ these will be displayed in the menu as foreign partitions.␊ |
557 | ␉␉ */␊ |
558 | ␉␉if (isCDROM)␊ |
559 | ␉␉{␊ |
560 | ␉␉␉timeout = kCDBootTimeout;␊ |
561 | ␉␉}␊ |
562 | ␉␉else ␊ |
563 | ␉␉{␊ |
564 | ␉␉␉timeout = sysConfigValid ? kBootTimeout : 0;␊ |
565 | ␉␉}␊ |
566 | ␉}␊ |
567 | ␉␊ |
568 | ␉if (timeout < 0) ␊ |
569 | ␉{␊ |
570 | ␉␉gBootMode |= kBootModeQuiet;␊ |
571 | ␉}␊ |
572 | ␉␊ |
573 | ␉// If the user is holding down a modifier key, enter safe mode.␊ |
574 | ␉if ((readKeyboardShiftFlags() & 0x0F) != 0) ␊ |
575 | ␉{␊ |
576 | ␉␉␊ |
577 | ␉␉//gBootMode |= kBootModeSafe;␊ |
578 | ␉}␊ |
579 | ␉␊ |
580 | ␉// Checking user pressed keys␊ |
581 | ␉bool f8press = false, spress = false, vpress = false;␊ |
582 | ␉while (readKeyboardStatus())␊ |
583 | ␉{␊ |
584 | ␉␉key = bgetc ();␊ |
585 | ␉␉if (key == 0x4200) f8press = true;␊ |
586 | ␉␉if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true;␊ |
587 | ␉␉if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true;␊ |
588 | ␉}␊ |
589 | ␉// If user typed F8, abort quiet mode, and display the menu.␊ |
590 | ␉if (f8press)␊ |
591 | ␉{␊ |
592 | ␉␉gBootMode &= ~kBootModeQuiet;␊ |
593 | ␉␉timeout = 0;␊ |
594 | ␉}␊ |
595 | ␉// If user typed 'v' or 'V', boot in verbose mode.␊ |
596 | ␉if ((gBootMode & kBootModeQuiet) && firstRun && vpress)␊ |
597 | ␉{␊ |
598 | ␉␉addBootArg(kVerboseModeFlag);␊ |
599 | ␉}␊ |
600 | ␉// If user typed 's' or 'S', boot in single user mode.␊ |
601 | ␉if ((gBootMode & kBootModeQuiet) && firstRun && spress)␊ |
602 | ␉{␊ |
603 | ␉␉addBootArg(kSingleUserModeFlag);␊ |
604 | ␉}␊ |
605 | ␉␊ |
606 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
607 | ␉{␊ |
608 | ␉␉setCursorPosition(0, 0, 0);␊ |
609 | ␉␉clearScreenRows(0, kScreenLastRow);␊ |
610 | ␉␉if (!(gBootMode & kBootModeQuiet)) ␊ |
611 | ␉␉{␊ |
612 | ␉␉␉// Display banner and show hardware info.␊ |
613 | ␉␉␉printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);␊ |
614 | ␉␉␉printf(getVBEInfoString());␊ |
615 | ␉␉}␊ |
616 | ␉␉changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);␊ |
617 | ␉␉verbose("Scanning device %x...", gBIOSDev);␊ |
618 | ␉}␊ |
619 | ␉␊ |
620 | ␉// When booting from CD, default to hard drive boot when possible. ␊ |
621 | ␉if (isCDROM && firstRun)␊ |
622 | ␉{␊ |
623 | ␉␉const char *val;␊ |
624 | ␉␉char *prompt = NULL;␊ |
625 | ␉␉char *name = NULL;␊ |
626 | ␉␉int cnt;␊ |
627 | ␉␉int optionKey;␊ |
628 | ␉␉␊ |
629 | ␉␉if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->bootConfig))␊ |
630 | ␉␉{␊ |
631 | ␉␉␉prompt = malloc(cnt + 1);␊ |
632 | ␉␉␉strncat(prompt, val, cnt);␊ |
633 | ␉␉}␊ |
634 | ␉␉else ␊ |
635 | ␉␉{␊ |
636 | ␉␉␉name = malloc(80);␊ |
637 | ␉␉␉getBootVolumeDescription(gBootVolume, name, 79, false);␊ |
638 | ␉␉␉prompt = malloc(256);␊ |
639 | ␉␉␉sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name);␊ |
640 | ␉␉␉free(name);␊ |
641 | ␉␉}␊ |
642 | ␉␉␊ |
643 | ␉␉if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->bootConfig ))␊ |
644 | ␉␉{␊ |
645 | ␉␉␉// The key specified is a special key.␊ |
646 | ␉␉}␊ |
647 | ␉␉else␊ |
648 | ␉␉{␊ |
649 | ␉␉␉// Default to F8.␊ |
650 | ␉␉␉optionKey = 0x4200;␊ |
651 | ␉␉}␊ |
652 | ␉␉␊ |
653 | ␉␉// If the timeout is zero then it must have been set above due to the␊ |
654 | ␉␉// early catch of F8 which means the user wants to set boot options␊ |
655 | ␉␉// which we ought to interpret as meaning he wants to boot the CD.␊ |
656 | ␉␉if (timeout != 0) {␊ |
657 | ␉␉␉key = GUI_countdown(prompt, kMenuTopRow, timeout);␊ |
658 | ␉␉} ␊ |
659 | ␉␉else ␊ |
660 | ␉␉{␊ |
661 | ␉␉␉key = optionKey;␊ |
662 | ␉␉}␊ |
663 | ␉␉␊ |
664 | ␉␉if (prompt != NULL)␊ |
665 | ␉␉{␊ |
666 | ␉␉␉free(prompt);␊ |
667 | ␉␉}␊ |
668 | ␉␉␊ |
669 | ␉␉clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );␊ |
670 | ␉␉␊ |
671 | ␉␉// Hit the option key ?␊ |
672 | ␉␉if (key == optionKey) ␊ |
673 | ␉␉{␊ |
674 | ␉␉␉gBootMode &= ~kBootModeQuiet;␊ |
675 | ␉␉␉timeout = 0;␊ |
676 | ␉␉} ␊ |
677 | ␉␉else ␊ |
678 | ␉␉{␊ |
679 | ␉␉␉key = key & 0xFF;␊ |
680 | ␉␉␉␊ |
681 | ␉␉␉// Try booting hard disk if user pressed 'h'␊ |
682 | ␉␉␉if (biosDevIsCDROM(gBIOSDev) && key == 'h')␊ |
683 | ␉␉␉{␊ |
684 | ␉␉␉␉BVRef bvr;␊ |
685 | ␉␉␉␉␊ |
686 | ␉␉␉␉// Look at partitions hosting OS X other than the CD-ROM␊ |
687 | ␉␉␉␉for (bvr = bvChain; bvr; bvr=bvr->next)␊ |
688 | ␉␉␉␉{␊ |
689 | ␉␉␉␉␉if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev)␊ |
690 | ␉␉␉␉␉{␊ |
691 | ␉␉␉␉␉␉gBootVolume = bvr;␊ |
692 | ␉␉␉␉␉}␊ |
693 | ␉␉␉␉}␊ |
694 | ␉␉␉}␊ |
695 | ␉␉␉goto done;␊ |
696 | ␉␉}␊ |
697 | ␉}␊ |
698 | ␉␊ |
699 | ␉if (gBootMode & kBootModeQuiet)␊ |
700 | ␉{␊ |
701 | ␉␉// No input allowed from user.␊ |
702 | ␉␉goto done;␊ |
703 | ␉}␊ |
704 | ␉␊ |
705 | ␉if (firstRun && timeout > 0 && GUI_countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0)␊ |
706 | ␉{␊ |
707 | ␉␉// If the user is holding down a modifier key,␊ |
708 | ␉␉// enter safe mode.␊ |
709 | ␉␉if ((readKeyboardShiftFlags() & 0x0F) != 0)␊ |
710 | ␉␉{␊ |
711 | ␉␉␉gBootMode |= kBootModeSafe;␊ |
712 | ␉␉}␊ |
713 | ␉␉goto done;␊ |
714 | ␉}␊ |
715 | ␉␊ |
716 | ␉if (gDeviceCount)␊ |
717 | ␉{␊ |
718 | ␉␉// Allocate memory for an array of menu items.␊ |
719 | ␉␉menuItems = malloc(sizeof(MenuItem) * gDeviceCount);␊ |
720 | ␉␉if (menuItems == NULL) ␊ |
721 | ␉␉{␊ |
722 | ␉␉␉goto done;␊ |
723 | ␉␉}␊ |
724 | ␉␉␊ |
725 | ␉␉// Associate a menu item for each BVRef.␊ |
726 | ␉␉for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next)␊ |
727 | ␉␉{␊ |
728 | ␉␉␉if (bvr->visible)␊ |
729 | ␉␉␉{␊ |
730 | ␉␉␉␉getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true);␊ |
731 | ␉␉␉␉menuItems[i].param = (void *) bvr;␊ |
732 | ␉␉␉␉if (bvr == menuBVR)␊ |
733 | ␉␉␉␉{␊ |
734 | ␉␉␉␉␉selectIndex = i;␊ |
735 | ␉␉␉␉}␊ |
736 | ␉␉␉␉i--;␊ |
737 | ␉␉␉}␊ |
738 | ␉␉}␊ |
739 | ␉}␊ |
740 | ␉␊ |
741 | ␉if (bootArgs->Video.v_display == GRAPHICS_MODE)␊ |
742 | ␉{␊ |
743 | ␉␉// redraw the background buffer␊ |
744 | ␉␉gui.logo.draw = true;␊ |
745 | ␉␉drawBackground();␊ |
746 | ␉␉gui.devicelist.draw = true;␊ |
747 | ␉␉gui.redraw = true;␊ |
748 | ␉␉if (!(gBootMode & kBootModeQuiet))␊ |
749 | ␉␉{␊ |
750 | ␉␉␉bool showBootBanner = false;␊ |
751 | ␉␉␉␊ |
752 | ␉␉␉// Check if "Boot Banner"=N switch is present in config file.␊ |
753 | ␉␉␉if (getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig) && showBootBanner)␊ |
754 | ␉␉␉{␊ |
755 | ␉␉␉␉// Display banner and show hardware info.␊ |
756 | ␉␉␉␉gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);␊ |
757 | ␉␉␉}␊ |
758 | ␉␉␉␊ |
759 | ␉␉␉// redraw background␊ |
760 | ␉␉␉memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);␊ |
761 | ␉␉}␊ |
762 | ␉}␊ |
763 | ␉else ␊ |
764 | ␉{␊ |
765 | ␉␉// Clear screen and hide the blinking cursor.␊ |
766 | ␉␉clearScreenRows(kMenuTopRow, kMenuTopRow + 2);␊ |
767 | ␉␉changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);␊ |
768 | ␉}␊ |
769 | ␉␊ |
770 | ␉nextRow = kMenuTopRow;␊ |
771 | ␉showPrompt = true;␊ |
772 | ␉␊ |
773 | ␉if (gDeviceCount)␊ |
774 | ␉{␊ |
775 | ␉␉if( bootArgs->Video.v_display == VGA_TEXT_MODE )␊ |
776 | ␉␉{␊ |
777 | ␉␉␉printf("Use \30\31 keys to select the startup volume.");␊ |
778 | ␉␉}␊ |
779 | ␉␉GUI_showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );␊ |
780 | ␉␉nextRow += min( gDeviceCount, kMenuMaxItems ) + 3;␊ |
781 | ␉}␊ |
782 | ␉␊ |
783 | ␉// Show the boot prompt.␊ |
784 | ␉showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);␊ |
785 | ␉GUI_showBootPrompt( nextRow, showPrompt );␊ |
786 | ␉␊ |
787 | ␉do {␊ |
788 | ␉␉if (bootArgs->Video.v_display == GRAPHICS_MODE)␊ |
789 | ␉␉{␊ |
790 | ␉␉␉// redraw background␊ |
791 | ␉␉␉memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );␊ |
792 | ␉␉␉// reset cursor co-ords␊ |
793 | ␉␉␉gui.debug.cursor = pos( gui.screen.width - 160 , 10 );␊ |
794 | ␉␉}␊ |
795 | ␉␉key = getc();␊ |
796 | ␉␉GUI_updateMenu( key, (void **) &menuBVR );␊ |
797 | ␉␉newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);␊ |
798 | ␉␉␊ |
799 | ␉␉if (newShowPrompt != showPrompt)␊ |
800 | ␉␉{␊ |
801 | ␉␉␉showPrompt = newShowPrompt;␊ |
802 | ␉␉␉GUI_showBootPrompt( nextRow, showPrompt );␊ |
803 | ␉␉}␊ |
804 | ␉␉␊ |
805 | ␉␉if (showPrompt)␊ |
806 | ␉␉{␊ |
807 | ␉␉␉GUI_updateBootArgs(key);␊ |
808 | ␉␉}␊ |
809 | ␉␉␊ |
810 | ␉␉switch (key)␊ |
811 | ␉␉{␊ |
812 | ␉␉␉case kReturnKey:␊ |
813 | ␉␉␉␉if (gui.menu.draw)␊ |
814 | ␉␉␉␉{ ␊ |
815 | ␉␉␉␉␉key=0;␊ |
816 | ␉␉␉␉␉break;␊ |
817 | ␉␉␉␉}␊ |
818 | ␉␉␉␉if (*gBootArgs == '?')␊ |
819 | ␉␉␉␉{␊ |
820 | ␉␉␉␉␉char * argPtr = gBootArgs;␊ |
821 | ␉␉␉␉␉␊ |
822 | ␉␉␉␉␉// Skip the leading "?" character.␊ |
823 | ␉␉␉␉␉argPtr++;␊ |
824 | ␉␉␉␉␉getNextArg(&argPtr, booterCommand);␊ |
825 | ␉␉␉␉␉getNextArg(&argPtr, booterParam);␊ |
826 | ␉␉␉␉␉␊ |
827 | ␉␉␉␉␉/*␊ |
828 | ␉␉␉␉␉ * TODO: this needs to be refactored.␊ |
829 | ␉␉␉␉␉ */␊ |
830 | ␉␉␉␉␉if (strcmp( booterCommand, "video" ) == 0)␊ |
831 | ␉␉␉␉␉{␊ |
832 | ␉␉␉␉␉␉if (bootArgs->Video.v_display == GRAPHICS_MODE)␊ |
833 | ␉␉␉␉␉␉{␊ |
834 | ␉␉␉␉␉␉␉showInfoBox(getVBEInfoString(), getVBEModeInfoString());␊ |
835 | ␉␉␉␉␉␉}␊ |
836 | ␉␉␉␉␉␉else␊ |
837 | ␉␉␉␉␉␉{␊ |
838 | ␉␉␉␉␉␉␉printVBEModeInfo();␊ |
839 | ␉␉␉␉␉␉}␊ |
840 | ␉␉␉␉␉}␊ |
841 | ␉␉␉␉␉else if ( strcmp( booterCommand, "memory" ) == 0)␊ |
842 | ␉␉␉␉␉{␊ |
843 | ␉␉␉␉␉␉if (bootArgs->Video.v_display == GRAPHICS_MODE ) ␊ |
844 | ␉␉␉␉␉␉{␊ |
845 | ␉␉␉␉␉␉␉showInfoBox("Memory Map", getMemoryInfoString());␊ |
846 | ␉␉␉␉␉␉}␊ |
847 | ␉␉␉␉␉␉else␊ |
848 | ␉␉␉␉␉␉{␊ |
849 | ␉␉␉␉␉␉␉printMemoryInfo();␊ |
850 | ␉␉␉␉␉␉}␊ |
851 | ␉␉␉␉␉}␊ |
852 | ␉␉␉␉␉else if (strcmp(booterCommand, "lspci") == 0)␊ |
853 | ␉␉␉␉␉{␊ |
854 | ␉␉␉␉␉␉lspci();␊ |
855 | ␉␉␉␉␉}␊ |
856 | ␉␉␉␉␉else if (strcmp(booterCommand, "more") == 0)␊ |
857 | ␉␉␉␉␉{␊ |
858 | ␉␉␉␉␉␉showTextFile(booterParam);␊ |
859 | ␉␉␉␉␉}␊ |
860 | ␉␉␉␉␉else if (strcmp(booterCommand, "rd") == 0)␊ |
861 | ␉␉␉␉␉{␊ |
862 | ␉␉␉␉␉␉processRAMDiskCommand(&argPtr, booterParam);␊ |
863 | ␉␉␉␉␉} ␊ |
864 | ␉␉␉␉␉else if (strcmp(booterCommand, "norescan") == 0)␊ |
865 | ␉␉␉␉␉{␊ |
866 | ␉␉␉␉␉␉if (gEnableCDROMRescan)␊ |
867 | ␉␉␉␉␉␉{␊ |
868 | ␉␉␉␉␉␉␉gEnableCDROMRescan = false;␊ |
869 | ␉␉␉␉␉␉␉break;␊ |
870 | ␉␉␉␉␉␉}␊ |
871 | ␉␉␉␉␉} ␊ |
872 | ␉␉␉␉␉else␊ |
873 | ␉␉␉␉␉{␊ |
874 | ␉␉␉␉␉␉showHelp();␊ |
875 | ␉␉␉␉␉}␊ |
876 | ␉␉␉␉␉key = 0;␊ |
877 | ␉␉␉␉␉GUI_showBootPrompt(nextRow, showPrompt);␊ |
878 | ␉␉␉␉␉break;␊ |
879 | ␉␉␉␉}␊ |
880 | ␉␉␉␉gBootVolume = menuBVR;␊ |
881 | ␉␉␉␉setRootVolume(menuBVR);␊ |
882 | ␉␉␉␉gBIOSDev = menuBVR->biosdev;␊ |
883 | ␉␉␉␉break;␊ |
884 | ␉␉␉␉␊ |
885 | ␉␉␉case kEscapeKey:␊ |
886 | ␉␉␉␉clearBootArgs();␊ |
887 | ␉␉␉␉break;␊ |
888 | ␉␉␉␉␊ |
889 | ␉␉␉case kF5Key:␊ |
890 | ␉␉␉␉// New behavior:␊ |
891 | ␉␉␉␉// Clear gBootVolume to restart the loop␊ |
892 | ␉␉␉␉// if the user enabled rescanning the optical drive.␊ |
893 | ␉␉␉␉// Otherwise boot the default boot volume.␊ |
894 | ␉␉␉␉if (gEnableCDROMRescan)␊ |
895 | ␉␉␉␉{␊ |
896 | ␉␉␉␉␉gBootVolume = NULL;␊ |
897 | ␉␉␉␉␉clearBootArgs();␊ |
898 | ␉␉␉␉}␊ |
899 | ␉␉␉␉break;␊ |
900 | ␉␉␉␉␊ |
901 | ␉␉␉case kF10Key:␊ |
902 | ␉␉␉␉gScanSingleDrive = false;␊ |
903 | ␉␉␉␉scanDisks(gBIOSDev, &bvCount);␊ |
904 | ␉␉␉␉gBootVolume = NULL;␊ |
905 | ␉␉␉␉clearBootArgs();␊ |
906 | ␉␉␉␉break;␊ |
907 | ␉␉␉␉␊ |
908 | ␉␉␉case kTabKey:␊ |
909 | ␉␉␉␉// New behavior:␊ |
910 | ␉␉␉␉// Switch between text & graphic interfaces␊ |
911 | ␉␉␉␉// Only Permitted if started in graphics interface␊ |
912 | ␉␉␉␉if (useGUI)␊ |
913 | ␉␉␉␉{␊ |
914 | ␉␉␉␉␉if (bootArgs->Video.v_display == GRAPHICS_MODE)␊ |
915 | ␉␉␉␉␉{␊ |
916 | ␉␉␉␉␉␉setVideoMode(VGA_TEXT_MODE, 0);␊ |
917 | ␉␉␉␉␉␉␊ |
918 | ␉␉␉␉␉␉setCursorPosition(0, 0, 0);␊ |
919 | ␉␉␉␉␉␉clearScreenRows(0, kScreenLastRow);␊ |
920 | ␉␉␉␉␉␉␊ |
921 | ␉␉␉␉␉␉// Display banner and show hardware info.␊ |
922 | ␉␉␉␉␉␉printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);␊ |
923 | ␉␉␉␉␉␉printf(getVBEInfoString());␊ |
924 | ␉␉␉␉␉␉␊ |
925 | ␉␉␉␉␉␉clearScreenRows(kMenuTopRow, kMenuTopRow + 2);␊ |
926 | ␉␉␉␉␉␉changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);␊ |
927 | ␉␉␉␉␉␉␊ |
928 | ␉␉␉␉␉␉nextRow = kMenuTopRow;␊ |
929 | ␉␉␉␉␉␉showPrompt = true;␊ |
930 | ␉␉␉␉␉␉␊ |
931 | ␉␉␉␉␉␉if (gDeviceCount)␊ |
932 | ␉␉␉␉␉␉{␊ |
933 | ␉␉␉␉␉␉␉printf("Use \30\31 keys to select the startup volume.");␊ |
934 | ␉␉␉␉␉␉␉GUI_showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems);␊ |
935 | ␉␉␉␉␉␉␉nextRow += min(gDeviceCount, kMenuMaxItems) + 3;␊ |
936 | ␉␉␉␉␉␉}␊ |
937 | ␉␉␉␉␉␉␊ |
938 | ␉␉␉␉␉␉showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);␊ |
939 | ␉␉␉␉␉␉GUI_showBootPrompt(nextRow, showPrompt);␊ |
940 | ␉␉␉␉␉␉//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );␊ |
941 | ␉␉␉␉␉} ␊ |
942 | ␉␉␉␉␉else ␊ |
943 | ␉␉␉␉␉{␊ |
944 | ␉␉␉␉␉␉gui.redraw = true;␊ |
945 | ␉␉␉␉␉␉setVideoMode(GRAPHICS_MODE, 0);␊ |
946 | ␉␉␉␉␉␉updateVRAM();␊ |
947 | ␉␉␉␉␉}␊ |
948 | ␉␉␉␉}␊ |
949 | ␉␉␉␉key = 0;␊ |
950 | ␉␉␉␉break;␊ |
951 | ␉␉␉␉␊ |
952 | ␉␉␉default:␊ |
953 | ␉␉␉␉key = 0;␊ |
954 | ␉␉␉␉break;␊ |
955 | ␉␉}␊ |
956 | ␉} while (0 == key);␊ |
957 | ␉␊ |
958 | done:␊ |
959 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
960 | ␉{␊ |
961 | ␉␉clearScreenRows(kMenuTopRow, kScreenLastRow);␊ |
962 | ␉␉changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);␊ |
963 | ␉}␊ |
964 | ␉shouldboot = false;␊ |
965 | ␉gui.menu.draw = false;␊ |
966 | ␉if (menuItems)␊ |
967 | ␉{␊ |
968 | ␉␉free(menuItems);␊ |
969 | ␉␉menuItems = NULL;␊ |
970 | ␉}␊ |
971 | ␉return 0;␊ |
972 | }␊ |
973 | ␊ |
974 | ␊ |
975 | ␊ |
976 | int GUI_error(const char * fmt, ...)␊ |
977 | {␊ |
978 | va_list ap;␊ |
979 | gErrors = true;␊ |
980 | va_start(ap, fmt);␊ |
981 | ␉␊ |
982 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
983 | ␉{␊ |
984 | ␉␉prf(fmt, ap, putchar, 0);␊ |
985 | }␊ |
986 | ␉else␊ |
987 | ␉{␊ |
988 | ␉␉vprf(fmt, ap);␊ |
989 | ␉}␊ |
990 | ␉␊ |
991 | ␉va_end(ap);␊ |
992 | return(0);␊ |
993 | }␊ |
994 | ␊ |
995 | int GUI_verbose(const char * fmt, ...)␊ |
996 | {␊ |
997 | va_list ap;␊ |
998 | ␊ |
999 | ␉va_start(ap, fmt);␊ |
1000 | if (gVerboseMode)␊ |
1001 | {␊ |
1002 | ␉␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
1003 | ␉␉{␊ |
1004 | ␉␉␉prf(fmt, ap, putchar, 0);␊ |
1005 | ␉␉}␊ |
1006 | ␉␉else␊ |
1007 | ␉␉{␊ |
1008 | ␉␉␉vprf(fmt, ap);␊ |
1009 | ␉␉}␊ |
1010 | }␊ |
1011 | ␉␊ |
1012 | ␉/* Kabyl: BooterLog */␊ |
1013 | ␉struct putc_info pi;␊ |
1014 | ␉␊ |
1015 | ␉if (!msgbuf)␊ |
1016 | ␉␉return 0;␊ |
1017 | ␉␊ |
1018 | ␉if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))␊ |
1019 | ␉␉return 0;␊ |
1020 | ␉pi.str = cursor;␊ |
1021 | ␉pi.last_str = 0;␊ |
1022 | ␉prf(fmt, ap, sputc, &pi);␊ |
1023 | ␉cursor += strlen((char *)cursor);␊ |
1024 | ␉␊ |
1025 | ␉␊ |
1026 | va_end(ap);␊ |
1027 | return(0);␊ |
1028 | }␊ |
1029 | ␊ |
1030 | int GUI_printf(const char * fmt, ...)␊ |
1031 | {␊ |
1032 | va_list ap;␊ |
1033 | ␉va_start(ap, fmt);␊ |
1034 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
1035 | ␉{␊ |
1036 | ␉␉prf(fmt, ap, putchar, 0);␊ |
1037 | ␉}␊ |
1038 | ␉else␊ |
1039 | ␉{␊ |
1040 | ␉␉vprf(fmt, ap);␊ |
1041 | ␉}␊ |
1042 | ␉␊ |
1043 | ␉/* Kabyl: BooterLog */␊ |
1044 | ␉struct putc_info pi;␊ |
1045 | ␉␊ |
1046 | ␉if (!msgbuf)␊ |
1047 | ␉␉return 0;␊ |
1048 | ␉␊ |
1049 | ␉if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))␊ |
1050 | ␉␉return 0;␊ |
1051 | ␉pi.str = cursor;␊ |
1052 | ␉pi.last_str = 0;␊ |
1053 | ␉prf(fmt, ap, sputc, &pi);␊ |
1054 | ␉cursor += strlen((char *)cursor);␊ |
1055 | ␉␊ |
1056 | ␉va_end(ap);␊ |
1057 | return 0;␊ |
1058 | }␊ |
1059 | ␊ |
1060 | void GUI_stop(const char * fmt, ...)␊ |
1061 | {␊ |
1062 | ␉va_list ap;␊ |
1063 | ␉␊ |
1064 | ␉printf("\n");␊ |
1065 | ␉va_start(ap, fmt);␊ |
1066 | ␉␊ |
1067 | ␉if (bootArgs->Video.v_display == VGA_TEXT_MODE)␊ |
1068 | ␉{␊ |
1069 | ␉␉prf(fmt, ap, putchar, 0);␊ |
1070 | ␉} ␊ |
1071 | ␉else ␊ |
1072 | ␉{␊ |
1073 | ␉␉vprf(fmt, ap);␊ |
1074 | ␉}␊ |
1075 | ␉va_end(ap);␊ |
1076 | ␉␊ |
1077 | ␉printf("\nThis is a non recoverable error! System HALTED!!!");␊ |
1078 | ␉halt();␊ |
1079 | ␉while (1);␊ |
1080 | }␊ |
1081 | ␊ |
1082 | void GUI_showHelp(void)␊ |
1083 | {␊ |
1084 | ␉if (bootArgs->Video.v_display == GRAPHICS_MODE) {␊ |
1085 | ␉␉showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt);␊ |
1086 | ␉} else {␊ |
1087 | ␉␉showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len);␊ |
1088 | ␉}␊ |
1089 | }␊ |
1090 |