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 /* InternalLoadSeg((BPTR)&fakefile, BNULL, FunctionArray, NULL);
155 * with A6 = NULL. Check internalloadseg.c for more information
158 return AROS_CALL4(BPTR
, __AROS_GETVECADDR(DOSBase
, 126),
159 AROS_LCA(BPTR
, (BPTR
)&fakefile
, D0
),
160 AROS_LCA(BPTR
, BNULL
, A0
),
161 AROS_LCA(LONG_FUNC
*, FunctionArray
, A1
),
162 AROS_LCA(LONG
*, NULL
, A2
),
163 struct Library
*, NULL
);
166 static ULONG
calcChkSum(ULONG
*ptr
, ULONG size
)
173 sum
+= AROS_BE2LONG(*ptr
);
179 LONG PartitionRDBCheckPartitionTable
181 struct Library
*PartitionBase
,
182 struct PartitionHandle
*root
186 struct RigidDiskBlock
*rdb
= (struct RigidDiskBlock
*)root
->buffer
;
187 struct PartitionType type
;
188 struct TagItem tags
[] = {{PT_TYPE
, (IPTR
)&type
}, {TAG_DONE
, 0}};
190 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
193 if (root
->root
!= NULL
)
195 GetPartitionAttrs(root
, tags
);
197 (root
->root
->table
->type
!= PHPTT_MBR
&&
198 root
->root
->table
->type
!= PHPTT_EBR
) ||
199 (type
.id
[0] != 0x30 && type
.id
[0] != 0x76)
205 for (i
=0;i
<RDB_LOCATION_LIMIT
; i
++)
207 if (readBlock(PartitionBase
, root
, i
, rdb
) != 0)
209 if (rdb
->rdb_ID
== AROS_BE2LONG(IDNAME_RIGIDDISK
))
212 if (i
!= RDB_LOCATION_LIMIT
)
214 if (calcChkSum((ULONG
*)rdb
, AROS_BE2LONG(rdb
->rdb_SummedLongs
))==0)
220 void CopyBE2HostDosEnvec(LONG
*src
, SIPTR
*dst
, ULONG size
) {
223 while (count
!= size
)
225 *dst
++ = AROS_BE2LONG(*src
);
231 void CopyHost2BEDosEnvec(SIPTR
*src
, ULONG
*dst
, ULONG size
) {
235 while (count
!= size
)
237 *dst
++ = AROS_LONG2BE(*src
);
244 struct BadBlockNode
*PartitionRDBNewBadBlock
246 struct Library
*PartitionBase
,
247 struct PartitionHandle
*root
,
248 struct BadBlockBlock
*buffer
251 struct BadBlockNode
*bn
;
254 (AROS_BE2LONG(buffer
->bbb_ID
) == IDNAME_BADBLOCK
) &&
255 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->bbb_SummedLongs
))==0)
258 bn
= AllocMem(sizeof(struct BadBlockNode
), MEMF_PUBLIC
| MEMF_CLEAR
);
261 CopyMem(buffer
, &bn
->bbb
, sizeof(struct BadBlockBlock
));
268 struct PartitionHandle
*PartitionRDBNewHandle
270 struct Library
*PartitionBase
,
271 struct PartitionHandle
*root
,
272 struct PartitionBlock
*buffer
275 struct PartitionBlock
*pblock
;
276 struct PartitionHandle
*ph
;
279 (AROS_BE2LONG(buffer
->pb_ID
) == IDNAME_PARTITION
) &&
280 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->pb_SummedLongs
))==0)
283 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
286 ph
->ln
.ln_Name
= AllocVec(32, MEMF_PUBLIC
| MEMF_CLEAR
);
289 pblock
= AllocMem(sizeof(struct PartitionBlock
), MEMF_PUBLIC
);
292 CopyMem(buffer
, pblock
, sizeof(struct PartitionBlock
));
296 CopyMem(pblock
->pb_DriveName
+1, ph
->ln
.ln_Name
, pblock
->pb_DriveName
[0]);
297 ph
->ln
.ln_Name
[pblock
->pb_DriveName
[0]]=0;
298 CopyBE2HostDosEnvec(pblock
->pb_Environment
, (SIPTR
*)&ph
->de
, AROS_BE2LONG(pblock
->pb_Environment
[DE_TABLESIZE
])+1);
299 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
300 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
301 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
302 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
303 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
304 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
307 FreeVec(ph
->ln
.ln_Name
);
309 FreeMem(ph
, sizeof(struct PartitionHandle
));
315 struct FileSysNode
*PartitionRDBNewFileSys
317 struct Library
*PartitionBase
,
318 struct PartitionHandle
*root
,
319 struct FileSysHeaderBlock
*buffer
322 struct FileSysNode
*fn
;
325 (AROS_BE2LONG(buffer
->fhb_ID
) == IDNAME_FILESYSHEADER
) &&
326 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->fhb_SummedLongs
))==0)
329 fn
= AllocMem(sizeof(struct FileSysNode
), MEMF_PUBLIC
| MEMF_CLEAR
);
332 CopyMem(buffer
, &fn
->fhb
, sizeof(struct FileSysHeaderBlock
));
334 /* Fill in common part of the handle */
335 fn
->h
.ln
.ln_Name
= fn
->fhb
.fhb_FileSysName
;
337 fn
->h
.handler
= &FilesystemRDB
;
345 static void PartitionRDBFreeFileSystem(struct FileSysHandle
*fsh
)
347 struct FileSysNode
*fn
= (struct FileSysNode
*)fsh
;
350 FreeVec(fn
->filesystem
);
351 FreeMem(fn
, sizeof(struct FileSysNode
));
354 ULONG PartitionRDBCalcFSSize
356 struct Library
*PartitionBase
,
357 struct PartitionHandle
*root
,
358 struct FileSysNode
*fn
,
359 struct LoadSegBlock
*buffer
366 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
367 while (block
!= (ULONG
)-1)
370 if (readBlock(PartitionBase
, root
, block
, buffer
) !=0)
373 (AROS_BE2LONG(buffer
->lsb_ID
) != IDNAME_LOADSEG
) ||
374 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->lsb_SummedLongs
)))
377 block
= AROS_BE2LONG(buffer
->lsb_Next
);
382 void PartitionRDBReadFileSys
384 struct Library
*PartitionBase
,
385 struct PartitionHandle
*root
,
386 struct FileSysNode
*fn
,
387 struct LoadSegBlock
*buffer
393 size
= PartitionRDBCalcFSSize(PartitionBase
, root
, fn
, buffer
);
397 fn
->filesystem
= AllocVec(size
*512, MEMF_PUBLIC
);
401 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
402 while (block
!= (ULONG
)-1)
404 if (readBlock(PartitionBase
, root
, block
, &fn
->filesystem
[size
]) !=0)
406 block
= AROS_BE2LONG(fn
->filesystem
[size
].lsb_Next
);
413 LONG PartitionRDBOpenPartitionTable
415 struct Library
*PartitionBase
,
416 struct PartitionHandle
*root
420 struct RDBData
*data
;
423 buffer
= AllocVec(root
->de
.de_SizeBlock
<< 2, MEMF_PUBLIC
);
426 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
);
429 for (i
=0;i
<RDB_LOCATION_LIMIT
; i
++)
431 if (readBlock(PartitionBase
, root
, i
, buffer
) != 0) {
435 CopyMem(buffer
, &data
->rdb
, sizeof(struct RigidDiskBlock
));
436 if (data
->rdb
.rdb_ID
== AROS_BE2LONG(IDNAME_RIGIDDISK
))
439 if (i
!= RDB_LOCATION_LIMIT
)
444 NEWLIST(&root
->table
->list
);
445 NEWLIST(&data
->badblocklist
);
446 NEWLIST(&data
->fsheaderlist
);
447 root
->table
->data
= data
;
449 /* take the values of the rdb instead of TD_GEOMETRY */
450 root
->dg
.dg_SectorSize
= AROS_BE2LONG(data
->rdb
.rdb_BlockBytes
);
451 root
->dg
.dg_Cylinders
= AROS_BE2LONG(data
->rdb
.rdb_Cylinders
);
452 root
->dg
.dg_TrackSectors
= AROS_BE2LONG(data
->rdb
.rdb_Sectors
);
453 root
->dg
.dg_Heads
= AROS_BE2LONG(data
->rdb
.rdb_Heads
);
455 * Before v3.1 partition.library left rdb_CylBlocks uninitialized, so don't rely on it here.
456 * Otherwise you'll get problem reading drives partitioned with earlier partition.library.
458 root
->dg
.dg_CylSectors
= root
->dg
.dg_TrackSectors
* root
->dg
.dg_Heads
;
459 root
->dg
.dg_TotalSectors
= root
->dg
.dg_CylSectors
* root
->dg
.dg_Cylinders
;
461 /* read bad blocks */
462 block
= AROS_BE2LONG(data
->rdb
.rdb_BadBlockList
);
463 while (block
!= (ULONG
)-1)
465 struct BadBlockNode
*bn
;
467 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
469 bn
= PartitionRDBNewBadBlock(PartitionBase
, root
, (struct BadBlockBlock
*)buffer
);
472 AddTail(&data
->badblocklist
, &bn
->ln
);
473 block
= AROS_BE2LONG(bn
->bbb
.bbb_Next
);
481 /* read partition blocks */
482 block
= AROS_BE2LONG(data
->rdb
.rdb_PartitionList
);
483 while (block
!= (ULONG
)-1)
485 struct PartitionHandle
*ph
;
486 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
488 ph
= PartitionRDBNewHandle(PartitionBase
, root
, (struct PartitionBlock
*)buffer
);
491 AddTail(&root
->table
->list
, &ph
->ln
);
492 block
= AROS_BE2LONG(((struct PartitionBlock
*)ph
->data
)->pb_Next
);
500 /* read filesystem blocks */
501 block
= AROS_BE2LONG(data
->rdb
.rdb_FileSysHeaderList
);
502 while (block
!= (ULONG
)-1)
504 struct FileSysNode
*fn
;
506 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
508 fn
= PartitionRDBNewFileSys(PartitionBase
, root
, (struct FileSysHeaderBlock
*)buffer
);
511 AddTail(&data
->fsheaderlist
, &fn
->h
.ln
);
512 PartitionRDBReadFileSys(PartitionBase
, root
, fn
, (struct LoadSegBlock
*)buffer
);
513 block
= AROS_BE2LONG(fn
->fhb
.fhb_Next
);
524 FreeMem(data
, sizeof(struct RDBData
));
530 void PartitionRDBFreeHandle
532 struct Library
*PartitionBase
,
533 struct PartitionHandle
*ph
536 ClosePartitionTable(ph
);
538 FreeMem(ph
->data
, sizeof(struct PartitionBlock
));
539 FreeVec(ph
->ln
.ln_Name
);
540 FreeMem(ph
, sizeof(struct PartitionHandle
));
543 void PartitionRDBClosePartitionTable
545 struct Library
*PartitionBase
,
546 struct PartitionHandle
*root
549 struct PartitionHandle
*ph
;
550 struct BadBlockNode
*bn
;
551 struct FileSysNode
*fn
;
552 struct RDBData
*data
;
554 while ((ph
= (struct PartitionHandle
*)RemTail(&root
->table
->list
)))
555 PartitionRDBFreeHandle(PartitionBase
, ph
);
556 data
= (struct RDBData
*)root
->table
->data
;
557 while ((bn
= (struct BadBlockNode
*)RemTail(&data
->badblocklist
)))
558 FreeMem(bn
, sizeof(struct BadBlockNode
));
560 while ((fn
= (struct FileSysNode
*)RemTail(&data
->fsheaderlist
)))
562 /* Do not deallocate filesystem handles which are queued for loading */
564 PartitionRDBFreeFileSystem(&fn
->h
);
566 FreeMem(data
, sizeof(struct RDBData
));
569 ULONG PartitionRDBWriteFileSys
571 struct Library
*PartitionBase
,
572 struct PartitionHandle
*root
,
573 struct FileSysNode
*fn
,
582 while (size
!= fn
->fsblocks
)
584 fn
->filesystem
[size
].lsb_Next
= (size
+1) != fn
->fsblocks
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
585 fn
->filesystem
[size
].lsb_ChkSum
= 0;
586 fn
->filesystem
[size
].lsb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&fn
->filesystem
[size
], AROS_LONG2BE(fn
->filesystem
[size
].lsb_SummedLongs
)));
588 if (writeBlock(PartitionBase
, root
, block
++, &fn
->filesystem
[size
]) != 0)
591 kprintf("RDB-write: block=%ld, type=LSEG\n", block
);
600 static LONG
PartitionRDBWritePartitionTable(struct Library
*PartitionBase
, struct PartitionHandle
*root
)
602 struct RDBData
*data
;
603 struct PartitionHandle
*ph
;
604 struct PartitionBlock
*pblock
;
605 struct BadBlockNode
*bn
;
606 struct FileSysNode
*fn
;
609 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
612 data
= root
->table
->data
;
613 block
= data
->rdbblock
+1; /* RDB will be written at the end */
615 memset(root
->buffer
, 0, root
->de
.de_SizeBlock
<< 2);
617 /* write bad blocks */
618 bn
= (struct BadBlockNode
*)data
->badblocklist
.lh_Head
;
620 data
->rdb
.rdb_BadBlockList
= block
;
622 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
623 while (bn
->ln
.ln_Succ
)
625 bn
->bbb
.bbb_Next
= bn
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
626 bn
->bbb
.bbb_ChkSum
= 0;
627 bn
->bbb
.bbb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&bn
->bbb
, AROS_BE2LONG(bn
->bbb
.bbb_SummedLongs
)));
628 CopyMem(&bn
->bbb
, root
->buffer
, sizeof(struct BadBlockBlock
));
630 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
632 kprintf("RDB-write: block=%ld, type=BADB\n", block
);
636 bn
= (struct BadBlockNode
*)bn
->ln
.ln_Succ
;
639 /* write partition blocks */
640 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
642 data
->rdb
.rdb_PartitionList
= AROS_LONG2BE(block
);
644 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
645 while (ph
->ln
.ln_Succ
)
647 pblock
= (struct PartitionBlock
*)ph
->data
;
648 pblock
->pb_Next
= ph
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
649 pblock
->pb_ChkSum
= 0;
650 pblock
->pb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)pblock
, AROS_BE2LONG(pblock
->pb_SummedLongs
)));
651 CopyMem(pblock
, root
->buffer
, sizeof(struct PartitionBlock
));
653 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
655 kprintf("RDB-write: block=%ld, type=PART\n", block
);
658 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
661 /* write filesystem blocks */
662 fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
;
663 if (fn
->h
.ln
.ln_Succ
)
664 data
->rdb
.rdb_FileSysHeaderList
= AROS_LONG2BE(block
);
666 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
667 while (fn
->h
.ln
.ln_Succ
)
670 struct FileSysHeaderBlock
*fsb
;
673 block
++; /* header block will be written later */
674 fn
->fhb
.fhb_SegListBlocks
= AROS_LONG2BE(block
);
675 /* write filesystem LSEG blocks */
676 block
= PartitionRDBWriteFileSys(PartitionBase
, root
, fn
, block
);
677 fn
->fhb
.fhb_Next
= fn
->h
.ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
) : (ULONG
)-1;
678 fn
->fhb
.fhb_ChkSum
= 0;
679 CopyMem(&fn
->fhb
, root
->buffer
, sizeof(struct FileSysHeaderBlock
));
680 fsb
= (struct FileSysHeaderBlock
*)root
->buffer
;
681 fsb
->fhb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)root
->buffer
, AROS_BE2LONG(fn
->fhb
.fhb_SummedLongs
)));
683 writeBlock(PartitionBase
, root
, fshblock
, root
->buffer
);
685 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock
);
687 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
;
689 data
->rdb
.rdb_HighRDSKBlock
= AROS_LONG2BE(block
-1);
690 data
->rdb
.rdb_ChkSum
= 0;
691 data
->rdb
.rdb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&data
->rdb
, AROS_BE2LONG(data
->rdb
.rdb_SummedLongs
)));
692 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
694 writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
);
696 kprintf("RDB-write: block=%ld, type=RDSK\n", data
->rdbblock
);
701 LONG
PartitionRDBCreatePartitionTable(struct Library
*PartitionBase
, struct PartitionHandle
*ph
)
703 struct RDBData
*data
;
706 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
| MEMF_CLEAR
);
709 /* Get number of reserved sectors to place the partition table. By default we reserve 2 cylinders. */
710 ULONG rdbsize
= ph
->dg
.dg_CylSectors
<< 1;
713 * Modern machines love LBA, so container partition may be not cylinder-aligned. In this case we will
714 * likely use flat LBA to describe own placement, with Heads == TrackSectors == 1. This will give us
715 * just two sectors for the RDB, which is horribly small.
716 * Here we detect this situation and increase rdbsize by two until it reaches a minimum of 256 blocks.
717 * This way we keep it aligned to our (virtual) CylSectors value, which allows to set correct LoCylinder
720 while (rdbsize
< 256)
723 ph
->table
->data
= data
;
725 data
->rdb
.rdb_ID
= AROS_LONG2BE(IDNAME_RIGIDDISK
);
726 data
->rdb
.rdb_SummedLongs
= AROS_LONG2BE(sizeof(struct RigidDiskBlock
)/4);
727 data
->rdb
.rdb_BlockBytes
= AROS_LONG2BE(ph
->dg
.dg_SectorSize
);
728 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
729 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
730 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
731 data
->rdb
.rdb_DriveInit
= (ULONG
)-1;
732 for (i
= 0; i
< 6; i
++)
733 data
->rdb
.rdb_Reserved1
[i
] = (ULONG
)-1;
734 data
->rdb
.rdb_Cylinders
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
);
735 data
->rdb
.rdb_Sectors
= AROS_LONG2BE(ph
->dg
.dg_TrackSectors
);
736 data
->rdb
.rdb_Heads
= AROS_LONG2BE(ph
->dg
.dg_Heads
);
738 data
->rdb
.rdb_Park
= data
->rdb
.rdb_Cylinders
;
739 data
->rdb
.rdb_WritePreComp
= data
->rdb
.rdb_Cylinders
;
740 data
->rdb
.rdb_ReducedWrite
= data
->rdb
.rdb_Cylinders
;
742 data
->rdb
.rdb_RDBBlocksLo
= AROS_LONG2BE(1); /* leave a block for PC */
743 data
->rdb
.rdb_RDBBlocksHi
= AROS_LONG2BE(rdbsize
- 1);
744 data
->rdb
.rdb_LoCylinder
= AROS_LONG2BE(rdbsize
/ ph
->dg
.dg_CylSectors
);
745 data
->rdb
.rdb_HiCylinder
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
-1);
746 data
->rdb
.rdb_CylBlocks
= AROS_LONG2BE(ph
->dg
.dg_CylSectors
);
747 /* AutoParkSeconds */
751 /* ControllerVendor */
752 /* ControllerProduct */
753 /* ControllerRevision */
756 NEWLIST(&data
->badblocklist
);
757 NEWLIST(&data
->fsheaderlist
);
758 NEWLIST(&ph
->table
->list
);
764 static LONG
PartitionRDBGetPartitionTableAttr(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*tag
)
766 struct RDBData
*data
= root
->table
->data
;
771 *((LONG
*)tag
->ti_Data
) = AROS_BE2LONG(data
->rdb
.rdb_RDBBlocksHi
) + 1; /* Reserved blocks count starts from 0, so ignore rdb_RDBBlocksLo */
778 static LONG
PartitionRDBGetPartitionAttr(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tag
)
780 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
785 *((ULONG
*)tag
->ti_Data
) = AROS_LONG2BE(ph
->de
.de_DosType
);
786 PTYPE(tag
->ti_Data
)->id_len
= 4;
790 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_BOOTABLE
) ? TRUE
: FALSE
;
794 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_NOMOUNT
) ? FALSE
: TRUE
;
801 static LONG
PartitionRDBSetPartitionAttrs(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, const struct TagItem
*taglist
)
804 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
806 while ((tag
= NextTagItem((struct TagItem
**)&taglist
)))
812 struct DosEnvec
*de
= (struct DosEnvec
*)tag
->ti_Data
;
814 CopyMem(de
, &ph
->de
, (de
->de_TableSize
+1)*sizeof(IPTR
));
815 CopyHost2BEDosEnvec((SIPTR
*)de
, data
->pb_Environment
, de
->de_TableSize
+1);
820 struct PartitionType
*ptype
=(struct PartitionType
*)tag
->ti_Data
;
823 CopyMem(ptype
->id
, &dt
, 4);
824 ph
->de
.de_DosType
= AROS_BE2LONG(dt
);
825 data
->pb_Environment
[DE_DOSTYPE
] = dt
;
830 STRPTR name
= (STRPTR
)tag
->ti_Data
;
831 ULONG len
= strlen(name
);
833 CopyMem(name
, ph
->ln
.ln_Name
, len
+1);
834 CopyMem(name
, data
->pb_DriveName
+1, len
);
835 data
->pb_DriveName
[len
+1] = 0;
836 data
->pb_DriveName
[0] = len
;
841 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_BOOTABLE
);
843 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_BOOTABLE
);
847 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_NOMOUNT
);
849 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_NOMOUNT
);
856 struct PartitionHandle
*PartitionRDBAddPartition(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*taglist
)
858 if (FindTagItem(PT_DOSENVEC
, taglist
) != NULL
)
860 struct PartitionBlock
*pblock
;
861 struct PartitionHandle
*ph
;
862 struct PartitionHandle
*oph
;
864 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
867 ph
->ln
.ln_Name
= AllocVec(32, MEMF_PUBLIC
| MEMF_CLEAR
);
870 pblock
= AllocMem(sizeof(struct PartitionBlock
), MEMF_PUBLIC
| MEMF_CLEAR
);
876 pblock
->pb_ID
= AROS_LONG2BE(IDNAME_PARTITION
);
877 pblock
->pb_SummedLongs
= AROS_LONG2BE(sizeof(struct PartitionBlock
)/4);
878 PartitionRDBSetPartitionAttrs(PartitionBase
, ph
, taglist
);
879 oph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
880 while (oph
->ln
.ln_Succ
)
882 if (ph
->de
.de_LowCyl
<oph
->de
.de_LowCyl
)
884 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Succ
;
888 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Pred
;
891 Insert(&root
->table
->list
, &ph
->ln
, &oph
->ln
);
894 AddHead(&root
->table
->list
, &ph
->ln
);
897 AddTail(&root
->table
->list
, &ph
->ln
);
898 if (FindTagItem(PT_DOSENVEC
, taglist
) == NULL
)
900 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
901 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
902 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
903 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
904 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
905 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
909 FreeVec(ph
->ln
.ln_Name
);
911 FreeMem(ph
, sizeof(struct PartitionHandle
));
917 void PartitionRDBDeletePartition
919 struct Library
*PartitionBase
,
920 struct PartitionHandle
*ph
924 PartitionRDBFreeHandle(PartitionBase
, ph
);
927 const struct PartitionAttribute PartitionRDBPartitionTableAttrs
[]=
929 {PTT_TYPE
, PLAM_READ
},
930 {PTT_RESERVED
, PLAM_READ
},
934 const struct PartitionAttribute PartitionRDBPartitionAttrs
[]=
936 /* TODO: implement write */
937 {PT_GEOMETRY
, PLAM_READ
},
938 {PT_DOSENVEC
, PLAM_READ
| PLAM_WRITE
},
939 {PT_TYPE
, PLAM_READ
| PLAM_WRITE
},
940 {PT_NAME
, PLAM_READ
| PLAM_WRITE
},
941 {PT_BOOTABLE
, PLAM_READ
| PLAM_WRITE
},
942 {PT_AUTOMOUNT
, PLAM_READ
| PLAM_WRITE
},
946 ULONG PartitionRDBDestroyPartitionTable
948 struct Library
*PartitionBase
,
949 struct PartitionHandle
*root
952 struct RDBData
*data
;
953 struct RigidDiskBlock
*rdb
;
955 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
958 data
= root
->table
->data
;
959 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
960 rdb
= (struct RigidDiskBlock
*)root
->buffer
;
962 if (writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
))
967 struct Node
*PartitionRDBFindFileSystem(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tags
)
969 struct RDBData
*data
= (struct RDBData
*)ph
->table
->data
;
970 struct FileSysNode
*fn
;
971 struct TagItem
*idTag
= FindTagItem(FST_ID
, tags
);
972 struct TagItem
*nameTag
= FindTagItem(FST_NAME
, tags
);
974 for (fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
; fn
->h
.ln
.ln_Succ
;
975 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
)
979 if (fn
->fhb
.fhb_DosType
!= idTag
->ti_Data
)
985 if (strcmp(fn
->fhb
.fhb_FileSysName
, (char *)nameTag
->ti_Data
))
995 BPTR
PartitionRDBLoadFileSystem(struct PartitionBase_intern
*PartitionBase
, struct FileSysHandle
*fn
)
997 if (PartitionBase
->pb_DOSBase
)
998 return LoadFS((struct FileSysNode
*)fn
, (struct DosLibrary
*)PartitionBase
->pb_DOSBase
);
1003 static LONG
PartitionRDBGetFileSystemAttr(struct Library
*PartitionBase
, struct FileSysHandle
*fn
, const struct TagItem
*tag
)
1005 struct FileSysEntry
*fse
;
1006 struct FileSysHeaderBlock
*fhb
= &((struct FileSysNode
*)fn
)->fhb
;
1008 switch (tag
->ti_Tag
)
1011 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_DosType
);
1015 *((STRPTR
*)tag
->ti_Data
) = fhb
->fhb_FileSysName
;
1019 fse
= (struct FileSysEntry
*)tag
->ti_Data
;
1021 /* RDB filesystems are not prioritized */
1022 fse
->fse_Node
.ln_Pri
= 0;
1025 * Don't use CopyMem() or something like that.
1026 * First, you need to deal with endianess.
1027 * Second, some things are actually pointers, you need
1028 * to sign-extend them on 64 bits.
1030 fse
->fse_DosType
= AROS_BE2LONG(fhb
->fhb_DosType
);
1031 fse
->fse_Version
= AROS_BE2LONG(fhb
->fhb_Version
);
1032 fse
->fse_PatchFlags
= AROS_BE2LONG(fhb
->fhb_PatchFlags
);
1033 fse
->fse_Type
= AROS_BE2LONG(fhb
->fhb_Type
);
1034 fse
->fse_Task
= AROS_BE2LONG(fhb
->fhb_Task
);
1035 fse
->fse_Lock
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Lock
);
1036 /* Just for convenience. This is expected to be zero. */
1037 fse
->fse_Handler
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Handler
);
1038 fse
->fse_StackSize
= AROS_BE2LONG(fhb
->fhb_StackSize
);
1039 fse
->fse_Priority
= AROS_BE2LONG(fhb
->fhb_Priority
);
1040 fse
->fse_Startup
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Startup
);
1041 /* Skip fse_SegList */
1042 fse
->fse_GlobalVec
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_GlobalVec
);
1046 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_Version
);
1053 const struct PTFunctionTable PartitionRDB
=
1057 PartitionRDBCheckPartitionTable
,
1058 PartitionRDBOpenPartitionTable
,
1059 PartitionRDBClosePartitionTable
,
1060 PartitionRDBWritePartitionTable
,
1061 PartitionRDBCreatePartitionTable
,
1062 PartitionRDBAddPartition
,
1063 PartitionRDBDeletePartition
,
1064 PartitionRDBGetPartitionTableAttr
,
1066 PartitionRDBGetPartitionAttr
,
1067 PartitionRDBSetPartitionAttrs
,
1068 PartitionRDBPartitionTableAttrs
,
1069 PartitionRDBPartitionAttrs
,
1070 PartitionRDBDestroyPartitionTable
,
1071 PartitionRDBFindFileSystem
1074 const struct FSFunctionTable FilesystemRDB
=
1076 PartitionRDBLoadFileSystem
,
1077 PartitionRDBGetFileSystemAttr
,
1078 PartitionRDBFreeFileSystem