revert between 56095 -> 55830 in arch
[AROS.git] / rom / partition / partitionrdb.c
blob6622f26b18e95c3a97507e136db95b7de69ac8ca
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 */
7 #define RDB_WRITE 1
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"
22 #include "platform.h"
24 #ifndef DEBUG
25 #define DEBUG 1
26 #endif
27 #include "debug.h"
29 #include <string.h>
31 struct RDBData {
32 struct RigidDiskBlock rdb;
33 UBYTE rdbblock; /* the block rdb was read from */
34 struct List badblocklist;
35 struct List fsheaderlist;
38 struct BadBlockNode {
39 struct Node ln;
40 struct BadBlockBlock bbb;
43 struct FileSysNode
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))
54 struct FileSysReader
56 ULONG count;
57 ULONG offset;
58 ULONG size;
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))
68 AROS_USERFUNC_INIT
70 struct FileSysReader *fsr = (struct FileSysReader*)file;
71 ULONG outsize = 0;
72 UBYTE *outbuf = buffer;
74 while (length > 0) {
75 ULONG size = length;
77 if (size + fsr->offset > fsr->size)
78 size = fsr->size - fsr->offset;
79 if (size > 0) {
80 UBYTE *inbuf = (UBYTE*)(fsr->fsn->filesystem[fsr->count].lsb_LoadData) + fsr->offset;
81 CopyMem(inbuf, outbuf, size);
84 outsize += size;
85 fsr->offset += size;
86 length -= size;
87 outbuf += size;
89 if (fsr->offset == fsr->size) {
90 fsr->offset = 0;
91 fsr->count++;
92 if (fsr->count == fsr->fsn->fsblocks)
93 break;
98 return outsize;
100 AROS_USERFUNC_EXIT
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))
109 AROS_USERFUNC_INIT
111 struct FileSysReader *fsr = (struct FileSysReader*)file;
112 LONG oldpos = fsr->offset;
114 switch (mode) {
115 case OFFSET_BEGINNING: break;
116 case OFFSET_END: pos = fsr->size - pos; break;
117 case OFFSET_CURRENT: pos = fsr->offset + pos; break;
118 default: return -1;
121 if (pos < 0 || pos >= fsr->size)
122 return -1;
124 fsr->offset = pos;
126 return oldpos;
128 AROS_USERFUNC_EXIT
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;
137 #ifndef __mc68000
138 /* Prevent loading hunk files on non-m68k */
139 if (AROS_BE2LONG(node->filesystem[0].lsb_LoadData[0]) == 0x000003f3)
140 return BNULL;
141 #endif
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 */
149 fakefile.count = 0;
150 fakefile.offset = 0;
151 fakefile.size = LSEGDATASIZE;
152 fakefile.fsn = node;
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)
168 ULONG i;
169 ULONG sum=0;
171 for (i=0;i<size;i++)
173 sum += AROS_BE2LONG(*ptr);
174 ptr++;
176 return sum;
179 LONG PartitionRDBCheckPartitionTable
181 struct Library *PartitionBase,
182 struct PartitionHandle *root
185 UBYTE i;
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))
191 return 0;
193 if (root->root != NULL)
195 GetPartitionAttrs(root, tags);
196 if (
197 (root->root->table->type != PHPTT_MBR &&
198 root->root->table->type != PHPTT_EBR) ||
199 (type.id[0] != 0x30 && type.id[0] != 0x76)
202 return 0;
205 for (i=0;i<RDB_LOCATION_LIMIT; i++)
207 if (readBlock(PartitionBase, root, i, rdb) != 0)
208 return 0;
209 if (rdb->rdb_ID == AROS_BE2LONG(IDNAME_RIGIDDISK))
210 break;
212 if (i != RDB_LOCATION_LIMIT)
214 if (calcChkSum((ULONG *)rdb, AROS_BE2LONG(rdb->rdb_SummedLongs))==0)
215 return 1;
217 return 0;
220 void CopyBE2HostDosEnvec(LONG *src, SIPTR *dst, ULONG size) {
221 ULONG count=0;
223 while (count != size)
225 *dst++ = AROS_BE2LONG(*src);
226 src++;
227 count++;
231 void CopyHost2BEDosEnvec(SIPTR *src, ULONG *dst, ULONG size) {
233 ULONG count=0;
235 while (count != size)
237 *dst++ = AROS_LONG2BE(*src);
238 src++;
239 count++;
244 struct BadBlockNode *PartitionRDBNewBadBlock
246 struct Library *PartitionBase,
247 struct PartitionHandle *root,
248 struct BadBlockBlock *buffer
251 struct BadBlockNode *bn;
253 if (
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);
259 if (bn)
261 CopyMem(buffer, &bn->bbb, sizeof(struct BadBlockBlock));
262 return bn;
265 return NULL;
268 struct PartitionHandle *PartitionRDBNewHandle
270 struct Library *PartitionBase,
271 struct PartitionHandle *root,
272 struct PartitionBlock *buffer
275 struct PartitionBlock *pblock;
276 struct PartitionHandle *ph;
278 if (
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);
284 if (ph)
286 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
287 if (ph->ln.ln_Name)
289 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC);
290 if (pblock)
292 CopyMem(buffer, pblock, sizeof(struct PartitionBlock));
293 ph->root = root;
294 ph->bd = root->bd;
295 ph->data = pblock;
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;
305 return ph;
307 FreeVec(ph->ln.ln_Name);
309 FreeMem(ph, sizeof(struct PartitionHandle));
312 return NULL;
315 struct FileSysNode *PartitionRDBNewFileSys
317 struct Library *PartitionBase,
318 struct PartitionHandle *root,
319 struct FileSysHeaderBlock *buffer
322 struct FileSysNode *fn;
324 if (
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);
330 if (fn)
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;
336 fn->h.ln.ln_Pri = 0;
337 fn->h.handler = &FilesystemRDB;
339 return fn;
342 return NULL;
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
361 ULONG size;
362 ULONG block;
364 size = 0;
365 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
366 while (block != (ULONG)-1)
368 size++;
369 if (readBlock(PartitionBase, root, block, buffer) !=0)
370 return 0;
371 if (
372 (AROS_BE2LONG(buffer->lsb_ID) != IDNAME_LOADSEG) ||
373 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->lsb_SummedLongs)))
375 return 0;
376 block = AROS_BE2LONG(buffer->lsb_Next);
378 return size;
381 void PartitionRDBReadFileSys
383 struct Library *PartitionBase,
384 struct PartitionHandle *root,
385 struct FileSysNode *fn,
386 struct LoadSegBlock *buffer
389 ULONG size;
390 ULONG block;
392 size = PartitionRDBCalcFSSize(PartitionBase, root, fn, buffer);
393 if (size)
395 fn->fsblocks = size;
396 fn->filesystem = AllocVec(size*512, MEMF_PUBLIC);
397 if (fn->filesystem)
399 size = 0;
400 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
401 while (block != (ULONG)-1)
403 if (readBlock(PartitionBase, root, block, &fn->filesystem[size]) !=0)
404 return;
405 block = AROS_BE2LONG(fn->filesystem[size].lsb_Next);
406 size++;
412 LONG PartitionRDBOpenPartitionTable
414 struct Library *PartitionBase,
415 struct PartitionHandle *root
418 UBYTE *buffer;
419 struct RDBData *data;
420 UBYTE i;
422 buffer = AllocVec(root->de.de_SizeBlock << 2, MEMF_PUBLIC);
423 if (!buffer)
424 return 1;
425 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC);
426 if (data)
428 for (i=0;i<RDB_LOCATION_LIMIT; i++)
430 if (readBlock(PartitionBase, root, i, buffer) != 0) {
431 FreeVec(buffer);
432 return 1;
434 CopyMem(buffer, &data->rdb, sizeof(struct RigidDiskBlock));
435 if (data->rdb.rdb_ID == AROS_BE2LONG(IDNAME_RIGIDDISK))
436 break;
438 if (i != RDB_LOCATION_LIMIT)
440 ULONG block;
442 data->rdbblock = i;
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);
469 if (bn != NULL)
471 AddTail(&data->badblocklist, &bn->ln);
472 block = AROS_BE2LONG(bn->bbb.bbb_Next);
474 else
475 break;
477 else
478 break;
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);
488 if (ph != NULL)
490 AddTail(&root->table->list, &ph->ln);
491 block = AROS_BE2LONG(((struct PartitionBlock *)ph->data)->pb_Next);
493 else
494 break;
496 else
497 break;
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);
508 if (fn != NULL)
510 AddTail(&data->fsheaderlist, &fn->h.ln);
511 PartitionRDBReadFileSys(PartitionBase, root, fn, (struct LoadSegBlock *)buffer);
512 block = AROS_BE2LONG(fn->fhb.fhb_Next);
514 else
515 break;
517 else
518 break;
520 FreeVec(buffer);
521 return 0;
523 FreeMem(data, sizeof(struct RDBData));
525 FreeVec(buffer);
526 return 1;
529 void PartitionRDBFreeHandle
531 struct Library *PartitionBase,
532 struct PartitionHandle *ph
535 ClosePartitionTable(ph);
536 Remove(&ph->ln);
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 */
562 if (!fn->h.boot)
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,
573 ULONG block
576 ULONG size;
578 if (fn->filesystem)
580 size = 0;
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)));
586 #if RDB_WRITE
587 if (writeBlock(PartitionBase, root, block++, &fn->filesystem[size]) != 0)
588 return block;
589 #else
590 kprintf("RDB-write: block=%ld, type=LSEG\n", block);
591 block++;
592 #endif
593 size++;
596 return 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;
606 ULONG block;
608 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
609 return 0;
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;
618 if (bn->ln.ln_Succ)
619 data->rdb.rdb_BadBlockList = block;
620 else
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));
628 #if RDB_WRITE
629 writeBlock(PartitionBase, root, block++, root->buffer);
630 #else
631 kprintf("RDB-write: block=%ld, type=BADB\n", block);
632 block++;
633 #endif
635 bn = (struct BadBlockNode *)bn->ln.ln_Succ;
638 /* write partition blocks */
639 ph = (struct PartitionHandle *)root->table->list.lh_Head;
640 if (ph->ln.ln_Succ)
641 data->rdb.rdb_PartitionList = AROS_LONG2BE(block);
642 else
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));
651 #if RDB_WRITE
652 writeBlock(PartitionBase, root, block++, root->buffer);
653 #else
654 kprintf("RDB-write: block=%ld, type=PART\n", block);
655 block++;
656 #endif
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);
664 else
665 data->rdb.rdb_FileSysHeaderList = (ULONG)-1;
666 while (fn->h.ln.ln_Succ)
668 ULONG fshblock;
669 struct FileSysHeaderBlock *fsb;
671 fshblock = block;
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)));
681 #if RDB_WRITE
682 writeBlock(PartitionBase, root, fshblock, root->buffer);
683 #else
684 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock);
685 #endif
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));
692 #if RDB_WRITE
693 writeBlock(PartitionBase, root, data->rdbblock, root->buffer);
694 #else
695 kprintf("RDB-write: block=%ld, type=RDSK\n", data->rdbblock);
696 #endif
697 return 0;
700 LONG PartitionRDBCreatePartitionTable(struct Library *PartitionBase, struct PartitionHandle *ph)
702 struct RDBData *data;
703 ULONG i;
705 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC | MEMF_CLEAR);
706 if (data)
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
717 * value.
719 while (rdbsize < 256)
720 rdbsize <<= 1;
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;
740 /* StepRate */
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 */
747 /* DiskVendor */
748 /* DiskProduct */
749 /* DiskRevision */
750 /* ControllerVendor */
751 /* ControllerProduct */
752 /* ControllerRevision */
754 data->rdbblock = 1;
755 NEWLIST(&data->badblocklist);
756 NEWLIST(&data->fsheaderlist);
757 NEWLIST(&ph->table->list);
758 return 0;
760 return 1;
763 static LONG PartitionRDBGetPartitionTableAttr(struct Library *PartitionBase,
764 struct PartitionHandle *root, const struct TagItem *tag)
766 struct RDBData *data = root->table->data;
768 switch (tag->ti_Tag)
770 case PTT_RESERVED:
771 *((LONG *)tag->ti_Data) = AROS_BE2LONG(data->rdb.rdb_RDBBlocksHi) + 1; /* Reserved blocks count starts from 0, so ignore rdb_RDBBlocksLo */
772 return TRUE;
775 return 0;
778 static LONG PartitionRDBGetPartitionAttr(struct Library *PartitionBase,
779 struct PartitionHandle *ph, const struct TagItem *tag)
781 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
783 switch (tag->ti_Tag)
785 case PT_TYPE:
786 *((ULONG *)tag->ti_Data) = AROS_LONG2BE(ph->de.de_DosType);
787 PTYPE(tag->ti_Data)->id_len = 4;
788 return TRUE;
790 case PT_BOOTABLE:
791 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_BOOTABLE) ? TRUE : FALSE;
792 return TRUE;
794 case PT_AUTOMOUNT:
795 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_NOMOUNT) ? FALSE : TRUE;
796 return TRUE;
799 return 0;
802 static LONG PartitionRDBSetPartitionAttrs(struct Library *PartitionBase, struct PartitionHandle *ph, const struct TagItem *taglist)
804 struct TagItem *tag;
805 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
807 while ((tag = NextTagItem((struct TagItem **)&taglist)))
809 switch (tag->ti_Tag)
811 case PT_DOSENVEC:
813 struct DosEnvec *de = (struct DosEnvec *)tag->ti_Data;
815 CopyMem(de, &ph->de, (de->de_TableSize+1)*sizeof(IPTR));
816 CopyHost2BEDosEnvec((SIPTR *)de, data->pb_Environment, de->de_TableSize+1);
818 break;
819 case PT_TYPE:
821 struct PartitionType *ptype=(struct PartitionType *)tag->ti_Data;
822 ULONG dt;
824 CopyMem(ptype->id, &dt, 4);
825 ph->de.de_DosType = AROS_BE2LONG(dt);
826 data->pb_Environment[DE_DOSTYPE] = dt;
828 break;
829 case PT_NAME:
831 STRPTR name = (STRPTR)tag->ti_Data;
832 ULONG len = strlen(name);
834 CopyMem(name, ph->ln.ln_Name, len+1);
835 CopyMem(name, data->pb_DriveName+1, len);
836 data->pb_DriveName[len+1] = 0;
837 data->pb_DriveName[0] = len;
839 break;
840 case PT_BOOTABLE:
841 if (tag->ti_Data)
842 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_BOOTABLE);
843 else
844 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_BOOTABLE);
845 break;
846 case PT_AUTOMOUNT:
847 if (tag->ti_Data)
848 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_NOMOUNT);
849 else
850 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_NOMOUNT);
851 break;
854 return 0;
857 struct PartitionHandle *PartitionRDBAddPartition(struct Library *PartitionBase, struct PartitionHandle *root, const struct TagItem *taglist)
859 if (FindTagItem(PT_DOSENVEC, taglist) != NULL)
861 struct PartitionBlock *pblock;
862 struct PartitionHandle *ph;
863 struct PartitionHandle *oph;
865 ph = AllocMem(sizeof(struct PartitionHandle), MEMF_PUBLIC | MEMF_CLEAR);
866 if (ph)
868 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
869 if (ph->ln.ln_Name)
871 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC | MEMF_CLEAR);
872 if (pblock)
874 ph->root = root;
875 ph->bd = root->bd;
876 ph->data = pblock;
877 pblock->pb_ID = AROS_LONG2BE(IDNAME_PARTITION);
878 pblock->pb_SummedLongs = AROS_LONG2BE(sizeof(struct PartitionBlock)/4);
879 PartitionRDBSetPartitionAttrs(PartitionBase, ph, taglist);
880 oph = (struct PartitionHandle *)root->table->list.lh_Head;
881 while (oph->ln.ln_Succ)
883 if (ph->de.de_LowCyl<oph->de.de_LowCyl)
884 break;
885 oph = (struct PartitionHandle *)oph->ln.ln_Succ;
887 if (oph->ln.ln_Succ)
889 oph = (struct PartitionHandle *)oph->ln.ln_Pred;
890 if (oph->ln.ln_Pred)
892 Insert(&root->table->list, &ph->ln, &oph->ln);
894 else
895 AddHead(&root->table->list, &ph->ln);
897 else
898 AddTail(&root->table->list, &ph->ln);
899 if (FindTagItem(PT_DOSENVEC, taglist) == NULL)
901 ph->dg.dg_DeviceType = DG_DIRECT_ACCESS;
902 ph->dg.dg_SectorSize = ph->de.de_SizeBlock<<2;
903 ph->dg.dg_Heads = ph->de.de_Surfaces;
904 ph->dg.dg_TrackSectors = ph->de.de_BlocksPerTrack;
905 ph->dg.dg_Cylinders = ph->de.de_HighCyl - ph->de.de_LowCyl + 1;
906 ph->dg.dg_BufMemType = ph->de.de_BufMemType;
908 return ph;
910 FreeVec(ph->ln.ln_Name);
912 FreeMem(ph, sizeof(struct PartitionHandle));
915 return NULL;
918 void PartitionRDBDeletePartition
920 struct Library *PartitionBase,
921 struct PartitionHandle *ph
925 PartitionRDBFreeHandle(PartitionBase, ph);
928 const struct PartitionAttribute PartitionRDBPartitionTableAttrs[]=
930 {PTT_TYPE, PLAM_READ},
931 {PTT_RESERVED, PLAM_READ},
932 {TAG_DONE, 0}
935 const struct PartitionAttribute PartitionRDBPartitionAttrs[]=
937 /* TODO: implement write */
938 {PT_GEOMETRY, PLAM_READ},
939 {PT_DOSENVEC, PLAM_READ | PLAM_WRITE},
940 {PT_TYPE, PLAM_READ | PLAM_WRITE},
941 {PT_NAME, PLAM_READ | PLAM_WRITE},
942 {PT_BOOTABLE, PLAM_READ | PLAM_WRITE},
943 {PT_AUTOMOUNT, PLAM_READ | PLAM_WRITE},
944 {TAG_DONE, 0}
947 ULONG PartitionRDBDestroyPartitionTable
949 struct Library *PartitionBase,
950 struct PartitionHandle *root
953 struct RDBData *data;
954 struct RigidDiskBlock *rdb;
956 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
957 return 0;
959 data = root->table->data;
960 CopyMem(&data->rdb, root->buffer, sizeof(struct RigidDiskBlock));
961 rdb = (struct RigidDiskBlock *)root->buffer;
962 rdb->rdb_ID = 0;
963 if (writeBlock(PartitionBase, root, data->rdbblock, root->buffer))
964 return 1;
965 return 0;
968 struct Node *PartitionRDBFindFileSystem(struct Library *PartitionBase, struct PartitionHandle *ph, const struct TagItem *tags)
970 struct RDBData *data = (struct RDBData *)ph->table->data;
971 struct FileSysNode *fn;
972 struct TagItem *idTag = FindTagItem(FST_ID , tags);
973 struct TagItem *nameTag = FindTagItem(FST_NAME, tags);
975 for (fn = (struct FileSysNode *)data->fsheaderlist.lh_Head; fn->h.ln.ln_Succ;
976 fn = (struct FileSysNode *)fn->h.ln.ln_Succ)
978 if (idTag)
980 if (fn->fhb.fhb_DosType != idTag->ti_Data)
981 continue;
984 if (nameTag)
986 if (strcmp(fn->fhb.fhb_FileSysName, (char *)nameTag->ti_Data))
987 continue;
990 return &fn->h.ln;
993 return NULL;
996 BPTR PartitionRDBLoadFileSystem(struct PartitionBase_intern *PartitionBase, struct FileSysHandle *fn)
998 if (PartitionBase->pb_DOSBase)
999 return LoadFS((struct FileSysNode *)fn, (struct DosLibrary *)PartitionBase->pb_DOSBase);
1000 else
1001 return BNULL;
1004 static LONG PartitionRDBGetFileSystemAttr(struct Library *PartitionBase, struct FileSysHandle *fn, const struct TagItem *tag)
1006 struct FileSysEntry *fse;
1007 struct FileSysHeaderBlock *fhb = &((struct FileSysNode *)fn)->fhb;
1009 switch (tag->ti_Tag)
1011 case FST_ID:
1012 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_DosType);
1013 return TRUE;
1015 case FST_NAME:
1016 *((STRPTR *)tag->ti_Data) = fhb->fhb_FileSysName;
1017 return TRUE;
1019 case FST_FSENTRY:
1020 fse = (struct FileSysEntry *)tag->ti_Data;
1022 /* RDB filesystems are not prioritized */
1023 fse->fse_Node.ln_Pri = 0;
1026 * Don't use CopyMem() or something like that.
1027 * First, you need to deal with endianess.
1028 * Second, some things are actually pointers, you need
1029 * to sign-extend them on 64 bits.
1031 fse->fse_DosType = AROS_BE2LONG(fhb->fhb_DosType);
1032 fse->fse_Version = AROS_BE2LONG(fhb->fhb_Version);
1033 fse->fse_PatchFlags = AROS_BE2LONG(fhb->fhb_PatchFlags);
1034 fse->fse_Type = AROS_BE2LONG(fhb->fhb_Type);
1035 fse->fse_Task = AROS_BE2LONG(fhb->fhb_Task);
1036 fse->fse_Lock = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Lock);
1037 /* Just for convenience. This is expected to be zero. */
1038 fse->fse_Handler = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Handler);
1039 fse->fse_StackSize = AROS_BE2LONG(fhb->fhb_StackSize);
1040 fse->fse_Priority = AROS_BE2LONG(fhb->fhb_Priority);
1041 fse->fse_Startup = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Startup);
1042 /* Skip fse_SegList */
1043 fse->fse_GlobalVec = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_GlobalVec);
1044 return TRUE;
1046 case FST_VERSION:
1047 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_Version);
1048 return TRUE;
1051 return 0;
1054 const struct PTFunctionTable PartitionRDB =
1056 PHPTT_RDB,
1057 "RDB",
1058 PartitionRDBCheckPartitionTable,
1059 PartitionRDBOpenPartitionTable,
1060 PartitionRDBClosePartitionTable,
1061 PartitionRDBWritePartitionTable,
1062 PartitionRDBCreatePartitionTable,
1063 PartitionRDBAddPartition,
1064 PartitionRDBDeletePartition,
1065 PartitionRDBGetPartitionTableAttr,
1066 NULL,
1067 PartitionRDBGetPartitionAttr,
1068 PartitionRDBSetPartitionAttrs,
1069 PartitionRDBPartitionTableAttrs,
1070 PartitionRDBPartitionAttrs,
1071 PartitionRDBDestroyPartitionTable,
1072 PartitionRDBFindFileSystem
1075 const struct FSFunctionTable FilesystemRDB =
1077 PartitionRDBLoadFileSystem,
1078 PartitionRDBGetFileSystemAttr,
1079 PartitionRDBFreeFileSystem