00001 00005 #include "board.h" 00006 #include "filesys.h" 00007 #include "storage.h" 00008 #include "console.h" 00009 #include "mmc.h" 00010 00011 00012 /* This needs display to put file name directly to display buffer */ 00013 /* It's not pretty but it saves a lot of memory! */ 00014 #include "display.h" 00015 00016 00017 00021 data unsigned long fatStart; 00022 00024 data unsigned long rootStart; 00025 00029 data unsigned long dataStart; 00030 00032 data unsigned char fatSectorsPerCluster; 00033 00034 00035 00037 #define MAX_NUMBER_FRAGMENTS 10 00038 00039 00041 xdata struct fragmentEntry { 00042 unsigned long start; 00043 unsigned long length; 00044 } fragment[MAX_NUMBER_FRAGMENTS]; 00045 00047 xdata unsigned long fileSize; 00048 00050 #define MAX_NUMBER_SUBDIRECTORIES 5 00051 00053 xdata struct directoryStack { 00054 unsigned long sector; 00055 unsigned char entry; 00056 } dirStack[MAX_NUMBER_SUBDIRECTORIES]; 00057 00059 xdata unsigned char dirLevel = 0; 00060 00062 xdata unsigned long freeSector = 0; 00063 00065 xdata char currentFileName[12]; 00066 00068 bit IS_FAT_12 = 0; 00069 00070 00072 void PConvertSectorToCluster(unsigned long *sector){ 00073 *sector-=dataStart; 00074 *sector/=fatSectorsPerCluster; 00075 } 00076 00078 void PConvertClusterToSector(unsigned long *cluster){ 00079 *cluster*=fatSectorsPerCluster; 00080 *cluster+=dataStart; 00081 } 00082 00083 00085 unsigned long GetFatEntry(unsigned long clusterNumber){ 00086 unsigned char entryNumber; /* entry number inside page */ 00087 00088 if (!IS_FAT_32){ //FAT16 00089 entryNumber = clusterNumber & 0xff; 00090 clusterNumber >>= 8; 00091 }else{ //FAT32 00092 entryNumber = clusterNumber & 0x7f; 00093 clusterNumber >>= 7; 00094 } 00095 clusterNumber += fatStart; 00096 if (sectorAddress.l != clusterNumber){ 00097 sectorAddress.l = clusterNumber; 00098 ReadDiskSector(sectorAddress.l); 00099 } 00100 if (IS_FAT_32){ 00101 clusterNumber=diskSect.Fat32Table[entryNumber]; 00102 return clusterNumber; 00103 } 00104 if ((clusterNumber=diskSect.Fat16Table[entryNumber])==0xffff) return 0xffffffff; 00105 return clusterNumber; 00106 } 00107 00108 00109 00110 00129 void WriteClusterChain(){ 00130 00131 xdata unsigned long currentCluster; //is now fragment[0].start 00132 xdata unsigned long fragSize; //is now fragment[0].length 00133 xdata unsigned long fatPageSector; 00134 xdata unsigned char entryNumber; 00135 00136 00137 // PREPARE 00138 00139 // Calculate starting cluster number... 00140 currentCluster = fragment[0].start; 00141 PConvertSectorToCluster(¤tCluster); 00142 00143 fragSize = fragment[0].length; //size in sectors 00144 00145 // Write cluster number and size in bytes to fragment[0] 00146 // for the function that registers directory entries 00147 fragment[0].start = currentCluster; 00148 fragment[0].length *= 512; 00149 00150 // Locate the relevant page in FAT clusterchain records 00151 fatPageSector = currentCluster; 00152 if (!IS_FAT_32){ //FAT16 00153 entryNumber = fatPageSector & 0xff; 00154 fatPageSector >>= 8; 00155 }else{ //FAT32 00156 entryNumber = fatPageSector & 0x7f; 00157 fatPageSector >>= 7; 00158 } 00159 fatPageSector += fatStart; 00160 00161 ConsoleWrite("Writing clusterchain from: "); ConsolePutUInt(currentCluster); 00162 ConsoleWrite("Fragment size (sectors): "); ConsolePutUInt(fragSize); 00163 ConsoleWrite("FatPageSector: "); ConsolePutUInt(fatPageSector); 00164 ConsoleWrite("EntryNumber: "); ConsolePutUInt(entryNumber); 00165 00166 00167 // WRITE CLUSTER CHAIN TO FIRST FAT 00168 00169 while (fragSize>fatSectorsPerCluster){ 00170 // while more than 1 cluster left... 00171 00172 // is the FAT clusterchain page changed? 00173 if (sectorAddress.l != fatPageSector){ 00174 // Yes, have we advanced by 1 sector? 00175 if (sectorAddress.l == (fatPageSector - 1)){ 00176 //Yes, we must save the edited sector 00177 WriteDiskSector (sectorAddress.l); 00179 } 00180 // at least we need to load the new clusterchain page 00181 sectorAddress.l = fatPageSector; 00182 ReadDiskSector(sectorAddress.l); 00183 }//Load/Save FAT sector 00184 00185 00186 // Register Middle Entry 00187 currentCluster++; //advancce to next cluster 00188 00189 //fragSize-=fatSectorsPerCluster; //we will register one cluster 00190 //to avoid memory spill in C compiler, the preceding line is written as: 00191 for (temp.c = fatSectorsPerCluster;temp.c;temp.c--){ 00192 fragSize--; 00193 } 00194 00195 if (IS_FAT_32){ 00196 diskSect.Fat32Table[entryNumber]=currentCluster; 00197 }else{ 00198 diskSect.Fat16Table[entryNumber]=(currentCluster&0xffff); 00199 } 00200 00201 // Calculate next entry position in FAT records 00202 fatPageSector = currentCluster; 00203 if (!IS_FAT_32){ //FAT16 00204 entryNumber = fatPageSector & 0xff; 00205 fatPageSector >>= 8; 00206 }else{ //FAT32 00207 entryNumber = fatPageSector & 0x7f; 00208 fatPageSector >>= 7; 00209 } 00210 fatPageSector += fatStart; 00211 00212 }//while 00213 00214 00215 // WRITE THE FINAL ENTRY TO FAT CLUSTERCHAIN 00216 00217 // is the FAT clusterchain page changed? 00218 if (sectorAddress.l != fatPageSector){ 00219 // Yes, have we advanced by 1 sector? 00220 if (sectorAddress.l == (fatPageSector - 1)){ 00221 //Yes, we must save the edited sector 00222 WriteDiskSector (sectorAddress.l); 00224 } 00225 // at least we need to load the new clusterchain page 00226 sectorAddress.l = fatPageSector; 00227 ReadDiskSector(sectorAddress.l); 00228 }//Load/Save FAT sector 00229 00230 00231 //Write the Last entry 00232 if (IS_FAT_32){ 00233 diskSect.Fat32Table[entryNumber]=fragment[1].start; 00234 }else{ 00235 diskSect.Fat16Table[entryNumber]=(fragment[1].start & 0xffff); 00236 } 00237 WriteDiskSector(sectorAddress.l); //Write last sector 00238 00239 OpenFile(0); //Register FAT entry 00240 00241 } 00242 00243 00244 00245 00248 unsigned char ScanForFreeSector(){ 00249 00250 //ConsoleWrite("\rLooking for free space starting from "); 00251 00252 if ((freeSector) && (freeSector-dataStart+1)%fatSectorsPerCluster){ 00253 //Still room in current cluster... 00254 freeSector++; 00255 00256 //ConsoleWrite("free at sector "); 00257 //ConsolePutUInt(freeSector); 00258 00259 return 1; 00260 } 00261 00262 if (freeSector){ 00263 //Advance to next sector 00264 freeSector++; 00265 //switch from using sectors to using clusters 00266 PConvertSectorToCluster(&freeSector); 00267 }else{ 00268 freeSector=3; //starting cluster entry (should be 2?) 00269 } 00270 00271 00272 //scan until free entry is found 00273 //freeSector actually counts clusters here. 00274 while(GetFatEntry(freeSector)){ 00275 freeSector++; 00276 } 00277 00278 ConsoleWrite("F"); 00279 ConsolePutUInt(freeSector); 00280 00281 00282 //while (!KEY_BUTTON); 00283 //ConsoleWrite("free at cluster "); 00284 //ConsolePutUInt(freeSector); 00285 00286 //switch back from using clusters to using sectors. 00287 PConvertClusterToSector(&freeSector); 00288 00289 //ConsoleWrite("sector "); 00290 //ConsolePutUInt(freeSector); 00291 00292 return 1; 00293 } 00294 00295 00303 unsigned long GetNextSector(unsigned long currentSector){ 00304 addressType fatSector; 00305 unsigned char entryNumber; 00306 00307 /* how manyth sector from start of data area -> fatsector */ 00308 fatSector.l = currentSector - dataStart; 00309 00310 /* Check for cluster boundary */ 00311 /* if we're not in cluster boundary then return currentsector + 1 */ 00312 if ((fatSector.b.b0 + 1) % fatSectorsPerCluster){ 00313 return currentSector + 1; 00314 } 00315 00316 /* is the value negative? then return currentSector + 1 */ 00317 if (fatSector.b.b3 & 0x80) { 00318 return currentSector + 1; 00319 } 00320 00321 /* The trivial conditions are not met, we actually do need to 00322 look up the next sector info from FAT tables in the disk.*/ 00323 00324 /* convert fatSector from CurrentSectorN to currentClusterN */ 00325 fatSector.l /= fatSectorsPerCluster; 00326 00327 /* calculate which page (fatSector) and entry of FAT table correspond 00328 to current sector */ 00329 00330 if (!IS_FAT_32){ //FAT16 00331 entryNumber = fatSector.b.b0; /* 256 entries / page in FAT16 table */ 00332 fatSector.l >>= 8; /* Divide by 256 (n of entries/page in FAT32 table */ 00333 }else{ //FAT32 00334 entryNumber =(fatSector.b.b0 & 0x7f); /* 128 entries/page in FAT32 tbl */ 00335 fatSector.l >>= 7; /* Divide by 128 (n of entries/sector in FAT32 table */ 00336 } 00337 00338 /* Get sector address for the needed page */ 00339 fatSector.l += fatStart; 00340 00341 /* Load (if needed) table page from disk */ 00342 if (sectorAddress.l != fatSector.l){ 00343 sectorAddress.l = fatSector.l; /* (not needed because mmc.c does this) */ 00344 ReadDiskSector(fatSector.l); 00345 00346 ConsolePutChar('n'); 00347 00348 00349 } 00350 /* Now there should be correct FAT entry page in memory... */ 00351 00352 if (!IS_FAT_32){ //FAT16 00353 fatSector.l = diskSect.Fat16Table[entryNumber]; 00354 /* Check for FAT16 end-of-file condition */ 00355 if ((fatSector.b.b1 == 0xff) && (fatSector.b.b0 == 0xff)){ 00356 /* End of file */ 00357 fatSector.b.b3 = 0xff; /* return a large value (fat32 compatible) */ 00358 return fatSector.l; 00359 } 00360 }else{ //FAT32 00361 fatSector.l = diskSect.Fat32Table[entryNumber] & 0x0fffffff; 00362 /* Check for FAT32 end-of-file condition */ 00363 if ((fatSector.b.b3&0x08) //Quick test 00364 && (fatSector.l>0x0ffffff0)){ //Complete test 00365 /* End of file */ 00366 return 0xffffffff; /* return EOF*/ 00367 } 00368 } 00369 00370 00371 /* now fatSector.l contains the proper next cluster value */ 00372 00373 fatSector.l *= fatSectorsPerCluster; 00374 /* now fatSector.l contains the next sector value */ 00375 00376 fatSector.l += dataStart; 00377 /* now fatSector.l contains the proper absolute sector address */ 00378 00379 return fatSector.l; 00380 } 00381 00382 00401 Public unsigned char BuildFragmentTable(){ 00402 00403 unsigned char c=0; 00404 addressType this,next; 00405 addressType fatSector; 00406 unsigned char entryNumber; 00407 00408 00409 if (IS_FAT_12){ 00410 ConsoleWrite("Single fragment support for FAT12"); 00411 fragment[0].start = sectorAddress.l; 00412 fragment[0].length = fileSize/512; 00413 return(1); //Return 1 fragment 00414 } 00415 00416 00417 //as long as the sectorAddress is "sane"... 00418 while (!(sectorAddress.b.b3 & 0x80)){ 00419 00420 fragment[c].start = sectorAddress.l; 00421 fragment[c].length = fatSectorsPerCluster; 00422 00423 /* Find cluster entry for the current sector */ 00424 00425 /* in how manyth sector from start of data area are we? ->this */ 00426 this.l = sectorAddress.l - dataStart; 00427 /* convert from CurrentSectorN to currentClusterN */ 00428 this.l /= fatSectorsPerCluster; 00429 /* this.l is now the current cluster number */ 00430 00431 00432 /* now let's find the FAT entry for this.l cluster */ 00433 if (!IS_FAT_32){ //FAT16 00434 entryNumber = this.b.b0; /* 256 entries / page in FAT16 table */ 00435 fatSector.l = this.l >> 8; /* Div by n of entries/page in FAT16 tbl*/ 00436 }else{ //FAT32 00437 entryNumber = (this.b.b0 & 0x7f); /* 128 entries/page in FAT32 table */ 00438 fatSector.l = this.l >> 7; /* Div by n of entries/page in FAT32 tbl*/ 00439 } 00440 fatSector.l += fatStart; 00441 /* fatSector.l is now the DISK SECTOR NUMBER CONTAINING THE FAT table */ 00442 /* read this page into memory */ 00443 ReadDiskSector(fatSector.l); 00444 00445 if (!IS_FAT_32){ //FAT16 00446 next.l = diskSect.Fat16Table[entryNumber]; /* get next cluster n */ 00447 /* Check for FAT16 end-of-file condition */ 00448 if ((next.b.b1 == 0xff) && (next.b.b0 == 0xff)){ 00449 /* FAT16 End of file */ 00450 next.b.b3 = 0xff; /* return a large value (fat32 compatible) */ 00451 } 00452 }else{ //FAT32 00453 next.l = diskSect.Fat32Table[entryNumber]&0x0fffffff; 00454 } 00455 /* next.l is the FAT entry (next cluster number) */ 00456 00457 00458 ConsoleWrite("\rFragment start: cluster "); 00459 ConsolePutUInt(this.l); 00460 ConsoleWrite("sector "); 00461 ConsolePutUInt(fragment[c].start); 00462 00463 while (next.l==(this.l+1)){ 00464 //Not a fragment break -- continue to next entry 00465 00466 //in this temp.l is used only to allow compiler memory spilling to temp 00467 temp.l = fragment[c].length; 00468 temp.l += fatSectorsPerCluster; 00469 fragment[c].length = temp.l; 00470 00471 entryNumber++; 00472 00473 // --- Check for a page break 00474 if (entryNumber==0){ //entryNumber has rolled over!!!! (8bit char) 00475 //FAT16 table page border is reached 00476 fatSector.l++; //Advance to next page; 00477 entryNumber=0; 00478 ReadDiskSector(fatSector.l); 00479 } 00480 if (IS_FAT_32 && (entryNumber==128)){ 00481 //FAT32 table page border is reached 00482 fatSector.l++; 00483 entryNumber=0; 00484 ReadDiskSector(fatSector.l); 00485 } 00486 00487 // --- Advance to next cluster 00488 this.l = next.l; 00489 00490 if (!IS_FAT_32){ 00491 //FAT16 get next cluster n 00492 next.l = diskSect.Fat16Table[entryNumber]; 00493 if ((next.b.b1==0xff)&&(next.b.b0==0xff)){ 00494 //FAT16 end-of-file 00495 next.b.b3 = 0xff; //mark end-of-file (FAT32 compatible) 00496 } 00497 }else{ 00498 //FAT32 get next cluster n 00499 next.l = diskSect.Fat32Table[entryNumber]; 00500 } 00501 }//This repeats until there is a discontinuity 00502 00503 /* next.l now has the cluster entry for last cluster in fragment 00504 it has a high value if eof (see FAT spec) */ 00505 00506 00507 ConsoleWrite("Size: "); 00508 ConsolePutUInt(fragment[c].length); 00509 ConsoleWrite("sectors."); 00510 00511 //EOF test 00512 if ((next.b.b3&0x08) //Quick test 00513 && ((next.l>0x0ffffff0) | !IS_FAT_32)){ //Complete test 00514 //EOF 00515 ConsoleWrite(" <EOF>\r"); 00516 sectorAddress.b.b3 = 0xff; 00517 }else{ 00518 00519 //Determine next physical sector for next fragment 00520 sectorAddress.l = next.l; 00521 sectorAddress.l *= fatSectorsPerCluster; 00522 sectorAddress.l += dataStart; 00523 } 00524 00525 c++; //Advance to next fragment number 00526 00527 if (c==MAX_NUMBER_FRAGMENTS){ 00528 //End of RAM space allocated for fragment table 00529 //Force end-of-file 00530 sectorAddress.b.b3=0xff; 00531 } 00532 00533 }//break or continue to next cluster 00534 00535 return c; //Return number of fragments; 00536 } 00537 00538 00539 00541 unsigned char LoadNextSector(){ 00542 sectorAddress.l = GetNextSector(sectorAddress.l); 00543 if (sectorAddress.b.b1 & 0x80){ 00545 return 0x0d; /*EOF*/ 00546 } 00547 if (ReadDiskSector(sectorAddress.l)){ 00548 return 0x0d; /*EOF*/ 00549 } 00550 return 0; /* All OK return */ 00551 } 00552 00561 Public unsigned char FGetChar(){ 00562 00563 if (!fileSize) return 0; //return 0 for end-of-file 00564 00565 if (dataBufPtr==0){ 00566 /* A file has been opened but not read from yet, so read the first 00567 sector. */ 00568 ReadDiskSector(sectorAddress.l); 00569 dataBufPtr = diskSect.raw.buf; 00570 } 00571 00572 if (dataBufPtr>diskSect.raw.buf+511){ 00573 /* An end of sector has been reached, read the next sector */ 00574 if (LoadNextSector()){ 00575 /* Error, end-of-file according to FAT records */ 00576 return 0; /* must return something */ 00577 } 00578 dataBufPtr=diskSect.raw.buf; 00579 } 00580 00581 /* Everything should now be ok for reading a byte. */ 00582 00583 fileSize--; 00584 return (*dataBufPtr++); 00585 } 00586 00587 00588 00610 Public unsigned char OpenFile(unsigned int fileNumber){ 00611 char tempc; 00612 00613 ConsoleWrite("\rFilesystem: Looking for file "); 00614 ConsolePutUInt(fileNumber); 00615 ConsoleWrite("... "); 00616 00617 /* Start at the start of root directory. */ 00618 dirLevel = 0; /* At root directory */ 00619 dirStack[dirLevel].sector=rootStart; 00620 dirStack[dirLevel].entry=0; 00621 00622 00623 if (fileNumber==0){ 00624 fileNumber = 32766; //use max-1 value for scanning for free entry 00625 } 00626 00627 while (fileNumber){ 00628 if (dirStack[dirLevel].entry==0){ 00629 /* At the start of new dir, load first disk sector */ 00630 while (ReadDiskSector(dirStack[dirLevel].sector)){ 00631 InitMMC; 00632 } 00633 } 00634 temp.c = dirStack[dirLevel].entry; 00635 00636 /* We are now looking at FAT directory structure. */ 00637 00638 /* Is current entry empty? */ 00639 if ((diskSect.dir[temp.c].entry.Name[0]==0) 00640 ||(diskSect.dir[temp.c].entry.Name[0]==0xe5)){ 00641 /* Yes. Are we supposed to make an entry now? */ 00642 if (fileNumber>30000){ 00643 //yes, this is actually a request to write file directory entry!; 00644 00645 fileNumber = 32767-fileNumber; 00646 00647 diskSect.dir[temp.c].entry.Name[0] ='R'; 00648 diskSect.dir[temp.c].entry.Name[1] ='E'; 00649 diskSect.dir[temp.c].entry.Name[2] ='C'; 00650 diskSect.dir[temp.c].entry.Name[7] =(fileNumber%10)+'0'; 00651 fileNumber /= 10; 00652 diskSect.dir[temp.c].entry.Name[6] =(fileNumber%10)+'0'; 00653 fileNumber /= 10; 00654 diskSect.dir[temp.c].entry.Name[5] =(fileNumber%10)+'0'; 00655 fileNumber /= 10; 00656 diskSect.dir[temp.c].entry.Name[4] =(fileNumber%10)+'0'; 00657 fileNumber /= 10; 00658 diskSect.dir[temp.c].entry.Name[3] =(fileNumber%10)+'0'; 00659 diskSect.dir[temp.c].entry.Name[8] ='W'; 00660 diskSect.dir[temp.c].entry.Name[9] ='A'; 00661 diskSect.dir[temp.c].entry.Name[10]='V'; 00662 diskSect.dir[temp.c].entry.Attr = 0; 00663 diskSect.dir[temp.c].entry.FstClusHi = (fragment[0].start >> 16); 00664 diskSect.dir[temp.c].entry.FstClusLo = (fragment[0].start & 0xffff); 00665 diskSect.dir[temp.c].entry.FileSize = (fragment[0].length); 00666 00667 ConsoleWrite(" Making Directory Entry "); 00668 WriteDiskSector(sectorAddress.l); 00669 00670 return 99; //created a FAT entry 00671 } //register file 00672 } 00673 00674 00675 /* Does current entry point to a regular file? */ 00676 /* Attributes: NO directory, NO volume id, NO system, NO hidden */ 00677 if (((diskSect.dir[temp.c].entry.Attr & 222) == 0) 00678 && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 00679 && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ 00680 00681 /* It is a regular file. */ 00682 if (!(--fileNumber)){ 00683 00684 /* ------------ FILE FOUND ------------- */ 00685 00686 sectorAddress.l = 00687 ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 00688 + diskSect.dir[temp.c].entry.FstClusLo; 00689 sectorAddress.l *= fatSectorsPerCluster; 00690 sectorAddress.l += dataStart; 00691 00692 fileSize = diskSect.dir[temp.c].entry.FileSize; 00693 dataBufPtr = 0; /* Reset data buffer ptr for FGetChar */ 00694 00695 ConsoleWrite("found, FAT name is \""); 00696 for (tempc=0; tempc<11; tempc++){ 00697 ConsolePutChar(diskSect.dir[temp.c].entry.Name[tempc]); 00698 } 00699 00700 //Store file name nicely for displaying on screen :) 00701 for (tempc=0; tempc<8; tempc++){ 00702 currentFileName[tempc]=diskSect.dir[temp.c].entry.Name[tempc]; 00703 } 00704 currentFileName[8]='.'; 00705 currentFileName[9]=diskSect.dir[temp.c].entry.Name[8]; 00706 currentFileName[10]=diskSect.dir[temp.c].entry.Name[9]; 00707 currentFileName[11]=diskSect.dir[temp.c].entry.Name[10]; 00708 displayText[0]=' '; 00709 for (tempc=0; tempc<12; tempc++){ 00710 displayText[tempc+1]=currentFileName[tempc]; 00711 } 00712 00713 ConsoleWrite("\"\rFile size: "); 00714 ConsolePutUInt(fileSize); 00715 ConsoleWrite("bytes. "); 00716 00717 ConsoleWrite("Start cluster: "); 00718 ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusHi); 00719 ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusLo); 00720 ConsoleWrite("h, sector "); 00721 ConsolePutUInt(sectorAddress.l); 00722 ConsoleWrite("decimal.\r"); 00723 00724 return 0; /* File found, All OK return */ 00725 } 00726 } /* it was a regular file */ 00727 00728 00729 00730 /* Is it a subdirectory? */ 00731 if (((diskSect.dir[temp.c].entry.Attr & 16) != 0) 00732 && (diskSect.dir[temp.c].entry.Name[0] != '.') /* skip . and .. */ 00733 && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 00734 && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ 00735 00736 /* It is a subdirectory. */ 00737 00738 if (dirLevel<MAX_NUMBER_SUBDIRECTORIES-1){ 00739 /* Yes, we have room in dirStack to traverse deeper. */ 00740 dirLevel++; /* Advance to next directory level */ 00741 sectorAddress.l = 00742 ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 00743 + diskSect.dir[temp.c].entry.FstClusLo; 00744 sectorAddress.l *= fatSectorsPerCluster; 00745 sectorAddress.l += dataStart; 00746 00747 /* Prepare for loading. */ 00748 dirStack[dirLevel].sector = sectorAddress.l; 00749 dirStack[dirLevel].entry = 255; /* Magic number */ 00750 00751 } /* we had room in dirStack */ 00752 } /* it was a subdirectory */ 00753 00754 00755 /* Have we reached the end of the directory? */ 00756 if (diskSect.dir[temp.c].entry.Name[0] == 0){ 00757 /* It's the end of directory. */ 00758 00759 /* Is it the end of root directory? */ 00760 if (dirLevel == 0){ 00761 /* End of root directory, end of all files in volume */ 00762 ConsoleWrite("File not found.\r"); 00763 sectorAddress.l = dataStart; 00764 /* when in error point to start of data */ 00765 return 0x0c; /* File Not Found return */ 00766 } 00767 00768 /* End of subdirectory, return from subdirectory */ 00769 dirLevel--; 00770 ReadDiskSector(dirStack[dirLevel].sector); 00771 /* restore temp entry pointer */ 00772 temp.c = dirStack[dirLevel].entry; 00773 00774 } /* it was end of directory */ 00775 00776 00777 /* Advance to next entry */ 00778 temp.c++; 00779 00780 /* If we just went to a subdir, set temp entry pointer to 0 */ 00781 if (dirStack[dirLevel].entry == 255){ 00782 /* Magic Number 255: we have gone to a subdirectory */ 00783 temp.c=0; 00784 } 00785 00786 if (temp.c==16){ /* End of sector */ 00787 /* Prepare to load next sector */ 00788 dirStack[dirLevel].sector = GetNextSector (dirStack[dirLevel].sector); 00789 temp.c=0; 00790 } 00791 00792 dirStack[dirLevel].entry = temp.c; 00793 } 00794 00795 /* Control should never reach this far, end of root directory should 00796 occur first. */ 00797 00798 sectorAddress.l = dataStart; /* when in error point to start of data */ 00799 return 0x0c; /* File Not Found return */ 00800 } 00801 00802 00803 00806 unsigned char FatInitGlobals(){ 00807 00808 ConsoleWrite("Formatter signature:"); 00809 for (temp.c=0; temp.c<8; temp.c++){ 00810 ConsolePutChar(diskSect.fat.BS_OEMName[temp.c]); 00811 } 00812 ConsoleWrite("\rBytes per sector: "); 00813 ConsolePutUInt(diskSect.fat.BPB_BytsPerSec); 00814 ConsoleWrite("\rSectors per Cluster: "); 00815 ConsolePutUInt(diskSect.fat.BPB_SecPerClus); 00816 ConsoleWrite("\rReserved sectors: "); 00817 ConsolePutUInt(diskSect.fat.BPB_RsvdSecCnt); 00818 ConsoleWrite("\rNumber of FATs: "); 00819 ConsolePutUInt(diskSect.fat.BPB_NumFATs); 00820 ConsoleWrite("\rRoot entries: "); 00821 ConsolePutUInt(diskSect.fat.BPB_RootEntCnt); 00822 ConsoleWrite("\rTotal Sectors 16: "); 00823 ConsolePutUInt(diskSect.fat.BPB_TotSec16); 00824 ConsoleWrite("\rFat Size 16: "); 00825 ConsolePutUInt(diskSect.fat.BPB_FATSz16); 00826 ConsoleWrite("\rHidden Sectors: "); 00827 ConsolePutUInt(diskSect.fat.BPB_HiddSec); 00828 ConsoleWrite("\rTotal Sectors 32: "); 00829 ConsolePutUInt(diskSect.fat.BPB_TotSec32); 00830 00831 00832 00833 /* Determine FAT Type (16/32) */ 00834 /* This should be done better, but it'll do for now. */ 00835 IS_FAT_32 = 1; 00836 if (diskSect.fat.BPB_RootEntCnt) 00837 IS_FAT_32 = 0; /* FAT32 does not have separate root entries. */ 00838 00839 ConsoleWrite("\rFile system is "); 00840 if (IS_FAT_32){ 00841 ConsoleWrite("FAT32"); 00842 } else { 00843 ConsoleWrite("FAT16"); 00844 } 00845 00846 ConsoleWrite("\rFile system signature is "); 00847 for (temp.c=0;temp. c<8; temp.c++) 00848 if (IS_FAT_32){ 00849 ConsolePutChar(diskSect.fat.ext._32.BS_FilSysType[temp.c]); 00850 } else { 00851 ConsolePutChar(diskSect.fat.ext._16.BS_FilSysType[temp.c]); 00852 } 00853 00854 if (!IS_FAT_32){ 00855 if (diskSect.fat.ext._16.BS_FilSysType[4]=='2'){ 00856 IS_FAT_12 = 1; 00857 ConsoleWrite("Well, actually it's FAT12 filesystem.\r"); 00858 } 00859 } 00860 00861 00862 ConsoleWrite("\rVolume Label is "); 00863 for (temp.c=0; temp.c<11; temp.c++) 00864 if (IS_FAT_32){ 00865 ConsolePutChar(diskSect.fat.ext._32.BS_VolLab[temp.c]); 00866 } else { 00867 ConsolePutChar(diskSect.fat.ext._16.BS_VolLab[temp.c]); 00868 } 00869 /* OK, let's calculate */ 00870 /* First, let's get rid of the idea that we have byte addresses 00871 in the file system. Nope, let's only deal in physical disk 00872 sectors of 512 bytes. First we convert the FAT byter per sector 00873 value to "512B disk sectors per fat sector" value. */ 00874 00875 diskSect.fat.BPB_BytsPerSec /= 512; 00876 00877 /* Then we adjust the Sector per Cluster to mean physical disk 00878 sectors. in 99% of the cases it is already so because bytes 00879 per sector almost always is 512 in FAT. Maximum cluster size 00880 is 65536 bytes (128 disk sectors). */ 00881 00882 fatSectorsPerCluster = 00883 diskSect.fat.BPB_SecPerClus *= diskSect.fat.BPB_BytsPerSec; 00884 /* Note: BPB_BytsPerSec has already been divided by 512 */ 00885 00886 ConsoleWrite("\rSectors per Cluster: "); 00887 ConsolePutUInt(fatSectorsPerCluster); 00888 00889 fatStart = (unsigned long)sectorAddress.l 00890 + (unsigned long)diskSect.fat.BPB_RsvdSecCnt 00891 * (unsigned long)diskSect.fat.BPB_BytsPerSec; 00892 00893 ConsoleWrite("\rFAT Start sector: "); 00894 ConsolePutUInt(fatStart); 00895 00896 rootStart = diskSect.fat.BPB_FATSz16; 00897 if (rootStart==0){ 00898 if (!IS_FAT_32) 00899 return 0x0b; /* should be FAT32; can not find root directory */ 00900 rootStart = diskSect.fat.ext._32.BPB_FATSz32; 00901 } 00902 rootStart *= diskSect.fat.BPB_NumFATs; 00903 rootStart *= diskSect.fat.BPB_BytsPerSec; /* ADJUSTED BytsPerSec! */ 00904 rootStart += fatStart; 00905 00906 ConsoleWrite("\rRoot start sector: "); 00907 ConsolePutUInt(rootStart); 00908 00909 dataStart = diskSect.fat.BPB_RootEntCnt >> 4; 00910 dataStart += rootStart; 00911 dataStart -= (fatSectorsPerCluster*2); /*first cluster is cluster 2*/ 00912 00913 ConsoleWrite("\rData start sector: "); 00914 ConsolePutUInt(dataStart); 00915 ConsolePutChar(13); 00916 00917 return 0; 00918 } 00919 00923 Public unsigned char InitFileSystem(){ 00924 unsigned char c; 00925 00926 /* Initialize variables to sane values in case of error exit. */ 00927 fatStart = 0; 00928 rootStart = 0; 00929 dataStart = 0; 00930 freeSector = 0; 00931 00932 ConsoleWrite("Init: Filesystem; supports: MBR, FAT16, FAT32\r"); 00933 00934 ConsoleWrite("Trying to bring up storage...\r"); 00935 /* Initialize the storage system */ 00936 if ((c=InitStorage())){ 00937 ConsoleWrite("Storage init returns error "); 00938 ConsolePutUInt(c); 00939 ConsolePutChar(13); 00940 return c; /* Error in InitStorage */ 00941 } 00942 00943 ConsoleWrite("Storage ok.\rSector 0 read..."); 00944 00945 /* Load MBR */ 00946 sectorAddress.l = 0; /* the first sector on disk */ 00947 ReadDiskSector(0); 00948 00949 00950 00951 00952 ConsoleWrite("ok.\rSector signature..."); 00953 00954 /* Ok, it should be a MBR sector. Let's verify */ 00955 if (diskSect.raw.buf[510] != 0x55) 00956 return 8; /* sector 0 is not MBR. */ 00957 if (diskSect.raw.buf[511] != 0xaa) 00958 return 8; /* sector 0 is not MBR. */ 00959 00960 ConsoleWrite("ok.\rPartition 1..."); 00961 00962 00963 if (!((diskSect.raw.buf[0x036]=='F') 00964 &&(diskSect.raw.buf[0x037]=='A') 00965 &&(diskSect.raw.buf[0x038]=='T'))){ 00966 00967 00968 00969 00970 /* This checks that partition 1 is active. Alter code to allow 00971 * other partition configurations. */ 00972 if (diskSect.raw.buf[0x1be] == 0x80){ 00973 sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; 00974 sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; 00975 sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; 00976 sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; 00977 ConsoleWrite (" active"); 00978 }else{ 00979 //-------- DEBUG: Uncomment if you want to explore the sector 00980 //DumpDiskSector(); 00981 //while (!KEY_BUTTON); 00982 sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; 00983 sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; 00984 sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; 00985 sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; 00986 00987 } 00988 00989 // return 9; /* No active partition*/ 00990 00991 } 00992 00993 ConsoleWrite(" at sector "); 00994 ConsolePutHex8(sectorAddress.b.b3); 00995 ConsolePutHex8(sectorAddress.b.b2); 00996 ConsolePutHex8(sectorAddress.b.b1); 00997 ConsolePutHex8(sectorAddress.b.b0); 00998 ConsolePutChar('\r'); 00999 01000 01001 /* Now leave MBR and load sector 0 of partition */ 01002 //SeekDiskSectorToRead(); 01003 //ReadDiskSector(); /* to global buffer */ 01004 01005 ReadDiskSector(sectorAddress.l); 01006 01007 if (FatInitGlobals()){ 01008 return 0x0a; /* FAT init failed */ 01009 } 01010 01011 return 0; /* All ok return */ 01012 01013 } 01014 01015 01016 01017 01018