Просмотр исходного кода

ramips: add support for Fon FON2601

FON2601 is a wireless router.

Specification:
- SoC: Mediatek MT7620A (580MHz)
- RAM: 128 MiB
- ROM: 16 MiB SPI Flash
- Wireless:
   for 11b/g/n (upto 300 Mbps):  MT7620A built-in WMAC
   for 11a/n/ac (upto 867 Mbps): MT7662E
- Ethernet LAN: 1 port, upto 100 Mbps
- Ethernet WAN: 1 port, upto 1000 Mbps
- USB: 1 port (USB 2.0 host)
- LEDs: 4 (all can be controlled by SoC's GPIO)
- buttons: 1 (Displayed as "WPS" on enclosure)
- serial port: 57600n8
 pins: Vcc(3.3V), Rx, Tx, GND
(left to right, viewed from outside of board)

Installation (only available via UART):
  1. download sysupgrade binary image by wget command
  2. write sysupgrade binary image to Flash
     command is:
       mtd write sysupgrade.bin firmware
  3. reboot

Important Notice:
  Only one button is displayed as "WPS" on enclosure.
  However, it is configured as "reset" (factory resetting feature).

Signed-off-by: NOGUCHI Hiroshi <[email protected]>
[removed unrelated openwrt-keyring revert, missing -Wall for uimage_padhdr]
Signed-off-by: Petr Štetiar <[email protected]>
NOGUCHI Hiroshi 6 лет назад
Родитель
Сommit
a1c6a316d2

+ 60 - 12
target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c

@@ -24,9 +24,9 @@
 
 /*
  * uimage_header itself is only 64B, but it may be prepended with another data.
- * Currently the biggest size is for Edimax devices: 20B + 64B
+ * Currently the biggest size is for Fon(Foxconn) devices: 64B + 32B
  */
-#define MAX_HEADER_LEN		84
+#define MAX_HEADER_LEN		96
 
 #define IH_MAGIC	0x27051956	/* Image Magic Number		*/
 #define IH_NMLEN		32	/* Image Name Length		*/
@@ -80,12 +80,12 @@ read_uimage_header(struct mtd_info *mtd, size_t offset, u_char *buf,
  * __mtdsplit_parse_uimage - scan partition and create kernel + rootfs parts
  *
  * @find_header: function to call for a block of data that will return offset
- *      of a valid uImage header if found
+ *      and tail padding length of a valid uImage header if found
  */
 static int __mtdsplit_parse_uimage(struct mtd_info *master,
-				   const struct mtd_partition **pparts,
-				   struct mtd_part_parser_data *data,
-				   ssize_t (*find_header)(u_char *buf, size_t len))
+		   const struct mtd_partition **pparts,
+		   struct mtd_part_parser_data *data,
+		   ssize_t (*find_header)(u_char *buf, size_t len, int *extralen))
 {
 	struct mtd_partition *parts;
 	u_char *buf;
@@ -97,6 +97,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
 	size_t rootfs_size = 0;
 	int uimage_part, rf_part;
 	int ret;
+	int extralen;
 	enum mtdsplit_part_type type;
 
 	nr_parts = 2;
@@ -120,7 +121,8 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
 		if (ret)
 			continue;
 
-		ret = find_header(buf, MAX_HEADER_LEN);
+		extralen = 0;
+		ret = find_header(buf, MAX_HEADER_LEN, &extralen);
 		if (ret < 0) {
 			pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
 				 master->name, (unsigned long long) offset);
@@ -128,7 +130,9 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
 		}
 		header = (struct uimage_header *)(buf + ret);
 
-		uimage_size = sizeof(*header) + be32_to_cpu(header->ih_size) + ret;
+		uimage_size = sizeof(*header) +
+				be32_to_cpu(header->ih_size) + ret + extralen;
+
 		if ((offset + uimage_size) > master->size) {
 			pr_debug("uImage exceeds MTD device \"%s\"\n",
 				 master->name);
@@ -206,7 +210,7 @@ err_free_parts:
 	return ret;
 }
 
-static ssize_t uimage_verify_default(u_char *buf, size_t len)
+static ssize_t uimage_verify_default(u_char *buf, size_t len, int *extralen)
 {
 	struct uimage_header *header = (struct uimage_header *)buf;
 
@@ -269,7 +273,7 @@ static struct mtd_part_parser uimage_generic_parser = {
 #define FW_MAGIC_WNDR3700V2	0x33373031
 #define FW_MAGIC_WPN824N	0x31313030
 
-static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len)
+static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len, int *extralen)
 {
 	struct uimage_header *header = (struct uimage_header *)buf;
 	uint8_t expected_type = IH_TYPE_FILESYSTEM;
@@ -332,7 +336,7 @@ static struct mtd_part_parser uimage_netgear_parser = {
 #define FW_EDIMAX_OFFSET	20
 #define FW_MAGIC_EDIMAX		0x43535953
 
-static ssize_t uimage_find_edimax(u_char *buf, size_t len)
+static ssize_t uimage_find_edimax(u_char *buf, size_t len, int *extralen)
 {
 	u32 *magic;
 
@@ -345,7 +349,7 @@ static ssize_t uimage_find_edimax(u_char *buf, size_t len)
 	if (be32_to_cpu(*magic) != FW_MAGIC_EDIMAX)
 		return -EINVAL;
 
-	if (!uimage_verify_default(buf + FW_EDIMAX_OFFSET, len))
+	if (!uimage_verify_default(buf + FW_EDIMAX_OFFSET, len, extralen))
 		return FW_EDIMAX_OFFSET;
 
 	return -EINVAL;
@@ -377,6 +381,49 @@ static struct mtd_part_parser uimage_edimax_parser = {
 	.type = MTD_PARSER_TYPE_FIRMWARE,
 };
 
+
+/**************************************************
+ * Fon(Foxconn)
+ **************************************************/
+
+#define FONFXC_PAD_LEN		32
+
+static ssize_t uimage_find_fonfxc(u_char *buf, size_t len, int *extralen)
+{
+	if (uimage_verify_default(buf, len, extralen) < 0)
+		return -EINVAL;
+
+	*extralen = FONFXC_PAD_LEN;
+
+	return 0;
+}
+
+static int
+mtdsplit_uimage_parse_fonfxc(struct mtd_info *master,
+			      const struct mtd_partition **pparts,
+			      struct mtd_part_parser_data *data)
+{
+	return __mtdsplit_parse_uimage(master, pparts, data,
+				       uimage_find_fonfxc);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+static const struct of_device_id mtdsplit_uimage_fonfxc_of_match_table[] = {
+	{ .compatible = "fonfxc,uimage" },
+	{},
+};
+#endif
+
+static struct mtd_part_parser uimage_fonfxc_parser = {
+	.owner = THIS_MODULE,
+	.name = "fonfxc-fw",
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+	.of_match_table = mtdsplit_uimage_fonfxc_of_match_table,
+#endif
+	.parse_fn = mtdsplit_uimage_parse_fonfxc,
+	.type = MTD_PARSER_TYPE_FIRMWARE,
+};
+
 /**************************************************
  * Init
  **************************************************/
@@ -386,6 +433,7 @@ static int __init mtdsplit_uimage_init(void)
 	register_mtd_parser(&uimage_generic_parser);
 	register_mtd_parser(&uimage_netgear_parser);
 	register_mtd_parser(&uimage_edimax_parser);
+	register_mtd_parser(&uimage_fonfxc_parser);
 
 	return 0;
 }

+ 4 - 0
target/linux/ramips/base-files/etc/board.d/02_network

@@ -329,6 +329,10 @@ ramips_setup_interfaces()
 		ucidef_add_switch "switch1" \
 			"1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "6@eth0"
 		;;
+	fon,fon2601)
+		ucidef_add_switch "switch0" \
+			"0:lan" "4:wan" "6@eth0"
+		;;
 	gehua,ghl-r-001)
 		ucidef_add_switch "switch0" \
 			"0:lan" "1:lan" "2:lan" "4:wan" "6@eth0"

+ 166 - 0
target/linux/ramips/dts/mt7620a_fon_fon2601.dts

@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "mt7620a.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	compatible = "fon,fon2601", "ralink,mt7620a-soc";
+	model = "Fon FON2601";
+
+	aliases {
+		led-boot = &led_power;
+		led-failsafe = &led_power;
+		led-running = &led_power;
+		led-upgrade = &led_power;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_power: power_r {
+			label = "fon2601:red:power";
+			gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+		};
+
+		internet_g {
+			label = "fon2601:green:internet";
+			gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+		};
+
+		net_g {
+			label = "fon2601:green:net";
+			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+		};
+
+		wifi_g {
+			label = "fon2601:green:wifi";
+			gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "reset";
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+};
+
+&spi0 {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0 0x30000>;
+				read-only;
+			};
+
+			partition@30000 {
+				label = "u-boot-env";
+				reg = <0x30000 0x10000>;
+				read-only;
+			};
+
+			factory: partition@40000 {
+				label = "factory";
+				reg = <0x40000 0x10000>;
+				read-only;
+			};
+
+			partition@50000 {
+				compatible = "fonfxc,uimage";
+				label = "firmware";
+				reg = <0x50000 0xf90000>;
+			};
+
+			partition@fe0000 {
+				label = "board_data";
+				reg = <0xfe0000 0x20000>;
+				read-only;
+			};
+		};
+	};
+};
+
+&state_default {
+	gpio {
+		ralink,group = "i2c", "uartf";
+		ralink,function = "gpio";
+	};
+	nd_sd {
+		ralink,group = "nd_sd";
+		ralink,function = "sd";
+	};
+	spi_cs {
+		ralink,group = "spi refclk";
+		ralink,function = "spi refclk";
+	};
+};
+
+&ethernet {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii2_pins &mdio_pins>;
+
+	mtd-mac-address = <&factory 0x4>;
+
+	port@4 {
+		status = "okay";
+		phy-handle = <&phy4>;
+		phy-mode = "rgmii";
+	};
+
+	mdio-bus {
+		status = "okay";
+
+		phy4: ethernet-phy@4 {
+			reg = <4>;
+			phy-mode = "rgmii";
+		};
+	};
+};
+
+&gsw {
+	mediatek,port4 = "gmac";
+};
+
+&wmac {
+	ralink,mtd-eeprom = <&factory 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pa_pins>, <&wled_pins>;
+};
+
+&pcie {
+	status = "okay";
+};
+&pcie0 {
+	wifi@0,0 {
+		compatible = "pci14c3,7662";
+		reg = <0x0000 0 0 0 0>;
+		mediatek,mtd-eeprom = <&factory 0x8000>;
+		ieee80211-freq-limit = <5000000 6000000>;
+	};
+};
+
+&ehci {
+	status = "okay";
+};
+
+&ohci {
+	status = "okay";
+};

+ 5 - 0
target/linux/ramips/image/Makefile

@@ -147,6 +147,11 @@ define Build/sercom-footer
 	$(call Build/sercom-seal,-f)
 endef
 
+define Build/fonfxcimage
+	uimage_padhdr -i $@ -o [email protected]
+	mv [email protected] $@
+endef
+
 ifeq ($(SUBTARGET),rt288x)
 include rt288x.mk
 endif

+ 13 - 0
target/linux/ramips/image/mt7620.mk

@@ -372,6 +372,19 @@ define Device/elecom_wrh-300cr
 endef
 TARGET_DEVICES += elecom_wrh-300cr
 
+define Device/fon_fon2601
+  MTK_SOC := mt7620a
+  IMAGE_SIZE := 15936k
+  DEVICE_VENDOR := Fon
+  DEVICE_MODEL := FON2601
+  DEVICE_PACKAGES := kmod-mt76x2 kmod-usb2 kmod-usb-ohci
+  KERNEL_INITRAMFS := $$(KERNEL) | fonfxcimage
+  IMAGE/sysupgrade.bin := append-kernel | append-rootfs |\
+			fonfxcimage |\
+			pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE)
+endef
+TARGET_DEVICES += fon_fon2601
+
 define Device/glinet_gl-mt300a
   MTK_SOC := mt7620a
   IMAGE_SIZE := 15872k

+ 1 - 0
tools/firmware-utils/Makefile

@@ -92,6 +92,7 @@ define Host/Compile
 	$(call cc,dns313-header, -Wall)
 	$(call cc,mksercommfw, -Wall)
 	$(call cc,nec-enc, -Wall --std=gnu99)
+	$(call cc,uimage_padhdr, -Wall -lz)
 endef
 
 define Host/Install

+ 157 - 0
tools/firmware-utils/src/uimage_padhdr.c

@@ -0,0 +1,157 @@
+/*
+ * uimage_padhdr.c : add zero paddings after the tail of uimage header
+ *
+ * Copyright (C) 2019 NOGUCHI Hiroshi <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <zlib.h>
+
+
+/* from u-boot/include/image.h */
+#define IH_MAGIC	0x27051956	/* Image Magic Number		*/
+#define IH_NMLEN		32	/* Image Name Length		*/
+
+/*
+ * Legacy format image header,
+ * all data in network byte order (aka natural aka bigendian).
+ */
+typedef struct image_header {
+	uint32_t	ih_magic;	/* Image Header Magic Number	*/
+	uint32_t	ih_hcrc;	/* Image Header CRC Checksum	*/
+	uint32_t	ih_time;	/* Image Creation Timestamp	*/
+	uint32_t	ih_size;	/* Image Data Size		*/
+	uint32_t	ih_load;	/* Data	 Load  Address		*/
+	uint32_t	ih_ep;		/* Entry Point Address		*/
+	uint32_t	ih_dcrc;	/* Image Data CRC Checksum	*/
+	uint8_t		ih_os;		/* Operating System		*/
+	uint8_t		ih_arch;	/* CPU architecture		*/
+	uint8_t		ih_type;	/* Image Type			*/
+	uint8_t		ih_comp;	/* Compression Type		*/
+	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
+} image_header_t;
+
+
+/* default padding size */
+#define	IH_PAD_BYTES		(32)
+
+
+static void usage(char *prog)
+{
+	fprintf(stderr,
+		"%s -i <input_uimage_file> -o <output_file> [-l <padding bytes>]\n",
+		prog);
+}
+
+int main(int argc, char *argv[])
+{
+	struct stat statbuf;
+	u_int8_t *filebuf;
+	int ifd;
+	int ofd;
+	ssize_t rsz;
+	u_int32_t crc_recalc;
+	image_header_t *imgh;
+	int opt;
+	char *infname = NULL;
+	char *outfname = NULL;
+	int padsz = IH_PAD_BYTES;
+	int ltmp;
+
+	while ((opt = getopt(argc, argv, "i:o:l:")) != -1) {
+		switch (opt) {
+		case 'i':
+			infname = optarg;
+			break;
+		case 'o':
+			outfname = optarg;
+			break;
+		case 'l':
+			ltmp = strtol(optarg, NULL, 0);
+			if (ltmp > 0)
+				padsz = ltmp;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!infname || !outfname) {
+		usage(argv[0]);
+		exit(1);
+	}
+
+	if (stat(infname, &statbuf) < 0) {
+		fprintf(stderr,
+			"could not find input file. (errno = %d)\n", errno);
+		exit(1);
+	}
+
+	filebuf = malloc(statbuf.st_size + padsz);
+	if (!filebuf) {
+		fprintf(stderr, "buffer allocation failed\n");
+		exit(1);
+	}
+
+	ifd = open(infname, O_RDONLY);
+	if (ifd < 0) {
+		fprintf(stderr,
+			"could not open input file. (errno = %d)\n", errno);
+		exit(1);
+	}
+
+	ofd = open(outfname, O_WRONLY | O_CREAT, 0644);
+	if (ofd < 0) {
+		fprintf(stderr,
+			"could not open output file. (errno = %d)\n", errno);
+		exit(1);
+	}
+
+	rsz = read(ifd, filebuf, sizeof(*imgh));
+	if (rsz != sizeof(*imgh)) {
+		fprintf(stderr,
+			"could not read input file (errno = %d).\n", errno);
+		exit(1);
+	}
+
+	memset(&(filebuf[sizeof(*imgh)]), 0, padsz);
+
+	rsz = read(ifd, &(filebuf[sizeof(*imgh) + padsz]),
+				statbuf.st_size - sizeof(*imgh));
+	if (rsz != (int32_t)(statbuf.st_size - sizeof(*imgh))) {
+		fprintf(stderr,
+			"could not read input file (errno = %d).\n", errno);
+		exit(1);
+	}
+
+	imgh = (image_header_t *)filebuf;
+
+	imgh->ih_hcrc = 0;
+	crc_recalc = crc32(0, filebuf, sizeof(*imgh) + padsz);
+	imgh->ih_hcrc = htonl(crc_recalc);
+
+	rsz = write(ofd, filebuf, statbuf.st_size + padsz);
+	if (rsz != (int32_t)statbuf.st_size + padsz) {
+		fprintf(stderr,
+			"could not write output file (errnor = %d).\n", errno);
+		exit(1);
+	}
+
+	return 0;
+}