move delay code into separate function.
[AROS.git] / rom / partition / partitionrdb.c
blobbf32c4bdf9d67cc5ba17f364a1194551c8188ecf
1 /*
2 Copyright © 1995-2013, 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, struct PartitionHandle *root, struct TagItem *tag)
765 struct RDBData *data = root->table->data;
767 switch (tag->ti_Tag)
769 case PTT_RESERVED:
770 *((LONG *)tag->ti_Data) = AROS_BE2LONG(data->rdb.rdb_RDBBlocksHi) + 1; /* Reserved blocks count starts from 0, so ignore rdb_RDBBlocksLo */
771 return TRUE;
774 return 0;
777 static LONG PartitionRDBGetPartitionAttr(struct Library *PartitionBase, struct PartitionHandle *ph, struct TagItem *tag)
779 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
781 switch (tag->ti_Tag)
783 case PT_TYPE:
784 *((ULONG *)tag->ti_Data) = AROS_LONG2BE(ph->de.de_DosType);
785 PTYPE(tag->ti_Data)->id_len = 4;
786 return TRUE;
788 case PT_BOOTABLE:
789 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_BOOTABLE) ? TRUE : FALSE;
790 return TRUE;
792 case PT_AUTOMOUNT:
793 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_NOMOUNT) ? FALSE : TRUE;
794 return TRUE;
797 return 0;
800 static LONG PartitionRDBSetPartitionAttrs(struct Library *PartitionBase, struct PartitionHandle *ph, const struct TagItem *taglist)
802 struct TagItem *tag;
803 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
805 while ((tag = NextTagItem((struct TagItem **)&taglist)))
807 switch (tag->ti_Tag)
809 case PT_DOSENVEC:
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);
816 break;
817 case PT_TYPE:
819 struct PartitionType *ptype=(struct PartitionType *)tag->ti_Data;
820 ULONG dt;
822 CopyMem(ptype->id, &dt, 4);
823 ph->de.de_DosType = AROS_BE2LONG(dt);
824 data->pb_Environment[DE_DOSTYPE] = dt;
826 break;
827 case PT_NAME:
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;
837 break;
838 case PT_BOOTABLE:
839 if (tag->ti_Data)
840 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_BOOTABLE);
841 else
842 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_BOOTABLE);
843 break;
844 case PT_AUTOMOUNT:
845 if (tag->ti_Data)
846 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_NOMOUNT);
847 else
848 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_NOMOUNT);
849 break;
852 return 0;
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);
864 if (ph)
866 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
867 if (ph->ln.ln_Name)
869 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC | MEMF_CLEAR);
870 if (pblock)
872 ph->root = root;
873 ph->bd = root->bd;
874 ph->data = pblock;
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)
882 break;
883 oph = (struct PartitionHandle *)oph->ln.ln_Succ;
885 if (oph->ln.ln_Succ)
887 oph = (struct PartitionHandle *)oph->ln.ln_Pred;
888 if (oph->ln.ln_Pred)
890 Insert(&root->table->list, &ph->ln, &oph->ln);
892 else
893 AddHead(&root->table->list, &ph->ln);
895 else
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;
906 return ph;
908 FreeVec(ph->ln.ln_Name);
910 FreeMem(ph, sizeof(struct PartitionHandle));
913 return NULL;
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},
930 {TAG_DONE, 0}
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},
942 {TAG_DONE, 0}
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))
955 return 0;
957 data = root->table->data;
958 CopyMem(&data->rdb, root->buffer, sizeof(struct RigidDiskBlock));
959 rdb = (struct RigidDiskBlock *)root->buffer;
960 rdb->rdb_ID = 0;
961 if (writeBlock(PartitionBase, root, data->rdbblock, root->buffer))
962 return 1;
963 return 0;
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)
976 if (idTag)
978 if (fn->fhb.fhb_DosType != idTag->ti_Data)
979 continue;
982 if (nameTag)
984 if (strcmp(fn->fhb.fhb_FileSysName, (char *)nameTag->ti_Data))
985 continue;
988 return &fn->h.ln;
991 return NULL;
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);
998 else
999 return BNULL;
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)
1009 case FST_ID:
1010 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_DosType);
1011 return TRUE;
1013 case FST_NAME:
1014 *((STRPTR *)tag->ti_Data) = fhb->fhb_FileSysName;
1015 return TRUE;
1017 case FST_FSENTRY:
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);
1042 return TRUE;
1044 case FST_VERSION:
1045 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_Version);
1046 return TRUE;
1049 return 0;
1052 const struct PTFunctionTable PartitionRDB =
1054 PHPTT_RDB,
1055 "RDB",
1056 PartitionRDBCheckPartitionTable,
1057 PartitionRDBOpenPartitionTable,
1058 PartitionRDBClosePartitionTable,
1059 PartitionRDBWritePartitionTable,
1060 PartitionRDBCreatePartitionTable,
1061 PartitionRDBAddPartition,
1062 PartitionRDBDeletePartition,
1063 PartitionRDBGetPartitionTableAttr,
1064 NULL,
1065 PartitionRDBGetPartitionAttr,
1066 PartitionRDBSetPartitionAttrs,
1067 PartitionRDBPartitionTableAttrs,
1068 PartitionRDBPartitionAttrs,
1069 PartitionRDBDestroyPartitionTable,
1070 PartitionRDBFindFileSystem
1073 const struct FSFunctionTable FilesystemRDB =
1075 PartitionRDBLoadFileSystem,
1076 PartitionRDBGetFileSystemAttr,
1077 PartitionRDBFreeFileSystem