2 Copyright © 1995-2013, 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
;
349 FreeVec(fn
->filesystem
);
350 FreeMem(fn
, sizeof(struct FileSysNode
));
353 ULONG PartitionRDBCalcFSSize
355 struct Library
*PartitionBase
,
356 struct PartitionHandle
*root
,
357 struct FileSysNode
*fn
,
358 struct LoadSegBlock
*buffer
365 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
366 while (block
!= (ULONG
)-1)
369 if (readBlock(PartitionBase
, root
, block
, buffer
) !=0)
372 (AROS_BE2LONG(buffer
->lsb_ID
) != IDNAME_LOADSEG
) ||
373 (calcChkSum((ULONG
*)buffer
, AROS_BE2LONG(buffer
->lsb_SummedLongs
)))
376 block
= AROS_BE2LONG(buffer
->lsb_Next
);
381 void PartitionRDBReadFileSys
383 struct Library
*PartitionBase
,
384 struct PartitionHandle
*root
,
385 struct FileSysNode
*fn
,
386 struct LoadSegBlock
*buffer
392 size
= PartitionRDBCalcFSSize(PartitionBase
, root
, fn
, buffer
);
396 fn
->filesystem
= AllocVec(size
*512, MEMF_PUBLIC
);
400 block
= AROS_BE2LONG(fn
->fhb
.fhb_SegListBlocks
);
401 while (block
!= (ULONG
)-1)
403 if (readBlock(PartitionBase
, root
, block
, &fn
->filesystem
[size
]) !=0)
405 block
= AROS_BE2LONG(fn
->filesystem
[size
].lsb_Next
);
412 LONG PartitionRDBOpenPartitionTable
414 struct Library
*PartitionBase
,
415 struct PartitionHandle
*root
419 struct RDBData
*data
;
422 buffer
= AllocVec(root
->de
.de_SizeBlock
<< 2, MEMF_PUBLIC
);
425 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
);
428 for (i
=0;i
<RDB_LOCATION_LIMIT
; i
++)
430 if (readBlock(PartitionBase
, root
, i
, buffer
) != 0) {
434 CopyMem(buffer
, &data
->rdb
, sizeof(struct RigidDiskBlock
));
435 if (data
->rdb
.rdb_ID
== AROS_BE2LONG(IDNAME_RIGIDDISK
))
438 if (i
!= RDB_LOCATION_LIMIT
)
443 NEWLIST(&root
->table
->list
);
444 NEWLIST(&data
->badblocklist
);
445 NEWLIST(&data
->fsheaderlist
);
446 root
->table
->data
= data
;
448 /* take the values of the rdb instead of TD_GEOMETRY */
449 root
->dg
.dg_SectorSize
= AROS_BE2LONG(data
->rdb
.rdb_BlockBytes
);
450 root
->dg
.dg_Cylinders
= AROS_BE2LONG(data
->rdb
.rdb_Cylinders
);
451 root
->dg
.dg_TrackSectors
= AROS_BE2LONG(data
->rdb
.rdb_Sectors
);
452 root
->dg
.dg_Heads
= AROS_BE2LONG(data
->rdb
.rdb_Heads
);
454 * Before v3.1 partition.library left rdb_CylBlocks uninitialized, so don't rely on it here.
455 * Otherwise you'll get problem reading drives partitioned with earlier partition.library.
457 root
->dg
.dg_CylSectors
= root
->dg
.dg_TrackSectors
* root
->dg
.dg_Heads
;
458 root
->dg
.dg_TotalSectors
= root
->dg
.dg_CylSectors
* root
->dg
.dg_Cylinders
;
460 /* read bad blocks */
461 block
= AROS_BE2LONG(data
->rdb
.rdb_BadBlockList
);
462 while (block
!= (ULONG
)-1)
464 struct BadBlockNode
*bn
;
466 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
468 bn
= PartitionRDBNewBadBlock(PartitionBase
, root
, (struct BadBlockBlock
*)buffer
);
471 AddTail(&data
->badblocklist
, &bn
->ln
);
472 block
= AROS_BE2LONG(bn
->bbb
.bbb_Next
);
480 /* read partition blocks */
481 block
= AROS_BE2LONG(data
->rdb
.rdb_PartitionList
);
482 while (block
!= (ULONG
)-1)
484 struct PartitionHandle
*ph
;
485 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
487 ph
= PartitionRDBNewHandle(PartitionBase
, root
, (struct PartitionBlock
*)buffer
);
490 AddTail(&root
->table
->list
, &ph
->ln
);
491 block
= AROS_BE2LONG(((struct PartitionBlock
*)ph
->data
)->pb_Next
);
499 /* read filesystem blocks */
500 block
= AROS_BE2LONG(data
->rdb
.rdb_FileSysHeaderList
);
501 while (block
!= (ULONG
)-1)
503 struct FileSysNode
*fn
;
505 if (readBlock(PartitionBase
, root
, block
, buffer
)==0)
507 fn
= PartitionRDBNewFileSys(PartitionBase
, root
, (struct FileSysHeaderBlock
*)buffer
);
510 AddTail(&data
->fsheaderlist
, &fn
->h
.ln
);
511 PartitionRDBReadFileSys(PartitionBase
, root
, fn
, (struct LoadSegBlock
*)buffer
);
512 block
= AROS_BE2LONG(fn
->fhb
.fhb_Next
);
523 FreeMem(data
, sizeof(struct RDBData
));
529 void PartitionRDBFreeHandle
531 struct Library
*PartitionBase
,
532 struct PartitionHandle
*ph
535 ClosePartitionTable(ph
);
537 FreeMem(ph
->data
, sizeof(struct PartitionBlock
));
538 FreeVec(ph
->ln
.ln_Name
);
539 FreeMem(ph
, sizeof(struct PartitionHandle
));
542 void PartitionRDBClosePartitionTable
544 struct Library
*PartitionBase
,
545 struct PartitionHandle
*root
548 struct PartitionHandle
*ph
;
549 struct BadBlockNode
*bn
;
550 struct FileSysNode
*fn
;
551 struct RDBData
*data
;
553 while ((ph
= (struct PartitionHandle
*)RemTail(&root
->table
->list
)))
554 PartitionRDBFreeHandle(PartitionBase
, ph
);
555 data
= (struct RDBData
*)root
->table
->data
;
556 while ((bn
= (struct BadBlockNode
*)RemTail(&data
->badblocklist
)))
557 FreeMem(bn
, sizeof(struct BadBlockNode
));
559 while ((fn
= (struct FileSysNode
*)RemTail(&data
->fsheaderlist
)))
561 /* Do not deallocate filesystem handles which are queued for loading */
563 PartitionRDBFreeFileSystem(&fn
->h
);
565 FreeMem(data
, sizeof(struct RDBData
));
568 ULONG PartitionRDBWriteFileSys
570 struct Library
*PartitionBase
,
571 struct PartitionHandle
*root
,
572 struct FileSysNode
*fn
,
581 while (size
!= fn
->fsblocks
)
583 fn
->filesystem
[size
].lsb_Next
= (size
+1) != fn
->fsblocks
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
584 fn
->filesystem
[size
].lsb_ChkSum
= 0;
585 fn
->filesystem
[size
].lsb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&fn
->filesystem
[size
], AROS_LONG2BE(fn
->filesystem
[size
].lsb_SummedLongs
)));
587 if (writeBlock(PartitionBase
, root
, block
++, &fn
->filesystem
[size
]) != 0)
590 kprintf("RDB-write: block=%ld, type=LSEG\n", block
);
599 static LONG
PartitionRDBWritePartitionTable(struct Library
*PartitionBase
, struct PartitionHandle
*root
)
601 struct RDBData
*data
;
602 struct PartitionHandle
*ph
;
603 struct PartitionBlock
*pblock
;
604 struct BadBlockNode
*bn
;
605 struct FileSysNode
*fn
;
608 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
611 data
= root
->table
->data
;
612 block
= data
->rdbblock
+1; /* RDB will be written at the end */
614 memset(root
->buffer
, 0, root
->de
.de_SizeBlock
<< 2);
616 /* write bad blocks */
617 bn
= (struct BadBlockNode
*)data
->badblocklist
.lh_Head
;
619 data
->rdb
.rdb_BadBlockList
= block
;
621 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
622 while (bn
->ln
.ln_Succ
)
624 bn
->bbb
.bbb_Next
= bn
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
625 bn
->bbb
.bbb_ChkSum
= 0;
626 bn
->bbb
.bbb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&bn
->bbb
, AROS_BE2LONG(bn
->bbb
.bbb_SummedLongs
)));
627 CopyMem(&bn
->bbb
, root
->buffer
, sizeof(struct BadBlockBlock
));
629 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
631 kprintf("RDB-write: block=%ld, type=BADB\n", block
);
635 bn
= (struct BadBlockNode
*)bn
->ln
.ln_Succ
;
638 /* write partition blocks */
639 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
641 data
->rdb
.rdb_PartitionList
= AROS_LONG2BE(block
);
643 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
644 while (ph
->ln
.ln_Succ
)
646 pblock
= (struct PartitionBlock
*)ph
->data
;
647 pblock
->pb_Next
= ph
->ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
+1) : (ULONG
)-1;
648 pblock
->pb_ChkSum
= 0;
649 pblock
->pb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)pblock
, AROS_BE2LONG(pblock
->pb_SummedLongs
)));
650 CopyMem(pblock
, root
->buffer
, sizeof(struct PartitionBlock
));
652 writeBlock(PartitionBase
, root
, block
++, root
->buffer
);
654 kprintf("RDB-write: block=%ld, type=PART\n", block
);
657 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
660 /* write filesystem blocks */
661 fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
;
662 if (fn
->h
.ln
.ln_Succ
)
663 data
->rdb
.rdb_FileSysHeaderList
= AROS_LONG2BE(block
);
665 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
666 while (fn
->h
.ln
.ln_Succ
)
669 struct FileSysHeaderBlock
*fsb
;
672 block
++; /* header block will be written later */
673 fn
->fhb
.fhb_SegListBlocks
= AROS_LONG2BE(block
);
674 /* write filesystem LSEG blocks */
675 block
= PartitionRDBWriteFileSys(PartitionBase
, root
, fn
, block
);
676 fn
->fhb
.fhb_Next
= fn
->h
.ln
.ln_Succ
->ln_Succ
? AROS_LONG2BE(block
) : (ULONG
)-1;
677 fn
->fhb
.fhb_ChkSum
= 0;
678 CopyMem(&fn
->fhb
, root
->buffer
, sizeof(struct FileSysHeaderBlock
));
679 fsb
= (struct FileSysHeaderBlock
*)root
->buffer
;
680 fsb
->fhb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)root
->buffer
, AROS_BE2LONG(fn
->fhb
.fhb_SummedLongs
)));
682 writeBlock(PartitionBase
, root
, fshblock
, root
->buffer
);
684 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock
);
686 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
;
688 data
->rdb
.rdb_HighRDSKBlock
= AROS_LONG2BE(block
-1);
689 data
->rdb
.rdb_ChkSum
= 0;
690 data
->rdb
.rdb_ChkSum
= AROS_LONG2BE(0-calcChkSum((ULONG
*)&data
->rdb
, AROS_BE2LONG(data
->rdb
.rdb_SummedLongs
)));
691 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
693 writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
);
695 kprintf("RDB-write: block=%ld, type=RDSK\n", data
->rdbblock
);
700 LONG
PartitionRDBCreatePartitionTable(struct Library
*PartitionBase
, struct PartitionHandle
*ph
)
702 struct RDBData
*data
;
705 data
= AllocMem(sizeof(struct RDBData
), MEMF_PUBLIC
| MEMF_CLEAR
);
708 /* Get number of reserved sectors to place the partition table. By default we reserve 2 cylinders. */
709 ULONG rdbsize
= ph
->dg
.dg_CylSectors
<< 1;
712 * Modern machines love LBA, so container partition may be not cylinder-aligned. In this case we will
713 * likely use flat LBA to describe own placement, with Heads == TrackSectors == 1. This will give us
714 * just two sectors for the RDB, which is horribly small.
715 * Here we detect this situation and increase rdbsize by two until it reaches a minimum of 256 blocks.
716 * This way we keep it aligned to our (virtual) CylSectors value, which allows to set correct LoCylinder
719 while (rdbsize
< 256)
722 ph
->table
->data
= data
;
724 data
->rdb
.rdb_ID
= AROS_LONG2BE(IDNAME_RIGIDDISK
);
725 data
->rdb
.rdb_SummedLongs
= AROS_LONG2BE(sizeof(struct RigidDiskBlock
)/4);
726 data
->rdb
.rdb_BlockBytes
= AROS_LONG2BE(ph
->dg
.dg_SectorSize
);
727 data
->rdb
.rdb_BadBlockList
= (ULONG
)-1;
728 data
->rdb
.rdb_PartitionList
= (ULONG
)-1;
729 data
->rdb
.rdb_FileSysHeaderList
= (ULONG
)-1;
730 data
->rdb
.rdb_DriveInit
= (ULONG
)-1;
731 for (i
= 0; i
< 6; i
++)
732 data
->rdb
.rdb_Reserved1
[i
] = (ULONG
)-1;
733 data
->rdb
.rdb_Cylinders
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
);
734 data
->rdb
.rdb_Sectors
= AROS_LONG2BE(ph
->dg
.dg_TrackSectors
);
735 data
->rdb
.rdb_Heads
= AROS_LONG2BE(ph
->dg
.dg_Heads
);
737 data
->rdb
.rdb_Park
= data
->rdb
.rdb_Cylinders
;
738 data
->rdb
.rdb_WritePreComp
= data
->rdb
.rdb_Cylinders
;
739 data
->rdb
.rdb_ReducedWrite
= data
->rdb
.rdb_Cylinders
;
741 data
->rdb
.rdb_RDBBlocksLo
= AROS_LONG2BE(1); /* leave a block for PC */
742 data
->rdb
.rdb_RDBBlocksHi
= AROS_LONG2BE(rdbsize
- 1);
743 data
->rdb
.rdb_LoCylinder
= AROS_LONG2BE(rdbsize
/ ph
->dg
.dg_CylSectors
);
744 data
->rdb
.rdb_HiCylinder
= AROS_LONG2BE(ph
->dg
.dg_Cylinders
-1);
745 data
->rdb
.rdb_CylBlocks
= AROS_LONG2BE(ph
->dg
.dg_CylSectors
);
746 /* AutoParkSeconds */
750 /* ControllerVendor */
751 /* ControllerProduct */
752 /* ControllerRevision */
755 NEWLIST(&data
->badblocklist
);
756 NEWLIST(&data
->fsheaderlist
);
757 NEWLIST(&ph
->table
->list
);
763 static LONG
PartitionRDBGetPartitionTableAttr(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*tag
)
765 struct RDBData
*data
= root
->table
->data
;
770 *((LONG
*)tag
->ti_Data
) = AROS_BE2LONG(data
->rdb
.rdb_RDBBlocksHi
) + 1; /* Reserved blocks count starts from 0, so ignore rdb_RDBBlocksLo */
777 static LONG
PartitionRDBGetPartitionAttr(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tag
)
779 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
784 *((ULONG
*)tag
->ti_Data
) = AROS_LONG2BE(ph
->de
.de_DosType
);
785 PTYPE(tag
->ti_Data
)->id_len
= 4;
789 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_BOOTABLE
) ? TRUE
: FALSE
;
793 *((LONG
*)tag
->ti_Data
) = (AROS_BE2LONG(data
->pb_Flags
) & PBFF_NOMOUNT
) ? FALSE
: TRUE
;
800 static LONG
PartitionRDBSetPartitionAttrs(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, const struct TagItem
*taglist
)
803 struct PartitionBlock
*data
= (struct PartitionBlock
*)ph
->data
;
805 while ((tag
= NextTagItem((struct TagItem
**)&taglist
)))
811 struct DosEnvec
*de
= (struct DosEnvec
*)tag
->ti_Data
;
813 CopyMem(de
, &ph
->de
, (de
->de_TableSize
+1)*sizeof(IPTR
));
814 CopyHost2BEDosEnvec((SIPTR
*)de
, data
->pb_Environment
, de
->de_TableSize
+1);
819 struct PartitionType
*ptype
=(struct PartitionType
*)tag
->ti_Data
;
822 CopyMem(ptype
->id
, &dt
, 4);
823 ph
->de
.de_DosType
= AROS_BE2LONG(dt
);
824 data
->pb_Environment
[DE_DOSTYPE
] = dt
;
829 STRPTR name
= (STRPTR
)tag
->ti_Data
;
830 ULONG len
= strlen(name
);
832 CopyMem(name
, ph
->ln
.ln_Name
, len
+1);
833 CopyMem(name
, data
->pb_DriveName
+1, len
);
834 data
->pb_DriveName
[len
+1] = 0;
835 data
->pb_DriveName
[0] = len
;
840 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_BOOTABLE
);
842 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_BOOTABLE
);
846 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) & ~PBFF_NOMOUNT
);
848 data
->pb_Flags
= AROS_LONG2BE(AROS_BE2LONG(data
->pb_Flags
) | PBFF_NOMOUNT
);
855 struct PartitionHandle
*PartitionRDBAddPartition(struct Library
*PartitionBase
, struct PartitionHandle
*root
, struct TagItem
*taglist
)
857 if (FindTagItem(PT_DOSENVEC
, taglist
) != NULL
)
859 struct PartitionBlock
*pblock
;
860 struct PartitionHandle
*ph
;
861 struct PartitionHandle
*oph
;
863 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
866 ph
->ln
.ln_Name
= AllocVec(32, MEMF_PUBLIC
| MEMF_CLEAR
);
869 pblock
= AllocMem(sizeof(struct PartitionBlock
), MEMF_PUBLIC
| MEMF_CLEAR
);
875 pblock
->pb_ID
= AROS_LONG2BE(IDNAME_PARTITION
);
876 pblock
->pb_SummedLongs
= AROS_LONG2BE(sizeof(struct PartitionBlock
)/4);
877 PartitionRDBSetPartitionAttrs(PartitionBase
, ph
, taglist
);
878 oph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
879 while (oph
->ln
.ln_Succ
)
881 if (ph
->de
.de_LowCyl
<oph
->de
.de_LowCyl
)
883 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Succ
;
887 oph
= (struct PartitionHandle
*)oph
->ln
.ln_Pred
;
890 Insert(&root
->table
->list
, &ph
->ln
, &oph
->ln
);
893 AddHead(&root
->table
->list
, &ph
->ln
);
896 AddTail(&root
->table
->list
, &ph
->ln
);
897 if (FindTagItem(PT_DOSENVEC
, taglist
) == NULL
)
899 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
900 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
901 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
902 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
903 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
904 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
908 FreeVec(ph
->ln
.ln_Name
);
910 FreeMem(ph
, sizeof(struct PartitionHandle
));
916 void PartitionRDBDeletePartition
918 struct Library
*PartitionBase
,
919 struct PartitionHandle
*ph
923 PartitionRDBFreeHandle(PartitionBase
, ph
);
926 const struct PartitionAttribute PartitionRDBPartitionTableAttrs
[]=
928 {PTT_TYPE
, PLAM_READ
},
929 {PTT_RESERVED
, PLAM_READ
},
933 const struct PartitionAttribute PartitionRDBPartitionAttrs
[]=
935 /* TODO: implement write */
936 {PT_GEOMETRY
, PLAM_READ
},
937 {PT_DOSENVEC
, PLAM_READ
| PLAM_WRITE
},
938 {PT_TYPE
, PLAM_READ
| PLAM_WRITE
},
939 {PT_NAME
, PLAM_READ
| PLAM_WRITE
},
940 {PT_BOOTABLE
, PLAM_READ
| PLAM_WRITE
},
941 {PT_AUTOMOUNT
, PLAM_READ
| PLAM_WRITE
},
945 ULONG PartitionRDBDestroyPartitionTable
947 struct Library
*PartitionBase
,
948 struct PartitionHandle
*root
951 struct RDBData
*data
;
952 struct RigidDiskBlock
*rdb
;
954 if (sizeof(root
->buffer
) < (root
->de
.de_SizeBlock
<< 2))
957 data
= root
->table
->data
;
958 CopyMem(&data
->rdb
, root
->buffer
, sizeof(struct RigidDiskBlock
));
959 rdb
= (struct RigidDiskBlock
*)root
->buffer
;
961 if (writeBlock(PartitionBase
, root
, data
->rdbblock
, root
->buffer
))
966 struct Node
*PartitionRDBFindFileSystem(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, struct TagItem
*tags
)
968 struct RDBData
*data
= (struct RDBData
*)ph
->table
->data
;
969 struct FileSysNode
*fn
;
970 struct TagItem
*idTag
= FindTagItem(FST_ID
, tags
);
971 struct TagItem
*nameTag
= FindTagItem(FST_NAME
, tags
);
973 for (fn
= (struct FileSysNode
*)data
->fsheaderlist
.lh_Head
; fn
->h
.ln
.ln_Succ
;
974 fn
= (struct FileSysNode
*)fn
->h
.ln
.ln_Succ
)
978 if (fn
->fhb
.fhb_DosType
!= idTag
->ti_Data
)
984 if (strcmp(fn
->fhb
.fhb_FileSysName
, (char *)nameTag
->ti_Data
))
994 BPTR
PartitionRDBLoadFileSystem(struct PartitionBase_intern
*PartitionBase
, struct FileSysHandle
*fn
)
996 if (PartitionBase
->pb_DOSBase
)
997 return LoadFS((struct FileSysNode
*)fn
, (struct DosLibrary
*)PartitionBase
->pb_DOSBase
);
1002 static LONG
PartitionRDBGetFileSystemAttr(struct Library
*PartitionBase
, struct FileSysHandle
*fn
, const struct TagItem
*tag
)
1004 struct FileSysEntry
*fse
;
1005 struct FileSysHeaderBlock
*fhb
= &((struct FileSysNode
*)fn
)->fhb
;
1007 switch (tag
->ti_Tag
)
1010 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_DosType
);
1014 *((STRPTR
*)tag
->ti_Data
) = fhb
->fhb_FileSysName
;
1018 fse
= (struct FileSysEntry
*)tag
->ti_Data
;
1020 /* RDB filesystems are not prioritized */
1021 fse
->fse_Node
.ln_Pri
= 0;
1024 * Don't use CopyMem() or something like that.
1025 * First, you need to deal with endianess.
1026 * Second, some things are actually pointers, you need
1027 * to sign-extend them on 64 bits.
1029 fse
->fse_DosType
= AROS_BE2LONG(fhb
->fhb_DosType
);
1030 fse
->fse_Version
= AROS_BE2LONG(fhb
->fhb_Version
);
1031 fse
->fse_PatchFlags
= AROS_BE2LONG(fhb
->fhb_PatchFlags
);
1032 fse
->fse_Type
= AROS_BE2LONG(fhb
->fhb_Type
);
1033 fse
->fse_Task
= AROS_BE2LONG(fhb
->fhb_Task
);
1034 fse
->fse_Lock
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Lock
);
1035 /* Just for convenience. This is expected to be zero. */
1036 fse
->fse_Handler
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Handler
);
1037 fse
->fse_StackSize
= AROS_BE2LONG(fhb
->fhb_StackSize
);
1038 fse
->fse_Priority
= AROS_BE2LONG(fhb
->fhb_Priority
);
1039 fse
->fse_Startup
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_Startup
);
1040 /* Skip fse_SegList */
1041 fse
->fse_GlobalVec
= (BPTR
)(SIPTR
)AROS_BE2LONG(fhb
->fhb_GlobalVec
);
1045 *((ULONG
*)tag
->ti_Data
) = AROS_BE2LONG(fhb
->fhb_Version
);
1052 const struct PTFunctionTable PartitionRDB
=
1056 PartitionRDBCheckPartitionTable
,
1057 PartitionRDBOpenPartitionTable
,
1058 PartitionRDBClosePartitionTable
,
1059 PartitionRDBWritePartitionTable
,
1060 PartitionRDBCreatePartitionTable
,
1061 PartitionRDBAddPartition
,
1062 PartitionRDBDeletePartition
,
1063 PartitionRDBGetPartitionTableAttr
,
1065 PartitionRDBGetPartitionAttr
,
1066 PartitionRDBSetPartitionAttrs
,
1067 PartitionRDBPartitionTableAttrs
,
1068 PartitionRDBPartitionAttrs
,
1069 PartitionRDBDestroyPartitionTable
,
1070 PartitionRDBFindFileSystem
1073 const struct FSFunctionTable FilesystemRDB
=
1075 PartitionRDBLoadFileSystem
,
1076 PartitionRDBGetFileSystemAttr
,
1077 PartitionRDBFreeFileSystem