2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
9 #include <aros/config.h>
10 #include <proto/dos.h>
11 #include <proto/exec.h>
12 #include <proto/partition.h>
13 #include <proto/utility.h>
15 #include <devices/hardblocks.h>
16 #include <exec/memory.h>
17 #include <exec/types.h>
18 #include <libraries/partition.h>
19 #include <resources/filesysres.h>
21 #include "partition_support.h"
32 struct RigidDiskBlock rdb
;
33 UBYTE rdbblock
; /* the block rdb was read from */
34 struct List badblocklist
;
35 struct List fsheaderlist
;
40 struct BadBlockBlock bbb
;
45 struct FileSysHandle h
;
47 struct FileSysHeaderBlock fhb
;
48 struct LoadSegBlock
*filesystem
; /* the FS in LSEG blocks */
49 ULONG fsblocks
; /* nr of LSEG blocks for FS */
52 #define LSEGDATASIZE (123 * sizeof(ULONG))
59 struct FileSysNode
*fsn
;
62 static AROS_UFH4(LONG
, ReadFunc
,
63 AROS_UFHA(BPTR
, file
, D1
),
64 AROS_UFHA(APTR
, buffer
, D2
),
65 AROS_UFHA(LONG
, length
, D3
),
66 AROS_UFHA(struct Library
*, DOSBase
, A6
))
70 struct FileSysReader
*fsr
= (struct FileSysReader
*)file
;
72 UBYTE
*outbuf
= buffer
;
77 if (size
+ fsr
->offset
> fsr
->size
)
78 size
= fsr
->size
- fsr
->offset
;
80 UBYTE
*inbuf
= (UBYTE
*)(fsr
->fsn
->filesystem
[fsr
->count
].lsb_LoadData
) + fsr
->offset
;
81 CopyMem(inbuf
, outbuf
, size
);
89 if (fsr
->offset
== fsr
->size
) {
92 if (fsr
->count
== fsr
->fsn
->fsblocks
)
103 static AROS_UFH4(LONG
, SeekFunc
,
104 AROS_UFHA(BPTR
, file
, D1
),
105 AROS_UFHA(LONG
, pos
, D2
),
106 AROS_UFHA(LONG
, mode
, D3
),
107 AROS_UFHA(struct Library
*, DOSBase
, A6
))
111 struct FileSysReader
*fsr
= (struct FileSysReader
*)file
;
112 LONG oldpos
= fsr
->offset
;
115 case OFFSET_BEGINNING
: break;
116 case OFFSET_END
: pos
= fsr
->size
- pos
; break;
117 case OFFSET_CURRENT
: pos
= fsr
->offset
+ pos
; break;
121 if (pos
< 0 || pos
>= fsr
->size
)
131 /* Load a filesystem into DOS seglist */
132 static BPTR
LoadFS(struct FileSysNode
*node
, struct DosLibrary
*DOSBase
)
134 LONG_FUNC FunctionArray
[4];
135 struct FileSysReader fakefile
;
138 /* Prevent loading hunk files on non-m68k */
139 if (AROS_BE2LONG(node
->filesystem
[0].lsb_LoadData
[0]) == 0x000003f3)
143 FunctionArray
[0] = (LONG_FUNC
)ReadFunc
;
144 FunctionArray
[1] = (LONG_FUNC
)__AROS_GETVECADDR(SysBase
,33); /* AllocMem() */
145 FunctionArray
[2] = (LONG_FUNC
)__AROS_GETVECADDR(SysBase
,35); /* FreeMem() */
146 FunctionArray
[3] = (LONG_FUNC
)SeekFunc
;
148 /* Initialize our stream */
151 fakefile
.size
= LSEGDATASIZE
;
154 return InternalLoadSeg((BPTR
)&fakefile
, BNULL
, FunctionArray
, NULL
);
158 * Insert RDB LSEG filesystem to FileSystem.resource
159 * FIXME: this is an obsolete hack. Use new filesystem API
160 * in Boot Strap instead.
163 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
165 /* We can't use InternalLoadSeg() because DOS isn't initialized
166 * at this point. To allow this to be built as a relocatable
167 * library, we will use the loadseg linklib.
172 void register_elf(BPTR file
, BPTR hunks
, struct elfheader
*eh
, struct sheader
*sh
, struct DosLibrary
*DOSBase
)
174 /* Do-nothing function to make the linker happy */
177 static void AddFS(struct RDBData
*data
)
179 struct FileSysResource
*fsr
;
180 struct FileSysNode
*node
;
181 void (* FunctionArray
[4])();
182 struct FileSysReader fakefile
;
184 FunctionArray
[0] = (void(*))ReadFunc
;
185 FunctionArray
[1] = __AROS_GETVECADDR(SysBase
,33); /* AllocMem() */
186 FunctionArray
[2] = __AROS_GETVECADDR(SysBase
,35); /* FreeMem() */
187 FunctionArray
[3] = (void(*))SeekFunc
;
189 fsr
= OpenResource("FileSystem.resource");
193 ForeachNode(&data
->fsheaderlist
, node
) {
194 struct FileSysEntry
*fsrnode
;
195 ULONG dostype
= node
->fhb
.fhb_DosType
;
196 ULONG version
= node
->fhb
.fhb_Version
;
197 BOOL newerinstalled
= FALSE
;
198 ULONG size
= LSEGDATASIZE
;
200 ForeachNode(&fsr
->fsr_FileSysEntries
, fsrnode
) {
201 if (fsrnode
->fse_DosType
== dostype
&& fsrnode
->fse_Version
>= version
)
202 newerinstalled
= TRUE
;
206 fsrnode
= AllocVec(sizeof(struct FileSysEntry
), MEMF_PUBLIC
| MEMF_CLEAR
);
211 fakefile
.size
= size
;
213 if (node
->filesystem
[0].lsb_LoadData
[0] == 0x000003f3) {
215 BPTR seg
= LoadSegment((BPTR
)&fakefile
, BNULL
, (SIPTR
*)FunctionArray
, NULL
);
217 D(bug("RDB fs %08x %d.%d '%s' seg=%08x added\n",
218 dostype
, version
>> 16, version
& 0xffff, &node
->fhb
.fhb_FileSysName
, seg
));
219 CopyMem(&node
->fhb
.fhb_DosType
, &fsrnode
->fse_DosType
, sizeof(struct FileSysEntry
) - sizeof(struct Node
));
220 fsrnode
->fse_SegList
= seg
;
221 AddHead(&fsr
->fsr_FileSysEntries
, &fsrnode
->fse_Node
);
229 static ULONG
calcChkSum(ULONG
*ptr
, ULONG size
)
236 sum
+= AROS_BE2LONG(*ptr
);
242 LONG PartitionRDBCheckPartitionTable
244 struct Library
*PartitionBase
,
245 struct PartitionHandle
*root
249 struct RigidDiskBlock
*rdb
= (struct RigidDiskBlock
*)root
->buffer
;
250 struct PartitionType type
;
251 struct TagItem tags
[] = {{PT_TYPE
, (IPTR
)&type
}, {TAG_DONE
, 0}};
253 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
256 if (root
->root
!= NULL
)
258 GetPartitionAttrs(root
, tags
);
260 (root
->root
->table
->type
!= PHPTT_MBR
&&
261 root
->root
->table
->type
!= PHPTT_EBR
) ||
262 (type
.id
[0] != 0x30 && type
.id
[0] != 0x76)
268 for (i
=0;i
<RDB_LOCATION_LIMIT
; i
++)
270 if (readBlock(PartitionBase
, root
, i
, rdb
) != 0)
272 if (rdb
->rdb_ID
== AROS_BE2LONG(IDNAME_RIGIDDISK
))
275 if (i
!= RDB_LOCATION_LIMIT
)
277 if (calcChkSum((ULONG
*)rdb
, AROS_BE2LONG(rdb
->rdb_SummedLongs
))==0)
283 void CopyBE2HostDosEnvec(LONG
*src
, SIPTR
*dst
, ULONG size
) {
286 while (count
!= size
)
288 *dst
++ = AROS_BE2LONG(*src
);
294 void CopyHost2BEDosEnvec(SIPTR
*src
, ULONG
*dst
, ULONG size
) {
298 while (count
!= size
)
300 *dst
++ = AROS_LONG2BE(*src
);
307 struct BadBlockNode
*PartitionRDBNewBadBlock
309 struct Library
*PartitionBase
,
310 struct PartitionHandle
*root
,
311 struct BadBlockBlock
*buffer
314 struct BadBlockNode
*bn
;
317 (AROS_BE2LONG(buffer
->bbb_ID
) == IDNAME_BADBLOCK
) &&
318 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->bbb_SummedLongs
))==0)
321 bn
= AllocMem(sizeof(struct BadBlockNode
), MEMF_PUBLIC
| MEMF_CLEAR
);
324 CopyMem(buffer
, &bn
->bbb
, sizeof(struct BadBlockBlock
));
331 struct PartitionHandle
*PartitionRDBNewHandle
333 struct Library
*PartitionBase
,
334 struct PartitionHandle
*root
,
335 struct PartitionBlock
*buffer
338 struct PartitionBlock
*pblock
;
339 struct PartitionHandle
*ph
;
342 (AROS_BE2LONG(buffer
->pb_ID
) == IDNAME_PARTITION
) &&
343 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->pb_SummedLongs
))==0)
346 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
349 ph
->ln
.ln_Name
= AllocVec(32, MEMF_PUBLIC
| MEMF_CLEAR
);
352 pblock
= AllocMem(sizeof(struct PartitionBlock
), MEMF_PUBLIC
);
355 CopyMem(buffer
, pblock
, sizeof(struct PartitionBlock
));
359 CopyMem(pblock
->pb_DriveName
+1, ph
->ln
.ln_Name
, pblock
->pb_DriveName
[0]);
360 ph
->ln
.ln_Name
[pblock
->pb_DriveName
[0]]=0;
361 CopyBE2HostDosEnvec(pblock
->pb_Environment
, (SIPTR
*)&ph
->de
, AROS_BE2LONG(((struct DosEnvec
*)pblock
->pb_Environment
)->de_TableSize
)+1);
362 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
363 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
364 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
365 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
366 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
367 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
370 FreeVec(ph
->ln
.ln_Name
);
372 FreeMem(ph
, sizeof(struct PartitionHandle
));
378 struct FileSysNode
*PartitionRDBNewFileSys
380 struct Library
*PartitionBase
,
381 struct PartitionHandle
*root
,
382 struct FileSysHeaderBlock
*buffer
385 struct FileSysNode
*fn
;
388 (AROS_BE2LONG(buffer
->fhb_ID
) == IDNAME_FILESYSHEADER
) &&
389 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->fhb_SummedLongs
))==0)
392 fn
= AllocMem(sizeof(struct FileSysNode
), MEMF_PUBLIC
| MEMF_CLEAR
);
395 CopyMem(buffer
, &fn
->fhb
, sizeof(struct FileSysHeaderBlock
));
397 /* Fill in common part of the handle */
398 fn
->h
.ln
.ln_Name
= fn
->fhb
.fhb_FileSysName
;
400 fn
->h
.handler
= &FilesystemRDB
;
408 static void PartitionRDBFreeFileSystem(struct FileSysHandle
*fsh
)
410 struct FileSysNode
*fn
= (struct FileSysNode
*)fsh
;
413 FreeVec(fn
->filesystem
);
414 FreeMem(fn
, sizeof(struct FileSysNode
));
417 ULONG PartitionRDBCalcFSSize
419 struct Library
*PartitionBase
,
420 struct PartitionHandle
*root
,
421 struct FileSysNode
*fn
,
422 struct LoadSegBlock
*buffer
429 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
430 while (block
!= (ULONG
)-1)
433 if (readBlock(PartitionBase
, root
, block
, buffer
) !=0)
436 (AROS_BE2LONG(buffer
->lsb_ID
) != IDNAME_LOADSEG
) ||
437 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->lsb_SummedLongs
)))
440 block
= AROS_BE2LONG(buffer
->lsb_Next
);
445 void PartitionRDBReadFileSys
447 struct Library
*PartitionBase
,
448 struct PartitionHandle
*root
,
449 struct FileSysNode
*fn
,
450 struct LoadSegBlock
*buffer
456 size
= PartitionRDBCalcFSSize(PartitionBase
, root
, fn
, buffer
);
460 fn
->filesystem
= AllocVec(size
*512, MEMF_PUBLIC
);
464 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
465 while (block
!= (ULONG
)-1)
467 if (readBlock(PartitionBase
, root
, block
, &fn
->filesystem
[size
]) !=0)
469 block
= AROS_BE2LONG(fn
->filesystem
[size
].lsb_Next
);
476 LONG PartitionRDBOpenPartitionTable
478 struct Library
*PartitionBase
,
479 struct PartitionHandle
*root
483 struct RDBData
*data
;
486 buffer
= AllocVec(root
->de
.de_SizeBlock
<< 2, MEMF_PUBLIC
);
489 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
);
492 for (i
=0;i
<RDB_LOCATION_LIMIT
; i
++)
494 if (readBlock(PartitionBase
, root
, i
, buffer
) != 0) {
498 CopyMem(buffer
, &data
->rdb
, sizeof(struct RigidDiskBlock
));
499 if (data
->rdb
.rdb_ID
== AROS_BE2LONG(IDNAME_RIGIDDISK
))
502 if (i
!= RDB_LOCATION_LIMIT
)
507 NEWLIST(&root
->table
->list
);
508 NEWLIST(&data
->badblocklist
);
509 NEWLIST(&data
->fsheaderlist
);
510 root
->table
->data
= data
;
511 /* take the values of the rdb instead of TD_GEOMETRY */
512 root
->dg
.dg_SectorSize
= AROS_BE2LONG(data
->rdb
.rdb_BlockBytes
);
513 root
->dg
.dg_Cylinders
= AROS_BE2LONG(data
->rdb
.rdb_Cylinders
);
514 root
->dg
.dg_TrackSectors
= AROS_BE2LONG(data
->rdb
.rdb_Sectors
);
515 root
->dg
.dg_Heads
= AROS_BE2LONG(data
->rdb
.rdb_Heads
);
516 /* read bad blocks */
517 block
= AROS_BE2LONG(data
->rdb
.rdb_BadBlockList
);
518 while (block
!= (ULONG
)-1)
520 struct BadBlockNode
*bn
;
522 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
524 bn
= PartitionRDBNewBadBlock(PartitionBase
, root
, (struct BadBlockBlock
*)buffer
);
527 AddTail(&data
->badblocklist
, &bn
->ln
);
528 block
= AROS_BE2LONG(bn
->bbb
.bbb_Next
);
536 /* read partition blocks */
537 block
= AROS_BE2LONG(data
->rdb
.rdb_PartitionList
);
538 while (block
!= (ULONG
)-1)
540 struct PartitionHandle
*ph
;
541 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
543 ph
= PartitionRDBNewHandle(PartitionBase
, root
, (struct PartitionBlock
*)buffer
);
546 AddTail(&root
->table
->list
, &ph
->ln
);
547 block
= AROS_BE2LONG(((struct PartitionBlock
*)ph
->data
)->pb_Next
);
555 /* read filesystem blocks */
556 block
= AROS_BE2LONG(data
->rdb
.rdb_FileSysHeaderList
);
557 while (block
!= (ULONG
)-1)
559 struct FileSysNode
*fn
;
561 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
563 fn
= PartitionRDBNewFileSys(PartitionBase
, root
, (struct FileSysHeaderBlock
*)buffer
);
566 AddTail(&data
->fsheaderlist
, &fn
->h
.ln
);
567 PartitionRDBReadFileSys(PartitionBase
, root
, fn
, (struct LoadSegBlock
*)buffer
);
568 block
= AROS_BE2LONG(fn
->fhb
.fhb_Next
);
577 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
582 FreeMem(data
, sizeof(struct RDBData
));
588 void PartitionRDBFreeHandle
590 struct Library
*PartitionBase
,
591 struct PartitionHandle
*ph
594 ClosePartitionTable(ph
);
596 FreeMem(ph
->data
, sizeof(struct PartitionBlock
));
597 FreeVec(ph
->ln
.ln_Name
);
598 FreeMem(ph
, sizeof(struct PartitionHandle
));
601 void PartitionRDBClosePartitionTable
603 struct Library
*PartitionBase
,
604 struct PartitionHandle
*root
607 struct PartitionHandle
*ph
;
608 struct BadBlockNode
*bn
;
609 struct FileSysNode
*fn
;
610 struct RDBData
*data
;
612 while ((ph
= (struct PartitionHandle
*)RemTail(&root
->table
->list
)))
613 PartitionRDBFreeHandle(PartitionBase
, ph
);
614 data
= (struct RDBData
*)root
->table
->data
;
615 while ((bn
= (struct BadBlockNode
*)RemTail(&data
->badblocklist
)))
616 FreeMem(bn
, sizeof(struct BadBlockNode
));
618 while ((fn
= (struct FileSysNode
*)RemTail(&data
->fsheaderlist
)))
620 /* Do not deallocate filesystem handles which are queued for loading */
622 PartitionRDBFreeFileSystem(&fn
->h
);
624 FreeMem(data
, sizeof(struct RDBData
));
627 ULONG PartitionRDBWriteFileSys
629 struct Library
*PartitionBase
,
630 struct PartitionHandle
*root
,
631 struct FileSysNode
*fn
,
640 while (size
!= fn
->fsblocks
)
642 fn
->filesystem
[size
].lsb_Next
= (size
+1) != fn
->fsblocks
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
643 fn
->filesystem
[size
].lsb_ChkSum
= 0;
644 fn
->filesystem
[size
].lsb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&fn
->filesystem
[size
], AROS_LONG2BE(fn
->filesystem
[size
].lsb_SummedLongs
)));
646 if (writeBlock(PartitionBase
, root
, block
++, &fn
->filesystem
[size
]) != 0)
649 kprintf("RDB-write: block=%ld, type=LSEG\n", block
);
658 static LONG
PartitionRDBWritePartitionTable(struct Library
*PartitionBase
, struct PartitionHandle
*root
)
660 struct RDBData
*data
;
661 struct PartitionHandle
*ph
;
662 struct PartitionBlock
*pblock
;
663 struct BadBlockNode
*bn
;
664 struct FileSysNode
*fn
;
667 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
670 data
= root
->table
->data
;
671 block
= data
->rdbblock
+1; /* RDB will be written at the end */
673 memset(root
->buffer
, 0, root
->de
.de_SizeBlock
<< 2);
675 /* write bad blocks */
676 bn
= (struct BadBlockNode
*)data
->badblocklist
.lh_Head
;
678 data
->rdb
.rdb_BadBlockList
= block
;
680 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
681 while (bn
->ln
.ln_Succ
)
683 bn
->bbb
.bbb_Next
= bn
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
684 bn
->bbb
.bbb_ChkSum
= 0;
685 bn
->bbb
.bbb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&bn
->bbb
, AROS_BE2LONG(bn
->bbb
.bbb_SummedLongs
)));
686 CopyMem(&bn
->bbb
, root
->buffer
, sizeof(struct BadBlockBlock
));
688 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
690 kprintf("RDB-write: block=%ld, type=BADB\n", block
);
694 bn
= (struct BadBlockNode
*)bn
->ln
.ln_Succ
;
697 /* write partition blocks */
698 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
700 data
->rdb
.rdb_PartitionList
= AROS_LONG2BE(block
);
702 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
703 while (ph
->ln
.ln_Succ
)
705 pblock
= (struct PartitionBlock
*)ph
->data
;
706 pblock
->pb_Next
= ph
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
707 pblock
->pb_ChkSum
= 0;
708 pblock
->pb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)pblock
, AROS_BE2LONG(pblock
->pb_SummedLongs
)));
709 CopyMem(pblock
, root
->buffer
, sizeof(struct PartitionBlock
));
711 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
713 kprintf("RDB-write: block=%ld, type=PART\n", block
);
716 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
719 /* write filesystem blocks */
720 fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
;
721 if (fn
->h
.ln
.ln_Succ
)
722 data
->rdb
.rdb_FileSysHeaderList
= AROS_LONG2BE(block
);
724 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
725 while (fn
->h
.ln
.ln_Succ
)
730 block
++; /* header block will be written later */
731 fn
->fhb
.fhb_SegListBlocks
= AROS_LONG2BE(block
);
732 /* write filesystem LSEG blocks */
733 block
= PartitionRDBWriteFileSys(PartitionBase
, root
, fn
, block
);
734 fn
->fhb
.fhb_Next
= fn
->h
.ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
) : (ULONG
)-1;
735 fn
->fhb
.fhb_ChkSum
= 0;
736 CopyMem(&fn
->fhb
, root
->buffer
, sizeof(struct FileSysHeaderBlock
));
737 ((struct FileSysHeaderBlock
*)root
->buffer
)->fhb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)root
->buffer
, AROS_BE2LONG(fn
->fhb
.fhb_SummedLongs
)));
739 writeBlock(PartitionBase
, root
, fshblock
, root
->buffer
);
741 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock
);
743 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
;
745 data
->rdb
.rdb_HighRDSKBlock
= AROS_LONG2BE(block
-1);
746 data
->rdb
.rdb_ChkSum
= 0;
747 data
->rdb
.rdb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&data
->rdb
, AROS_BE2LONG(data
->rdb
.rdb_SummedLongs
)));
748 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
750 writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
);
752 kprintf("RDB-write: block=%ld, type=RDSK\n", data
->rdbblock
);
757 LONG PartitionRDBCreatePartitionTable
759 struct Library
*PartitionBase
,
760 struct PartitionHandle
*ph
763 struct RDBData
*data
;
766 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
| MEMF_CLEAR
);
769 ph
->table
->data
= data
;
770 data
->rdb
.rdb_ID
= AROS_LONG2BE(IDNAME_RIGIDDISK
);
771 data
->rdb
.rdb_SummedLongs
= AROS_LONG2BE(sizeof(struct RigidDiskBlock
)/4);
772 data
->rdb
.rdb_BlockBytes
= AROS_LONG2BE(ph
->dg
.dg_SectorSize
);
773 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
774 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
775 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
776 data
->rdb
.rdb_DriveInit
= (ULONG
)-1;
778 data
->rdb
.rdb_Reserved1
[i
] = (ULONG
)-1;
779 data
->rdb
.rdb_Cylinders
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
);
780 data
->rdb
.rdb_Sectors
= AROS_LONG2BE(ph
->dg
.dg_TrackSectors
);
781 data
->rdb
.rdb_Heads
= AROS_LONG2BE(ph
->dg
.dg_Heads
);
783 data
->rdb
.rdb_Park
= data
->rdb
.rdb_Cylinders
;
784 data
->rdb
.rdb_WritePreComp
= data
->rdb
.rdb_Cylinders
;
785 data
->rdb
.rdb_ReducedWrite
= data
->rdb
.rdb_Cylinders
;
788 data
->rdb
.rdb_RDBBlocksLo
= AROS_LONG2BE(1); /* leave a block for PC */
789 data
->rdb
.rdb_RDBBlocksHi
= AROS_LONG2BE((ph
->dg
.dg_Heads
*ph
->dg
.dg_TrackSectors
*2)-1); /* two cylinders */
790 data
->rdb
.rdb_LoCylinder
= AROS_LONG2BE(2);
791 data
->rdb
.rdb_HiCylinder
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
-1);
792 data
->rdb
.rdb_CylBlocks
= AROS_LONG2BE(ph
->dg
.dg_Heads
*ph
->dg
.dg_TrackSectors
);
793 /* AutoParkSeconds */
797 /* ControllerVendor */
798 /* ControllerProduct */
799 /* ControllerRevision */
802 NEWLIST(&data
->badblocklist
);
803 NEWLIST(&data
->fsheaderlist
);
804 NEWLIST(&ph
->table
->list
);
810 static LONG
PartitionRDBGetPartitionTableAttr(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*tag
)
815 *((LONG
*)tag
->ti_Data
) = (root
->de
.de_Surfaces
* root
->de
.de_BlocksPerTrack
) << 1; /* 2 cylinders */
822 static LONG
PartitionRDBGetPartitionAttr(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tag
)
824 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
829 *((ULONG
*)tag
->ti_Data
) = AROS_LONG2BE(ph
->de
.de_DosType
);
830 PTYPE(tag
->ti_Data
)->id_len
= 4;
834 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_BOOTABLE
) ? TRUE
: FALSE
;
838 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_NOMOUNT
) ? FALSE
: TRUE
;
845 static LONG
PartitionRDBSetPartitionAttrs(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, const struct TagItem
*taglist
)
848 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
850 while ((tag
= NextTagItem(&taglist
)))
856 struct DosEnvec
*de
= (struct DosEnvec
*)tag
->ti_Data
;
858 CopyMem(de
, &ph
->de
, (de
->de_TableSize
+1)*sizeof(IPTR
));
859 CopyHost2BEDosEnvec((SIPTR
*)de
, data
->pb_Environment
, de
->de_TableSize
+1);
864 struct PartitionType
*ptype
=(struct PartitionType
*)tag
->ti_Data
;
867 CopyMem(ptype
->id
, &dt
, 4);
868 ph
->de
.de_DosType
= AROS_BE2LONG(dt
);
869 data
->pb_Environment
[DE_DOSTYPE
] = dt
;
874 STRPTR name
= (STRPTR
)tag
->ti_Data
;
875 ULONG len
= strlen(name
);
877 CopyMem(name
, ph
->ln
.ln_Name
, len
+1);
878 CopyMem(name
, data
->pb_DriveName
+1, len
);
879 data
->pb_DriveName
[len
+1] = 0;
880 data
->pb_DriveName
[0] = len
;
885 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_BOOTABLE
);
887 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_BOOTABLE
);
891 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_NOMOUNT
);
893 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_NOMOUNT
);
900 struct PartitionHandle
*PartitionRDBAddPartition(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*taglist
)
902 if (FindTagItem(PT_DOSENVEC
, taglist
) != NULL
)
904 struct PartitionBlock
*pblock
;
905 struct PartitionHandle
*ph
;
906 struct PartitionHandle
*oph
;
908 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
911 ph
->ln
.ln_Name
= AllocVec(32, MEMF_PUBLIC
| MEMF_CLEAR
);
914 pblock
= AllocMem(sizeof(struct PartitionBlock
), MEMF_PUBLIC
| MEMF_CLEAR
);
920 pblock
->pb_ID
= AROS_LONG2BE(IDNAME_PARTITION
);
921 pblock
->pb_SummedLongs
= AROS_LONG2BE(sizeof(struct PartitionBlock
)/4);
922 PartitionRDBSetPartitionAttrs(PartitionBase
, ph
, taglist
);
923 oph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
924 while (oph
->ln
.ln_Succ
)
926 if (ph
->de
.de_LowCyl
<oph
->de
.de_LowCyl
)
928 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Succ
;
932 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Pred
;
935 Insert(&root
->table
->list
, &ph
->ln
, &oph
->ln
);
938 AddHead(&root
->table
->list
, &ph
->ln
);
941 AddTail(&root
->table
->list
, &ph
->ln
);
942 if (FindTagItem(PT_DOSENVEC
, taglist
) == NULL
)
944 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
945 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
946 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
947 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
948 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
949 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
953 FreeVec(ph
->ln
.ln_Name
);
955 FreeMem(ph
, sizeof(struct PartitionHandle
));
961 void PartitionRDBDeletePartition
963 struct Library
*PartitionBase
,
964 struct PartitionHandle
*ph
968 PartitionRDBFreeHandle(PartitionBase
, ph
);
971 const struct PartitionAttribute PartitionRDBPartitionTableAttrs
[]=
973 {PTT_TYPE
, PLAM_READ
},
974 {PTT_RESERVED
, PLAM_READ
},
978 const struct PartitionAttribute PartitionRDBPartitionAttrs
[]=
980 /* TODO: implement write */
981 {PT_GEOMETRY
, PLAM_READ
},
982 {PT_DOSENVEC
, PLAM_READ
| PLAM_WRITE
},
983 {PT_TYPE
, PLAM_READ
| PLAM_WRITE
},
984 {PT_NAME
, PLAM_READ
| PLAM_WRITE
},
985 {PT_BOOTABLE
, PLAM_READ
| PLAM_WRITE
},
986 {PT_AUTOMOUNT
, PLAM_READ
| PLAM_WRITE
},
990 ULONG PartitionRDBDestroyPartitionTable
992 struct Library
*PartitionBase
,
993 struct PartitionHandle
*root
996 struct RDBData
*data
;
998 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
1001 data
= root
->table
->data
;
1002 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
1003 ((struct RigidDiskBlock
*)root
->buffer
)->rdb_ID
= 0;
1004 if (writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
))
1009 struct Node
*PartitionRDBFindFileSystem(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tags
)
1011 struct RDBData
*data
= (struct RDBData
*)ph
->table
->data
;
1012 struct FileSysNode
*fn
;
1013 struct TagItem
*idTag
= FindTagItem(FST_ID
, tags
);
1014 struct TagItem
*nameTag
= FindTagItem(FST_NAME
, tags
);
1016 for (fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
; fn
->h
.ln
.ln_Succ
;
1017 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
)
1021 if (fn
->fhb
.fhb_ID
!= idTag
->ti_Data
)
1027 if (strcmp(fn
->fhb
.fhb_FileSysName
, (char *)nameTag
->ti_Data
))
1037 BPTR
PartitionRDBLoadFileSystem(struct PartitionBase_intern
*PartitionBase
, struct FileSysHandle
*fn
)
1039 if (PartitionBase
->pb_DOSBase
)
1040 return LoadFS((struct FileSysNode
*)fn
, (struct DosLibrary
*)PartitionBase
->pb_DOSBase
);
1045 static LONG
PartitionRDBGetFileSystemAttr(struct Library
*PartitionBase
, struct FileSysHandle
*fn
, const struct TagItem
*tag
)
1047 struct FileSysEntry
*fse
;
1048 struct FileSysHeaderBlock
*fhb
= &((struct FileSysNode
*)fn
)->fhb
;
1050 switch (tag
->ti_Tag
)
1053 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_DosType
);
1057 *((STRPTR
*)tag
->ti_Data
) = fhb
->fhb_FileSysName
;
1061 fse
= (struct FileSysEntry
*)tag
->ti_Data
;
1063 /* RDB filesystems are not prioritized */
1064 fse
->fse_Node
.ln_Pri
= 0;
1067 * Don't use CopyMem() or something like that.
1068 * First, you need to deal with endianess.
1069 * Second, some things are actually pointers, you need
1070 * to sign-extend them on 64 bits.
1072 fse
->fse_DosType
= AROS_BE2LONG(fhb
->fhb_DosType
);
1073 fse
->fse_Version
= AROS_BE2LONG(fhb
->fhb_Version
);
1074 fse
->fse_PatchFlags
= AROS_BE2LONG(fhb
->fhb_PatchFlags
);
1075 fse
->fse_Type
= AROS_BE2LONG(fhb
->fhb_Type
);
1076 fse
->fse_Task
= AROS_BE2LONG(fhb
->fhb_Task
);
1077 fse
->fse_Lock
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Lock
);
1078 /* Just for convenience. This is expected to be zero. */
1079 fse
->fse_Handler
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Handler
);
1080 fse
->fse_StackSize
= AROS_BE2LONG(fhb
->fhb_StackSize
);
1081 fse
->fse_Priority
= AROS_BE2LONG(fhb
->fhb_Priority
);
1082 fse
->fse_Startup
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Startup
);
1083 /* Skip fse_SegList */
1084 fse
->fse_GlobalVec
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_GlobalVec
);
1088 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_Version
);
1095 const struct PTFunctionTable PartitionRDB
=
1099 PartitionRDBCheckPartitionTable
,
1100 PartitionRDBOpenPartitionTable
,
1101 PartitionRDBClosePartitionTable
,
1102 PartitionRDBWritePartitionTable
,
1103 PartitionRDBCreatePartitionTable
,
1104 PartitionRDBAddPartition
,
1105 PartitionRDBDeletePartition
,
1106 PartitionRDBGetPartitionTableAttr
,
1108 PartitionRDBGetPartitionAttr
,
1109 PartitionRDBSetPartitionAttrs
,
1110 PartitionRDBPartitionTableAttrs
,
1111 PartitionRDBPartitionAttrs
,
1112 PartitionRDBDestroyPartitionTable
,
1113 PartitionRDBFindFileSystem
1116 const struct FSFunctionTable FilesystemRDB
=
1118 PartitionRDBLoadFileSystem
,
1119 PartitionRDBGetFileSystemAttr
,
1120 PartitionRDBFreeFileSystem