2 Copyright © 1995-2007, 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
;
152 GetPartitionAttrs(ph
, (struct TagItem
*)tags
);
153 offset
+= de
.de_LowCyl
* de
.de_Surfaces
* de
.de_BlocksPerTrack
;
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
170 ULONG i
, blockspercyl
;
171 const struct PartitionAttribute
*attrs
;
174 struct DeviceNode
*devnode
;
175 struct PartitionType ptyp
;
177 TEXT
*devname
, *handler
;
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] = (IPTR
)name
;
191 tags
[2] = PT_DOSENVEC
;
192 tags
[3] = (IPTR
)&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] = (IPTR
)&ppos
;
202 tags
[3] = (IPTR
)&ptyp
;
203 tags
[4] = PT_DOSENVEC
;
204 tags
[5] = (IPTR
)&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);
221 if (table
->table
->type
== PHPTT_EBR
)
224 name
[i
++] = '0' + (UBYTE
)(ppos
/ 10);
225 name
[i
++] = '0' + (UBYTE
)(ppos
% 10);
227 /* set DOSTYPE based on the partition type */
228 pp
[4 + DE_DOSTYPE
] = MatchPartType(ptyp
.id
[0]);
229 /* set some common DOSENV fields */
230 pp
[4 + DE_TABLESIZE
] = DE_BOOTBLOCKS
;
231 pp
[4 + DE_NUMBUFFERS
] = 20;
232 pp
[4 + DE_BUFMEMTYPE
] = MEMF_PUBLIC
;
233 pp
[4 + DE_MAXTRANSFER
] = 0x00200000;
234 pp
[4 + DE_MASK
] = 0x7ffffffe;
235 /* set some fs specific fields */
240 case 0x2e: /* FFS I */
242 pp
[4 + DE_SECSPERBLOCK
] = 1;
243 pp
[4 + DE_RESERVEDBLKS
] = 2;
244 pp
[4 + DE_BOOTBLOCKS
] = 2;
250 pp
[1] = (IPTR
)AROS_BSTR_ADDR(fssm
->fssm_Device
);
251 pp
[2] = fssm
->fssm_Unit
;
252 pp
[3] = fssm
->fssm_Flags
;
253 i
= GetOffset(PartitionBase
, pn
);
254 blockspercyl
= pp
[4 + DE_BLKSPERTRACK
] * pp
[4 + DE_NUMHEADS
];
255 if (i
% blockspercyl
!= 0)
258 pp
[4 + DE_LOWCYL
] += i
;
259 pp
[4 + DE_HIGHCYL
] += i
;
261 handler
= MatchHandler(pp
[4 + DE_DOSTYPE
]);
263 /* Skip unknown partition types */
266 devnode
= MakeDosNode(pp
);
269 devnode
->dn_Handler
= MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(
270 strlen(handler
)), MEMF_PUBLIC
| MEMF_CLEAR
));
271 if (devnode
->dn_Handler
)
274 while (handler
[i
] != '\0')
276 AROS_BSTR_putchar(devnode
->dn_Handler
, i
, handler
[i
]);
279 AROS_BSTR_setstrlen(devnode
->dn_Handler
, i
);
280 AddBootNode(pp
[4 + DE_BOOTPRI
], 0, devnode
, 0);
281 D(bug("[Boot] AddBootNode(%s,0x%lx,'%s')\n",
282 devnode
->dn_Ext
.dn_AROS
.dn_DevName
,
283 pp
[4 + DE_DOSTYPE
], handler
));
292 static BOOL CheckTables
294 struct ExpansionBase
*ExpansionBase
,
295 struct PartitionBase
*PartitionBase
,
296 struct FileSysStartupMsg
*fssm
,
297 struct PartitionHandle
*table
,
298 struct ExecBase
*SysBase
302 struct PartitionHandle
*ph
;
304 /* Traverse partition tables recursively, and attempt to add a BootNode
305 for any non-subtable partitions found */
306 if (OpenPartitionTable(table
) == 0)
308 ph
= (struct PartitionHandle
*)table
->table
->list
.lh_Head
;
309 while (ph
->ln
.ln_Succ
)
311 /* Attempt to add partition to system if it isn't a subtable */
312 if (!CheckTables(ExpansionBase
, PartitionBase
, fssm
, ph
, SysBase
))
313 AddPartitionVolume(ExpansionBase
, PartitionBase
, fssm
, table
,
315 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
318 ClosePartitionTable(table
);
323 static BOOL
IsRemovable(struct ExecBase
*SysBase
, struct IOExtTD
*ioreq
)
325 struct DriveGeometry dg
;
327 ioreq
->iotd_Req
.io_Command
= TD_GETGEOMETRY
;
328 ioreq
->iotd_Req
.io_Data
= &dg
;
329 ioreq
->iotd_Req
.io_Length
= sizeof(struct DriveGeometry
);
330 DoIO((struct IORequest
*)ioreq
);
331 return (dg
.dg_Flags
& DGF_REMOVABLE
) ? TRUE
: FALSE
;
334 static VOID CheckPartitions
336 struct ExpansionBase
*ExpansionBase
,
337 struct ExecBase
*SysBase
,
341 struct PartitionBase
*PartitionBase
;
342 struct PartitionHandle
*pt
;
343 struct FileSysStartupMsg
*fssm
;
346 (struct PartitionBase
*)OpenLibrary("partition.library", 1);
349 fssm
= BADDR(((struct DeviceNode
*)bn
->bn_DeviceNode
)->dn_Startup
);
350 pt
= OpenRootPartition(AROS_BSTR_ADDR(fssm
->fssm_Device
),
354 if (IsRemovable(SysBase
, pt
->bd
->ioreq
))
356 /* don't check removable devices for partition tables */
357 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
361 if (!CheckTables(ExpansionBase
, PartitionBase
, fssm
, pt
,
364 /* no partition table found, so reinsert node */
365 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
368 CloseRootPartition(pt
);
372 /* amicdrom fails here because of non-initialized libraries */
373 Enqueue(&ExpansionBase
->MountList
, (struct Node
*)bn
);
375 CloseLibrary((struct Library
*)PartitionBase
);
379 AROS_UFH3(int, AROS_SLIB_ENTRY(init
, boot
),
380 AROS_UFHA(ULONG
, dummy
, D0
),
381 AROS_UFHA(ULONG
, seglist
, A0
),
382 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
386 struct ExpansionBase
*ExpansionBase
;
387 struct BootNode
*bootNode
;
389 struct Resident
*DOSResident
;
391 #if !(AROS_FLAVOUR & AROS_FLAVOUR_EMULATION)
393 (struct ExpansionBase
*)OpenLibrary("expansion.library", 0);
394 if( ExpansionBase
== NULL
)
396 D(bug( "Could not open expansion.library, something's wrong!\n"));
397 Alert(AT_DeadEnd
| AG_OpenLib
| AN_BootStrap
| AO_ExpansionLib
);
400 /* move all boot nodes into another list */
402 while ((bootNode
= (struct BootNode
*)RemHead(&ExpansionBase
->MountList
)))
403 AddTail(&list
, &bootNode
->bn_Node
);
405 /* check boot nodes for partition tables */
406 while ((bootNode
= (struct BootNode
*)RemHead(&list
)))
407 CheckPartitions(ExpansionBase
, SysBase
, bootNode
);
408 CloseLibrary((struct Library
*)ExpansionBase
);
411 DOSResident
= FindResident( "dos.library" );
413 if( DOSResident
== NULL
)
415 Alert( AT_DeadEnd
| AG_OpenLib
| AN_BootStrap
| AO_DOSLib
);
418 InitResident( DOSResident
, NULL
);
425 static const UBYTE boot_end
= 0;