Fixed handling of symbolic links, pretend to have changed file owner.
[AROS.git] / rom / dosboot / menu.c
blobfc5651eeefbdf850dcfeab37c2da9593ca4ec35b
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Main bootmenu code
6 Lang: english
7 */
9 #include <aros/debug.h>
11 #include <proto/bootloader.h>
12 #include <proto/exec.h>
13 #include <proto/graphics.h>
14 #include <proto/intuition.h>
15 #include <proto/oop.h>
16 #include <devices/keyboard.h>
17 #include <devices/rawkeycodes.h>
18 #include <devices/timer.h>
19 #include <exec/memory.h>
20 #include <graphics/driver.h>
21 #include <libraries/expansionbase.h>
22 #include <aros/bootloader.h>
23 #include <aros/symbolsets.h>
25 #include LC_LIBDEFS_FILE
27 #include "dosboot_intern.h"
28 #include "menu.h"
30 static BOOL init_gfx(STRPTR gfxclassname, BOOL bootmode, LIBBASETYPEPTR DOSBootBase)
32 OOP_Object *gfxhidd;
33 BOOL success = FALSE;
35 D(bug("[BootMenu] init_gfx('%s')\n", gfxclassname));
37 GfxBase = (void *)OpenLibrary("graphics.library", 41);
38 if (!GfxBase)
39 return FALSE;
41 gfxhidd = OOP_NewObject(NULL, gfxclassname, NULL);
42 if (gfxhidd) {
43 if (AddDisplayDriver(gfxhidd, DDRV_BootMode, bootmode, TAG_DONE))
44 OOP_DisposeObject(gfxhidd);
45 else
46 success = TRUE;
49 CloseLibrary(&GfxBase->LibNode);
51 ReturnBool ("init_gfxhidd", success);
54 static BOOL initHidds(LIBBASETYPEPTR DOSBootBase)
56 struct BootConfig *bootcfg = &DOSBootBase->bm_BootConfig;
58 D(bug("[BootMenu] initHidds()\n"));
60 if (bootcfg->gfxhidd) {
61 if (!OpenLibrary(bootcfg->gfxlib, 0))
62 return FALSE;
64 if (!init_gfx(bootcfg->gfxhidd, bootcfg->bootmode, DOSBootBase))
65 return FALSE;
68 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
69 return TRUE;
72 static struct Gadget *createGadgets(LIBBASETYPEPTR DOSBootBase)
74 /* FIXME: This is very unclean! free-up resources if we fail! */
76 /* Create Option Gadgets */
77 DOSBootBase->bm_MainGadgets.bootopt = createButton(
78 180, 63, 280, 14,
79 NULL, "Boot Options...",
80 BUTTON_BOOT_OPTIONS, (struct DOSBootBase *)DOSBootBase);
81 if (DOSBootBase->bm_MainGadgets.bootopt == NULL)
82 return NULL;
84 DOSBootBase->bm_MainGadgets.displayopt = createButton(
85 180, 84, 280, 14,
86 DOSBootBase->bm_MainGadgets.bootopt->gadget, "Display Options...",
87 BUTTON_DISPLAY_OPTIONS, (struct DOSBootBase *)DOSBootBase);
88 if (DOSBootBase->bm_MainGadgets.displayopt == NULL)
89 return NULL;
91 DOSBootBase->bm_MainGadgets.expboarddiag = createButton(
92 180, 105, 280, 14,
93 DOSBootBase->bm_MainGadgets.displayopt->gadget, "Expansion Board Diagnostic...",
94 BUTTON_EXPBOARDDIAG, (struct DOSBootBase *)DOSBootBase);
95 if (DOSBootBase->bm_MainGadgets.expboarddiag == NULL)
96 return NULL;
98 /* Create BOOT Gadgets */
99 DOSBootBase->bm_MainGadgets.boot = createButton(
100 16, 184, 280, 14,
101 DOSBootBase->bm_MainGadgets.expboarddiag->gadget, "Boot",
102 BUTTON_BOOT, (struct DOSBootBase *)DOSBootBase);
103 if (DOSBootBase->bm_MainGadgets.boot == NULL)
104 return NULL;
106 DOSBootBase->bm_MainGadgets.bootnss = createButton(
107 344, 184, 280, 14,
108 DOSBootBase->bm_MainGadgets.boot->gadget, "Boot With No Startup-Sequence",
109 BUTTON_BOOT_WNSS, (struct DOSBootBase *)DOSBootBase);
110 if (DOSBootBase->bm_MainGadgets.bootnss == NULL)
111 return NULL;
113 return DOSBootBase->bm_MainGadgets.bootopt->gadget;
116 static void freeGadgets(LIBBASETYPEPTR DOSBootBase)
118 if (DOSBootBase->bm_MainGadgets.boot != NULL)
119 freeButtonGadget(DOSBootBase->bm_MainGadgets.boot, (struct DOSBootBase *)DOSBootBase);
120 if (DOSBootBase->bm_MainGadgets.bootnss != NULL);
121 freeButtonGadget(DOSBootBase->bm_MainGadgets.bootnss, (struct DOSBootBase *)DOSBootBase);
122 if (DOSBootBase->bm_MainGadgets.bootopt != NULL)
123 freeButtonGadget(DOSBootBase->bm_MainGadgets.bootopt, (struct DOSBootBase *)DOSBootBase);
124 if (DOSBootBase->bm_MainGadgets.displayopt != NULL)
125 freeButtonGadget(DOSBootBase->bm_MainGadgets.displayopt, (struct DOSBootBase *)DOSBootBase);
126 if (DOSBootBase->bm_MainGadgets.expboarddiag != NULL)
127 freeButtonGadget(DOSBootBase->bm_MainGadgets.expboarddiag, (struct DOSBootBase *)DOSBootBase);
130 static void msgLoop(LIBBASETYPEPTR DOSBootBase, struct Window *win)
132 BOOL exit = FALSE;
133 struct IntuiMessage *msg;
134 struct Gadget *g;
136 D(bug("[BootMenu] msgLoop(DOSBootBase @ %p, Window @ %p)\n", DOSBootBase, win));
140 if (win->UserPort)
142 WaitPort(win->UserPort);
143 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
145 if (msg->Class == IDCMP_GADGETUP)
147 g = msg->IAddress;
148 switch (g->GadgetID)
150 case BUTTON_BOOT:
151 DOSBootBase->BootFlags &= ~BF_NO_STARTUP_SEQUENCE;
152 exit = TRUE;
153 break;
154 case BUTTON_BOOT_WNSS:
155 DOSBootBase->BootFlags |= BF_NO_STARTUP_SEQUENCE;
156 exit = TRUE;
157 break;
160 ReplyMsg((struct Message *)msg);
163 else
165 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
166 Wait(0);
168 } while (exit == FALSE);
169 while ((msg=(struct IntuiMessage *)GetMsg(win->UserPort)))
170 ReplyMsg(&msg->ExecMessage);
173 static BOOL initScreen(LIBBASETYPEPTR DOSBootBase, struct BootConfig *bcfg)
175 struct Screen *bm_Screen;
176 struct Gadget *first = NULL;
177 BOOL res = FALSE;
179 D(bug("[BootMenu] initScreen()\n"));
181 bm_Screen = OpenBootScreen(DOSBootBase);
182 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", bm_Screen));
184 if ((first = createGadgets(DOSBootBase)) != NULL)
186 struct NewWindow nw =
188 0, 0, /* Left, Top */
189 bm_Screen->Width, /* Width, Height */
190 bm_Screen->Height,
191 0, 1, /* DetailPen, BlockPen */
192 IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_GADGETDOWN, /* IDCMPFlags */
193 WFLG_SMART_REFRESH | WFLG_BORDERLESS | WFLG_ACTIVATE, /* Flags */
194 first, /* FirstGadget */
195 NULL, /* CheckMark */
196 NULL, /* Title */
197 bm_Screen, /* Screen */
198 NULL, /* BitMap */
199 0, 0, /* MinWidth, MinHeight */
200 0, 0, /* MaxWidth, MaxHeight */
201 CUSTOMSCREEN, /* Type */
204 D(bug("[BootMenu] initScreen: Gadgets created @ %p\n", first));
206 if ((DOSBootBase->bm_Window = OpenWindow(&nw)) != NULL)
208 D(bug("[BootMenu] initScreen: Window opened @ %p\n", DOSBootBase->bm_Window));
209 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", DOSBootBase->bm_Window->RPort));
210 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", DOSBootBase->bm_Window->UserPort));
211 SetAPen(DOSBootBase->bm_Window->RPort, 2);
212 D(bug("[BootMenu] initScreen: SetAPen 2\n"));
213 Move(DOSBootBase->bm_Window->RPort, 215, 20);
214 D(bug("[BootMenu] initScreen: Move(d) to 215, 20\n"));
215 Text(DOSBootBase->bm_Window->RPort, "AROS Early Startup Control", 26);
216 D(bug("[BootMenu] initScreen: Early Startup text displayed\n"));
217 #if defined(USE_PALNTSC)
218 #warning "TODO: Check if we are using a PAL/NTSC display mode ..."
219 SetAPen(DOSBootBase->bm_Window->RPort, 1);
220 Move(DOSBootBase->bm_Window->RPort, 225, 40);
221 Text(DOSBootBase->bm_Window->RPort, "(press a key to toggle the display between PAL and NTSC)", 23);
222 #endif
223 msgLoop(DOSBootBase, DOSBootBase->bm_Window);
224 res = TRUE;
226 CloseWindow(DOSBootBase->bm_Window);
227 freeGadgets(DOSBootBase);
230 CloseBootScreen(bm_Screen, DOSBootBase);
232 return res;
235 /* From keyboard.device/keyboard_intern.h */
236 #define KB_MAXKEYS 256
237 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
238 #define ioStd(x) ((struct IOStdReq *)x)
240 static BOOL buttonsPressed(LIBBASETYPEPTR DOSBootBase)
242 BOOL success = FALSE;
243 struct MsgPort *mp = NULL;
244 UBYTE matrix[KB_MATRIXSIZE];
246 #ifdef mc68000
248 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
249 * Let's check mouse buttons.
251 if (OpenResource("ciaa.resource"))
253 volatile UBYTE *cia = (UBYTE*)0xbfe001;
254 volatile UWORD *potinp = (UWORD*)0xdff016;
256 /* check left + right mouse button state */
257 if ((cia[0] & 0x40) == 0 && (potinp[0] & 0x0400) == 0)
258 return TRUE;
260 #endif
262 if ((mp = CreateMsgPort()) != NULL)
264 struct IORequest *io = NULL;
265 if ((io = CreateIORequest(mp, sizeof ( struct IOStdReq))) != NULL)
267 if (0 == OpenDevice("keyboard.device", 0, io, 0))
269 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
270 ioStd(io)->io_Command = KBD_READMATRIX;
271 ioStd(io)->io_Data = matrix;
272 ioStd(io)->io_Length = sizeof(matrix);
273 DoIO(io);
274 if (0 == io->io_Error)
277 int i;
278 bug("[BootMenu] buttonsPressed: Matrix : ");
279 for (i = 0; i < ioStd(io)->io_Actual; i ++)
281 bug("%02x ", matrix[i]);
283 bug("\n");
285 if (matrix[RAWKEY_SPACE/8] & (1<<(RAWKEY_SPACE%8)))
287 D(bug("[BootMenu] SPACEBAR pressed\n"));
288 success = TRUE;
291 CloseDevice(io);
293 DeleteIORequest(io);
295 DeleteMsgPort(mp);
297 return success;
300 int bootmenu_Init(LIBBASETYPEPTR LIBBASE)
302 struct BootLoaderBase *BootLoaderBase = OpenResource("bootloader.resource");
303 BOOL bmi_RetVal = FALSE;
304 BOOL WantBootMenu = FALSE;
306 D(bug("[BootMenu] bootmenu_Init()\n"));
308 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
309 #ifndef mc68000
311 * VGA and PCI hardware display drivers still need
312 * external initialization.
313 * This urgently needs to be fixed. After fixing this kludge
314 * will not be needed any more.
316 InitBootConfig(&LIBBASE->bm_BootConfig, BootLoaderBase);
317 #endif
318 #endif
320 /* Check for command line argument */
321 if (BootLoaderBase)
323 struct List *list = NULL;
324 struct Node *node = NULL;
326 if ((list = (struct List *)GetBootInfo(BL_Args)) != NULL)
328 ForeachNode(list,node)
330 if (0 == stricmp(node->ln_Name, "bootmenu"))
332 D(bug("[BootMenu] bootmenu_Init: Forced with bootloader argument\n"));
333 WantBootMenu = TRUE;
335 else if (0 == stricmp(node->ln_Name, "nomonitors"))
337 LIBBASE->BootFlags |= BF_NO_DISPLAY_DRIVERS;
339 else if (0 == strnicmp(node->ln_Name, "bootdevice=", 11))
341 LIBBASE->db_BootDevice = &node->ln_Name[11];
347 /* Initialize default HIDDs */
348 if (!initHidds(LIBBASE))
349 return FALSE;
351 /* check keyboard if needed */
352 if (!WantBootMenu)
353 WantBootMenu = buttonsPressed(LIBBASE);
355 /* Bring up early startup menu if requested */
356 if (WantBootMenu)
358 bmi_RetVal = FALSE;
360 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
361 bmi_RetVal = initScreen(LIBBASE, &LIBBASE->bm_BootConfig);
364 return bmi_RetVal;