Updated debug output.
[AROS.git] / rom / partition / partitionrdb.c
blob77eac84fb30f108eaca6a9c463d76320902c4f9d
1 /*
2 Copyright © 1995-2011, 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 if (fn->filesystem)
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
362 ULONG size;
363 ULONG block;
365 size = 0;
366 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
367 while (block != (ULONG)-1)
369 size++;
370 if (readBlock(PartitionBase, root, block, buffer) !=0)
371 return 0;
372 if (
373 (AROS_BE2LONG(buffer->lsb_ID) != IDNAME_LOADSEG) ||
374 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->lsb_SummedLongs)))
376 return 0;
377 block = AROS_BE2LONG(buffer->lsb_Next);
379 return size;
382 void PartitionRDBReadFileSys
384 struct Library *PartitionBase,
385 struct PartitionHandle *root,
386 struct FileSysNode *fn,
387 struct LoadSegBlock *buffer
390 ULONG size;
391 ULONG block;
393 size = PartitionRDBCalcFSSize(PartitionBase, root, fn, buffer);
394 if (size)
396 fn->fsblocks = size;
397 fn->filesystem = AllocVec(size*512, MEMF_PUBLIC);
398 if (fn->filesystem)
400 size = 0;
401 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
402 while (block != (ULONG)-1)
404 if (readBlock(PartitionBase, root, block, &fn->filesystem[size]) !=0)
405 return;
406 block = AROS_BE2LONG(fn->filesystem[size].lsb_Next);
407 size++;
413 LONG PartitionRDBOpenPartitionTable
415 struct Library *PartitionBase,
416 struct PartitionHandle *root
419 UBYTE *buffer;
420 struct RDBData *data;
421 UBYTE i;
423 buffer = AllocVec(root->de.de_SizeBlock << 2, MEMF_PUBLIC);
424 if (!buffer)
425 return 1;
426 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC);
427 if (data)
429 for (i=0;i<RDB_LOCATION_LIMIT; i++)
431 if (readBlock(PartitionBase, root, i, buffer) != 0) {
432 FreeVec(buffer);
433 return 1;
435 CopyMem(buffer, &data->rdb, sizeof(struct RigidDiskBlock));
436 if (data->rdb.rdb_ID == AROS_BE2LONG(IDNAME_RIGIDDISK))
437 break;
439 if (i != RDB_LOCATION_LIMIT)
441 ULONG block;
443 data->rdbblock = i;
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);
470 if (bn != NULL)
472 AddTail(&data->badblocklist, &bn->ln);
473 block = AROS_BE2LONG(bn->bbb.bbb_Next);
475 else
476 break;
478 else
479 break;
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);
489 if (ph != NULL)
491 AddTail(&root->table->list, &ph->ln);
492 block = AROS_BE2LONG(((struct PartitionBlock *)ph->data)->pb_Next);
494 else
495 break;
497 else
498 break;
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);
509 if (fn != NULL)
511 AddTail(&data->fsheaderlist, &fn->h.ln);
512 PartitionRDBReadFileSys(PartitionBase, root, fn, (struct LoadSegBlock *)buffer);
513 block = AROS_BE2LONG(fn->fhb.fhb_Next);
515 else
516 break;
518 else
519 break;
521 FreeVec(buffer);
522 return 0;
524 FreeMem(data, sizeof(struct RDBData));
526 FreeVec(buffer);
527 return 1;
530 void PartitionRDBFreeHandle
532 struct Library *PartitionBase,
533 struct PartitionHandle *ph
536 ClosePartitionTable(ph);
537 Remove(&ph->ln);
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 */
563 if (!fn->h.boot)
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,
574 ULONG block
577 ULONG size;
579 if (fn->filesystem)
581 size = 0;
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)));
587 #if RDB_WRITE
588 if (writeBlock(PartitionBase, root, block++, &fn->filesystem[size]) != 0)
589 return block;
590 #else
591 kprintf("RDB-write: block=%ld, type=LSEG\n", block);
592 block++;
593 #endif
594 size++;
597 return 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;
607 ULONG block;
609 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
610 return 0;
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;
619 if (bn->ln.ln_Succ)
620 data->rdb.rdb_BadBlockList = block;
621 else
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));
629 #if RDB_WRITE
630 writeBlock(PartitionBase, root, block++, root->buffer);
631 #else
632 kprintf("RDB-write: block=%ld, type=BADB\n", block);
633 block++;
634 #endif
636 bn = (struct BadBlockNode *)bn->ln.ln_Succ;
639 /* write partition blocks */
640 ph = (struct PartitionHandle *)root->table->list.lh_Head;
641 if (ph->ln.ln_Succ)
642 data->rdb.rdb_PartitionList = AROS_LONG2BE(block);
643 else
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));
652 #if RDB_WRITE
653 writeBlock(PartitionBase, root, block++, root->buffer);
654 #else
655 kprintf("RDB-write: block=%ld, type=PART\n", block);
656 block++;
657 #endif
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);
665 else
666 data->rdb.rdb_FileSysHeaderList = (ULONG)-1;
667 while (fn->h.ln.ln_Succ)
669 ULONG fshblock;
670 struct FileSysHeaderBlock *fsb;
672 fshblock = block;
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)));
682 #if RDB_WRITE
683 writeBlock(PartitionBase, root, fshblock, root->buffer);
684 #else
685 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock);
686 #endif
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));
693 #if RDB_WRITE
694 writeBlock(PartitionBase, root, data->rdbblock, root->buffer);
695 #else
696 kprintf("RDB-write: block=%ld, type=RDSK\n", data->rdbblock);
697 #endif
698 return 0;
701 LONG PartitionRDBCreatePartitionTable(struct Library *PartitionBase, struct PartitionHandle *ph)
703 struct RDBData *data;
704 ULONG i;
706 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC | MEMF_CLEAR);
707 if (data)
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
718 * value.
720 while (rdbsize < 256)
721 rdbsize <<= 1;
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;
741 /* StepRate */
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 */
748 /* DiskVendor */
749 /* DiskProduct */
750 /* DiskRevision */
751 /* ControllerVendor */
752 /* ControllerProduct */
753 /* ControllerRevision */
755 data->rdbblock = 1;
756 NEWLIST(&data->badblocklist);
757 NEWLIST(&data->fsheaderlist);
758 NEWLIST(&ph->table->list);
759 return 0;
761 return 1;
764 static LONG PartitionRDBGetPartitionTableAttr(struct Library *PartitionBase, struct PartitionHandle *root, 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, struct PartitionHandle *ph, struct TagItem *tag)
780 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
782 switch (tag->ti_Tag)
784 case PT_TYPE:
785 *((ULONG *)tag->ti_Data) = AROS_LONG2BE(ph->de.de_DosType);
786 PTYPE(tag->ti_Data)->id_len = 4;
787 return TRUE;
789 case PT_BOOTABLE:
790 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_BOOTABLE) ? TRUE : FALSE;
791 return TRUE;
793 case PT_AUTOMOUNT:
794 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_NOMOUNT) ? FALSE : TRUE;
795 return TRUE;
798 return 0;
801 static LONG PartitionRDBSetPartitionAttrs(struct Library *PartitionBase, struct PartitionHandle *ph, const struct TagItem *taglist)
803 struct TagItem *tag;
804 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
806 while ((tag = NextTagItem((struct TagItem **)&taglist)))
808 switch (tag->ti_Tag)
810 case PT_DOSENVEC:
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);
817 break;
818 case PT_TYPE:
820 struct PartitionType *ptype=(struct PartitionType *)tag->ti_Data;
821 ULONG dt;
823 CopyMem(ptype->id, &dt, 4);
824 ph->de.de_DosType = AROS_BE2LONG(dt);
825 data->pb_Environment[DE_DOSTYPE] = dt;
827 break;
828 case PT_NAME:
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;
838 break;
839 case PT_BOOTABLE:
840 if (tag->ti_Data)
841 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_BOOTABLE);
842 else
843 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_BOOTABLE);
844 break;
845 case PT_AUTOMOUNT:
846 if (tag->ti_Data)
847 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_NOMOUNT);
848 else
849 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_NOMOUNT);
850 break;
853 return 0;
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);
865 if (ph)
867 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
868 if (ph->ln.ln_Name)
870 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC | MEMF_CLEAR);
871 if (pblock)
873 ph->root = root;
874 ph->bd = root->bd;
875 ph->data = pblock;
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)
883 break;
884 oph = (struct PartitionHandle *)oph->ln.ln_Succ;
886 if (oph->ln.ln_Succ)
888 oph = (struct PartitionHandle *)oph->ln.ln_Pred;
889 if (oph->ln.ln_Pred)
891 Insert(&root->table->list, &ph->ln, &oph->ln);
893 else
894 AddHead(&root->table->list, &ph->ln);
896 else
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;
907 return ph;
909 FreeVec(ph->ln.ln_Name);
911 FreeMem(ph, sizeof(struct PartitionHandle));
914 return NULL;
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},
931 {TAG_DONE, 0}
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},
943 {TAG_DONE, 0}
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))
956 return 0;
958 data = root->table->data;
959 CopyMem(&data->rdb, root->buffer, sizeof(struct RigidDiskBlock));
960 rdb = (struct RigidDiskBlock *)root->buffer;
961 rdb->rdb_ID = 0;
962 if (writeBlock(PartitionBase, root, data->rdbblock, root->buffer))
963 return 1;
964 return 0;
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)
977 if (idTag)
979 if (fn->fhb.fhb_DosType != idTag->ti_Data)
980 continue;
983 if (nameTag)
985 if (strcmp(fn->fhb.fhb_FileSysName, (char *)nameTag->ti_Data))
986 continue;
989 return &fn->h.ln;
992 return NULL;
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);
999 else
1000 return BNULL;
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)
1010 case FST_ID:
1011 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_DosType);
1012 return TRUE;
1014 case FST_NAME:
1015 *((STRPTR *)tag->ti_Data) = fhb->fhb_FileSysName;
1016 return TRUE;
1018 case FST_FSENTRY:
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);
1043 return TRUE;
1045 case FST_VERSION:
1046 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_Version);
1047 return TRUE;
1050 return 0;
1053 const struct PTFunctionTable PartitionRDB =
1055 PHPTT_RDB,
1056 "RDB",
1057 PartitionRDBCheckPartitionTable,
1058 PartitionRDBOpenPartitionTable,
1059 PartitionRDBClosePartitionTable,
1060 PartitionRDBWritePartitionTable,
1061 PartitionRDBCreatePartitionTable,
1062 PartitionRDBAddPartition,
1063 PartitionRDBDeletePartition,
1064 PartitionRDBGetPartitionTableAttr,
1065 NULL,
1066 PartitionRDBGetPartitionAttr,
1067 PartitionRDBSetPartitionAttrs,
1068 PartitionRDBPartitionTableAttrs,
1069 PartitionRDBPartitionAttrs,
1070 PartitionRDBDestroyPartitionTable,
1071 PartitionRDBFindFileSystem
1074 const struct FSFunctionTable FilesystemRDB =
1076 PartitionRDBLoadFileSystem,
1077 PartitionRDBGetFileSystemAttr,
1078 PartitionRDBFreeFileSystem