Added missing properties.
[tangerine.git] / rom / dos / dosboot.c
blob8a09b36ac486045cffa87b05243ba11adfbe96e7
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Start up the ol' Dos boot process.
6 Lang: english
7 */
9 /* This definition enables mounting
10 disk-based handlers (e.g. fat.handler) at bootup.
11 Comment it out in case if some critical bugs appear. */
12 #define MOUNT_DISK_HANDLERS
14 #define DOSBOOT_DISCINSERT_SCREENPRINT
16 # define DEBUG 0
17 # include <aros/debug.h>
19 #include <aros/macros.h>
20 #include <aros/asmcall.h>
22 #include <proto/bootmenu.h>
23 #include <proto/exec.h>
24 #include <proto/dos.h>
26 #include <exec/types.h>
27 #include <exec/nodes.h>
28 #include <exec/lists.h>
29 #include <exec/execbase.h>
30 #include <exec/alerts.h>
31 #include <exec/memory.h>
32 #include <dos/dosextens.h>
33 #include <dos/dostags.h>
34 #include <dos/filehandler.h>
35 #include <dos/filesystem.h>
36 #include <libraries/expansionbase.h>
37 #include <libraries/bootmenu.h>
38 #include <devices/trackdisk.h>
40 #include <string.h>
42 #include "dos_intern.h"
44 #define BNF_RETRY 0x8000 /* Private flag for the BootNode */
46 extern BOOL init_hidds(struct ExecBase *, struct DosLibrary *);
47 extern void boot();
49 BOOL attemptingboot = FALSE;
50 BOOL bootdevicefound = FALSE;
52 /** Support Functions **/
53 static BOOL __dosboot_Mount(struct DeviceNode *dn, struct DosLibrary * DOSBase)
55 BOOL rc;
57 if (!dn->dn_Ext.dn_AROS.dn_Device)
58 rc = RunHandler(dn, DOSBase);
59 else
60 rc = TRUE;
62 if (rc)
64 if (!AddDosEntry((struct DosList *) dn))
66 Alert(AT_DeadEnd | AG_NoMemory | AN_DOSLib);
69 return rc;
72 static BOOL __dosboot_IsBootable(CONST_STRPTR deviceName, struct DosLibrary * DOSBase)
74 BOOL result = FALSE;
75 BPTR lock;
76 STRPTR buffer;
77 LONG bufferLength;
78 struct InfoData info;
80 #define STARTUP_SEQUENCE_FILE ":S/Startup-Sequence"
82 bufferLength = strlen(deviceName) + sizeof(STARTUP_SEQUENCE_FILE) + 1;
84 if ((buffer = AllocMem(bufferLength, MEMF_ANY)) == NULL)
86 Alert(AT_DeadEnd | AG_NoMemory | AN_DOSLib);
89 strcpy(buffer, deviceName);
90 strcat(buffer, STARTUP_SEQUENCE_FILE);
92 D(bug("[DOS] __dosboot_IsBootable: Trying to get a lock on '%s'\n", buffer));
94 if ((lock = Lock(buffer, SHARED_LOCK)) == 0)
96 D(bug("[DOS] __dosboot_IsBootable: could not lock '%s'\n", buffer));
97 goto cleanup;
100 if (!Info(lock, &info))
102 D(bug("[DOS] __dosboot_IsBootable: could not get info on '%s'\n", buffer));
103 goto cleanup;
106 if (info.id_DiskType != ID_NO_DISK_PRESENT)
108 result = TRUE;
111 cleanup:
112 if (buffer != NULL ) FreeMem(buffer, bufferLength);
113 if (lock != 0 ) UnLock(lock);
115 return result;
118 /** Boot Code **/
120 AROS_UFH3(void, __dosboot_IntBoot,
121 AROS_UFHA(APTR, argString, A0),
122 AROS_UFHA(ULONG, argSize, D0),
123 AROS_UFHA(struct ExecBase *,SysBase, A6)
126 AROS_USERFUNC_INIT
128 struct ExpansionBase *ExpansionBase = NULL;
129 struct DosLibrary *DOSBase = NULL;
130 struct BootMenuBase *BootMenuBase = NULL;
132 struct BootNode *bootNode = NULL;
133 STRPTR bootName;
134 LONG bootNameLength;
135 BPTR lock;
137 struct MsgPort *mp; // Message port used with timer.device
138 struct timerequest *tr = NULL; // timer's time request message
140 #define deviceName (((struct DosList *) bootNode->bn_DeviceNode)->dol_Ext.dol_AROS.dol_DevName)
142 /**** Open all required libraries **********************************************/
143 if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0)) == NULL)
145 D(bug("[DOS] __dosboot_IntBoot: Could not open dos.library, something's wrong!\n" ));
146 Alert(AT_DeadEnd| AG_OpenLib | AN_DOSLib | AO_DOSLib);
149 if ((ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library", 0)) == NULL)
151 D(bug("[DOS] __dosboot_IntBoot: Could not open expansion.library, something's wrong!\n"));
152 Alert(AT_DeadEnd | AG_OpenLib | AN_DOSLib | AO_ExpansionLib);
155 if ((BootMenuBase = (struct BootMenuBase *)OpenResource("bootmenu.resource")) == NULL)
157 D(bug("[DOS] __dosboot_IntBoot: Could not open bootmenu.resource, something's wrong!\n"));
160 if ((mp = CreateMsgPort()) != NULL)
162 if ((tr = (struct timerequest *)CreateIORequest(mp, sizeof(struct timerequest))) != NULL)
164 if ((OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)tr, 0)) == 0)
166 #define ioStd(x) ((struct IOStdReq *)x)
167 ioStd(tr)->io_Command = TR_ADDREQUEST;
169 else
171 D(bug("[DOS] __dosboot_IntBoot: Could not open timer.device, something's wrong!\n"));
172 DeleteMsgPort(mp);
173 DeleteIORequest((struct IORequest *)tr);
174 tr = NULL;
177 else
179 DeleteMsgPort(mp);
183 /* Check if bootmenu is requested ... and setup base options */
184 if (BootMenuBase != NULL)
185 bootmenu_CheckAndDisplay();
187 /**** Try to mount all filesystems in the MountList ****************************/
188 D(bug("[DOS] __dosboot_IntBoot: Checking MountList for useable nodes:\n" ));
190 ForeachNode(&ExpansionBase->MountList, bootNode)
192 D(bug("[DOS] __dosboot_IntBoot: BootNode: %p, bn_DeviceNode: %p, Name '%s', Priority %4d\n",
193 bootNode, bootNode->bn_DeviceNode,
194 deviceName ? deviceName : "(null)", bootNode->bn_Node.ln_Pri
197 Try to mount the filesystem. If it fails, mark the BootNode
198 so DOS doesn't try to boot from it later but will retry to
199 mount it after boot device is found and system directories
200 assigned.
203 if( !__dosboot_Mount( (struct DeviceNode *) bootNode->bn_DeviceNode ,
204 (struct DosLibrary *) DOSBase))
206 #ifdef MOUNT_DISK_HANDLERS
207 bootNode->bn_Flags |= BNF_RETRY;
208 #else
209 REMOVE(bootNode);
210 #endif
212 else
213 bootNode->bn_Flags &= ~BNF_RETRY;
216 /**** Try to find a bootable filesystem ****************************************/
217 while (bootdevicefound == FALSE)
219 ForeachNode(&ExpansionBase->MountList, bootNode)
221 /* Check if the mounted filesystem is bootable. If it's not,
222 it's probably some kind of transient error (ie. no disk
223 in drive or wrong disk) so we only move it to the end of
224 the list. */
225 if ((!(bootNode->bn_Flags & BNF_RETRY)) && __dosboot_IsBootable( deviceName, (struct DosLibrary *)DOSBase ) )
227 bootdevicefound = TRUE;
228 break;
232 if (!bootdevicefound)
234 if (!attemptingboot)
236 #warning "TODO: Show insert disc animation !"
237 attemptingboot = TRUE;
239 else
241 #warning "TODO: re-run insert disc animation !"
243 #if defined(DOSBOOT_DISCINSERT_SCREENPRINT)
244 kprintf("No bootable disk was found.\n");
245 kprintf("Please insert a bootable disk in any drive.\n");
247 kprintf("Retrying in 5 seconds...\n");
248 #endif
250 if (tr != NULL) {
251 tr->tr_time.tv_secs = 5;
252 tr->tr_time.tv_micro = 0;
253 DoIO((struct IORequest *)tr);
254 } else
255 Delay(500);
259 if (mp)
260 DeleteMsgPort(mp);
262 if (tr)
264 CloseDevice((struct IORequest *)tr);
265 DeleteIORequest((struct IORequest *)tr);
268 if (bootdevicefound)
270 /* Construct the complete device name of the boot device */
271 bootNameLength = strlen(deviceName) + 2;
273 if ((bootName = AllocMem(bootNameLength, MEMF_ANY|MEMF_CLEAR)) == NULL)
275 Alert(AT_DeadEnd | AG_NoMemory | AO_DOSLib | AN_StartMem);
278 strcpy(bootName, deviceName);
279 strcat(bootName, ":");
281 D(bug("[DOS] __dosboot_IntBoot: Booting from device '%s'\n", bootName));
283 /* Lock the boot device and add some default assigns */
284 lock = Lock(bootName, SHARED_LOCK);
285 if (lock) DOSBase->dl_SYSLock = DupLock(lock);
287 if ((lock != NULL) && (DOSBase->dl_SYSLock != NULL))
289 AssignLock("SYS", lock);
291 else
293 Alert(AT_DeadEnd | AG_BadParm | AN_DOSLib);
296 FreeMem( bootName, bootNameLength );
298 if ((lock = Lock("SYS:", SHARED_LOCK)) != NULL)
300 CurrentDir(lock);
302 else
304 Alert(AT_DeadEnd | AG_BadParm | AN_DOSLib);
307 if ((lock = Lock("SYS:C", SHARED_LOCK)) != NULL)
309 AssignLock("C", lock);
312 if ((lock = Lock("SYS:S", SHARED_LOCK)) != NULL)
314 AssignLock("S", lock);
317 if ((lock = Lock("SYS:Libs", SHARED_LOCK)) != NULL)
319 AssignLock("LIBS", lock);
322 if ((lock = Lock("SYS:Devs", SHARED_LOCK)) != NULL)
324 AssignLock("DEVS", lock);
327 if ((lock = Lock("DEVS:Drivers", SHARED_LOCK)) != NULL)
329 AssignLock("DRIVERS", lock);
330 AssignAdd("LIBS", lock); /* Let hidds in DRIVERS: directory be found by OpenLibrary */
333 if ((lock = Lock("SYS:L", SHARED_LOCK)) != NULL)
335 AssignLock("L", lock);
338 /* Late binding ENVARC: assign, only if used */
339 AssignLate("ENVARC", "SYS:Prefs/env-archive");
342 Attempt to mount filesystems marked for retry. If it fails again,
343 remove the BootNode from the list.
345 ForeachNode(&ExpansionBase->MountList, bootNode)
347 if (bootNode->bn_Flags & BNF_RETRY)
349 D(bug("[DOS] __dosboot_IntBoot: Retrying node: %p, DevNode: %p, Name = %s\n", bootNode, bootNode->bn_DeviceNode, deviceName ? deviceName : "(null)" ));
350 if( !__dosboot_Mount((struct DeviceNode *)bootNode->bn_DeviceNode, (struct DosLibrary *)DOSBase))
352 REMOVE( bootNode );
357 /* We don't need expansion.library any more */
358 CloseLibrary( (struct Library *) ExpansionBase );
360 /* Initialize HIDDs */
361 init_hidds(SysBase, (struct DosLibrary *)DOSBase);
363 /* We now call the system dependant boot - should NEVER return! */
364 AROS_UFC3(void, boot,
365 AROS_UFCA(STRPTR, argString, A0),
366 AROS_UFCA(ULONG, argSize, D0),
367 AROS_UFCA(struct ExecBase *, SysBase, A6));
370 //We Should NEVER reach here!
371 #undef deviceName
373 AROS_USERFUNC_EXIT
376 void DOSBoot(struct ExecBase *SysBase, struct DosLibrary *DOSBase)
378 struct TagItem bootprocess[] =
380 { NP_Entry, (IPTR) __dosboot_IntBoot },
381 { NP_Name, (IPTR) "Boot Process" },
382 { NP_Input, (IPTR) NULL },
383 { NP_Output, (IPTR) NULL },
384 { NP_WindowPtr, -1 },
385 { NP_CurrentDir, (IPTR) NULL },
386 { NP_StackSize, AROS_STACKSIZE * 2 },
387 { NP_Cli, (IPTR) 0 },
388 { TAG_END, }
391 if (CreateNewProc(bootprocess) == NULL)
393 D(bug("[DOS] DOSBoot: CreateNewProc() failed with %ld\n", ((struct Process *)FindTask(NULL))->pr_Result2));
394 Alert( AT_DeadEnd | AN_DOSLib | AG_ProcCreate );