fx_rtn fx_write_panic0(u32_t pstart, u32_t pend) { panic0_hdr_t *p; uint16_t *ptr, i, sum; assert(fx_buf); memset(fx_buf, 0, MS_BUF_SIZE); p = (void *) fx_buf; p->sig_a = CT_LE_32(PANIC0_MAJIK); p0c.sig_a = CF_LE_32(p->sig_a); p->panic_start = CT_LE_32(pstart); p0c.panic_start= CF_LE_32(p->panic_start); p->panic_nxt = CT_LE_32(pstart); p0c.panic_nxt = CF_LE_32(p->panic_nxt); p->panic_end = CT_LE_32(pend); p0c.panic_end = CF_LE_32(p->panic_end); p->fubar = 0; p0c.fubar = 0; p->sig_b = CT_LE_32(PANIC0_MAJIK); p0c.sig_b = CF_LE_32(p->sig_b); p->chksum = 0; ptr = (void *) p; sum = 0; for (i = 0; i < PANIC0_SIZE_SHORTS; i++) sum += CF_LE_16(ptr[i]); p->chksum = CT_LE_16((uint16_t) (0 - sum)); p0c.chksum = CF_LE_16(p->chksum); assert(!ms_write_blk(PANIC0_SECTOR, fx_buf)); return(FX_OK); }
fx_rtn fx_cap_dblk(char *name, char *ext, char *n_name, char *n_ext, u32_t size, fat_dir_entry_t **rtn_de) { fat_dir_entry_t *de, *n_de; u32_t rds, n_rds, o_size, cluster; u32_t *fat, fat_sector, fat_offset; assert(fx_buf); if (strlen(name) != 8 || strlen(ext) != 3 || strlen(n_name) != 8 || strlen(n_ext) != 3) return(FX_INTERNAL); /* check to see if new name already exists */ de = f32_get_de(n_name, n_ext, &rds); if (de) return(FX_EXIST); de = f32_get_de(name, ext, &rds); if (!de) return(FX_NOT_FOUND); if (size >= CF_LE_32(de->size)) return(FX_INTERNAL); if (!f32_find_empty(&n_de, &n_rds)) return(FX_NO_ROOM); /* * read dir entry of original file and tweak size. */ assert(! ms_read_blk(rds, fx_buf)); o_size = CF_LE_32(de->size); de->size = CT_LE_32(size); assert(! ms_write_blk(rds, fx_buf)); /* * compute eof cluster. write it to eof. */ cluster = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); cluster += (size + (FX_CLUSTER_SIZE * SECTOR_SIZE - 1))/(FX_CLUSTER_SIZE * SECTOR_SIZE) - 1; fat_sector = FAT_SECTOR(cluster) + fx_fat_start; fat_offset = FAT_OFFSET(cluster); assert(! ms_read_blk(fat_sector, fx_buf)); fat = fx_buf; fat[fat_offset] = CT_LE_32(EOF_FAT32); assert(! ms_write_blk(fat_sector, fx_buf)); /* * now read the directory sector for the new file */ cluster++; assert(! ms_read_blk(n_rds, fx_buf)); memcpy(n_de->name, n_name, 8); memcpy(n_de->ext, n_ext, 3); n_de->starthi = CT_LE_16(cluster >> 16); n_de->start = CT_LE_16(cluster & 0xffff); size += (FX_CLUSTER_SIZE * SECTOR_SIZE - 1); size &= ~FX_CB_MASK; /* round up to next cluster */ n_de->size = CT_LE_32(o_size - size); assert(! ms_write_blk(n_rds, fx_buf)); return(FX_OK); }
static bool_t f32_get_chain(u32_t cluster, u32_t *start, u32_t *end) { u32_t fat_sector, nxt_cluster; uint8_t fat_offset; u32_t *fats; *start = 0; *end = 0; cluster &= FAT32_CLUSTER_MASK; if (cluster < 2 || cluster > fx_max_cluster) { fprintf(stderr, "*** bad cluster, %lu\n", cluster); return(FALSE); } fat_sector = FAT_SECTOR(cluster); fat_sector += fx_fat_start; if (fat_sector > fx_fat_end) { fprintf(stderr, "*** bad fat sector: %lu\n", fat_sector); return(FALSE); } fat_offset = FAT_OFFSET(cluster); assert(!ms_read_blk(fat_sector, fx_buf)); fats = fx_buf; *start = clu2sec(cluster); nxt_cluster = CF_LE_32(fats[fat_offset]) & FAT32_CLUSTER_MASK; while (nxt_cluster < EOF_FAT32 && nxt_cluster >= 2 && nxt_cluster == cluster + 1) { cluster++; fat_offset++; if (fat_offset > FAT_MAX_OFFSET) { fat_sector++; fat_offset = 0; if (fat_sector > fx_fat_end) { fprintf(stderr, "*** fat_sector (%lu) > fx_fat_end (%lu)\n", fat_sector, fx_fat_end); return(FALSE); } assert(!ms_read_blk(fat_sector, fx_buf)); } nxt_cluster = CF_LE_32(fats[fat_offset]) & FAT32_CLUSTER_MASK; if (nxt_cluster == BAD_FAT32) { fprintf(stderr, "*** nxt_cluster is BAD_FAT32, %lu\n", nxt_cluster); return(FALSE); } } if (nxt_cluster >= EOF_FAT32) { *end = clu2sec(cluster + 1) - 1; return(TRUE); } *start = 0; *end = 0; return(FALSE); }
void display_info(void) { fat_dir_entry_t *de; u32_t rds; fprintf(stderr, "fs_loc: p: s: %-8x e: %x\n", loc.locators[FS_LOC_PANIC].start, loc.locators[FS_LOC_PANIC].end); fprintf(stderr, " c: s: %-8x e: %x\n", loc.locators[FS_LOC_CONFIG].start, loc.locators[FS_LOC_CONFIG].end); fprintf(stderr, " i: s: %-8x e: %x\n", loc.locators[FS_LOC_IMAGE].start, loc.locators[FS_LOC_IMAGE].end); fprintf(stderr, " d: s: %-8x e: %-8x n: %x\n", loc.locators[FS_LOC_DBLK].start, loc.locators[FS_LOC_DBLK].end, msc_dblk_nxt); if (p0c.panic_start) fprintf(stderr, "panic0: p: %-8x %-8x (nxt) %-8x\n", p0c.panic_start, p0c.panic_end, p0c.panic_nxt); else fprintf(stderr, "panic0: no panic0 block\n"); de = f32_get_de("PANIC001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "PANIC001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "PANIC001: not found\n"); de = f32_get_de("CNFG0001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "CNFG0001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "CNFG0001: not found\n"); de = f32_get_de("IMAGE001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "IMAGE001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "IMAGE001: not found\n"); de = f32_get_de("DBLK0001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "DBLK0001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "DBLK0001: not found\n"); }
void display_info(void) { fat_dir_entry_t *de; u32_t rds; if (msc.dblk_start) { fprintf(stderr, "dblk_loc: p: %-8x %-8x\n", msc.panic_start, msc.panic_end); fprintf(stderr, " c: %-8x %-8x\n", msc.config_start, msc.config_end); fprintf(stderr, " d: %-8x %-8x (nxt) %-8x\n", msc.dblk_start, msc.dblk_end, msc.dblk_nxt); } if (p0c.panic_start) fprintf(stderr, "panic0: p: %-8x %-8x (nxt) %-8x\n", p0c.panic_start, p0c.panic_end, p0c.panic_nxt); else fprintf(stderr, "panic0: no panic0 block\n"); de = f32_get_de("PANIC001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "PANIC001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "PANIC001: not found\n"); de = f32_get_de("CNFG0001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "CNFG0001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "CNFG0001: not found\n"); de = f32_get_de("DBLK0001", " ", &rds); if (de) { rds = (CF_LE_16(de->starthi) << 16) | CF_LE_16(de->start); fprintf(stderr, "DBLK0001: start 0x%04x size: %10u (0x%x)\n", fx_clu2sec(rds), CF_LE_32(de->size), CF_LE_32(de->size)); } else fprintf(stderr, "DBLK0001: not found\n"); }
fx_rtn fx_create_contig(char *name, char *ext, u32_t size, u32_t *s, u32_t *e) { u32_t *fat; u32_t max, max_count, start, count; u32_t fat_sector, i, limit; fat_dir_entry_t *de; info_sector_t *info; uint8_t offset; int done; assert(fx_buf); if (strlen(name) != 8 || strlen(ext) != 3) return(FX_INTERNAL); if (fx_find_file(name, ext, &start, &count) != FX_NOT_FOUND) return(FX_EXIST); fat = fx_buf; start = count = max = max_count = done = 0; for (fat_sector = fx_fat_start; fat_sector <= fx_fat_end; fat_sector++) { assert(!ms_read_blk(fat_sector, fx_buf)); for (i = (fat_sector == fx_fat_start ? 2 : 0); i <= (fat_sector == fx_fat_end ? (fx_max_cluster & FAT32_CPB_MASK) : FAT32_CPB_MASK); i++) { if ((fat[i] & CT_LE_32(FAT32_CLUSTER_MASK)) == 0) { /* swap constant, compile time */ switch(start) { case 0: start = ((fat_sector - fx_fat_start) << FAT32_CPB_BITS) + i; count = 1; break; default: count++; if (size && count * FX_CLUSTER_SIZE * SECTOR_SIZE >= size) done = 1; break; } if (done) break; } else switch(start) { case 0: break; default: if (count > max_count) { max = start; max_count = count; } start = count = 0; break; } } if (done) break; } if (start && count > max_count) { max = start; max_count = count; } if (debug) { printf("create_contig: size: %lx s: %lx, count: %lx\n", size, max, max_count); printf(" clusters: %lx-%lx, sectors: %lx-%lx, size: %lx\n", max, max + max_count - 1, clu2sec(max), clu2sec(max + max_count) - 1, max_count * FX_CLUSTER_SIZE * SECTOR_SIZE); } *s = clu2sec(max); *e = clu2sec(max + max_count) - 1; if (max == 0) return(FX_NO_ROOM); assert(max + max_count - 1 <= fx_data_end); if (!f32_find_empty(&de, &i)) return(FX_NO_ROOM); memset(de, 0, sizeof(fat_dir_entry_t)); strncpy((char *) de->name, name, 8); strncpy((char *) de->ext, ext, 3); de->attr = ATTR_NONE; de->starthi = CT_LE_16(max >> 16); de->start = CT_LE_16(max & 0xffff); de->size = CT_LE_32(max_count * FX_CLUSTER_SIZE * SECTOR_SIZE); assert(! ms_write_blk(i, fx_buf)); /* now rerun through the FAT changing the chain */ fat_sector = FAT_SECTOR(max) + fx_fat_start; offset = FAT_OFFSET(max); assert(!ms_read_blk(fat_sector, fx_buf)); fat = fx_buf; limit = max + max_count; /* one past last */ for (start = max + 1; start <= limit; start++) { fat[offset] = (start == limit ? CT_LE_32(EOF_FAT32) : CT_LE_32(start)); offset++; if (offset > FAT_MAX_OFFSET) { assert(!ms_write_blk(fat_sector, fx_buf)); assert(!ms_write_blk(fat_sector + fx_fat_size, fx_buf)); fat_sector++; assert(!ms_read_blk(fat_sector, fx_buf)); offset = 0; } } if (offset) { assert(!ms_write_blk(fat_sector, fx_buf)); assert(!ms_write_blk(fat_sector + fx_fat_size, fx_buf)); } if (fx_info_sector) { assert(!ms_read_blk(fx_info_sector, fx_buf)); info = fx_buf; if (info->boot_sig == CT_LE_16(BOOT_SIG) && IS_FSINFO(info)) { info->free_clusters = CT_LE_32((u32_t) -1); info->next_cluster = CF_LE_32((u32_t) -1); assert(!ms_write_blk(fx_info_sector, fx_buf)); } else fx_info_sector = 0; fx_free_clusters = (u32_t) -1; fx_next_cluster = (u32_t) -1; } return(FX_OK); }
fx_rtn fx_init(void) { boot_sector_t *bs; info_sector_t *info; mbr_t *mbr; u32_t start, size; assert(fx_buf); assert(! ms_read_blk(0, fx_buf)); /* First sector is either an MBR or the boot_sector of the partition. It * had better have the 2 byte signature at the end. ie. 0xaa55. * * Start by looking for a boot sector rather than the MBR. */ bs = fx_buf; if (bs->sig != CT_LE_16(BOOT_SIG)) return(FX_BAD_BOOT_SIG); start = fx_data_start = 0; if ( ! fat32_boot_sector(bs)) { /* * something doesn't look right. Look at the sector as an MBR and see * if it makes sense. We only look at partition 1. */ mbr = fx_buf; start = (mbr->p1.start4[3] << 24) | (mbr->p1.start4[2] << 16) | (mbr->p1.start4[1] << 8) | mbr->p1.start4[0]; size = (mbr->p1.size4[3] << 24) | (mbr->p1.size4[2] << 16) | (mbr->p1.size4[1] << 8 ) | mbr->p1.size4[0]; /* check for reasonableness, boot_ind can be 0x00 or 0x80 */ if ((mbr->p1.boot_ind != 0 && mbr->p1.boot_ind != 0x80) || !fat32_part(mbr->p1.part_type) || /* reasonable fat32 partition? */ start == 0 || /* can't start at 0 */ size == 0) /* zero means nothing, bail */ return(FX_NO_PARTITION); assert(! ms_read_blk(start, fx_buf)); bs = fx_buf; if (CF_LE_16(bs->sig) != BOOT_SIG) return(FX_BAD_BOOT_SIG); if (!fat32_boot_sector(bs)) /* make sure what we got is good */ return(FX_NO_PARTITION); /* check mbr partition size vs. total_sect entry in the file system header only accept if the same or if file system size is one less than the partition header */ if (size != CF_LE_32(bs->total_sect)) { /* and partition size should match internal */ if (debug) printf("*** mbr/fs size mismatch: mbr: %lu (%lx), fs: %lu (%lx)\n", size, size, CF_LE_32(bs->total_sect), CF_LE_32(bs->total_sect)); if (size != CF_LE_32(bs->total_sect) + 1) return(FX_SIZE_MISMATCH); } fx_data_start = start; } if (debug) printf("Partition start: %lx, size: %lx\n", (u32_t) fx_data_start, CF_LE_32(bs->total_sect)); /* buf contains the boot_sector. compute total data sectors and make sure that it conforms to FAT32. */ fx_cluster_size = bs->cluster_size; /* u8 */ fx_reserved = CF_LE_16(bs->reserved); fx_num_fats = bs->fats; /* u8 */ fx_total_sectors = CF_LE_32(bs->total_sect); fx_fat_size = CF_LE_32(bs->fat32_length); fx_info_sector = start + CF_LE_16(bs->info_sector); fx_data_end = fx_data_start + fx_total_sectors - 1; fx_fat_start = fx_data_start + fx_reserved; fx_fat_end = fx_fat_start + fx_fat_size - 1; fx_data_start = fx_fat_start + fx_fat_size * FX_NUM_FATS; size = fx_total_sectors; size -= (fx_reserved + (fx_fat_size * fx_num_fats)); fx_max_cluster = size/fx_cluster_size; /* last cluster */ if (debug) printf("phys data sectors: %lx, phys clusters: %lx, unused sectors: %lx\n", size, fx_max_cluster, size - fx_max_cluster * fx_cluster_size); if (fx_max_cluster < 65525) /* if less, not FAT32 */ return(FX_NOT_FAT32); fx_max_cluster++; /* make into cluster id */ fx_data_end = clu2sec(fx_max_cluster + 1) - 1; /* get last usable data sector */ if (fx_cluster_size != FX_CLUSTER_SIZE) fprintf(stderr, "*** bad fx_cluster_size (%u) should be (%u)\n", fx_cluster_size, FX_CLUSTER_SIZE); if (fx_num_fats != FX_NUM_FATS) fprintf(stderr, "*** wrong number of FATS: (%u) should be (%u)\n", fx_num_fats, FX_NUM_FATS); f32_get_chain(CF_LE_32(bs->root_cluster), &fx_rdir_start, &fx_rdir_end); assert(fx_rdir_start && fx_rdir_end); assert(!ms_read_blk(fx_info_sector, fx_buf)); info = fx_buf; if (info->boot_sig == CT_LE_16(BOOT_SIG) && IS_FSINFO(info)) { fx_free_clusters = CF_LE_32(info->free_clusters); fx_next_cluster = CF_LE_32(info->next_cluster); } else { fx_info_sector = 0; fx_free_clusters = (u32_t) -1; fx_next_cluster = (u32_t) -1; } if (debug) { printf("ts: %lx, r: %x, fat_s: %lx, n: %d, ds: %lx\n", fx_total_sectors, fx_reserved, fx_fat_size, fx_num_fats, fx_total_sectors-fx_reserved-(fx_num_fats*fx_fat_size)); printf("fat_size (secs): %lx, (clus) %lx, %lx bytes\n", fx_fat_size, fx_fat_size * SECTOR_SIZE / sizeof(u32_t), fx_fat_size * SECTOR_SIZE); printf("data_start: %lx, end: %lx, usable sectors: %lx, last phys sector: %lx\n", fx_data_start, fx_data_end, fx_data_end - fx_data_start + 1, /* usable */ fx_data_start + (fx_total_sectors - fx_reserved - (fx_num_fats * fx_fat_size)) - 1); printf("unused fat entries: %lx, cluster ids: 2 - %lx\n", (fx_fat_end - fx_fat_start + 1) * FAT32_CPB - (fx_max_cluster + 1), fx_max_cluster); printf("Last cluster: %lx, sectors: %lx - %lx, fat sector: %lx, off: %lx\n", fx_max_cluster, clu2sec(fx_max_cluster), clu2sec(fx_max_cluster + 1) - 1, FAT_SECTOR(fx_max_cluster) + fx_fat_start, FAT_OFFSET(fx_max_cluster)); printf(" fat_start: %5lx, fat_end: %5lx\n", fx_fat_start, fx_fat_end); printf(" info: free %5lx, next: %5lx\n", fx_free_clusters, fx_next_cluster); } return(FX_OK); }