gcc-4.6.2: Update with patch for gengtype.c
[AROS.git] / rom / dosboot / menu.c
blob604280a97b781482ff4930a24259583ba4df5663
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 #ifdef __ppc__
45 #define INITHIDDS_KLUDGE
46 #endif
47 #endif
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)
58 OOP_Class *gfxclass;
59 BOOL success = FALSE;
61 D(bug("[BootMenu] init_gfx('%s')\n", gfxclassname));
63 GfxBase = (void *)OpenLibrary("graphics.library", 41);
64 if (!GfxBase)
65 return FALSE;
67 gfxclass = OOP_FindClass(gfxclassname);
68 if (gfxclass)
70 if (!AddDisplayDriver(gfxclass, NULL, DDRV_BootMode, bootmode, TAG_DONE))
71 success = TRUE;
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))
87 return FALSE;
89 if (!init_gfx(bootcfg->gfxhidd, bootcfg->bootmode, DOSBootBase))
90 return FALSE;
93 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
94 return TRUE;
97 #endif
99 static struct Gadget *createGadgetsBoot(LIBBASETYPEPTR DOSBootBase)
101 /* Create Option Gadgets */
102 DOSBootBase->bm_MainGadgets.bootopt = createButton(
103 180, 63, 280, 14,
104 NULL, "Boot Options...",
105 BUTTON_BOOT_OPTIONS, (struct DOSBootBase *)DOSBootBase);
106 DOSBootBase->bm_MainGadgets.displayopt = createButton(
107 180, 84, 280, 14,
108 DOSBootBase->bm_MainGadgets.bootopt->gadget, "Display Options...",
109 BUTTON_DISPLAY_OPTIONS, (struct DOSBootBase *)DOSBootBase);
110 DOSBootBase->bm_MainGadgets.expboarddiag = createButton(
111 180, 105, 280, 14,
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)
128 return NULL;
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,
136 NULL, "Use",
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)
144 return NULL;
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);
168 else
169 return createGadgetsUseCancel(DOSBootBase);
171 static void freeGadgets(LIBBASETYPEPTR DOSBootBase, WORD page)
173 if (page == PAGE_MAIN)
174 freeGadgetsBoot(DOSBootBase);
175 else
176 freeGadgetsUseCancel(DOSBootBase);
179 static void toggleMode(LIBBASETYPEPTR DOSBootBase)
181 #ifdef mc68000
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;
190 #endif
193 static UWORD msgLoop(LIBBASETYPEPTR DOSBootBase, struct Window *win)
195 WORD exit = -1;
196 struct IntuiMessage *msg;
197 struct Gadget *g;
199 D(bug("[BootMenu] msgLoop(DOSBootBase @ %p, Window @ %p)\n", DOSBootBase, win));
203 if (win->UserPort)
205 WaitPort(win->UserPort);
206 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
208 if (msg->Class == IDCMP_VANILLAKEY) {
209 if (msg->Code == 27)
210 exit = PAGE_MAIN;
211 else if (msg->Code >= '1' && msg->Code <= '3')
212 exit = PAGE_MAIN + msg->Code - '0';
213 else
214 toggleMode(DOSBootBase);
215 } else if (msg->Class == IDCMP_GADGETUP)
217 g = msg->IAddress;
218 switch (g->GadgetID)
220 case BUTTON_BOOT:
221 DOSBootBase->db_BootFlags &= ~BF_NO_STARTUP_SEQUENCE;
222 exit = EXIT_BOOT;
223 break;
224 case BUTTON_BOOT_WNSS:
225 DOSBootBase->db_BootFlags |= BF_NO_STARTUP_SEQUENCE;
226 exit = EXIT_BOOT_WNSS;
227 break;
228 case BUTTON_USE:
229 case BUTTON_CANCEL:
230 case BUTTON_CONTINUE:
231 exit = PAGE_MAIN;
232 break;
233 case BUTTON_BOOT_OPTIONS:
234 exit = PAGE_BOOT;
235 break;
236 case BUTTON_EXPBOARDDIAG:
237 exit = PAGE_EXPANSION;
238 break;
239 case BUTTON_DISPLAY_OPTIONS:
240 exit = PAGE_DISPLAY;
241 break;
244 ReplyMsg((struct Message *)msg);
247 else
249 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
250 Wait(0);
252 } while (exit < 0);
253 while ((msg=(struct IntuiMessage *)GetMsg(win->UserPort)))
254 ReplyMsg(&msg->ExecMessage);
255 return exit;
258 static void initPageExpansion(LIBBASETYPEPTR DOSBootBase)
260 struct Window *win = DOSBootBase->bm_Window;
261 struct ExpansionBase *ExpansionBase = DOSBootBase->bm_ExpansionBase;
262 struct ConfigDev *cd;
263 WORD y = 50, cnt;
264 char text[100];
266 SetAPen(win->RPort, 1);
267 cd = NULL;
268 cnt = 0;
269 while ((cd = FindConfigDev(cd, -1, -1))) {
270 NewRawDoFmt("%2d: %08lx - %08lx (%08lx) %5d %3d %08lx", RAWFMTFUNC_STRING, text,
271 ++cnt,
272 cd->cd_BoardAddr, cd->cd_BoardAddr + cd->cd_BoardSize - 1, cd->cd_BoardSize,
273 cd->cd_Rom.er_Manufacturer, cd->cd_Rom.er_Product, cd->cd_Rom.er_SerialNumber);
274 if ((cd->cd_Rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII)
275 strcat(text, " Z3");
276 else if ((cd->cd_Rom.er_Type & ERT_TYPEMASK) == ERT_ZORROII)
277 strcat(text, " Z2");
278 else
279 strcat(text, " ");
280 if (cd->cd_Rom.er_Type & ERTF_DIAGVALID)
281 strcat(text, " ROM");
282 if (cd->cd_Rom.er_Type & ERTF_MEMLIST)
283 strcat(text, " RAM");
284 Move(win->RPort, 20, y);
285 Text(win->RPort, text, strlen(text));
286 y += 16;
290 static BOOL bstreqcstr(BSTR bstr, CONST_STRPTR cstr)
292 int clen;
293 int blen;
295 clen = strlen(cstr);
296 blen = AROS_BSTR_strlen(bstr);
297 if (clen != blen)
298 return FALSE;
300 return (memcmp(AROS_BSTR_ADDR(bstr),cstr,clen) == 0);
303 void selectBootDevice(LIBBASETYPEPTR DOSBootBase)
305 struct BootNode *bn;
307 if (DOSBootBase->db_BootDevice == NULL &&
308 DOSBootBase->db_BootNode != NULL)
309 return;
311 Forbid(); /* .. access to ExpansionBase->MountList */
313 if (DOSBootBase->db_BootNode == NULL && DOSBootBase->db_BootDevice == NULL)
315 bn = (APTR)GetHead(&DOSBootBase->bm_ExpansionBase->MountList);
317 else
319 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, bn)
321 struct DeviceNode *dn;
323 dn = bn->bn_DeviceNode;
324 if (dn == NULL || dn->dn_Name == BNULL)
325 continue;
327 if (bstreqcstr(dn->dn_Name, DOSBootBase->db_BootDevice))
328 break;
332 Permit();
334 DOSBootBase->db_BootNode = bn;
335 DOSBootBase->db_BootDevice = NULL;
338 /* This makes the selected boot device the actual
339 * boot device. It also updates the boot flags.
341 static void setBootDevice(LIBBASETYPEPTR DOSBootBase)
343 struct BootNode *bn;
345 bn = DOSBootBase->db_BootNode;
347 if (bn != NULL)
349 Remove((struct Node *)bn);
350 bn->bn_Node.ln_Type = NT_BOOTNODE;
351 bn->bn_Node.ln_Pri = 127;
352 /* We use AddHead() instead of Enqueue() here
353 * to *insure* that this gets to the front of
354 * the boot list.
356 AddHead(&DOSBootBase->bm_ExpansionBase->MountList, (struct Node *)&bn);
359 DOSBootBase->bm_ExpansionBase->eb_BootFlags = DOSBootBase->db_BootFlags;
362 static void initPageBoot(LIBBASETYPEPTR DOSBootBase)
364 struct Window *win = DOSBootBase->bm_Window;
365 struct BootNode *bn;
366 WORD y = 50;
367 char text[100], *textp;
369 SetAPen(win->RPort, 1);
371 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, bn)
373 struct DeviceNode *dn = bn->bn_DeviceNode;
374 struct FileSysStartupMsg *fssm = BADDR(dn->dn_Startup);
375 struct DosEnvec *de = NULL;
376 struct IOStdReq *io;
377 struct MsgPort *port;
378 char dostype[5];
379 UBYTE i;
380 ULONG size;
381 BOOL devopen, ismedia;
383 if (y >= DOSBootBase->bottomY - 20)
384 break;
385 if (!fssm || !fssm->fssm_Device)
386 continue;
387 if (fssm->fssm_Environ > (BPTR)0x64) {
388 de = BADDR(fssm->fssm_Environ);
389 if (de->de_TableSize < 15)
390 de = NULL;
393 NewRawDoFmt("%c%10s: %4d %s-%ld", RAWFMTFUNC_STRING, text,
394 IsBootableNode(bn) ?
395 ((DOSBootBase->db_BootNode == bn) ? '*' : '+')
396 : ' ',
397 AROS_BSTR_ADDR(dn->dn_Name),
398 bn->bn_Node.ln_Pri,
399 AROS_BSTR_ADDR(fssm->fssm_Device),
400 fssm->fssm_Unit);
401 Move(win->RPort, 20, y);
402 Text(win->RPort, text, strlen(text));
404 textp = NULL;
405 devopen = ismedia = FALSE;
406 if ((port = (struct MsgPort*)CreateMsgPort())) {
407 if ((io = (struct IOStdReq*)CreateIORequest(port, sizeof(struct IOStdReq)))) {
408 if (!OpenDevice(AROS_BSTR_ADDR(fssm->fssm_Device), fssm->fssm_Unit, (struct IORequest*)io, fssm->fssm_Flags)) {
409 devopen = TRUE;
410 io->io_Command = TD_CHANGESTATE;
411 io->io_Actual = 1;
412 DoIO((struct IORequest*)io);
413 if (!io->io_Error && io->io_Actual == 0)
414 ismedia = TRUE;
415 CloseDevice((struct IORequest*)io);
417 DeleteIORequest((struct IORequest*)io);
419 DeleteMsgPort(port);
422 if (de && ismedia) {
423 for (i = 0; i < 4; i++) {
424 dostype[i] = (de->de_DosType >> ((3 - i) * 8)) & 0xff;
425 if (dostype[i] < 9)
426 dostype[i] += '0';
427 else if (dostype[i] < 32)
428 dostype[i] = '.';
430 dostype[4] = 0;
432 size = (de->de_HighCyl - de->de_LowCyl + 1) * de->de_Surfaces * de->de_BlocksPerTrack;
433 /* try to prevent ULONG overflow */
434 if (de->de_SizeBlock <= 128)
435 size /= 2;
436 else
437 size *= de->de_SizeBlock / 256;
439 NewRawDoFmt("%s [%08lx] %ldk", RAWFMTFUNC_STRING, text,
440 dostype, de->de_DosType,
441 size);
442 textp = text;
443 } else if (!devopen) {
444 textp = "[device open error]";
445 } else if (!ismedia) {
446 textp = "[no media]";
448 if (textp) {
449 Move(win->RPort, 400, y);
450 Text(win->RPort, textp, strlen(textp));
453 y += 16;
459 static void centertext(LIBBASETYPEPTR DOSBootBase, BYTE pen, WORD y, const char *text)
461 struct Window *win = DOSBootBase->bm_Window;
462 SetAPen(win->RPort, pen);
463 Move(win->RPort, win->Width / 2 - TextLength(win->RPort, text, strlen(text)) / 2, y);
464 Text(win->RPort, text, strlen(text));
467 static void initPage(LIBBASETYPEPTR DOSBootBase, WORD page)
469 UBYTE *text;
471 if (page == PAGE_DISPLAY)
472 text = "Display Options";
473 else if (page == PAGE_EXPANSION)
474 text = "Expansion Board Diagnostic";
475 else if (page == PAGE_BOOT)
476 text = "Boot Options";
477 else
478 text = "AROS Early Startup Control";
479 centertext(DOSBootBase, 2, 10, text);
481 if (page == PAGE_BOOT)
482 initPageBoot(DOSBootBase);
483 else if (page == PAGE_EXPANSION)
484 initPageExpansion(DOSBootBase);
486 if (page == PAGE_MAIN && (GfxBase->DisplayFlags & (NTSC | PAL))) {
487 ULONG modeid = GetVPModeID(&DOSBootBase->bm_Screen->ViewPort);
488 if (modeid != INVALID_ID && (((modeid & MONITOR_ID_MASK) == NTSC_MONITOR_ID) || ((modeid & MONITOR_ID_MASK) == PAL_MONITOR_ID))) {
489 centertext(DOSBootBase, 1, 30, "(press a key to toggle the display between PAL and NTSC)");
494 static WORD initWindow(LIBBASETYPEPTR DOSBootBase, struct BootConfig *bcfg, WORD page)
496 struct Gadget *first = NULL;
497 WORD newpage = -1;
499 if ((first = createGadgets(DOSBootBase, page)) != NULL)
501 struct NewWindow nw =
503 0, 0, /* Left, Top */
504 DOSBootBase->bm_Screen->Width, /* Width, Height */
505 DOSBootBase->bm_Screen->Height,
506 0, 1, /* DetailPen, BlockPen */
507 IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_GADGETDOWN, /* IDCMPFlags */
508 WFLG_SMART_REFRESH | WFLG_BORDERLESS | WFLG_ACTIVATE, /* Flags */
509 first, /* FirstGadget */
510 NULL, /* CheckMark */
511 NULL, /* Title */
512 DOSBootBase->bm_Screen, /* Screen */
513 NULL, /* BitMap */
514 0, 0, /* MinWidth, MinHeight */
515 0, 0, /* MaxWidth, MaxHeight */
516 CUSTOMSCREEN, /* Type */
519 D(bug("[BootMenu] initPage: Gadgets created @ %p\n", first));
521 if ((DOSBootBase->bm_Window = OpenWindow(&nw)) != NULL)
523 D(bug("[BootMenu] initScreen: Window opened @ %p\n", DOSBootBase->bm_Window));
524 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", DOSBootBase->bm_Window->RPort));
525 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", DOSBootBase->bm_Window->UserPort));
526 initPage(DOSBootBase, page);
527 newpage = msgLoop(DOSBootBase, DOSBootBase->bm_Window);
529 CloseWindow(DOSBootBase->bm_Window);
531 freeGadgets(DOSBootBase, page);
533 return newpage;
536 static BOOL initScreen(LIBBASETYPEPTR DOSBootBase, struct BootConfig *bcfg)
538 WORD page;
540 D(bug("[BootMenu] initScreen()\n"));
542 page = -1;
543 DOSBootBase->bm_Screen = OpenBootScreen(DOSBootBase);
544 if (DOSBootBase->bm_Screen)
546 DOSBootBase->bottomY = DOSBootBase->bm_Screen->Height - (DOSBootBase->bm_Screen->Height > 256 ? 32 : 16);
547 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", DOSBootBase->bm_Screen));
549 page = PAGE_MAIN;
550 do {
551 page = initWindow(DOSBootBase, bcfg, page);
552 } while (page != EXIT_BOOT && page != EXIT_BOOT_WNSS);
553 CloseBootScreen(DOSBootBase->bm_Screen, DOSBootBase);
555 return page >= 0;
558 /* From keyboard.device/keyboard_intern.h */
559 #define KB_MAXKEYS 256
560 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
561 #define ioStd(x) ((struct IOStdReq *)x)
563 static BOOL buttonsPressed(LIBBASETYPEPTR DOSBootBase)
565 BOOL success = FALSE;
566 struct MsgPort *mp = NULL;
567 UBYTE matrix[KB_MATRIXSIZE];
569 #ifdef mc68000
571 * On m68k we may have ciaa.resource (if running on classic Amiga HW)
572 * Let's check mouse buttons.
574 if (OpenResource("ciaa.resource"))
576 volatile UBYTE *cia = (UBYTE*)0xbfe001;
577 volatile UWORD *potinp = (UWORD*)0xdff016;
579 /* check left + right mouse button state */
580 if ((cia[0] & 0x40) == 0 && (potinp[0] & 0x0400) == 0)
581 return TRUE;
583 #endif
585 if ((mp = CreateMsgPort()) != NULL)
587 struct IORequest *io = NULL;
588 if ((io = CreateIORequest(mp, sizeof ( struct IOStdReq))) != NULL)
590 if (0 == OpenDevice("keyboard.device", 0, io, 0))
592 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
593 ioStd(io)->io_Command = KBD_READMATRIX;
594 ioStd(io)->io_Data = matrix;
595 ioStd(io)->io_Length = sizeof(matrix);
596 DoIO(io);
597 if (0 == io->io_Error)
600 int i;
601 bug("[BootMenu] buttonsPressed: Matrix : ");
602 for (i = 0; i < ioStd(io)->io_Actual; i ++)
604 bug("%02x ", matrix[i]);
606 bug("\n");
608 if (matrix[RAWKEY_SPACE/8] & (1<<(RAWKEY_SPACE%8)))
610 D(bug("[BootMenu] SPACEBAR pressed\n"));
611 success = TRUE;
614 CloseDevice(io);
616 DeleteIORequest(io);
618 DeleteMsgPort(mp);
620 return success;
623 int bootmenu_Init(LIBBASETYPEPTR LIBBASE, BOOL WantBootMenu)
625 BOOL bmi_RetVal = FALSE;
627 D(bug("[BootMenu] bootmenu_Init()\n"));
629 #ifdef INITHIDDS_KLUDGE
631 * PCI hardware display drivers still need external initialization.
632 * This urgently needs to be fixed. After fixing this kludge
633 * will not be needed any more.
635 InitBootConfig(&LIBBASE->bm_BootConfig);
636 if (!initHidds(LIBBASE))
637 return FALSE;
638 #endif
640 /* check keyboard if needed */
641 if (!WantBootMenu)
642 WantBootMenu = buttonsPressed(LIBBASE);
644 /* Bring up early startup menu if requested */
645 if (WantBootMenu)
647 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
648 bmi_RetVal = initScreen(LIBBASE, &LIBBASE->bm_BootConfig);
651 /* Make the user's select the top boot device */
652 setBootDevice(LIBBASE);
654 return bmi_RetVal;