Files
poky/meta/recipes-devtools/qemu/qemu-helper/raw2flash.c
Richard Purdie 29d6678fd5 Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things
and is generally overwhelming. This commit splits it into several
logical sections roughly based on function, recipes.txt gives more
information about the classifications used.

The opportunity is also used to switch from "packages" to "recipes"
as used in OpenEmbedded as the term "packages" can be confusing to
people and has many different meanings.

Not all recipes have been classified yet, this is just a first pass
at separating things out. Some packages are moved to meta-extras as
they're no longer actively used or maintained.

Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
2010-08-27 15:29:45 +01:00

371 lines
9.7 KiB
C

/*
* Copyright (c) 2006 OpenedHand Ltd.
*
* This file is licensed under GNU GPL v2.
*/
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#define TFR(_) _
#define VERBOSE
#define PBAR_LEN 40
#define PARTITION_START 0x00700000
static const int ecc_pos8[] = {
0x0, 0x1, 0x2,
};
static const int ecc_pos16[] = {
0x0, 0x1, 0x2, 0x3, 0x6, 0x7,
};
static const int ecc_pos64[] = {
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
};
static const int ecc_akita[] = {
0x05, 0x01, 0x02, 0x03, 0x06, 0x07, 0x15, 0x11,
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37,
};
struct jffs_marker_s {
int pos;
uint8_t value;
};
static const struct jffs_marker_s free_pos8[] = {
{ 0x03, 0xff }, { 0x04, 0xff }, { 0x06, 0x85 }, { 0x07, 0x19 },
{ -1 },
};
static const struct jffs_marker_s free_pos16[] = {
{ 0x08, 0x85 }, { 0x09, 0x19 }, { 0x0a, 0x03 }, { 0x0b, 0x20 },
{ 0x0c, 0x08 }, { 0x0d, 0x00 }, { 0x0e, 0x00 }, { 0x0f, 0x00 },
{ -1 },
};
static const struct jffs_marker_s free_pos64[] = {
{ 0x02, 0xff }, { 0x03, 0xff }, { 0x04, 0xff }, { 0x05, 0xff },
{ 0x06, 0xff }, { 0x07, 0xff }, { 0x08, 0xff }, { 0x09, 0xff },
{ 0x0a, 0xff }, { 0x0b, 0xff }, { 0x0c, 0xff }, { 0x0d, 0xff },
{ 0x0e, 0xff }, { 0x0f, 0xff }, { 0x10, 0x85 }, { 0x11, 0x19 },
{ 0x12, 0x03 }, { 0x13, 0x20 }, { 0x14, 0x08 }, { 0x15, 0x00 },
{ 0x16, 0x00 }, { 0x17, 0x00 }, { 0x18, 0xff }, { 0x19, 0xff },
{ 0x1a, 0xff }, { 0x1b, 0xff }, { 0x1c, 0xff }, { 0x1d, 0xff },
{ 0x1e, 0xff }, { 0x1f, 0xff }, { 0x20, 0xff }, { 0x21, 0xff },
{ 0x22, 0xff }, { 0x23, 0xff }, { 0x24, 0xff }, { 0x25, 0xff },
{ 0x26, 0xff }, { 0x27, 0xff },
{ -1 },
};
static const struct jffs_marker_s free_akita[] = {
{ 0x08, 0x85 }, { 0x09, 0x19 }, { 0x0a, 0x03 }, { 0x0b, 0x20 },
{ 0x0c, 0x08 }, { 0x0d, 0x00 }, { 0x0e, 0x00 }, { 0x0f, 0x00 },
{ 0x10, 0xff },
{ -1 },
};
#define LEN(array) (sizeof(array) / sizeof(*array))
static const struct ecc_style_s {
int page_size;
int oob_size;
int eccbytes;
int eccsize;
const int *eccpos;
int romsize;
const struct jffs_marker_s *freepos;
} spitz = {
0x200, 0x10, 0x100, LEN(ecc_pos16), ecc_pos16, 0x01000000, free_pos16
}, akita = {
0x800, 0x40, 0x100, LEN(ecc_akita), ecc_akita, 0x08000000, free_akita
}, borzoi = {
0x800, 0x40, 0x100, LEN(ecc_akita), ecc_akita, 0x08000000, free_akita
}, terrier = {
0x800, 0x40, 0x100, LEN(ecc_akita), ecc_akita, 0x08000000, free_akita
};
struct ecc_state_s {
int count;
uint8_t cp;
uint8_t lp[2];
const struct ecc_style_s *style;
};
#ifndef flash2raw
/*
* Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
*/
static const uint8_t ecc_precalc_table[] = {
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
};
/* Update ECC parity count */
static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample) {
uint8_t idx = ecc_precalc_table[sample];
s->cp ^= idx & 0x3f;
if (idx & 0x40) {
s->lp[0] ^= ~(s->count & 0xff);
s->lp[1] ^= s->count & 0xff;
}
s->count ++;
return sample;
}
static void buffer_digest(struct ecc_state_s *ecc,
const uint8_t *buf, uint8_t *out) {
int i, lp_a[2];
ecc->lp[0] = 0x00;
ecc->lp[1] = 0x00;
ecc->cp = 0x00;
ecc->count = 0;
for (i = 0; i < ecc->style->eccbytes; i ++)
ecc_digest(ecc, buf[i]);
# define BSHR(byte, from, to) ((ecc->lp[byte] >> (from - to)) & (1 << to))
lp_a[0] =
BSHR(0, 4, 0) | BSHR(0, 5, 2) |
BSHR(0, 6, 4) | BSHR(0, 7, 6) |
BSHR(1, 4, 1) | BSHR(1, 5, 3) |
BSHR(1, 6, 5) | BSHR(1, 7, 7);
# define BSHL(byte, from, to) ((ecc->lp[byte] << (to - from)) & (1 << to))
lp_a[1] =
BSHL(0, 0, 0) | BSHL(0, 1, 2) |
BSHL(0, 2, 4) | BSHL(0, 3, 6) |
BSHL(1, 0, 1) | BSHL(1, 1, 3) |
BSHL(1, 2, 5) | BSHL(1, 3, 7);
out[0] = ~lp_a[1];
out[1] = ~lp_a[0];
out[2] = (~ecc->cp << 2) | 0x03;
}
static void jffs2_format(const struct ecc_state_s *ecc, uint8_t oob[]) {
const struct jffs_marker_s *byte;
for (byte = ecc->style->freepos; byte->pos >= 0; byte ++)
oob[byte->pos] = byte->value;
}
static void buffer_fill(const struct ecc_state_s *ecc, uint8_t buffer[],
int *len, int *partition, int count, uint8_t jffs_buffer[]) {
int ret;
switch (*partition) {
case 0:
if (count < PARTITION_START) {
memcpy(buffer, jffs_buffer + count,
ecc->style->eccbytes);
*len = ecc->style->eccbytes;
break;
}
*partition = 1;
case 1:
if (count - PARTITION_START < PARTITION_START) {
memcpy(buffer, jffs_buffer + count - PARTITION_START,
ecc->style->eccbytes);
*len = ecc->style->eccbytes;
break;
}
while (*len < ecc->style->eccbytes) {
ret = TFR(read(0, buffer + *len, 0x800 - *len));
if (ret <= 0)
break;
*len += ret;
}
if (*len == 0)
*partition = 2;
else if (*len < ecc->style->eccbytes) {
fprintf(stderr, "\nWarning: %i stray bytes\n", *len);
memset(buffer + *len, 0xff,
ecc->style->eccbytes - *len);
*len = ecc->style->eccbytes;
break;
} else
break;
case 2:
memset(buffer, 0xff, ecc->style->eccbytes);
*len = ecc->style->eccbytes;
break;
}
}
int main(int argc, char *argv[], char *envp[]) {
struct ecc_state_s ecc;
uint8_t buffer[0x1000], ecc_payload[0x40], regs[3], *jffs;
int ret, len, eccbyte, count, partition;
/* Check if we're called by "raw2flash.spitz" or similar */
len = strlen(argv[0]);
if (!strcasecmp(argv[0] + len - 5, "akita"))
ecc.style = &akita;
else if (!strcasecmp(argv[0] + len - 6, "borzoi"))
ecc.style = &borzoi;
else if (!strcasecmp(argv[0] + len - 7, "terrier"))
ecc.style = &terrier;
else
ecc.style = &spitz;
# ifdef VERBOSE
fprintf(stderr, "[");
# endif
/* Skip first 10 bytes */
TFR(read(0, buffer, 0x10));
len = 0;
jffs = (uint8_t *) malloc(PARTITION_START);
while (len < PARTITION_START) {
ret = TFR(read(0, jffs + len, PARTITION_START - len));
if (ret <= 0)
break;
len += ret;
}
/* Convert data from stdin */
partition = len = eccbyte = count = 0;
memset(ecc_payload, 0xff, ecc.style->oob_size);
jffs2_format(&ecc, ecc_payload);
while (count < ecc.style->romsize) {
buffer_fill(&ecc, buffer, &len, &partition, count, jffs);
buffer_digest(&ecc, buffer, regs);
ecc_payload[ecc.style->eccpos[eccbyte ++]] = regs[0];
ecc_payload[ecc.style->eccpos[eccbyte ++]] = regs[1];
ecc_payload[ecc.style->eccpos[eccbyte ++]] = regs[2];
TFR(write(1, buffer, ecc.style->eccbytes));
count += ecc.style->eccbytes;
len -= ecc.style->eccbytes;
memmove(buffer, buffer + ecc.style->eccbytes, len);
if (eccbyte >= ecc.style->eccsize) {
TFR(write(1, ecc_payload, ecc.style->oob_size));
eccbyte = 0;
memset(ecc_payload, 0xff, ecc.style->oob_size);
if (partition < 2)
jffs2_format(&ecc, ecc_payload);
}
# ifdef VERBOSE
if (count * PBAR_LEN / ecc.style->romsize >
(count - ecc.style->eccbytes) *
PBAR_LEN / ecc.style->romsize)
fprintf(stderr, "#");
# endif
}
# ifdef VERBOSE
fprintf(stderr, "]\n");
# endif
free(jffs);
return 0;
}
#else
int main(int argc, char *argv[], char *envp[]) {
struct ecc_state_s ecc;
uint8_t buffer[0x1000];
int ret, len, count;
/* Check if we're called by "flash2raw.spitz" or similar */
len = strlen(argv[0]);
if (!strcasecmp(argv[0] + len - 5, "akita"))
ecc.style = &akita;
else if (!strcasecmp(argv[0] + len - 6, "borzoi"))
ecc.style = &borzoi;
else if (!strcasecmp(argv[0] + len - 7, "terrier"))
ecc.style = &terrier;
else
ecc.style = &spitz;
# ifdef VERBOSE
fprintf(stderr, "[");
# endif
/* Convert data from stdin */
count = 0;
while (count < ecc.style->romsize) {
len = 0;
while (len < ecc.style->page_size) {
ret = TFR(read(0, buffer + len,
ecc.style->page_size - len));
if (ret <= 0)
break;
len += ret;
}
if (len == 0)
break;
if (len < ecc.style->page_size) {
fprintf(stderr, "\nWarning: %i stray bytes\n", len);
}
TFR(write(1, buffer, ecc.style->page_size));
count += len;
len = 0;
while (len < ecc.style->oob_size) {
ret = TFR(read(0, buffer, ecc.style->oob_size - len));
if (ret <= 0)
break;
len += ret;
}
# ifdef VERBOSE
if (count * PBAR_LEN / ecc.style->romsize >
(count - ecc.style->page_size) *
PBAR_LEN / ecc.style->romsize)
fprintf(stderr, "#");
# endif
}
# ifdef VERBOSE
fprintf(stderr, "]\n");
# endif
return 0;
}
#endif