[][MAC80211][WiFi6/7][app][Add eMMC support in atenl]
[Description]
Add eMMC support in atenl
1. add mtd/mmc open/write function
2. add new opt for specifying partition name and offset
Usage:
- atenl -i phy0 -c "sync eeprom all" -p <name>:<offset>
- <offset> can be specified as decimal (e.g. 2560) or
hexadecimal (0xa000)
[Release-log]
N/A
Change-Id: I10c19e15d2500cb287793a5e77f1b336eb6870a5
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9897396
diff --git a/feed/app/atenl/Makefile b/feed/app/atenl/Makefile
index b0b4744..f4246db 100644
--- a/feed/app/atenl/Makefile
+++ b/feed/app/atenl/Makefile
@@ -20,10 +20,11 @@
CATEGORY:=MTK Properties
TITLE:=testmode daemon for nl80211
SUBMENU:=Applications
- DEPENDS:=+libnl-tiny
+ DEPENDS:=+libnl-tiny +libblkid
endef
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
+TARGET_CFLAGS += -lblkid
define Package/atenl/install
mkdir -p $(1)/usr/sbin
diff --git a/feed/app/atenl/src/atenl.h b/feed/app/atenl/src/atenl.h
index da3fd72..1cd5a3e 100644
--- a/feed/app/atenl/src/atenl.h
+++ b/feed/app/atenl/src/atenl.h
@@ -92,8 +92,8 @@
bool unicast;
int sock_eth;
- const char *mtd_part;
- u32 mtd_offset;
+ const char *flash_part;
+ u32 flash_offset;
u8 band_idx;
u8 *eeprom_data;
int eeprom_fd;
@@ -465,7 +465,7 @@
u16 ch, u16 center_ch1, u16 center_ch2);
int atenl_nl_process(struct atenl *an, struct atenl_data *data);
int atenl_nl_process_many(struct atenl *an, struct atenl_data *data);
-int atenl_nl_check_mtd(struct atenl *an);
+int atenl_nl_check_flash(struct atenl *an);
int atenl_nl_write_eeprom(struct atenl *an, u32 offset, u8 *val, int len);
int atenl_nl_write_efuse_all(struct atenl *an);
int atenl_nl_write_ext_eeprom_all(struct atenl *an);
@@ -477,7 +477,7 @@
void atenl_get_ibf_cal_result(struct atenl *an);
int atenl_eeprom_init(struct atenl *an, u8 phy_idx);
void atenl_eeprom_close(struct atenl *an);
-int atenl_eeprom_write_mtd(struct atenl *an);
+int atenl_eeprom_write_flash(struct atenl *an);
int atenl_eeprom_update_precal(struct atenl *an, int write_offs, int size);
int atenl_eeprom_read_from_driver(struct atenl *an, u32 offset, int len);
void atenl_eeprom_cmd_handler(struct atenl *an, u8 phy_idx, char *cmd);
diff --git a/feed/app/atenl/src/eeprom.c b/feed/app/atenl/src/eeprom.c
index 6dd4113..5f060aa 100644
--- a/feed/app/atenl/src/eeprom.c
+++ b/feed/app/atenl/src/eeprom.c
@@ -3,6 +3,8 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <blkid/blkid.h>
#include "atenl.h"
@@ -357,8 +359,8 @@
char buf[30];
set_band_val(an, 0, phy_idx, phy_idx);
- atenl_nl_check_mtd(an);
- flash_mode = an->mtd_part != NULL;
+ atenl_nl_check_flash(an);
+ flash_mode = an->flash_part != NULL;
// Get the first main phy index for this chip
an->main_phy_idx = phy_idx - an->band_idx;
@@ -430,30 +432,146 @@
return 0;
}
-int atenl_eeprom_write_mtd(struct atenl *an)
+int atenl_mtd_open(struct atenl *an, int flags)
{
-#define TMP_FILE "/tmp/tmp_eeprom.bin"
- pid_t pid;
+ char dev[128], buf[16];
+ char *part_num;
+ FILE *f;
+ int fd;
+
+ f = fopen("/proc/mtd", "r");
+ if (!f)
+ return -1;
+
+ while (fgets(dev, sizeof(dev), f)) {
+ if (!strcasestr(dev, an->flash_part))
+ continue;
+
+ part_num = strtok(dev, ":");
+ if (part_num)
+ break;
+ }
+
+ fclose(f);
+
+ if (!part_num)
+ return -1;
+
+ /* mtdblockX emulates an mtd device as a block device.
+ * Use mtdblockX instead of mtdX to avoid padding & buffer handling.
+ */
+ snprintf(buf, sizeof(buf), "/dev/mtdblock%s", part_num + 3);
+
+ fd = open(buf, flags);
+
+ return fd;
+}
+
+int atenl_mmc_open(struct atenl *an, int flags)
+{
+ const char *mmc_dev = "/dev/mmcblk0";
+ int nparts, part_num;
+ blkid_partlist plist;
+ blkid_probe probe;
+ int i, fd = -1;
+ char buf[16];
+
+ probe = blkid_new_probe_from_filename(mmc_dev);
+ if (!probe)
+ return -1;
+
+ plist = blkid_probe_get_partitions(probe);
+ if (!plist)
+ goto out;
+
+ nparts = blkid_partlist_numof_partitions(plist);
+ if (!nparts)
+ goto out;
+
+ for (i = 0; i < nparts; i++) {
+ blkid_partition part;
+ const char *name;
+
+ part = blkid_partlist_get_partition(plist, i);
+ if (!part)
+ continue;
+
+ name = blkid_partition_get_name(part);
+ if (!name)
+ continue;
+
+ if (strncasecmp(name, an->flash_part, strlen(an->flash_part)))
+ continue;
+
+ part_num = blkid_partition_get_partno(part);
+ snprintf(buf, sizeof(buf), "%sp%d", mmc_dev, part_num);
+
+ fd = open(buf, flags);
+ if (fd >= 0)
+ break;
+ }
+
+out:
+ blkid_free_probe(probe);
+ return fd;
+}
+
+void atenl_flash_write(struct atenl *an, int fd, u32 size, bool is_mtd)
+{
+ u32 flash_size, offs;
+ int ret;
+
+ flash_size = lseek(fd, 0, SEEK_END);
+ if (size > flash_size)
+ return;
+
+ offs = an->flash_offset;
+ ret = lseek(fd, offs, SEEK_SET);
+ if (ret < 0)
+ return;
+
+ ret = write(fd, an->eeprom_data, size);
+ if (ret < 0)
+ return;
+
+ atenl_info("write to %s partition %s offset 0x%x size 0x%x\n",
+ is_mtd ? "mtd" : "mmc", an->flash_part, offs, size);
+}
+
+int atenl_eeprom_write_flash(struct atenl *an)
+{
u32 size = an->eeprom_size;
- u32 *precal_info = an->eeprom_data + an->eeprom_size;
- u32 precal_size = precal_info[0] + precal_info[1];
- char cmd[100];
+ u32 precal_size, *precal_info;
+ int fd;
- if (an->mtd_part == NULL || !(~an->mtd_offset))
+ /* flash_offset = -1 for binfile mode */
+ if (an->flash_part == NULL || !(~an->flash_offset)) {
+ atenl_err("Flash partition or offset is not specified\n");
return 0;
+ }
+
+ precal_info = (u32 *)(an->eeprom_data + size);
+ precal_size = precal_info[0] + precal_info[1];
if (precal_size)
size += PRE_CAL_INFO + precal_size;
- sprintf(cmd, "dd if=%s of=%s bs=1 count=%d", eeprom_file, TMP_FILE, size);
- system(cmd);
+ fd = atenl_mtd_open(an, O_RDWR | O_SYNC);
+ if (fd >= 0) {
+ atenl_flash_write(an, fd, size, true);
+ goto out;
+ }
- sprintf(cmd, "mtd -p %d write %s %s", an->mtd_offset, TMP_FILE, an->mtd_part);
- system(cmd);
+ fd = atenl_mmc_open(an, O_RDWR | O_SYNC);
+ if (fd >= 0) {
+ atenl_flash_write(an, fd, size, false);
+ goto out;
+ }
- sprintf(cmd, "rm %s", TMP_FILE);
- system(cmd);
+ atenl_err("Fail to open %s\n", an->flash_part);
+out:
+ close(fd);
return 0;
}
@@ -512,7 +630,7 @@
atenl_eeprom_init(an, phy_idx);
if (!strncmp(cmd, "sync eeprom all", 15)) {
- atenl_eeprom_write_mtd(an);
+ atenl_eeprom_write_flash(an);
} else if (!strncmp(cmd, "eeprom", 6)) {
char *s = strchr(cmd, ' ');
@@ -526,9 +644,9 @@
unlink(eeprom_file);
} else if (!strncmp(s, "file", 4)) {
atenl_info("%s\n", eeprom_file);
- if (an->mtd_part != NULL)
+ if (an->flash_part != NULL)
atenl_info("%s mode\n",
- ~an->mtd_offset == 0 ? "Binfile" : "Flash");
+ ~an->flash_offset == 0 ? "Binfile" : "Flash");
else
atenl_info("Efuse / Default bin mode\n");
} else if (!strncmp(s, "set", 3)) {
@@ -555,7 +673,7 @@
s++;
if (!strncmp(s, "flash", 5)) {
- atenl_eeprom_write_mtd(an);
+ atenl_eeprom_write_flash(an);
} else if (!strncmp(s, "to efuse", 8)) {
atenl_eeprom_sync_to_driver(an);
atenl_nl_write_efuse_all(an);
diff --git a/feed/app/atenl/src/hqa.c b/feed/app/atenl/src/hqa.c
index 2f25043..678bb93 100644
--- a/feed/app/atenl/src/hqa.c
+++ b/feed/app/atenl/src/hqa.c
@@ -480,7 +480,7 @@
atenl_hqa_check_efuse_mode(struct atenl *an, struct atenl_data *data)
{
struct atenl_cmd_hdr *hdr = atenl_hdr(data);
- bool flash_mode = an->mtd_part != NULL;
+ bool flash_mode = an->flash_part != NULL;
enum atenl_cmd cmd = data->cmd;
u32 mode;
diff --git a/feed/app/atenl/src/main.c b/feed/app/atenl/src/main.c
index ef13245..0dbcb41 100644
--- a/feed/app/atenl/src/main.c
+++ b/feed/app/atenl/src/main.c
@@ -87,7 +87,9 @@
" -h = show help text\n"
" -i = phy name of driver interface, please use first phy for dbdc\n"
" -u = use unicast to respond to HQADLL\n"
- " -b = specify your bridge name\n");
+ " -b = specify your bridge name\n"
+ " -c = eeprom-related command\n"
+ " -p = specify the flash partition name and offset (<name>:<offs>)\n");
printf("examples:\n"
" %s -u -i phy0 -b br-lan\n", progname);
@@ -124,6 +126,7 @@
{
int opt, phy_idx, ret = 0;
char *phy = "phy0", *cmd = NULL;
+ char *token;
struct atenl *an;
progname = argv[0];
@@ -133,7 +136,7 @@
return -ENOMEM;
while(1) {
- opt = getopt(argc, argv, "hi:uc:b:");
+ opt = getopt(argc, argv, "hi:uc:b:p:");
if (opt == -1)
break;
@@ -154,6 +157,13 @@
case 'c':
cmd = optarg;
break;
+ case 'p':
+ token = strtok(optarg, ":");
+ if (!token)
+ break;
+ an->flash_part = token;
+ an->flash_offset = strtol(strtok(NULL, ":"), NULL, 0);
+ break;
default:
atenl_err("Not supported option: %c\n", opt);
goto out;
diff --git a/feed/app/atenl/src/nl.c b/feed/app/atenl/src/nl.c
index 7796ba9..e019979 100644
--- a/feed/app/atenl/src/nl.c
+++ b/feed/app/atenl/src/nl.c
@@ -1186,7 +1186,7 @@
return 0;
}
-static int atenl_nl_check_mtd_cb(struct nl_msg *msg, void *arg)
+static int atenl_nl_check_flash_cb(struct nl_msg *msg, void *arg)
{
struct atenl_nl_priv *nl_priv = (struct atenl_nl_priv *)arg;
struct atenl *an = nl_priv->an;
@@ -1203,13 +1203,13 @@
if (!tb[MT76_TM_ATTR_MTD_PART] || !tb[MT76_TM_ATTR_MTD_OFFSET])
return NL_SKIP;
- an->mtd_part = strdup(nla_get_string(tb[MT76_TM_ATTR_MTD_PART]));
- an->mtd_offset = nla_get_u32(tb[MT76_TM_ATTR_MTD_OFFSET]);
+ an->flash_part = strdup(nla_get_string(tb[MT76_TM_ATTR_MTD_PART]));
+ an->flash_offset = nla_get_u32(tb[MT76_TM_ATTR_MTD_OFFSET]);
return NL_SKIP;
}
-int atenl_nl_check_mtd(struct atenl *an)
+int atenl_nl_check_flash(struct atenl *an)
{
struct atenl_nl_priv nl_priv = { .an = an };
struct nl_msg *msg;
@@ -1219,9 +1219,14 @@
return 2;
}
+ /* User has a specified flash partition */
+ if (an->flash_part)
+ return 0;
+
msg = unl_genl_msg(&nl_priv.unl, NL80211_CMD_TESTMODE, true);
nla_put_u32(msg, NL80211_ATTR_WIPHY, get_band_val(an, 0, phy_idx));
- unl_genl_request(&nl_priv.unl, msg, atenl_nl_check_mtd_cb, (void *)&nl_priv);
+ unl_genl_request(&nl_priv.unl, msg, atenl_nl_check_flash_cb,
+ (void *)&nl_priv);
unl_free(&nl_priv.unl);