2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: Start up the ol' Dos boot process.
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
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>
42 #include "dos_intern.h"
44 #define BNF_RETRY 0x8000 /* Private flag for the BootNode */
46 extern BOOL
init_hidds(struct ExecBase
*, struct DosLibrary
*);
49 BOOL attemptingboot
= FALSE
;
50 BOOL bootdevicefound
= FALSE
;
52 /** Support Functions **/
53 static BOOL
__dosboot_Mount(struct DeviceNode
*dn
, struct DosLibrary
* DOSBase
)
57 if (!dn
->dn_Ext
.dn_AROS
.dn_Device
)
58 rc
= RunHandler(dn
, DOSBase
);
64 if (!AddDosEntry((struct DosList
*) dn
))
66 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
72 static BOOL
__dosboot_IsBootable(CONST_STRPTR deviceName
, struct DosLibrary
* DOSBase
)
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
));
100 if (!Info(lock
, &info
))
102 D(bug("[DOS] __dosboot_IsBootable: could not get info on '%s'\n", buffer
));
106 if (info
.id_DiskType
!= ID_NO_DISK_PRESENT
)
112 if (buffer
!= NULL
) FreeMem(buffer
, bufferLength
);
113 if (lock
!= 0 ) UnLock(lock
);
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
)
128 struct ExpansionBase
*ExpansionBase
= NULL
;
129 struct DosLibrary
*DOSBase
= NULL
;
130 struct BootMenuBase
*BootMenuBase
= NULL
;
132 struct BootNode
*bootNode
= NULL
;
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
;
171 D(bug("[DOS] __dosboot_IntBoot: Could not open timer.device, something's wrong!\n"));
173 DeleteIORequest((struct IORequest
*)tr
);
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
203 if( !__dosboot_Mount( (struct DeviceNode
*) bootNode
->bn_DeviceNode
,
204 (struct DosLibrary
*) DOSBase
))
206 #ifdef MOUNT_DISK_HANDLERS
207 bootNode
->bn_Flags
|= BNF_RETRY
;
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
225 if ((!(bootNode
->bn_Flags
& BNF_RETRY
)) && __dosboot_IsBootable( deviceName
, (struct DosLibrary
*)DOSBase
) )
227 bootdevicefound
= TRUE
;
232 if (!bootdevicefound
)
236 #warning "TODO: Show insert disc animation !"
237 attemptingboot
= TRUE
;
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");
251 tr
->tr_time
.tv_secs
= 5;
252 tr
->tr_time
.tv_micro
= 0;
253 DoIO((struct IORequest
*)tr
);
264 CloseDevice((struct IORequest
*)tr
);
265 DeleteIORequest((struct IORequest
*)tr
);
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
);
293 Alert(AT_DeadEnd
| AG_BadParm
| AN_DOSLib
);
296 FreeMem( bootName
, bootNameLength
);
298 if ((lock
= Lock("SYS:", SHARED_LOCK
)) != NULL
)
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
))
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!
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 },
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
);