2 Copyright 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: Start up the ol' Dos boot process.
9 #define DOSBOOT_DISCINSERT_SCREENPRINT
12 # include <aros/debug.h>
14 #include <aros/macros.h>
15 #include <aros/asmcall.h>
17 #include <proto/bootmenu.h>
18 #include <proto/bootloader.h>
19 #include <proto/exec.h>
20 #include <proto/dos.h>
22 #include <exec/types.h>
23 #include <exec/nodes.h>
24 #include <exec/lists.h>
25 #include <exec/execbase.h>
26 #include <exec/alerts.h>
27 #include <exec/memory.h>
28 #include <dos/dosextens.h>
29 #include <dos/dostags.h>
30 #include <dos/filehandler.h>
31 #include <dos/filesystem.h>
32 #include <libraries/expansionbase.h>
33 #include <libraries/bootmenu.h>
34 #include <devices/trackdisk.h>
39 #include "dos_intern.h"
41 #define BNF_RETRY 0x8000 /* Private flag for the BootNode */
43 extern BOOL
init_hidds(struct ExecBase
*, struct DosLibrary
*);
44 extern void boot(struct ExecBase
*SysBase
, BOOL hidds_ok
);
46 BOOL attemptingboot
= FALSE
;
47 BOOL bootdevicefound
= FALSE
;
49 /** Support Functions **/
50 static BOOL
__dosboot_Mount(struct DeviceNode
*dn
, struct DosLibrary
* DOSBase
)
54 if (!dn
->dn_Ext
.dn_AROS
.dn_Device
)
55 rc
= RunHandler(dn
, DOSBase
);
61 if (!AddDosEntry((struct DosList
*) dn
))
63 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
69 static BOOL
__dosboot_IsBootable(CONST_STRPTR deviceName
, struct DosLibrary
* DOSBase
)
77 #define STARTUP_SEQUENCE_FILE ":C/Shell"
79 bufferLength
= strlen(deviceName
) + sizeof(STARTUP_SEQUENCE_FILE
) + 1;
81 if ((buffer
= AllocMem(bufferLength
, MEMF_ANY
)) == NULL
)
83 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
86 strcpy(buffer
, deviceName
);
87 strcat(buffer
, STARTUP_SEQUENCE_FILE
);
89 D(bug("[DOS] __dosboot_IsBootable: Trying to get a lock on '%s'\n", buffer
));
91 if ((lock
= Lock(buffer
, SHARED_LOCK
)) == 0)
93 D(bug("[DOS] __dosboot_IsBootable: could not lock '%s'\n", buffer
));
97 if (!Info(lock
, &info
))
99 D(bug("[DOS] __dosboot_IsBootable: could not get info on '%s'\n", buffer
));
103 if (info
.id_DiskType
!= ID_NO_DISK_PRESENT
)
109 if (buffer
!= NULL
) FreeMem(buffer
, bufferLength
);
110 if (lock
!= 0 ) UnLock(lock
);
117 AROS_UFH3(void, __dosboot_IntBoot
,
118 AROS_UFHA(APTR
, argString
, A0
),
119 AROS_UFHA(ULONG
, argSize
, D0
),
120 AROS_UFHA(struct ExecBase
*,SysBase
, A6
)
125 struct ExpansionBase
*ExpansionBase
= NULL
;
126 struct DosLibrary
*DOSBase
= NULL
;
127 struct BootMenuBase
*BootMenuBase
= NULL
;
128 void *BootLoaderBase
= NULL
;
130 struct BootNode
*bootNode
= NULL
;
136 struct MsgPort
*mp
; // Message port used with timer.device
137 struct timerequest
*tr
= NULL
; // timer's time request message
139 #define deviceName (((struct DosList *) bootNode->bn_DeviceNode)->dol_Ext.dol_AROS.dol_DevName)
141 /**** Open all required libraries **********************************************/
142 if ((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 0)) == NULL
)
144 D(bug("[DOS] __dosboot_IntBoot: Could not open dos.library, something's wrong!\n" ));
145 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
)
165 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
;
170 D(bug("[DOS] __dosboot_IntBoot: Could not open timer.device, something's wrong!\n"));
172 DeleteIORequest((struct IORequest
*)tr
);
182 /* Check if bootmenu is requested ... and setup base options */
183 if (BootMenuBase
!= NULL
)
184 bootmenu_CheckAndDisplay();
186 /**** Try to mount all filesystems in the MountList ****************************/
187 D(bug("[DOS] __dosboot_IntBoot: Checking MountList for useable nodes:\n" ));
189 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
191 D(bug("[DOS] __dosboot_IntBoot: BootNode: %p, bn_DeviceNode: %p, Name '%s', Priority %4d\n",
192 bootNode
, bootNode
->bn_DeviceNode
,
193 deviceName
? deviceName
: "(null)", bootNode
->bn_Node
.ln_Pri
196 Try to mount the filesystem. If it fails, mark the BootNode
197 so DOS doesn't try to boot from it later but will retry to
198 mount it after boot device is found and system directories
202 if( !__dosboot_Mount( (struct DeviceNode
*) bootNode
->bn_DeviceNode
,
203 (struct DosLibrary
*) DOSBase
))
204 bootNode
->bn_Flags
|= BNF_RETRY
;
206 bootNode
->bn_Flags
&= ~BNF_RETRY
;
209 /**** Try to find a bootable filesystem ****************************************/
210 while (bootdevicefound
== FALSE
)
212 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
214 /* Check if the mounted filesystem is bootable. If it's not,
215 it's probably some kind of transient error (ie. no disk
216 in drive or wrong disk) so we only move it to the end of
218 if ((!(bootNode
->bn_Flags
& BNF_RETRY
)) && (bootNode
->bn_Node
.ln_Pri
!= -128) &&
219 __dosboot_IsBootable(deviceName
, (struct DosLibrary
*)DOSBase
))
221 bootdevicefound
= TRUE
;
226 if (!bootdevicefound
)
230 #warning "TODO: Show insert disc animation !"
231 attemptingboot
= TRUE
;
235 #warning "TODO: re-run insert disc animation !"
237 #if defined(DOSBOOT_DISCINSERT_SCREENPRINT)
238 kprintf("No bootable disk was found.\n");
239 kprintf("Please insert a bootable disk in any drive.\n");
241 kprintf("Retrying in 5 seconds...\n");
245 tr
->tr_time
.tv_secs
= 5;
246 tr
->tr_time
.tv_micro
= 0;
247 DoIO((struct IORequest
*)tr
);
258 CloseDevice((struct IORequest
*)tr
);
259 DeleteIORequest((struct IORequest
*)tr
);
264 /* Construct the complete device name of the boot device */
265 bootNameLength
= strlen(deviceName
) + 2;
267 if ((bootName
= AllocMem(bootNameLength
, MEMF_ANY
|MEMF_CLEAR
)) == NULL
)
269 Alert(AT_DeadEnd
| AG_NoMemory
| AO_DOSLib
| AN_StartMem
);
272 strcpy(bootName
, deviceName
);
273 strcat(bootName
, ":");
275 D(bug("[DOS] __dosboot_IntBoot: Booting from device '%s'\n", bootName
));
277 /* Lock the boot device and add some default assigns */
278 lock
= Lock(bootName
, SHARED_LOCK
);
279 if (lock
) DOSBase
->dl_SYSLock
= DupLock(lock
);
281 if ((lock
!= NULL
) && (DOSBase
->dl_SYSLock
!= NULL
))
283 AssignLock("SYS", lock
);
287 Alert(AT_DeadEnd
| AG_BadParm
| AN_DOSLib
);
290 FreeMem( bootName
, bootNameLength
);
292 if ((lock
= Lock("SYS:", SHARED_LOCK
)) != NULL
)
298 Alert(AT_DeadEnd
| AG_BadParm
| AN_DOSLib
);
301 if ((lock
= Lock("SYS:C", SHARED_LOCK
)) != NULL
)
303 AssignLock("C", lock
);
306 if ((lock
= Lock("SYS:S", SHARED_LOCK
)) != NULL
)
308 AssignLock("S", lock
);
311 if ((lock
= Lock("SYS:Libs", SHARED_LOCK
)) != NULL
)
313 AssignLock("LIBS", lock
);
316 if ((lock
= Lock("SYS:Devs", SHARED_LOCK
)) != NULL
)
318 AssignLock("DEVS", lock
);
321 if ((lock
= Lock("DEVS:Drivers", SHARED_LOCK
)) != NULL
)
323 AssignLock("DRIVERS", lock
);
324 AssignAdd("LIBS", lock
); /* Let hidds in DRIVERS: directory be found by OpenLibrary */
327 if ((lock
= Lock("SYS:L", SHARED_LOCK
)) != NULL
)
329 AssignLock("L", lock
);
332 /* Late binding ENVARC: assign, only if used */
333 AssignLate("ENVARC", "SYS:Prefs/env-archive");
336 Attempt to mount filesystems marked for retry. If it fails again,
337 remove the BootNode from the list.
339 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
341 if (bootNode
->bn_Flags
& BNF_RETRY
)
343 D(bug("[DOS] __dosboot_IntBoot: Retrying node: %p, DevNode: %p, Name = %s\n", bootNode
, bootNode
->bn_DeviceNode
, deviceName
? deviceName
: "(null)" ));
344 if( !__dosboot_Mount((struct DeviceNode
*)bootNode
->bn_DeviceNode
, (struct DosLibrary
*)DOSBase
))
351 /* We don't need expansion.library any more */
352 CloseLibrary( (struct Library
*) ExpansionBase
);
354 /* Initialize HIDDs */
355 hidds_ok
= init_hidds(SysBase
, (struct DosLibrary
*)DOSBase
);
357 /* We now call the system dependant boot - should NEVER return! */
358 boot(SysBase
, hidds_ok
);
361 //We Should NEVER reach here!
367 void DOSBoot(struct ExecBase
*SysBase
, struct DosLibrary
*DOSBase
)
369 struct TagItem bootprocess
[] =
371 { NP_Entry
, (IPTR
) __dosboot_IntBoot
},
372 { NP_Name
, (IPTR
) "Boot Process" },
373 { NP_Input
, (IPTR
) NULL
},
374 { NP_Output
, (IPTR
) NULL
},
375 { NP_WindowPtr
, -1 },
376 { NP_CurrentDir
, (IPTR
) NULL
},
377 { NP_StackSize
, AROS_STACKSIZE
* 2 },
378 { NP_Cli
, (IPTR
) 0 },
382 if (CreateNewProc(bootprocess
) == NULL
)
384 D(bug("[DOS] DOSBoot: CreateNewProc() failed with %ld\n", ((struct Process
*)FindTask(NULL
))->pr_Result2
));
385 Alert( AT_DeadEnd
| AN_DOSLib
| AG_ProcCreate
);