revert between 56095 -> 55830 in arch
[AROS.git] / rom / dosboot / dosboot_init.c
blobdce8b80e4eda873509dc0022d911c9394eda7306
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>
29 #include <clib/alib_protos.h>
31 #include <proto/exec.h>
32 #include <proto/expansion.h>
33 #include <proto/partition.h>
34 #include <proto/bootloader.h>
36 #include LC_LIBDEFS_FILE
38 #include "dosboot_intern.h"
39 #include "../expansion/expansion_intern.h"
40 #include "menu.h"
42 /* Delay just like Dos/Delay(), ticks are
43 * in 1/50th of a second.
45 static void bootDelay(ULONG timeout)
47 struct timerequest timerio;
48 struct MsgPort timermp;
50 memset(&timermp, 0, sizeof(timermp));
52 timermp.mp_Node.ln_Type = NT_MSGPORT;
53 timermp.mp_Flags = PA_SIGNAL;
54 timermp.mp_SigBit = SIGB_SINGLE;
55 timermp.mp_SigTask = FindTask(NULL);
56 NEWLIST(&timermp.mp_MsgList);
58 timerio.tr_node.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
59 timerio.tr_node.io_Message.mn_ReplyPort = &timermp;
60 timerio.tr_node.io_Message.mn_Length = sizeof(timermp);
62 if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)&timerio, 0) != 0) {
63 D(bug("dosboot: Can't open timer.device unit 0\n"));
64 return;
67 timerio.tr_node.io_Command = TR_ADDREQUEST;
68 timerio.tr_time.tv_secs = timeout / TICKS_PER_SECOND;
69 timerio.tr_time.tv_micro = 1000000UL / TICKS_PER_SECOND * (timeout % TICKS_PER_SECOND);
71 SetSignal(0, SIGF_SINGLE);
73 DoIO(&timerio.tr_node);
75 CloseDevice((struct IORequest *)&timerio);
78 static BOOL bstreqcstr(BSTR bstr, CONST_STRPTR cstr)
80 int clen;
81 int blen;
83 clen = strlen(cstr);
84 blen = AROS_BSTR_strlen(bstr);
85 if (clen != blen)
86 return FALSE;
88 return (memcmp(AROS_BSTR_ADDR(bstr),cstr,clen) == 0);
91 static void selectBootDevice(LIBBASETYPEPTR DOSBootBase, STRPTR bootDeviceName)
93 struct BootNode *bn = NULL;
95 if (bootDeviceName == NULL &&
96 DOSBootBase->db_BootNode != NULL)
97 return;
99 Forbid(); /* .. access to ExpansionBase->MountList */
101 if (bootDeviceName != NULL)
103 struct BootNode *i;
104 ForeachNode(&DOSBootBase->bm_ExpansionBase->MountList, i)
106 struct DeviceNode *dn;
108 dn = i->bn_DeviceNode;
109 if (dn == NULL || dn->dn_Name == BNULL)
110 continue;
112 if (bstreqcstr(dn->dn_Name, bootDeviceName))
114 bn = i;
115 break;
120 /* Default */
121 if (bn == NULL)
122 bn = (APTR)GetHead(&DOSBootBase->bm_ExpansionBase->MountList);
124 Permit();
126 DOSBootBase->db_BootNode = bn;
129 /* This makes the selected boot device the actual
130 * boot device. It also updates the boot flags.
132 static void setBootDevice(LIBBASETYPEPTR DOSBootBase)
134 struct BootNode *bn;
136 bn = DOSBootBase->db_BootNode;
138 if (bn != NULL)
140 Remove((struct Node *)bn);
141 bn->bn_Node.ln_Type = NT_BOOTNODE;
142 bn->bn_Node.ln_Pri = 127;
143 /* We use AddHead() instead of Enqueue() here
144 * to *insure* that this gets to the front of
145 * the boot list.
147 AddHead(&DOSBootBase->bm_ExpansionBase->MountList, (struct Node *)bn);
150 IntExpBase(DOSBootBase->bm_ExpansionBase)->BootFlags =
151 DOSBootBase->db_BootFlags;
154 int dosboot_Init(LIBBASETYPEPTR LIBBASE)
156 struct ExpansionBase *ExpansionBase;
157 void *BootLoaderBase;
158 BOOL WantBootMenu = FALSE;
159 ULONG t;
160 STRPTR bootDeviceName = NULL;
162 LIBBASE->delayTicks = 50;
164 D(bug("dosboot_Init: GO GO GO!\n"));
166 ExpansionBase = (APTR)OpenLibrary("expansion.library", 0);
168 D(bug("[Strap] ExpansionBase 0x%p\n", ExpansionBase));
169 if( ExpansionBase == NULL )
171 D(bug( "Could not open expansion.library, something's wrong!\n"));
172 Alert(AT_DeadEnd | AG_OpenLib | AN_BootStrap | AO_ExpansionLib);
175 ExpansionBase->Flags |= EBF_SILENTSTART;
177 LIBBASE->bm_ExpansionBase = ExpansionBase;
180 * Search the kernel parameters for the bootdelay=%d string. It determines the
181 * delay in seconds.
183 if ((BootLoaderBase = OpenResource("bootloader.resource")) != NULL)
185 struct List *args = GetBootInfo(BL_Args);
187 if (args)
189 struct Node *node;
191 ForeachNode(args, node)
193 if (0 == strncmp(node->ln_Name, "bootdelay=", 10))
195 ULONG delay = atoi(&node->ln_Name[10]);
197 D(bug("[Boot] delay of %d seconds requested.", delay));
198 if (delay)
199 bootDelay(delay * 50);
201 else if (0 == stricmp(node->ln_Name, "bootmenu"))
203 D(bug("[BootMenu] bootmenu_Init: Forced with bootloader argument\n"));
204 WantBootMenu = TRUE;
207 * TODO: The following two flags should have corresponding switches
208 * in 'display options' page.
210 else if (0 == stricmp(node->ln_Name, "nomonitors"))
212 LIBBASE->db_BootFlags |= BF_NO_DISPLAY_DRIVERS;
214 else if (0 == stricmp(node->ln_Name, "nocomposition"))
216 LIBBASE->db_BootFlags |= BF_NO_COMPOSITION;
218 else if (0 == strnicmp(node->ln_Name, "bootdevice=", 11))
220 bootDeviceName = &node->ln_Name[11];
222 else if (0 == stricmp(node->ln_Name, "econsole"))
224 LIBBASE->db_BootFlags |= BF_EMERGENCY_CONSOLE;
225 D(bug("[Boot] Emergency console selected\n"));
228 IntExpBase(ExpansionBase)->BootFlags = LIBBASE->db_BootFlags;
232 /* Scan for any additional partition volumes */
233 dosboot_BootScan(LIBBASE);
235 /* Select the initial boot device, so that the choice is available in the menu */
236 selectBootDevice(LIBBASE, bootDeviceName);
238 /* Show the boot menu if needed */
239 bootmenu_Init(LIBBASE, WantBootMenu);
241 /* Set final boot device */
242 setBootDevice(LIBBASE);
244 /* We want to be able to find ourselves in RTF_AFTERDOS */
245 LIBBASE->bm_Screen = NULL;
246 AddResource(&LIBBASE->db_Node);
248 /* Attempt to boot until we succeed */
249 for (;;)
251 dosboot_BootStrap(LIBBASE);
253 if (!LIBBASE->bm_Screen)
254 LIBBASE->bm_Screen = NoBootMediaScreen(LIBBASE);
256 D(bug("No bootable disk was found.\n"));
257 D(bug("Please insert a bootable disk in any drive.\n"));
258 D(bug("Retrying in 3 seconds...\n"));
260 for (t = 0; t < 150; t += LIBBASE->delayTicks)
262 bootDelay(LIBBASE->delayTicks);
264 if (LIBBASE->bm_Screen)
265 anim_Animate(LIBBASE->bm_Screen, LIBBASE);
269 /* We never get here */
270 return FALSE;
273 ADD2INITLIB(dosboot_Init, 1)