2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Start up the ol' Dos boot process.
9 #define AROS_BOOT_CHECKSIG
12 * Load DEVS:system-configuration only on m68k.
13 * Setup pre-2.0 boot disk colors and mouse cursors (for example)
15 #define USE_SYSTEM_CONFIGURATION
19 # include <aros/debug.h>
21 #include <aros/macros.h>
22 #include <aros/asmcall.h>
23 #include <aros/symbolsets.h>
25 #include <proto/exec.h>
26 #include <proto/dos.h>
28 #include <exec/types.h>
29 #include <exec/nodes.h>
30 #include <exec/lists.h>
31 #include <exec/execbase.h>
32 #include <exec/alerts.h>
33 #include <exec/memory.h>
34 #include <dos/dosextens.h>
35 #include <dos/dostags.h>
36 #include <dos/filehandler.h>
37 #include <dos/filesystem.h>
38 #include <libraries/expansionbase.h>
39 #include <devices/trackdisk.h>
44 #ifdef USE_SYSTEM_CONFIGURATION
46 #include <proto/intuition.h>
48 static void load_system_configuration(struct DosLibrary
*DOSBase
)
52 struct Preferences prefs
;
53 struct Library
*IntuitionBase
;
55 fh
= Open("DEVS:system-configuration", MODE_OLDFILE
);
58 len
= Read(fh
, &prefs
, sizeof prefs
);
60 if (len
!= sizeof prefs
)
62 IntuitionBase
= TaggedOpenLibrary(TAGGEDOPEN_INTUITION
);
64 SetPrefs(&prefs
, len
, FALSE
);
65 CloseLibrary(IntuitionBase
);
70 #define load_system_configuration(DOSBase)
74 #include LC_LIBDEFS_FILE
76 #define BNF_MOUNTED 0x8000 /* Private flag for the BootNode */
79 #include "dosboot_intern.h"
82 * This functions differs from normal DOS mount sequence in
83 * that it first attempts to start a handler for the DeviceNode and
84 * then adds it to DOSList only if succeeded.
85 * This helps to get rid of non-functional DeviceNodes because of missing handlers.
87 static BOOL
__dosboot_Mount(struct DeviceNode
*dn
, struct DosLibrary
* DOSBase
)
89 /* RunHandler() is a private dos.library function */
90 struct MsgPort
*rc
= RunHandler(dn
, NULL
);
94 if (!AddDosEntry((struct DosList
*) dn
))
96 kprintf("Mounting node 0x%p (%b) failed at AddDosEntry() -- maybe it was already added by someone else!\n", dn
, dn
->dn_Name
);
97 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
100 return rc
? TRUE
: FALSE
;
103 static BOOL
__dosboot_IsBootable(CONST_STRPTR deviceName
, struct DosLibrary
* DOSBase
)
110 D(bug("[DOSBoot] __dosboot_IsBootable('%s')\n", deviceName
));
112 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(mc68000)
115 bufferLength
= strlen(deviceName
) + 1 + 1;
116 /* bootable if we can lock the device */
117 buffer
= AllocMem(bufferLength
, MEMF_ANY
);
120 sprintf(buffer
, "%s:", deviceName
);
121 if ((lock
= Lock(buffer
, SHARED_LOCK
)))
129 #if defined(AROS_BOOT_CHECKSIG)
130 #define AROSBOOTSIG_FILE ":AROS.boot"
133 struct FileInfoBlock abfile_fib
;
135 bufferLength
= strlen(deviceName
) + sizeof(AROSBOOTSIG_FILE
) + 1;
137 if ((buffer
= AllocMem(bufferLength
, MEMF_ANY
)) == NULL
)
139 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
142 strcpy(buffer
, deviceName
);
143 strcat(buffer
, AROSBOOTSIG_FILE
);
145 if ((lock
= Open(buffer
, MODE_OLDFILE
)) == 0)
147 D(bug("[DOSBoot] __dosboot_IsBootable: Failed to open '%s'\n", buffer
));
151 D(bug("[DOSBoot] __dosboot_IsBootable: Opened '%s'\n", buffer
));
152 FreeMem(buffer
, bufferLength
);
155 if (ExamineFH(lock
, &abfile_fib
))
157 bufferLength
= abfile_fib
.fib_Size
+ 1;
159 if ((buffer
= AllocMem(bufferLength
, MEMF_ANY
)) == NULL
)
161 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
163 D(bug("[DOSBoot] __dosboot_IsBootable: Allocated %d bytes for Buffer @ %p\n", bufferLength
, buffer
));
164 if ((readsize
= Read(lock
, buffer
, (bufferLength
- 1))) != -1)
169 buffer
[readsize
] = '\0';
171 buffer
[bufferLength
- 1] = '\0';
173 D(bug("[DOSBoot] __dosboot_IsBootable: Buffer contains '%s'\n", buffer
));
174 if ((sigptr
= strstr(buffer
, AROS_CPU
)) != 0)
176 D(bug("[DOSBoot] __dosboot_IsBootable: Signature '%s' found\n", sigptr
));
185 #define SHELL_FILE ":C/Shell"
189 bufferLength
= strlen(deviceName
) + sizeof(SHELL_FILE
) + 1;
191 if ((buffer
= AllocMem(bufferLength
, MEMF_PUBLIC
)) == NULL
)
193 Alert(AT_DeadEnd
| AG_NoMemory
| AN_DOSLib
);
196 strcpy(buffer
, deviceName
);
197 strcat(buffer
, SHELL_FILE
);
199 D(bug("[DOSBoot] __dosboot_IsBootable: "
200 "Trying to load '%s' as an executable\n", buffer
));
202 if ((seglist
= LoadSeg(buffer
)) == (BPTR
)NULL
)
204 D(bug("[DOSBoot] __dosboot_IsBootable: could not load '%s'\n", buffer
));
216 if (buffer
!= NULL
) FreeMem(buffer
, bufferLength
);
218 D(bug("[DOSBoot] __dosboot_IsBootable returned %d\n", result
));
223 static void AddBootAssign(CONST_STRPTR path
, CONST_STRPTR assign
)
226 if (!(lock
= Lock(path
, SHARED_LOCK
)))
227 lock
= Lock("SYS:", SHARED_LOCK
);
229 AssignLock(assign
, lock
);
234 AROS_UFH3(void, __dosboot_BootProcess
,
235 AROS_UFHA(APTR
, argString
, A0
),
236 AROS_UFHA(ULONG
, argSize
, D0
),
237 AROS_UFHA(struct ExecBase
*,SysBase
, A6
)
242 struct ExpansionBase
*ExpansionBase
= NULL
;
243 struct DosLibrary
*DOSBase
= NULL
;
244 LIBBASETYPEPTR LIBBASE
= FindTask(NULL
)->tc_UserData
;
246 struct BootNode
*bootNode
= NULL
;
247 struct Node
*tmpNode
= NULL
;
251 APTR BootLoaderBase
= OpenResource("bootloader.resource");
252 struct Screen
*bootScreen
= NULL
;
254 D(bug("[DOSBoot] __dosboot_BootProcess()\n"));
256 /**** Open all required libraries **********************************************/
257 if ((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 0)) == NULL
)
259 D(bug("[DOSBoot] __dosboot_BootProcess: Failed to open dos.library.\n" ));
260 Alert(AT_DeadEnd
| AG_OpenLib
| AN_DOSLib
| AO_DOSLib
);
263 if ((ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library", 0)) == NULL
)
265 D(bug("[DOSBoot] __dosboot_BootProcess: Failed to open expansion.library.\n"));
266 Alert(AT_DeadEnd
| AG_OpenLib
| AN_DOSLib
| AO_ExpansionLib
);
269 /**** Try to mount all filesystems in the MountList ****************************/
270 D(bug("[DOSBoot] __dosboot_BootProcess: Checking expansion.library/MountList for useable nodes:\n"));
272 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
274 struct DeviceNode
*dn
= bootNode
->bn_DeviceNode
;
276 D(bug("[DOSBoot] __dosboot_BootProcess: BootNode: %p, bn_DeviceNode: %p, Name '%b', Priority %4d\n",
277 bootNode
, dn
, dn
->dn_Name
, bootNode
->bn_Node
.ln_Pri
));
279 * Try to mount the filesystem. If it succeeds, mark the BootNode
282 if (__dosboot_Mount(dn
, DOSBase
))
284 bootNode
->bn_Flags
|= BNF_MOUNTED
;
285 D(bug("[DOSBoot] __dosboot_BootProcess: Marked '%b' as useable\n", dn
->dn_Name
));
288 /* Since this is our private flag, make sure that noone has ocassionally set it */
289 bootNode
->bn_Flags
&= ~BNF_MOUNTED
;
292 LIBBASE
->delayTicks
= 500;
294 /**** Try to find a bootable filesystem ****************************************/
295 while (LIBBASE
->db_BootDevice
== NULL
)
297 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
299 struct DeviceNode
*dn
= bootNode
->bn_DeviceNode
;
300 STRPTR deviceName
= AROS_BSTR_ADDR(dn
->dn_Name
);
302 D(bug("[DOSBoot] __dosboot_BootProcess: Trying '%s' ...\n", deviceName
));
305 * Check if the mounted filesystem is bootable. If it's not,
306 * it's probably some kind of transient error (ie. no disk
307 * in drive or wrong disk) so we will retry after some time.
309 if ((bootNode
->bn_Flags
& BNF_MOUNTED
) && (bootNode
->bn_Node
.ln_Pri
!= -128)
310 && __dosboot_IsBootable(deviceName
, DOSBase
))
312 LIBBASE
->db_BootDevice
= deviceName
;
317 if (!(LIBBASE
->db_BootDevice
))
322 bootScreen
= NoBootMediaScreen(LIBBASE
);
324 D(kprintf("No bootable disk was found.\n"));
325 D(kprintf("Please insert a bootable disk in any drive.\n"));
326 D(kprintf("Retrying in 3 seconds...\n"));
328 for (t
= 0; t
< 150; t
+= LIBBASE
->delayTicks
)
331 Delay(LIBBASE
->delayTicks
);
332 anim_Animate(bootScreen
, DOSBootBase
);
336 * Retry to mount stuff -- there might be some additional device in the meanwhile
337 * (this for example happens when USB stick is inserted and a new device has been
340 ForeachNode(&ExpansionBase
->MountList
, bootNode
)
342 if (!(bootNode
->bn_Flags
& BNF_MOUNTED
))
344 struct DeviceNode
*dn
= bootNode
->bn_DeviceNode
;
346 D(bug("[DOSBoot] __dosboot_BootProcess: Trying to mount '%b' ...\n", dn
->dn_Name
));
347 if (__dosboot_Mount(dn
, DOSBase
))
349 bootNode
->bn_Flags
|= BNF_MOUNTED
;
350 D(bug("[DOSBoot] __dosboot_BootProcess: Late marked '%b' as useable\n", dn
->dn_Name
));
359 anim_Stop(DOSBootBase
);
360 CloseBootScreen(bootScreen
, LIBBASE
);
363 if (LIBBASE
->db_BootDevice
!= NULL
)
365 /* Construct the complete device name of the boot device */
366 bootNameLength
= strlen(LIBBASE
->db_BootDevice
) + 2;
368 if ((bootName
= AllocMem(bootNameLength
, MEMF_ANY
|MEMF_CLEAR
)) == NULL
)
370 Alert(AT_DeadEnd
| AG_NoMemory
| AO_DOSLib
| AN_StartMem
);
373 strcpy(bootName
, LIBBASE
->db_BootDevice
);
374 strcat(bootName
, ":");
376 D(bug("[DOSBoot] __dosboot_BootProcess: Booting from device '%s'\n", bootName
));
378 /* Lock the boot device and add some default assigns */
379 lock
= Lock(bootName
, SHARED_LOCK
);
381 DOSBase
->dl_SYSLock
= DupLock(lock
);
383 if ((lock
!= BNULL
) && (DOSBase
->dl_SYSLock
!= BNULL
))
385 AssignLock("SYS", lock
);
389 Alert(AT_DeadEnd
| AG_BadParm
| AN_DOSLib
);
392 FreeMem( bootName
, bootNameLength
);
394 if ((lock
= Lock("SYS:", SHARED_LOCK
)) != BNULL
)
400 Alert(AT_DeadEnd
| AG_BadParm
| AN_DOSLib
);
403 AddBootAssign("SYS:C", "C");
404 AddBootAssign("SYS:S", "S");
405 AddBootAssign("SYS:Libs", "LIBS");
406 AddBootAssign("SYS:Devs", "DEVS");
407 AddBootAssign("SYS:L", "L");
408 AddBootAssign("SYS:Fonts", "FONTS");
411 if ((lock
= Lock("DEVS:Drivers", SHARED_LOCK
)) != BNULL
)
413 AssignLock("DRIVERS", lock
);
414 AssignAdd("LIBS", lock
); /* Let hidds in DRIVERS: directory be found by OpenLibrary */
418 /* Late binding ENVARC: assign, only if used */
419 AssignLate("ENVARC", "SYS:Prefs/env-archive");
420 load_system_configuration(DOSBase
);
423 * Attempt to mount filesystems which are not mounted yet.
424 * Here we already can load disk-based handlers.
425 * If mounting fails again, remove the BootNode from the list.
427 D(bug("[DOSBoot] Assigns done, retrying mounting handlers\n"));
428 ForeachNodeSafe(&ExpansionBase
->MountList
, bootNode
, tmpNode
)
430 if (!(bootNode
->bn_Flags
& BNF_MOUNTED
))
432 struct DeviceNode
*dn
= bootNode
->bn_DeviceNode
;
434 D(bug("[DOSBoot] __dosboot_BootProcess: Retrying node: %p, DevNode: %p, Name = %s\n", bootNode
, dn
, dn
->dn_Name
));
435 if( !__dosboot_Mount(dn
, DOSBase
))
443 ExpansionBase
->Flags
|= EBF_BOOTFINISHED
;
445 /* We don't need expansion.library any more */
446 D(bug("[DOSBoot] Closing expansion.library\n"));
447 CloseLibrary( (struct Library
*) ExpansionBase
);
450 /* Initialize HIDDs */
451 if (!(LIBBASE
->BootFlags
& BF_NO_DISPLAY_DRIVERS
))
453 D(bug("[DOSBoot] Loading display drivers\n"));
454 __dosboot_InitHidds(DOSBase
);
457 /* We now call the system dependant boot - should NEVER return! */
458 D(bug("[DOSBoot] Calling bootstrap code\n"));
459 __dosboot_Boot(BootLoaderBase
, DOSBase
, LIBBASE
->BootFlags
);
465 int dosboot_Init(LIBBASETYPEPTR LIBBASE
)
467 struct TagItem bootprocess
[] =
469 { NP_Entry
, (IPTR
) __dosboot_BootProcess
},
470 { NP_Name
, (IPTR
) "Boot Process" },
471 { NP_UserData
, (IPTR
) LIBBASE
},
472 { NP_Input
, (IPTR
) NULL
},
473 { NP_Output
, (IPTR
) NULL
},
474 { NP_WindowPtr
, -1 },
475 { NP_CurrentDir
, (IPTR
) NULL
},
476 { NP_StackSize
, AROS_STACKSIZE
* 2 },
477 { NP_Cli
, (IPTR
) 0 },
481 D(bug("[DOSBoot] dosboot_Init()\n"));
482 D(bug("[DOSBoot] dosboot_Init: Launching Boot Process control task ..\n"));
484 LIBBASE
->db_BootDevice
= NULL
;
485 LIBBASE
->BootFlags
= 0;
487 bootmenu_Init(LIBBASE
);
489 if (CreateNewProc(bootprocess
) == NULL
)
491 D(bug("[DOSBoot] dosboot_Init: CreateNewProc() failed with %ld\n", ((struct Process
*)FindTask(NULL
))->pr_Result2
));
492 Alert( AT_DeadEnd
| AN_DOSLib
| AG_ProcCreate
);
497 ADD2INITLIB(dosboot_Init
, 1)