2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
5 Desc: Main bootmenu code
10 #include <aros/debug.h>
12 #include <proto/bootloader.h>
13 #include <proto/exec.h>
14 #include <proto/graphics.h>
15 #include <proto/intuition.h>
16 #include <devices/keyboard.h>
17 #include <devices/rawkeycodes.h>
18 #include <devices/timer.h>
19 #include <exec/memory.h>
20 #include <graphics/gfxbase.h>
21 #include <libraries/bootmenu.h>
22 #include <libraries/expansionbase.h>
23 #include <aros/bootloader.h>
24 #include <aros/symbolsets.h>
26 #include "devs_private.h"
28 #include "bootmenu_intern.h"
30 #include LC_LIBDEFS_FILE
36 static BOOL
init_gfx(STRPTR gfxclassname
, struct BootMenuBase
*BootMenuBase
)
39 D(bug("[BootMenu] init_gfx(hiddbase='%s')\n", gfxclassname
));
41 /* Call private gfx.library call to init the HIDD.
42 Gfx library is responsible for closing the HIDD
43 library (although it will probably not be necessary).
46 D(bug("[BootMenu] init_gfx: calling private LateGfxInit() ..\n"));
47 if (LateGfxInit(gfxclassname
))
49 D(bug("[BootMenu] init_gfx: calling private LateGfxInit Succeeded\n"));
50 if (LateIntuiInit(NULL
))
52 D(bug("[BootMenu] init_gfx: calling private LateIntuiInit Succeeded\n"));
57 D(bug("[BootMenu] init_gfx: calling private LateIntuiInit Failed!\n"));
62 D(bug("[BootMenu] init_gfx: calling private LateGfxInit Failed!\n"));
64 ReturnBool ("init_gfxhidd", success
);
67 static BOOL
init_device( STRPTR hiddclassname
, STRPTR devicename
, struct BootMenuBase
*BootMenuBase
)
70 struct MsgPort
*mp
= NULL
;
72 D(bug("[BootMenu] init_device(classname='%s', devicename='%s')\n", hiddclassname
, devicename
));
74 if ((mp
= CreateMsgPort()) != NULL
)
76 struct IORequest
*io
= NULL
;
77 if ((io
= CreateIORequest(mp
, sizeof ( struct IOStdReq
))) != NULL
)
79 if (0 == OpenDevice(devicename
, 0, io
, 0))
81 #define ioStd(x) ((struct IOStdReq *)x)
82 ioStd(io
)->io_Command
= CMD_HIDDINIT
;
83 ioStd(io
)->io_Data
= hiddclassname
;
84 ioStd(io
)->io_Length
= strlen(hiddclassname
);
86 /* Let the device init the HIDD */
88 if (0 == io
->io_Error
)
98 ReturnBool("init_device", success
);
101 static BOOL
initHidds(struct BootConfig
*bootcfg
, struct BootMenuBase
*BootMenuBase
)
103 D(bug("[BootMenu] initHidds()\n"));
105 if ((OpenLibrary(bootcfg
->defaultgfx
.libname
, 0)) != NULL
)
107 if ((init_gfx(bootcfg
->defaultgfx
.hiddname
, BootMenuBase
)) == TRUE
)
110 if (!bootcfg
->defaultmouse
.hiddname
[0])
115 if ((OpenLibrary(bootcfg
->defaultmouse
.libname
, 0)) != NULL
)
117 if ((init_device(bootcfg
->defaultmouse
.hiddname
, "gameport.device", BootMenuBase
)) == TRUE
)
120 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
130 static struct Gadget
*createGadgets(struct BootMenuBase_intern
*BootMenuBase
)
132 #warning "TOD: This is very unclean! free-up resources if we fail!"
134 /* Create Option Gadgets */
135 BootMenuBase
->bm_MainGadgets
.bootopt
= createButton(
137 NULL
, "Boot Options...",
138 BUTTON_BOOT_OPTIONS
, (struct BootMenuBase
*)BootMenuBase
);
139 if (BootMenuBase
->bm_MainGadgets
.bootopt
== NULL
)
142 BootMenuBase
->bm_MainGadgets
.displayopt
= createButton(
144 BootMenuBase
->bm_MainGadgets
.bootopt
->gadget
, "Display Options...",
145 BUTTON_DISPLAY_OPTIONS
, (struct BootMenuBase
*)BootMenuBase
);
146 if (BootMenuBase
->bm_MainGadgets
.displayopt
== NULL
)
149 BootMenuBase
->bm_MainGadgets
.expboarddiag
= createButton(
151 BootMenuBase
->bm_MainGadgets
.displayopt
->gadget
, "Expansion Board Diagnostic...",
152 BUTTON_EXPBOARDDIAG
, (struct BootMenuBase
*)BootMenuBase
);
153 if (BootMenuBase
->bm_MainGadgets
.expboarddiag
== NULL
)
156 /* Create BOOT Gadgets */
157 BootMenuBase
->bm_MainGadgets
.boot
= createButton(
159 BootMenuBase
->bm_MainGadgets
.expboarddiag
->gadget
, "Boot",
160 BUTTON_BOOT
, (struct BootMenuBase
*)BootMenuBase
);
161 if (BootMenuBase
->bm_MainGadgets
.boot
== NULL
)
164 BootMenuBase
->bm_MainGadgets
.bootnss
= createButton(
166 BootMenuBase
->bm_MainGadgets
.boot
->gadget
, "Boot With No Startup-Sequence",
167 BUTTON_BOOT_WNSS
, (struct BootMenuBase
*)BootMenuBase
);
168 if (BootMenuBase
->bm_MainGadgets
.bootnss
== NULL
)
171 return BootMenuBase
->bm_MainGadgets
.bootopt
->gadget
;
174 static void freeGadgets(struct BootMenuBase_intern
*BootMenuBase
)
176 if (BootMenuBase
->bm_MainGadgets
.boot
!= NULL
)
177 freeButtonGadget(BootMenuBase
->bm_MainGadgets
.boot
, (struct BootMenuBase
*)BootMenuBase
);
178 if (BootMenuBase
->bm_MainGadgets
.bootnss
!= NULL
);
179 freeButtonGadget(BootMenuBase
->bm_MainGadgets
.bootnss
, (struct BootMenuBase
*)BootMenuBase
);
180 if (BootMenuBase
->bm_MainGadgets
.bootopt
!= NULL
)
181 freeButtonGadget(BootMenuBase
->bm_MainGadgets
.bootopt
, (struct BootMenuBase
*)BootMenuBase
);
182 if (BootMenuBase
->bm_MainGadgets
.displayopt
!= NULL
)
183 freeButtonGadget(BootMenuBase
->bm_MainGadgets
.displayopt
, (struct BootMenuBase
*)BootMenuBase
);
184 if (BootMenuBase
->bm_MainGadgets
.expboarddiag
!= NULL
)
185 freeButtonGadget(BootMenuBase
->bm_MainGadgets
.expboarddiag
, (struct BootMenuBase
*)BootMenuBase
);
188 static void msgLoop(struct BootMenuBase_intern
*BootMenuBase
, struct Window
*win
, struct BootConfig
*bcfg
)
191 struct IntuiMessage
*msg
;
194 D(bug("[BootMenu] msgLoop(BootMenuBase @ %p, Window @ %p, Cfg @ %p)\n", BootMenuBase
, win
, bcfg
));
200 WaitPort(win
->UserPort
);
201 while ((msg
= (struct IntuiMessage
*)GetMsg(win
->UserPort
)))
203 if (msg
->Class
== IDCMP_GADGETUP
)
209 ExpansionBase
->Flags
&= ~EBF_DOSFLAG
;
212 case BUTTON_BOOT_WNSS
:
213 ExpansionBase
->Flags
|= EBF_DOSFLAG
;
218 ReplyMsg((struct Message
*)msg
);
223 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
226 } while (exit
== FALSE
);
227 while ((msg
=(struct IntuiMessage
*)GetMsg(win
->UserPort
)))
228 ReplyMsg(&msg
->ExecMessage
);
231 static UWORD pens
[] = {~0};
233 struct NewScreen ns
=
235 0, 0, 640, 256, 4, /* left, top, width, height, depth */
236 0, 1, /* DetailPen, BlockPen */
237 HIRES
, /* ViewModes */
238 CUSTOMSCREEN
, /* Type */
240 NULL
, /* DefaultTitle */
242 NULL
, /* CustomBitMap */
245 static BOOL
initScreen(struct BootMenuBase_intern
*BootMenuBase
, struct BootConfig
*bcfg
)
247 struct Gadget
*first
= NULL
;
250 D(bug("[BootMenu] initScreen()\n"));
252 if ((BootMenuBase
->bm_Screen
= OpenScreen(&ns
)) != NULL
)
254 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", BootMenuBase
->bm_Screen
));
255 if ((first
= createGadgets(BootMenuBase
)) != NULL
)
257 struct NewWindow nw
=
259 0, 0, /* Left, Top */
260 BootMenuBase
->bm_Screen
->Width
, /* Width, Height */
261 BootMenuBase
->bm_Screen
->Height
,
262 0, 1, /* DetailPen, BlockPen */
263 IDCMP_MOUSEBUTTONS
| IDCMP_MOUSEMOVE
| IDCMP_VANILLAKEY
| IDCMP_GADGETUP
| IDCMP_GADGETDOWN
, /* IDCMPFlags */
264 WFLG_SMART_REFRESH
| WFLG_BORDERLESS
, /* Flags */
265 first
, /* FirstGadget */
266 NULL
, /* CheckMark */
268 BootMenuBase
->bm_Screen
, /* Screen */
270 0, 0, /* MinWidth, MinHeight */
271 0, 0, /* MaxWidth, MaxHeight */
272 CUSTOMSCREEN
, /* Type */
275 D(bug("[BootMenu] initScreen: Gadgets created @ %p\n", first
));
277 if ((BootMenuBase
->bm_Window
= OpenWindow(&nw
)) != NULL
)
279 D(bug("[BootMenu] initScreen: Window opened @ %p\n", BootMenuBase
->bm_Window
));
280 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", BootMenuBase
->bm_Window
->RPort
));
281 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", BootMenuBase
->bm_Window
->UserPort
));
282 SetAPen(BootMenuBase
->bm_Window
->RPort
, 2);
283 D(bug("[BootMenu] initScreen: SetAPen 2\n"));
284 Move(BootMenuBase
->bm_Window
->RPort
, 215, 20);
285 D(bug("[BootMenu] initScreen: Move(d) to 215, 20\n"));
286 Text(BootMenuBase
->bm_Window
->RPort
, "AROS Early Startup Control", 26);
287 D(bug("[BootMenu] initScreen: Early Startup text displayed\n"));
288 #if defined(USE_PALNTSC)
289 #warning "TODO: Check if we are using a PAL/NTSC display mode ..."
290 SetAPen(BootMenuBase
->bm_Window
->RPort
, 1);
291 Move(BootMenuBase
->bm_Window
->RPort
, 225, 40);
292 Text(BootMenuBase
->bm_Window
->RPort
, "(press a key to toggle the display between PAL and NTSC)", 23);
294 msgLoop(BootMenuBase
, BootMenuBase
->bm_Window
, bcfg
);
298 Alert(AT_DeadEnd
| AN_OpenWindow
);
300 CloseWindow(BootMenuBase
->bm_Window
);
301 freeGadgets(BootMenuBase
);
304 Alert(AT_DeadEnd
| AN_BadGadget
);
306 CloseScreen(BootMenuBase
->bm_Screen
);
310 Alert(AT_DeadEnd
| AN_OpenScreen
);
315 /* From keyboard.device/keyboard_intern.h */
316 #define KB_MAXKEYS 256
317 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
318 #define ioStd(x) ((struct IOStdReq *)x)
320 static BOOL
buttonsPressed(struct BootMenuBase
*BootMenuBase
, struct DefaultHidd
*kbd
)
322 BOOL success
= FALSE
;
323 struct MsgPort
*mp
= NULL
;
324 UBYTE matrix
[KB_MATRIXSIZE
];
326 if ((mp
= CreateMsgPort()) != NULL
)
328 struct IORequest
*io
= NULL
;
329 if ((io
= CreateIORequest(mp
, sizeof ( struct IOStdReq
))) != NULL
)
331 if (0 == OpenDevice("keyboard.device", 0, io
, 0))
333 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
334 ioStd(io
)->io_Command
= KBD_READMATRIX
;
335 ioStd(io
)->io_Data
= matrix
;
336 ioStd(io
)->io_Length
= sizeof(matrix
);
338 if (0 == io
->io_Error
)
342 bug("[BootMenu] buttonsPressed: Matrix : ");
343 for (i
= 0; i
< ioStd(io
)->io_Actual
; i
++)
345 bug("%02x ", matrix
[i
]);
349 if (matrix
[RAWKEY_SPACE
/8] & (1<<(RAWKEY_SPACE
%8)))
351 D(bug("[BootMenu] SPACEBAR pressed\n"));
364 int bootmenu_Init(LIBBASETYPEPTR LIBBASE
)
366 struct BootLoaderBase
*BootLoaderBase
= NULL
;
367 struct DefaultHidd
*kbd
= &LIBBASE
->bm_BootConfig
.defaultkbd
;
368 int bmi_RetVal
= (int)FALSE
;
369 D(bug("[BootMenu] bootmenu_Init()\n"));
371 LIBBASE
->bm_Force
= FALSE
; /* Set FALSE here to be sure .. */
373 if ((ExpansionBase
= OpenLibrary("expansion.library", 0)) != NULL
)
375 if ((GfxBase
= OpenLibrary("graphics.library", 37)) != NULL
)
377 if ((IntuitionBase
= OpenLibrary("intuition.library", 37)) != NULL
)
379 BootLoaderBase
= OpenResource("bootloader.resource");
380 InitBootConfig(&LIBBASE
->bm_BootConfig
, BootLoaderBase
);
383 struct List
*list
= NULL
;
384 struct Node
*node
= NULL
;
386 if ((list
= (struct List
*)GetBootInfo(BL_Args
)) != NULL
)
388 ForeachNode(list
,node
)
390 if (0 == strcmp(node
->ln_Name
,"bootmenu"))
392 D(bug("[BootMenu] bootmenu_Init: Forced with bootloader argument\n"));
393 LIBBASE
->bm_Force
= TRUE
;
399 if (!kbd
->hiddname
[0])
401 D(bug("[BootMenu] bootmenu_Init: This system uses no keyboard HIDD\n"));
402 bmi_RetVal
= (int)TRUE
;
404 else if (OpenLibrary(kbd
->libname
, 0) != NULL
)
406 if (init_device(kbd
->hiddname
, "keyboard.device", LIBBASE
))
408 bmi_RetVal
= (int)TRUE
;
415 if ((bmi_RetVal
) && (LIBBASE
->bm_Force
|| buttonsPressed(LIBBASE
, &LIBBASE
->bm_BootConfig
.defaultkbd
)))
417 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
418 /* init mouse + gfx */
419 if (initHidds(&LIBBASE
->bm_BootConfig
, LIBBASE
))
421 D(bug("[BootMenu] bootmenu_Init: Hidds Initialised\n"));
422 initScreen(LIBBASE
, &LIBBASE
->bm_BootConfig
);
426 D(bug("[BootMenu] bootmenu_Init: Hidds Failed to initialise!\n"));
431 D(bug("[BootMenu] bootmenu_Init: Menu not requested ..\n"));
436 ADD2INITLIB(bootmenu_Init
, 0)