See the patch notes about the stock firmware for TP-Link Onhub and
https://chromium-review.googlesource.com/243115.

As noted there, the production firmware for Google OnHub devices only
provide the *-base64 Device Tree property, and so either the kernel or
some user space mechanism needs to know how to parse/convert this
property.

I haven't submitted this patch upstream. However, it applies relatively
cleanly to the tree even after almost 8 years, so it doesn't seem too
hard to maintain.

Signed-off-by: Brian Norris <computersforpe...@gmail.com>
---

 .../970-ath10k-calibration-base64.patch       | 249 ++++++++++++++++++
 1 file changed, 249 insertions(+)
 create mode 100644 
package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch

diff --git 
a/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch 
b/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch
new file mode 100644
index 000000000000..739bdee9ccf4
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch
@@ -0,0 +1,249 @@
+Adapted from:
+https://chromium-review.googlesource.com/307062
+
+This "hack" remained in the production kernel, and so the production firmware
+for Google OnHub still only knows how to patch the *-base64 Device Tree
+property.
+
+CHROMIUM: HACK: ath10k: read calibration data in base64 format from DT
+
+ Chrome OS firmware doesn't support binary format in VPD currently.
+ As a workaround, the firmware stores the calibration data in base64
+ format in the same node with the different name:
+
+   qcom,ath10k-calibration-data-base64 = [ 01 02 03 ... ];
+
+   Since the original property "qcom,ath10k-calibration-data" is always
+   looked for first, it should have an invalid size (e.g. 1).
+
+   BUG=chrome-os-partner:35262
+   TEST=build/boot on storm suceeded. Setup Storm board as AP using
+   hostapd and
+   connected to the board using another device. Device was able to
+   connect to
+   the internet and load multiple websites.
+
+   Change-Id: I95675a803fad3b94977ecd0977bd9980779ad7e9
+   Signed-off-by: Toshi Kikuchi <tos...@chromium.org>
+   Reviewed-on: https://chromium-review.googlesource.com/243115
+   Reviewed-by: Grant Grundler <grund...@chromium.org>
+
+Change-Id: I17874f0ed03e28d279b08fe70aca70af57c90bda
+Signed-off-by: Anilkumar Kolli <ako...@codeaurora.org>
+Reviewed-on: https://chromium-review.googlesource.com/307062
+Commit-Ready: Grant Grundler <grund...@chromium.org>
+Tested-by: Grant Grundler <grund...@chromium.org>
+Reviewed-by: Srinivasa duvvuri <sduvv...@chromium.org>
+Reviewed-by: Grant Grundler <grund...@chromium.org>
+--- a/ath10k-5.15/Makefile
++++ b/ath10k-5.15/Makefile
+@@ -4,6 +4,7 @@ ath10k_core-y += mac.o \
+                debug.o \
+                core.o \
+                coredump.o \
++               decode64.o \
+                htc.o \
+                htt.o \
+                htt_rx.o \
+--- a/ath10k-5.15/core.c
++++ b/ath10k-5.15/core.c
+@@ -18,6 +18,7 @@
+ #include <linux/ctype.h>
+ 
+ #include "core.h"
++#include "decode64.h"
+ #include "mac.h"
+ #include "htc.h"
+ #include "hif.h"
+@@ -2167,6 +2168,73 @@ static int ath10k_download_cal_file(stru
+       return 0;
+ }
+ 
++static int ath10k_download_cal_dt_base64(struct ath10k *ar)
++{
++      struct device_node *node;
++      int data_len;
++      void *data;
++      int ret;
++
++      node = ar->dev->of_node;
++      if (!node)
++              /* Device Tree is optional, don't print any warnings if
++               * there's no node for ath10k.
++               */
++              return -ENOENT;
++
++      if (!of_get_property(node, "qcom,ath10k-calibration-data-base64",
++                           &data_len)) {
++              /* The calibration data node is optional */
++              return -ENOENT;
++      }
++
++      data = kmalloc(data_len, GFP_KERNEL);
++      if (!data) {
++              ret = -ENOMEM;
++              goto out;
++      }
++
++      ret = of_property_read_u8_array(node,
++                                      "qcom,ath10k-calibration-data-base64",
++                                      data, data_len);
++      if (ret) {
++              ath10k_warn(ar,
++                  "failed to read calibration data (base64) from DT: %d\n",
++                          ret);
++              goto out_free;
++      }
++
++      data_len = strip_nl(data, data + data_len, data);
++      data_len = decode64(data, data + data_len, data);
++      if (data_len < 0) {
++              ath10k_warn(ar,
++                          "base64 decoder found invalid input\n");
++              ret = -EINVAL;
++              goto out_free;
++      }
++
++      if (data_len != ar->hw_params.cal_data_len) {
++              ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
++                          data_len);
++              ret = -EMSGSIZE;
++              goto out_free;
++      }
++
++      ret = ath10k_download_board_data(ar, data, data_len);
++      if (ret) {
++              ath10k_warn(ar, "failed to download base64 calibration data 
from Device Tree: %d\n",
++                          ret);
++              goto out_free;
++      }
++
++      ret = 0;
++out_free:
++      kfree(data);
++
++out:
++      return ret;
++}
++
+ static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
+ {
+       struct device_node *node;
+@@ -2787,6 +2855,12 @@ static int ath10k_download_cal_data(stru
+                  "boot did not find target EEPROM entry, try OTP next: %d\n",
+                  ret);
+ 
++      ret = ath10k_download_cal_dt_base64(ar);
++      if (ret == 0) {
++              ar->cal_mode = ATH10K_CAL_MODE_DT;
++              goto done;
++      }
++
+       ret = ath10k_download_and_run_otp(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to run otp: %d (download-cal-data)\n", 
ret);
+--- /dev/null
++++ b/ath10k-5.15/decode64.c
+@@ -0,0 +1,89 @@
++/*
++ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
++ * Copyright (c) 2014, The Chromium OS Authors
++ *
++ * 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 "decode64.h"
++
++static char revkey[128] = {
++      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
++      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
++      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
++      52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
++      -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
++      15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
++      -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
++      41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
++};
++
++int
++decode64(unsigned char *src, unsigned char *src_end, unsigned char *dst)
++{
++      unsigned char *dst_end = dst;
++
++      while (&src[3] < src_end) {
++              int x;
++              int t[4];
++              int i;
++
++              if (src[0] == '=' || src[1] == '=' ||
++                  (src[2] == '=' && src[3] != '=')) {
++                      return -1;
++              }
++
++              for (i = 0; i < 4; i++) {
++                      if (src[i] == '=') {
++                              t[i] = 0;
++                      } else {
++                              if (src[i] >= 128 ||
++                                  ((t[i] = revkey[src[i]]) < 0)) {
++                                      return -1;
++                              }
++                      }
++              }
++
++              x = (t[0] << 18) + (t[1] << 12) + (t[2] << 6) + t[3];
++
++              *dst_end++ = (x >> 16) & 0xff;
++              if (src[2] != '=')
++                      *dst_end++ = (x >> 8) & 0xff;
++              if (src[3] != '=')
++                      *dst_end++ = x & 0xff;
++
++              src += 4;
++      }
++
++      if (src != src_end)
++              return -1;
++
++      return dst_end - dst;
++}
++
++int
++strip_nl(unsigned char *src, unsigned char *src_end, unsigned char *dst)
++{
++      unsigned char *dst_end = dst;
++
++      while (src < src_end) {
++              if (*src != '\n')
++                      *dst_end++ = *src;
++              src++;
++      }
++
++      return dst_end - dst;
++}
+--- /dev/null
++++ b/ath10k-5.15/decode64.h
+@@ -0,0 +1,10 @@
++#ifndef _DECODE64_H_
++#define _DECODE64_H_
++
++int decode64(unsigned char *src, unsigned char *src_end,
++           unsigned char *dst);
++
++int strip_nl(unsigned char *src, unsigned char *src_end,
++           unsigned char *dst);
++
++#endif /* _DECODE64_H_ */
-- 
2.39.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to