diff options
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu-helper')
-rw-r--r-- | meta/recipes-devtools/qemu/qemu-helper/raw2flash.c | 370 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu-helper/tunctl.c | 156 |
2 files changed, 526 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu-helper/raw2flash.c b/meta/recipes-devtools/qemu/qemu-helper/raw2flash.c new file mode 100644 index 0000000000..19faf629b9 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu-helper/raw2flash.c @@ -0,0 +1,370 @@ +/* + * 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 diff --git a/meta/recipes-devtools/qemu/qemu-helper/tunctl.c b/meta/recipes-devtools/qemu/qemu-helper/tunctl.c new file mode 100644 index 0000000000..16e24a2add --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu-helper/tunctl.c @@ -0,0 +1,156 @@ +/* Copyright 2002 Jeff Dike + * Licensed under the GPL + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <pwd.h> +#include <grp.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <linux/if_tun.h> + +/* TUNSETGROUP appeared in 2.6.23 */ +#ifndef TUNSETGROUP +#define TUNSETGROUP _IOW('T', 206, int) +#endif + +static void Usage(char *name) +{ + fprintf(stderr, "Create: %s [-b] [-u owner] [-g group] [-t device-name] " + "[-f tun-clone-device]\n", name); + fprintf(stderr, "Delete: %s -d device-name [-f tun-clone-device]\n\n", + name); + fprintf(stderr, "The default tun clone device is /dev/net/tun - some systems" + " use\n/dev/misc/net/tun instead\n\n"); + fprintf(stderr, "-b will result in brief output (just the device name)\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + struct ifreq ifr; + struct passwd *pw; + struct group *gr; + uid_t owner = -1; + gid_t group = -1; + int tap_fd, opt, delete = 0, brief = 0; + char *tun = "", *file = "/dev/net/tun", *name = argv[0], *end; + + while((opt = getopt(argc, argv, "bd:f:t:u:g:")) > 0){ + switch(opt) { + case 'b': + brief = 1; + break; + case 'd': + delete = 1; + tun = optarg; + break; + case 'f': + file = optarg; + break; + case 'u': + pw = getpwnam(optarg); + if(pw != NULL){ + owner = pw->pw_uid; + break; + } + owner = strtol(optarg, &end, 0); + if(*end != '\0'){ + fprintf(stderr, "'%s' is neither a username nor a numeric uid.\n", + optarg); + Usage(name); + } + break; + case 'g': + gr = getgrnam(optarg); + if(gr != NULL){ + group = gr->gr_gid; + break; + } + group = strtol(optarg, &end, 0); + if(*end != '\0'){ + fprintf(stderr, "'%s' is neither a groupname nor a numeric group.\n", + optarg); + Usage(name); + } + break; + + case 't': + tun = optarg; + break; + case 'h': + default: + Usage(name); + } + } + + argv += optind; + argc -= optind; + + if(argc > 0) + Usage(name); + + if((tap_fd = open(file, O_RDWR)) < 0){ + fprintf(stderr, "Failed to open '%s' : ", file); + perror(""); + exit(1); + } + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy(ifr.ifr_name, tun, sizeof(ifr.ifr_name) - 1); + if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){ + perror("TUNSETIFF"); + exit(1); + } + + if(delete){ + if(ioctl(tap_fd, TUNSETPERSIST, 0) < 0){ + perror("disabling TUNSETPERSIST"); + exit(1); + } + printf("Set '%s' nonpersistent\n", ifr.ifr_name); + } + else { + /* emulate behaviour prior to TUNSETGROUP */ + if(owner == -1 && group == -1) { + owner = geteuid(); + } + + if(owner != -1) { + if(ioctl(tap_fd, TUNSETOWNER, owner) < 0){ + perror("TUNSETOWNER"); + exit(1); + } + } + if(group != -1) { + if(ioctl(tap_fd, TUNSETGROUP, group) < 0){ + perror("TUNSETGROUP"); + exit(1); + } + } + + if(ioctl(tap_fd, TUNSETPERSIST, 1) < 0){ + perror("enabling TUNSETPERSIST"); + exit(1); + } + + if(brief) + printf("%s\n", ifr.ifr_name); + else { + printf("Set '%s' persistent and owned by", ifr.ifr_name); + if(owner != -1) + printf(" uid %d", owner); + if(group != -1) + printf(" gid %d", group); + printf("\n"); + } + } + return(0); +} |