2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
5 Desc: Main bootmenu code
9 #include <aros/config.h>
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 <proto/expansion.h>
17 #include <proto/oop.h>
18 #include <devices/keyboard.h>
19 #include <devices/rawkeycodes.h>
20 #include <devices/timer.h>
21 #include <exec/memory.h>
22 #include <graphics/driver.h>
23 #include <libraries/expansionbase.h>
24 #include <libraries/configvars.h>
25 #include <dos/filehandler.h>
26 #include <devices/trackdisk.h>
27 #include <exec/rawfmt.h>
28 #include <aros/bootloader.h>
29 #include <aros/symbolsets.h>
31 #include LC_LIBDEFS_FILE
33 #include "dosboot_intern.h"
38 #define PAGE_DISPLAY 3
39 #define PAGE_EXPANSION 4
41 #define EXIT_BOOT_WNSS 6
43 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
45 #define INITHIDDS_KLUDGE
49 #ifdef INITHIDDS_KLUDGE
52 * This is an extremely obsolete kludge.
53 * It's still needed for ATI driver on PowerPC native.
56 static BOOL
init_gfx(STRPTR gfxclassname
, BOOL bootmode
, LIBBASETYPEPTR DOSBootBase
)
61 D(bug("[BootMenu] init_gfx('%s')\n", gfxclassname
));
63 GfxBase
= (void *)OpenLibrary("graphics.library", 41);
67 gfxclass
= OOP_FindClass(gfxclassname
);
70 if (!AddDisplayDriver(gfxclass
, NULL
, DDRV_BootMode
, bootmode
, TAG_DONE
))
74 CloseLibrary(&GfxBase
->LibNode
);
76 ReturnBool ("init_gfxhidd", success
);
79 static BOOL
initHidds(LIBBASETYPEPTR DOSBootBase
)
81 struct BootConfig
*bootcfg
= &DOSBootBase
->bm_BootConfig
;
83 D(bug("[BootMenu] initHidds()\n"));
85 if (bootcfg
->gfxhidd
) {
86 if (!OpenLibrary(bootcfg
->gfxlib
, 0))
89 if (!init_gfx(bootcfg
->gfxhidd
, bootcfg
->bootmode
, DOSBootBase
))
93 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
99 static struct Gadget
*createGadgetsBoot(LIBBASETYPEPTR DOSBootBase
)
101 /* Create Option Gadgets */
102 DOSBootBase
->bm_MainGadgets
.bootopt
= createButton(
104 NULL
, "Boot Options...",
105 BUTTON_BOOT_OPTIONS
, (struct DOSBootBase
*)DOSBootBase
);
106 DOSBootBase
->bm_MainGadgets
.displayopt
= createButton(
108 DOSBootBase
->bm_MainGadgets
.bootopt
->gadget
, "Display Options...",
109 BUTTON_DISPLAY_OPTIONS
, (struct DOSBootBase
*)DOSBootBase
);
110 DOSBootBase
->bm_MainGadgets
.expboarddiag
= createButton(
112 DOSBootBase
->bm_MainGadgets
.displayopt
->gadget
, "Expansion Board Diagnostic...",
113 BUTTON_EXPBOARDDIAG
, (struct DOSBootBase
*)DOSBootBase
);
114 /* Create BOOT Gadgets */
115 DOSBootBase
->bm_MainGadgets
.boot
= createButton(
116 16, DOSBootBase
->bottomY
, 280, 14,
117 DOSBootBase
->bm_MainGadgets
.expboarddiag
->gadget
, "Boot",
118 BUTTON_BOOT
, (struct DOSBootBase
*)DOSBootBase
);
119 DOSBootBase
->bm_MainGadgets
.bootnss
= createButton(
120 344, DOSBootBase
->bottomY
, 280, 14,
121 DOSBootBase
->bm_MainGadgets
.boot
->gadget
, "Boot With No Startup-Sequence",
122 BUTTON_BOOT_WNSS
, (struct DOSBootBase
*)DOSBootBase
);
123 if (!DOSBootBase
->bm_MainGadgets
.bootopt
||
124 !DOSBootBase
->bm_MainGadgets
.displayopt
||
125 !DOSBootBase
->bm_MainGadgets
.expboarddiag
||
126 !DOSBootBase
->bm_MainGadgets
.boot
||
127 !DOSBootBase
->bm_MainGadgets
.bootnss
)
129 return DOSBootBase
->bm_MainGadgets
.bootopt
->gadget
;
132 static struct Gadget
*createGadgetsUseCancel(LIBBASETYPEPTR DOSBootBase
)
134 DOSBootBase
->bm_MainGadgets
.use
= createButton(
135 16, DOSBootBase
->bottomY
, 280, 14,
137 BUTTON_USE
, (struct DOSBootBase
*)DOSBootBase
);
138 DOSBootBase
->bm_MainGadgets
.cancel
= createButton(
139 344, DOSBootBase
->bottomY
, 280, 14,
140 DOSBootBase
->bm_MainGadgets
.use
->gadget
, "Cancel",
141 BUTTON_CANCEL
, (struct DOSBootBase
*)DOSBootBase
);
142 if (!DOSBootBase
->bm_MainGadgets
.use
||
143 !DOSBootBase
->bm_MainGadgets
.cancel
)
145 return DOSBootBase
->bm_MainGadgets
.use
->gadget
;
149 static void freeGadgetsBoot(LIBBASETYPEPTR DOSBootBase
)
151 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.boot
, (struct DOSBootBase
*)DOSBootBase
);
152 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.bootnss
, (struct DOSBootBase
*)DOSBootBase
);
153 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.bootopt
, (struct DOSBootBase
*)DOSBootBase
);
154 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.displayopt
, (struct DOSBootBase
*)DOSBootBase
);
155 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.expboarddiag
, (struct DOSBootBase
*)DOSBootBase
);
158 static void freeGadgetsUseCancel(LIBBASETYPEPTR DOSBootBase
)
160 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.use
, (struct DOSBootBase
*)DOSBootBase
);
161 freeButtonGadget(DOSBootBase
->bm_MainGadgets
.cancel
, (struct DOSBootBase
*)DOSBootBase
);
164 static struct Gadget
*createGadgets(LIBBASETYPEPTR DOSBootBase
, WORD page
)
166 if (page
== PAGE_MAIN
)
167 return createGadgetsBoot(DOSBootBase
);
169 return createGadgetsUseCancel(DOSBootBase
);
171 static void freeGadgets(LIBBASETYPEPTR DOSBootBase
, WORD page
)
173 if (page
== PAGE_MAIN
)
174 freeGadgetsBoot(DOSBootBase
);
176 freeGadgetsUseCancel(DOSBootBase
);
179 static void toggleMode(LIBBASETYPEPTR DOSBootBase
)
183 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
185 if (OpenResource("ciaa.resource")) {
186 volatile UWORD
*beamcon0
= (UWORD
*)0xdff1dc;
187 GfxBase
->DisplayFlags
^= PAL
| NTSC
;
188 *beamcon0
= (GfxBase
->DisplayFlags
& PAL
) ? 0x0020 : 0x0000;
193 static UWORD
msgLoop(LIBBASETYPEPTR DOSBootBase
, struct Window
*win
)
196 struct IntuiMessage
*msg
;
199 D(bug("[BootMenu] msgLoop(DOSBootBase @ %p, Window @ %p)\n", DOSBootBase
, win
));
205 WaitPort(win
->UserPort
);
206 while ((msg
= (struct IntuiMessage
*)GetMsg(win
->UserPort
)))
208 if (msg
->Class
== IDCMP_VANILLAKEY
) {
211 else if (msg
->Code
>= '1' && msg
->Code
<= '3')
212 exit
= PAGE_MAIN
+ msg
->Code
- '0';
213 else if (msg
->Code
>= 'a' && msg
->Code
<='j') {
214 BYTE pos
= msg
->Code
- 'a', i
= 0;
216 DOSBootBase
->db_BootNode
= NULL
;
218 Forbid(); /* .. access to ExpansionBase->MountList */
219 ForeachNode(&DOSBootBase
->bm_ExpansionBase
->MountList
, bn
)
223 DOSBootBase
->db_BootNode
= bn
;
229 if (DOSBootBase
->db_BootNode
!= NULL
)
237 toggleMode(DOSBootBase
);
238 } else if (msg
->Class
== IDCMP_GADGETUP
)
244 DOSBootBase
->db_BootFlags
&= ~BF_NO_STARTUP_SEQUENCE
;
247 case BUTTON_BOOT_WNSS
:
248 DOSBootBase
->db_BootFlags
|= BF_NO_STARTUP_SEQUENCE
;
249 exit
= EXIT_BOOT_WNSS
;
252 DOSBootBase
->db_BootNode
= NULL
;
255 case BUTTON_CONTINUE
:
258 case BUTTON_BOOT_OPTIONS
:
261 case BUTTON_EXPBOARDDIAG
:
262 exit
= PAGE_EXPANSION
;
264 case BUTTON_DISPLAY_OPTIONS
:
269 ReplyMsg((struct Message
*)msg
);
274 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
279 while ((msg
=(struct IntuiMessage
*)GetMsg(win
->UserPort
)))
280 ReplyMsg(&msg
->ExecMessage
);
285 static void initPageExpansion(LIBBASETYPEPTR DOSBootBase
)
287 struct Window
*win
= DOSBootBase
->bm_Window
;
288 struct ExpansionBase
*ExpansionBase
= DOSBootBase
->bm_ExpansionBase
;
289 struct ConfigDev
*cd
;
293 SetAPen(win
->RPort
, 1);
296 while ((cd
= FindConfigDev(cd
, -1, -1))) {
297 NewRawDoFmt("%2d: %08lx - %08lx (%08lx) %5d %3d %08lx", RAWFMTFUNC_STRING
, text
,
299 cd
->cd_BoardAddr
, cd
->cd_BoardAddr
+ cd
->cd_BoardSize
- 1, cd
->cd_BoardSize
,
300 cd
->cd_Rom
.er_Manufacturer
, cd
->cd_Rom
.er_Product
, cd
->cd_Rom
.er_SerialNumber
);
301 if ((cd
->cd_Rom
.er_Type
& ERT_TYPEMASK
) == ERT_ZORROIII
)
303 else if ((cd
->cd_Rom
.er_Type
& ERT_TYPEMASK
) == ERT_ZORROII
)
307 if (cd
->cd_Rom
.er_Type
& ERTF_DIAGVALID
)
308 strcat(text
, " ROM");
309 if (cd
->cd_Rom
.er_Type
& ERTF_MEMLIST
)
310 strcat(text
, " RAM");
311 Move(win
->RPort
, 20, y
);
312 Text(win
->RPort
, text
, strlen(text
));
317 static void initPageBoot(LIBBASETYPEPTR DOSBootBase
)
319 struct Window
*win
= DOSBootBase
->bm_Window
;
322 char text
[100], *textp
;
324 SetAPen(win
->RPort
, 1);
326 ForeachNode(&DOSBootBase
->bm_ExpansionBase
->MountList
, bn
)
328 struct DeviceNode
*dn
= bn
->bn_DeviceNode
;
329 struct FileSysStartupMsg
*fssm
= BADDR(dn
->dn_Startup
);
330 struct DosEnvec
*de
= NULL
;
332 struct MsgPort
*port
;
336 BOOL devopen
, ismedia
;
338 if (y
>= DOSBootBase
->bottomY
- 20)
340 if (!fssm
|| !fssm
->fssm_Device
)
342 if (fssm
->fssm_Environ
> (BPTR
)0x64) {
343 de
= BADDR(fssm
->fssm_Environ
);
344 if (de
->de_TableSize
< 15)
348 NewRawDoFmt("%c%10s: %4d %s-%ld", RAWFMTFUNC_STRING
, text
,
349 (DOSBootBase
->db_BootNode
== bn
) ? '*' : IsBootableNode(bn
) ? '+' : ' ',
350 AROS_BSTR_ADDR(dn
->dn_Name
),
352 AROS_BSTR_ADDR(fssm
->fssm_Device
),
354 Move(win
->RPort
, 20, y
);
355 Text(win
->RPort
, text
, strlen(text
));
358 devopen
= ismedia
= FALSE
;
359 if ((port
= (struct MsgPort
*)CreateMsgPort())) {
360 if ((io
= (struct IOStdReq
*)CreateIORequest(port
, sizeof(struct IOStdReq
)))) {
361 if (!OpenDevice(AROS_BSTR_ADDR(fssm
->fssm_Device
), fssm
->fssm_Unit
, (struct IORequest
*)io
, fssm
->fssm_Flags
)) {
363 io
->io_Command
= TD_CHANGESTATE
;
365 DoIO((struct IORequest
*)io
);
366 if (!io
->io_Error
&& io
->io_Actual
== 0)
368 CloseDevice((struct IORequest
*)io
);
370 DeleteIORequest((struct IORequest
*)io
);
376 for (i
= 0; i
< 4; i
++) {
377 dostype
[i
] = (de
->de_DosType
>> ((3 - i
) * 8)) & 0xff;
380 else if (dostype
[i
] < 32)
385 size
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) * de
->de_Surfaces
* de
->de_BlocksPerTrack
;
386 /* try to prevent ULONG overflow */
387 if (de
->de_SizeBlock
<= 128)
390 size
*= de
->de_SizeBlock
/ 256;
392 NewRawDoFmt("%s [%08lx] %ldk", RAWFMTFUNC_STRING
, text
,
393 dostype
, de
->de_DosType
,
396 } else if (!devopen
) {
397 textp
= "[device open error]";
398 } else if (!ismedia
) {
399 textp
= "[no media]";
402 Move(win
->RPort
, 400, y
);
403 Text(win
->RPort
, textp
, strlen(textp
));
412 static void centertext(LIBBASETYPEPTR DOSBootBase
, BYTE pen
, WORD y
, const char *text
)
414 struct Window
*win
= DOSBootBase
->bm_Window
;
415 SetAPen(win
->RPort
, pen
);
416 Move(win
->RPort
, win
->Width
/ 2 - TextLength(win
->RPort
, text
, strlen(text
)) / 2, y
);
417 Text(win
->RPort
, text
, strlen(text
));
420 static void initPage(LIBBASETYPEPTR DOSBootBase
, WORD page
)
424 if (page
== PAGE_DISPLAY
)
425 text
= "Display Options";
426 else if (page
== PAGE_EXPANSION
)
427 text
= "Expansion Board Diagnostic";
428 else if (page
== PAGE_BOOT
)
429 text
= "Boot Options";
431 text
= "AROS Early Startup Control";
432 centertext(DOSBootBase
, 2, 10, text
);
434 if (page
== PAGE_BOOT
)
435 initPageBoot(DOSBootBase
);
436 else if (page
== PAGE_EXPANSION
)
437 initPageExpansion(DOSBootBase
);
439 if (page
== PAGE_MAIN
&& (GfxBase
->DisplayFlags
& (NTSC
| PAL
))) {
440 ULONG modeid
= GetVPModeID(&DOSBootBase
->bm_Screen
->ViewPort
);
441 if (modeid
!= INVALID_ID
&& (((modeid
& MONITOR_ID_MASK
) == NTSC_MONITOR_ID
) || ((modeid
& MONITOR_ID_MASK
) == PAL_MONITOR_ID
))) {
442 centertext(DOSBootBase
, 1, 30, "(press a key to toggle the display between PAL and NTSC)");
446 if (page
== PAGE_BOOT
)
448 centertext(DOSBootBase
, 1, 30, "Press A-J to select boot device");
449 centertext(DOSBootBase
, 1, 45, "\"+\" => bootable, \"*\" => selected for boot");
453 static WORD
initWindow(LIBBASETYPEPTR DOSBootBase
, struct BootConfig
*bcfg
, WORD page
)
455 struct Gadget
*first
= NULL
;
458 if ((first
= createGadgets(DOSBootBase
, page
)) != NULL
)
460 struct NewWindow nw
=
462 0, 0, /* Left, Top */
463 DOSBootBase
->bm_Screen
->Width
, /* Width, Height */
464 DOSBootBase
->bm_Screen
->Height
,
465 0, 1, /* DetailPen, BlockPen */
466 IDCMP_MOUSEBUTTONS
| IDCMP_MOUSEMOVE
| IDCMP_VANILLAKEY
| IDCMP_GADGETUP
| IDCMP_GADGETDOWN
, /* IDCMPFlags */
467 WFLG_SMART_REFRESH
| WFLG_BORDERLESS
| WFLG_ACTIVATE
, /* Flags */
468 first
, /* FirstGadget */
469 NULL
, /* CheckMark */
471 DOSBootBase
->bm_Screen
, /* Screen */
473 0, 0, /* MinWidth, MinHeight */
474 0, 0, /* MaxWidth, MaxHeight */
475 CUSTOMSCREEN
, /* Type */
478 D(bug("[BootMenu] initPage: Gadgets created @ %p\n", first
));
480 if ((DOSBootBase
->bm_Window
= OpenWindow(&nw
)) != NULL
)
482 D(bug("[BootMenu] initScreen: Window opened @ %p\n", DOSBootBase
->bm_Window
));
483 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", DOSBootBase
->bm_Window
->RPort
));
484 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", DOSBootBase
->bm_Window
->UserPort
));
485 initPage(DOSBootBase
, page
);
486 newpage
= msgLoop(DOSBootBase
, DOSBootBase
->bm_Window
);
488 CloseWindow(DOSBootBase
->bm_Window
);
490 freeGadgets(DOSBootBase
, page
);
495 static BOOL
initScreen(LIBBASETYPEPTR DOSBootBase
, struct BootConfig
*bcfg
)
499 D(bug("[BootMenu] initScreen()\n"));
502 DOSBootBase
->bm_Screen
= OpenBootScreen(DOSBootBase
);
503 if (DOSBootBase
->bm_Screen
)
505 DOSBootBase
->bottomY
= DOSBootBase
->bm_Screen
->Height
- (DOSBootBase
->bm_Screen
->Height
> 256 ? 32 : 16);
506 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", DOSBootBase
->bm_Screen
));
510 page
= initWindow(DOSBootBase
, bcfg
, page
);
511 } while (page
!= EXIT_BOOT
&& page
!= EXIT_BOOT_WNSS
);
512 CloseBootScreen(DOSBootBase
->bm_Screen
, DOSBootBase
);
517 /* From keyboard.device/keyboard_intern.h */
518 #define KB_MAXKEYS 256
519 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
520 #define ioStd(x) ((struct IOStdReq *)x)
522 static BOOL
buttonsPressed(LIBBASETYPEPTR DOSBootBase
)
524 BOOL success
= FALSE
;
525 struct MsgPort
*mp
= NULL
;
526 UBYTE matrix
[KB_MATRIXSIZE
];
530 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
531 * Let's check mouse buttons.
533 if (OpenResource("ciaa.resource"))
535 volatile UBYTE
*cia
= (UBYTE
*)0xbfe001;
536 volatile UWORD
*potinp
= (UWORD
*)0xdff016;
538 /* check left + right mouse button state */
539 if ((cia
[0] & 0x40) == 0 && (potinp
[0] & 0x0400) == 0)
544 if ((mp
= CreateMsgPort()) != NULL
)
546 struct IORequest
*io
= NULL
;
547 if ((io
= CreateIORequest(mp
, sizeof ( struct IOStdReq
))) != NULL
)
549 if (0 == OpenDevice("keyboard.device", 0, io
, 0))
551 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
552 ioStd(io
)->io_Command
= KBD_READMATRIX
;
553 ioStd(io
)->io_Data
= matrix
;
554 ioStd(io
)->io_Length
= sizeof(matrix
);
556 if (0 == io
->io_Error
)
560 bug("[BootMenu] buttonsPressed: Matrix : ");
561 for (i
= 0; i
< ioStd(io
)->io_Actual
; i
++)
563 bug("%02x ", matrix
[i
]);
567 if (matrix
[RAWKEY_SPACE
/8] & (1<<(RAWKEY_SPACE
%8)))
569 D(bug("[BootMenu] SPACEBAR pressed\n"));
582 int bootmenu_Init(LIBBASETYPEPTR LIBBASE
, BOOL WantBootMenu
)
584 BOOL bmi_RetVal
= FALSE
;
586 D(bug("[BootMenu] bootmenu_Init()\n"));
588 #ifdef INITHIDDS_KLUDGE
590 * PCI hardware display drivers still need external initialization.
591 * This urgently needs to be fixed. After fixing this kludge
592 * will not be needed any more.
594 InitBootConfig(&LIBBASE
->bm_BootConfig
);
595 if (!initHidds(LIBBASE
))
599 /* check keyboard if needed */
601 WantBootMenu
= buttonsPressed(LIBBASE
);
603 /* Bring up early startup menu if requested */
606 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
607 bmi_RetVal
= initScreen(LIBBASE
, &LIBBASE
->bm_BootConfig
);