diff mbox

[OpenWrt-Devel,4/8] caldata-utils: new package to manipulate ath10k

Message ID BLU436-SMTP2184EC6C2C7640F423277BDB9A0@phx.gbl
State Changes Requested
Headers show

Commit Message

Adrian Panella April 1, 2016, 1:48 a.m. UTC
From df9a676bb3ba225f0fd6621dbaeec945baf3153d Mon Sep 17 00:00:00 2001
From: Adrian Panella <ianchi74@outlook.com>
Date: Wed, 30 Mar 2016 23:31:06 -0600
Subject: [PATCH 12/15] caldata-utils: new package to manipulate ath10k
  calibration data

Signed-off-by: Adrian Panella <ianchi74@outlook.com>
---
  package/utils/caldata-utils/Makefile      |  60 +++++++++
  package/utils/caldata-utils/src/Makefile  |   8 ++
  package/utils/caldata-utils/src/caldata.c | 213 
++++++++++++++++++++++++++++++
  package/utils/caldata-utils/src/caldata.h |  42 ++++++
  package/utils/caldata-utils/src/utils.c   |  72 ++++++++++
  5 files changed, 395 insertions(+)
  create mode 100644 package/utils/caldata-utils/Makefile
  create mode 100644 package/utils/caldata-utils/src/Makefile
  create mode 100644 package/utils/caldata-utils/src/caldata.c
  create mode 100644 package/utils/caldata-utils/src/caldata.h
  create mode 100644 package/utils/caldata-utils/src/utils.c

+
+

Comments

Pushpal Sidhu April 1, 2016, 6:56 p.m. UTC | #1
Hi,

On Thu, Mar 31, 2016 at 6:48 PM, Adrian Panella <ianchi74@outlook.com> wrote:
>
>
> From df9a676bb3ba225f0fd6621dbaeec945baf3153d Mon Sep 17 00:00:00 2001
> From: Adrian Panella <ianchi74@outlook.com>
> Date: Wed, 30 Mar 2016 23:31:06 -0600
> Subject: [PATCH 12/15] caldata-utils: new package to manipulate ath10k
>  calibration data
>
> Signed-off-by: Adrian Panella <ianchi74@outlook.com>
> ---
>  package/utils/caldata-utils/Makefile      |  60 +++++++++
>  package/utils/caldata-utils/src/Makefile  |   8 ++
>  package/utils/caldata-utils/src/caldata.c | 213 ++++++++++++++++++++++++++++++
>  package/utils/caldata-utils/src/caldata.h |  42 ++++++
>  package/utils/caldata-utils/src/utils.c   |  72 ++++++++++
>  5 files changed, 395 insertions(+)
>  create mode 100644 package/utils/caldata-utils/Makefile
>  create mode 100644 package/utils/caldata-utils/src/Makefile
>  create mode 100644 package/utils/caldata-utils/src/caldata.c
>  create mode 100644 package/utils/caldata-utils/src/caldata.h
>  create mode 100644 package/utils/caldata-utils/src/utils.c
>
> diff --git a/package/utils/caldata-utils/Makefile b/package/utils/caldata-utils/Makefile
> new file mode 100644
> index 0000000..eff7761
> --- /dev/null
> +++ b/package/utils/caldata-utils/Makefile
> @@ -0,0 +1,60 @@
> +#
> +# Copyright (C) 2006-2010 OpenWrt.org
> +# Copyright (C) 2016 Adrian Panella
> +#
> +# This is free software, licensed under the GNU General Public License v2.
> +# See /LICENSE for more information.
> +#
> +
> +include $(TOPDIR)/rules.mk
> +
> +PKG_NAME:=caldata-utils
> +PKG_RELEASE:=1
> +
> +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
> +PKG_BUILD_DEPENDS:=USE_UCLIBC:argp-standalone USE_MUSL:argp-standalone
> +
> +include $(INCLUDE_DIR)/package.mk
> +
> +ifdef CONFIG_USE_UCLIBC
> +    LIBARGP="-largp"
> +endif
> +
> +ifdef CONFIG_USE_MUSL
> +    LIBARGP="-largp"
> +endif
> +
> +
> +define Package/caldata-utils
> +  SECTION:=utils
> +  CATEGORY:=Utilities
> +  TITLE:=Utility to manipulate calibration data for ath10k
> +  MAINTAINER:=Adrian Panella <ianchi74@outlook.com>
> +endef
> +
> +define Package/caldata-utils/description
> + This package contains an utility to manipulate calibration data for ath10k drivers.
> + It enables to extract from MTD partition or file and to patch MAC address fixing the checksum.
> +endef
> +
> +define Build/Prepare
> +    mkdir -p $(PKG_BUILD_DIR)
> +    $(CP) ./src/* $(PKG_BUILD_DIR)/
> +endef
> +
> +define Build/Configure
> +endef
> +
> +define Build/Compile
> +    $(MAKE) -C $(PKG_BUILD_DIR) \
> +        CC="$(TARGET_CC)" \
> +        CFLAGS="$(TARGET_CFLAGS) -Wall" \
> +        LDFLAGS="$(TARGET_LDFLAGS) $(LIBARGP)"
> +endef
> +
> +define Package/caldata-utils/install
> +    $(INSTALL_DIR) $(1)/usr/sbin
> +    $(INSTALL_BIN) $(PKG_BUILD_DIR)/caldata $(1)/usr/sbin/
> +endef
> +
> +$(eval $(call BuildPackage,caldata-utils))
> diff --git a/package/utils/caldata-utils/src/Makefile b/package/utils/caldata-utils/src/Makefile
> new file mode 100644
> index 0000000..57ab936
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/Makefile
> @@ -0,0 +1,8 @@
> +
> +all: caldata
> +
> +caldata: caldata.c utils.c
> +    $(CC) $(CFLAGS) -o $@ caldata.c utils.c $(LDFLAGS)
> +
> +clean:
> +    rm caldata
> diff --git a/package/utils/caldata-utils/src/caldata.c b/package/utils/caldata-utils/src/caldata.c
> new file mode 100644
> index 0000000..d5391d5
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/caldata.c
> @@ -0,0 +1,213 @@
> +/*
> + *
> + * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +/*
> + *
> + * caldata
> + *
> + * Utility to manipulate calibration data for ath10k drivers.
> + * It enables to extract from MTD partition or file and to patch MAC address fixing the checksum.
> + *
> + */
> +
> +
> +#include <stdio.h>
> +#include <argp.h>
> +#include <stdlib.h>
> +
> +#include "caldata.h"
> +
> +
> +/* Parse a single option. */
> +static error_t parse_opt (int key, char *arg, struct argp_state *state)
> +{
> +  struct arguments *arguments = state->input;
> +
> +  switch (key)
> +    {
> +    case 'i':
> +      arguments->input_file = arg;
> +      break;
> +
> +    case 'f':
> +      arguments->output_file = arg;
> +      break;
> +
> +    case 'o':
> +      sscanf(arg,"%li", &arguments->offset);
> +      break;
> +
> +    case 's':
> +      sscanf(arg,"%li", &arguments->size);
> +      break;
> +
> +    case 'a':
> +
> +      if(!isMAC(arg))
> +        argp_error(state,"address is not a valid MAC address");
> +
> +      arguments->macaddr = arg;
> +      break;
> +
> +    case 'v':
> +      arguments->verify = 1;
> +      break;
> +
> +    case ARGP_KEY_END: //all options processed, verify consistency
> +
> +        if(!arguments->input_file)
> +            argp_error(state,"No input file or partition specified.");
> +
> +        if(!arguments->verify && !arguments->output_file)
> +            argp_error(state, "Must specify either -f FILE or -v.");
> +
> +        break;
> +
> +    default:
> +      return ARGP_ERR_UNKNOWN;
> +    }
> +  return 0;
> +}
> +
> +
> +int loadfile(char *file, void **data, int offset, int size) {
> +    *data=NULL;
> +    char *source = NULL;
> +
> +
> +    char mtdpath[32];
> +    FILE *fp=NULL;
> +
> +    //try input as partition
> +    int mtdnr = getMTD(file);
> +    if(mtdnr>=0) {
> +        sprintf(mtdpath, "/dev/mtdblock%d", mtdnr);
> +        fp = fopen(mtdpath, "rb");
> +    }
> +    //try as file
> +    if(!fp)
> +        fp = fopen(file, "rb");
> +
> +    if (fp != NULL) {
> +        /* Go to the end of the file. */
> +        if (fseek(fp, 0L, SEEK_END) == 0) {
> +            /* Get the size of the file. */
> +            long filesize = ftell(fp);
> +            if (filesize == -1)  {
> +                fclose(fp);
> +                return -1; }
> +
> +            size= size ? size : (filesize - offset);
> +            if(size + offset > filesize) {
> +                fputs("Offset + size gets past EOF", stderr);
> +                fclose(fp);
> +                exit(1);}
> +
> +            source = malloc(size + 1);
> +
> +            /* offset from the start of the file. */
> +            if (fseek(fp, offset, SEEK_SET) != 0) {
> +                free(source);
> +                fclose(fp);
> +                return -1;}
> +
> +            /* Read file into memory. */
> +            size_t newLen = fread(source, sizeof(char), size, fp);
> +            if (newLen == 0) {
> +                free(source);
> +                fclose(fp);
> +                return -1;
> +            }
> +            else {
> +                fclose(fp);
> +                *data=source;
> +                return size;
> +            }
> +        }
> +    }
> +    return -1;
> +}
> +
> +int main (int argc, char **argv)
> +{
> +    struct arguments arguments;
> +    unsigned short ret=0;
> +
> +    /* Default values. */
> +    arguments.input_file = NULL;
> +    arguments.output_file = NULL;
> +    arguments.offset = 0;
> +    arguments.size = 0;
> +    arguments.macaddr = NULL;
> +    arguments.verify = 0;
> +
> +    /* Parse arguments and validate*/
> +    argp_parse (&argp, argc, argv, 0, 0, &arguments);
> +
> +
> +    // read input data
> +    unsigned short  *data;
> +    int data_len=loadfile(arguments.input_file,(void **)&data, arguments.offset, arguments.size);
> +
> +    if(data_len<0) {
> +        fputs("Error reading input file/partition.\n", stderr);
> +        exit(1);
> +        }
> +
> +    unsigned char *mac=(unsigned char *)data+6;
> +
> +    if(arguments.verify) {
> +
> +        printf("Size: %d\n", data[0]);
> +        printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
> +        ret=checksum(data, data[0]) ? 1 : 0;
> +        printf("Checksum: 0x%04x (%s)\n", data[1], ret ? "ERROR" : "OK");
> +        if(ret)
> +            fputs("Calibration data checksum error\n", stderr);
> +
> +        free(data);
> +        exit(ret);
> +    }
> +
> +    if(arguments.macaddr) {
> + sscanf(arguments.macaddr,"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
> +        data[1]=0;
> +        data[1]=checksum(data, data[0]);
> +    }
> +
> +    FILE *fp=fopen(arguments.output_file,"wb");
> +
> +    if(!fp) {
> +        fputs("Error opening output file\n", stderr);
> +        free(data);
> +        exit(1);
> +    }
> +
> +    if(fwrite(data, data_len, 1, fp)!=1) {
> +        fputs("Error writing output file\n", stderr);
> +        free(data);
> +        fclose(fp);
> +        exit(1);
> +    }
> +
> +
> +    fclose(fp);
> +    free(data);
> +    exit(0);
> +}
> diff --git a/package/utils/caldata-utils/src/caldata.h b/package/utils/caldata-utils/src/caldata.h
> new file mode 100644
> index 0000000..27c8175
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/caldata.h
> @@ -0,0 +1,42 @@
> +
> +/* Documentation */
> +const char *argp_program_version =  "caldata utils 1.0";
> +static char doc[] =  "caldata - Utility to manipulate calibration data for ath10k";
> +static char args_doc[] = "ARG1 ARG2";
> +
> +/* Options */
> +static struct argp_option options[] = {
> +  {"input",      'i', "PARTITION/FILE",    0,  "Read from PARTITION or FILE" },
> +  {"output",    'f', "FILE",    0,  "Output to FILE." },
> +  {"offset",    'o', "BYTES",    0,  "Skip first BYTES" },
> +  {"size",        's', "BYTES",    0,    "Size of data to read"},
> +  {"maddress",    'a', "ADDRESS",    0,    "new MAC address to assign"},
> +  {"verify",    'v', 0,            0,    "Only verify input, no output"},
> +  { 0 }
> +};
> +
> +/* Used by main to communicate with parse_opt. */
> +struct arguments
> +{
> +  char *input_file;
> +  char *output_file;
> +
> +  long int offset;
> +  long int size;
> +  char *macaddr;
> +  int newmac[6];
> +
> +  int  verify;
> +};
> +
> +static error_t parse_opt (int key, char *arg, struct argp_state *state);
> +
> +static struct argp argp = { options, parse_opt, args_doc, doc };
> +
> +
> +// Utils
> +
> +int isMAC(char *s);
> +int getMTD(char *name);
> +unsigned short checksum(void *caldata, int size);
> +
> diff --git a/package/utils/caldata-utils/src/utils.c b/package/utils/caldata-utils/src/utils.c
> new file mode 100644
> index 0000000..d8bda63
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/utils.c
> @@ -0,0 +1,72 @@
> +/*
> + *
> + * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <ctype.h>
> +#include <string.h>
> +
> +int isMAC(char *s) {
> +    int i;
> +    for(i = 0; i < 17; i++) {
> +        if(i % 3 != 2 && !isxdigit(s[i]))
> +            return 0;
> +        if(i % 3 == 2 && s[i] != ':')
> +            return 0;
> +    }
> +    if(s[17] != '\0')
> +        return 0;
> +    return 1;
> +}
> +
> +
> +int getMTD(char *name)
> +{
> +    int device = -1;
> +    int dev;
> +    char part[32];
> +    FILE *fp = fopen("/proc/mtd", "rb");
> +    if (!fp)
> +        return -1;
> +    while (!feof(fp) && fscanf(fp, "%*[^0-9]%d: %*s %*s \"%[^\"]\"", &dev, part) == 2) {
> +        if (!strcmp(part, name)) {
> +            device = dev;
> +            break;
> +        }
> +    }
> +    fclose(fp);
> +    return device;
> +}
> +
> +
> +unsigned short checksum(void *caldata, int size)
> +{
> +    unsigned short *ptr = (unsigned short *)caldata;
> +    unsigned short crc = 0;
> +    int i;
> +
> +    for (i = 0; i < size; i += 2) {
> +        crc ^= *ptr;
> +        ptr++;
> +    }
> +    crc = ~crc;
> +    return crc;
> +}
> +
> +
> --
> 1.9.1
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

I'm not convinced this should go into the core packages, but instead
to https://github.com/openwrt/packages.

- Pushpal
Adrian Panella April 1, 2016, 8:01 p.m. UTC | #2
So far I find it essential to make ath10k work on EA8500 with the right mac address (and perhaps on other routers using QCA99x0), and so a prerequisite for that profile. That was why I proposed it in the core packages. More or less like the uboot-env utilities, which are also a prerequisite for this profile.
Or perhaps like the "oseama" or "rbcfg" packages in other platforms.

Most of the functionality could be covered easily with a script and was my first attempt, but I couldn't find a way to code in a sh script the checksum calculation function to be able to patch the calibration data; and so ended writing it as a C helper utility.

Basically the essential part is the small checksum function in utils.c. 
If you help me with some ideas, I can try to refactor it into a script.



-----Original Message-----
From: Pushpal Sidhu [mailto:psidhu@gateworks.com] 
Sent: viernes, 01 de abril de 2016 12:57 p.m.
To: Adrian Panella
Cc: OpenWrt Development List; John Crispin
Subject: Re: [OpenWrt-Devel] [PATCH 4/8] caldata-utils: new package to manipulate ath10k

Hi,

On Thu, Mar 31, 2016 at 6:48 PM, Adrian Panella <ianchi74@outlook.com> wrote:
>
>
> From df9a676bb3ba225f0fd6621dbaeec945baf3153d Mon Sep 17 00:00:00 2001
> From: Adrian Panella <ianchi74@outlook.com>
> Date: Wed, 30 Mar 2016 23:31:06 -0600
> Subject: [PATCH 12/15] caldata-utils: new package to manipulate ath10k  
> calibration data
>
> Signed-off-by: Adrian Panella <ianchi74@outlook.com>
> ---
>  package/utils/caldata-utils/Makefile      |  60 +++++++++
>  package/utils/caldata-utils/src/Makefile  |   8 ++
>  package/utils/caldata-utils/src/caldata.c | 213 
> ++++++++++++++++++++++++++++++  package/utils/caldata-utils/src/caldata.h |  42 ++++++
>  package/utils/caldata-utils/src/utils.c   |  72 ++++++++++
>  5 files changed, 395 insertions(+)
>  create mode 100644 package/utils/caldata-utils/Makefile
>  create mode 100644 package/utils/caldata-utils/src/Makefile
>  create mode 100644 package/utils/caldata-utils/src/caldata.c
>  create mode 100644 package/utils/caldata-utils/src/caldata.h
>  create mode 100644 package/utils/caldata-utils/src/utils.c
>
> diff --git a/package/utils/caldata-utils/Makefile 
> b/package/utils/caldata-utils/Makefile
> new file mode 100644
> index 0000000..eff7761
> --- /dev/null
> +++ b/package/utils/caldata-utils/Makefile
> @@ -0,0 +1,60 @@
> +#
> +# Copyright (C) 2006-2010 OpenWrt.org # Copyright (C) 2016 Adrian 
> +Panella # # This is free software, licensed under the GNU General 
> +Public License v2.
> +# See /LICENSE for more information.
> +#
> +
> +include $(TOPDIR)/rules.mk
> +
> +PKG_NAME:=caldata-utils
> +PKG_RELEASE:=1
> +
> +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) 
> +PKG_BUILD_DEPENDS:=USE_UCLIBC:argp-standalone 
> +USE_MUSL:argp-standalone
> +
> +include $(INCLUDE_DIR)/package.mk
> +
> +ifdef CONFIG_USE_UCLIBC
> +    LIBARGP="-largp"
> +endif
> +
> +ifdef CONFIG_USE_MUSL
> +    LIBARGP="-largp"
> +endif
> +
> +
> +define Package/caldata-utils
> +  SECTION:=utils
> +  CATEGORY:=Utilities
> +  TITLE:=Utility to manipulate calibration data for ath10k
> +  MAINTAINER:=Adrian Panella <ianchi74@outlook.com> endef
> +
> +define Package/caldata-utils/description  This package contains an 
> +utility to manipulate calibration data for ath10k drivers.
> + It enables to extract from MTD partition or file and to patch MAC address fixing the checksum.
> +endef
> +
> +define Build/Prepare
> +    mkdir -p $(PKG_BUILD_DIR)
> +    $(CP) ./src/* $(PKG_BUILD_DIR)/
> +endef
> +
> +define Build/Configure
> +endef
> +
> +define Build/Compile
> +    $(MAKE) -C $(PKG_BUILD_DIR) \
> +        CC="$(TARGET_CC)" \
> +        CFLAGS="$(TARGET_CFLAGS) -Wall" \
> +        LDFLAGS="$(TARGET_LDFLAGS) $(LIBARGP)"
> +endef
> +
> +define Package/caldata-utils/install
> +    $(INSTALL_DIR) $(1)/usr/sbin
> +    $(INSTALL_BIN) $(PKG_BUILD_DIR)/caldata $(1)/usr/sbin/ endef
> +
> +$(eval $(call BuildPackage,caldata-utils))
> diff --git a/package/utils/caldata-utils/src/Makefile 
> b/package/utils/caldata-utils/src/Makefile
> new file mode 100644
> index 0000000..57ab936
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/Makefile
> @@ -0,0 +1,8 @@
> +
> +all: caldata
> +
> +caldata: caldata.c utils.c
> +    $(CC) $(CFLAGS) -o $@ caldata.c utils.c $(LDFLAGS)
> +
> +clean:
> +    rm caldata
> diff --git a/package/utils/caldata-utils/src/caldata.c 
> b/package/utils/caldata-utils/src/caldata.c
> new file mode 100644
> index 0000000..d5391d5
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/caldata.c
> @@ -0,0 +1,213 @@
> +/*
> + *
> + * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +/*
> + *
> + * caldata
> + *
> + * Utility to manipulate calibration data for ath10k drivers.
> + * It enables to extract from MTD partition or file and to patch MAC address fixing the checksum.
> + *
> + */
> +
> +
> +#include <stdio.h>
> +#include <argp.h>
> +#include <stdlib.h>
> +
> +#include "caldata.h"
> +
> +
> +/* Parse a single option. */
> +static error_t parse_opt (int key, char *arg, struct argp_state 
> +*state) {
> +  struct arguments *arguments = state->input;
> +
> +  switch (key)
> +    {
> +    case 'i':
> +      arguments->input_file = arg;
> +      break;
> +
> +    case 'f':
> +      arguments->output_file = arg;
> +      break;
> +
> +    case 'o':
> +      sscanf(arg,"%li", &arguments->offset);
> +      break;
> +
> +    case 's':
> +      sscanf(arg,"%li", &arguments->size);
> +      break;
> +
> +    case 'a':
> +
> +      if(!isMAC(arg))
> +        argp_error(state,"address is not a valid MAC address");
> +
> +      arguments->macaddr = arg;
> +      break;
> +
> +    case 'v':
> +      arguments->verify = 1;
> +      break;
> +
> +    case ARGP_KEY_END: //all options processed, verify consistency
> +
> +        if(!arguments->input_file)
> +            argp_error(state,"No input file or partition 
> + specified.");
> +
> +        if(!arguments->verify && !arguments->output_file)
> +            argp_error(state, "Must specify either -f FILE or -v.");
> +
> +        break;
> +
> +    default:
> +      return ARGP_ERR_UNKNOWN;
> +    }
> +  return 0;
> +}
> +
> +
> +int loadfile(char *file, void **data, int offset, int size) {
> +    *data=NULL;
> +    char *source = NULL;
> +
> +
> +    char mtdpath[32];
> +    FILE *fp=NULL;
> +
> +    //try input as partition
> +    int mtdnr = getMTD(file);
> +    if(mtdnr>=0) {
> +        sprintf(mtdpath, "/dev/mtdblock%d", mtdnr);
> +        fp = fopen(mtdpath, "rb");
> +    }
> +    //try as file
> +    if(!fp)
> +        fp = fopen(file, "rb");
> +
> +    if (fp != NULL) {
> +        /* Go to the end of the file. */
> +        if (fseek(fp, 0L, SEEK_END) == 0) {
> +            /* Get the size of the file. */
> +            long filesize = ftell(fp);
> +            if (filesize == -1)  {
> +                fclose(fp);
> +                return -1; }
> +
> +            size= size ? size : (filesize - offset);
> +            if(size + offset > filesize) {
> +                fputs("Offset + size gets past EOF", stderr);
> +                fclose(fp);
> +                exit(1);}
> +
> +            source = malloc(size + 1);
> +
> +            /* offset from the start of the file. */
> +            if (fseek(fp, offset, SEEK_SET) != 0) {
> +                free(source);
> +                fclose(fp);
> +                return -1;}
> +
> +            /* Read file into memory. */
> +            size_t newLen = fread(source, sizeof(char), size, fp);
> +            if (newLen == 0) {
> +                free(source);
> +                fclose(fp);
> +                return -1;
> +            }
> +            else {
> +                fclose(fp);
> +                *data=source;
> +                return size;
> +            }
> +        }
> +    }
> +    return -1;
> +}
> +
> +int main (int argc, char **argv)
> +{
> +    struct arguments arguments;
> +    unsigned short ret=0;
> +
> +    /* Default values. */
> +    arguments.input_file = NULL;
> +    arguments.output_file = NULL;
> +    arguments.offset = 0;
> +    arguments.size = 0;
> +    arguments.macaddr = NULL;
> +    arguments.verify = 0;
> +
> +    /* Parse arguments and validate*/
> +    argp_parse (&argp, argc, argv, 0, 0, &arguments);
> +
> +
> +    // read input data
> +    unsigned short  *data;
> +    int data_len=loadfile(arguments.input_file,(void **)&data, 
> + arguments.offset, arguments.size);
> +
> +    if(data_len<0) {
> +        fputs("Error reading input file/partition.\n", stderr);
> +        exit(1);
> +        }
> +
> +    unsigned char *mac=(unsigned char *)data+6;
> +
> +    if(arguments.verify) {
> +
> +        printf("Size: %d\n", data[0]);
> +        printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
> +        ret=checksum(data, data[0]) ? 1 : 0;
> +        printf("Checksum: 0x%04x (%s)\n", data[1], ret ? "ERROR" : "OK");
> +        if(ret)
> +            fputs("Calibration data checksum error\n", stderr);
> +
> +        free(data);
> +        exit(ret);
> +    }
> +
> +    if(arguments.macaddr) {
> + sscanf(arguments.macaddr,"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
> +        data[1]=0;
> +        data[1]=checksum(data, data[0]);
> +    }
> +
> +    FILE *fp=fopen(arguments.output_file,"wb");
> +
> +    if(!fp) {
> +        fputs("Error opening output file\n", stderr);
> +        free(data);
> +        exit(1);
> +    }
> +
> +    if(fwrite(data, data_len, 1, fp)!=1) {
> +        fputs("Error writing output file\n", stderr);
> +        free(data);
> +        fclose(fp);
> +        exit(1);
> +    }
> +
> +
> +    fclose(fp);
> +    free(data);
> +    exit(0);
> +}
> diff --git a/package/utils/caldata-utils/src/caldata.h 
> b/package/utils/caldata-utils/src/caldata.h
> new file mode 100644
> index 0000000..27c8175
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/caldata.h
> @@ -0,0 +1,42 @@
> +
> +/* Documentation */
> +const char *argp_program_version =  "caldata utils 1.0"; static char 
> +doc[] =  "caldata - Utility to manipulate calibration data for 
> +ath10k"; static char args_doc[] = "ARG1 ARG2";
> +
> +/* Options */
> +static struct argp_option options[] = {
> +  {"input",      'i', "PARTITION/FILE",    0,  "Read from PARTITION or FILE" },
> +  {"output",    'f', "FILE",    0,  "Output to FILE." },
> +  {"offset",    'o', "BYTES",    0,  "Skip first BYTES" },
> +  {"size",        's', "BYTES",    0,    "Size of data to read"},
> +  {"maddress",    'a', "ADDRESS",    0,    "new MAC address to assign"},
> +  {"verify",    'v', 0,            0,    "Only verify input, no output"},
> +  { 0 }
> +};
> +
> +/* Used by main to communicate with parse_opt. */ struct arguments {
> +  char *input_file;
> +  char *output_file;
> +
> +  long int offset;
> +  long int size;
> +  char *macaddr;
> +  int newmac[6];
> +
> +  int  verify;
> +};
> +
> +static error_t parse_opt (int key, char *arg, struct argp_state 
> +*state);
> +
> +static struct argp argp = { options, parse_opt, args_doc, doc };
> +
> +
> +// Utils
> +
> +int isMAC(char *s);
> +int getMTD(char *name);
> +unsigned short checksum(void *caldata, int size);
> +
> diff --git a/package/utils/caldata-utils/src/utils.c 
> b/package/utils/caldata-utils/src/utils.c
> new file mode 100644
> index 0000000..d8bda63
> --- /dev/null
> +++ b/package/utils/caldata-utils/src/utils.c
> @@ -0,0 +1,72 @@
> +/*
> + *
> + * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <ctype.h>
> +#include <string.h>
> +
> +int isMAC(char *s) {
> +    int i;
> +    for(i = 0; i < 17; i++) {
> +        if(i % 3 != 2 && !isxdigit(s[i]))
> +            return 0;
> +        if(i % 3 == 2 && s[i] != ':')
> +            return 0;
> +    }
> +    if(s[17] != '\0')
> +        return 0;
> +    return 1;
> +}
> +
> +
> +int getMTD(char *name)
> +{
> +    int device = -1;
> +    int dev;
> +    char part[32];
> +    FILE *fp = fopen("/proc/mtd", "rb");
> +    if (!fp)
> +        return -1;
> +    while (!feof(fp) && fscanf(fp, "%*[^0-9]%d: %*s %*s \"%[^\"]\"", &dev, part) == 2) {
> +        if (!strcmp(part, name)) {
> +            device = dev;
> +            break;
> +        }
> +    }
> +    fclose(fp);
> +    return device;
> +}
> +
> +
> +unsigned short checksum(void *caldata, int size) {
> +    unsigned short *ptr = (unsigned short *)caldata;
> +    unsigned short crc = 0;
> +    int i;
> +
> +    for (i = 0; i < size; i += 2) {
> +        crc ^= *ptr;
> +        ptr++;
> +    }
> +    crc = ~crc;
> +    return crc;
> +}
> +
> +
> --
> 1.9.1
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

I'm not convinced this should go into the core packages, but instead to https://github.com/openwrt/packages.

- Pushpal
Sven Eckelmann March 8, 2017, 8:27 a.m. UTC | #3
On Donnerstag, 31. März 2016 19:48:20 CET Adrian Panella wrote:
> >From df9a676bb3ba225f0fd6621dbaeec945baf3153d Mon Sep 17 00:00:00 2001
> From: Adrian Panella <ianchi74@outlook.com>
> Date: Wed, 30 Mar 2016 23:31:06 -0600
> Subject: [PATCH 12/15] caldata-utils: new package to manipulate ath10k
>   calibration data
> 
> Signed-off-by: Adrian Panella <ianchi74@outlook.com>
> ---
>   package/utils/caldata-utils/Makefile      |  60 +++++++++
>   package/utils/caldata-utils/src/Makefile  |   8 ++
>   package/utils/caldata-utils/src/caldata.c | 213 
> ++++++++++++++++++++++++++++++
>   package/utils/caldata-utils/src/caldata.h |  42 ++++++
>   package/utils/caldata-utils/src/utils.c   |  72 ++++++++++
>   5 files changed, 395 insertions(+)
>   create mode 100644 package/utils/caldata-utils/Makefile
>   create mode 100644 package/utils/caldata-utils/src/Makefile
>   create mode 100644 package/utils/caldata-utils/src/caldata.c
>   create mode 100644 package/utils/caldata-utils/src/caldata.h
>   create mode 100644 package/utils/caldata-utils/src/utils.c

I know that the patch submitted here is in a broken state. But was there any
decision made what will be done about this problem in general?

This will become a problem again on IPQ4019 when somebody must patch the mac 
address in the pre-cal data. The OTP firmware binary of ath10k will simply 
reject its content when the checksum in the pre-cal data is incorrect.

This reject will happen when the PARAM_FLASH_SECTION_ALL parameter is sent to 
the OTP [1] (step 4). Instead it will then use the boarddata from board-2.bin 
which was send to the device in step 3. It is then missing most calibration 
data which is specific to this single board.

Kind regards,
	Sven

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=3d9195ea19e4854d7daa11688b01905e244aead9
diff mbox

Patch

diff --git a/package/utils/caldata-utils/Makefile 
b/package/utils/caldata-utils/Makefile
new file mode 100644
index 0000000..eff7761
--- /dev/null
+++ b/package/utils/caldata-utils/Makefile
@@ -0,0 +1,60 @@ 
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2016 Adrian Panella
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=caldata-utils
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+PKG_BUILD_DEPENDS:=USE_UCLIBC:argp-standalone USE_MUSL:argp-standalone
+
+include $(INCLUDE_DIR)/package.mk
+
+ifdef CONFIG_USE_UCLIBC
+    LIBARGP="-largp"
+endif
+
+ifdef CONFIG_USE_MUSL
+    LIBARGP="-largp"
+endif
+
+
+define Package/caldata-utils
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Utility to manipulate calibration data for ath10k
+  MAINTAINER:=Adrian Panella <ianchi74@outlook.com>
+endef
+
+define Package/caldata-utils/description
+ This package contains an utility to manipulate calibration data for 
ath10k drivers.
+ It enables to extract from MTD partition or file and to patch MAC 
address fixing the checksum.
+endef
+
+define Build/Prepare
+    mkdir -p $(PKG_BUILD_DIR)
+    $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+    $(MAKE) -C $(PKG_BUILD_DIR) \
+        CC="$(TARGET_CC)" \
+        CFLAGS="$(TARGET_CFLAGS) -Wall" \
+        LDFLAGS="$(TARGET_LDFLAGS) $(LIBARGP)"
+endef
+
+define Package/caldata-utils/install
+    $(INSTALL_DIR) $(1)/usr/sbin
+    $(INSTALL_BIN) $(PKG_BUILD_DIR)/caldata $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,caldata-utils))
diff --git a/package/utils/caldata-utils/src/Makefile 
b/package/utils/caldata-utils/src/Makefile
new file mode 100644
index 0000000..57ab936
--- /dev/null
+++ b/package/utils/caldata-utils/src/Makefile
@@ -0,0 +1,8 @@ 
+
+all: caldata
+
+caldata: caldata.c utils.c
+    $(CC) $(CFLAGS) -o $@ caldata.c utils.c $(LDFLAGS)
+
+clean:
+    rm caldata
diff --git a/package/utils/caldata-utils/src/caldata.c 
b/package/utils/caldata-utils/src/caldata.c
new file mode 100644
index 0000000..d5391d5
--- /dev/null
+++ b/package/utils/caldata-utils/src/caldata.c
@@ -0,0 +1,213 @@ 
+/*
+ *
+ * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
02111-1307, USA.
+ */
+
+/*
+ *
+ * caldata
+ *
+ * Utility to manipulate calibration data for ath10k drivers.
+ * It enables to extract from MTD partition or file and to patch MAC 
address fixing the checksum.
+ *
+ */
+
+
+#include <stdio.h>
+#include <argp.h>
+#include <stdlib.h>
+
+#include "caldata.h"
+
+
+/* Parse a single option. */
+static error_t parse_opt (int key, char *arg, struct argp_state *state)
+{
+  struct arguments *arguments = state->input;
+
+  switch (key)
+    {
+    case 'i':
+      arguments->input_file = arg;
+      break;
+
+    case 'f':
+      arguments->output_file = arg;
+      break;
+
+    case 'o':
+      sscanf(arg,"%li", &arguments->offset);
+      break;
+
+    case 's':
+      sscanf(arg,"%li", &arguments->size);
+      break;
+
+    case 'a':
+
+      if(!isMAC(arg))
+        argp_error(state,"address is not a valid MAC address");
+
+      arguments->macaddr = arg;
+      break;
+
+    case 'v':
+      arguments->verify = 1;
+      break;
+
+    case ARGP_KEY_END: //all options processed, verify consistency
+
+        if(!arguments->input_file)
+            argp_error(state,"No input file or partition specified.");
+
+        if(!arguments->verify && !arguments->output_file)
+            argp_error(state, "Must specify either -f FILE or -v.");
+
+        break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+int loadfile(char *file, void **data, int offset, int size) {
+    *data=NULL;
+    char *source = NULL;
+
+
+    char mtdpath[32];
+    FILE *fp=NULL;
+
+    //try input as partition
+    int mtdnr = getMTD(file);
+    if(mtdnr>=0) {
+        sprintf(mtdpath, "/dev/mtdblock%d", mtdnr);
+        fp = fopen(mtdpath, "rb");
+    }
+    //try as file
+    if(!fp)
+        fp = fopen(file, "rb");
+
+    if (fp != NULL) {
+        /* Go to the end of the file. */
+        if (fseek(fp, 0L, SEEK_END) == 0) {
+            /* Get the size of the file. */
+            long filesize = ftell(fp);
+            if (filesize == -1)  {
+                fclose(fp);
+                return -1; }
+
+            size= size ? size : (filesize - offset);
+            if(size + offset > filesize) {
+                fputs("Offset + size gets past EOF", stderr);
+                fclose(fp);
+                exit(1);}
+
+            source = malloc(size + 1);
+
+            /* offset from the start of the file. */
+            if (fseek(fp, offset, SEEK_SET) != 0) {
+                free(source);
+                fclose(fp);
+                return -1;}
+
+            /* Read file into memory. */
+            size_t newLen = fread(source, sizeof(char), size, fp);
+            if (newLen == 0) {
+                free(source);
+                fclose(fp);
+                return -1;
+            }
+            else {
+                fclose(fp);
+                *data=source;
+                return size;
+            }
+        }
+    }
+    return -1;
+}
+
+int main (int argc, char **argv)
+{
+    struct arguments arguments;
+    unsigned short ret=0;
+
+    /* Default values. */
+    arguments.input_file = NULL;
+    arguments.output_file = NULL;
+    arguments.offset = 0;
+    arguments.size = 0;
+    arguments.macaddr = NULL;
+    arguments.verify = 0;
+
+    /* Parse arguments and validate*/
+    argp_parse (&argp, argc, argv, 0, 0, &arguments);
+
+
+    // read input data
+    unsigned short  *data;
+    int data_len=loadfile(arguments.input_file,(void **)&data, 
arguments.offset, arguments.size);
+
+    if(data_len<0) {
+        fputs("Error reading input file/partition.\n", stderr);
+        exit(1);
+        }
+
+    unsigned char *mac=(unsigned char *)data+6;
+
+    if(arguments.verify) {
+
+        printf("Size: %d\n", data[0]);
+        printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], 
mac[2], mac[3], mac[4], mac[5]);
+        ret=checksum(data, data[0]) ? 1 : 0;
+        printf("Checksum: 0x%04x (%s)\n", data[1], ret ? "ERROR" : "OK");
+        if(ret)
+            fputs("Calibration data checksum error\n", stderr);
+
+        free(data);
+        exit(ret);
+    }
+
+    if(arguments.macaddr) {
+ sscanf(arguments.macaddr,"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+        data[1]=0;
+        data[1]=checksum(data, data[0]);
+    }
+
+    FILE *fp=fopen(arguments.output_file,"wb");
+
+    if(!fp) {
+        fputs("Error opening output file\n", stderr);
+        free(data);
+        exit(1);
+    }
+
+    if(fwrite(data, data_len, 1, fp)!=1) {
+        fputs("Error writing output file\n", stderr);
+        free(data);
+        fclose(fp);
+        exit(1);
+    }
+
+
+    fclose(fp);
+    free(data);
+    exit(0);
+}
diff --git a/package/utils/caldata-utils/src/caldata.h 
b/package/utils/caldata-utils/src/caldata.h
new file mode 100644
index 0000000..27c8175
--- /dev/null
+++ b/package/utils/caldata-utils/src/caldata.h
@@ -0,0 +1,42 @@ 
+
+/* Documentation */
+const char *argp_program_version =  "caldata utils 1.0";
+static char doc[] =  "caldata - Utility to manipulate calibration data 
for ath10k";
+static char args_doc[] = "ARG1 ARG2";
+
+/* Options */
+static struct argp_option options[] = {
+  {"input",      'i', "PARTITION/FILE",    0,  "Read from PARTITION or 
FILE" },
+  {"output",    'f', "FILE",    0,  "Output to FILE." },
+  {"offset",    'o', "BYTES",    0,  "Skip first BYTES" },
+  {"size",        's', "BYTES",    0,    "Size of data to read"},
+  {"maddress",    'a', "ADDRESS",    0,    "new MAC address to assign"},
+  {"verify",    'v', 0,            0,    "Only verify input, no output"},
+  { 0 }
+};
+
+/* Used by main to communicate with parse_opt. */
+struct arguments
+{
+  char *input_file;
+  char *output_file;
+
+  long int offset;
+  long int size;
+  char *macaddr;
+  int newmac[6];
+
+  int  verify;
+};
+
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+static struct argp argp = { options, parse_opt, args_doc, doc };
+
+
+// Utils
+
+int isMAC(char *s);
+int getMTD(char *name);
+unsigned short checksum(void *caldata, int size);
+
diff --git a/package/utils/caldata-utils/src/utils.c 
b/package/utils/caldata-utils/src/utils.c
new file mode 100644
index 0000000..d8bda63
--- /dev/null
+++ b/package/utils/caldata-utils/src/utils.c
@@ -0,0 +1,72 @@ 
+/*
+ *
+ * Copyright (C) 2016 Adrian Panella <ianchi74@outlook.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+int isMAC(char *s) {
+    int i;
+    for(i = 0; i < 17; i++) {
+        if(i % 3 != 2 && !isxdigit(s[i]))
+            return 0;
+        if(i % 3 == 2 && s[i] != ':')
+            return 0;
+    }
+    if(s[17] != '\0')
+        return 0;
+    return 1;
+}
+
+
+int getMTD(char *name)
+{
+    int device = -1;
+    int dev;
+    char part[32];
+    FILE *fp = fopen("/proc/mtd", "rb");
+    if (!fp)
+        return -1;
+    while (!feof(fp) && fscanf(fp, "%*[^0-9]%d: %*s %*s \"%[^\"]\"", 
&dev, part) == 2) {
+        if (!strcmp(part, name)) {
+            device = dev;
+            break;
+        }
+    }
+    fclose(fp);
+    return device;
+}
+
+
+unsigned short checksum(void *caldata, int size)
+{
+    unsigned short *ptr = (unsigned short *)caldata;
+    unsigned short crc = 0;
+    int i;
+
+    for (i = 0; i < size; i += 2) {
+        crc ^= *ptr;
+        ptr++;
+    }
+    crc = ~crc;
+    return crc;
+}