Artifact [6c6d395245]

Artifact 6c6d3952456652cb7df9eb52248b376689a1878e:


#include <stdint.h>
#include <scsi/sg.h>
#include <unistd.h>
#include <endian.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <string.h>

#define JQ6500_CM

struct jqcmd {
    uint16_t j_cmd;
    uint32_t j_off;
    uint32_t j_foo;
    uint32_t j_len;
} __attribute__((packed));

#define BASE 0x40000
#define MAXSIZE 0x200000 - BASE /* 2MB - 256kB */

off_t
filesize(char *file)
{
    int result;
    struct stat buf;
    result = stat(file, &buf);
    if (result != 0)
	err(1, "cannot stat %s", file);
    return buf.st_size;
}

void
w32le(uint8_t **loc, uint32_t val)
{
    memcpy(*loc, &htole32(val), 4);
    (*loc) += 4;
}

int
main(int argc, char **argv)
{
    uint8_t buf[MAXSIZE];
    uint8_t *dir, *data;
  
    int count, size, dev;
    int i, len;
  
    if (argc < 3) {
	fprintf(stderr, "%s device mp3file ...\n", argv[0]);
	return 1;
    }

    memset(buf, 0xff, MAXSIZE);

    count = argc-2;
    dir = buf;
    size = (3 + 2 * count) * 4;
    data = dir + size;

    w32le(&dir, 1);		/* Number of Subdirs */
    w32le(&dir, BASE + 8);	/* Offset of first subdir */
    w32le(&dir, count);		/* Number of files in subdir 1 */

    for (i = 0; i < count; i++) {
	int fd;
	char *fname = argv[i+2];
	len = filesize(fname);
	size += len;
	if (size >= MAXSIZE) {
	    fprintf(stderr, "length %d exceeds maximum of %d", size, MAXSIZE);
	    return 1;
	}
	fd = open(fname, O_RDONLY);
	if (fd < 0) 
	    err(1, "cannot open %s", fname);
	if (read(fd, data, len) != len) 
	    err(1, "cannot read %s", fname);
	close(fd);
	w32le(&dir, BASE + data - buf);	/* File offset */
	w32le(&dir, len);		/* File length */
	data += len;
    }
    
#define ERASE 0xfbd8
#define WRITE 0xfbd9
#define BLKSZ 0x1000
#define TIMEOUT 30000

    dev = open(argv[1], O_RDWR);
    if (dev < 0)
	err(1, "cannot open device %s", argv[1]);
    
    for (i = 0; i < size; i += BLKSZ) {
	
	struct jqcmd cmd;
	struct sg_io_hdr hdr;

	memset(&cmd, 0, sizeof(cmd));
	cmd.j_cmd = htobe16(ERASE);
	cmd.j_off = htobe32(BASE + i);

	memset(&hdr, 0, sizeof(hdr));
	hdr.interface_id = 'S';
	hdr.timeout = TIMEOUT;
	hdr.cmdp = (unsigned char *) &cmd;
	hdr.cmd_len = sizeof(cmd);
	hdr.dxfer_direction = SG_DXFER_NONE;

	if (ioctl(dev, SG_IO, &hdr) < 0)
	    err(1, "erase failed");

	memset(&cmd, 0, sizeof(cmd));
	cmd.j_cmd = htobe16(WRITE);
	cmd.j_off = htobe32(BASE + i);
	cmd.j_len = htobe32(BLKSZ);

	memset(&hdr, 0, sizeof(hdr));
	hdr.interface_id = 'S';
	hdr.timeout = TIMEOUT;
	hdr.cmdp = (unsigned char *) &cmd;
	hdr.cmd_len = sizeof(cmd);
	hdr.dxfer_direction = SG_DXFER_TO_DEV;
	hdr.dxferp = buf + i;
	hdr.dxfer_len = BLKSZ;
	
	if (ioctl(dev, SG_IO, &hdr) < 0)
	    err(1, "erase failed at offset %x", BASE + i);
	fprintf(stderr, "%06x/\n", BASE + i, BASE + size);
    }
    close(dev);
    return 0;
}