📄 filesys.c
字号:
//EOF test if ((next.b.b3&0x08) //Quick test && ((next.l>0x0ffffff0) | !IS_FAT_32)){ //Complete test //EOF ConsoleWrite(" <EOF>\r"); sectorAddress.b.b3 = 0xff; }else{ //Determine next physical sector for next fragment sectorAddress.l = next.l; sectorAddress.l *= fatSectorsPerCluster; sectorAddress.l += dataStart; } c++; //Advance to next fragment number if (c==MAX_NUMBER_FRAGMENTS){ //End of RAM space allocated for fragment table //Force end-of-file sectorAddress.b.b3=0xff; } }//break or continue to next cluster return c; //Return number of fragments;}/** Traverse to next sector in file or directory */unsigned char LoadNextSector(){ sectorAddress.l = GetNextSector(sectorAddress.l); if (sectorAddress.b.b1 & 0x80){ /** End of File */ return 0x0d; /*EOF*/ } if (ReadDiskSector(sectorAddress.l)){ return 0x0d; /*EOF*/ } return 0; /* All OK return */} /** Read a character from current file. * This can be called after calling OpenFile. It is a slow method * for reading character based file data. * fileSize holds the number of characters still left in file to be read, * check for fileSize=0 to detect end-of-file. If FGetChar is called * after the end of file is reached, it does nothing and returns 0. */Public unsigned char FGetChar(){ if (!fileSize) return 0; //return 0 for end-of-file if (dataBufPtr==0){ /* A file has been opened but not read from yet, so read the first sector. */ ReadDiskSector(sectorAddress.l); dataBufPtr = diskSect.raw.buf; } if (dataBufPtr>diskSect.raw.buf+511){ /* An end of sector has been reached, read the next sector */ if (LoadNextSector()){ /* Error, end-of-file according to FAT records */ return 0; /* must return something */ } dataBufPtr=diskSect.raw.buf; } /* Everything should now be ok for reading a byte. */ fileSize--; return (*dataBufPtr++);} /** Open a file for reading. * Prepares the Filing System to read a data file from the storage. * Files are referred to by their numbers, not file names. This makes the * system generic, not necessarily needing a complex file system such as * FAT. The way to assign numbers to files is implementation dependent. * Returns 0 when ok, error code otherwise. * \param fileNumber number of file, starting from beginning of storage, * to open. * * What this function actually does, is: it starts reading the FAT * records from start of the root directory, traversing through * subdirectories as it encounters them. When the fileNumber'th valid * record is encountered, it sets sectorAddress to point to its * first data sector but doesn't load any sector. fileSize is loaded * with the size in bytes indicated in the FAT record. * * Additionally, if it's called with 0 as the fileNumber and it * happens to see an empty directory record, it registers a new * file with name RECnnnnn.WAV starting from cluster fragment[0].start * with file size from fragment[0].length*/Public unsigned char OpenFile(unsigned int fileNumber){ char tempc; ConsoleWrite("\rFilesystem: Looking for file "); ConsolePutUInt(fileNumber); ConsoleWrite("... "); /* Start at the start of root directory. */ dirLevel = 0; /* At root directory */ dirStack[dirLevel].sector=rootStart; dirStack[dirLevel].entry=0; if (fileNumber==0){ fileNumber = 32766; //use max-1 value for scanning for free entry } while (fileNumber){ if (dirStack[dirLevel].entry==0){ /* At the start of new dir, load first disk sector */ while (ReadDiskSector(dirStack[dirLevel].sector)){ InitMMC; } } temp.c = dirStack[dirLevel].entry; /* We are now looking at FAT directory structure. */ /* Is current entry empty? */ if ((diskSect.dir[temp.c].entry.Name[0]==0) ||(diskSect.dir[temp.c].entry.Name[0]==0xe5)){ /* Yes. Are we supposed to make an entry now? */ if (fileNumber>30000){ //yes, this is actually a request to write file directory entry!; fileNumber = 32767-fileNumber; diskSect.dir[temp.c].entry.Name[0] ='R'; diskSect.dir[temp.c].entry.Name[1] ='E'; diskSect.dir[temp.c].entry.Name[2] ='C'; diskSect.dir[temp.c].entry.Name[7] =(fileNumber%10)+'0'; fileNumber /= 10; diskSect.dir[temp.c].entry.Name[6] =(fileNumber%10)+'0'; fileNumber /= 10; diskSect.dir[temp.c].entry.Name[5] =(fileNumber%10)+'0'; fileNumber /= 10; diskSect.dir[temp.c].entry.Name[4] =(fileNumber%10)+'0'; fileNumber /= 10; diskSect.dir[temp.c].entry.Name[3] =(fileNumber%10)+'0'; diskSect.dir[temp.c].entry.Name[8] ='W'; diskSect.dir[temp.c].entry.Name[9] ='A'; diskSect.dir[temp.c].entry.Name[10]='V'; diskSect.dir[temp.c].entry.Attr = 0; diskSect.dir[temp.c].entry.FstClusHi = (fragment[0].start >> 16); diskSect.dir[temp.c].entry.FstClusLo = (fragment[0].start & 0xffff); diskSect.dir[temp.c].entry.FileSize = (fragment[0].length); ConsoleWrite(" Making Directory Entry "); WriteDiskSector(sectorAddress.l); return 99; //created a FAT entry } //register file } /* Does current entry point to a regular file? */ /* Attributes: NO directory, NO volume id, NO system, NO hidden */ if (((diskSect.dir[temp.c].entry.Attr & 222) == 0) && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ /* It is a regular file. */ if (!(--fileNumber)){ /* ------------ FILE FOUND ------------- */ sectorAddress.l = ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) + diskSect.dir[temp.c].entry.FstClusLo; sectorAddress.l *= fatSectorsPerCluster; sectorAddress.l += dataStart; fileSize = diskSect.dir[temp.c].entry.FileSize; dataBufPtr = 0; /* Reset data buffer ptr for FGetChar */ ConsoleWrite("found, FAT name is \""); for (tempc=0; tempc<11; tempc++){ ConsolePutChar(diskSect.dir[temp.c].entry.Name[tempc]); } //Store file name nicely for displaying on screen :) for (tempc=0; tempc<8; tempc++){ currentFileName[tempc]=diskSect.dir[temp.c].entry.Name[tempc]; } currentFileName[8]='.'; currentFileName[9]=diskSect.dir[temp.c].entry.Name[8]; currentFileName[10]=diskSect.dir[temp.c].entry.Name[9]; currentFileName[11]=diskSect.dir[temp.c].entry.Name[10]; displayText[0]=' '; for (tempc=0; tempc<12; tempc++){ displayText[tempc+1]=currentFileName[tempc]; } ConsoleWrite("\"\rFile size: "); ConsolePutUInt(fileSize); ConsoleWrite("bytes. "); ConsoleWrite("Start cluster: "); ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusHi); ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusLo); ConsoleWrite("h, sector "); ConsolePutUInt(sectorAddress.l); ConsoleWrite("decimal.\r"); return 0; /* File found, All OK return */ } } /* it was a regular file */ /* Is it a subdirectory? */ if (((diskSect.dir[temp.c].entry.Attr & 16) != 0) && (diskSect.dir[temp.c].entry.Name[0] != '.') /* skip . and .. */ && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ /* It is a subdirectory. */ if (dirLevel<MAX_NUMBER_SUBDIRECTORIES-1){ /* Yes, we have room in dirStack to traverse deeper. */ dirLevel++; /* Advance to next directory level */ sectorAddress.l = ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) + diskSect.dir[temp.c].entry.FstClusLo; sectorAddress.l *= fatSectorsPerCluster; sectorAddress.l += dataStart; /* Prepare for loading. */ dirStack[dirLevel].sector = sectorAddress.l; dirStack[dirLevel].entry = 255; /* Magic number */ } /* we had room in dirStack */ } /* it was a subdirectory */ /* Have we reached the end of the directory? */ if (diskSect.dir[temp.c].entry.Name[0] == 0){ /* It's the end of directory. */ /* Is it the end of root directory? */ if (dirLevel == 0){ /* End of root directory, end of all files in volume */ ConsoleWrite("File not found.\r"); sectorAddress.l = dataStart; /* when in error point to start of data */ return 0x0c; /* File Not Found return */ } /* End of subdirectory, return from subdirectory */ dirLevel--; ReadDiskSector(dirStack[dirLevel].sector); /* restore temp entry pointer */ temp.c = dirStack[dirLevel].entry; } /* it was end of directory */ /* Advance to next entry */ temp.c++; /* If we just went to a subdir, set temp entry pointer to 0 */ if (dirStack[dirLevel].entry == 255){ /* Magic Number 255: we have gone to a subdirectory */ temp.c=0; } if (temp.c==16){ /* End of sector */ /* Prepare to load next sector */ dirStack[dirLevel].sector = GetNextSector (dirStack[dirLevel].sector); temp.c=0; } dirStack[dirLevel].entry = temp.c; } /* Control should never reach this far, end of root directory should occur first. */ sectorAddress.l = dataStart; /* when in error point to start of data */ return 0x0c; /* File Not Found return */}/** Decipher structure of FAT volume and set globals accordingly. */ unsigned char FatInitGlobals(){ ConsoleWrite("Formatter signature:"); for (temp.c=0; temp.c<8; temp.c++){ ConsolePutChar(diskSect.fat.BS_OEMName[temp.c]); } ConsoleWrite("\rBytes per sector: "); ConsolePutUInt(diskSect.fat.BPB_BytsPerSec); ConsoleWrite("\rSectors per Cluster: "); ConsolePutUInt(diskSect.fat.BPB_SecPerClus); ConsoleWrite("\rReserved sectors: "); ConsolePutUInt(diskSect.fat.BPB_RsvdSecCnt); ConsoleWrite("\rNumber of FATs: "); ConsolePutUInt(diskSect.fat.BPB_NumFATs); ConsoleWrite("\rRoot entries: "); ConsolePutUInt(diskSect.fat.BPB_RootEntCnt); ConsoleWrite("\rTotal Sectors 16: "); ConsolePutUInt(diskSect.fat.BPB_TotSec16); ConsoleWrite("\rFat Size 16: "); ConsolePutUInt(diskSect.fat.BPB_FATSz16); ConsoleWrite("\rHidden Sectors: "); ConsolePutUInt(diskSect.fat.BPB_HiddSec); ConsoleWrite("\rTotal Sectors 32: "); ConsolePutUInt(diskSect.fat.BPB_TotSec32); /* Determine FAT Type (16/32) */ /* This should be done better, but it'll do for now. */ IS_FAT_32 = 1; if (diskSect.fat.BPB_RootEntCnt) IS_FAT_32 = 0; /* FAT32 does not have separate root entries. */ ConsoleWrite("\rFile system is "); if (IS_FAT_32){ ConsoleWrite("FAT32"); } else { ConsoleWrite("FAT16"); } ConsoleWrite("\rFile system signature is "); for (temp.c=0;temp. c<8; temp.c++) if (IS_FAT_32){ ConsolePutChar(diskSect.fat.ext._32.BS_FilSysType[temp.c]); } else { ConsolePutChar(diskSect.fat.ext._16.BS_FilSysType[temp.c]); } if (!IS_FAT_32){ if (diskSect.fat.ext._16.BS_FilSysType[4]=='2'){ IS_FAT_12 = 1; ConsoleWrite("Well, actually it's FAT12 filesystem.\r"); } } ConsoleWrite("\rVolume Label is "); for (temp.c=0; temp.c<11; temp.c++) if (IS_FAT_32){ ConsolePutChar(diskSect.fat.ext._32.BS_VolLab[temp.c]); } else { ConsolePutChar(diskSect.fat.ext._16.BS_VolLab[temp.c]); } /* OK, let's calculate */ /* First, let's get rid of the idea that we have byte addresses in the file system. Nope, let's only deal in physical disk sectors of 512 bytes. First we convert the FAT byter per sector value to "512B disk sectors per fat sector" value. */ diskSect.fat.BPB_BytsPerSec /= 512; /* Then we adjust the Sector per Cluster to mean physical disk sectors. in 99% of the cases it is already so because bytes per sector almost always is 512 in FAT. Maximum cluster size is 65536 bytes (128 disk sectors). */ fatSectorsPerCluster = diskSect.fat.BPB_SecPerClus *= diskSect.fat.BPB_BytsPerSec; /* Note: BPB_BytsPerSec has already been divided by 512 */ ConsoleWrite("\rSectors per Cluster: "); ConsolePutUInt(fatSectorsPerCluster); fatStart = (unsigned long)sectorAddress.l + (unsigned long)diskSect.fat.BPB_RsvdSecCnt * (unsigned long)diskSect.fat.BPB_BytsPerSec; ConsoleWrite("\rFAT Start sector: "); ConsolePutUInt(fatStart); rootStart = diskSect.fat.BPB_FATSz16; if (rootStart==0){ if (!IS_FAT_32) return 0x0b; /* should be FAT32; can not find root directory */ rootStart = diskSect.fat.ext._32.BPB_FATSz32; } rootStart *= diskSect.fat.BPB_NumFATs; rootStart *= diskSect.fat.BPB_BytsPerSec; /* ADJUSTED BytsPerSec! */ rootStart += fatStart; ConsoleWrite("\rRoot start sector: "); ConsolePutUInt(rootStart); dataStart = diskSect.fat.BPB_RootEntCnt >> 4; dataStart += rootStart; dataStart -= (fatSectorsPerCluster*2); /*first cluster is cluster 2*/ ConsoleWrite("\rData start sector: "); ConsolePutUInt(dataStart); ConsolePutChar(13); return 0;}/** Start the filing system and initialize all necessary subsystems. Init storage and file system. FAT16 and FAT32 are supported */Public unsigned char InitFileSystem(){ unsigned char c; /* Initialize variables to sane values in case of error exit. */ fatStart = 0; rootStart = 0; dataStart = 0; freeSector = 0; ConsoleWrite("Init: Filesystem; supports: MBR, FAT16, FAT32\r"); ConsoleWrite("Trying to bring up storage...\r"); /* Initialize the storage system */ if ((c=InitStorage())){ ConsoleWrite("Storage init returns error "); ConsolePutUInt(c); ConsolePutChar(13); return c; /* Error in InitStorage */ } ConsoleWrite("Storage ok.\rSector 0 read..."); /* Load MBR */ sectorAddress.l = 0; /* the first sector on disk */ ReadDiskSector(0); ConsoleWrite("ok.\rSector signature..."); /* Ok, it should be a MBR sector. Let's verify */ if (diskSect.raw.buf[510] != 0x55) return 8; /* sector 0 is not MBR. */ if (diskSect.raw.buf[511] != 0xaa) return 8; /* sector 0 is not MBR. */ ConsoleWrite("ok.\rPartition 1..."); if (!((diskSect.raw.buf[0x036]=='F') &&(diskSect.raw.buf[0x037]=='A') &&(diskSect.raw.buf[0x038]=='T'))){ /* This checks that partition 1 is active. Alter code to allow * other partition configurations. */ if (diskSect.raw.buf[0x1be] == 0x80){ sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; ConsoleWrite (" active"); }else{ //-------- DEBUG: Uncomment if you want to explore the sector //DumpDiskSector(); //while (!KEY_BUTTON); sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; } // return 9; /* No active partition*/ } ConsoleWrite(" at sector "); ConsolePutHex8(sectorAddress.b.b3); ConsolePutHex8(sectorAddress.b.b2); ConsolePutHex8(sectorAddress.b.b1); ConsolePutHex8(sectorAddress.b.b0); ConsolePutChar('\r'); /* Now leave MBR and load sector 0 of partition */ //SeekDiskSectorToRead(); //ReadDiskSector(); /* to global buffer */ ReadDiskSector(sectorAddress.l); if (FatInitGlobals()){ return 0x0a; /* FAT init failed */ } return 0; /* All ok return */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -