added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / rom / dos / dosboot.c
blob0d073b807454fd132349fc74d519c3d7753e0cb3
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Start up the ol' Dos boot process.
6 Lang: english
7 */
9 /* Uncomment this definition in order to enable mounting
10 disk-based handlers (e.g. fat.handler) at bootup.
11 This code works however fat.handler itself currently has
12 problems, so this option is disabled for now
13 #define MOUNT_DISK_HANDLERS */
15 # define DEBUG 0
16 # include <aros/debug.h>
18 #include <aros/macros.h>
20 #include <exec/types.h>
21 #include <exec/nodes.h>
22 #include <exec/lists.h>
23 #include <exec/execbase.h>
24 #include <exec/alerts.h>
25 #include <exec/memory.h>
26 #include <dos/dosextens.h>
27 #include <dos/dostags.h>
28 #include <libraries/expansionbase.h>
29 #include <aros/asmcall.h>
30 #include <string.h>
31 #include <dos/filehandler.h>
32 #include <dos/filesystem.h>
33 #include <devices/trackdisk.h>
35 #include <proto/exec.h>
36 #include <proto/dos.h>
38 #include <string.h>
40 #include "dos_intern.h"
42 #define BNF_RETRY 0x8000 /* Private flag for the BootNode */
44 extern void boot();
46 BOOL init_hidds( struct ExecBase *, struct DosLibrary * );
47 BOOL mount( struct DeviceNode *dn, struct DosLibrary * );
48 BOOL isBootable( CONST_STRPTR deviceNam, struct DosLibrary * );
50 AROS_UFH3(void, intBoot,
51 AROS_UFHA(APTR, argString, A0),
52 AROS_UFHA(ULONG, argSize, D0),
53 AROS_UFHA(struct ExecBase *,SysBase, A6)
56 AROS_USERFUNC_INIT
58 struct ExpansionBase *ExpansionBase = NULL;
59 struct DosLibrary *DOSBase = NULL;
60 struct BootNode *bootNode = NULL;
61 STRPTR bootName;
62 LONG bootNameLength;
63 BPTR lock;
64 LONG second;
66 # define deviceName (((struct DosList *) bootNode->bn_DeviceNode)->dol_Ext.dol_AROS.dol_DevName)
68 /**** Open all required libraries **********************************************/
69 DOSBase = (struct DosLibrary *) OpenLibrary( "dos.library", 0 );
70 ExpansionBase = (struct ExpansionBase *) OpenLibrary( "expansion.library", 0 );
72 if( DOSBase == NULL )
74 D(bug( "Could not open dos.library, something's wrong!\n" ));
75 Alert(AT_DeadEnd| AG_OpenLib | AN_DOSLib | AO_DOSLib);
78 if( ExpansionBase == NULL )
80 D(bug( "Could not open expansion.library, something's wrong!\n"));
81 Alert(AT_DeadEnd | AG_OpenLib | AN_DOSLib | AO_ExpansionLib);
84 /**** Try to mount all filesystems in the MountList ****************************/
85 D(bug( "Examining MountList:\n" ));
87 ForeachNode( &ExpansionBase->MountList, bootNode )
89 D(bug
91 "Node: %p, DevNode: %p, Name = %s\n",
92 bootNode, bootNode->bn_DeviceNode,
93 deviceName ? deviceName : "(null)"
94 ));
95 /*
96 Try to mount the filesystem. If it fails, mark the BootNode
97 so DOS doesn't try to boot from it later but will retry to
98 mount it after boot device is found and system directories
99 assigned.
102 if( !mount( (struct DeviceNode *) bootNode->bn_DeviceNode ,
103 (struct DosLibrary *) DOSBase))
105 #ifdef MOUNT_DISK_HANDLERS
106 bootNode->bn_Flags |= BNF_RETRY;
107 #else
108 REMOVE( bootNode );
109 #endif
111 else
112 bootNode->bn_Flags &= ~BNF_RETRY;
115 /**** Try to find a bootable filesystem ****************************************/
116 while( TRUE )
118 ForeachNode( &ExpansionBase->MountList, bootNode )
121 Check if the mounted filesystem is bootable. If it's not,
122 it's probably some kind of transient error (ie. no disk
123 in drive or wrong disk) so we only move it to the end of
124 the list.
127 if((!(bootNode->bn_Flags & BNF_RETRY)) && isBootable( deviceName, (struct DosLibrary *)DOSBase ) )
129 goto boot;
133 kprintf( "No bootable disk was found.\n" );
134 kprintf( "Please insert a bootable disk in any drive.\n" );
136 #if 0
137 for( second = 5; second > 0; second-- ) {
138 kprintf( "Retrying in %d seconds...\n", second );
139 Delay( 50 );
141 #else
142 kprintf( "Retrying in 5 seconds...\n" );
143 Delay( 500 );
144 #endif
146 /* FIXME: Should there be a prompt instead of a automatic retry? */
149 boot:
151 /* Construct the complete device name of the boot device */
152 bootNameLength = strlen( deviceName ) + 2;
153 bootName = AllocMem( bootNameLength, MEMF_ANY);
155 if( bootName == NULL )
157 Alert(AT_DeadEnd | AG_NoMemory | AO_DOSLib | AN_StartMem);
160 strcpy( bootName, deviceName );
161 strcat( bootName, ":" );
163 kprintf("[DOS] Booting from device %s\n",bootName);
165 /* Lock the boot device and add some default assigns */
166 lock = Lock(bootName, SHARED_LOCK);
167 if (lock) DOSBase->dl_SYSLock = DupLock(lock);
169 if ((lock != NULL) && (DOSBase->dl_SYSLock != NULL))
171 AssignLock("SYS", lock);
173 else
175 Alert(AT_DeadEnd | AG_BadParm | AN_DOSLib);
178 FreeMem( bootName, bootNameLength );
180 lock = Lock("SYS:", SHARED_LOCK);
182 if (lock != NULL)
184 CurrentDir(lock);
186 else
188 Alert(AT_DeadEnd | AG_BadParm | AN_DOSLib);
191 lock = Lock("SYS:C", SHARED_LOCK);
193 if (lock != NULL)
195 AssignLock("C", lock);
198 lock = Lock("SYS:S", SHARED_LOCK);
200 if (lock != NULL)
202 AssignLock("S", lock);
205 lock = Lock("SYS:Libs", SHARED_LOCK);
207 if (lock != NULL)
209 AssignLock("LIBS", lock);
212 lock = Lock("SYS:Devs", SHARED_LOCK);
214 if (lock != NULL)
216 AssignLock("DEVS", lock);
219 lock = Lock("DEVS:Drivers", SHARED_LOCK);
221 if (lock != NULL)
223 AssignLock("DRIVERS", lock);
224 AssignAdd("LIBS", lock); /* Let hidds in DRIVERS: directory be found by OpenLibrary */
227 lock = Lock("SYS:L", SHARED_LOCK);
229 if (lock != NULL)
231 AssignLock("L", lock);
234 /* Late binding ENVARC: assign, only if used */
235 AssignLate("ENVARC", "SYS:Prefs/env-archive");
238 Retry to mount marked filesystems. If it fails again,
239 remove the BootNode from the list.
241 ForeachNode( &ExpansionBase->MountList, bootNode )
243 if (bootNode->bn_Flags & BNF_RETRY) {
244 D(bug
246 "Retry node: %p, DevNode: %p, Name = %s\n",
247 bootNode, bootNode->bn_DeviceNode,
248 deviceName ? deviceName : "(null)"
250 if( !mount( (struct DeviceNode *) bootNode->bn_DeviceNode ,
251 (struct DosLibrary *) DOSBase))
253 REMOVE( bootNode );
258 /* We don't need expansion.library any more */
259 CloseLibrary( (struct Library *) ExpansionBase );
261 /* Initialize HIDDs */
262 init_hidds(SysBase, (struct DosLibrary *)DOSBase);
264 /* We now call the system dependant boot - should never return. */
265 AROS_UFC3(void, boot,
266 AROS_UFCA(STRPTR, argString, A0),
267 AROS_UFCA(ULONG, argSize, D0),
268 AROS_UFCA(struct ExecBase *, SysBase, A6));
270 # undef deviceName
272 AROS_USERFUNC_EXIT
275 void DOSBoot(struct ExecBase *SysBase, struct DosLibrary *DOSBase)
277 struct TagItem bootprocess[] =
279 { NP_Entry, (IPTR) intBoot },
280 { NP_Name, (IPTR) "Boot Process" },
281 { NP_Input, (IPTR) NULL },
282 { NP_Output, (IPTR) NULL },
283 { NP_WindowPtr, -1 },
284 { NP_CurrentDir, (IPTR) NULL },
285 { NP_StackSize, AROS_STACKSIZE * 2},
286 { NP_Cli, (IPTR) 0 },
287 { TAG_END, }
290 if( CreateNewProc( bootprocess ) == NULL )
292 D(bug
294 "CreateNewProc() failed with %ld\n",
295 ((struct Process *) FindTask( NULL ))->pr_Result2
297 Alert( AT_DeadEnd | AN_DOSLib | AG_ProcCreate );
301 BOOL mount( struct DeviceNode *dn, struct DosLibrary * DOSBase )
303 BOOL rc;
305 if (!dn->dn_Ext.dn_AROS.dn_Device)
306 rc = RunHandler(dn, DOSBase);
307 else
308 rc = TRUE;
309 if (rc)
311 if (!AddDosEntry((struct DosList *) dn))
313 Alert(AT_DeadEnd | AG_NoMemory | AN_DOSLib);
316 return rc;
319 BOOL isBootable( CONST_STRPTR deviceName, struct DosLibrary * DOSBase )
321 BOOL result = FALSE;
322 BPTR lock;
323 STRPTR buffer;
324 LONG bufferLength;
325 struct InfoData info;
327 #define STARTUP_SEQUENCE_FILE ":S/Startup-Sequence"
329 bufferLength = strlen( deviceName ) + sizeof(STARTUP_SEQUENCE_FILE) + 1;
331 if( (buffer = AllocMem( bufferLength, MEMF_ANY ) ) == NULL )
333 Alert( AT_DeadEnd | AG_NoMemory | AN_DOSLib );
336 strcpy( buffer, deviceName );
337 strcat( buffer, STARTUP_SEQUENCE_FILE );
339 D(bug("Trying to get a lock on '%s'\n", buffer));
341 if( (lock = Lock( buffer, SHARED_LOCK )) == 0 )
343 D(bug( "dosboot: could not lock '%s'\n", buffer ));
344 goto cleanup;
347 if( !Info( lock, &info ) )
349 D(bug( "dosboot: could not get info on '%s'\n", buffer ));
350 goto cleanup;
353 if( info.id_DiskType != ID_NO_DISK_PRESENT )
355 result = TRUE;
358 cleanup:
359 if( buffer != NULL ) FreeMem( buffer, bufferLength );
360 if( lock != 0 ) UnLock( lock );
362 return result;