diff --git a/docs/index.rst b/docs/index.rst index 2342481f..3f1f075c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -315,6 +315,7 @@ ipq40xx * ZyXEL + - NBG6617 [#80211s]_ - WRE6606 [#80211s]_ ipq806x diff --git a/patches/openwrt/0009-ipq40xx-add-support-for-the-ZyXEL-NBG6617.patch b/patches/openwrt/0009-ipq40xx-add-support-for-the-ZyXEL-NBG6617.patch new file mode 100644 index 00000000..bf445169 --- /dev/null +++ b/patches/openwrt/0009-ipq40xx-add-support-for-the-ZyXEL-NBG6617.patch @@ -0,0 +1,1023 @@ +From: Christian Lamparter +Date: Thu, 21 Jun 2018 14:24:59 +0200 +Subject: ipq40xx: add support for the ZyXEL NBG6617 + +This patch adds support for ZyXEL NBG6617 + +Hardware highlights: + +SOC: IPQ4018 / QCA Dakota +CPU: Quad-Core ARMv7 Processor rev 5 (v7l) Cortex-A7 +DRAM: 256 MiB DDR3L-1600/1866 Nanya NT5CC128M16IP-DI @ 537 MHz +NOR: 32 MiB Macronix MX25L25635F +ETH: Qualcomm Atheros QCA8075 Gigabit Switch (4 x LAN, 1 x WAN) +USB: 1 x 3.0 (via Synopsys DesignWare DWC3 controller in the SoC) +WLAN1: Qualcomm Atheros QCA4018 2.4GHz 802.11bgn 2:2x2 +WLAN2: Qualcomm Atheros QCA4018 5GHz 802.11a/n/ac 2:2x2 +INPUT: RESET Button, WIFI/Rfkill Togglebutton, WPS Button +LEDS: Power, WAN, LAN 1-4, WLAN 2.4GHz, WLAN 5GHz, USB, WPS + +Serial: + WARNING: The serial port needs a TTL/RS-232 3.3v level converter! + The Serial setting is 115200-8-N-1. The 1x4 .1" header comes + pre-soldered. Pinout: + 1. 3v3 (Label printed on the PCB), 2. RX, 3. GND, 4. TX + +first install / debricking / restore stock: + 0. Have a PC running a tftp-server @ 192.168.1.99/24 + 1. connect the PC to any LAN-Ports + 2. put the openwrt...-factory.bin (or V1.00(ABCT.X).bin for stock) file + into the tftp-server root directory and rename it to just "ras.bin". + 3. power-cycle the router and hold down the the WPS button (for 30sek) + 4. Wait (for a long time - the serial console provides some progress + reports. The u-boot says it best: "Please be patient". + 5. Once the power LED starts to flashes slowly and the USB + WPS LEDs + flashes fast at the same time. You have to reboot the device and + it should then come right up. + +Installation via Web-UI: + 0. Connect a PC to the powered-on router. It will assign your PC a + IP-address via DHCP + 1. Access the Web-UI at 192.168.1.1 (Default Passwort: 1234) + 2. Go to the "Expert Mode" + 3. Under "Maintenance", select "Firmware-Upgrade" + 4. Upload the OpenWRT factory image + 5. Wait for the Device to finish. + It will reboot into OpenWRT without any additional actions needed. + +To open the ZyXEL NBG6617: + 0. remove the four rubber feet glued on the backside + 1. remove the four philips screws and pry open the top cover + (by applying force between the plastic top housing from the + backside/lan-port side) + +Access the real u-boot shell: +ZyXEL uses a proprietary loader/shell on top of u-boot: "ZyXEL zloader v2.02" +When the device is starting up, the user can enter the the loader shell +by simply pressing a key within the 3 seconds once the following string +appears on the serial console: + +| Hit any key to stop autoboot: 3 + +The user is then dropped to a locked shell. + +|NBG6617> HELP +|ATEN x[,y] set BootExtension Debug Flag (y=password) +|ATSE x show the seed of password generator +|ATSH dump manufacturer related data in ROM +|ATRT [x,y,z,u] RAM read/write test (x=level, y=start addr, z=end addr, u=iterations) +|ATGO boot up whole system +|ATUR x upgrade RAS image (filename) +|NBG6617> + +In order to escape/unlock a password challenge has to be passed. +Note: the value is dynamic! you have to calculate your own! + +First use ATSE $MODELNAME (MODELNAME is the hostname in u-boot env) +to get the challange value/seed. + +|NBG6617> ATSE NBG6617 +|012345678901 + +This seed/value can be converted to the password with the help of this +bash script (Thanks to http://www.adslayuda.com/Zyxel650-9.html authors): + +- tool.sh - +ror32() { + echo $(( ($1 >> $2) | (($1 << (32 - $2) & (2**32-1)) ) )) +} +v="0x$1" +a="0x${v:2:6}" +b=$(( $a + 0x10F0A563)) +c=$(( 0x${v:12:14} & 7 )) +p=$(( $(ror32 $b $c) ^ $a )) +printf "ATEN 1,%X\n" $p +- end of tool.sh - + +|# bash ./tool.sh 012345678901 +| +|ATEN 1,879C711 + +copy and paste the result into the shell to unlock zloader. + +|NBG6617> ATEN 1,0046B0017430 + +If the entered code was correct the shell will change to +use the ATGU command to enter the real u-boot shell. + +|NBG6617> ATGU +|NBG6617# + +Co-authored-by: David Bauer +Signed-off-by: Christian Lamparter +Signed-off-by: David Bauer + +diff --git a/include/image-commands.mk b/include/image-commands.mk +index 4d3f025b123f44cfd48d5b6cf081ae7633577277..28b39c310e499caea4fe8a6d9ad6dceb5d95363b 100644 +--- a/include/image-commands.mk ++++ b/include/image-commands.mk +@@ -49,6 +49,19 @@ define Build/eva-image + mv $@.new $@ + endef + ++define Build/make-ras ++ let \ ++ newsize="$(subst k,* 1024,$(RAS_ROOTFS_SIZE))"; \ ++ $(TOPDIR)/scripts/make-ras.sh \ ++ --board $(RAS_BOARD) \ ++ --version $(RAS_VERSION) \ ++ --kernel $(call param_get_default,kernel,$(1),$(IMAGE_KERNEL)) \ ++ --rootfs $@ \ ++ --rootfssize $$newsize \ ++ $@.new ++ @mv $@.new $@ ++endef ++ + define Build/netgear-chk + $(STAGING_DIR_HOST)/bin/mkchkimg \ + -o $@.new \ +diff --git a/package/boot/uboot-envtools/files/ipq40xx b/package/boot/uboot-envtools/files/ipq40xx +index d475e566299416176af3b8646a7510cd3c9787e7..8cd4799b295fd38c9e846af5769c9fa9f5490f8b 100644 +--- a/package/boot/uboot-envtools/files/ipq40xx ++++ b/package/boot/uboot-envtools/files/ipq40xx +@@ -35,6 +35,9 @@ openmesh,a42 |\ + openmesh,a62) + ubootenv_add_uci_config "/dev/mtd5" "0x0" "0x10000" "0x10000" + ;; ++zyxel,nbg6617) ++ ubootenv_add_uci_config "/dev/mtd6" "0x0" "0x10000" "0x10000" ++ ;; + esac + + config_load ubootenv +diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile +index 1cfcc33de3af58e9773d22cdcbe0c95f1633e2d9..b1428f173ddb507f0c92313dcca7aae57284a0b8 100644 +--- a/package/firmware/ipq-wifi/Makefile ++++ b/package/firmware/ipq-wifi/Makefile +@@ -14,7 +14,7 @@ define Build/Compile + endef + + #ALLWIFIBOARDS:= +-ALLWIFIBOARDS:=zyxel_wre6606 ++ALLWIFIBOARDS:=zyxel_nbg6617 zyxel_wre6606 + ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD)) + + define Package/ipq-wifi-default +@@ -50,5 +50,6 @@ endef + + $(eval $(call generate-ipq-wifi-package,zyxel_wre6606,board-zyxel_wre6606.bin,ZyXEL WRE6606)) + #$(eval $(call generate-ipq-wifi-package,,,)) ++$(eval $(call generate-ipq-wifi-package,zyxel_nbg6617,board-zyxel_nbg6617.bin,ZyXEL NBG6617)) + + $(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) +diff --git a/package/firmware/ipq-wifi/board-zyxel_nbg6617.bin b/package/firmware/ipq-wifi/board-zyxel_nbg6617.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..ab4d43e8cbc949c06f74e332807b8d92239a7de0 +GIT binary patch +literal 24276 +zcmeHPdr(tX8b3f3b+K|ohzNKIAwYrF7CNWZXS>;2@eZ$zi`g^ +z&f`1hJHLB!bMHMr?mLO`A@RFK;bEyE3F+|}LLisR0hFvzEC#?IhC)Tzj)J1X;6k}H +z$kafo#Pjxb%W@MuBlek>cl71}w#whU;;2(38j-~gOzsF9giA3;4Z$_HSbvnx~p +zfbkmV)5WavuD}pVn)D-q7f`0x5$896 +z6O4EeFQmY^=s$Q{%tu@|rLlAO*whKs))~iT0R6|J8fIuz^O9Jav$ON6RjZuL1b{ns +z%+wurXCCM}fBc%drBa@~J2_!| +zKz*jZRQgWx*6~58l}R&_-~0v2gKs#2VEi+6ePv;GGOQd{H&sfrcO}P+_hZdq86O%n +z)K_GSlcRM84+De1_*L~;IKtb>QRAOO1DVdC4|YwuE=nJur<-iCsTr~`qS-l_LmN^6qj+*j^V8!Rrw?NO4W$5EiiUA`QZW62=V1%TiRwSfQ?B|P|$!;5g6pQQSmfLhf$%TR4(-q74bwpxt?NI +z)D`hS6VL>1!lMKv1x?|mh~v;WM1=BC9+&rshipf;bGM7b&@hCL8lBKwvaSLaD@-r! +zEAv-%vx5^13h1-0;?ooej5A(D)!QhYM$MZ*r5UBwsL{+->phsYbwk~rx*=Yu7uQRi +zh$cQwL{iaIZmKu}jd&V?M5EE%XmM3dRSmv0^aq5=4Cq6)g}N%@FHc +z)6c*VV{5ngBh8R`@Smrc{j^wBt$knSTJ}0zlah0=<>-?rkth)$KrRgeU@VGPBuW+t +zkQovI5&;qc5&;qc5`h(rz((Fi#E1G8?=2*qx{bFDiKVW=1!NR9UmCe@9_#M4?T%)S +zu@;vF8)F3@LUQVMBJg~M*xA8iHMez#z}9w)<>w;xE6y!ajXnkdrpHx1qmQSj@KG%G +z>^p$PT;dw`)L8H7($tnHev7oM7OdMifB?52IJE$Tg8<0S34m-M79>G2VZhQRYB*pr +zy}g;!q!pIWEM+otTUbC4>;Qf`3P7tf;t&@J0DBDr1VBK^UyT4qcgJ!X;{dg)Mu=X_MD;IXqo1w>b9l>$h3( +z>yPjp93Z*=c$1Fp?cM_^NBNMa?W{)unT=mBvEbK(1?1OX!;b@=&Xr$}+24QU0)!6w +z58fZnuSek|O`_+yJFj+HMKLnn0l5CcUfR74{Cd-%P+I_AKRmqwEZ_pav;YgZ*qL7s +z1vi~*$|N+5qxH~!PrK{RpzosB(uYl65?WYR3>w6;lqhFOeIaT!d-;mowk0P$`@#TV +z38G|++hiLO0TKZcf#r&Ti63u`U;m$f{Pj=YfBy$KIX&kds{{63o=iHP0dhEUp-U1HbcVV}Uijh`tR7ifk5gj|Z_|_@$)=Le~Mqtuv +zU7gj;mS-ieAHQClg+0{1^VsqZ!<3uty!ze9M60G;nJEeV?#6^#Q?1OC@F%WoE+|VR +zNqql_5pAzZDUoR6b|&y0$}ADoYo!FoQ4e +zaUe?9CfYS+sywA|atv0MDRX5h(9Mew%Q!v?YdbX+vP97)oxuY*2YX}*Uh0!B*>V6$ +zlt`2a5O^Jy2Eo+G;uVWP+sKj2v8^F>Uga0Hzf}v*1y*l5a_mCVNluApp-a-;-UDZM +zDE$s?lw2G+b~&LXw9ZR0GJH^za(>J2ypEph$!rX-V#qe6ecgY!Ij+`Uz9~;Nyr-Lg +z-lv)>tLx9}WxJzb=s-$WA1y`@4V4p*u1@l@xFV`S2vUc>FU4}bh-Ab;!<=yvz)rGzCHbPWVwgL +zMRaX&-^ct9edO+WeOhU^@Ek*dR>rNep@=1RE9KTv7UVSfoyClm6hBp9+gM9mSy_{NI +z_{x;(IP#7Z14kY>2q8Z|D2i3$N(l$fwd)v`fx?)hQ>57|Kmg;vQy~96tL@5z#o)g$ +z_7sSC^?3QO$*sr6Ci(SdEPFy8v|;m&lgc1^X2{jAHkef%K!iX + +literal 0 +HcmV?d00001 + +diff --git a/scripts/make-ras.sh b/scripts/make-ras.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..ccddaa0016b0c926d4737abb5757e7212b0a1157 +--- /dev/null ++++ b/scripts/make-ras.sh +@@ -0,0 +1,196 @@ ++#!/usr/bin/env bash ++# ++# --- ZyXEL header format --- ++# Original Version by Benjamin Berg ++# ++# The firmware image prefixed with a header (which is written into the MTD device). ++# The header is one erase block (~64KiB) in size, but the checksum only convers the ++# first 2KiB. Padding is 0xff. All integers are in big-endian. ++# ++# The checksum is always a 16-Bit System V checksum (sum -s) stored in a 32-Bit integer. ++# ++# 4 bytes: checksum of the rootfs image ++# 4 bytes: length of the contained rootfs image file (big endian) ++# 32 bytes: Firmware Version string (NUL terminated, 0xff padded) ++# 4 bytes: checksum over the header partition (big endian - see below) ++# 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) ++# 4 bytes: checksum of the kernel partition ++# 4 bytes: length of the contained kernel image file (big endian) ++# rest: 0xff padding ++# ++# The checksums are calculated by adding up all bytes and if a 16bit ++# overflow occurs, one is added and the sum is masked to 16 bit: ++# csum = csum + databyte; if (csum > 0xffff) { csum += 1; csum &= 0xffff }; ++# Should the file have an odd number of bytes then the byte len-0x800 is ++# used additionally. ++# ++# The checksum for the header is calculated over the first 2048 bytes with ++# the rootfs image checksum as the placeholder during calculation. ++# ++# The header is padded with 0xff to the erase block size of the device. ++# ++board="" ++version="" ++kernel="" ++rootfs="" ++outfile="" ++err="" ++ ++while [ "$1" ]; do ++ case "$1" in ++ "--board") ++ board="$2" ++ shift ++ shift ++ continue ++ ;; ++ "--version") ++ version="$2" ++ shift ++ shift ++ continue ++ ;; ++ "--kernel") ++ kernel="$2" ++ shift ++ shift ++ continue ++ ;; ++ "--rootfs") ++ rootfs="$2" ++ shift ++ shift ++ continue ++ ;; ++ "--rootfssize") ++ rootfssize="$2" ++ shift ++ shift ++ continue ++ ;; ++ *) ++ if [ ! "$outfile" ]; then ++ outfile=$1 ++ shift ++ continue ++ fi ++ ;; ++ esac ++done ++ ++if [ ! -n "$board" -o ! -n "$version" -o ! -r "$kernel" -o ! -r "$rootfs" -o ! "$rootfssize" -o ! "$outfile" ]; then ++ echo "syntax: $0 [--board ras-boardname] [--version ras-version] [--kernel kernelimage] [--rootfs rootfs] out" ++ exit 1 ++fi ++ ++rootfs_len=$(wc -c < "$rootfs") ++ ++if [ "$rootfs_len" -lt "$rootfssize" ]; then ++ dd if=$rootfs of=$rootfs.new bs=$rootfssize conv=sync ++ mv $rootfs.new $rootfs ++fi ++ ++if [ ${#version} -ge 28 ]; then ++ echo "version: '$version' is too long" ++ exit 1 ++fi ++ ++tmpdir="$( mktemp -d 2> /dev/null )" ++if [ -z "$tmpdir" ]; then ++ # try OSX signature ++ tmpdir="$( mktemp -t 'ubitmp' -d )" ++fi ++ ++if [ -z "$tmpdir" ]; then ++ exit 1 ++fi ++ ++to_be() { ++ local val="$1" ++ local size="$2" ++ ++ case "$size" in ++ 4) ++ echo $(( "$val" >> 24 | ("$val" & 0xff0000) >> 8 | ("$val" & 0xff00) << 8 | ("$val" & 0xff) << 24 )) ++ ;; ++ 2) ++ echo $(( "$val" >> 8 | ("$val" & 0xff) << 8)) ++ ;; ++ esac ++} ++ ++checksum_file() { ++ local file=$1 ++ ++ # ZyXEL seems to use System V sum mode... Now this is classy, who would have thought?! ++ echo $(sum -s ${file} | cut -f1 -d" ") ++} ++ ++append_bin() { ++ local val=$1 ++ local size=$2 ++ local file=$3 ++ ++ while [ "$size" -ne 0 ]; do ++ printf \\$(printf %o $(("$val" & 0xff))) >> "$file" ++ val=$(($val >> 8)) ++ let size-=1 ++ done ++ return ++} ++ ++tf=${tmpdir}/out ++pad=$(printf '%0.1s' $(printf "\xff"){1..64}) ++ ++rootfs_header_file="$tmpdir/rootfs_header" ++rootfs_chksum=$(to_be $(checksum_file ${rootfs}) 4) ++rootfs_len=$(to_be $(wc -c < "$rootfs") 4) ++ ++versionpadlen=$(( 32 - ( ${#version} + 1) )) ++ ++# 4 bytes: checksum of the rootfs image ++append_bin "$rootfs_chksum" 4 "$rootfs_header_file" ++# 4 bytes: length of the contained rootfs image file (big endian) ++append_bin "$rootfs_len" 4 "$rootfs_header_file" ++# 32 bytes: Firmware Version string (NUL terminated, 0xff padded) ++printf "%s\x00%.*s" "$version" "$versionpadlen" "$pad" >> "$rootfs_header_file" ++ ++kernel_header_file="$tmpdir/kernel_header" ++kernel_chksum=$(to_be $(checksum_file ${kernel}) 4) ++kernel_len=$(to_be $(wc -c < "$kernel") 4) ++ ++# 4 bytes: checksum of the kernel image ++append_bin "$kernel_chksum" 4 "$kernel_header_file" ++# 4 bytes: length of the contained kernel image file (big endian) ++append_bin "$kernel_len" 4 "$kernel_header_file" ++ ++board_header_file="$tmpdir/board_header" ++board_file="$tmpdir/board" ++boardpadlen=$(( 64 - ( ${#board} + 1) )) ++# 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) ++printf "%s\x00%.*s" "$board" "$boardpadlen" "$pad" > "$board_file" ++cat "$kernel_header_file" >> "$board_file" ++printf "%.12s" "$pad" >> "$board_file" ++# rest: 0xff padding ++for i in {1..511}; do ++ printf "%s%s" "$pad" "$pad" >> "$board_file" ++done ++ ++tmp_board_file="$tmpdir/tmp_board_file" ++cat "$rootfs_header_file" > "$tmp_board_file" ++ ++# The checksum for the header is calculated over the first 2048 bytes with ++# the rootfs image checksum as the placeholder during calculation. ++append_bin "$rootfs_chksum" 4 "$tmp_board_file" ++cat "$board_file" >> "$tmp_board_file" ++ ++truncate -s 2048 $tmp_board_file ++board_chksum=$(to_be $(checksum_file ${tmp_board_file}) 4) ++ ++# 4 bytes: checksum over the header partition (big endian) ++append_bin "$board_chksum" 4 "$board_header_file" ++cat "$board_file" >> "$board_header_file" ++ ++cat "$rootfs_header_file" "$board_header_file" "$rootfs" "$kernel" > "$outfile" ++ ++rm -rf "$tmpdir" +diff --git a/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +index fcba2aea543cdead03ef372bc6b751481846fbf7..475a8623f705d683a7ee3521ee71f2b57fa2e44d 100755 +--- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +@@ -34,6 +34,11 @@ netgear,ex6150v2) + meraki,mr33) + ucidef_set_interface_lan "eth0" + ;; ++zyxel,nbg6617) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2G" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5G" "phy1tpt" ++ ucidef_set_led_usbport "usb" "USB" "${board}:green:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" ++ ;; + zyxel,wre6606) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:green:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:green:wlan5g" "phy1tpt" +diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network +index 03e0c0e16c33f43fafcbba9c5af4baf6dd73e425..5c90ef136fd7cbbe023001030d8c9003347bd249 100755 +--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network ++++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network +@@ -48,6 +48,11 @@ netgear,ex6150v2 |\ + zyxel,wre6606) + ucidef_set_interface_lan "eth0" + ;; ++zyxel,nbg6617) ++ ucidef_set_interfaces_lan_wan "eth0" "eth1" ++ ucidef_add_switch "switch0" \ ++ "0u@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" ++ ;; + *) + echo "Unsupported hardware. Network interfaces not intialized" + ;; +diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index d89ddf6e57ee9f759f6dcc7c7f8152c11305499b..1d4fd9cd8f9a3983ac3323ce72153c1dcc17a69a 100644 +--- a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -146,6 +146,7 @@ case "$FIRMWARE" in + openmesh,a62) + ath10kcal_extract "0:ART" 4096 12064 + ;; ++ zyxel,nbg6617 |\ + zyxel,wre6606) + ath10kcal_extract "ART" 4096 12064 + ath10kcal_patch_mac_crc $(macaddr_add $(cat /sys/class/net/eth0/address) -2) +@@ -181,6 +182,7 @@ case "$FIRMWARE" in + openmesh,a62) + ath10kcal_extract "0:ART" 20480 12064 + ;; ++ zyxel,nbg6617 |\ + zyxel,wre6606) + ath10kcal_extract "ART" 20480 12064 + ath10kcal_patch_mac_crc $(macaddr_add $(cat /sys/class/net/eth0/address) -1) +diff --git a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh +index 1acd7366c81f7c70ef9018d97a833e4d355e8119..44e81ca366dd57d3d5d7fbb9065254925e94061a 100644 +--- a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh ++++ b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh +@@ -8,6 +8,10 @@ preinit_set_mac_address() { + mac_lan=$(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 102) + [ -n "$mac_lan" ] && ip link set dev eth0 address "$mac_lan" + ;; ++ zyxel,nbg6617) ++ base_mac=$(cat /sys/class/net/eth0/address) ++ ip link set dev eth0 address $(macaddr_add "$base_mac" +2) ++ ip link set dev eth1 address $(macaddr_add "$base_mac" +3) + esac + } + +diff --git a/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh b/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh +new file mode 100644 +index 0000000000000000000000000000000000000000..578ddbe4c4f6e91d925ea3a0de9e060daac82e72 +--- /dev/null ++++ b/target/linux/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh +@@ -0,0 +1,19 @@ ++#!/bin/sh ++ ++set_preinit_iface() { ++ . /lib/functions.sh ++ ++ case $(board_name) in ++ asus,rt-ac58u| \ ++ avm,fritzbox-4040| \ ++ glinet,gl-b1300| \ ++ meraki,mr33| \ ++ zyxel,nbg6617) ++ ifname=eth0 ++ ;; ++ *) ++ ;; ++ esac ++} ++ ++boot_hook_add preinit_main set_preinit_iface +diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh +index 4096e127ea9eaa8106475a3143b0b2ea796b5c7c..0e29302465fb5fca6f2a2194c751728f492053d5 100644 +--- a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh +@@ -29,6 +29,21 @@ EOF + return 0; + } + ++zyxel_do_upgrade() { ++ local tar_file="$1" ++ ++ local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') ++ board_dir=${board_dir%/} ++ ++ tar Oxf $tar_file ${board_dir}/kernel | mtd write - kernel ++ ++ if [ "$SAVE_CONFIG" -eq 1 ]; then ++ tar Oxf $tar_file ${board_dir}/root | mtd -j "$CONF_TAR" write - rootfs ++ else ++ tar Oxf $tar_file ${board_dir}/root | mtd write - rootfs ++ fi ++} ++ + platform_do_upgrade() { + case "$(board_name)" in + 8dev,jalapeno) +@@ -48,6 +63,9 @@ platform_do_upgrade() { + CI_KERNPART="part.safe" + nand_do_upgrade "$1" + ;; ++ zyxel,nbg6617) ++ zyxel_do_upgrade "$1" ++ ;; + *) + default_do_upgrade "$ARGV" + ;; +diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..d7f8c5955caee15d373a342b75c8c1947f5b8022 +--- /dev/null ++++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts +@@ -0,0 +1,321 @@ ++/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include "qcom-ipq4019.dtsi" ++#include "qcom-ipq4019-bus.dtsi" ++#include ++#include ++#include ++#include ++ ++/ { ++ model = "ZyXEL NBG6617"; ++ compatible = "zyxel,nbg6617", "qcom,ipq4019"; ++ ++ chosen { ++ /* ++ * the vendor u-boot adds root and mtdparts cmdline parameters ++ * which we don't want... but we have to overwrite them or else ++ * the kernel will take them at face value. ++ */ ++ bootargs-append = " mtdparts= root=31:13"; ++ }; ++ ++ aliases { ++ led-boot = &power; ++ led-failsafe = &power; ++ led-running = &power; ++ led-upgrade = &power; ++ }; ++ ++ soc { ++ mdio@90000 { ++ status = "okay"; ++ }; ++ ++ ess-psgmii@98000 { ++ status = "okay"; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ tcsr@194b000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x194b000 0x100>; ++ qcom,usb-hsphy-mode-select = ; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ ++ usb2@60f8800 { ++ status = "okay"; ++ }; ++ ++ serial@78af000 { ++ pinctrl-0 = <&serial_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ usb3@8af8800 { ++ status = "okay"; ++ }; ++ ++ crypto@8e3a000 { ++ status = "okay"; ++ }; ++ ++ watchdog@b017000 { ++ status = "okay"; ++ }; ++ ++ ess-switch@c000000 { ++ status = "okay"; ++ }; ++ ++ edma@c080000 { ++ status = "okay"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wlan { ++ label = "wlan"; ++ gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; ++ linux,code = ; ++ linux,input-type = ; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ pinctrl-0 = <&led_pins>; ++ pinctrl-names = "default"; ++ ++ power: power { ++ label = "nbg6617:green:power"; ++ gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ usb { ++ label = "nbg6617:green:usb"; ++ gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wlan2G { ++ label = "nbg6617:green:wlan2G"; ++ gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wlan5G { ++ label = "nbg6617:green:wlan5G"; ++ gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wps { ++ label = "nbg6617:green:wps"; ++ gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; ++ ++&tlmm { ++ serial_pins: serial_pinmux { ++ mux { ++ pins = "gpio60", "gpio61"; ++ function = "blsp_uart0"; ++ bias-disable; ++ }; ++ }; ++ spi_0_pins: spi_0_pinmux { ++ mux { ++ function = "blsp_spi0"; ++ pins = "gpio55", "gpio56", "gpio57"; ++ drive-strength = <12>; ++ bias-disable; ++ }; ++ ++ mux_cs { ++ function = "gpio"; ++ pins = "gpio54"; ++ drive-strength = <2>; ++ bias-disable; ++ output-low; ++ }; ++ }; ++ led_pins: led_pinmux { ++ mux { ++ pins = "gpio0", "gpio1", "gpio3", "gpio5", "gpio58"; ++ drive-strength = <0x8>; ++ bias-disable; ++ output-low; ++ }; ++ }; ++}; ++ ++&spi_0 { /* BLSP1 QUP1 */ ++ pinctrl-0 = <&spi_0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; ++ ++ mx25l25635f@0 { ++ compatible = "mx25l25635f", "jedec,spi-nor"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ status = "okay"; ++ m25p,fast-read; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition0@0 { ++ label = "SBL1"; ++ reg = <0x00000000 0x00040000>; ++ read-only; ++ }; ++ partition1@40000 { ++ label = "MIBIB"; ++ reg = <0x00040000 0x00020000>; ++ read-only; ++ }; ++ partition2@60000 { ++ label = "QSEE"; ++ reg = <0x00060000 0x00060000>; ++ read-only; ++ }; ++ partition3@c0000 { ++ label = "CDT"; ++ reg = <0x000c0000 0x00010000>; ++ read-only; ++ }; ++ partition4@d0000 { ++ label = "DDRPARAMS"; ++ reg = <0x000d0000 0x00010000>; ++ read-only; ++ }; ++ partition5@e0000 { ++ label = "APPSBL"; /* u-boot */ ++ reg = <0x000e0000 0x00080000>; ++ /* U-Boot Standalone App "zloader" is located at 0x64000 */ ++ read-only; ++ }; ++ partition6@160000 { ++ label = "APPSBLENV"; /* u-boot env */ ++ reg = <0x00160000 0x00010000>; ++ }; ++ partition7@170000 { ++ /* make a backup of this partition! */ ++ label = "ART"; ++ reg = <0x00170000 0x00010000>; ++ read-only; ++ }; ++ partition8@180000 { ++ label = "kernel"; ++ reg = <0x00180000 0x00400000>; ++ }; ++ partition9@580000 { ++ label = "dualflag"; ++ reg = <0x00580000 0x00010000>; ++ read-only; ++ }; ++ partition10@590000 { ++ label = "header"; ++ reg = <0x00590000 0x00010000>; ++ }; ++ partition11@5a0000 { ++ label = "romd"; ++ reg = <0x005a0000 0x00100000>; ++ read-only; ++ }; ++ partition12@6a0000 { ++ label = "not_root_data"; ++ /* ++ * for some strange reason, someone at ZyXEL ++ * had the "great" idea to put the rootfs_data ++ * in front of rootfs... Don't do that! ++ * As a result this one, full MebiByte remains ++ * unused. ++ */ ++ reg = <0x006a0000 0x00100000>; ++ }; ++ partition13@7a0000 { ++ label = "rootfs"; ++ reg = <0x007a0000 0x01860000>; ++ }; ++ }; ++ }; ++}; ++ ++&cryptobam { ++ status = "okay"; ++}; ++ ++&blsp_dma { ++ status = "okay"; ++}; ++ ++&wifi0 { ++ status = "okay"; ++}; ++ ++&wifi1 { ++ status = "okay"; ++}; ++ ++&usb3_ss_phy { ++ status = "okay"; ++}; ++ ++&usb3_hs_phy { ++ status = "okay"; ++}; ++ ++&usb2_hs_phy { ++ status = "okay"; ++}; +diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile +index 38600cf979242142aa08c30163e63d911f0ddb63..d1ee1004fddce6cf6007259229d8eee5b5b2ea3b 100644 +--- a/target/linux/ipq40xx/image/Makefile ++++ b/target/linux/ipq40xx/image/Makefile +@@ -1,6 +1,8 @@ + include $(TOPDIR)/rules.mk + include $(INCLUDE_DIR)/image.mk + ++DEVICE_VARS += RAS_BOARD RAS_ROOTFS_SIZE RAS_VERSION ++ + define Device/Default + PROFILES := Default + KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) +@@ -205,6 +207,26 @@ define Device/qcom_ap-dk04.1-c1 + endef + TARGET_DEVICES += qcom_ap-dk04.1-c1 + ++define Device/zyxel_nbg6617 ++ $(call Device/FitImageLzma) ++ DEVICE_DTS := qcom-ipq4018-nbg6617 ++ DEVICE_TITLE := ZyXEL NBG6617 ++ ROOTFS_SIZE := 24960k ++ RAS_BOARD := NBG6617 ++ RAS_ROOTFS_SIZE := 19840k ++ RAS_VERSION := "$(VERSION_DIST) $(REVISION)" ++ IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata ++ IMAGES := sysupgrade.bin factory.bin ++# The ZyXEL firmware allows flashing thru the web-gui only when the rootfs is ++# at least as large as the one of the initial firmware image (not the current ++# one on the device). This only applies to the Web-UI, the bootlaoder ignores ++# this minimum-size. However, the larger image can be flashed both ways. ++ IMAGE/factory.bin := append-rootfs | pad-rootfs | check-size $$$$(ROOTFS_SIZE) | make-ras ++ IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | check-size $$$$(ROOTFS_SIZE) | sysupgrade-tar rootfs=$$$$@ | append-metadata ++ DEVICE_PACKAGES := ipq-wifi-zyxel_nbg6617 uboot-envtools ++endef ++TARGET_DEVICES += zyxel_nbg6617 ++ + define Device/zyxel_wre6606 + $(call Device/FitImage) + DEVICE_TITLE := ZyXEL WRE6606 +diff --git a/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch +index 3aa368be8381d9c48aefccbe6d4cc768b00dc41e..8066f986a4e030c9c8fe0ec4438e92d30daa77f0 100644 +--- a/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch ++++ b/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch +@@ -10,7 +10,7 @@ Signed-off-by: John Crispin + + --- a/arch/arm/boot/dts/Makefile + +++ b/arch/arm/boot/dts/Makefile +-@@ -697,7 +697,19 @@ dtb-$(CONFIG_ARCH_QCOM) += \ ++@@ -697,7 +697,20 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8074-dragonboard.dtb \ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ +@@ -19,6 +19,7 @@ Signed-off-by: John Crispin + + qcom-ipq4018-ex6150v2.dtb \ + + qcom-ipq4018-fritz4040.dtb \ + + qcom-ipq4018-jalapeno.dtb \ +++ qcom-ipq4018-nbg6617.dtb \ + + qcom-ipq4018-rt-ac58u.dtb \ + + qcom-ipq4018-wre6606.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ +diff --git a/target/linux/ipq40xx/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch b/target/linux/ipq40xx/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..7c513a6ad8ec817bf388c67e1181f08982888fa5 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +@@ -0,0 +1,64 @@ ++Index: linux-4.14.50/drivers/mtd/spi-nor/spi-nor.c ++=================================================================== ++--- linux-4.14.50.orig/drivers/mtd/spi-nor/spi-nor.c +++++ linux-4.14.50/drivers/mtd/spi-nor/spi-nor.c ++@@ -1025,6 +1025,7 @@ static const struct flash_info spi_nor_i ++ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, ++ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, ++ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +++ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, ++ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, ++ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, ++ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++@@ -1189,11 +1190,12 @@ static const struct flash_info spi_nor_i ++ { }, ++ }; ++ ++-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) +++static const struct flash_info *spi_nor_read_id(struct spi_nor *nor, +++ const char *name) ++ { ++ int tmp; ++ u8 id[SPI_NOR_MAX_ID_LEN]; ++- const struct flash_info *info; +++ const struct flash_info *info, *first_match = NULL; ++ ++ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); ++ if (tmp < 0) { ++@@ -1204,10 +1206,16 @@ static const struct flash_info *spi_nor_ ++ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { ++ info = &spi_nor_ids[tmp]; ++ if (info->id_len) { ++- if (!memcmp(info->id, id, info->id_len)) ++- return &spi_nor_ids[tmp]; +++ if (!memcmp(info->id, id, info->id_len)) { +++ if (!name || !strcmp(name, info->name)) +++ return info; +++ if (!first_match) +++ first_match = info; +++ } ++ } ++ } +++ if (first_match) +++ return first_match; ++ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", ++ id[0], id[1], id[2]); ++ return ERR_PTR(-ENODEV); ++@@ -2667,7 +2675,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ info = spi_nor_match_id(name); ++ /* Try to auto-detect if chip name wasn't specified or not found */ ++ if (!info) ++- info = spi_nor_read_id(nor); +++ info = spi_nor_read_id(nor, NULL); ++ if (IS_ERR_OR_NULL(info)) ++ return -ENOENT; ++ ++@@ -2678,7 +2686,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ if (name && info->id_len) { ++ const struct flash_info *jinfo; ++ ++- jinfo = spi_nor_read_id(nor); +++ jinfo = spi_nor_read_id(nor, name); ++ if (IS_ERR(jinfo)) { ++ return PTR_ERR(jinfo); ++ } else if (jinfo != info) { diff --git a/patches/openwrt/0010-build-add-mkrasimage.patch b/patches/openwrt/0010-build-add-mkrasimage.patch new file mode 100644 index 00000000..941c2fe1 --- /dev/null +++ b/patches/openwrt/0010-build-add-mkrasimage.patch @@ -0,0 +1,782 @@ +From: David Bauer +Date: Wed, 22 Aug 2018 17:30:44 +0200 +Subject: build: add mkrasimage + +The current make-ras.sh image generation script for the ZyXEL NBG6617 +has portability issues with bash. Because of this, factory images are +currently not built correctly by the OpenWRT buildbots. + +This commit replaces the make-ras.sh by C-written mkrasimage. + +The new mkrasimage is also compatible with other ZyXEL devices using +the ras image-format. +This is not tested with the NBG6616 but it correctly builds the +header for ZyXEL factory image. + +Signed-off-by: David Bauer + +diff --git a/include/image-commands.mk b/include/image-commands.mk +index 28b39c310e499caea4fe8a6d9ad6dceb5d95363b..552d8db1cbacf533c12d0d8e2e5cffbe5591adb4 100644 +--- a/include/image-commands.mk ++++ b/include/image-commands.mk +@@ -49,17 +49,17 @@ define Build/eva-image + mv $@.new $@ + endef + +-define Build/make-ras ++define Build/zyxel-ras-image + let \ + newsize="$(subst k,* 1024,$(RAS_ROOTFS_SIZE))"; \ +- $(TOPDIR)/scripts/make-ras.sh \ +- --board $(RAS_BOARD) \ +- --version $(RAS_VERSION) \ +- --kernel $(call param_get_default,kernel,$(1),$(IMAGE_KERNEL)) \ +- --rootfs $@ \ +- --rootfssize $$newsize \ +- $@.new +- @mv $@.new $@ ++ $(STAGING_DIR_HOST)/bin/mkrasimage \ ++ -b $(RAS_BOARD) \ ++ -v $(RAS_VERSION) \ ++ -r $@ \ ++ -s $$newsize \ ++ -o $@.new \ ++ $(if $(findstring separate-kernel,$(word 1,$(1))),-k $(IMAGE_KERNEL)) \ ++ && mv $@.new $@ + endef + + define Build/netgear-chk +diff --git a/scripts/make-ras.sh b/scripts/make-ras.sh +deleted file mode 100755 +index ccddaa0016b0c926d4737abb5757e7212b0a1157..0000000000000000000000000000000000000000 +--- a/scripts/make-ras.sh ++++ /dev/null +@@ -1,196 +0,0 @@ +-#!/usr/bin/env bash +-# +-# --- ZyXEL header format --- +-# Original Version by Benjamin Berg +-# +-# The firmware image prefixed with a header (which is written into the MTD device). +-# The header is one erase block (~64KiB) in size, but the checksum only convers the +-# first 2KiB. Padding is 0xff. All integers are in big-endian. +-# +-# The checksum is always a 16-Bit System V checksum (sum -s) stored in a 32-Bit integer. +-# +-# 4 bytes: checksum of the rootfs image +-# 4 bytes: length of the contained rootfs image file (big endian) +-# 32 bytes: Firmware Version string (NUL terminated, 0xff padded) +-# 4 bytes: checksum over the header partition (big endian - see below) +-# 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) +-# 4 bytes: checksum of the kernel partition +-# 4 bytes: length of the contained kernel image file (big endian) +-# rest: 0xff padding +-# +-# The checksums are calculated by adding up all bytes and if a 16bit +-# overflow occurs, one is added and the sum is masked to 16 bit: +-# csum = csum + databyte; if (csum > 0xffff) { csum += 1; csum &= 0xffff }; +-# Should the file have an odd number of bytes then the byte len-0x800 is +-# used additionally. +-# +-# The checksum for the header is calculated over the first 2048 bytes with +-# the rootfs image checksum as the placeholder during calculation. +-# +-# The header is padded with 0xff to the erase block size of the device. +-# +-board="" +-version="" +-kernel="" +-rootfs="" +-outfile="" +-err="" +- +-while [ "$1" ]; do +- case "$1" in +- "--board") +- board="$2" +- shift +- shift +- continue +- ;; +- "--version") +- version="$2" +- shift +- shift +- continue +- ;; +- "--kernel") +- kernel="$2" +- shift +- shift +- continue +- ;; +- "--rootfs") +- rootfs="$2" +- shift +- shift +- continue +- ;; +- "--rootfssize") +- rootfssize="$2" +- shift +- shift +- continue +- ;; +- *) +- if [ ! "$outfile" ]; then +- outfile=$1 +- shift +- continue +- fi +- ;; +- esac +-done +- +-if [ ! -n "$board" -o ! -n "$version" -o ! -r "$kernel" -o ! -r "$rootfs" -o ! "$rootfssize" -o ! "$outfile" ]; then +- echo "syntax: $0 [--board ras-boardname] [--version ras-version] [--kernel kernelimage] [--rootfs rootfs] out" +- exit 1 +-fi +- +-rootfs_len=$(wc -c < "$rootfs") +- +-if [ "$rootfs_len" -lt "$rootfssize" ]; then +- dd if=$rootfs of=$rootfs.new bs=$rootfssize conv=sync +- mv $rootfs.new $rootfs +-fi +- +-if [ ${#version} -ge 28 ]; then +- echo "version: '$version' is too long" +- exit 1 +-fi +- +-tmpdir="$( mktemp -d 2> /dev/null )" +-if [ -z "$tmpdir" ]; then +- # try OSX signature +- tmpdir="$( mktemp -t 'ubitmp' -d )" +-fi +- +-if [ -z "$tmpdir" ]; then +- exit 1 +-fi +- +-to_be() { +- local val="$1" +- local size="$2" +- +- case "$size" in +- 4) +- echo $(( "$val" >> 24 | ("$val" & 0xff0000) >> 8 | ("$val" & 0xff00) << 8 | ("$val" & 0xff) << 24 )) +- ;; +- 2) +- echo $(( "$val" >> 8 | ("$val" & 0xff) << 8)) +- ;; +- esac +-} +- +-checksum_file() { +- local file=$1 +- +- # ZyXEL seems to use System V sum mode... Now this is classy, who would have thought?! +- echo $(sum -s ${file} | cut -f1 -d" ") +-} +- +-append_bin() { +- local val=$1 +- local size=$2 +- local file=$3 +- +- while [ "$size" -ne 0 ]; do +- printf \\$(printf %o $(("$val" & 0xff))) >> "$file" +- val=$(($val >> 8)) +- let size-=1 +- done +- return +-} +- +-tf=${tmpdir}/out +-pad=$(printf '%0.1s' $(printf "\xff"){1..64}) +- +-rootfs_header_file="$tmpdir/rootfs_header" +-rootfs_chksum=$(to_be $(checksum_file ${rootfs}) 4) +-rootfs_len=$(to_be $(wc -c < "$rootfs") 4) +- +-versionpadlen=$(( 32 - ( ${#version} + 1) )) +- +-# 4 bytes: checksum of the rootfs image +-append_bin "$rootfs_chksum" 4 "$rootfs_header_file" +-# 4 bytes: length of the contained rootfs image file (big endian) +-append_bin "$rootfs_len" 4 "$rootfs_header_file" +-# 32 bytes: Firmware Version string (NUL terminated, 0xff padded) +-printf "%s\x00%.*s" "$version" "$versionpadlen" "$pad" >> "$rootfs_header_file" +- +-kernel_header_file="$tmpdir/kernel_header" +-kernel_chksum=$(to_be $(checksum_file ${kernel}) 4) +-kernel_len=$(to_be $(wc -c < "$kernel") 4) +- +-# 4 bytes: checksum of the kernel image +-append_bin "$kernel_chksum" 4 "$kernel_header_file" +-# 4 bytes: length of the contained kernel image file (big endian) +-append_bin "$kernel_len" 4 "$kernel_header_file" +- +-board_header_file="$tmpdir/board_header" +-board_file="$tmpdir/board" +-boardpadlen=$(( 64 - ( ${#board} + 1) )) +-# 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) +-printf "%s\x00%.*s" "$board" "$boardpadlen" "$pad" > "$board_file" +-cat "$kernel_header_file" >> "$board_file" +-printf "%.12s" "$pad" >> "$board_file" +-# rest: 0xff padding +-for i in {1..511}; do +- printf "%s%s" "$pad" "$pad" >> "$board_file" +-done +- +-tmp_board_file="$tmpdir/tmp_board_file" +-cat "$rootfs_header_file" > "$tmp_board_file" +- +-# The checksum for the header is calculated over the first 2048 bytes with +-# the rootfs image checksum as the placeholder during calculation. +-append_bin "$rootfs_chksum" 4 "$tmp_board_file" +-cat "$board_file" >> "$tmp_board_file" +- +-truncate -s 2048 $tmp_board_file +-board_chksum=$(to_be $(checksum_file ${tmp_board_file}) 4) +- +-# 4 bytes: checksum over the header partition (big endian) +-append_bin "$board_chksum" 4 "$board_header_file" +-cat "$board_file" >> "$board_header_file" +- +-cat "$rootfs_header_file" "$board_header_file" "$rootfs" "$kernel" > "$outfile" +- +-rm -rf "$tmpdir" +diff --git a/target/linux/ar71xx/image/generic.mk b/target/linux/ar71xx/image/generic.mk +index 640557532c8a02f37bc6f84ade8cb34e7172162d..4568b656219419e9ca1156c6716bd2124074cb32 100644 +--- a/target/linux/ar71xx/image/generic.mk ++++ b/target/linux/ar71xx/image/generic.mk +@@ -1086,8 +1086,12 @@ define Device/NBG6616 + IMAGE_SIZE := 15323k + MTDPARTS := spi0.0:192k(u-boot)ro,64k(env)ro,64k(RFdata)ro,384k(zyxel_rfsd),384k(romd),64k(header),2048k(kernel),13184k(rootfs),15232k@0x120000(firmware) + CMDLINE += mem=128M +- IMAGES := sysupgrade.bin ++ RAS_BOARD := NBG6616 ++ RAS_ROOTFS_SIZE := 14464k ++ RAS_VERSION := "$(VERSION_DIST) $(REVISION)" ++ IMAGES := factory.bin sysupgrade.bin + KERNEL := kernel-bin | patch-cmdline | lzma | uImage lzma | jffs2 boot/vmlinux.lzma.uImage ++ IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | pad-to 64k | check-size $$$$(IMAGE_SIZE) | zyxel-ras-image + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) + # We cannot currently build a factory image. It is the sysupgrade image + # prefixed with a header (which is actually written into the MTD device). +diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile +index d1ee1004fddce6cf6007259229d8eee5b5b2ea3b..5cd11cae237b4658906652967d8120bd0dc080a8 100644 +--- a/target/linux/ipq40xx/image/Makefile ++++ b/target/linux/ipq40xx/image/Makefile +@@ -221,7 +221,7 @@ define Device/zyxel_nbg6617 + # at least as large as the one of the initial firmware image (not the current + # one on the device). This only applies to the Web-UI, the bootlaoder ignores + # this minimum-size. However, the larger image can be flashed both ways. +- IMAGE/factory.bin := append-rootfs | pad-rootfs | check-size $$$$(ROOTFS_SIZE) | make-ras ++ IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k | check-size $$$$(ROOTFS_SIZE) | zyxel-ras-image separate-kernel + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | check-size $$$$(ROOTFS_SIZE) | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ipq-wifi-zyxel_nbg6617 uboot-envtools + endef +diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile +index 2902af3231a87592e9c040e7e7e1e4e1958a01a5..a7f740ff62e05c7f6f24caa6da538302abee8d8f 100644 +--- a/target/linux/ipq806x/image/Makefile ++++ b/target/linux/ipq806x/image/Makefile +@@ -67,7 +67,8 @@ define Device/ZyXELImage + KERNEL_SUFFIX := -uImage + KERNEL = kernel-bin | append-dtb | uImage none | pad-to $${KERNEL_SIZE} + KERNEL_NAME := zImage +- IMAGES := sysupgrade.bin mmcblk0p5-rootfs.bin mmcblk0p4-kernel.bin ++ IMAGES := factory.bin sysupgrade.bin mmcblk0p5-rootfs.bin mmcblk0p4-kernel.bin ++ IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to $$$$(BLOCKSIZE) | zyxel-ras-image separate-kernel + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to $$$${BLOCKSIZE} | sysupgrade-tar rootfs=$$$$@ | append-metadata + IMAGE/mmcblk0p5-rootfs.bin := append-rootfs | pad-rootfs | pad-to $$$${BLOCKSIZE} + IMAGE/mmcblk0p4-kernel.bin := append-kernel +@@ -245,6 +246,9 @@ define Device/zyxel_nbg6817 + KERNEL_SIZE := 4096k + BLOCKSIZE := 64k + BOARD_NAME := nbg6817 ++ RAS_BOARD := NBG6817 ++ RAS_ROOTFS_SIZE := 20934k ++ RAS_VERSION := "V1.99(OWRT.9999)C0" + SUPPORTED_DEVICES += nbg6817 + DEVICE_TITLE := ZyXEL NBG6817 + DEVICE_PACKAGES := ath10k-firmware-qca9984 e2fsprogs kmod-fs-ext4 losetup +diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile +index 4b4af999088455e3d9231b227fecfa71c8284b2f..a6379e35eb01f1cbbe2b1ece3fc9eb20bcd68d90 100644 +--- a/tools/firmware-utils/Makefile ++++ b/tools/firmware-utils/Makefile +@@ -70,6 +70,7 @@ define Host/Compile + $(call cc,fix-u-media-header cyg_crc32,-Wall) + $(call cc,hcsmakeimage bcmalgo) + $(call cc,mkporayfw, -Wall) ++ $(call cc,mkrasimage, --std=gnu99) + $(call cc,mkhilinkfw, -lcrypto) + $(call cc,mkdcs932, -Wall) + $(call cc,mkheader_gemtek,-lz) +diff --git a/tools/firmware-utils/src/mkrasimage.c b/tools/firmware-utils/src/mkrasimage.c +new file mode 100644 +index 0000000000000000000000000000000000000000..8eee29cc086a04104b51e263aeac0e73340056ca +--- /dev/null ++++ b/tools/firmware-utils/src/mkrasimage.c +@@ -0,0 +1,459 @@ ++/* ++ * --- ZyXEL header format --- ++ * Original Version by Benjamin Berg ++ * C implementation based on generation-script by Christian Lamparter ++ * ++ * The firmware image prefixed with a header (which is written into the MTD device). ++ * The header is one erase block (~64KiB) in size, but the checksum only convers the ++ * first 2KiB. Padding is 0xff. All integers are in big-endian. ++ * ++ * The checksum is always a 16-Bit System V checksum (sum -s) stored in a 32-Bit integer. ++ * ++ * 4 bytes: checksum of the rootfs image ++ * 4 bytes: length of the contained rootfs image file (big endian) ++ * 32 bytes: Firmware Version string (NUL terminated, 0xff padded) ++ * 4 bytes: checksum over the header partition (big endian - see below) ++ * 64 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) ++ * 4 bytes: checksum of the kernel partition ++ * 4 bytes: length of the contained kernel image file (big endian) ++ * rest: 0xff padding (To erase block size) ++ * ++ * The kernel partition checksum and length is not used for every device. ++ * If it's notused, pad those 8 bytes with 0xFF. ++ * ++ * The checksums are calculated by adding up all bytes and if a 16bit ++ * overflow occurs, one is added and the sum is masked to 16 bit: ++ * csum = csum + databyte; if (csum > 0xffff) { csum += 1; csum &= 0xffff }; ++ * Should the file have an odd number of bytes then the byte len-0x800 is ++ * used additionally. ++ * ++ * The checksum for the header is calculated over the first 2048 bytes with ++ * the rootfs image checksum as the placeholder during calculation. ++ * ++ * 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. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#define VERSION_STRING_LEN 31 ++#define ROOTFS_HEADER_LEN 40 ++ ++#define KERNEL_HEADER_LEN 8 ++ ++#define BOARD_NAME_LEN 64 ++#define BOARD_HEADER_LEN 68 ++ ++#define HEADER_PARTITION_CALC_LENGTH 2048 ++#define HEADER_PARTITION_LENGTH 0x10000 ++ ++struct file_info { ++ char *name; /* name of the file */ ++ char *data; /* file content */ ++ size_t size; /* length of the file */ ++}; ++ ++static char *progname; ++ ++static char *board_name = 0; ++static char *version_name = 0; ++static unsigned int rootfs_size = 0; ++ ++static struct file_info kernel = { NULL, NULL, 0 }; ++static struct file_info rootfs = { NULL, NULL, 0 }; ++static struct file_info rootfs_out = { NULL, NULL, 0 }; ++static struct file_info out = { NULL, NULL, 0 }; ++ ++#define ERR(fmt, ...) do { \ ++ fprintf(stderr, "[%s] *** error: " fmt "\n", \ ++ progname, ## __VA_ARGS__ ); \ ++} while (0) ++ ++void map_file(struct file_info *finfo) ++{ ++ struct stat file_stat = {0}; ++ int fd; ++ ++ fd = open(finfo->name, O_RDONLY, (mode_t)0600); ++ if (fd == -1) { ++ ERR("Error while opening file %s.", finfo->name); ++ exit(EXIT_FAILURE); ++ } ++ ++ if (fstat(fd, &file_stat) == -1) { ++ ERR("Error getting file size for %s.", finfo->name); ++ exit(EXIT_FAILURE); ++ } ++ ++ finfo->size = file_stat.st_size; ++ finfo->data = mmap(0, finfo->size, PROT_READ, MAP_SHARED, fd, 0); ++ ++ if (finfo->data == MAP_FAILED) { ++ ERR("Error mapping file %s.", finfo->name); ++ exit(EXIT_FAILURE); ++ } ++ ++ close(fd); ++} ++ ++void unmap_file(struct file_info *finfo) ++{ ++ if(munmap(finfo->data, finfo->size) == -1) { ++ ERR("Error unmapping file %s.", finfo->name); ++ exit(EXIT_FAILURE); ++ } ++} ++ ++void write_file(struct file_info *finfo) ++{ ++ FILE *fout = fopen(finfo->name, "w"); ++ ++ fwrite(finfo->data, finfo->size, 1, fout); ++ ++ if (ferror(fout)) { ++ ERR("Wanted to write, but something went wrong."); ++ exit(EXIT_FAILURE); ++ } ++ ++ fclose(fout); ++} ++ ++void usage(int status) ++{ ++ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; ++ ++ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); ++ fprintf(stream, ++ "\n" ++ "Options:\n" ++ " -k path for kernel image\n" ++ " -r path for rootfs image\n" ++ " -s size of output rootfs\n" ++ " -v version string\n" ++ " -b name of board to generate image for\n" ++ " -o name of output image\n" ++ " -h show this screen\n" ++ ); ++ ++ exit(status); ++} ++ ++static int sysv_chksm(const unsigned char *data, int size) ++{ ++ int r; ++ int checksum; ++ unsigned int s = 0; /* The sum of all the input bytes, modulo (UINT_MAX + 1). */ ++ ++ ++ for (int i = 0; i < size; i++) { ++ s += data[i]; ++ } ++ ++ r = (s & 0xffff) + ((s & 0xffffffff) >> 16); ++ checksum = (r & 0xffff) + (r >> 16); ++ ++ return checksum; ++} ++ ++static int zyxel_chksm(const unsigned char *data, int size) ++{ ++ return htonl(sysv_chksm(data, size)); ++} ++ ++char *generate_rootfs_header(struct file_info filesystem, char *version) ++{ ++ size_t version_string_length; ++ unsigned int chksm, size; ++ char *rootfs_header; ++ size_t ptr = 0; ++ ++ rootfs_header = malloc(ROOTFS_HEADER_LEN); ++ if (!rootfs_header) { ++ ERR("Couldn't allocate memory for rootfs header!"); ++ exit(EXIT_FAILURE); ++ } ++ ++ /* Prepare padding for firmware-version string here */ ++ memset(rootfs_header, 0xff, ROOTFS_HEADER_LEN); ++ ++ chksm = zyxel_chksm((const unsigned char *)filesystem.data, filesystem.size); ++ size = htonl(filesystem.size); ++ ++ /* 4 bytes: checksum of the rootfs image */ ++ memcpy(rootfs_header + ptr, &chksm, 4); ++ ptr += 4; ++ ++ /* 4 bytes: length of the contained rootfs image file (big endian) */ ++ memcpy(rootfs_header + ptr, &size, 4); ++ ptr += 4; ++ ++ /* 32 bytes: Firmware Version string (NUL terminated, 0xff padded) */ ++ version_string_length = strlen(version) <= VERSION_STRING_LEN ? strlen(version) : VERSION_STRING_LEN; ++ memcpy(rootfs_header + ptr, version, version_string_length); ++ ptr += version_string_length; ++ /* Add null-terminator */ ++ rootfs_header[ptr] = 0x0; ++ ++ return rootfs_header; ++} ++ ++char *generate_kernel_header(struct file_info kernel) ++{ ++ unsigned int chksm, size; ++ char *kernel_header; ++ size_t ptr = 0; ++ ++ kernel_header = malloc(KERNEL_HEADER_LEN); ++ if (!kernel_header) { ++ ERR("Couldn't allocate memory for kernel header!"); ++ exit(EXIT_FAILURE); ++ } ++ ++ chksm = zyxel_chksm((const unsigned char *)kernel.data, kernel.size); ++ size = htonl(kernel.size); ++ ++ /* 4 bytes: checksum of the kernel image */ ++ memcpy(kernel_header + ptr, &chksm, 4); ++ ptr += 4; ++ ++ /* 4 bytes: length of the contained kernel image file (big endian) */ ++ memcpy(kernel_header + ptr, &size, 4); ++ ++ return kernel_header; ++} ++ ++unsigned int generate_board_header_checksum(char *kernel_hdr, char *rootfs_hdr, char *boardname) ++{ ++ char *board_hdr_tmp; ++ unsigned int sum; ++ size_t ptr = 0; ++ ++ /* ++ * The checksum of the board header is calculated over the first 2048 bytes of ++ * the header partition with the rootfs checksum used as a placeholder for then ++ * board checksum we calculate in this step. The checksum gained from this step ++ * is then used for the final board header partition. ++ */ ++ ++ board_hdr_tmp = malloc(HEADER_PARTITION_CALC_LENGTH); ++ if (!board_hdr_tmp) { ++ ERR("Couldn't allocate memory for temporary board header!"); ++ exit(EXIT_FAILURE); ++ } ++ memset(board_hdr_tmp, 0xff, HEADER_PARTITION_CALC_LENGTH); ++ ++ /* 40 bytes: RootFS header */ ++ memcpy(board_hdr_tmp, rootfs_hdr, ROOTFS_HEADER_LEN); ++ ptr += ROOTFS_HEADER_LEN; ++ ++ /* 4 bytes: RootFS checksum (BE) as placeholder for board-header checksum */ ++ memcpy(board_hdr_tmp + ptr, rootfs_hdr, 4); ++ ptr += 4; ++ ++ /* 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) */ ++ memcpy(board_hdr_tmp + ptr, boardname, strlen(boardname)); ++ ptr += strlen(boardname); ++ /* Add null-terminator */ ++ board_hdr_tmp[ptr] = 0x0; ++ ptr = ROOTFS_HEADER_LEN + 4 + BOARD_NAME_LEN; ++ ++ /* 8 bytes: Kernel header */ ++ if (kernel_hdr) ++ memcpy(board_hdr_tmp + ptr, kernel_hdr, 8); ++ ++ /* Calculate the checksum over the first 2048 bytes */ ++ sum = zyxel_chksm((const unsigned char *)board_hdr_tmp, HEADER_PARTITION_CALC_LENGTH); ++ free(board_hdr_tmp); ++ return sum; ++} ++ ++char *generate_board_header(char *kernel_hdr, char *rootfs_hdr, char *boardname) ++{ ++ unsigned int board_checksum; ++ char *board_hdr; ++ ++ board_hdr = malloc(BOARD_HEADER_LEN); ++ if (!board_hdr) { ++ ERR("Couldn't allocate memory for board header!"); ++ exit(EXIT_FAILURE); ++ } ++ memset(board_hdr, 0xff, BOARD_HEADER_LEN); ++ ++ /* 4 bytes: checksum over the header partition (big endian) */ ++ board_checksum = generate_board_header_checksum(kernel_hdr, rootfs_hdr, boardname); ++ memcpy(board_hdr, &board_checksum, 4); ++ ++ /* 32 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) */ ++ memcpy(board_hdr + 4, boardname, strlen(boardname)); ++ board_hdr[4 + strlen(boardname)] = 0x0; ++ ++ return board_hdr; ++} ++ ++int build_image() ++{ ++ char *rootfs_header = NULL; ++ char *kernel_header = NULL; ++ char *board_header = NULL; ++ ++ size_t ptr; ++ ++ /* Load files */ ++ if (kernel.name) ++ map_file(&kernel); ++ map_file(&rootfs); ++ ++ /* ++ * Allocate memory and copy input rootfs for temporary output rootfs. ++ * This is important as we have to generate the rootfs checksum over the ++ * entire rootfs partition. As we might have to pad the partition to allow ++ * for flashing via ZyXEL's Web-GUI, we prepare the rootfs partition for the ++ * output image here (and also use it for calculating the rootfs checksum). ++ * ++ * The roofs padding has to be done with 0x00. ++ */ ++ rootfs_out.data = calloc(rootfs_out.size, sizeof(char)); ++ memcpy(rootfs_out.data, rootfs.data, rootfs.size); ++ ++ /* Prepare headers */ ++ rootfs_header = generate_rootfs_header(rootfs_out, version_name); ++ if (kernel.name) ++ kernel_header = generate_kernel_header(kernel); ++ board_header = generate_board_header(kernel_header, rootfs_header, board_name); ++ ++ /* Prepare output file */ ++ out.size = HEADER_PARTITION_LENGTH + rootfs_out.size; ++ if (kernel.name) ++ out.size += kernel.size; ++ out.data = malloc(out.size); ++ memset(out.data, 0xFF, out.size); ++ ++ /* Build output image */ ++ memcpy(out.data, rootfs_header, ROOTFS_HEADER_LEN); ++ memcpy(out.data + ROOTFS_HEADER_LEN, board_header, BOARD_HEADER_LEN); ++ if (kernel.name) ++ memcpy(out.data + ROOTFS_HEADER_LEN + BOARD_HEADER_LEN, kernel_header, KERNEL_HEADER_LEN); ++ ptr = HEADER_PARTITION_LENGTH; ++ memcpy(out.data + ptr, rootfs_out.data, rootfs_out.size); ++ ptr += rootfs_out.size; ++ if (kernel.name) ++ memcpy(out.data + ptr, kernel.data, kernel.size); ++ ++ /* Write back output image */ ++ write_file(&out); ++ ++ /* Free allocated memory */ ++ if (kernel.name) ++ unmap_file(&kernel); ++ unmap_file(&rootfs); ++ free(out.data); ++ free(rootfs_out.data); ++ ++ free(rootfs_header); ++ if (kernel.name) ++ free(kernel_header); ++ free(board_header); ++ ++ return 0; ++} ++ ++int check_options() ++{ ++ if (!rootfs.name) { ++ ERR("No rootfs filename supplied"); ++ return -2; ++ } ++ ++ if (!out.name) { ++ ERR("No output filename supplied"); ++ return -3; ++ } ++ ++ if (!board_name) { ++ ERR("No board-name supplied"); ++ return -4; ++ } ++ ++ if (!version_name) { ++ ERR("No version supplied"); ++ return -5; ++ } ++ ++ if (rootfs_size <= 0) { ++ ERR("Invalid rootfs size supplied"); ++ return -6; ++ } ++ ++ if (strlen(board_name) > 31) { ++ ERR("Board name is to long"); ++ return -7; ++ } ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int ret; ++ progname = basename(argv[0]); ++ while (1) { ++ int c; ++ ++ c = getopt(argc, argv, "b:k:o:r:s:v:h"); ++ if (c == -1) ++ break; ++ ++ switch (c) { ++ case 'b': ++ board_name = optarg; ++ break; ++ case 'h': ++ usage(EXIT_SUCCESS); ++ break; ++ case 'k': ++ kernel.name = optarg; ++ break; ++ case 'o': ++ out.name = optarg; ++ break; ++ case 'r': ++ rootfs.name = optarg; ++ break; ++ case 's': ++ sscanf(optarg, "%u", &rootfs_size); ++ break; ++ case 'v': ++ version_name = optarg; ++ break; ++ default: ++ usage(EXIT_FAILURE); ++ break; ++ } ++ } ++ ++ ret = check_options(); ++ if (ret) ++ usage(EXIT_FAILURE); ++ ++ /* As ZyXEL Web-GUI only accept images with a rootfs equal or larger than the first firmware shipped ++ * for the device, we need to pad rootfs partition to this size. To perform further calculations, we ++ * decide the size of this part here. In case the rootfs we want to integrate in our image is larger, ++ * take it's size, otherwise the supplied size. ++ * ++ * Be careful! We rely on assertion of correct size to be performed beforehand. It is unknown if images ++ * with a to large rootfs are accepted or not. ++ */ ++ rootfs_out.size = rootfs_size < rootfs.size ? rootfs.size : rootfs_size; ++ return build_image(); ++} diff --git a/patches/openwrt/0011-ipq40xx-fix-NBG6617-LED-mapping.patch b/patches/openwrt/0011-ipq40xx-fix-NBG6617-LED-mapping.patch new file mode 100644 index 00000000..b3fff8d2 --- /dev/null +++ b/patches/openwrt/0011-ipq40xx-fix-NBG6617-LED-mapping.patch @@ -0,0 +1,27 @@ +From: David Bauer +Date: Sun, 4 Nov 2018 01:00:18 +0100 +Subject: ipq40xx: fix NBG6617 LED mapping + +The NBG6617's LEDs are wrongly identified in the 01_leds boardinit +script (board instead of boardname), thus referencing non-existant LEDs +in UCI. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +index 475a8623f705d683a7ee3521ee71f2b57fa2e44d..ab2f77ee10a8e4371d8c52d6d6b6a35bae8aceb6 100755 +--- a/target/linux/ipq40xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds +@@ -35,9 +35,9 @@ meraki,mr33) + ucidef_set_interface_lan "eth0" + ;; + zyxel,nbg6617) +- ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:green:wlan2G" "phy0tpt" +- ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5G" "phy1tpt" +- ucidef_set_led_usbport "usb" "USB" "${board}:green:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:green:wlan2G" "phy0tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:green:wlan5G" "phy1tpt" ++ ucidef_set_led_usbport "usb" "USB" "${boardname}:green:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" + ;; + zyxel,wre6606) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:green:wlan2g" "phy0tpt" diff --git a/targets/ipq40xx b/targets/ipq40xx index 1ab2530d..23e29a08 100644 --- a/targets/ipq40xx +++ b/targets/ipq40xx @@ -43,6 +43,9 @@ packages $ATH10K_PACKAGES_IPQ40XX $ATH10K_PACKAGES_QCA9888 # ZyXEL +device zyxel-nbg6617 zyxel_nbg6617 +packages $ATH10K_PACKAGES_IPQ40XX + device zyxel-wre6606 zyxel_wre6606 factory packages $ATH10K_PACKAGES_IPQ40XX