Upon leaving IRQ check whether the code will go back to user mode (or system mode...
[AROS.git] / rom / dosboot / dosboot_init.c
blob3bf2dd3a1e178136477bfb25bf20bc83d5a85271
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Boot AROS
6 Lang: english
7 */
9 #include <string.h>
10 #include <stdlib.h>
12 #include <aros/debug.h>
13 #include <exec/alerts.h>
14 #include <aros/asmcall.h>
15 #include <aros/bootloader.h>
16 #include <exec/lists.h>
17 #include <exec/memory.h>
18 #include <exec/resident.h>
19 #include <exec/types.h>
20 #include <libraries/configvars.h>
21 #include <libraries/expansion.h>
22 #include <libraries/expansionbase.h>
23 #include <libraries/partition.h>
24 #include <utility/tagitem.h>
25 #include <devices/bootblock.h>
26 #include <devices/timer.h>
27 #include <dos/dosextens.h>
28 #include <resources/filesysres.h>
30 #include <proto/exec.h>
31 #include <proto/expansion.h>
32 #include <proto/partition.h>
33 #include <proto/bootloader.h>
35 #include LC_LIBDEFS_FILE
37 #include "dosboot_intern.h"
38 #include "../expansion/expansion_intern.h"
39 #include "menu.h"
41 /* Delay just like Dos/Delay(), ticks are
42 * in 1/50th of a second.
44 static void bootDelay(ULONG timeout)
46 struct timerequest timerio;
47 struct MsgPort timermp;
49 memset(&timermp, 0, sizeof(timermp));
51 timermp.mp_Node.ln_Type = NT_MSGPORT;
52 timermp.mp_Flags = PA_SIGNAL;
53 timermp.mp_SigBit = SIGB_SINGLE;
54 timermp.mp_SigTask = FindTask(NULL);
55 NEWLIST(&timermp.mp_MsgList);
57 timerio.tr_node.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
58 timerio.tr_node.io_Message.mn_ReplyPort = &timermp;
59 timerio.tr_node.io_Message.mn_Length = sizeof(timermp);
61 if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)&timerio, 0) != 0) {
62 D(bug("dosboot: Can't open timer.device unit 0\n"));
63 return;
66 timerio.tr_node.io_Command = TR_ADDREQUEST;
67 timerio.tr_time.tv_secs = timeout / TICKS_PER_SECOND;
68 timerio.tr_time.tv_micro = 1000000UL / TICKS_PER_SECOND * (timeout % TICKS_PER_SECOND);
70 SetSignal(0, SIGF_SINGLE);
72 DoIO(&timerio.tr_node);
74 CloseDevice((struct IORequest *)&timerio);
77 static BOOL bstreqcstr(BSTR bstr, CONST_STRPTR cstr)
79 int clen;
80 int blen;
82 clen = strlen(cstr);
83 blen = AROS_BSTR_strlen(bstr);
84 if (clen != blen)
85 return FALSE;
87 return (memcmp(AROS_BSTR_ADDR(bstr),cstr,clen) == 0);
90 static void selectBootDevice(LIBBASETYPEPTR DOSBootBase, STRPTR bootDeviceName)
92 struct BootNode *bn = NULL;
94 if (bootDeviceName == NULL &&
95 DOSBootBase->db_BootNode != NULL)
96 return;
98 Forbid(); /* .. access to ExpansionBase->MountList */
100 if (bootDeviceName != NULL)
102 struct BootNode *i;
103 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, i)
105 struct DeviceNode *dn;
107 dn = i->bn_DeviceNode;
108 if (dn == NULL || dn->dn_Name == BNULL)
109 continue;
111 if (bstreqcstr(dn->dn_Name, bootDeviceName))
113 bn = i;
114 break;
119 /* Default */
120 if (bn == NULL)
121 bn = (APTR)GetHead(&DOSBootBase->bm_ExpansionBase->MountList);
123 Permit();
125 DOSBootBase->db_BootNode = bn;
128 /* This makes the selected boot device the actual
129 * boot device. It also updates the boot flags.
131 static void setBootDevice(LIBBASETYPEPTR DOSBootBase)
133 struct BootNode *bn;
135 bn = DOSBootBase->db_BootNode;
137 if (bn != NULL)
139 Remove((struct Node *)bn);
140 bn->bn_Node.ln_Type = NT_BOOTNODE;
141 bn->bn_Node.ln_Pri = 127;
142 /* We use AddHead() instead of Enqueue() here
143 * to *insure* that this gets to the front of
144 * the boot list.
146 AddHead(&DOSBootBase->bm_ExpansionBase->MountList, (struct Node *)bn);
149 IntExpBase(DOSBootBase->bm_ExpansionBase)->BootFlags =
150 DOSBootBase->db_BootFlags;
153 int dosboot_Init(LIBBASETYPEPTR LIBBASE)
155 struct ExpansionBase *ExpansionBase;
156 void *BootLoaderBase;
157 BOOL WantBootMenu = FALSE;
158 ULONG t;
159 STRPTR bootDeviceName = NULL;
161 LIBBASE->delayTicks = 50;
163 D(bug("dosboot_Init: GO GO GO!\n"));
165 ExpansionBase = (APTR)OpenLibrary("expansion.library", 0);
167 D(bug("[Strap] ExpansionBase 0x%p\n", ExpansionBase));
168 if( ExpansionBase == NULL )
170 D(bug( "Could not open expansion.library, something's wrong!\n"));
171 Alert(AT_DeadEnd | AG_OpenLib | AN_BootStrap | AO_ExpansionLib);
174 ExpansionBase->Flags |= EBF_SILENTSTART;
176 LIBBASE->bm_ExpansionBase = ExpansionBase;
179 * Search the kernel parameters for the bootdelay=%d string. It determines the
180 * delay in seconds.
182 if ((BootLoaderBase = OpenResource("bootloader.resource")) != NULL)
184 struct List *args = GetBootInfo(BL_Args);
186 if (args)
188 struct Node *node;
190 ForeachNode(args, node)
192 if (0 == strncmp(node->ln_Name, "bootdelay=", 10))
194 ULONG delay = atoi(&node->ln_Name[10]);
196 D(bug("[Boot] delay of %d seconds requested.", delay));
197 if (delay)
198 bootDelay(delay * 50);
200 else if (0 == stricmp(node->ln_Name, "bootmenu"))
202 D(bug("[BootMenu] bootmenu_Init: Forced with bootloader argument\n"));
203 WantBootMenu = TRUE;
206 * TODO: The following two flags should have corresponding switches
207 * in 'display options' page.
209 else if (0 == stricmp(node->ln_Name, "nomonitors"))
211 LIBBASE->db_BootFlags |= BF_NO_DISPLAY_DRIVERS;
213 else if (0 == stricmp(node->ln_Name, "nocomposition"))
215 LIBBASE->db_BootFlags |= BF_NO_COMPOSITION;
217 else if (0 == strnicmp(node->ln_Name, "bootdevice=", 11))
219 bootDeviceName = &node->ln_Name[11];
221 else if (0 == stricmp(node->ln_Name, "econsole"))
223 LIBBASE->db_BootFlags |= BF_EMERGENCY_CONSOLE;
224 D(bug("[Boot] Emergency console selected\n"));
227 IntExpBase(ExpansionBase)->BootFlags = LIBBASE->db_BootFlags;
231 /* Scan for any additional partition volumes */
232 dosboot_BootScan(LIBBASE);
234 /* Select the initial boot device, so that the choice is available in the menu */
235 selectBootDevice(LIBBASE, bootDeviceName);
237 /* Show the boot menu if needed */
238 bootmenu_Init(LIBBASE, WantBootMenu);
240 /* Set final boot device */
241 setBootDevice(LIBBASE);
243 /* We want to be able to find ourselves in RTF_AFTERDOS */
244 LIBBASE->bm_Screen = NULL;
245 AddResource(&LIBBASE->db_Node);
247 /* Attempt to boot until we succeed */
248 for (;;)
250 dosboot_BootStrap(LIBBASE);
252 if (!LIBBASE->bm_Screen)
253 LIBBASE->bm_Screen = NoBootMediaScreen(LIBBASE);
255 D(bug("No bootable disk was found.\n"));
256 D(bug("Please insert a bootable disk in any drive.\n"));
257 D(bug("Retrying in 3 seconds...\n"));
259 for (t = 0; t < 150; t += LIBBASE->delayTicks)
261 bootDelay(LIBBASE->delayTicks);
263 if (LIBBASE->bm_Screen)
264 anim_Animate(LIBBASE->bm_Screen, LIBBASE);
268 /* We never get here */
269 return FALSE;
272 ADD2INITLIB(dosboot_Init, 1)