static floperr_t get_bml3_dirent(imgtool_image *f, int index_loc, struct bml3_dirent *ent) { floperr_t err; UINT8 head, track, sector, offset; UINT8 buf[32]; bml3_diskinfo *info = bml3_get_diskinfo(f); dirent_location(f, index_loc, &head, &track, §or, &offset); err = floppy_read_sector(imgtool_floppy(f), head, track, sector, offset, (void *) buf, sizeof(buf)); memset(ent, 0, sizeof(*ent)); switch (info->variant) { case 0: memcpy(&ent->fname, &buf[0], 8); ent->ftype = buf[11]; ent->asciiflag = buf[12]; ent->first_granule = buf[14]; break; case 1: memcpy(&ent->fname, &buf[0], 8); memcpy(&ent->fext, &buf[8], 3); ent->ftype = buf[11]; ent->asciiflag = buf[12]; ent->first_granule = buf[13]; ent->lastsectorbytes = (buf[14] << 8) | buf[15]; break; default: return FLOPPY_ERROR_INVALIDIMAGE; } return err; }
static imgtoolerr_t imgtool_floppy_transfer_sector_tofrom_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f, int direction) { floperr_t err; floppy_image_legacy *floppy; dynamic_buffer buffer; floppy = imgtool_floppy(img); buffer.resize(length); if (direction) { err = floppy_read_sector(floppy, head, track, sector, offset, buffer, length); if (err) goto done; stream_write(f, buffer, length); } else { stream_read(f, buffer, length); err = floppy_write_sector(floppy, head, track, sector, offset, buffer, length, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } err = FLOPPY_ERROR_SUCCESS; done: return imgtool_floppy_error(err); }
void floppy_write(uint8_t * buf, size_t count, int offset) { int offset_sector = offset / FLOPPY_SECTOR_SIZE; int offset_in_sector = offset % FLOPPY_SECTOR_SIZE; uint32_t cylinder; uint32_t head; uint32_t sector; size_t c; char buffer[FLOPPY_SECTOR_SIZE]; while (count) { cylinder = offset_sector / (FLOPPY_SECTORS_PER_TRACK * FLOPPY_NB_HEADS); head = (offset_sector % (FLOPPY_SECTORS_PER_TRACK * FLOPPY_NB_HEADS)) / (FLOPPY_SECTORS_PER_TRACK); sector = (offset_sector % (FLOPPY_SECTORS_PER_TRACK * FLOPPY_NB_HEADS)) % (FLOPPY_SECTORS_PER_TRACK); floppy_read_sector(cylinder, head, sector, buffer); c = FLOPPY_SECTOR_SIZE - offset_in_sector; if (count <= c) { memcpy(buffer + offset_in_sector, buf, count); count = 0; } else { memcpy(buffer + offset_in_sector, buf, c); count -= c; buf += c; offset_in_sector = 0; offset_sector++; } floppy_write_sector(cylinder, head, sector, buffer); } }
static imgtoolerr_t imgtool_floppy_read_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len) { floperr_t ferr; ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, len); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static floperr_t get_granule_map(imgtool::image &img, uint8_t *granule_map, uint8_t granule_count[MAX_GRANULEMAP_SIZE]) { uint8_t count; count = get_granule_count(img); if (granule_count) *granule_count = count; return floppy_read_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, count); }
/* granule_map must be an array of MAX_GRANULEMAP_SIZE bytes */ static floperr_t get_granule_map(imgtool_image *img, UINT8 *granule_map, UINT8 *granule_count) { UINT8 count; count = get_granule_count(img); if (granule_count) *granule_count = count; return floppy_read_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, count); }
/* granule_map must be an array of MAX_GRANULEMAP_SIZE bytes */ static floperr_t get_granule_map(imgtool_image *img, UINT8 *granule_map, UINT8 *granule_count) { bml3_diskinfo *info = bml3_get_diskinfo(img); UINT8 count; count = get_granule_count(img); if (granule_count) *granule_count = count; // The first byte of the granule map sector is ignored (and expected to be 0) return floppy_read_sector(imgtool_floppy(img), 0, 20, info->fat_start_sector, info->fat_start_offset, granule_map, count); }
static imgtoolerr_t os9_read_lsn(imgtool_image *img, UINT32 lsn, int offset, void *buffer, size_t buffer_len) { imgtoolerr_t err; floperr_t ferr; UINT32 head, track, sector; err = os9_locate_lsn(img, lsn, &head, &track, §or); if (err) return err; ferr = floppy_read_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
/* return the actual data of a sector */ static imgtoolerr_t vzdos_read_sector_data(imgtool_image *img, int track, int sector, UINT8 *data) { int ret, data_start; UINT8 buffer[DATA_SIZE + 4]; /* data + checksum */ ret = vzdos_get_data_start(img, track, sector, &data_start); if (ret) return (imgtoolerr_t)ret; ret = floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, &buffer, sizeof(buffer)); if (ret) return (imgtoolerr_t)ret; /* verify sector checksums */ if (pick_integer_le(buffer, DATA_SIZE + 2, 2) != chksum16(buffer, DATA_SIZE + 2)) return IMGTOOLERR_CORRUPTFILE; memcpy(data, &buffer, DATA_SIZE + 2); return IMGTOOLERR_SUCCESS; }
/* returns the offset where the actual sector data starts */ static imgtoolerr_t vzdos_get_data_start(imgtool_image *img, int track, int sector, int *start) { imgtoolerr_t ret; UINT8 buffer[25]; /* enough to read the sector header */ ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, &buffer, sizeof(buffer)); if (ret) return ret; /* search for start of data */ if (memcmp(buffer + 19, "\xC3\x18\xE7\xFE", 4) == 0) *start = 23; else if (memcmp(buffer + 20, "\xC3\x18\xE7\xFE", 4) == 0) *start = 24; else if (memcmp(buffer + 21, "\xC3\x18\xE7\xFE", 4) == 0) *start = 25; else return IMGTOOLERR_CORRUPTIMAGE; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t imgtool_floppy_transfer_sector_tofrom_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f, int direction) { floperr_t err; floppy_image_legacy *floppy; void *buffer = NULL; floppy = imgtool_floppy(img); buffer = malloc(length); if (!buffer) { err = FLOPPY_ERROR_OUTOFMEMORY; goto done; } if (direction) { err = floppy_read_sector(floppy, head, track, sector, offset, buffer, length); if (err) goto done; stream_write(f, buffer, length); } else { stream_read(f, buffer, length); err = floppy_write_sector(floppy, head, track, sector, offset, buffer, length, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } err = FLOPPY_ERROR_SUCCESS; done: if (buffer) free(buffer); return imgtool_floppy_error(err); }
static floperr_t get_rsdos_dirent(imgtool::image &f, int index_loc, rsdos_dirent &ent) { return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent)); }
static imgtoolerr_t os9_diskimage_open(imgtool_image *image, imgtool_stream *stream) { imgtoolerr_t err; floperr_t ferr; os9_diskinfo *info; UINT32 track_size_in_sectors, i; //, attributes; UINT8 header[256]; UINT32 allocation_bitmap_lsns; UINT8 b, mask; info = os9_get_diskinfo(image); ferr = floppy_read_sector(imgtool_floppy(image), 0, 0, 1, 0, header, sizeof(header)); if (ferr) return imgtool_floppy_error(ferr); info->total_sectors = pick_integer_be(header, 0, 3); track_size_in_sectors = pick_integer_be(header, 3, 1); info->allocation_bitmap_bytes = pick_integer_be(header, 4, 2); info->cluster_size = pick_integer_be(header, 6, 2); info->root_dir_lsn = pick_integer_be(header, 8, 3); info->owner_id = pick_integer_be(header, 11, 2); // attributes = pick_integer_be(header, 13, 1); info->disk_id = pick_integer_be(header, 14, 2); info->format_flags = pick_integer_be(header, 16, 1); info->sectors_per_track = pick_integer_be(header, 17, 2); info->bootstrap_lsn = pick_integer_be(header, 21, 3); info->bootstrap_size = pick_integer_be(header, 24, 2); info->sector_size = pick_integer_be(header, 104, 2); info->sides = (info->format_flags & 0x01) ? 2 : 1; info->double_density = (info->format_flags & 0x02) ? 1 : 0; info->double_track = (info->format_flags & 0x04) ? 1 : 0; info->quad_track_density = (info->format_flags & 0x08) ? 1 : 0; info->octal_track_density = (info->format_flags & 0x10) ? 1 : 0; pick_string(header, 31, 32, info->name); if (info->sector_size == 0) info->sector_size = 256; /* does the root directory and allocation bitmap collide? */ allocation_bitmap_lsns = (info->allocation_bitmap_bytes + info->sector_size - 1) / info->sector_size; if (1 + allocation_bitmap_lsns > info->root_dir_lsn) return IMGTOOLERR_CORRUPTIMAGE; /* is the allocation bitmap too big? */ info->allocation_bitmap = (UINT8*)imgtool_image_malloc(image, info->allocation_bitmap_bytes); if (!info->allocation_bitmap) return IMGTOOLERR_OUTOFMEMORY; memset(info->allocation_bitmap, 0, info->allocation_bitmap_bytes); /* sectors per track and track size don't jive? */ if (info->sectors_per_track != track_size_in_sectors) return IMGTOOLERR_CORRUPTIMAGE; /* zero sectors per track? */ if (info->sectors_per_track == 0) return IMGTOOLERR_CORRUPTIMAGE; /* do we have an odd number of sectors? */ if (info->total_sectors % info->sectors_per_track) return IMGTOOLERR_CORRUPTIMAGE; /* read the allocation bitmap */ for (i = 0; i < allocation_bitmap_lsns; i++) { err = os9_read_lsn(image, 1 + i, 0, &info->allocation_bitmap[i * info->sector_size], MIN(info->allocation_bitmap_bytes - (i * info->sector_size), info->sector_size)); if (err) return err; } /* check to make sure that the allocation bitmap and root sector are reserved */ for (i = 0; i <= allocation_bitmap_lsns; i++) { b = info->allocation_bitmap[i / 8]; mask = 1 << (7 - (i % 8)); if ((b & mask) == 0) return IMGTOOLERR_CORRUPTIMAGE; } return IMGTOOLERR_SUCCESS; }
static floperr_t get_rsdos_dirent(imgtool_image *f, int index_loc, struct rsdos_dirent *ent) { return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) ent, sizeof(*ent)); }
static floperr_t read_granule(imgtool_image *img, UINT8 granule, int offset, int length, UINT8 *buf) { UINT8 head, track, sector; granule_location(img, granule, &head, &track, §or); return floppy_read_sector(imgtool_floppy(img), head, track, sector, offset, buf, length); }
/* deletes directory entry, clears trackmap entries and sectors */ static imgtoolerr_t vzdos_diskimage_deletefile(imgtool_partition *partition, const char *fname) { imgtoolerr_t ret; imgtool_image *img = imgtool_partition_image(partition); int index, filesize, track, sector, next_track, next_sector; vzdos_dirent entry, next_entry; UINT8 buffer[DATA_SIZE + 2]; ret = vzdos_get_dirent_fname(img, fname, &entry); if (ret) return ret; ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, entry.start_track, sector_order[entry.start_sector], 24, &buffer, DATA_SIZE + 2); if (ret) return ret; filesize = entry.end_address - entry.start_address; track = entry.start_track; sector = entry.start_sector; /* delete directory entry */ ret = vzdos_searchentry(img, fname, &index); if (ret) return ret; ret = vzdos_get_dirent(img, index + 1, &next_entry); if (ret == IMGTOOLERR_FILENOTFOUND) { /* we are the last directory entry, just delete it */ ret = vzdos_clear_dirent(img, index); if (ret) return ret; } else if (ret) { /* an error occured */ return ret; } else { ret = vzdos_set_dirent(img, index++, next_entry); if (ret) return ret; while ((ret = vzdos_get_dirent(img, index + 1, &next_entry)) != IMGTOOLERR_FILENOTFOUND) { if (ret) return ret; ret = vzdos_set_dirent(img, index++, next_entry); if (ret) return ret; } ret = vzdos_clear_dirent(img, index); if (ret) return ret; } /* clear sectors and trackmap entries */ while (filesize > 0) { filesize -= DATA_SIZE; /* clear trackmap entry */ ret = vzdos_clear_trackmap(img, track, sector); if (ret) return ret; /* load next track and sector values */ next_track = pick_integer_le(buffer, DATA_SIZE, 1); next_sector = pick_integer_le(buffer, DATA_SIZE + 1, 1); /* overwrite sector with default values */ ret = vzdos_clear_sector(img, track, sector); if (ret) return ret; /* read next sector */ track = next_track; sector = next_sector; if (filesize > 0) { ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], 24, &buffer, DATA_SIZE + 2); if (ret) return ret; } } return IMGTOOLERR_SUCCESS; }