static floperr_t put_bml3_dirent(imgtool_image *f, int index_loc, const struct bml3_dirent *ent) { floperr_t err; UINT8 head, track, sector, offset; UINT8 buf[32]; bml3_diskinfo *info = bml3_get_diskinfo(f); if (index_loc >= max_dirents(f)) return (floperr_t)IMGTOOLERR_FILENOTFOUND; dirent_location(f, index_loc, &head, &track, §or, &offset); memset(buf, 0, sizeof(buf)); switch (info->variant) { case 0: memcpy(&buf[0], &ent->fname, 8); buf[11] = ent->ftype; buf[12] = ent->asciiflag; buf[14] = ent->first_granule; break; case 1: memcpy(&buf[0], &ent->fname, 8); memcpy(&buf[8], &ent->fext, 3); buf[11] = ent->ftype; buf[12] = ent->asciiflag; buf[13] = ent->first_granule; buf[14] = ent->lastsectorbytes >> 8; buf[15] = ent->lastsectorbytes & 0xff; break; default: return FLOPPY_ERROR_INVALIDIMAGE; } err = floppy_write_sector(imgtool_floppy(f), head, track, sector, offset, (void *) buf, sizeof(buf), 0); /* TODO: pass ddam argument from imgtool */ return err; }
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); }
static UINT8 get_granule_count(imgtool_image *img) { UINT16 tracks; UINT16 granules; tracks = floppy_get_tracks_per_disk(imgtool_floppy(img)); granules = (tracks - 1) * 2; return (granules > 255) ? 255 : (UINT8) granules; }
static uint8_t get_granule_count(imgtool::image &img) { uint16_t tracks; uint16_t granules; tracks = floppy_get_tracks_per_disk(imgtool_floppy(img)); granules = (tracks - 1) * 2; return (granules > 255) ? 255 : (uint8_t) granules; }
static imgtoolerr_t imgtool_floppy_write_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam) { floperr_t ferr; ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, len, ddam); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
/* 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); }
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); }
static imgtoolerr_t imgtool_floppy_get_sector_size(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size) { floperr_t ferr; ferr = floppy_get_sector_length(imgtool_floppy(image), head, track, sector, sector_size); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
/* 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; }
/* write data to sector */ static imgtoolerr_t vzdos_write_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; memcpy(buffer, data, DATA_SIZE + 2); place_integer_le(buffer, DATA_SIZE + 2, 2, chksum16(data, DATA_SIZE + 2)); ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, buffer, sizeof(buffer), 0); /* TODO: pass ddam argument from imgtool */ if (ret) return (imgtoolerr_t)ret; return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t os9_write_lsn(imgtool_image *img, UINT32 lsn, int offset, const 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_write_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len, 0); /* TODO: pass ddam argument from imgtool */ if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static imgtoolerr_t bml3_diskimage_open(imgtool_image *image, imgtool_stream *stream) { // imgtoolerr_t err; floperr_t ferr; bml3_diskinfo *info = bml3_get_diskinfo(image); floppy_image_legacy *floppy = imgtool_floppy(image); const struct FloppyCallbacks *callbacks = floppy_callbacks(floppy); // probe disk geometry to guess format int heads_per_disk = callbacks->get_heads_per_disk(floppy); UINT32 sector_length; ferr = callbacks->get_sector_length(floppy, 0, 20, 1, §or_length); if (ferr) return imgtool_floppy_error(ferr); int sectors_per_track = callbacks->get_sectors_per_track(floppy, 0, 20); if (heads_per_disk == 2 && sector_length == 128 && sectors_per_track == 16) { // single-sided, single-density info->sector_size = 128; info->heads = 1; info->fat_start_sector = 1; info->fat_start_offset = 5; info->fat_sectors = 2; info->dirent_start_sector = 7; info->granule_sectors = 4; info->first_granule_cylinder = 0; info->variant = 0; } else if (heads_per_disk == 2 && sector_length == 256 && sectors_per_track == 16) { // double-sided, double-density info->sector_size = 256; info->heads = 2; info->fat_start_sector = 2; info->fat_start_offset = 1; info->fat_sectors = 1; info->dirent_start_sector = 5; info->granule_sectors = 8; info->first_granule_cylinder = 1; info->variant = 1; } else { // invalid or unsupported format return IMGTOOLERR_CORRUPTIMAGE; } 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 vzdos_write_formatted_sector(imgtool_image *img, int track, int sector) { int ret; UINT8 sector_data[DATA_SIZE + 4 + 24]; static const UINT8 sector_header[24] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFE, 0xE7, 0x18, 0xC3, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xC3, 0x18, 0xE7, 0xFE }; memset(sector_data, 0x00, sizeof(sector_data)); memcpy(sector_data, sector_header, sizeof(sector_header)); sector_data[10] = (UINT8) track; /* current track */ sector_data[11] = (UINT8) sector; /* current sector */ sector_data[12] = (UINT8) track + sector; /* checksum-8 */ ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */ if (ret) return (imgtoolerr_t)ret; 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, struct rsdos_dirent *ent) { return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) ent, sizeof(*ent)); }
static floperr_t write_granule(imgtool_image *img, UINT8 granule, int offset, int length, const UINT8 *buf) { UINT8 head, track, sector; granule_location(img, granule, &head, &track, §or); return floppy_write_sector(imgtool_floppy(img), head, track, sector, offset, buf, length, 0); /* TODO: pass ddam argument from imgtool */ }
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); }
static floperr_t put_rsdos_dirent(imgtool::image &f, int index_loc, const rsdos_dirent &ent) { if (index_loc >= MAX_DIRENTS) return (floperr_t)IMGTOOLERR_FILENOTFOUND; return floppy_write_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent), 0); /* TODO: pass ddam argument from imgtool */ }
static void imgtool_floppy_close(imgtool_image *img) { floppy_close(imgtool_floppy(img)); }
static imgtoolerr_t rsdos_diskimage_writefile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions) { floperr_t ferr; imgtoolerr_t err; imgtool::image &img(partition.image()); struct rsdos_dirent ent, ent2; size_t i; uint64_t sz; uint64_t freespace = 0; unsigned char g; unsigned char *gptr; uint8_t granule_count; uint8_t granule_map[MAX_GRANULEMAP_SIZE]; // can we write to this image? if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; err = rsdos_diskimage_freespace(partition, &freespace); if (err) return err; // is there enough space? sz = sourcef.size(); if (sz > freespace) return IMGTOOLERR_NOSPACE; // setup our directory entry err = prepare_dirent(ent, fname); if (err) return err; ent.ftype = writeoptions->lookup_int(RSDOS_OPTIONS_FTYPE); ent.asciiflag = uint8_t(writeoptions->lookup_int(RSDOS_OPTIONS_ASCII)) - 1; ent.lastsectorbytes_lsb = sz % 256; ent.lastsectorbytes_msb = (((sz % 256) == 0) && (sz > 0)) ? 1 : 0; gptr = &ent.first_granule; ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); g = 0x00; do { while (granule_map[g] != 0xff) { g++; if ((g >= granule_count) || (g == 0)) return IMGTOOLERR_UNEXPECTED; // we should have already verified that there is enough space } *gptr = g; gptr = &granule_map[g]; i = std::min(sz, uint64_t(9*256)); err = transfer_to_granule(img, g, i, sourcef); if (err) return err; sz -= i; // go to next granule g++; } while(sz > 0); // now that we are done with the file, we need to specify the final entry // in the file allocation table *gptr = 0xc0 + ((i + 255) / 256); // now we need to find an empty directory entry i = -1; do { ferr = get_rsdos_dirent(img, ++i, ent2); if (ferr) return imgtool_floppy_error(ferr); } while((ent2.filename[0] != '\0') && strcmp(ent.filename, ent2.filename) && (ent2.filename[0] != -1)); // delete file if it already exists if (ent2.filename[0] && (ent2.filename[0] != -1)) { err = delete_entry(img, ent2, i); if (err) return err; } ferr = put_rsdos_dirent(img, i, ent); if (ferr) return imgtool_floppy_error(ferr); // write the granule map back out ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
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 floperr_t put_granule_map(imgtool::image &img, const uint8_t *granule_map, uint8_t granule_count) { return floppy_write_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, granule_count, 0); /* TODO: pass ddam argument from imgtool */ }
static imgtoolerr_t bml3_diskimage_writefile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions) { floperr_t ferr; imgtoolerr_t err; imgtool_image *img = imgtool_partition_image(partition); bml3_diskinfo *info = bml3_get_diskinfo(img); struct bml3_dirent ent, ent2; size_t i; UINT64 sz, read_sz; UINT64 freespace = 0; unsigned char g; unsigned char *gptr; UINT8 granule_count; UINT8 granule_map[MAX_GRANULEMAP_SIZE]; UINT8 eof_buf[MAX_SECTOR_SIZE]; // one-time setup of eof_buf memset(eof_buf, 0, sizeof(eof_buf)); eof_buf[0] = 0x1A; /* can we write to this image? */ if (floppy_is_read_only(imgtool_floppy(img))) return IMGTOOLERR_READONLY; err = bml3_diskimage_freespace(partition, &freespace); if (err) return err; /* is there enough space? */ sz = read_sz = stream_size(sourcef); if (info->variant == 0) { // also need to write EOF sz++; } if (sz > freespace) return IMGTOOLERR_NOSPACE; /* setup our directory entry */ err = prepare_dirent(info->variant, &ent, fname); if (err) return err; ent.ftype = option_resolution_lookup_int(writeoptions, BML3_OPTIONS_FTYPE); ent.asciiflag = ((UINT8) option_resolution_lookup_int(writeoptions, BML3_OPTIONS_ASCII)) - 1; gptr = &ent.first_granule; ferr = get_granule_map(img, granule_map, &granule_count); if (ferr) return imgtool_floppy_error(ferr); g = 0x00; do { while (granule_map[g] != 0xff) { g++; if ((g >= granule_count) || (g == 0)) return IMGTOOLERR_UNEXPECTED; /* We should have already verified that there is enough space */ } *gptr = g; gptr = &granule_map[g]; i = MIN(read_sz, info->granule_sectors * info->sector_size); if (i > 0) { err = transfer_to_granule(img, g, i, sourcef); if (err) return err; read_sz -= i; sz -= i; } if (i < info->granule_sectors * info->sector_size && sz > 0) { // write EOF and trailing NULs in the final sector ferr = write_granule(img, g, i, (info->granule_sectors * info->sector_size - i - 1) % info->sector_size + 1, eof_buf); if (ferr) return imgtool_floppy_error(ferr); sz--; i++; } /* Go to next granule */ g++; } while(sz > 0); /* Now that we are done with the file, we need to specify the final entry * in the file allocation table */ *gptr = 0xc0 + ((i + info->sector_size-1) / info->sector_size) - (info->variant == 0 ? 1 : 0); ent.lastsectorbytes = (i - 1) % info->sector_size + 1; /* delete file if it already exists */ err = bml3_diskimage_deletefile(partition, fname); if (err && err != IMGTOOLERR_FILENOTFOUND) return err; /* Now we need to find an empty directory entry */ i = -1; do { ferr = get_bml3_dirent(img, ++i, &ent2); if (ferr) return imgtool_floppy_error(ferr); } while(ent2.fname[0] != '\0' && ent2.fname[0] != -1); ferr = put_bml3_dirent(img, i, &ent); if (ferr) return imgtool_floppy_error(ferr); /* write the granule map back out */ ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; }
static floperr_t put_granule_map(imgtool_image *img, const UINT8 *granule_map, UINT8 granule_count) { return floppy_write_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, granule_count, 0); /* TODO: pass ddam argument from imgtool */ }
static imgtoolerr_t os9_diskimage_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts) { imgtoolerr_t err; dynamic_buffer header; UINT32 heads, tracks, sectors, sector_bytes, first_sector_id; UINT32 cluster_size, owner_id; UINT32 allocation_bitmap_bits, allocation_bitmap_lsns; UINT32 attributes, format_flags, disk_id; UINT32 i; INT32 total_allocated_sectors; const char *title; time_t t; struct tm *ltime; time(&t); ltime = localtime(&t); heads = option_resolution_lookup_int(opts, 'H'); tracks = option_resolution_lookup_int(opts, 'T'); sectors = option_resolution_lookup_int(opts, 'S'); sector_bytes = option_resolution_lookup_int(opts, 'L'); first_sector_id = option_resolution_lookup_int(opts, 'F'); title = ""; header.resize(sector_bytes); if (sector_bytes > 256) sector_bytes = 256; cluster_size = 1; owner_id = 1; disk_id = 1; attributes = 0; allocation_bitmap_bits = heads * tracks * sectors / cluster_size; allocation_bitmap_lsns = (allocation_bitmap_bits / 8 + sector_bytes - 1) / sector_bytes; format_flags = ((heads > 1) ? 0x01 : 0x00) | ((tracks > 40) ? 0x02 : 0x00); memset(&header[0], 0, sector_bytes); place_integer_be(&header[0], 0, 3, heads * tracks * sectors); place_integer_be(&header[0], 3, 1, sectors); place_integer_be(&header[0], 4, 2, (allocation_bitmap_bits + 7) / 8); place_integer_be(&header[0], 6, 2, cluster_size); place_integer_be(&header[0], 8, 3, 1 + allocation_bitmap_lsns); place_integer_be(&header[0], 11, 2, owner_id); place_integer_be(&header[0], 13, 1, attributes); place_integer_be(&header[0], 14, 2, disk_id); place_integer_be(&header[0], 16, 1, format_flags); place_integer_be(&header[0], 17, 2, sectors); place_string(&header[0], 31, 32, title); place_integer_be(&header[0], 103, 2, sector_bytes / 256); /* path descriptor options */ place_integer_be(&header[0], 0x3f+0x00, 1, 1); /* device class */ place_integer_be(&header[0], 0x3f+0x01, 1, 1); /* drive number */ place_integer_be(&header[0], 0x3f+0x03, 1, 0x20); /* device type */ place_integer_be(&header[0], 0x3f+0x04, 1, 1); /* density capability */ place_integer_be(&header[0], 0x3f+0x05, 2, tracks); /* number of tracks */ place_integer_be(&header[0], 0x3f+0x07, 1, heads); /* number of sides */ place_integer_be(&header[0], 0x3f+0x09, 2, sectors); /* sectors per track */ place_integer_be(&header[0], 0x3f+0x0b, 2, sectors); /* sectors on track zero */ place_integer_be(&header[0], 0x3f+0x0d, 1, 3); /* sector interleave factor */ place_integer_be(&header[0], 0x3f+0x0e, 1, 8); /* default sectors per allocation */ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 7; for (i = 0; i < allocation_bitmap_lsns; i++) { memset(&header[0], 0x00, sector_bytes); if (total_allocated_sectors > (8 * 256)) { memset(&header[0], 0xff, sector_bytes); total_allocated_sectors -= (8 * 256); } else if (total_allocated_sectors > 1 ) { int offset; UINT8 mask; while( total_allocated_sectors >= 0 ) { offset = total_allocated_sectors / 8; mask = 1 << (7 - ( total_allocated_sectors % 8 ) ); header[offset] |= mask; total_allocated_sectors--; } } err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + i, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; } memset(&header[0], 0, sector_bytes); header[0x00] = 0xBF; header[0x01] = 0x00; header[0x02] = 0x00; header[0x03] = (UINT8) ltime->tm_year; header[0x04] = (UINT8) ltime->tm_mon + 1; header[0x05] = (UINT8) ltime->tm_mday; header[0x06] = (UINT8) ltime->tm_hour; header[0x07] = (UINT8) ltime->tm_min; header[0x08] = 0x02; header[0x09] = 0x00; header[0x0A] = 0x00; header[0x0B] = 0x00; header[0x0C] = 0x40; header[0x0D] = (UINT8) (ltime->tm_year % 100); header[0x0E] = (UINT8) ltime->tm_mon; header[0x0F] = (UINT8) ltime->tm_mday; place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1); place_integer_be(&header[0], 0x13, 2, 8); err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */ if (err) goto done; memset(&header[0], 0, sector_bytes); header[0x00] = 0x2E; header[0x01] = 0xAE; header[0x1F] = 1 + allocation_bitmap_lsns; header[0x20] = 0xAE; header[0x3F] = 1 + allocation_bitmap_lsns; err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 2 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TOOD: pass ddam argument from imgtool */ if (err) goto done; done: return err; }
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; }