Build fix, include deflibdefs.h during dependencies generation.
[AROS.git] / rom / dosboot / dosboot_init.c
blob302384c93c409f881135630417abbe19cf654eca
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Start up the ol' Dos boot process.
6 Lang: english
7 */
9 #define AROS_BOOT_CHECKSIG
10 #ifdef __mc68000
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
16 #endif
18 # define DEBUG 0
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>
41 #include <string.h>
42 #include <stdio.h>
44 #ifdef USE_SYSTEM_CONFIGURATION
46 #include <proto/intuition.h>
48 static void load_system_configuration(struct DosLibrary *DOSBase)
50 BPTR fh;
51 ULONG len;
52 struct Preferences prefs;
53 struct Library *IntuitionBase;
55 fh = Open("DEVS:system-configuration", MODE_OLDFILE);
56 if (!fh)
57 return;
58 len = Read(fh, &prefs, sizeof prefs);
59 Close(fh);
60 if (len != sizeof prefs)
61 return;
62 IntuitionBase = TaggedOpenLibrary(TAGGEDOPEN_INTUITION);
63 if (IntuitionBase)
64 SetPrefs(&prefs, len, FALSE);
65 CloseLibrary(IntuitionBase);
68 #else
70 #define load_system_configuration(DOSBase)
72 #endif
74 #include LC_LIBDEFS_FILE
76 #define BNF_MOUNTED 0x8000 /* Private flag for the BootNode */
78 #include "menu.h"
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);
92 if (rc)
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)
105 BPTR lock;
106 BOOL result = FALSE;
107 STRPTR buffer;
108 LONG bufferLength;
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);
118 if (!buffer)
119 return FALSE;
120 sprintf(buffer, "%s:", deviceName);
121 if ((lock = Lock(buffer, SHARED_LOCK)))
122 result = TRUE;
123 UnLock(lock);
124 lock = 0;
127 #else
129 #if defined(AROS_BOOT_CHECKSIG)
130 #define AROSBOOTSIG_FILE ":AROS.boot"
132 LONG readsize;
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));
148 goto cleanup;
151 D(bug("[DOSBoot] __dosboot_IsBootable: Opened '%s'\n", buffer));
152 FreeMem(buffer, bufferLength);
153 buffer = NULL;
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)
166 char *sigptr = NULL;
168 if (readsize != 0)
169 buffer[readsize] = '\0';
170 else
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));
177 result = TRUE;
181 Close(lock);
182 lock = BNULL;
184 #else
185 #define SHELL_FILE ":C/Shell"
187 BPTR seglist;
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));
205 goto cleanup;
208 UnLoadSeg(seglist);
209 result = TRUE;
210 #endif
213 cleanup:
214 #endif
216 if (buffer != NULL ) FreeMem(buffer, bufferLength);
218 D(bug("[DOSBoot] __dosboot_IsBootable returned %d\n", result));
220 return result;
223 static void AddBootAssign(CONST_STRPTR path, CONST_STRPTR assign)
225 BPTR lock;
226 if (!(lock = Lock(path, SHARED_LOCK)))
227 lock = Lock("SYS:", SHARED_LOCK);
228 if (lock)
229 AssignLock(assign, lock);
232 /** Boot Code **/
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)
240 AROS_USERFUNC_INIT
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;
248 STRPTR bootName;
249 LONG bootNameLength;
250 BPTR lock;
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
280 * as mounted.
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));
287 else
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;
313 break;
317 if (!(LIBBASE->db_BootDevice))
319 ULONG t;
321 if (!bootScreen)
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
338 * added for it.
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));
357 if (bootScreen)
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);
380 if (lock)
381 DOSBase->dl_SYSLock = DupLock(lock);
383 if ((lock != BNULL) && (DOSBase->dl_SYSLock != BNULL))
385 AssignLock("SYS", lock);
387 else
389 Alert(AT_DeadEnd | AG_BadParm | AN_DOSLib);
392 FreeMem( bootName, bootNameLength );
394 if ((lock = Lock("SYS:", SHARED_LOCK)) != BNULL)
396 CurrentDir(lock);
398 else
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");
410 #if !(mc68000)
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 */
416 #endif
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))
437 Forbid();
438 REMOVE( bootNode );
439 Permit();
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 );
449 #if !(mc68000)
450 /* Initialize HIDDs */
451 if (!(LIBBASE->BootFlags & BF_NO_DISPLAY_DRIVERS))
453 D(bug("[DOSBoot] Loading display drivers\n"));
454 __dosboot_InitHidds(DOSBase);
456 #endif
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);
462 AROS_USERFUNC_EXIT
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 },
478 { TAG_END, }
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 );
494 return TRUE;
497 ADD2INITLIB(dosboot_Init, 1)