- Include aros/config.h at almost all places where AROS_FLAVOUR is used.
[AROS.git] / rom / partition / partitionrdb.c
blobf5073df8003079859fc2668413ee7f3a6f637348
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 return InternalLoadSeg((BPTR)&fakefile, BNULL, FunctionArray, NULL);
158 * Insert RDB LSEG filesystem to FileSystem.resource
159 * FIXME: this is an obsolete hack. Use new filesystem API
160 * in Boot Strap instead.
163 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
165 /* We can't use InternalLoadSeg() because DOS isn't initialized
166 * at this point. To allow this to be built as a relocatable
167 * library, we will use the loadseg linklib.
170 #include <loadseg.h>
172 void register_elf(BPTR file, BPTR hunks, struct elfheader *eh, struct sheader *sh, struct DosLibrary *DOSBase)
174 /* Do-nothing function to make the linker happy */
177 static void AddFS(struct RDBData *data)
179 struct FileSysResource *fsr;
180 struct FileSysNode *node;
181 void (* FunctionArray[4])();
182 struct FileSysReader fakefile;
184 FunctionArray[0] = (void(*))ReadFunc;
185 FunctionArray[1] = __AROS_GETVECADDR(SysBase,33); /* AllocMem() */
186 FunctionArray[2] = __AROS_GETVECADDR(SysBase,35); /* FreeMem() */
187 FunctionArray[3] = (void(*))SeekFunc;
189 fsr = OpenResource("FileSystem.resource");
190 if (!fsr)
191 return;
193 ForeachNode(&data->fsheaderlist, node) {
194 struct FileSysEntry *fsrnode;
195 ULONG dostype = node->fhb.fhb_DosType;
196 ULONG version = node->fhb.fhb_Version;
197 BOOL newerinstalled = FALSE;
198 ULONG size = LSEGDATASIZE;
200 ForeachNode(&fsr->fsr_FileSysEntries, fsrnode) {
201 if (fsrnode->fse_DosType == dostype && fsrnode->fse_Version >= version)
202 newerinstalled = TRUE;
204 if (newerinstalled)
205 continue;
206 fsrnode = AllocVec(sizeof(struct FileSysEntry), MEMF_PUBLIC | MEMF_CLEAR);
207 if (!fsrnode)
208 break;
209 fakefile.count = 0;
210 fakefile.offset = 0;
211 fakefile.size = size;
212 fakefile.fsn = node;
213 if (node->filesystem[0].lsb_LoadData[0] == 0x000003f3) {
214 APTR DOSBase = NULL;
215 BPTR seg = LoadSegment((BPTR)&fakefile, BNULL, (SIPTR*)FunctionArray, NULL);
216 if (seg) {
217 D(bug("RDB fs %08x %d.%d '%s' seg=%08x added\n",
218 dostype, version >> 16, version & 0xffff, &node->fhb.fhb_FileSysName, seg));
219 CopyMem(&node->fhb.fhb_DosType, &fsrnode->fse_DosType, sizeof(struct FileSysEntry) - sizeof(struct Node));
220 fsrnode->fse_SegList = seg;
221 AddHead(&fsr->fsr_FileSysEntries, &fsrnode->fse_Node);
227 #endif
229 static ULONG calcChkSum(ULONG *ptr, ULONG size)
231 ULONG i;
232 ULONG sum=0;
234 for (i=0;i<size;i++)
236 sum += AROS_BE2LONG(*ptr);
237 ptr++;
239 return sum;
242 LONG PartitionRDBCheckPartitionTable
244 struct Library *PartitionBase,
245 struct PartitionHandle *root
248 UBYTE i;
249 struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)root->buffer;
250 struct PartitionType type;
251 struct TagItem tags[] = {{PT_TYPE, (IPTR)&type}, {TAG_DONE, 0}};
253 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
254 return 0;
256 if (root->root != NULL)
258 GetPartitionAttrs(root, tags);
259 if (
260 (root->root->table->type != PHPTT_MBR &&
261 root->root->table->type != PHPTT_EBR) ||
262 (type.id[0] != 0x30 && type.id[0] != 0x76)
265 return 0;
268 for (i=0;i<RDB_LOCATION_LIMIT; i++)
270 if (readBlock(PartitionBase, root, i, rdb) != 0)
271 return 0;
272 if (rdb->rdb_ID == AROS_BE2LONG(IDNAME_RIGIDDISK))
273 break;
275 if (i != RDB_LOCATION_LIMIT)
277 if (calcChkSum((ULONG *)rdb, AROS_BE2LONG(rdb->rdb_SummedLongs))==0)
278 return 1;
280 return 0;
283 void CopyBE2HostDosEnvec(LONG *src, SIPTR *dst, ULONG size) {
284 ULONG count=0;
286 while (count != size)
288 *dst++ = AROS_BE2LONG(*src);
289 src++;
290 count++;
294 void CopyHost2BEDosEnvec(SIPTR *src, ULONG *dst, ULONG size) {
296 ULONG count=0;
298 while (count != size)
300 *dst++ = AROS_LONG2BE(*src);
301 src++;
302 count++;
307 struct BadBlockNode *PartitionRDBNewBadBlock
309 struct Library *PartitionBase,
310 struct PartitionHandle *root,
311 struct BadBlockBlock *buffer
314 struct BadBlockNode *bn;
316 if (
317 (AROS_BE2LONG(buffer->bbb_ID) == IDNAME_BADBLOCK) &&
318 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->bbb_SummedLongs))==0)
321 bn = AllocMem(sizeof(struct BadBlockNode), MEMF_PUBLIC | MEMF_CLEAR);
322 if (bn)
324 CopyMem(buffer, &bn->bbb, sizeof(struct BadBlockBlock));
325 return bn;
328 return NULL;
331 struct PartitionHandle *PartitionRDBNewHandle
333 struct Library *PartitionBase,
334 struct PartitionHandle *root,
335 struct PartitionBlock *buffer
338 struct PartitionBlock *pblock;
339 struct PartitionHandle *ph;
341 if (
342 (AROS_BE2LONG(buffer->pb_ID) == IDNAME_PARTITION) &&
343 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->pb_SummedLongs))==0)
346 ph = AllocMem(sizeof(struct PartitionHandle), MEMF_PUBLIC | MEMF_CLEAR);
347 if (ph)
349 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
350 if (ph->ln.ln_Name)
352 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC);
353 if (pblock)
355 CopyMem(buffer, pblock, sizeof(struct PartitionBlock));
356 ph->root = root;
357 ph->bd = root->bd;
358 ph->data = pblock;
359 CopyMem(pblock->pb_DriveName+1, ph->ln.ln_Name, pblock->pb_DriveName[0]);
360 ph->ln.ln_Name[pblock->pb_DriveName[0]]=0;
361 CopyBE2HostDosEnvec(pblock->pb_Environment, (SIPTR *)&ph->de, AROS_BE2LONG(((struct DosEnvec *)pblock->pb_Environment)->de_TableSize)+1);
362 ph->dg.dg_DeviceType = DG_DIRECT_ACCESS;
363 ph->dg.dg_SectorSize = ph->de.de_SizeBlock<<2;
364 ph->dg.dg_Heads = ph->de.de_Surfaces;
365 ph->dg.dg_TrackSectors = ph->de.de_BlocksPerTrack;
366 ph->dg.dg_Cylinders = ph->de.de_HighCyl - ph->de.de_LowCyl + 1;
367 ph->dg.dg_BufMemType = ph->de.de_BufMemType;
368 return ph;
370 FreeVec(ph->ln.ln_Name);
372 FreeMem(ph, sizeof(struct PartitionHandle));
375 return NULL;
378 struct FileSysNode *PartitionRDBNewFileSys
380 struct Library *PartitionBase,
381 struct PartitionHandle *root,
382 struct FileSysHeaderBlock *buffer
385 struct FileSysNode *fn;
387 if (
388 (AROS_BE2LONG(buffer->fhb_ID) == IDNAME_FILESYSHEADER) &&
389 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->fhb_SummedLongs))==0)
392 fn = AllocMem(sizeof(struct FileSysNode), MEMF_PUBLIC | MEMF_CLEAR);
393 if (fn)
395 CopyMem(buffer, &fn->fhb, sizeof(struct FileSysHeaderBlock));
397 /* Fill in common part of the handle */
398 fn->h.ln.ln_Name = fn->fhb.fhb_FileSysName;
399 fn->h.ln.ln_Pri = 0;
400 fn->h.handler = &FilesystemRDB;
402 return fn;
405 return NULL;
408 static void PartitionRDBFreeFileSystem(struct FileSysHandle *fsh)
410 struct FileSysNode *fn = (struct FileSysNode *)fsh;
412 if (fn->filesystem)
413 FreeVec(fn->filesystem);
414 FreeMem(fn, sizeof(struct FileSysNode));
417 ULONG PartitionRDBCalcFSSize
419 struct Library *PartitionBase,
420 struct PartitionHandle *root,
421 struct FileSysNode *fn,
422 struct LoadSegBlock *buffer
425 ULONG size;
426 ULONG block;
428 size = 0;
429 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
430 while (block != (ULONG)-1)
432 size++;
433 if (readBlock(PartitionBase, root, block, buffer) !=0)
434 return 0;
435 if (
436 (AROS_BE2LONG(buffer->lsb_ID) != IDNAME_LOADSEG) ||
437 (calcChkSum((ULONG *)buffer, AROS_BE2LONG(buffer->lsb_SummedLongs)))
439 return 0;
440 block = AROS_BE2LONG(buffer->lsb_Next);
442 return size;
445 void PartitionRDBReadFileSys
447 struct Library *PartitionBase,
448 struct PartitionHandle *root,
449 struct FileSysNode *fn,
450 struct LoadSegBlock *buffer
453 ULONG size;
454 ULONG block;
456 size = PartitionRDBCalcFSSize(PartitionBase, root, fn, buffer);
457 if (size)
459 fn->fsblocks = size;
460 fn->filesystem = AllocVec(size*512, MEMF_PUBLIC);
461 if (fn->filesystem)
463 size = 0;
464 block = AROS_BE2LONG(fn->fhb.fhb_SegListBlocks);
465 while (block != (ULONG)-1)
467 if (readBlock(PartitionBase, root, block, &fn->filesystem[size]) !=0)
468 return;
469 block = AROS_BE2LONG(fn->filesystem[size].lsb_Next);
470 size++;
476 LONG PartitionRDBOpenPartitionTable
478 struct Library *PartitionBase,
479 struct PartitionHandle *root
482 UBYTE *buffer;
483 struct RDBData *data;
484 UBYTE i;
486 buffer = AllocVec(root->de.de_SizeBlock << 2, MEMF_PUBLIC);
487 if (!buffer)
488 return 1;
489 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC);
490 if (data)
492 for (i=0;i<RDB_LOCATION_LIMIT; i++)
494 if (readBlock(PartitionBase, root, i, buffer) != 0) {
495 FreeVec(buffer);
496 return 1;
498 CopyMem(buffer, &data->rdb, sizeof(struct RigidDiskBlock));
499 if (data->rdb.rdb_ID == AROS_BE2LONG(IDNAME_RIGIDDISK))
500 break;
502 if (i != RDB_LOCATION_LIMIT)
504 ULONG block;
506 data->rdbblock = i;
507 NEWLIST(&root->table->list);
508 NEWLIST(&data->badblocklist);
509 NEWLIST(&data->fsheaderlist);
510 root->table->data = data;
511 /* take the values of the rdb instead of TD_GEOMETRY */
512 root->dg.dg_SectorSize = AROS_BE2LONG(data->rdb.rdb_BlockBytes);
513 root->dg.dg_Cylinders = AROS_BE2LONG(data->rdb.rdb_Cylinders);
514 root->dg.dg_TrackSectors = AROS_BE2LONG(data->rdb.rdb_Sectors);
515 root->dg.dg_Heads = AROS_BE2LONG(data->rdb.rdb_Heads);
516 /* read bad blocks */
517 block = AROS_BE2LONG(data->rdb.rdb_BadBlockList);
518 while (block != (ULONG)-1)
520 struct BadBlockNode *bn;
522 if (readBlock(PartitionBase, root, block, buffer)==0)
524 bn = PartitionRDBNewBadBlock(PartitionBase, root, (struct BadBlockBlock *)buffer);
525 if (bn != NULL)
527 AddTail(&data->badblocklist, &bn->ln);
528 block = AROS_BE2LONG(bn->bbb.bbb_Next);
530 else
531 break;
533 else
534 break;
536 /* read partition blocks */
537 block = AROS_BE2LONG(data->rdb.rdb_PartitionList);
538 while (block != (ULONG)-1)
540 struct PartitionHandle *ph;
541 if (readBlock(PartitionBase, root, block, buffer)==0)
543 ph = PartitionRDBNewHandle(PartitionBase, root, (struct PartitionBlock *)buffer);
544 if (ph != NULL)
546 AddTail(&root->table->list, &ph->ln);
547 block = AROS_BE2LONG(((struct PartitionBlock *)ph->data)->pb_Next);
549 else
550 break;
552 else
553 break;
555 /* read filesystem blocks */
556 block = AROS_BE2LONG(data->rdb.rdb_FileSysHeaderList);
557 while (block != (ULONG)-1)
559 struct FileSysNode *fn;
561 if (readBlock(PartitionBase, root, block, buffer)==0)
563 fn = PartitionRDBNewFileSys(PartitionBase, root, (struct FileSysHeaderBlock *)buffer);
564 if (fn != NULL)
566 AddTail(&data->fsheaderlist, &fn->h.ln);
567 PartitionRDBReadFileSys(PartitionBase, root, fn, (struct LoadSegBlock *)buffer);
568 block = AROS_BE2LONG(fn->fhb.fhb_Next);
570 else
571 break;
573 else
574 break;
576 FreeVec(buffer);
577 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT) && defined(__mc68000)
578 AddFS(data);
579 #endif
580 return 0;
582 FreeMem(data, sizeof(struct RDBData));
584 FreeVec(buffer);
585 return 1;
588 void PartitionRDBFreeHandle
590 struct Library *PartitionBase,
591 struct PartitionHandle *ph
594 ClosePartitionTable(ph);
595 Remove(&ph->ln);
596 FreeMem(ph->data, sizeof(struct PartitionBlock));
597 FreeVec(ph->ln.ln_Name);
598 FreeMem(ph, sizeof(struct PartitionHandle));
601 void PartitionRDBClosePartitionTable
603 struct Library *PartitionBase,
604 struct PartitionHandle *root
607 struct PartitionHandle *ph;
608 struct BadBlockNode *bn;
609 struct FileSysNode *fn;
610 struct RDBData *data;
612 while ((ph = (struct PartitionHandle *)RemTail(&root->table->list)))
613 PartitionRDBFreeHandle(PartitionBase, ph);
614 data = (struct RDBData *)root->table->data;
615 while ((bn = (struct BadBlockNode *)RemTail(&data->badblocklist)))
616 FreeMem(bn, sizeof(struct BadBlockNode));
618 while ((fn = (struct FileSysNode *)RemTail(&data->fsheaderlist)))
620 /* Do not deallocate filesystem handles which are queued for loading */
621 if (!fn->h.boot)
622 PartitionRDBFreeFileSystem(&fn->h);
624 FreeMem(data, sizeof(struct RDBData));
627 ULONG PartitionRDBWriteFileSys
629 struct Library *PartitionBase,
630 struct PartitionHandle *root,
631 struct FileSysNode *fn,
632 ULONG block
635 ULONG size;
637 if (fn->filesystem)
639 size = 0;
640 while (size != fn->fsblocks)
642 fn->filesystem[size].lsb_Next = (size+1) != fn->fsblocks ? AROS_LONG2BE(block+1) : (ULONG)-1;
643 fn->filesystem[size].lsb_ChkSum = 0;
644 fn->filesystem[size].lsb_ChkSum = AROS_LONG2BE(0-calcChkSum((ULONG *)&fn->filesystem[size], AROS_LONG2BE(fn->filesystem[size].lsb_SummedLongs)));
645 #if RDB_WRITE
646 if (writeBlock(PartitionBase, root, block++, &fn->filesystem[size]) != 0)
647 return block;
648 #else
649 kprintf("RDB-write: block=%ld, type=LSEG\n", block);
650 block++;
651 #endif
652 size++;
655 return block;
658 static LONG PartitionRDBWritePartitionTable(struct Library *PartitionBase, struct PartitionHandle *root)
660 struct RDBData *data;
661 struct PartitionHandle *ph;
662 struct PartitionBlock *pblock;
663 struct BadBlockNode *bn;
664 struct FileSysNode *fn;
665 ULONG block;
667 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
668 return 0;
670 data = root->table->data;
671 block = data->rdbblock+1; /* RDB will be written at the end */
673 memset(root->buffer, 0, root->de.de_SizeBlock << 2);
675 /* write bad blocks */
676 bn = (struct BadBlockNode *)data->badblocklist.lh_Head;
677 if (bn->ln.ln_Succ)
678 data->rdb.rdb_BadBlockList = block;
679 else
680 data->rdb.rdb_BadBlockList = (ULONG)-1;
681 while (bn->ln.ln_Succ)
683 bn->bbb.bbb_Next = bn->ln.ln_Succ->ln_Succ ? AROS_LONG2BE(block+1) : (ULONG)-1;
684 bn->bbb.bbb_ChkSum = 0;
685 bn->bbb.bbb_ChkSum = AROS_LONG2BE(0-calcChkSum((ULONG *)&bn->bbb, AROS_BE2LONG(bn->bbb.bbb_SummedLongs)));
686 CopyMem(&bn->bbb, root->buffer, sizeof(struct BadBlockBlock));
687 #if RDB_WRITE
688 writeBlock(PartitionBase, root, block++, root->buffer);
689 #else
690 kprintf("RDB-write: block=%ld, type=BADB\n", block);
691 block++;
692 #endif
694 bn = (struct BadBlockNode *)bn->ln.ln_Succ;
697 /* write partition blocks */
698 ph = (struct PartitionHandle *)root->table->list.lh_Head;
699 if (ph->ln.ln_Succ)
700 data->rdb.rdb_PartitionList = AROS_LONG2BE(block);
701 else
702 data->rdb.rdb_PartitionList = (ULONG)-1;
703 while (ph->ln.ln_Succ)
705 pblock = (struct PartitionBlock *)ph->data;
706 pblock->pb_Next = ph->ln.ln_Succ->ln_Succ ? AROS_LONG2BE(block+1) : (ULONG)-1;
707 pblock->pb_ChkSum = 0;
708 pblock->pb_ChkSum = AROS_LONG2BE(0-calcChkSum((ULONG *)pblock, AROS_BE2LONG(pblock->pb_SummedLongs)));
709 CopyMem(pblock, root->buffer, sizeof(struct PartitionBlock));
710 #if RDB_WRITE
711 writeBlock(PartitionBase, root, block++, root->buffer);
712 #else
713 kprintf("RDB-write: block=%ld, type=PART\n", block);
714 block++;
715 #endif
716 ph = (struct PartitionHandle *)ph->ln.ln_Succ;
719 /* write filesystem blocks */
720 fn = (struct FileSysNode *)data->fsheaderlist.lh_Head;
721 if (fn->h.ln.ln_Succ)
722 data->rdb.rdb_FileSysHeaderList = AROS_LONG2BE(block);
723 else
724 data->rdb.rdb_FileSysHeaderList = (ULONG)-1;
725 while (fn->h.ln.ln_Succ)
727 ULONG fshblock;
729 fshblock = block;
730 block++; /* header block will be written later */
731 fn->fhb.fhb_SegListBlocks = AROS_LONG2BE(block);
732 /* write filesystem LSEG blocks */
733 block = PartitionRDBWriteFileSys(PartitionBase, root, fn, block);
734 fn->fhb.fhb_Next = fn->h.ln.ln_Succ->ln_Succ ? AROS_LONG2BE(block) : (ULONG)-1;
735 fn->fhb.fhb_ChkSum = 0;
736 CopyMem(&fn->fhb, root->buffer, sizeof(struct FileSysHeaderBlock));
737 ((struct FileSysHeaderBlock *)root->buffer)->fhb_ChkSum = AROS_LONG2BE(0-calcChkSum((ULONG *)root->buffer, AROS_BE2LONG(fn->fhb.fhb_SummedLongs)));
738 #if RDB_WRITE
739 writeBlock(PartitionBase, root, fshblock, root->buffer);
740 #else
741 kprintf("RDB-write: block=%ld, type=FSHD\n", fshblock);
742 #endif
743 fn = (struct FileSysNode *)fn->h.ln.ln_Succ;
745 data->rdb.rdb_HighRDSKBlock = AROS_LONG2BE(block-1);
746 data->rdb.rdb_ChkSum = 0;
747 data->rdb.rdb_ChkSum = AROS_LONG2BE(0-calcChkSum((ULONG *)&data->rdb, AROS_BE2LONG(data->rdb.rdb_SummedLongs)));
748 CopyMem(&data->rdb, root->buffer, sizeof(struct RigidDiskBlock));
749 #if RDB_WRITE
750 writeBlock(PartitionBase, root, data->rdbblock, root->buffer);
751 #else
752 kprintf("RDB-write: block=%ld, type=RDSK\n", data->rdbblock);
753 #endif
754 return 0;
757 LONG PartitionRDBCreatePartitionTable
759 struct Library *PartitionBase,
760 struct PartitionHandle *ph
763 struct RDBData *data;
764 ULONG i;
766 data = AllocMem(sizeof(struct RDBData), MEMF_PUBLIC | MEMF_CLEAR);
767 if (data)
769 ph->table->data = data;
770 data->rdb.rdb_ID = AROS_LONG2BE(IDNAME_RIGIDDISK);
771 data->rdb.rdb_SummedLongs = AROS_LONG2BE(sizeof(struct RigidDiskBlock)/4);
772 data->rdb.rdb_BlockBytes = AROS_LONG2BE(ph->dg.dg_SectorSize);
773 data->rdb.rdb_BadBlockList = (ULONG)-1;
774 data->rdb.rdb_PartitionList = (ULONG)-1;
775 data->rdb.rdb_FileSysHeaderList = (ULONG)-1;
776 data->rdb.rdb_DriveInit = (ULONG)-1;
777 for (i=0;i<6;i++)
778 data->rdb.rdb_Reserved1[i] = (ULONG)-1;
779 data->rdb.rdb_Cylinders = AROS_LONG2BE(ph->dg.dg_Cylinders);
780 data->rdb.rdb_Sectors = AROS_LONG2BE(ph->dg.dg_TrackSectors);
781 data->rdb.rdb_Heads = AROS_LONG2BE(ph->dg.dg_Heads);
783 data->rdb.rdb_Park = data->rdb.rdb_Cylinders;
784 data->rdb.rdb_WritePreComp = data->rdb.rdb_Cylinders;
785 data->rdb.rdb_ReducedWrite = data->rdb.rdb_Cylinders;
786 /* StepRate */
788 data->rdb.rdb_RDBBlocksLo = AROS_LONG2BE(1); /* leave a block for PC */
789 data->rdb.rdb_RDBBlocksHi = AROS_LONG2BE((ph->dg.dg_Heads*ph->dg.dg_TrackSectors*2)-1); /* two cylinders */
790 data->rdb.rdb_LoCylinder = AROS_LONG2BE(2);
791 data->rdb.rdb_HiCylinder = AROS_LONG2BE(ph->dg.dg_Cylinders-1);
792 data->rdb.rdb_CylBlocks = AROS_LONG2BE(ph->dg.dg_Heads*ph->dg.dg_TrackSectors);
793 /* AutoParkSeconds */
794 /* DiskVendor */
795 /* DiskProduct */
796 /* DiskRevision */
797 /* ControllerVendor */
798 /* ControllerProduct */
799 /* ControllerRevision */
801 data->rdbblock = 1;
802 NEWLIST(&data->badblocklist);
803 NEWLIST(&data->fsheaderlist);
804 NEWLIST(&ph->table->list);
805 return 0;
807 return 1;
810 static LONG PartitionRDBGetPartitionTableAttr(struct Library *PartitionBase, struct PartitionHandle *root, struct TagItem *tag)
812 switch (tag->ti_Tag)
814 case PTT_RESERVED:
815 *((LONG *)tag->ti_Data) = (root->de.de_Surfaces * root->de.de_BlocksPerTrack) << 1; /* 2 cylinders */
816 return TRUE;
819 return 0;
822 static LONG PartitionRDBGetPartitionAttr(struct Library *PartitionBase, struct PartitionHandle *ph, struct TagItem *tag)
824 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
826 switch (tag->ti_Tag)
828 case PT_TYPE:
829 *((ULONG *)tag->ti_Data) = AROS_LONG2BE(ph->de.de_DosType);
830 PTYPE(tag->ti_Data)->id_len = 4;
831 return TRUE;
833 case PT_BOOTABLE:
834 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_BOOTABLE) ? TRUE : FALSE;
835 return TRUE;
837 case PT_AUTOMOUNT:
838 *((LONG *)tag->ti_Data) = (AROS_BE2LONG(data->pb_Flags) & PBFF_NOMOUNT) ? FALSE : TRUE;
839 return TRUE;
842 return 0;
845 static LONG PartitionRDBSetPartitionAttrs(struct Library *PartitionBase, struct PartitionHandle *ph, const struct TagItem *taglist)
847 struct TagItem *tag;
848 struct PartitionBlock *data = (struct PartitionBlock *)ph->data;
850 while ((tag = NextTagItem(&taglist)))
852 switch (tag->ti_Tag)
854 case PT_DOSENVEC:
856 struct DosEnvec *de = (struct DosEnvec *)tag->ti_Data;
858 CopyMem(de, &ph->de, (de->de_TableSize+1)*sizeof(IPTR));
859 CopyHost2BEDosEnvec((SIPTR *)de, data->pb_Environment, de->de_TableSize+1);
861 break;
862 case PT_TYPE:
864 struct PartitionType *ptype=(struct PartitionType *)tag->ti_Data;
865 ULONG dt;
867 CopyMem(ptype->id, &dt, 4);
868 ph->de.de_DosType = AROS_BE2LONG(dt);
869 data->pb_Environment[DE_DOSTYPE] = dt;
871 break;
872 case PT_NAME:
874 STRPTR name = (STRPTR)tag->ti_Data;
875 ULONG len = strlen(name);
877 CopyMem(name, ph->ln.ln_Name, len+1);
878 CopyMem(name, data->pb_DriveName+1, len);
879 data->pb_DriveName[len+1] = 0;
880 data->pb_DriveName[0] = len;
882 break;
883 case PT_BOOTABLE:
884 if (tag->ti_Data)
885 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_BOOTABLE);
886 else
887 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_BOOTABLE);
888 break;
889 case PT_AUTOMOUNT:
890 if (tag->ti_Data)
891 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) & ~PBFF_NOMOUNT);
892 else
893 data->pb_Flags = AROS_LONG2BE(AROS_BE2LONG(data->pb_Flags) | PBFF_NOMOUNT);
894 break;
897 return 0;
900 struct PartitionHandle *PartitionRDBAddPartition(struct Library *PartitionBase, struct PartitionHandle *root, struct TagItem *taglist)
902 if (FindTagItem(PT_DOSENVEC, taglist) != NULL)
904 struct PartitionBlock *pblock;
905 struct PartitionHandle *ph;
906 struct PartitionHandle *oph;
908 ph = AllocMem(sizeof(struct PartitionHandle), MEMF_PUBLIC | MEMF_CLEAR);
909 if (ph)
911 ph->ln.ln_Name = AllocVec(32, MEMF_PUBLIC | MEMF_CLEAR);
912 if (ph->ln.ln_Name)
914 pblock = AllocMem(sizeof(struct PartitionBlock), MEMF_PUBLIC | MEMF_CLEAR);
915 if (pblock)
917 ph->root = root;
918 ph->bd = root->bd;
919 ph->data = pblock;
920 pblock->pb_ID = AROS_LONG2BE(IDNAME_PARTITION);
921 pblock->pb_SummedLongs = AROS_LONG2BE(sizeof(struct PartitionBlock)/4);
922 PartitionRDBSetPartitionAttrs(PartitionBase, ph, taglist);
923 oph = (struct PartitionHandle *)root->table->list.lh_Head;
924 while (oph->ln.ln_Succ)
926 if (ph->de.de_LowCyl<oph->de.de_LowCyl)
927 break;
928 oph = (struct PartitionHandle *)oph->ln.ln_Succ;
930 if (oph->ln.ln_Succ)
932 oph = (struct PartitionHandle *)oph->ln.ln_Pred;
933 if (oph->ln.ln_Pred)
935 Insert(&root->table->list, &ph->ln, &oph->ln);
937 else
938 AddHead(&root->table->list, &ph->ln);
940 else
941 AddTail(&root->table->list, &ph->ln);
942 if (FindTagItem(PT_DOSENVEC, taglist) == NULL)
944 ph->dg.dg_DeviceType = DG_DIRECT_ACCESS;
945 ph->dg.dg_SectorSize = ph->de.de_SizeBlock<<2;
946 ph->dg.dg_Heads = ph->de.de_Surfaces;
947 ph->dg.dg_TrackSectors = ph->de.de_BlocksPerTrack;
948 ph->dg.dg_Cylinders = ph->de.de_HighCyl - ph->de.de_LowCyl + 1;
949 ph->dg.dg_BufMemType = ph->de.de_BufMemType;
951 return ph;
953 FreeVec(ph->ln.ln_Name);
955 FreeMem(ph, sizeof(struct PartitionHandle));
958 return NULL;
961 void PartitionRDBDeletePartition
963 struct Library *PartitionBase,
964 struct PartitionHandle *ph
968 PartitionRDBFreeHandle(PartitionBase, ph);
971 const struct PartitionAttribute PartitionRDBPartitionTableAttrs[]=
973 {PTT_TYPE, PLAM_READ},
974 {PTT_RESERVED, PLAM_READ},
975 {TAG_DONE, 0}
978 const struct PartitionAttribute PartitionRDBPartitionAttrs[]=
980 /* TODO: implement write */
981 {PT_GEOMETRY, PLAM_READ},
982 {PT_DOSENVEC, PLAM_READ | PLAM_WRITE},
983 {PT_TYPE, PLAM_READ | PLAM_WRITE},
984 {PT_NAME, PLAM_READ | PLAM_WRITE},
985 {PT_BOOTABLE, PLAM_READ | PLAM_WRITE},
986 {PT_AUTOMOUNT, PLAM_READ | PLAM_WRITE},
987 {TAG_DONE, 0}
990 ULONG PartitionRDBDestroyPartitionTable
992 struct Library *PartitionBase,
993 struct PartitionHandle *root
996 struct RDBData *data;
998 if (sizeof(root->buffer) < (root->de.de_SizeBlock << 2))
999 return 0;
1001 data = root->table->data;
1002 CopyMem(&data->rdb, root->buffer, sizeof(struct RigidDiskBlock));
1003 ((struct RigidDiskBlock *)root->buffer)->rdb_ID = 0;
1004 if (writeBlock(PartitionBase, root, data->rdbblock, root->buffer))
1005 return 1;
1006 return 0;
1009 struct Node *PartitionRDBFindFileSystem(struct Library *PartitionBase, struct PartitionHandle *ph, struct TagItem *tags)
1011 struct RDBData *data = (struct RDBData *)ph->table->data;
1012 struct FileSysNode *fn;
1013 struct TagItem *idTag = FindTagItem(FST_ID , tags);
1014 struct TagItem *nameTag = FindTagItem(FST_NAME, tags);
1016 for (fn = (struct FileSysNode *)data->fsheaderlist.lh_Head; fn->h.ln.ln_Succ;
1017 fn = (struct FileSysNode *)fn->h.ln.ln_Succ)
1019 if (idTag)
1021 if (fn->fhb.fhb_ID != idTag->ti_Data)
1022 continue;
1025 if (nameTag)
1027 if (strcmp(fn->fhb.fhb_FileSysName, (char *)nameTag->ti_Data))
1028 continue;
1031 return &fn->h.ln;
1034 return NULL;
1037 BPTR PartitionRDBLoadFileSystem(struct PartitionBase_intern *PartitionBase, struct FileSysHandle *fn)
1039 if (PartitionBase->pb_DOSBase)
1040 return LoadFS((struct FileSysNode *)fn, (struct DosLibrary *)PartitionBase->pb_DOSBase);
1041 else
1042 return BNULL;
1045 static LONG PartitionRDBGetFileSystemAttr(struct Library *PartitionBase, struct FileSysHandle *fn, const struct TagItem *tag)
1047 struct FileSysEntry *fse;
1048 struct FileSysHeaderBlock *fhb = &((struct FileSysNode *)fn)->fhb;
1050 switch (tag->ti_Tag)
1052 case FST_ID:
1053 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_DosType);
1054 return TRUE;
1056 case FST_NAME:
1057 *((STRPTR *)tag->ti_Data) = fhb->fhb_FileSysName;
1058 return TRUE;
1060 case FST_FSENTRY:
1061 fse = (struct FileSysEntry *)tag->ti_Data;
1063 /* RDB filesystems are not prioritized */
1064 fse->fse_Node.ln_Pri = 0;
1067 * Don't use CopyMem() or something like that.
1068 * First, you need to deal with endianess.
1069 * Second, some things are actually pointers, you need
1070 * to sign-extend them on 64 bits.
1072 fse->fse_DosType = AROS_BE2LONG(fhb->fhb_DosType);
1073 fse->fse_Version = AROS_BE2LONG(fhb->fhb_Version);
1074 fse->fse_PatchFlags = AROS_BE2LONG(fhb->fhb_PatchFlags);
1075 fse->fse_Type = AROS_BE2LONG(fhb->fhb_Type);
1076 fse->fse_Task = AROS_BE2LONG(fhb->fhb_Task);
1077 fse->fse_Lock = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Lock);
1078 /* Just for convenience. This is expected to be zero. */
1079 fse->fse_Handler = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Handler);
1080 fse->fse_StackSize = AROS_BE2LONG(fhb->fhb_StackSize);
1081 fse->fse_Priority = AROS_BE2LONG(fhb->fhb_Priority);
1082 fse->fse_Startup = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_Startup);
1083 /* Skip fse_SegList */
1084 fse->fse_GlobalVec = (BPTR)(SIPTR)AROS_BE2LONG(fhb->fhb_GlobalVec);
1085 return TRUE;
1087 case FST_VERSION:
1088 *((ULONG *)tag->ti_Data) = AROS_BE2LONG(fhb->fhb_Version);
1089 return TRUE;
1092 return 0;
1095 const struct PTFunctionTable PartitionRDB =
1097 PHPTT_RDB,
1098 "RDB",
1099 PartitionRDBCheckPartitionTable,
1100 PartitionRDBOpenPartitionTable,
1101 PartitionRDBClosePartitionTable,
1102 PartitionRDBWritePartitionTable,
1103 PartitionRDBCreatePartitionTable,
1104 PartitionRDBAddPartition,
1105 PartitionRDBDeletePartition,
1106 PartitionRDBGetPartitionTableAttr,
1107 NULL,
1108 PartitionRDBGetPartitionAttr,
1109 PartitionRDBSetPartitionAttrs,
1110 PartitionRDBPartitionTableAttrs,
1111 PartitionRDBPartitionAttrs,
1112 PartitionRDBDestroyPartitionTable,
1113 PartitionRDBFindFileSystem
1116 const struct FSFunctionTable FilesystemRDB =
1118 PartitionRDBLoadFileSystem,
1119 PartitionRDBGetFileSystemAttr,
1120 PartitionRDBFreeFileSystem