2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
13 #include <exec/alerts.h>
14 #include <aros/asmcall.h>
15 #include <exec/lists.h>
16 #include <exec/memory.h>
17 #include <exec/resident.h>
18 #include <exec/types.h>
19 #include <libraries/configvars.h>
20 #include <libraries/expansionbase.h>
21 #include <libraries/partition.h>
22 #include <utility/tagitem.h>
23 #include <devices/bootblock.h>
25 #include <proto/exec.h>
26 #include <proto/expansion.h>
27 #include <proto/partition.h>
30 #include <aros/debug.h>
32 #include <aros/macros.h>
36 #define uppercase(x) ((x >= 'a' && x <= 'z') ? (x & 0xdf) : x)
43 static const UBYTE boot_end
;
44 int AROS_SLIB_ENTRY(init
,boot
)();
46 const struct Resident boot_resident
=
49 (struct Resident
*)&boot_resident
,
56 "AROS Boot Strap 41.0\r\n",
60 static const struct _dt
{
63 { 0xffffffff, AROS_MAKE_ID('B','E','F','S' ), (IPTR
)"befs.handler" },
64 { 0xffffff00, AROS_MAKE_ID('B','S','D','\0'), (IPTR
)"bsd.handler" },
65 { 0xffffff00, AROS_MAKE_ID('C','P','M','\0'), (IPTR
)"cpm.handler" },
66 { 0xffffff00, AROS_MAKE_ID('D','O','S','\0'), (IPTR
)"afs.handler" },
67 { 0xffffff00, AROS_MAKE_ID('E','X','T','\0'), (IPTR
)"ext.handler" },
68 { 0xffffff00, AROS_MAKE_ID('F','A','T','\0'), (IPTR
)"fat.handler" },
69 { 0xffffff00, AROS_MAKE_ID('L','V','M','\0'), (IPTR
)"lvm.handler" },
70 { 0xffffff00, AROS_MAKE_ID('M','N','X','\0'), (IPTR
)"minix.handler" },
71 { 0xffffffff, AROS_MAKE_ID('N','T','F','S' ), (IPTR
)"ntfs.handler" },
72 { 0xffffffff, AROS_MAKE_ID('R','A','I','D' ), (IPTR
)"raid.handler" },
73 { 0xffffff00, AROS_MAKE_ID('S','F','S','\0'), (IPTR
)"sfs.handler" },
74 { 0xffffff00, AROS_MAKE_ID('S','K','Y','\0'), (IPTR
)"skyfs.handler" },
75 { 0xffffffff, AROS_MAKE_ID('V','F','A','T' ), (IPTR
)"fat.handler" },
79 static const struct _pt
{
82 { 0x01, AROS_MAKE_ID('F','A','T',' ') }, /* DOS 12-bit FAT */
83 { 0x04, AROS_MAKE_ID('F','A','T',' ') }, /* DOS 16-bit FAT (up to 32M) */
84 { 0x06, AROS_MAKE_ID('F','A','T',' ') }, /* DOS 16-bit FAT (over 32M) */
85 { 0x07, AROS_MAKE_ID('N','T','F','S') }, /* Windows NT NTFS */
86 { 0x0b, AROS_MAKE_ID('V','F','A','T') }, /* W95 FAT32 */
87 { 0x0c, AROS_MAKE_ID('V','F','A','T') }, /* W95 LBA FAT32 */
88 { 0x0e, AROS_MAKE_ID('F','A','T',' ') }, /* W95 16-bit LBA FAT */
89 { 0x2c, AROS_MAKE_ID('D','O','S','\0') }, /* AOS OFS */
90 { 0x2d, AROS_MAKE_ID('D','O','S','\1') }, /* AOS FFS */
91 { 0x2e, AROS_MAKE_ID('D','O','S','\3') }, /* AOS FFS-I */
92 { 0x2f, AROS_MAKE_ID('S','F','S','\0') }, /* AOS SFS */
93 { 0x80, AROS_MAKE_ID('M','N','X','\0') }, /* MINIX until 1.4a */
94 { 0x81, AROS_MAKE_ID('M','N','X','\1') }, /* MINIX since 1.4b */
95 { 0x83, AROS_MAKE_ID('E','X','T','\2') }, /* linux native partition */
96 { 0x8e, AROS_MAKE_ID('L','V','M','\0') }, /* linux LVM partition */
97 { 0x9f, AROS_MAKE_ID('B','S','D','\0') }, /* BSD/OS */
98 { 0xa5, AROS_MAKE_ID('B','S','D','\1') }, /* NetBSD, FreeBSD */
99 { 0xa6, AROS_MAKE_ID('B','S','D','\2') }, /* OpenBSD */
100 { 0xdb, AROS_MAKE_ID('C','P','M','\2') }, /* CPM/M */
101 { 0xeb, AROS_MAKE_ID('B','E','F','S') }, /* BeOS FS */
102 { 0xec, AROS_MAKE_ID('S','K','Y','\0') }, /* SkyOS FS */
103 { 0xfd, AROS_MAKE_ID('R','A','I','D') }, /* linux RAID with autodetect */
107 static IPTR
MatchHandler(IPTR DosType
)
112 for (i
= 0; i
< (sizeof(DosTypes
) / sizeof(struct _dt
)); i
++)
114 if ((DosType
& DosTypes
[i
].mask
) == DosTypes
[i
].type
)
123 static IPTR
MatchPartType(UBYTE PartType
)
128 for (i
= 0; i
< (sizeof(PartTypes
) / sizeof(struct _pt
)); i
++)
130 if ((IPTR
)PartType
== PartTypes
[i
].part
)
132 type
= PartTypes
[i
].type
;
139 static ULONG
GetOffset(struct PartitionBase
*PartitionBase
,
140 struct PartitionHandle
*ph
)
146 tags
[0] = PT_DOSENVEC
;
147 tags
[1] = (STACKIPTR
)&de
;
152 GetPartitionAttrs(ph
, (struct TagItem
*)tags
);
153 offset
+= de
.de_LowCyl
;
159 static VOID AddPartitionVolume
161 struct ExpansionBase
*ExpansionBase
,
162 struct PartitionBase
*PartitionBase
,
163 struct FileSysStartupMsg
*fssm
,
164 struct PartitionHandle
*table
,
165 struct PartitionHandle
*pn
,
166 struct ExecBase
* SysBase
171 const struct PartitionAttribute
*attrs
;
174 struct DeviceNode
*devnode
;
175 struct PartitionType ptyp
;
179 pp
= AllocVec(sizeof(struct DosEnvec
) + sizeof(IPTR
) * 4,
180 MEMF_PUBLIC
| MEMF_CLEAR
);
183 attrs
= QueryPartitionAttrs(table
);
184 while ((attrs
->attribute
!= PTA_DONE
) && (attrs
->attribute
!= PTA_NAME
))
185 attrs
++; /* look for name attr */
186 if (attrs
->attribute
!= PTA_DONE
)
188 /* partition has a name => RDB partition */
190 tags
[1] = (STACKIPTR
)name
;
191 tags
[2] = PT_DOSENVEC
;
192 tags
[3] = (STACKIPTR
)&pp
[4];
194 GetPartitionAttrs(pn
, (struct TagItem
*)tags
);
198 /* partition doesn't have a name => MBR partition */
199 tags
[0] = PT_POSITION
;
200 tags
[1] = (STACKIPTR
)&ppos
;
202 tags
[3] = (STACKIPTR
)&ptyp
;
203 tags
[4] = PT_DOSENVEC
;
204 tags
[5] = (STACKIPTR
)&pp
[4];
206 GetPartitionAttrs(pn
, (struct TagItem
*)tags
);
209 devname
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
210 for (i
= 0; i
< 26; i
++)
212 if (*devname
== '.' || *devname
== '\0')
214 name
[i
] = (UBYTE
)uppercase(*devname
);
217 if ((fssm
->fssm_Unit
/ 10))
218 name
[i
++] = '0' + (UBYTE
)(fssm
->fssm_Unit
/ 10);
219 name
[i
++] = '0' + (UBYTE
)(fssm
->fssm_Unit
% 10);
222 name
[i
++] = '0' + (UBYTE
)(ppos
/ 10);
223 name
[i
++] = '0' + (UBYTE
)(ppos
% 10);
225 /* set DOSTYPE based on the partition type */
226 pp
[4 + DE_DOSTYPE
] = MatchPartType(ptyp
.id
[0]);
227 /* set some common DOSENV fields */
228 pp
[4 + DE_TABLESIZE
] = DE_BOOTBLOCKS
;
229 pp
[4 + DE_NUMBUFFERS
] = 20;
230 pp
[4 + DE_BUFMEMTYPE
] = MEMF_PUBLIC
;
231 pp
[4 + DE_MAXTRANSFER
] = 0x00200000;
232 pp
[4 + DE_MASK
] = 0x7ffffffe;
233 /* set some fs specific fields */
238 case 0x2e: /* FFS I */
240 pp
[4 + DE_SECSPERBLOCK
] = 1;
241 pp
[4 + DE_RESERVEDBLKS
] = 2;
242 pp
[4 + DE_BOOTBLOCKS
] = 2;
247 pp
[1] = (IPTR
)AROS_BSTR_ADDR(fssm
->fssm_Device
);
248 pp
[2] = fssm
->fssm_Unit
;
249 pp
[3] = fssm
->fssm_Flags
;
250 i
= GetOffset(PartitionBase
, pn
);
251 pp
[4 + DE_LOWCYL
] += i
;
252 pp
[4 + DE_HIGHCYL
] += i
;
254 pp
[0] = MatchHandler(pp
[4 + DE_DOSTYPE
]);
256 /* Skip unknown partition types */
259 devnode
= MakeDosNode(pp
);
262 devnode
->dn_OldName
= MKBADDR(AllocVec(strlen(name
) + 2,
263 MEMF_PUBLIC
| MEMF_CLEAR
));
264 if (devnode
->dn_OldName
)
269 AROS_BSTR_putchar(devnode
->dn_OldName
, i
, name
[i
]);
272 AROS_BSTR_setstrlen(devnode
->dn_OldName
, i
);
273 devnode
->dn_NewName
= AROS_BSTR_ADDR(devnode
->dn_OldName
);
274 AddBootNode(pp
[4 + DE_BOOTPRI
], 0, devnode
, 0);
275 D(bug("[Boot] AddBootNode(%s,0x%lx,'%s')\n",
276 devnode
->dn_NewName
, pp
[4 + DE_DOSTYPE
], pp
[0]));
285 static BOOL CheckTables
287 struct ExpansionBase
*ExpansionBase
,
288 struct PartitionBase
*PartitionBase
,
289 struct FileSysStartupMsg
*fssm
,
290 struct PartitionHandle
*table
,
291 struct ExecBase
*SysBase
295 struct PartitionHandle
*ph
;
297 /* Traverse partition tables recursively, and attempt to add a BootNode
298 for any non-subtable partitions found */
299 if (OpenPartitionTable(table
) == 0)
301 ph
= (struct PartitionHandle
*)table
->table
->list
.lh_Head
;
302 while (ph
->ln
.ln_Succ
)
304 /* Attempt to add partition to system if it isn't a subtable */
305 if (!CheckTables(ExpansionBase
, PartitionBase
, fssm
, ph
, SysBase
))
306 AddPartitionVolume(ExpansionBase
, PartitionBase
, fssm
, table
,
308 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
311 ClosePartitionTable(table
);
316 static BOOL
IsRemovable(struct ExecBase
*SysBase
, struct IOExtTD
*ioreq
)
318 struct DriveGeometry dg
;
320 ioreq
->iotd_Req
.io_Command
= TD_GETGEOMETRY
;
321 ioreq
->iotd_Req
.io_Data
= &dg
;
322 ioreq
->iotd_Req
.io_Length
= sizeof(struct DriveGeometry
);
323 DoIO((struct IORequest
*)ioreq
);
324 return (dg
.dg_Flags
& DGF_REMOVABLE
) ? TRUE
: FALSE
;
327 static VOID CheckPartitions
329 struct ExpansionBase
*ExpansionBase
,
330 struct ExecBase
*SysBase
,
334 struct PartitionBase
*PartitionBase
;
335 struct PartitionHandle
*pt
;
336 struct FileSysStartupMsg
*fssm
;
339 (struct PartitionBase
*)OpenLibrary("partition.library", 1);
342 fssm
= BADDR(((struct DeviceNode
*)bn
->bn_DeviceNode
)->dn_Startup
);
343 pt
= OpenRootPartition(AROS_BSTR_ADDR(fssm
->fssm_Device
),
347 if (IsRemovable(SysBase
, pt
->bd
->ioreq
))
349 /* don't check removable devices for partition tables */
350 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
354 if (!CheckTables(ExpansionBase
, PartitionBase
, fssm
, pt
,
357 /* no partition table found, so reinsert node */
358 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
361 CloseRootPartition(pt
);
365 /* amicdrom fails here because of non-initialized libraries */
366 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
368 CloseLibrary((struct Library
*)PartitionBase
);
372 AROS_UFH3(int, AROS_SLIB_ENTRY(init
, boot
),
373 AROS_UFHA(ULONG
, dummy
, D0
),
374 AROS_UFHA(ULONG
, seglist
, A0
),
375 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
379 struct ExpansionBase
*ExpansionBase
;
380 struct BootNode
*bootNode
;
382 struct Resident
*DOSResident
;
384 #if !(AROS_FLAVOUR & AROS_FLAVOUR_EMULATION)
386 (struct ExpansionBase
*)OpenLibrary("expansion.library", 0);
387 if( ExpansionBase
== NULL
)
389 D(bug( "Could not open expansion.library, something's wrong!\n"));
390 Alert(AT_DeadEnd
| AG_OpenLib
| AN_BootStrap
| AO_ExpansionLib
);
393 /* move all boot nodes into another list */
395 while ((bootNode
= (struct BootNode
*)RemHead(&ExpansionBase
->MountList
)))
396 AddTail(&list
, &bootNode
->bn_Node
);
398 /* check boot nodes for partition tables */
399 while ((bootNode
= (struct BootNode
*)RemHead(&list
)))
400 CheckPartitions(ExpansionBase
, SysBase
, bootNode
);
401 CloseLibrary((struct Library
*)ExpansionBase
);
404 DOSResident
= FindResident( "dos.library" );
406 if( DOSResident
== NULL
)
408 Alert( AT_DeadEnd
| AG_OpenLib
| AN_BootStrap
| AO_DOSLib
);
411 InitResident( DOSResident
, NULL
);
418 static const UBYTE boot_end
= 0;