|
|
1.1 root 1: #ifdef FSYS_AFFS
2: #include "shared.h"
3: #include "filesys.h"
4:
5: /******************************** RDB definitions */
6: #define RDB_LOCATION_LIMIT 16
7: #define IDNAME_RIGIDDISK 0x5244534B /* 'RDSK' */
8:
9: struct RigidDiskBlock
10: {
11: unsigned long rdb_ID;
12: unsigned long rdb_SummedLongs;
13: long rdb_ChkSum;
14: unsigned long rdb_HostID;
15: unsigned long rdb_BlockBytes;
16: unsigned long rdb_Flags;
17: unsigned long rdb_BadBlockList;
18: unsigned long rdb_PartitionList;
19: unsigned long rdb_FileSysHeaderList;
20: unsigned long rdb_DriveInit;
21: unsigned long rdb_Reserved1[6];
22: unsigned long rdb_Cylinders;
23: unsigned long rdb_Sectors;
24: unsigned long rdb_Heads;
25: unsigned long rdb_Interleave;
26: unsigned long rdb_Park;
27: unsigned long rdb_Reserved2[3];
28: unsigned long rdb_WritePreComp;
29: unsigned long rdb_ReducedWrite;
30: unsigned long rdb_StepRate;
31: unsigned long rdb_Reserved3[5];
32: unsigned long rdb_RDBBlocksLo;
33: unsigned long rdb_RDBBlocksHi;
34: unsigned long rdb_LoCylinder;
35: unsigned long rdb_HiCylinder;
36: unsigned long rdb_CylBlocks;
37: unsigned long rdb_AutoParkSeconds;
38: unsigned long rdb_HighRDSKBlock;
39: unsigned long rdb_Reserved4;
40: char rdb_DiskVendor[8];
41: char rdb_DiskProduct[16];
42: char rdb_DiskRevision[4];
43: char rdb_ControllerVendor[8];
44: char rdb_ControllerProduct[16];
45: char rdb_ControllerRevision[4];
46: char rdb_DriveInitName[40];
47: };
48:
49: struct PartitionBlock
50: {
51: unsigned long pb_ID;
52: unsigned long pb_SummedLongs;
53: long pb_ChkSum;
54: unsigned long pb_HostID;
55: unsigned long pb_Next;
56: unsigned long pb_Flags;
57: unsigned long pb_Reserved1[2];
58: unsigned long pb_DevFlags;
59: char pb_DriveName[32];
60: unsigned long pb_Reserved2[15];
61: unsigned long pb_Environment[20];
62: unsigned long pb_EReserved[12];
63: };
64:
65: #define DE_TABLESIZE 0
66: #define DE_SIZEBLOCK 1
67: #define DE_BLOCKSIZE 2
68: #define DE_NUMHEADS 3
69: #define DE_SECSPERBLOCK 4
70: #define DE_BLKSPERTRACK 5
71: #define DE_RESERVEDBLKS 6
72: #define DE_PREFAC 7
73: #define DE_INTERLEAVE 8
74: #define DE_LOWCYL 9
75: #define DE_HIGHCYL 10
76: #define DE_UPPERCYL DE_HIGHCYL
77: #define DE_NUMBUFFERS 11
78: #define DE_BUFMEMTYPE 12
79: #define DE_MEMBUFTYPE DE_BUFMEMTYPE
80: #define DE_MAXTRANSFER 13
81: #define DE_MASK 14
82: #define DE_BOOTPRI 15
83: #define DE_DOSTYPE 16
84: #define DE_BAUD 17
85: #define DE_CONTROL 18
86: #define DE_BOOTBLOCKS 19
87:
88:
89: /******************************** AFFS definitions */
90: #define T_SHORT 2
91: #define T_LIST 16
92:
93: #define ST_FILE -3
94: #define ST_ROOT 1
95: #define ST_USERDIR 2
96:
97: struct BootBlock{
98: int id;
99: int chksum;
100: int rootblock;
101: int data[127];
102: };
103:
104: struct RootBlock{
105: int p_type; //0
106: int n1[2]; //1-2
107: int hashtable_size; //3
108: int n2; //4
109: int checksum; //5
110: int hashtable[72]; //6-77
111: int bitmap_valid_flag; //78
112: int bitmap_ptrs[25]; //79-103
113: int bitmap_extension; //104
114: int root_days; //105
115: int root_mins; //106
116: int root_ticks; //107;
117: char diskname[32]; //108-115
118: int n3[2]; //116-117
119: int volume_days; //118
120: int volume_mins; //119
121: int volume_ticks; //120
122: int creation_days; //121
123: int creation_mins; //122
124: int creation_ticks; //123
125: int n4[3]; //124-126
126: int s_type; //127
127: };
128:
129: struct DirHeader {
130: int p_type; //0
131: int own_key; //1
132: int n1[3]; //2-4
133: int checksum; //5
134: int hashtable[72]; //6-77
135: int n2; //78
136: int owner; //79
137: int protection; //80
138: int n3; //81
139: char comment[92]; //82-104
140: int days; //105
141: int mins; //106
142: int ticks; //107
143: char name[32]; //108-115
144: int n4[2]; //116-117
145: int linkchain; //118
146: int n5[5]; //119-123
147: int hashchain; //124
148: int parent; //125
149: int n6; //126
150: int s_type; //127
151: };
152:
153: struct FileHeader {
154: int p_type; //0
155: int own_key; //1
156: int n1[3]; //2-4
157: int checksum; //5
158: int filekey_table[72]; //6-77
159: int n2; //78
160: int owner; //79
161: int protection; //80
162: int bytesize; //81
163: char comment[92]; //82-104
164: int days; //105
165: int mins; //106
166: int ticks; //107
167: char name[32]; //108-115
168: int n3[2]; //116-117
169: int linkchain; //118
170: int n4[5]; //119-123
171: int hashchain; //124
172: int parent; //125
173: int extension; //126
174: int s_type; //127
175: };
176:
177: struct FileKeyExtension{
178: int p_type; //0
179: int own_key; //1
180: int table_size; //2
181: int n1[2]; //3-4
182: int checksum; //5
183: int filekey_table[72]; //6-77
184: int info[46]; //78-123
185: int n2; //124
186: int parent; //125
187: int extension; //126
188: int s_type; //127
189: };
190:
191: struct Position {
192: unsigned int block;
193: short filekey;
194: unsigned short byte;
195: unsigned int offset;
196: };
197:
198: struct ReadData {
199: unsigned int header_block;
200: struct Position current;
201: unsigned int filesize;
202: };
203:
204: //#warning "Big vs. little endian for configure needed"
205: #define AROS_BE2LONG(l) \
206: ( \
207: ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
208: ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \
209: ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \
210: ((((unsigned long)(l)) << 24) & 0xFF000000UL) \
211: )
212:
213: struct CacheBlock {
214: int blocknum;
215: unsigned short flags;
216: unsigned short access_count;
217: unsigned int blockbuffer[128];
218: };
219: #define LockBuffer(x) (((struct CacheBlock *)(x))->flags |= 0x0001)
220: #define UnLockBuffer(x) (((struct CacheBlock *)(x))->flags &= ~0x0001)
221:
222: #define MAX_CACHE_BLOCKS 10
223:
224: struct FSysBuffer {
225: struct ReadData file;
226: struct CacheBlock blocks[MAX_CACHE_BLOCKS];
227: };
228:
229: #define bootBlock(x) ((struct BootBlock *)(x)->blockbuffer)
230: #define rootBlock(x) ((struct RootBlock *)(x)->blockbuffer)
231: #define dirHeader(x) ((struct DirHeader *)(x)->blockbuffer)
232: #define fileHeader(x) ((struct FileHeader *)(x)->blockbuffer)
233: #define extensionBlock(x) ((struct FileKeyExtension *)(x)->blockbuffer)
234:
235: #define rdsk(x) ((struct RigidDiskBlock *)(x)->blockbuffer)
236: #define part(x) ((struct PartitionBlock *)(x)->blockbuffer)
237:
238: static struct FSysBuffer *fsysb;
239: static int blockoffset; /* offset if there is an embedded RDB partition */
240: static int rootb; /* block number of root block */
241: static int rdbb; /* block number of rdb block */
242:
243: static void initCache(void)
244: {
245: int i;
246:
247: for (i=0;i<MAX_CACHE_BLOCKS;i++)
248: {
249: fsysb->blocks[i].blocknum = -1;
250: fsysb->blocks[i].flags = 0;
251: fsysb->blocks[i].access_count = 0;
252: }
253: }
254:
255: static struct CacheBlock *getBlock(unsigned int block)
256: {
257: struct CacheBlock *freeblock;
258: int i;
259:
260: /* get first unlocked block */
261: i = 0;
262: do
263: {
264: freeblock = &fsysb->blocks[i++];
265: } while (freeblock->flags & 0x0001);
266: /* search through list if block is already loaded in */
267: for (i=0;i<MAX_CACHE_BLOCKS;i++)
268: {
269: if (fsysb->blocks[i].blocknum == block)
270: {
271: fsysb->blocks[i].access_count++;
272: return &fsysb->blocks[i];
273: }
274: if (!(fsysb->blocks[i].flags & 0x0001))
275: if (freeblock->access_count>fsysb->blocks[i].access_count)
276: freeblock = &fsysb->blocks[i];
277: }
278: freeblock->blocknum = block;
279: devread(block+blockoffset, 0, 512, (char *)freeblock->blockbuffer);
280: return freeblock;
281: }
282:
283: static unsigned int calcChkSum(unsigned short SizeBlock, unsigned int *buffer)
284: {
285: unsigned int sum=0,count=0;
286:
287: for (count=0;count<SizeBlock;count++)
288: sum += AROS_BE2LONG(buffer[count]);
289: return sum;
290: }
291:
292: int affs_mount(void) {
293: struct CacheBlock *cblock;
294: int i;
295:
296: if (
297: (current_drive & 0x80) &&
298: (current_partition != 0xFFFFFF) &&
299: (current_slice != 0x30)
300: )
301: return 0;
302: fsysb = (struct FSysBuffer *)FSYS_BUF;
303: blockoffset = 0;
304: initCache();
305: /* check for rdb partitiontable */
306: for (i=0;i<RDB_LOCATION_LIMIT;i++)
307: {
308: cblock = getBlock(i);
309: if (
310: (
311: ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFFFFFF00)==0x444F5300) &&
312: ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFF)>0)
313: ) ||
314: (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
315: )
316: break;
317: }
318: if (i == RDB_LOCATION_LIMIT)
319: return 0;
320: if (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
321: {
322: /* we have an RDB partition table within a MBR-Partition */
323: rdbb = i;
324: }
325: else if (i<2)
326: {
327: /* partition type is 0x30 = AROS and AFFS formatted */
328: rdbb = RDB_LOCATION_LIMIT;
329: rootb = (part_length-1+2)/2;
330: cblock = getBlock(rootb);
331: if (
332: (AROS_BE2LONG(rootBlock(cblock)->p_type) != T_SHORT) ||
333: (AROS_BE2LONG(rootBlock(cblock)->s_type) != ST_ROOT) ||
334: calcChkSum(128, cblock->blockbuffer)
335: )
336: return 0;
337: }
338: else
339: return 0;
340: return 1;
341: }
342:
343: static int seek(unsigned long offset)
344: {
345: struct CacheBlock *cblock;
346: unsigned long block;
347: unsigned long togo;
348:
349: block = fsysb->file.header_block;
350:
351: togo = offset / 512;
352: fsysb->file.current.filekey = 71-(togo % 72);
353: togo /= 72;
354: fsysb->file.current.byte = offset % 512;
355: fsysb->file.current.offset = offset;
356: while ((togo) && (block))
357: {
358: disk_read_func = disk_read_hook;
359: cblock = getBlock(block);
360: disk_read_func = NULL;
361: block = AROS_BE2LONG(extensionBlock(cblock)->extension);
362: togo--;
363: }
364: if (togo)
365: return 1;
366: fsysb->file.current.block = block;
367: return 0;
368: }
369:
370: int affs_read(char *buf, int len) {
371: struct CacheBlock *cblock;
372: unsigned short size;
373: unsigned int readbytes = 0;
374:
375: if (fsysb->file.current.offset != filepos)
376: {
377: if (seek(filepos))
378: return ERR_FILELENGTH;
379: }
380: if (fsysb->file.current.block == 0)
381: return 0;
382: if (len>(fsysb->file.filesize-fsysb->file.current.offset))
383: len=fsysb->file.filesize-fsysb->file.current.offset;
384: disk_read_func = disk_read_hook;
385: cblock = getBlock(fsysb->file.current.block);
386: disk_read_func = NULL;
387: while (len)
388: {
389: disk_read_func = disk_read_hook;
390: if (fsysb->file.current.filekey<0)
391: {
392: fsysb->file.current.filekey = 71;
393: fsysb->file.current.block = AROS_BE2LONG(extensionBlock(cblock)->extension);
394: if (fsysb->file.current.block)
395: {
396: cblock = getBlock(fsysb->file.current.block);
397: }
398: //#warning "else shouldn't occour"
399: }
400: size = 512;
401: size -= fsysb->file.current.byte;
402: if (size>len)
403: {
404: size = len;
405: devread
406: (
407: AROS_BE2LONG
408: (
409: extensionBlock(cblock)->filekey_table
410: [fsysb->file.current.filekey]
411: )+blockoffset,
412: fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
413: );
414: fsysb->file.current.byte += size;
415: }
416: else
417: {
418: devread
419: (
420: AROS_BE2LONG
421: (
422: extensionBlock(cblock)->filekey_table
423: [fsysb->file.current.filekey]
424: )+blockoffset,
425: fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
426: );
427: fsysb->file.current.byte = 0;
428: fsysb->file.current.filekey--;
429: }
430: disk_read_func = NULL;
431: len -= size;
432: readbytes += size;
433: }
434: fsysb->file.current.offset += readbytes;
435: filepos = fsysb->file.current.offset;
436: return readbytes;
437: }
438:
439: static unsigned char capitalch(unsigned char ch, unsigned char flags)
440: {
441:
442: if ((flags==0) || (flags==1))
443: return (unsigned char)((ch>='a') && (ch<='z') ? ch-('a'-'A') : ch);
444: else // DOS\(>=2)
445: return (unsigned char)(((ch>=224) && (ch<=254) && (ch!=247)) ||
446: ((ch>='a') && (ch<='z')) ? ch-('a'-'A') : ch);
447: }
448:
449: // str2 is a BCPL string
450: static int noCaseStrCmp(char *str1, char *str2, unsigned char flags)
451: {
452: unsigned char length;
453:
454: length=str2++[0];
455: do {
456: if ((*str1==0) && (length==0))
457: return 0;
458: length--;
459: // if ((*str1==0) && (*str2==0)) return 1;
460: } while (capitalch(*str1++,flags)==capitalch(*str2++,flags));
461: str1--;
462: return (*str1) ? 1 : -1;
463: }
464:
465: static unsigned int getHashKey(char *name,unsigned int tablesize, unsigned char flags)
466: {
467: unsigned int length;
468:
469: length=0;
470: while (name[length] != 0)
471: length++;
472: while (*name!=0)
473: length=(length * 13 +capitalch(*name++,flags)) & 0x7FF;
474: return length%tablesize;
475: }
476:
477: static grub_error_t getHeaderBlock(char *name, struct CacheBlock **dirh)
478: {
479: int key;
480:
481: key = getHashKey(name, 72, 1);
482: if (!dirHeader(*dirh)->hashtable[key])
483: return ERR_FILE_NOT_FOUND;
484: *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashtable[key]));
485: if (calcChkSum(128, (*dirh)->blockbuffer))
486: {
487: #ifdef DEBUG_AFFS
488: printf("ghb: %d\n", (*dirh)->blocknum);
489: #endif
490: return ERR_FSYS_CORRUPT;
491: }
492: if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
493: return ERR_BAD_FILETYPE;
494: while (noCaseStrCmp(name,dirHeader(*dirh)->name,1) != 0)
495: {
496: if (!dirHeader(*dirh)->hashchain)
497: return ERR_FILE_NOT_FOUND;
498: *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashchain));
499: if (calcChkSum(128, (*dirh)->blockbuffer))
500: {
501: #ifdef DEBUG_AFFS
502: printf("ghb2: %d\n", (*dirh)->blocknum);
503: #endif
504: return ERR_FSYS_CORRUPT;
505: }
506: if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
507: return ERR_BAD_FILETYPE;
508: }
509: return 0;
510: }
511:
512: static char *copyPart(char *src, char *dst)
513: {
514: while ((*src != '/') && (*src))
515: *dst++ = *src++;
516: if (*src == '/')
517: src++;
518: *dst-- = 0;
519: /* cut off spaces at the end */
520: while (*dst == ' ')
521: *dst-- = 0;
522: return src;
523: }
524:
525: static grub_error_t findBlock(char *name, struct CacheBlock **dirh)
526: {
527: char dname[32];
528: int block;
529:
530: name++; /* skip "/" */
531: /* partition table part */
532: if (rdbb < RDB_LOCATION_LIMIT)
533: {
534: int bpc;
535:
536: blockoffset = 0;
537: *dirh = getBlock(rdbb);
538: if (*name==0)
539: return 0;
540: name = copyPart(name, dname);
541: bpc = AROS_BE2LONG(rdsk(*dirh)->rdb_Sectors)*AROS_BE2LONG(rdsk(*dirh)->rdb_Heads);
542: block = AROS_BE2LONG(rdsk(*dirh)->rdb_PartitionList);
543: while (block != -1)
544: {
545: *dirh = getBlock(block);
546: if (noCaseStrCmp(dname, part(*dirh)->pb_DriveName, 1) == 0)
547: break;
548: block = AROS_BE2LONG(part(*dirh)->pb_Next);
549: }
550: if (block == -1)
551: return ERR_FILE_NOT_FOUND;
552: if (
553: ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFFFFFF00)!=0x444F5300) ||
554: ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFF)==0)
555: )
556: return ERR_BAD_FILETYPE;
557: blockoffset = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_LOWCYL]);
558: rootb = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_HIGHCYL]);
559: rootb = rootb-blockoffset+1; /* highcyl-lowcyl+1 */
560: rootb *= bpc;
561: rootb = rootb-1+AROS_BE2LONG(part(*dirh)->pb_Environment[DE_RESERVEDBLKS]);
562: rootb /= 2;
563: blockoffset *= bpc;
564: }
565:
566: /* filesystem part */
567: *dirh = getBlock(rootb);
568: while (*name)
569: {
570: if (
571: (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_ROOT) &&
572: (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_USERDIR)
573: )
574: return ERR_BAD_FILETYPE;
575: name = copyPart(name, dname);
576: errnum = getHeaderBlock(dname, dirh);
577: if (errnum)
578: return errnum;
579: }
580: return 0;
581: }
582:
583: #ifndef STAGE1_5
584: static void checkPossibility(char *filename, char *bstr)
585: {
586: char cstr[32];
587:
588: if (noCaseStrCmp(filename, bstr, 1)<=0)
589: {
590: if (print_possibilities>0)
591: print_possibilities = -print_possibilities;
592: memcpy(cstr, bstr+1, bstr[0]);
593: cstr[bstr[0]]=0;
594: print_a_completion(cstr);
595: }
596: }
597: #else
598: #define checkPossibility(a, b) do { } while(0)
599: #endif
600:
601: int affs_dir(char *dirname)
602: {
603: struct CacheBlock *buffer1;
604: struct CacheBlock *buffer2;
605: char *current = dirname;
606: char filename[128];
607: char *fname = filename;
608: int i,block;
609:
610: if (print_possibilities)
611: {
612: while (*current)
613: current++;
614: while (*current != '/')
615: current--;
616: current++;
617: while (*current)
618: {
619: *fname++ = *current;
620: *current++ = 0;
621: }
622: *fname=0;
623: errnum = findBlock(dirname, &buffer1);
624: if (errnum)
625: return 0;
626: if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == IDNAME_RIGIDDISK)
627: {
628: block = AROS_BE2LONG(rdsk(buffer1)->rdb_PartitionList);
629: while (block != -1)
630: {
631: buffer1 = getBlock(block);
632: checkPossibility(filename, part(buffer1)->pb_DriveName);
633: block = AROS_BE2LONG(part(buffer1)->pb_Next);
634: }
635: #ifndef STAGE1_5
636: if (*filename == 0)
637: if (print_possibilities>0)
638: print_possibilities = -print_possibilities;
639: #endif
640: }
641: else if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == T_SHORT)
642: {
643: LockBuffer(buffer1);
644: for (i=0;i<72;i++)
645: {
646: block = dirHeader(buffer1)->hashtable[i];
647: while (block)
648: {
649: buffer2 = getBlock(AROS_BE2LONG(block));
650: if (calcChkSum(128, buffer2->blockbuffer))
651: {
652: errnum = ERR_FSYS_CORRUPT;
653: return 0;
654: }
655: if (AROS_BE2LONG(dirHeader(buffer2)->p_type) != T_SHORT)
656: {
657: errnum = ERR_BAD_FILETYPE;
658: return 0;
659: }
660: checkPossibility(filename, dirHeader(buffer2)->name);
661: block = dirHeader(buffer2)->hashchain;
662: }
663: }
664: UnLockBuffer(buffer1);
665: #ifndef STAGE1_5
666: if (*filename == 0)
667: if (print_possibilities>0)
668: print_possibilities = -print_possibilities;
669: #endif
670: }
671: else
672: {
673: errnum = ERR_BAD_FILETYPE;
674: return 0;
675: }
676: while (*current != '/')
677: current--;
678: current++;
679: fname = filename;
680: while (*fname)
681: *current++ = *fname++;
682: //#warning "TODO: add some more chars until possibilities differ"
683: if (print_possibilities>0)
684: errnum = ERR_FILE_NOT_FOUND;
685: return (print_possibilities<0);
686: }
687: else
688: {
689: while (*current && !isspace(*current))
690: *fname++ = *current++;
691: *fname = 0;
692:
693: errnum = findBlock(filename, &buffer2);
694: if (errnum)
695: return 0;
696: if (AROS_BE2LONG(fileHeader(buffer2)->s_type)!=ST_FILE)
697: {
698: errnum = ERR_BAD_FILETYPE;
699: return 0;
700: }
701: fsysb->file.header_block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
702: fsysb->file.current.block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
703: fsysb->file.current.filekey = 71;
704: fsysb->file.current.byte = 0;
705: fsysb->file.current.offset = 0;
706: fsysb->file.filesize = AROS_BE2LONG(fileHeader(buffer2)->bytesize);
707: filepos = 0;
708: filemax = fsysb->file.filesize;
709: return 1;
710: }
711: }
712: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.