- Include aros/config.h at almost all places where AROS_FLAVOUR is used.
[AROS.git] / rom / dosboot / menu.c
blob7b2970ba19e113aa3f4bd73e96c9f89a3c507dd3
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Main bootmenu code
6 Lang: english
7 */
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"
34 #include "menu.h"
36 #define PAGE_MAIN 1
37 #define PAGE_BOOT 2
38 #define PAGE_DISPLAY 3
39 #define PAGE_EXPANSION 4
40 #define EXIT_BOOT 5
41 #define EXIT_BOOT_WNSS 6
43 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
44 #ifndef mc68000
46 static BOOL init_gfx(STRPTR gfxclassname, BOOL bootmode, LIBBASETYPEPTR DOSBootBase)
48 OOP_Object *gfxhidd;
49 BOOL success = FALSE;
51 D(bug("[BootMenu] init_gfx('%s')\n", gfxclassname));
53 GfxBase = (void *)OpenLibrary("graphics.library", 41);
54 if (!GfxBase)
55 return FALSE;
57 gfxhidd = OOP_NewObject(NULL, gfxclassname, NULL);
58 if (gfxhidd) {
59 if (AddDisplayDriver(gfxhidd, DDRV_BootMode, bootmode, TAG_DONE))
60 OOP_DisposeObject(gfxhidd);
61 else
62 success = TRUE;
65 CloseLibrary(&GfxBase->LibNode);
67 ReturnBool ("init_gfxhidd", success);
70 static BOOL initHidds(LIBBASETYPEPTR DOSBootBase)
72 struct BootConfig *bootcfg = &DOSBootBase->bm_BootConfig;
74 D(bug("[BootMenu] initHidds()\n"));
76 if (bootcfg->gfxhidd) {
77 if (!OpenLibrary(bootcfg->gfxlib, 0))
78 return FALSE;
80 if (!init_gfx(bootcfg->gfxhidd, bootcfg->bootmode, DOSBootBase))
81 return FALSE;
84 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
85 return TRUE;
88 #endif
89 #endif
91 static struct Gadget *createGadgetsBoot(LIBBASETYPEPTR DOSBootBase)
93 /* Create Option Gadgets */
94 DOSBootBase->bm_MainGadgets.bootopt = createButton(
95 180, 63, 280, 14,
96 NULL, "Boot Options...",
97 BUTTON_BOOT_OPTIONS, (struct DOSBootBase *)DOSBootBase);
98 DOSBootBase->bm_MainGadgets.displayopt = createButton(
99 180, 84, 280, 14,
100 DOSBootBase->bm_MainGadgets.bootopt->gadget, "Display Options...",
101 BUTTON_DISPLAY_OPTIONS, (struct DOSBootBase *)DOSBootBase);
102 DOSBootBase->bm_MainGadgets.expboarddiag = createButton(
103 180, 105, 280, 14,
104 DOSBootBase->bm_MainGadgets.displayopt->gadget, "Expansion Board Diagnostic...",
105 BUTTON_EXPBOARDDIAG, (struct DOSBootBase *)DOSBootBase);
106 /* Create BOOT Gadgets */
107 DOSBootBase->bm_MainGadgets.boot = createButton(
108 16, DOSBootBase->bottomY, 280, 14,
109 DOSBootBase->bm_MainGadgets.expboarddiag->gadget, "Boot",
110 BUTTON_BOOT, (struct DOSBootBase *)DOSBootBase);
111 DOSBootBase->bm_MainGadgets.bootnss = createButton(
112 344, DOSBootBase->bottomY, 280, 14,
113 DOSBootBase->bm_MainGadgets.boot->gadget, "Boot With No Startup-Sequence",
114 BUTTON_BOOT_WNSS, (struct DOSBootBase *)DOSBootBase);
115 if (!DOSBootBase->bm_MainGadgets.bootopt ||
116 !DOSBootBase->bm_MainGadgets.displayopt ||
117 !DOSBootBase->bm_MainGadgets.expboarddiag ||
118 !DOSBootBase->bm_MainGadgets.boot ||
119 !DOSBootBase->bm_MainGadgets.bootnss)
120 return NULL;
121 return DOSBootBase->bm_MainGadgets.bootopt->gadget;
124 static struct Gadget *createGadgetsUseCancel(LIBBASETYPEPTR DOSBootBase)
126 DOSBootBase->bm_MainGadgets.use = createButton(
127 16, DOSBootBase->bottomY, 280, 14,
128 NULL, "Use",
129 BUTTON_USE, (struct DOSBootBase *)DOSBootBase);
130 DOSBootBase->bm_MainGadgets.cancel = createButton(
131 344, DOSBootBase->bottomY, 280, 14,
132 DOSBootBase->bm_MainGadgets.use->gadget, "Cancel",
133 BUTTON_CANCEL, (struct DOSBootBase *)DOSBootBase);
134 if (!DOSBootBase->bm_MainGadgets.use ||
135 !DOSBootBase->bm_MainGadgets.cancel)
136 return NULL;
137 return DOSBootBase->bm_MainGadgets.use->gadget;
141 static void freeGadgetsBoot(LIBBASETYPEPTR DOSBootBase)
143 freeButtonGadget(DOSBootBase->bm_MainGadgets.boot, (struct DOSBootBase *)DOSBootBase);
144 freeButtonGadget(DOSBootBase->bm_MainGadgets.bootnss, (struct DOSBootBase *)DOSBootBase);
145 freeButtonGadget(DOSBootBase->bm_MainGadgets.bootopt, (struct DOSBootBase *)DOSBootBase);
146 freeButtonGadget(DOSBootBase->bm_MainGadgets.displayopt, (struct DOSBootBase *)DOSBootBase);
147 freeButtonGadget(DOSBootBase->bm_MainGadgets.expboarddiag, (struct DOSBootBase *)DOSBootBase);
150 static void freeGadgetsUseCancel(LIBBASETYPEPTR DOSBootBase)
152 freeButtonGadget(DOSBootBase->bm_MainGadgets.use, (struct DOSBootBase *)DOSBootBase);
153 freeButtonGadget(DOSBootBase->bm_MainGadgets.cancel, (struct DOSBootBase *)DOSBootBase);
156 static struct Gadget *createGadgets(LIBBASETYPEPTR DOSBootBase, WORD page)
158 if (page == PAGE_MAIN)
159 return createGadgetsBoot(DOSBootBase);
160 else
161 return createGadgetsUseCancel(DOSBootBase);
163 static void freeGadgets(LIBBASETYPEPTR DOSBootBase, WORD page)
165 if (page == PAGE_MAIN)
166 freeGadgetsBoot(DOSBootBase);
167 else
168 freeGadgetsUseCancel(DOSBootBase);
171 static void toggleMode(LIBBASETYPEPTR DOSBootBase)
173 #ifdef mc68000
175 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
177 if (OpenResource("ciaa.resource")) {
178 volatile UWORD *beamcon0 = (UWORD*)0xdff1dc;
179 GfxBase->DisplayFlags ^= PAL | NTSC;
180 *beamcon0 = (GfxBase->DisplayFlags & PAL) ? 0x0020 : 0x0000;
182 #endif
185 static UWORD msgLoop(LIBBASETYPEPTR DOSBootBase, struct Window *win)
187 WORD exit = -1;
188 struct IntuiMessage *msg;
189 struct Gadget *g;
191 D(bug("[BootMenu] msgLoop(DOSBootBase @ %p, Window @ %p)\n", DOSBootBase, win));
195 if (win->UserPort)
197 WaitPort(win->UserPort);
198 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
200 if (msg->Class == IDCMP_VANILLAKEY) {
201 if (msg->Code == 27)
202 exit = PAGE_MAIN;
203 else if (msg->Code >= '1' && msg->Code <= '3')
204 exit = PAGE_MAIN + msg->Code - '0';
205 else
206 toggleMode(DOSBootBase);
207 } else if (msg->Class == IDCMP_GADGETUP)
209 g = msg->IAddress;
210 switch (g->GadgetID)
212 case BUTTON_BOOT:
213 DOSBootBase->db_BootFlags &= ~BF_NO_STARTUP_SEQUENCE;
214 exit = EXIT_BOOT;
215 break;
216 case BUTTON_BOOT_WNSS:
217 DOSBootBase->db_BootFlags |= BF_NO_STARTUP_SEQUENCE;
218 exit = EXIT_BOOT_WNSS;
219 break;
220 case BUTTON_USE:
221 case BUTTON_CANCEL:
222 case BUTTON_CONTINUE:
223 exit = PAGE_MAIN;
224 break;
225 case BUTTON_BOOT_OPTIONS:
226 exit = PAGE_BOOT;
227 break;
228 case BUTTON_EXPBOARDDIAG:
229 exit = PAGE_EXPANSION;
230 break;
231 case BUTTON_DISPLAY_OPTIONS:
232 exit = PAGE_DISPLAY;
233 break;
236 ReplyMsg((struct Message *)msg);
239 else
241 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
242 Wait(0);
244 } while (exit < 0);
245 while ((msg=(struct IntuiMessage *)GetMsg(win->UserPort)))
246 ReplyMsg(&msg->ExecMessage);
247 return exit;
250 static void initPageExpansion(LIBBASETYPEPTR DOSBootBase)
252 struct Window *win = DOSBootBase->bm_Window;
253 struct ExpansionBase *ExpansionBase = DOSBootBase->bm_ExpansionBase;
254 struct ConfigDev *cd;
255 WORD y = 50, cnt;
256 char text[100];
258 SetAPen(win->RPort, 1);
259 cd = NULL;
260 cnt = 0;
261 while ((cd = FindConfigDev(cd, -1, -1))) {
262 NewRawDoFmt("%2d: %08lx - %08lx (%08lx) %5d %3d %08lx", RAWFMTFUNC_STRING, text,
263 ++cnt,
264 cd->cd_BoardAddr, cd->cd_BoardAddr + cd->cd_BoardSize - 1, cd->cd_BoardSize,
265 cd->cd_Rom.er_Manufacturer, cd->cd_Rom.er_Product, cd->cd_Rom.er_SerialNumber);
266 if ((cd->cd_Rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII)
267 strcat(text, " Z3");
268 else if ((cd->cd_Rom.er_Type & ERT_TYPEMASK) == ERT_ZORROII)
269 strcat(text, " Z2");
270 else
271 strcat(text, " ");
272 if (cd->cd_Rom.er_Type & ERTF_DIAGVALID)
273 strcat(text, " ROM");
274 if (cd->cd_Rom.er_Type & ERTF_MEMLIST)
275 strcat(text, " RAM");
276 Move(win->RPort, 20, y);
277 Text(win->RPort, text, strlen(text));
278 y += 16;
282 static BOOL bstreqcstr(BSTR bstr, CONST_STRPTR cstr)
284 int clen;
285 int blen;
287 clen = strlen(cstr);
288 blen = AROS_BSTR_strlen(bstr);
289 if (clen != blen)
290 return FALSE;
292 return (memcmp(AROS_BSTR_ADDR(bstr),cstr,clen) == 0);
295 void selectBootDevice(LIBBASETYPEPTR DOSBootBase)
297 struct BootNode *bn;
299 if (DOSBootBase->db_BootDevice == NULL &&
300 DOSBootBase->db_BootNode != NULL)
301 return;
303 Forbid(); /* .. access to ExpansionBase->MountList */
305 if (DOSBootBase->db_BootNode == NULL && DOSBootBase->db_BootDevice == NULL)
307 bn = (APTR)GetHead(&DOSBootBase->bm_ExpansionBase->MountList);
309 else
311 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, bn)
313 struct DeviceNode *dn;
315 dn = bn->bn_DeviceNode;
316 if (dn == NULL || dn->dn_Name == BNULL)
317 continue;
319 if (bstreqcstr(dn->dn_Name, DOSBootBase->db_BootDevice))
320 break;
324 Permit();
326 DOSBootBase->db_BootNode = bn;
327 DOSBootBase->db_BootDevice = NULL;
330 /* This makes the selected boot device the actual
331 * boot device. It also updates the boot flags.
333 static void setBootDevice(LIBBASETYPEPTR DOSBootBase)
335 struct BootNode *bn;
337 bn = DOSBootBase->db_BootNode;
339 if (bn != NULL)
341 Remove((struct Node *)bn);
342 bn->bn_Node.ln_Type = NT_BOOTNODE;
343 bn->bn_Node.ln_Pri = 127;
344 /* We use AddHead() instead of Enqueue() here
345 * to *insure* that this gets to the front of
346 * the boot list.
348 AddHead(&DOSBootBase->bm_ExpansionBase->MountList, (struct Node *)&bn);
351 DOSBootBase->bm_ExpansionBase->eb_BootFlags = DOSBootBase->db_BootFlags;
354 static void initPageBoot(LIBBASETYPEPTR DOSBootBase)
356 struct Window *win = DOSBootBase->bm_Window;
357 struct BootNode *bn;
358 WORD y = 50;
359 char text[100], *textp;
361 SetAPen(win->RPort, 1);
363 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, bn)
365 struct DeviceNode *dn = bn->bn_DeviceNode;
366 struct FileSysStartupMsg *fssm = BADDR(dn->dn_Startup);
367 struct DosEnvec *de = NULL;
368 struct IOStdReq *io;
369 struct MsgPort *port;
370 char dostype[5];
371 UBYTE i;
372 ULONG size;
373 BOOL devopen, ismedia;
375 if (y >= DOSBootBase->bottomY - 20)
376 break;
377 if (!fssm || !fssm->fssm_Device)
378 continue;
379 if (fssm->fssm_Environ > (BPTR)0x64) {
380 de = BADDR(fssm->fssm_Environ);
381 if (de->de_TableSize < 15)
382 de = NULL;
385 NewRawDoFmt("%c%10s: %4d %s-%ld", RAWFMTFUNC_STRING, text,
386 IsBootableNode(bn) ?
387 ((DOSBootBase->db_BootNode == bn) ? '*' : '+')
388 : ' ',
389 AROS_BSTR_ADDR(dn->dn_Name),
390 bn->bn_Node.ln_Pri,
391 AROS_BSTR_ADDR(fssm->fssm_Device),
392 fssm->fssm_Unit);
393 Move(win->RPort, 20, y);
394 Text(win->RPort, text, strlen(text));
396 textp = NULL;
397 devopen = ismedia = FALSE;
398 if ((port = (struct MsgPort*)CreateMsgPort())) {
399 if ((io = (struct IOStdReq*)CreateIORequest(port, sizeof(struct IOStdReq)))) {
400 if (!OpenDevice(AROS_BSTR_ADDR(fssm->fssm_Device), fssm->fssm_Unit, (struct IORequest*)io, fssm->fssm_Flags)) {
401 devopen = TRUE;
402 io->io_Command = TD_CHANGESTATE;
403 io->io_Actual = 1;
404 DoIO((struct IORequest*)io);
405 if (!io->io_Error && io->io_Actual == 0)
406 ismedia = TRUE;
407 CloseDevice((struct IORequest*)io);
409 DeleteIORequest((struct IORequest*)io);
411 DeleteMsgPort(port);
414 if (de && ismedia) {
415 for (i = 0; i < 4; i++) {
416 dostype[i] = (de->de_DosType >> ((3 - i) * 8)) & 0xff;
417 if (dostype[i] < 9)
418 dostype[i] += '0';
419 else if (dostype[i] < 32)
420 dostype[i] = '.';
422 dostype[4] = 0;
424 size = (de->de_HighCyl - de->de_LowCyl + 1) * de->de_Surfaces * de->de_BlocksPerTrack;
425 /* try to prevent ULONG overflow */
426 if (de->de_SizeBlock <= 128)
427 size /= 2;
428 else
429 size *= de->de_SizeBlock / 256;
431 NewRawDoFmt("%s [%08lx] %ldk", RAWFMTFUNC_STRING, text,
432 dostype, de->de_DosType,
433 size);
434 textp = text;
435 } else if (!devopen) {
436 textp = "[device open error]";
437 } else if (!ismedia) {
438 textp = "[no media]";
440 if (textp) {
441 Move(win->RPort, 400, y);
442 Text(win->RPort, textp, strlen(textp));
445 y += 16;
451 static void centertext(LIBBASETYPEPTR DOSBootBase, BYTE pen, WORD y, const char *text)
453 struct Window *win = DOSBootBase->bm_Window;
454 SetAPen(win->RPort, pen);
455 Move(win->RPort, win->Width / 2 - TextLength(win->RPort, text, strlen(text)) / 2, y);
456 Text(win->RPort, text, strlen(text));
459 static void initPage(LIBBASETYPEPTR DOSBootBase, WORD page)
461 UBYTE *text;
463 if (page == PAGE_DISPLAY)
464 text = "Display Options";
465 else if (page == PAGE_EXPANSION)
466 text = "Expansion Board Diagnostic";
467 else if (page == PAGE_BOOT)
468 text = "Boot Options";
469 else
470 text = "AROS Early Startup Control";
471 centertext(DOSBootBase, 2, 10, text);
473 if (page == PAGE_BOOT)
474 initPageBoot(DOSBootBase);
475 else if (page == PAGE_EXPANSION)
476 initPageExpansion(DOSBootBase);
478 if (page == PAGE_MAIN && (GfxBase->DisplayFlags & (NTSC | PAL))) {
479 ULONG modeid = GetVPModeID(&DOSBootBase->bm_Screen->ViewPort);
480 if (modeid != INVALID_ID && (((modeid & MONITOR_ID_MASK) == NTSC_MONITOR_ID) || ((modeid & MONITOR_ID_MASK) == PAL_MONITOR_ID))) {
481 centertext(DOSBootBase, 1, 30, "(press a key to toggle the display between PAL and NTSC)");
486 static WORD initWindow(LIBBASETYPEPTR DOSBootBase, struct BootConfig *bcfg, WORD page)
488 struct Gadget *first = NULL;
489 WORD newpage = -1;
491 if ((first = createGadgets(DOSBootBase, page)) != NULL)
493 struct NewWindow nw =
495 0, 0, /* Left, Top */
496 DOSBootBase->bm_Screen->Width, /* Width, Height */
497 DOSBootBase->bm_Screen->Height,
498 0, 1, /* DetailPen, BlockPen */
499 IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_GADGETDOWN, /* IDCMPFlags */
500 WFLG_SMART_REFRESH | WFLG_BORDERLESS | WFLG_ACTIVATE, /* Flags */
501 first, /* FirstGadget */
502 NULL, /* CheckMark */
503 NULL, /* Title */
504 DOSBootBase->bm_Screen, /* Screen */
505 NULL, /* BitMap */
506 0, 0, /* MinWidth, MinHeight */
507 0, 0, /* MaxWidth, MaxHeight */
508 CUSTOMSCREEN, /* Type */
511 D(bug("[BootMenu] initPage: Gadgets created @ %p\n", first));
513 if ((DOSBootBase->bm_Window = OpenWindow(&nw)) != NULL)
515 D(bug("[BootMenu] initScreen: Window opened @ %p\n", DOSBootBase->bm_Window));
516 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", DOSBootBase->bm_Window->RPort));
517 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", DOSBootBase->bm_Window->UserPort));
518 initPage(DOSBootBase, page);
519 newpage = msgLoop(DOSBootBase, DOSBootBase->bm_Window);
521 CloseWindow(DOSBootBase->bm_Window);
523 freeGadgets(DOSBootBase, page);
525 return newpage;
528 static BOOL initScreen(LIBBASETYPEPTR DOSBootBase, struct BootConfig *bcfg)
530 WORD page;
532 D(bug("[BootMenu] initScreen()\n"));
534 page = -1;
535 DOSBootBase->bm_Screen = OpenBootScreen(DOSBootBase);
536 if (DOSBootBase->bm_Screen)
538 DOSBootBase->bottomY = DOSBootBase->bm_Screen->Height - (DOSBootBase->bm_Screen->Height > 256 ? 32 : 16);
539 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", DOSBootBase->bm_Screen));
541 page = PAGE_MAIN;
542 do {
543 page = initWindow(DOSBootBase, bcfg, page);
544 } while (page != EXIT_BOOT && page != EXIT_BOOT_WNSS);
545 CloseBootScreen(DOSBootBase->bm_Screen, DOSBootBase);
547 return page >= 0;
550 /* From keyboard.device/keyboard_intern.h */
551 #define KB_MAXKEYS 256
552 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
553 #define ioStd(x) ((struct IOStdReq *)x)
555 static BOOL buttonsPressed(LIBBASETYPEPTR DOSBootBase)
557 BOOL success = FALSE;
558 struct MsgPort *mp = NULL;
559 UBYTE matrix[KB_MATRIXSIZE];
561 #ifdef mc68000
563 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
564 * Let's check mouse buttons.
566 if (OpenResource("ciaa.resource"))
568 volatile UBYTE *cia = (UBYTE*)0xbfe001;
569 volatile UWORD *potinp = (UWORD*)0xdff016;
571 /* check left + right mouse button state */
572 if ((cia[0] & 0x40) == 0 && (potinp[0] & 0x0400) == 0)
573 return TRUE;
575 #endif
577 if ((mp = CreateMsgPort()) != NULL)
579 struct IORequest *io = NULL;
580 if ((io = CreateIORequest(mp, sizeof ( struct IOStdReq))) != NULL)
582 if (0 == OpenDevice("keyboard.device", 0, io, 0))
584 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
585 ioStd(io)->io_Command = KBD_READMATRIX;
586 ioStd(io)->io_Data = matrix;
587 ioStd(io)->io_Length = sizeof(matrix);
588 DoIO(io);
589 if (0 == io->io_Error)
592 int i;
593 bug("[BootMenu] buttonsPressed: Matrix : ");
594 for (i = 0; i < ioStd(io)->io_Actual; i ++)
596 bug("%02x ", matrix[i]);
598 bug("\n");
600 if (matrix[RAWKEY_SPACE/8] & (1<<(RAWKEY_SPACE%8)))
602 D(bug("[BootMenu] SPACEBAR pressed\n"));
603 success = TRUE;
606 CloseDevice(io);
608 DeleteIORequest(io);
610 DeleteMsgPort(mp);
612 return success;
615 int bootmenu_Init(LIBBASETYPEPTR LIBBASE, BOOL WantBootMenu)
617 BOOL bmi_RetVal = FALSE;
619 D(bug("[BootMenu] bootmenu_Init()\n"));
621 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
622 #ifndef mc68000
624 * VGA and PCI hardware display drivers still need
625 * external initialization.
626 * This urgently needs to be fixed. After fixing this kludge
627 * will not be needed any more.
629 InitBootConfig(&LIBBASE->bm_BootConfig);
630 if (!initHidds(LIBBASE))
631 return FALSE;
632 #endif
633 #endif
635 /* check keyboard if needed */
636 if (!WantBootMenu)
637 WantBootMenu = buttonsPressed(LIBBASE);
639 /* Bring up early startup menu if requested */
640 if (WantBootMenu)
642 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
643 bmi_RetVal = initScreen(LIBBASE, &LIBBASE->bm_BootConfig);
646 /* Make the user's select the top boot device */
647 setBootDevice(LIBBASE);
649 return bmi_RetVal;