📄 fat.c
字号:
{ DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc); return rc * 10 - 4; } fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); /* calculate freecount if unset */ if ( fat_bpb.fsinfo.freecount == 0xffffffff ) { fat_recalc_free(); } LDEBUGF("Freecount: %d\n",fat_bpb.fsinfo.freecount); LDEBUGF("Nextfree: 0x%x\n",fat_bpb.fsinfo.nextfree); LDEBUGF("Cluster count: 0x%x\n",fat_bpb.dataclusters); LDEBUGF("Sectors per cluster: %d\n",fat_bpb.bpb_secperclus); LDEBUGF("FAT sectors: 0x%x\n",fat_bpb.fatsize); return 0;}void fat_recalc_free(void){ int free = 0; unsigned i; for (i = 0; i<fat_bpb.fatsize; i++) { unsigned int j; unsigned int* fat = cache_fat_sector(i); for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j; if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ break; if (!(SWAB32(fat[j]) & 0x0fffffff)) { free++; if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) fat_bpb.fsinfo.nextfree = c; } } } fat_bpb.fsinfo.freecount = free; update_fsinfo();}static int bpb_is_sane(void){ if(fat_bpb.bpb_bytspersec != 512) { DEBUGF( "bpb_is_sane() - Error: sector size is not 512 (%d)\n", fat_bpb.bpb_bytspersec); return -1; } if(fat_bpb.bpb_secperclus * fat_bpb.bpb_bytspersec > 128*1024) { DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K " "(%d * %d = %d)\n", fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus, fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus); return -2; } if(fat_bpb.bpb_numfats != 2) { DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", fat_bpb.bpb_numfats); } if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8) { DEBUGF( "bpb_is_sane() - Warning: Non-standard " "media type (0x%02x)\n", fat_bpb.bpb_media); } if(fat_bpb.last_word != 0xaa55) { DEBUGF( "bpb_is_sane() - Error: Last word is not " "0xaa55 (0x%04x)\n", fat_bpb.last_word); return -3; } if (fat_bpb.fsinfo.freecount > (fat_bpb.totalsectors - fat_bpb.firstdatasector)/ fat_bpb.bpb_secperclus) { DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size " "(0x%04x)\n", fat_bpb.fsinfo.freecount); return -4; } return 0;}static void *cache_fat_sector(int fatsector){ int secnum = fatsector + fat_bpb.bpb_rsvdseccnt; int cache_index = secnum & FAT_CACHE_MASK; struct fat_cache_entry *fce = &fat_cache[cache_index]; unsigned char *sectorbuf = &fat_cache_sectors[cache_index][0]; int rc; /* Delete the cache entry if it isn't the sector we want */ if(fce->inuse && fce->secnum != secnum) { /* Write back if it is dirty */ if(fce->dirty) { rc = ata_write_sectors(fce->secnum+fat_bpb.startsector, 1, sectorbuf); if(rc < 0) { panicf("cache_fat_sector() - Could not write sector %d" " (error %d)\n", secnum, rc); } if(fat_bpb.bpb_numfats > 1) { /* Write to the second FAT */ rc = ata_write_sectors(fce->secnum+fat_bpb.startsector+ fat_bpb.fatsize, 1, sectorbuf); if(rc < 0) { panicf("cache_fat_sector() - Could not write sector %d" " (error %d)\n", secnum + fat_bpb.fatsize, rc); } } } fce->secnum = 8; /* Normally an unused sector */ fce->dirty = false; fce->inuse = false; } /* Load the sector if it is not cached */ if(!fce->inuse) { rc = ata_read_sectors(secnum + fat_bpb.startsector,1, sectorbuf); if(rc < 0) { DEBUGF( "cache_fat_sector() - Could not read sector %d" " (error %d)\n", secnum, rc); return NULL; } fce->inuse = true; fce->secnum = secnum; } return sectorbuf;}static unsigned int find_free_cluster(unsigned int startcluster){ unsigned int sector; unsigned int offset; unsigned int i; sector = startcluster / CLUSTERS_PER_FAT_SECTOR; offset = startcluster % CLUSTERS_PER_FAT_SECTOR; for (i = 0; i<fat_bpb.fatsize; i++) { unsigned int j; unsigned int nr = (i + sector) % fat_bpb.fatsize; unsigned int* fat = cache_fat_sector(nr); if ( !fat ) break; for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { int k = (j + offset) % CLUSTERS_PER_FAT_SECTOR; if (!(SWAB32(fat[k]) & 0x0fffffff)) { unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k; /* Ignore the reserved clusters 0 & 1, and also cluster numbers out of bounds */ if ( c < 2 || c > fat_bpb.dataclusters+1 ) continue; LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); fat_bpb.fsinfo.nextfree = c; return c; } } offset = 0; } LDEBUGF("find_free_cluster(%x) == 0\n",startcluster); return 0; /* 0 is an illegal cluster number */}static int update_fat_entry(unsigned int entry, unsigned int val){ int sector = entry / CLUSTERS_PER_FAT_SECTOR; int offset = entry % CLUSTERS_PER_FAT_SECTOR; unsigned int* sec; LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); if (entry==val) panicf("Creating FAT loop: %x,%x\n",entry,val); if ( entry < 2 ) panicf("Updating reserved FAT entry %d.\n",entry); sec = cache_fat_sector(sector); if (!sec) { DEBUGF( "update_entry() - Could not cache sector %d\n", sector); return -1; } fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; if ( val ) { if (!(SWAB32(sec[offset]) & 0x0fffffff) && fat_bpb.fsinfo.freecount > 0) fat_bpb.fsinfo.freecount--; } else { if (SWAB32(sec[offset]) & 0x0fffffff) fat_bpb.fsinfo.freecount++; } LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); /* don't change top 4 bits */ sec[offset] &= SWAB32(0xf0000000); sec[offset] |= SWAB32(val & 0x0fffffff); return 0;}static int read_fat_entry(unsigned int entry){ int sector = entry / CLUSTERS_PER_FAT_SECTOR; int offset = entry % CLUSTERS_PER_FAT_SECTOR; unsigned int* sec; sec = cache_fat_sector(sector); if (!sec) { DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); return -1; } return SWAB32(sec[offset]) & 0x0fffffff;}static int get_next_cluster(unsigned int cluster){ int next_cluster; next_cluster = read_fat_entry(cluster); /* is this last cluster in chain? */ if ( next_cluster >= FAT_EOF_MARK ) return 0; else return next_cluster;}static int update_fsinfo(void){ unsigned char fsinfo[SECTOR_SIZE]; unsigned int* intptr; int rc; /* update fsinfo */ rc = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo); if (rc < 0) { DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc); return rc * 10 - 1; } intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); *intptr = SWAB32(fat_bpb.fsinfo.freecount); intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]); *intptr = SWAB32(fat_bpb.fsinfo.nextfree); rc = ata_write_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo,1,fsinfo); if (rc < 0) { DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc); return rc * 10 - 2; } return 0;}static int flush_fat(void){ int i; int rc; unsigned char *sec; int secnum; LDEBUGF("flush_fat()\n"); for(i = 0;i < FAT_CACHE_SIZE;i++) { if(fat_cache[i].inuse && fat_cache[i].dirty) { secnum = fat_cache[i].secnum + fat_bpb.startsector; LDEBUGF("Flushing FAT sector %x\n", secnum); sec = fat_cache_sectors[i]; /* Write to the first FAT */ rc = ata_write_sectors(secnum, 1, sec); if(rc) { DEBUGF( "flush_fat() - Couldn't write" " sector %d (error %d)\n", secnum, rc); return rc * 10 - 1; } if(fat_bpb.bpb_numfats > 1 ) { /* Write to the second FAT */ rc = ata_write_sectors(secnum + fat_bpb.fatsize, 1, sec); if (rc) { DEBUGF( "flush_fat() - Couldn't write" " sector %d (error %d)\n", secnum + fat_bpb.fatsize, rc); return rc * 10 - 2; } } fat_cache[i].dirty = false; } } rc = update_fsinfo(); if (rc < 0) return rc * 10 - 3; return 0;}static void fat_time(unsigned short* date, unsigned short* time, unsigned short* tenth ){#ifdef HAVE_RTC struct tm* tm = get_time(); if (date) *date = ((tm->tm_year - 80) << 9) | ((tm->tm_mon + 1) << 5) | tm->tm_mday; if (time) *time = (tm->tm_hour << 11) | (tm->tm_min << 5) | (tm->tm_sec >> 1); if (tenth) *tenth = (tm->tm_sec & 1) * 100;#else /* non-RTC version returns an increment from the supplied time, or a * fixed standard time/date if no time given as input */ bool next_day = false; if (time) { if (0 == *time) { /* set to 00:15:00 */ *time = (15 << 5); } else { unsigned short mins = (*time >> 5) & 0x003F; unsigned short hours = (*time >> 11) & 0x001F; if ((mins += 10) >= 60) { mins = 0; hours++; } if ((++hours) >= 24) { hours = hours - 24; next_day = true; } *time = (hours << 11) | (mins << 5); } } if (date) { if (0 == *date) { /* set to 1 August 2003 */ *date = ((2003 - 1980) << 9) | (8 << 5) | 1; } else { unsigned short day = *date & 0x001F; unsigned short month = (*date >> 5) & 0x000F; unsigned short year = (*date >> 9) & 0x007F; if (next_day) { /* do a very simple day increment - never go above 28 days */ if (++day > 28) { day = 1; if (++month > 12) { month = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -