From 21b307a2f63c6f26dc77505854f3b0837e9e57f7 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 15 Aug 2023 16:11:13 +0200 Subject: [PATCH] Some part of 6.1 RUTX support --- .../linux/ipq40xx/base-files/bin/board_modem | 39 + .../ipq40xx/base-files/bin/config_generate | 321 ++- .../base-files/etc/board.d/1-board_json | 399 +++- .../ipq40xx/base-files/lib/functions/board.sh | 14 + .../lib/functions/teltonika-defaults.sh | 275 +-- .../lib/functions/teltonika-functions.sh | 64 +- .../base-files/lib/functions/uci-defaults.sh | 122 +- .../base-files/lib/preinit/82_modem_power | 9 +- .../ipq40xx/base-files/lib/upgrade/stage2 | 29 +- 6.1/target/linux/ipq40xx/image/generic.mk | 22 +- .../uboot_fw/appsboardconfig_premium_tlt | 80 + .../image/uboot_fw/boardconfig_premium_tlt | 79 + .../uboot_fw/norplusnand-apps-flash.conf | 17 + .../image/uboot_fw/norplusnand-flash.conf | 53 + .../norplusnand-system-partition-ipq40xx.bin | Bin 0 -> 65536 bytes .../linux/ipq40xx/image/uboot_fw/pack.py | 1908 +++++++++++++++++ 16 files changed, 3061 insertions(+), 370 deletions(-) create mode 100755 6.1/target/linux/ipq40xx/image/uboot_fw/appsboardconfig_premium_tlt create mode 100755 6.1/target/linux/ipq40xx/image/uboot_fw/boardconfig_premium_tlt create mode 100644 6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-apps-flash.conf create mode 100644 6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-flash.conf create mode 100755 6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-system-partition-ipq40xx.bin create mode 100755 6.1/target/linux/ipq40xx/image/uboot_fw/pack.py diff --git a/6.1/target/linux/ipq40xx/base-files/bin/board_modem b/6.1/target/linux/ipq40xx/base-files/bin/board_modem index 7628fc86..6481c682 100755 --- a/6.1/target/linux/ipq40xx/base-files/bin/board_modem +++ b/6.1/target/linux/ipq40xx/base-files/bin/board_modem @@ -20,6 +20,18 @@ strstr() { print_array() { json_add_array $1 case "$1" in + 5G_NSA) + for element in $2 + do + json_add_string "" "$(echo $element)" + done + ;; + 5G_SA) + for element in $2 + do + json_add_string "" "$(echo $element)" + done + ;; 4G) for element in $2 do @@ -210,6 +222,28 @@ gather_band_capabilities() { lte_bands="" trysg_bands="850 1900" dug_bands="" + ###################### EC200A ######################### + elif strstr $revision_from_unhandler "EC200AAU"; then #EC200AAU + lte_bands="1 2 3 4 5 7 8 28 40 66" + trysg_bands="850 900 1700 1900 2100" + dug_bands="850 900 1800 1900" + elif strstr $revision_from_unhandler "EC200AEU"; then #EC200AEU + lte_bands="1 3 5 7 8 20 28 38 40 41" + trysg_bands="850 900 2100" + dug_bands="900 1800" + ####################### RG501QEU ####################### + elif strstr $revision_from_unhandler "RG501QEU"; then #5G module + nsa_nr5g_bands="1 3 5 7 8 20 28 38 40 41 77 78" + sa_nr5g_bands="1 3 5 7 8 20 28 38 40 41 77 78" + lte_bands="1 3 5 7 8 20 28 32 38 40 41 42 43" + trysg_bands="2100 850 900" + dug_bands="" + elif strstr $revision_from_unhandler "RG520NEU"; then #5G module + nsa_nr5g_bands="1 3 5 7 8 20 28 38 40 41 75 76 77 78" + sa_nr5g_bands="1 3 5 7 8 20 28 38 40 41 75 76 77 78" + lte_bands="1 3 5 7 8 20 28 32 38 40 41 42 43" + trysg_bands="2100 850 900" + dug_bands="" else lte_bands="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 26 27 28" trysg_bands="700 800 850 900 1500 1700 2600" @@ -249,6 +283,8 @@ setup_modem() { validate_service_modes && { gather_band_capabilities json_select_object service_modes + [ -z "$nsa_nr5g_bands" ] || print_array "5G_NSA" "$nsa_nr5g_bands" + [ -z "$sa_nr5g_bands" ] || print_array "5G_SA" "$sa_nr5g_bands" [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" @@ -280,7 +316,10 @@ setup_modem() { json_add_string type "$type" json_add_string desc "$desc" json_add_string control "$control" + json_add_string revision "${revision_from_unhandler::-2}" json_add_object service_modes + [ -z "$nsa_nr5g_bands" ] || print_array "5G_NSA" "$nsa_nr5g_bands" + [ -z "$sa_nr5g_bands" ] || print_array "5G_SA" "$sa_nr5g_bands" [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" diff --git a/6.1/target/linux/ipq40xx/base-files/bin/config_generate b/6.1/target/linux/ipq40xx/base-files/bin/config_generate index b2542b14..c205a7fd 100755 --- a/6.1/target/linux/ipq40xx/base-files/bin/config_generate +++ b/6.1/target/linux/ipq40xx/base-files/bin/config_generate @@ -10,24 +10,33 @@ CFG=/etc/board.json [ -s /etc/config/system ] && \ [ -s /etc/config/hwinfo ] && \ [ -s /etc/config/blesem ] && \ +[ -s /etc/config/poe ] && \ exit 0 +generate_bridge() { + local name=$1 + local macaddr=$2 + uci -q batch <<-EOF + set network.$name=device + set network.$name.name=$name + set network.$name.type=bridge + EOF + if [ -n "$macaddr" ]; then + uci -q batch <<-EOF + set network.$name.macaddr=$macaddr + EOF + fi +} + generate_static_network() { uci -q batch <<-EOF delete network.loopback set network.loopback='interface' - set network.loopback.ifname='lo' + set network.loopback.device='lo' set network.loopback.proto='static' set network.loopback.ipaddr='127.0.0.1' set network.loopback.netmask='255.0.0.0' EOF - [ -e /proc/sys/net/ipv6 ] && { - uci -q batch <<-EOF - delete network.globals - set network.globals='globals' - set network.globals.ula_prefix='auto' - EOF - } if json_is_a dsl object; then json_select dsl @@ -65,9 +74,30 @@ generate_static_network() { fi } +ip6assign= +disable_vlan= +apply_network_options() { + json_select network_options && { + json_get_vars ip6assign ula disable_vlan + json_select .. + } + [ -z "$ip6assign" ] && ip6assign=1 + [ -z "$ula" ] && ula=1 + + [ -e /proc/sys/net/ipv6 ] && [ "$ula" = 1 ] && { + uci -q batch <<-EOF + delete network.globals + set network.globals='globals' + set network.globals.ula_prefix='auto' + EOF + } +} + +metric=1 addr_offset=2 generate_network() { - local keys var val ifname macaddr proto type ipaddr netmask + local ports device macaddr proto type ipaddr netmask vlan no_metric + local bridge=$2 uci -q batch <<-EOF delete "network.$1" @@ -76,46 +106,88 @@ generate_network() { json_select network json_select "$1" - json_get_keys keys - for var in $keys; do - json_get_var val "$var" - [ "${var#_*}" = "$var" ] && { - eval "$var=\"\$val\"" - uci -q set "network.$1.$var=$val" - } - done + json_get_vars device macaddr proto ipaddr netmask vlan ipv6 guest type + json_get_values ports ports json_select .. json_select .. - #~ [ -n "$ifname" ] || return - # force bridge for multi-interface devices (and lan) - case "$1:$ifname" in - *\ * | lan:*) - type="bridge" - uci -q set "network.$1.type=$type" - ;; - esac + json_select network_options && { + json_get_vars no_metric + json_select .. + } + + # Force bridge for "lan" as it may have other devices (e.g. wireless) + # bridged + [ "$1" = "lan" ] && [ -z "$ports" ] && { + ports="$device" + } + + [ -n "$ports" ] && [ -z "$bridge" ] && { + + [ -n "$macaddr" ] && { + for port in $ports; do + uci -q batch <<-EOF + add network device + set network.@device[-1].name='$port' + set network.@device[-1].macaddr='$macaddr' + EOF + done + } + + uci -q batch <<-EOF + add network device + rename network.@device[-1]='br_$1' + set network.@device[-1].name='br-$1' + set network.@device[-1].type='bridge' + EOF + + [ -n "$device" ] && uci add_list network.@device[-1].ports="$device" || { + for port in $ports; do + uci add_list network.@device[-1].ports="$port" + done + } + + device=br-$1 + type= + macaddr="" + + json_select hwinfo + json_get_vars dsa + json_select .. + + } if [ -n "$macaddr" ]; then - for name in $ifname; do - uci -q batch <<-EOF - delete network.$1_${name/./_}_dev - set network.$1_${name/./_}_dev='device' - set network.$1_${name/./_}_dev.name='$name' - set network.$1_${name/./_}_dev.macaddr='$macaddr' - EOF - done + uci -q batch <<-EOF + add network device + set network.@device[-1].name='$device' + set network.@device[-1].macaddr='$macaddr' + EOF fi + uci -q batch <<-EOF + delete network.$1 + set network.$1='interface' + set network.$1.type='$type' + set network.$1.device='$device' + set network.$1.proto='none' + EOF + [ "$1" != "lan" ] && metric=$((metric+1)) + [ "$guest" = "1" ] && uci set network.$1.guest='1' + case "$proto" in static) - local ipad + local ipad metr case "$1" in lan) - ipad=${ipaddr:-"192.168.100.1"} + ipad="192.168.100.1" + metr=1 + ;; + *) + ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} + metr="$metric" ;; - *) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;; esac netm=${netmask:-"255.255.255.0"} @@ -124,26 +196,33 @@ generate_network() { set network.$1.proto='static' set network.$1.ipaddr='$ipad' set network.$1.netmask='$netm' + set network.$1.metric='$metr' EOF - [ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60' + + [ "$ipv6" = "1" ] && uci set network.$1.ipv6="$ipv6" + [ -e /proc/sys/net/ipv6 ] && [ "$ip6assign" = 1 ] && \ + uci set network.$1.ip6assign='60' ;; dhcp) # fixup IPv6 slave interface if parent is a bridge - [ "$type" = "bridge" ] && ifname="br-$1" + [ "$type" = "bridge" ] && device="br-$1" - uci set network.$1.proto='dhcp' - uci set network.$1.metric='1' - - #[ -e /proc/sys/net/ipv6 ] && { - # uci -q batch <<-EOF - # delete network.${1}6 - # set network.${1}6='interface' - # set network.${1}6.device='$ifname' - # set network.${1}6.proto='dhcpv6' - # set network.${1}6.metric='1' - # EOF - #} + uci -q batch <<-EOF + set network.$1.proto='dhcp' + set network.$1.metric='$metric' + EOF + [ -e /proc/sys/net/ipv6 ] && { + metric=$((metric+1)) + uci -q batch <<-EOF + delete network.${1}6 + set network.${1}6='interface' + set network.${1}6.device='$device' + set network.${1}6.proto='dhcpv6' + set network.${1}6.metric='$metric' + EOF + [ "$ip6assign" != 1 ] && uci set network.${1}6.delegate='0' + } ;; pppoe) @@ -157,12 +236,17 @@ generate_network() { set network.$1.ipv6='1' delete network.${1}6 set network.${1}6='interface' - set network.${1}6.ifname='@${1}' + set network.${1}6.device='@${1}' set network.${1}6.proto='dhcpv6' EOF } ;; esac + + [ -n "$no_metric" ] && { + uci -q delete network.${1}.metric + [ -e /proc/sys/net/ipv6 ] && uci -q delete network.${1}6.metric + } } add_modem_section() { @@ -170,35 +254,40 @@ add_modem_section() { local num="$2" local simcount="$3" local builtin="$4" + local custom_proto custom_ifname + json_select .. + json_get_vars custom_proto custom_ifname + json_select modems for count in $(seq "$simcount"); do interface="mob${num}s${count}a1" local proto="wwan" - # just like this for now - # probably we should merge connm with wwan - [ -e /dev/smd9 ] && { - proto="connm" - } + # if needed, use custom proto for rmnet/other devices + [ -n "${custom_proto}" ] && proto="${custom_proto}" - uci -q batch <<-EOF - delete network.$interface - set network.$interface='interface' - set network.$interface.proto='$proto' - set network.$interface.modem='$id' - set network.$interface.metric='$((num+1))' - set network.$interface.sim='${count}' - set network.$interface.pdp='1' - EOF + metric=$((metric+1)) - # just like this for now - # probably we should merge connm with wwan - [ -e /dev/smd9 ] && { - uci set network.$interface.ifname='rmnet0' - } + uci_remove network "${interface}" + uci_add network interface "${interface}" + uci_set network "${interface}" proto "$proto" + uci_set network "${interface}" modem "$id" + uci_set network "${interface}" metric "$metric" + uci_set network "${interface}" sim "${count}" + uci_set network "${interface}" dhcpv6 "0" + uci_set network "${interface}" pdptype "ip" + uci_set network "${interface}" method "nat" + uci_set network "${interface}" auth "none" + uci_set network "${interface}" auto_apn "1" + + # if needed, use custom ifname for rmnet/other devices + [ -n "${custom_ifname}" ] && \ + uci_set network "${interface}" device "${custom_ifname}" + + uci_commit network update_firewall_zone "wan" "$interface" - create_multiwan_iface "$interface" "$num" + create_multiwan_iface "$interface" "$metric" add_simcard_config "$id" "${count}" "${count}" "$builtin" add_sim_switch_config "$id" "${count}" add_quota_limit_config "$interface" @@ -243,6 +332,7 @@ generate_dynamic_lte() { product=$(cat "/sys/bus/usb/devices/$a/idProduct") [ -f "/lib/network/wwan/${vendor}:${product}" ] && { add_simcard_config "$a" "1" "0" "" + add_sms_storage_config "$a" } done } @@ -268,6 +358,7 @@ generate_switch_vlans_ports() { add network switch_vlan set network.@switch_vlan[-1].device='$switch' set network.@switch_vlan[-1].vlan='$role' + set network.@switch_vlan[-1].vid='$role' set network.@switch_vlan[-1].ports='$ports' EOF done @@ -319,6 +410,7 @@ generate_switch() { json_get_vars enable reset blinkrate cpu_port \ ar8xxx_mib_type ar8xxx_mib_poll_interval + [ "$disable_vlan" = 1 ] && enable=0 uci -q batch <<-EOF add network switch set network.@switch[-1].name='$key' @@ -342,14 +434,16 @@ generate_static_system() { uci -q batch <<-EOF delete system.@system[0] set system.system='system' - set system.@system[-1].hostname='OpenMPTCProuter' + set system.@system[-1].hostname='$hostname' set system.@system[-1].timezone='UTC' set system.@system[-1].ttylogin='0' - set system.@system[-1].log_size='128' + set system.@system[-1].log_buffer_size='128' + set system.@system[-1].log_size='200' set system.@system[-1].urandom_seed='0' delete system.ntp set system.ntp='timeserver' + set system.ntp.zoneName='UTC' set system.ntp.enabled='0' set system.ntp.enable_server='0' add_list system.ntp.server='0.pool.ntp.org' @@ -365,9 +459,9 @@ generate_static_system() { if json_is_a system object; then json_select system local hostname - #if json_get_var hostname hostname; then - # uci -q set "system.@system[-1].hostname=$hostname" - #fi + if json_get_var hostname hostname; then + uci -q set "system.@system[-1].hostname=$hostname" + fi if json_is_a ntpserver array; then local keys key @@ -542,6 +636,66 @@ generate_hwinfo() { EOF } +set_poe_ports() { + json_select "$1" + json_get_vars name class budget + uci -q batch <<-EOF + set poe.port$1='port$1' + set poe.port$1.name='$name' + set poe.port$1.poe_enable='1' + set poe.port$1.class='$class' + set poe.port$1.budget='$budget' + EOF + json_select .. +} + +set_poe_chips(){ + local keys key + uci -q set poe.chip$1=chip$1 + json_get_keys keys "$1" + json_select "$1" + for key in $keys; do + json_get_var var "$key" + uci -q set poe.chip$1.$key="$var" + done + json_select .. +} + +generate_poe_config(){ + if json_is_a poe object; then + json_select poe + json_get_vars chip_count budget poe_ports + uci -q batch <<-EOF + set poe.poe='poe' + set poe.poe.chip_count='$chip_count' + set poe.poe.budget='$budget' + set poe.poe.poe_ports='$poe_ports' + EOF + if json_is_a ports array; then + #json_for_each_item "set_poe_ports" ports + json_select ports + idx=1 + while json_is_a ${idx} object + do + "set_poe_ports" $idx + idx=$(( idx + 1 )) + done + json_select .. + fi + if json_is_a poe_chips array; then + json_select poe_chips + idx=1 + while json_is_a ${idx} object + do + "set_poe_chips" $idx + idx=$(( idx + 1 )) + done + json_select .. + fi + json_select .. + fi +} + generate_bluetooth() { uci -q batch <<-EOF set blesem.general='section' @@ -552,15 +706,15 @@ generate_bluetooth() { } add_firewall_zone() { - local ifname + local device json_select network json_select "$1" - json_get_vars ifname + json_get_vars device json_select .. json_select .. - fw3 -q network "$1" || fw3 -q device "$ifname" && return + fw3 -q network "$1" || fw3 -q device "$device" && return uci -q batch <<-EOF add firewall zone @@ -599,7 +753,7 @@ add_dhcp() { json_select .. json_select .. - [ "$_dhcp" = "1" ] || return + [ "$_dhcp" = "true" ] || return uci -q batch <<-EOF set dhcp.$1='dhcp' set dhcp.$1.interface='$1' @@ -617,11 +771,11 @@ umask 077 if [ ! -s /etc/config/network ]; then touch /etc/config/network generate_static_network + apply_network_options json_get_keys keys network for key in $keys; do generate_network $key - add_firewall_zone "$key" add_dhcp "$key" done @@ -651,6 +805,11 @@ if [ ! -s /etc/config/hwinfo ]; then for key in $keys; do generate_hwinfo $key; done fi +if [ ! -s /etc/config/poe ]; then + touch /etc/config/poe + generate_poe_config +fi + if [ ! -s /etc/config/blesem ]; then bluetooth="" json_select hwinfo diff --git a/6.1/target/linux/ipq40xx/base-files/etc/board.d/1-board_json b/6.1/target/linux/ipq40xx/base-files/etc/board.d/1-board_json index c9c258b2..8ce32f61 100755 --- a/6.1/target/linux/ipq40xx/base-files/etc/board.d/1-board_json +++ b/6.1/target/linux/ipq40xx/base-files/etc/board.d/1-board_json @@ -8,6 +8,9 @@ . /lib/functions/teltonika-defaults.sh . /lib/functions/system.sh +[ -f /lib/functions/target-defaults.sh ] && \ + . /lib/functions/target-defaults.sh + setup_json() { local model="$1" @@ -16,96 +19,155 @@ setup_json() { ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" + ucidef_set_usb_jack "/usb1/1-1/" ucidef_set_hwinfo usb ethernet ios + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX09*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out" + ucidef_add_static_modem_info "$model" "3-1" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb1/1-1/" ucidef_set_hwinfo dual_sim usb gps mobile ethernet ios + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX10*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" + ucidef_set_usb_jack "/usb1/1-1/" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 ucidef_set_hwinfo bluetooth usb wifi dual_band_ssid ethernet ios + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX11*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 + ucidef_add_static_modem_info "$model" "3-1" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb1/1-1/" ucidef_set_hwinfo dual_sim usb gps mobile wifi dual_band_ssid bluetooth ethernet ios + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTXR1*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "3-1" "2" - ucidef_set_hwinfo dual_sim usb mobile wifi dual_band_ssid ethernet sfp_port + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 + ucidef_add_static_modem_info "$model" "3-1" "2" "primary" + ucidef_set_hwinfo dual_sim usb mobile wifi dual_band_ssid ethernet sfp_port sfp_switch console rs232 + ucidef_set_usb_jack "/usb1/1-1/1-1.2/" + ucidef_add_serial_capabilities "rs232" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200" \ + "7 8" \ + "rts/cts xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/usb1/1-1/1-1.3/" ucidef_set_release_version "2.3.1" + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX12*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 # builtin and primary should be first modem ucidef_add_static_modem_info "$model" "3-1" "1" "primary" "gps_out" ucidef_add_static_modem_info "$model" "1-1.2" "1" - ucidef_set_hwinfo usb gps mobile wifi dual_band_ssid bluetooth ethernet ios + ucidef_set_usb_jack "/usb1/1-1/1-1.3/" + ucidef_set_hwinfo usb gps mobile wifi dual_band_ssid bluetooth ethernet ios dual_modem ucidef_set_release_version "2.3.1" + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX14*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "1-1" "2" "gps_out" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 + ucidef_add_static_modem_info "$model" "1-1" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb3/3-1/" ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios at_sim ucidef_set_release_version "2.6.1" + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX18*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "2-1" "2" "gps_out" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 + ucidef_add_static_modem_info "$model" "2-1" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb1/1-1/" ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; RUTX50*) ucidef_set_interfaces_lan_wan "eth0" "eth1" ucidef_add_switch "switch0" \ "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" - ucidef_add_static_modem_info "$model" "2-1" "2" "gps_out" + ucidef_add_wlan_bssid_limit "wlan0" 16 + ucidef_add_wlan_bssid_limit "wlan1" 16 + ucidef_add_static_modem_info "$model" "2-1" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb3/3-1/" ucidef_set_hwinfo dual_sim usb gps mobile wifi dual_band_ssid ethernet ios at_sim + ucidef_set_release_version "7.2.8" + ucidef_set_network_options "vlans" 128 "readonly_vlans" 2 ;; TRB2*) ucidef_set_led_switch "lan" "LAN" "eth_led" "switch0" "0x04" ucidef_set_interface_lan "eth0" - ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out" - ucidef_add_serial_capabilities "rs232 rs485" \ - "300 600 1200 2400 4800 9600 14400 19200 38400 56000 57600 115200 \ + ucidef_add_static_modem_info "$model" "1-1.4" "2" "primary" "gps_out" + ucidef_add_serial_capabilities "rs232" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200" \ + "7 8" \ + "rts/cts xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/usb1/1-1/1-1.3/" + ucidef_add_serial_capabilities "rs485" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200 \ 230400 460800 921600 1000000 3000000" \ - "7 8" - ucidef_set_hwinfo dual_sim mobile gps ethernet ios + "7 8" \ + "none" \ + "1 2" \ + "even odd mark space none" \ + "/usb1/1-1/1-1.2/" + ucidef_set_hwinfo dual_sim mobile gps ethernet ios rs232 rs485 + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 ;; + RUT361* |\ RUT200* |\ - RUT241*) + RUT241* |\ + RUT260*) ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x2" ucidef_set_led_switch "wan" "WAN" "eth2_led" "switch0" "0x1" - ucidef_add_switch "switch0" "1:lan" "0:wan" "6@eth0" - ucidef_set_interface_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" - ucidef_set_interface_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" - ucidef_add_static_modem_info "$model" "1-1" "1" - [ "${model:7:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \ + ucidef_add_switch "switch0" "1:lan" "0:wan:2" "6@eth0" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" + ucidef_set_interface_default_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" + ucidef_add_static_modem_info "$model" "1-1" "1" "primary" + [ "${model:6:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \ ethernet || ucidef_set_hwinfo mobile wifi ethernet ios + [ "${model:4:2}" = "60" ] && ucidef_set_release_version "7.4.2" + ucidef_set_network_options "vlans" 16 "readonly_vlans" 2 ;; RUT2*) ucidef_set_led_switch "lan" "LAN" "lan_led" "switch0" "0x04" ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_static_modem_info "$model" "1-1" "1" + ucidef_add_wlan_bssid_limit "wlan0" 8 + ucidef_add_static_modem_info "$model" "1-1" "1" "primary" [ "${model:6:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \ ethernet || ucidef_set_hwinfo mobile wifi ethernet ios + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 ;; RUT300*) ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x02" @@ -114,16 +176,34 @@ setup_json() { ucidef_set_led_switch "lan4" "LAN4" "eth4_led" "switch0" "0x04" ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" ucidef_set_interface_wan "eth1" + ucidef_set_usb_jack "/usb1/1-1/" ucidef_add_switch "switch0" \ "0@eth0" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" ucidef_set_hwinfo usb ethernet ios + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 + ;; + RUT301*) + ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x01" + ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x02" + ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "eth4_led" "switch0" "0x08" + ucidef_set_led_switch "wan" "WAN" "wan_led" "switch0" "0x10" + ucidef_add_switch "switch0" "0:lan:1" "1:lan:2" "2:lan:3" \ + "3:lan:4" "4:wan" "6@eth0" + ucidef_set_usb_jack "/usb2/2-1/" + ucidef_set_interface_default_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" + ucidef_set_hwinfo usb ethernet ios + ucidef_set_network_options "vlans" 16 "readonly_vlans" 2 ;; RUT360*) ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10" ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1" ucidef_set_interfaces_lan_wan "eth0" "eth1" - ucidef_add_static_modem_info "$model" "1-1" "1" + ucidef_add_wlan_bssid_limit "wlan0" 8 + ucidef_add_wlan_bssid_limit "wlan1" 8 + ucidef_add_static_modem_info "$model" "1-1" "1" "primary" ucidef_set_hwinfo mobile wifi dual_band_ssid ethernet ios + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 ;; RUT950*) ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10" @@ -131,10 +211,12 @@ setup_json() { ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" ucidef_set_interface_wan "eth1" + ucidef_add_wlan_bssid_limit "wlan0" 8 ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" - ucidef_add_static_modem_info "$model" "1-1" "2" + ucidef_add_static_modem_info "$model" "1-1" "2" "primary" [ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim mobile \ wifi ethernet || ucidef_set_hwinfo dual_sim mobile wifi ethernet ios + ucidef_set_network_options "vlans" 15 "readonly_vlans" 1 ;; RUT955*) ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10" @@ -142,65 +224,284 @@ setup_json() { ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1" ucidef_set_interface_wan "eth1" + ucidef_add_wlan_bssid_limit "wlan0" 8 ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1" - ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out" - [ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim usb gps \ - mobile wifi ethernet || ucidef_set_hwinfo dual_sim usb gps \ - mobile wifi ethernet ios + ucidef_set_usb_jack "/usb1/1-1/1-1.1/" + ucidef_add_static_modem_info "$model" "1-1.4" "2" "primary" "gps_out" + [ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim usb gps sd_card \ + mobile wifi ethernet rs232 rs485 || ucidef_set_hwinfo dual_sim usb gps sd_card \ + mobile wifi ethernet ios rs232 rs485 ucidef_add_serial_capabilities "rs232" \ - "200 300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 \ - 230400 460800 500000 576000" \ - "5 6 7 8" + "300 600 1200 2400 4800 9600 19200 38400 57600 115200" \ + "5 6 7 8" \ + "rts/cts xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/usb1/1-1/1-1.3/" ucidef_add_serial_capabilities "rs485" \ - "300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 230400 \ - 460800 500000 576000 921600 1000000 1152000 1500000 2000000 \ - 2500000 3000000" \ - "8" + "300 600 1200 2400 4800 9600 19200 38400 57600 115200 \ + 230400 460800 921600 1000000 3000000" \ + "8" \ + "none" \ + "1 2" \ + "even odd none" \ + "/tty/ttyATH1" + ucidef_set_network_options "vlans" 15 "readonly_vlans" 1 + ;; + RUT901* |\ + RUT951*) + ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x01" + ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x02" + ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" + ucidef_set_led_switch "wan" "WAN" "wan_led" "switch0" "0x10" + ucidef_add_switch "switch0" "0:lan:1" "1:lan:2" "2:lan:3" "4:wan" "6@eth0" + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" + ucidef_set_interface_default_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_static_modem_info "$model" "1-1" "2" "primary" + [ "${model:7:1}" = "6" ] && ucidef_set_hwinfo dual_sim mobile \ + wifi ethernet || ucidef_set_hwinfo dual_sim mobile wifi ethernet ios + [ "${model:4:2}" = "01" ] && ucidef_set_release_version "7.3.1" + ucidef_set_network_options "vlans" 16 "readonly_vlans" 2 + ;; + RUT906* |\ + RUT956*) + ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x01" + ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x02" + ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04" + ucidef_set_led_switch "wan" "WAN" "wan_led" "switch0" "0x10" + ucidef_add_switch "switch0" "0:lan:1" "1:lan:2" "2:lan:3" "4:wan" "6@eth0" + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" + ucidef_set_usb_jack "/usb1/1-1/1-1.1/" + ucidef_set_interface_default_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_static_modem_info "$model" "1-1.4" "2" "primary" "gps_out" + [ "${model:7:1}" = "6" ] && ucidef_set_hwinfo dual_sim usb gps \ + mobile wifi ethernet rs232 rs485 || ucidef_set_hwinfo dual_sim usb gps \ + mobile wifi ethernet ios rs232 rs485 + [ "${model:4:2}" = "06" ] && ucidef_set_release_version "7.4.2" + ucidef_add_serial_capabilities "rs232" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200" \ + "5 6 7 8" \ + "rts/cts xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/usb1/1-1/1-1.3/" + ucidef_add_serial_capabilities "rs485" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200 230400" \ + "5 6 7 8" \ + "xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/tty/ttyS1" + ucidef_set_network_options "vlans" 16 "readonly_vlans" 2 ;; TRB140*) ucidef_set_interface_lan "eth0 rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile ethernet || \ ucidef_set_hwinfo mobile ethernet ios + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + [ "${model:6:1}" = "4" ] && \ + ucidef_set_release_version "7.4.2" + ;; + TRB143*) + ucidef_set_interface_lan "eth0 rndis0" + [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile ethernet || \ + ucidef_set_hwinfo mobile ethernet ios + ucidef_add_serial_capabilities "mbus" \ + "300 600 1200 2400 4800 9600 19200 38400" \ + "5 6 7 8" \ + "xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/tty/ttyHS0" + if [ "${model:6:1}" = "4" ]; then + ucidef_set_release_version "7.4.3" + else + ucidef_set_release_version "7.1.7" + fi + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 ;; TRB141*) ucidef_set_interface_lan "rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" ucidef_set_hwinfo mobile ios + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + [ "${model:6:1}" = "4" ] && \ + ucidef_set_release_version "7.4.3" + ;; + TRB142*) + ucidef_set_interface_lan "rndis0" + [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile rs232 || \ + ucidef_set_hwinfo mobile ios rs232 + ucidef_add_serial_capabilities "rs232" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200" \ + "5 6 7 8" \ + "rts/cts xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/tty/ttyHS0" + if [ "${model:6:1}" = "3" ]; then + ucidef_set_release_version "7.1" + elif [ "${model:6:1}" = "4" ]; then + ucidef_set_release_version "7.4.3" + fi + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 ;; - TRB142* |\ TRB145*) ucidef_set_interface_lan "rndis0" - ucidef_add_trb14x_lte_modem "$model" - ucidef_add_nand_info "$model" - [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile || \ - ucidef_set_hwinfo mobile ios - [ "${model:5:1}" = "2" ] && local rs="rs232" - ucidef_add_serial_capabilities "${rs:-rs485}" \ - "300 600 1200 2400 4800 9600 19200 38400 57600 115200 460800" \ - "5 6 7 8" - [ "${model:5:2}" = "23" -o "${model:5:2}" = "52" ] && \ + [ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile rs485 || \ + ucidef_set_hwinfo mobile ios rs485 + ucidef_add_serial_capabilities "rs485" \ + "300 600 1200 2400 4800 9600 19200 38400 57600 115200 \ + 230400 460800 921600 1000000 3000000" \ + "5 6 7 8" \ + "xon/xoff none" \ + "1 2" \ + "even odd mark space none" \ + "/tty/ttyHS0" + if [ "${model:6:1}" = "2" ]; then ucidef_set_release_version "7.1" + elif [ "${model:6:1}" = "4" ]; then + ucidef_set_release_version "7.4.3" + fi + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 ;; TCR100*) ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10" ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1" ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_wlan_bssid_limit "wlan0" 8 + ucidef_add_wlan_bssid_limit "wlan1" 8 ucidef_set_interface guest proto static type bridge \ guest 1 _wireless true _dhcp true - ucidef_add_static_modem_info "$model" "1-1" "1" + ucidef_add_static_modem_info "$model" "1-1" "1" "primary" ucidef_set_hwinfo mobile wifi dual_band_ssid wps ethernet + ucidef_set_release_version "7.2.4" + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 + ;; + OTD140*) + ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10" + ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x2" + ucidef_add_switch "switch0" "4:lan:1" "1:lan:2" "6@eth0" + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" + ucidef_set_interface "lan" "default_ip" "%%LAN_IP%%" + ucidef_add_static_modem_info "$model" "1-1" "2" "primary" + ucidef_set_hwinfo ethernet mobile dual_sim poe + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 + ucidef_set_poe 2 15400 1 "lan2" "3" 15400 + ucidef_set_poe_chip "0X77" "0:lan2" + ucidef_set_poe_chip "0X2F" "1:lan2" + ;; + OTD160*) + ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x04" + ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x02" + ucidef_set_interface_lan "eth0" + ucidef_add_wlan_bssid_limit "wlan0" 8 + ucidef_add_wlan_bssid_limit "wlan1" 8 + ucidef_add_static_modem_info "$model" "1-1" "2" "primary" + ucidef_set_hwinfo dual_sim mobile wifi dual_band_ssid ethernet + ucidef_set_network_options "vlans" 16 "readonly_vlans" 1 + ;; + TAP100*) + ucidef_set_led_switch "lan" "LAN" "eth0_led" "switch0" "0x10" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_set_interface_lan "eth0" + ucidef_set_interface "lan" "ipv6" "1" + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary config 0x0)" + ucidef_set_hwinfo wifi ethernet sw_rst_on_init + ucidef_set_network_options "ula" false "disable_vlan" true "ip6assign" false "vlans" 16 "readonly_vlans" 1 "no_metric" true + ucidef_set_interface "dhcp" "device" "@lan" "proto" "dhcp" + ;; + TRB500*) + ucidef_set_interface_lan "eth0 ecm0" + ucidef_set_interface_default_macaddr "lan" "$(mtd_get_mac_binary mnf_info 0x0)" \ + "$(macaddr_add "$(mtd_get_mac_binary mnf_info 0x0)" 1)" + ucidef_set_hwinfo mobile ethernet ios + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM50*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ucidef_set_usb_jack "/usb1/1-2/" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_add_static_modem_info "$model" "2-1" "2" "primary" "gps_out" + ucidef_set_hwinfo usb ethernet ios gps mobile wifi dual_band_ssid dual_sim at_sim dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM51*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ucidef_set_usb_jack "/usb1/1-2/" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_add_static_modem_info "$model" "2-1" "2" "primary" + ucidef_set_hwinfo usb ethernet ios mobile wifi dual_band_ssid dual_sim at_sim dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ucidef_set_release_version "7.4.4" + ;; + RUTM08*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ucidef_set_usb_jack "/usb1/1-1/" + ucidef_set_hwinfo usb ethernet ios dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM09*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ucidef_add_static_modem_info "$model" "1-2" "2" "primary" "gps_out" + ucidef_set_usb_jack "/usb1/1-1/" + ucidef_set_hwinfo usb ethernet ios gps mobile dual_sim dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM10*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ucidef_set_usb_jack "/usb1/1-1/" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_set_hwinfo usb ethernet ios wifi dual_band_ssid dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM11*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ucidef_set_usb_jack "/usb1/1-1/" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_add_static_modem_info "$model" "1-2" "2" "primary" "gps_out" + ucidef_set_hwinfo usb ethernet ios gps mobile wifi dual_band_ssid dual_sim dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + RUTM12*) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ucidef_set_usb_jack "/usb1/1-2/1-2.3/" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_add_static_modem_info "$model" "1-1" "1" "primary" "gps_out" + ucidef_add_static_modem_info "$model" "1-2.2" "1" + ucidef_set_hwinfo usb ethernet ios gps mobile wifi dual_band_ssid dual_modem dsa hw_nat + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 + ;; + + x86) + ucidef_set_interface_wan "eth0" + ucidef_set_interface_lan "eth1" + ucidef_add_wlan_bssid_limit "wlan0" 4 + ucidef_add_wlan_bssid_limit "wlan1" 4 + ucidef_set_hwinfo usb wifi dual_band_ssid ethernet + ucidef_set_network_options "vlans" 4094 "readonly_vlans" 1 ;; *) echo "Unsupported hardware. Network interfaces not intialized" ;; esac + + ucidef_set_interface "lan" "default_ip" "%%LAN_IP%%" + + type ucidef_target_defaults &> /dev/null && \ + ucidef_target_defaults "$model" } #~ Get model name for RUTX products -model="$(mnf_info --name)" 2>/dev/null +if ! model="$(mnf_info --name)" 2>/dev/null; then + model="$(mnf_info --prod-code)" 2>/dev/null +fi platform="$(cat /proc/device-tree/platform)" 2>/dev/null diff --git a/6.1/target/linux/ipq40xx/base-files/lib/functions/board.sh b/6.1/target/linux/ipq40xx/base-files/lib/functions/board.sh index 2f38cbdc..b6741c88 100644 --- a/6.1/target/linux/ipq40xx/base-files/lib/functions/board.sh +++ b/6.1/target/linux/ipq40xx/base-files/lib/functions/board.sh @@ -38,3 +38,17 @@ is_builtin_modem() { echo 0 } + +is_dual_modem() { + json_init + json_load_file "/etc/board.json" + + json_get_keys hwinfo hwinfo + json_select hwinfo + + json_get_vars dual_modem + + [ "$dual_modem" = "1" ] && echo 1 || echo 0 + + json_select .. +} diff --git a/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh b/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh index 5cb17a99..3435d033 100755 --- a/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh +++ b/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-defaults.sh @@ -3,41 +3,6 @@ . /lib/functions.sh . /usr/share/libubox/jshn.sh -ucidef_add_nand_info() { - local model="$1" - - model=${model:0:7} - - json_select_object nand - - case "$model" in - TRB1412) - json_add_int blocksize 128 - json_add_int pagesize 2048 - json_add_int subpagesize 2048 - ;; - TRB1422 |\ - TRB1423 |\ - TRB1452) - json_add_int blocksize 256 - json_add_int pagesize 4096 - json_add_int subpagesize 4096 - ;; - TRB14*0) - json_add_int blocksize 128 - json_add_int pagesize 2048 - json_add_int subpagesize 2048 - ;; - TRB14*1) - json_add_int blocksize 256 - json_add_int pagesize 4096 - json_add_int subpagesize 4096 - ;; - esac - - json_select .. -} - ucidef_add_static_modem_info() { #Parameters: model usb_id sim_count other_params local model usb_id count @@ -74,114 +39,6 @@ ucidef_add_static_modem_info() { json_select .. } -ucidef_add_trb14x_lte_modem() { - print_array() { - json_add_array $1 - for element in $2 - do - json_add_string "" "$(echo $element)" - done - json_close_array - } - #Parameters: model primary - local model vendor product boudrate gps type desc control region modem_counter - modem_counter=1 - json_select_array "modems" - - model="$1" - - model=${model:0:7} - - case "$model" in - TRB1422) - vendor=05c6 - product=9215 - ;; - TRB1412 |\ - TRB1423 |\ - TRB1452 |\ - TRB140*) - vendor=2c7c - product=0125 - ;; - TRB14*) - vendor=2c7c - product=0121 - ;; - esac - - case "$model" in - TRB1412 |\ - TRB14*0) - region="EU" - [ "$product" = "0121" ] && { - lte_bands="1 3 7 8 20 28" - trysg_bands="wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - } - [ "$product" = "0125" ] && { - lte_bands="1 3 7 8 20 28 38 40 41" - trysg_bands="wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - } - ;; - TRB1422) - region="CE" - lte_bands="1 3 5 8 34 38 39 40 41" - trysg_bands="bc-0-a-system bc-0-b-system wcdma_2100 wcdma_900" - dug_bands="gsm_1800 gsm_900" - ;; - TRB1423 |\ - TRB1452 |\ - TRB14*1) - region="AU" - [ "$product" = "0121" ] && { - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850" - dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900" - } - [ "$product" = "0125" ] && { - lte_bands="1 2 3 4 5 7 8 28 40" - trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850" - dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900" - } - ;; - esac - - [ -f "/lib/network/wwan/$vendor:$product" ] && { - devicename="3-1" - json_set_namespace defaults old_cb - json_load "$(cat /lib/network/wwan/$vendor:$product)" - json_get_vars gps boudrate type desc control stop_bits - json_set_namespace $old_cb - - [ "${devicename%%:*}" = "$devicename" ] && { - json_add_object - json_add_string id "$devicename" - json_add_string num "$modem_counter" - json_add_string vendor "$vendor" - json_add_string product "$product" - json_add_string stop_bits "$stop_bits" - json_add_string gps "$gps" - json_add_string boudrate "$boudrate" - json_add_string type "$type" - json_add_string desc "$desc" - json_add_string region "$region" - json_add_string control "$control" - json_add_int simcount 1 - json_add_boolean builtin 1 - [ -n "$2" ] && json_add_boolean primary 1 - json_add_object service_modes - [ -z "$lte_bands" ] || print_array "4G" "$lte_bands" - [ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands" - [ -z "$dug_bands" ] || print_array "2G" "$dug_bands" - json_close_object - json_close_object - } - } - json_select .. -} - ucidef_add_serial_capabilities() { json_select_array serial json_add_object @@ -204,81 +61,83 @@ ucidef_add_serial_capabilities() { json_add_string "" $n done json_select .. + + json_select_array flow_control + for n in $4; do + json_add_string "" $n + done + json_select .. + + json_select_array stop_bits + for n in $5; do + json_add_string "" $n + done + json_select .. + + json_select_array parity_types + for n in $6; do + json_add_string "" $n + done + json_select .. + + json_add_string "path" $7 + + json_close_object + json_select .. +} + +ucidef_add_wlan_bssid_limit() { + json_select_object wlan + json_add_object "$1" + json_add_int bssid_limit "$2" json_close_object json_select .. } ucidef_set_hwinfo() { - local function - local dual_sim=0 - local wifi=0 - local dual_band_ssid=0 - local wps=0 - local mobile=0 - local gps=0 - local usb=0 - local bluetooth=0 - local ethernet=0 - local sfp_port=0 - local ios=0 - - for function in "$@"; do - case "$function" in - dual_sim) - dual_sim=1 - ;; - wifi) - wifi=1 - ;; - dual_band_ssid) - dual_band_ssid=1 - ;; - wps) - wps=1 - ;; - mobile) - mobile=1 - ;; - gps) - gps=1 - ;; - usb) - usb=1 - ;; - bluetooth) - bluetooth=1 - ;; - ethernet) - ethernet=1 - ;; - sfp_port) - sfp_port=1 - ;; - ios) - ios=1 - ;; - at_sim) - at_sim=1 - ;; - esac - done + local args=" $* " + local options=' + dual_sim + at_sim + wifi + dual_band_ssid + wps + mobile + gps + usb + poe + bluetooth + ethernet + sfp_port + ios + sfp_switch + rs232 + rs485 + console + dual_modem + sd_card + sw_rst_on_init + dsa + hw_nat + ' json_select_object hwinfo - json_add_boolean dual_sim "$dual_sim" - json_add_boolean usb "$usb" - json_add_boolean bluetooth "$bluetooth" - json_add_boolean wifi "$wifi" - json_add_boolean dual_band_ssid "$dual_band_ssid" - json_add_boolean wps "$wps" - json_add_boolean mobile "$mobile" - json_add_boolean gps "$gps" - json_add_boolean ethernet "$ethernet" - json_add_boolean sfp_port "$sfp_port" - json_add_boolean ios "$ios" - json_add_boolean at_sim "$at_sim" + + for opt in $options; do + if [[ "$args" =~ " $(echo "$opt" | tr -d '\011\012\015\040') " ]]; then + json_add_boolean "$opt" 1 + else + json_add_boolean "$opt" 0 + fi + done + json_select .. } ucidef_set_release_version() { json_add_string release_version "$1" } + +ucidef_set_usb_jack() { + json_add_string "usb_jack" "$1" +} diff --git a/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh b/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh index 5381f81f..43eaf285 100755 --- a/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh +++ b/6.1/target/linux/ipq40xx/base-files/lib/functions/teltonika-functions.sh @@ -4,7 +4,65 @@ is_ios_enabled() { local ios - json_load_file "/etc/board.json" && \ - json_select hwinfo && \ - json_get_var ios ios && [ "$ios" = "1" ] + json_load_file "/etc/board.json" && + json_select hwinfo && + json_get_var ios ios && [ "$ios" = "1" ] +} + +# set_tty_options +set_tty_options() { + local PARITY_TMP="" + local SBITS_TMP="" + local FCTRL_TMP="" + + case "$4" in + "odd") PARITY_TMP="parenb parodd -cmspar" ;; + "even") PARITY_TMP="parenb -parodd -cmspar" ;; + "mark") PARITY_TMP="parenb parodd cmspar";; + "space") PARITY_TMP="parenb -parodd cmspar";; + *) PARITY_TMP="-parenb -parodd -cmspar" ;; + esac + + case "$5" in + 1) SBITS_TMP="-cstopb" ;; + 2) SBITS_TMP="cstopb" ;; + *) SBITS_TMP="-cstopb" ;; + esac + + case "$6" in + "none") FCTRL_TMP="-crtscts -ixon -ixoff" ;; + "rts/cts") FCTRL_TMP="crtscts -ixon -ixoff" ;; + "xon/xoff") FCTRL_TMP="-crtscts ixon ixoff" ;; + *) FCTRL_TMP="-crtscts -ixon -ixoff" ;; + esac + + case "$7" in + 0 | 1) + echo "$7" >/sys/class/gpio/rs485_rx_en/value + ;; + esac + + if [ "$8" == "1" ]; then + FCTRL_TMP="$FCTRL_TMP echo" + else + FCTRL_TMP="$FCTRL_TMP -echo" + fi + + local stty_retries=0 + while ! stty -F "$1" "$2" cs"$3" $PARITY_TMP "$SBITS_TMP" $FCTRL_TMP; do + if [ $stty_retries -lt 5 ]; then + stty_retries=$((stty_retries + 1)) + echo "stty was unable to set all the parameters, retrying in 10 seconds" + sleep 10 + else + echo "stty failed, continuing anyway" + break + fi + done +} + +to_lower() { + tr '[A-Z]' '[a-z]' <<-EOF + $@ + EOF } diff --git a/6.1/target/linux/ipq40xx/base-files/lib/functions/uci-defaults.sh b/6.1/target/linux/ipq40xx/base-files/lib/functions/uci-defaults.sh index 75381262..8d4ff13e 100644 --- a/6.1/target/linux/ipq40xx/base-files/lib/functions/uci-defaults.sh +++ b/6.1/target/linux/ipq40xx/base-files/lib/functions/uci-defaults.sh @@ -40,11 +40,14 @@ ucidef_set_interface() { local val=$1; shift [ -n "$opt" -a -n "$val" ] || break - case "$val" in - true) json_add_boolean "$opt" "1" ;; - false) json_add_boolean "$opt" "0" ;; - *) json_add_string "$opt" "$val" ;; - esac + + [ "$opt" = "device" -a "$val" != "${val/ //}" ] && { + json_select_array "ports" + for e in $val; do json_add_string "" "$e"; done + json_close_array + } || { + json_add_string "$opt" "$val" + } done if ! json_is_a proto string; then @@ -59,6 +62,36 @@ ucidef_set_interface() { json_select .. } +ucidef_set_interface_default_macaddr() { + local network="$1" ifname + + json_select_object 'network' + json_select_object "$network" + if json_is_a ports array; then + json_select_array 'ports' + json_get_keys port_id + for i in $port_id; do + json_get_var port "$i" + ifname="${ifname} $port" + done + json_select .. + else + json_get_var ifname 'device' + fi + json_select .. + json_select .. + + for i in $ifname; do + local macaddr="$2"; shift + [ -n "$macaddr" ] || break + json_select_object 'network-device' + json_select_object "$i" + json_add_string 'macaddr' "$macaddr" + json_select .. + json_select .. + done +} + ucidef_set_board_id() { json_select_object model json_add_string id "$1" @@ -84,11 +117,11 @@ ucidef_set_compat_version() { } ucidef_set_interface_lan() { - ucidef_set_interface "lan" ifname "$1" proto "${2:-static}" + ucidef_set_interface "lan" device "$1" proto "${2:-static}" } ucidef_set_interface_wan() { - ucidef_set_interface "wan" ifname "$1" proto "${2:-dhcp}" + ucidef_set_interface "wan" device "$1" proto "${2:-dhcp}" } ucidef_set_interfaces_lan_wan() { @@ -186,14 +219,14 @@ _ucidef_finish_switch_roles() { json_select_object "$role" # attach previous interfaces (for multi-switch devices) - json_get_var devices ifname + json_get_var devices device if ! list_contains devices "$device"; then devices="${devices:+$devices }$device" fi json_select .. json_select .. - ucidef_set_interface "$role" ifname "$devices" + ucidef_set_interface "$role" device "$devices" done } @@ -210,7 +243,14 @@ ucidef_set_ar8xxx_switch_mib() { json_select .. } -ucidef_add_switch() { +ucidef_add_switch() { + local enabled=1 + if [ "$1" = "enabled" ]; then + shift + enabled="$1" + shift + fi + local name="$1"; shift local port num role device index need_tag prev_role local cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 @@ -218,7 +258,7 @@ ucidef_add_switch() { json_select_object switch json_select_object "$name" - json_add_boolean enable 1 + json_add_boolean enable "$enabled" json_add_boolean reset 1 for port in "$@"; do @@ -606,6 +646,66 @@ ucidef_set_ntpserver() { json_select .. } +ucidef_set_network_options() { + json_add_object "network_options" + n=$# + + for i in $(seq $((n / 2))); do + opt="$1" + val="$2" + + if [ "$val" -eq "$val" ] 2>/dev/null; then + json_add_int "$opt" "$val" + else + [ "$val" = "true" ] && val=1 || val=0 + json_add_boolean "$opt" "$val" + fi + shift; shift + done + json_close_object +} + +ucidef_set_poe() { + json_add_object poe + json_add_int "chip_count" "$1" + json_add_int "budget" "$2" + json_add_int "poe_ports" "$3" + shift 3 + json_add_array ports + while [ $# -gt 0 ] + do + json_add_object "" + json_add_string "name" "$1" + json_add_string "class" "$2" + json_add_int "budget" "$3" + json_close_object + shift 3 + done + json_close_array + json_add_array poe_chips + json_close_array + json_close_object +} + +ucidef_set_poe_chip() { + json_select_object poe + json_select_array poe_chips + json_add_object "" + for port in "$@"; do + case "$port" in + 0X*) + json_add_string address "$port" + ;; + [0-9]:*) + json_add_string chan"${port%%:*}" "${port##*:}" + ;; + esac + done + json_close_object + json_select .. + json_select .. +} + board_config_update() { json_init [ -f ${CFG} ] && json_load "$(cat ${CFG})" diff --git a/6.1/target/linux/ipq40xx/base-files/lib/preinit/82_modem_power b/6.1/target/linux/ipq40xx/base-files/lib/preinit/82_modem_power index 2d77ee72..52593d50 100644 --- a/6.1/target/linux/ipq40xx/base-files/lib/preinit/82_modem_power +++ b/6.1/target/linux/ipq40xx/base-files/lib/preinit/82_modem_power @@ -5,13 +5,16 @@ set_state() { [ -e "/sys/class/gpio/${label}_power/value" ] || return config_get disable ${label} disable + [ "${disable}" -eq 1 ] && \ - /sbin/mctl -s -m "${label}" || \ - /sbin/mctl -p -m "${label}" + /sbin/mctl -s -m "${label}" -c || \ + /sbin/mctl -p -m "${label}" -c } do_power_modem() { - /sbin/mctl -p || { + [ -f /etc/board.json ] || return + + [ -z "$(uci -q get system.modem.disable)" ] && /sbin/mctl -p -a -c || { config_load system config_foreach set_state mctl } diff --git a/6.1/target/linux/ipq40xx/base-files/lib/upgrade/stage2 b/6.1/target/linux/ipq40xx/base-files/lib/upgrade/stage2 index 93792413..5f79619e 100755 --- a/6.1/target/linux/ipq40xx/base-files/lib/upgrade/stage2 +++ b/6.1/target/linux/ipq40xx/base-files/lib/upgrade/stage2 @@ -42,13 +42,22 @@ switch_to_ramfs() { mtd partx losetup mkfs.ext4 nandwrite flash_erase \ ubiupdatevol ubiattach ubiblock ubiformat \ ubidetach ubirsvol ubirmvol ubimkvol \ - snapshot snapshot_tool date \ - dumpimage $RAMFS_COPY_BIN + snapshot snapshot_tool date jshn dtbtool dtc mkbootimg \ + ubinize-image.sh sysupgrade-tar.sh which ubinize mktemp \ + dumpimage ledman fwtool \ + $RAMFS_COPY_BIN do local file="$(command -v "$binary" 2>/dev/null)" [ -n "$file" ] && install_bin "$file" done - install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh /lib/upgrade/do_stage2 /usr/share/libubox/jshn.sh $RAMFS_COPY_DATA + install_file /etc/resolv.conf \ + /lib/*.sh \ + /lib/functions/*.sh \ + /lib/upgrade/*.sh \ + /lib/upgrade/do_stage2 \ + /usr/share/libubox/jshn.sh \ + /etc/board.json \ + $RAMFS_COPY_DATA [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64 @@ -111,10 +120,14 @@ kill_remaining() { # [ [ ] ] _v } -indicate_upgrade +[ -n "$(pgrep telnetd)" ] && { + killall -9 telnetd +} + +[ -n "$(pgrep dropbear)" ] && { + killall -9 dropbear +} -killall -9 telnetd -killall -9 dropbear killall -9 ash kill_remaining TERM @@ -125,10 +138,6 @@ sleep 1 echo 3 > /proc/sys/vm/drop_caches -if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then - platform_pre_upgrade "$IMAGE" -fi - if [ -n "$(rootfs_type)" ]; then v "Switching to ramdisk..." switch_to_ramfs diff --git a/6.1/target/linux/ipq40xx/image/generic.mk b/6.1/target/linux/ipq40xx/image/generic.mk index 9349d0f8..576e05e5 100644 --- a/6.1/target/linux/ipq40xx/image/generic.mk +++ b/6.1/target/linux/ipq40xx/image/generic.mk @@ -70,6 +70,19 @@ define Build/fit-rutx @mv $@.new $@ endef +define Build/UbootFw-rutx + $(CP) ./uboot_fw/ $(STAGING_DIR_HOST)/ + if [ -e $(STAGING_DIR_HOST)/uboot_fw/tz.mbn ]; then \ + $(SED) 's~file\.ubi~$@~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-flash.conf; \ + $(SED) 's~file\.elf~$(BIN_DIR)/openwrt-ipq40xx-u-boot-stripped.elf~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-flash.conf; \ + python $(TOPDIR)/target/linux/ipq40xx/image/uboot_fw/pack.py -t norplusnand -B -F boardconfig_premium_tlt -o $@ $(STAGING_DIR_HOST)/uboot_fw; \ + else \ + $(SED) 's~file\.ubi~$@~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-apps-flash.conf; \ + $(SED) 's~file\.elf~$(BIN_DIR)/openwrt-ipq40xx-u-boot-stripped.elf~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-apps-flash.conf; \ + python $(TOPDIR)/target/linux/ipq40xx/image/uboot_fw/pack.py -t norplusnand -B -F appsboardconfig_premium_tlt -o $@ $(STAGING_DIR_HOST)/uboot_fw; \ + fi +endef + define Build/copy-file cat "$(1)" > "$@" @@ -1119,11 +1132,10 @@ define Device/teltonika_rutx BLOCKSIZE := 128k PAGESIZE := 2048 FILESYSTEMS := squashfs - KERNEL_IN_UBI := 1 - IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin := append-ubi | qsdk-ipq-factory-nand | append-rutx-metadata - #DEVICE_PACKAGES := ipq-wifi-teltonika_rutx kmod-bluetooth kmod-r2ec sysupgrade-helper - DEVICE_PACKAGES := ipq-wifi-teltonika_rutx kmod-bluetooth sysupgrade-helper + IMAGES := factory.bin sysupgrade.bin + IMAGE/factory.ubi := append-ubi + IMAGE/sysupgrade.bin := append-ubi | UbootFw-rutx | append-metadata + DEVICE_PACKAGES := uboot-ipq40xx ipq-wifi-teltonika_rutx kmod-usb-net-qmi-wwan kmod-usb-serial-option kmod-bluetooth sysupgrade-helper HW_SUPPORT := io_expander%stm32:shiftreg_1 endef TARGET_DEVICES += teltonika_rutx diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/appsboardconfig_premium_tlt b/6.1/target/linux/ipq40xx/image/uboot_fw/appsboardconfig_premium_tlt new file mode 100755 index 00000000..10c6cfb3 --- /dev/null +++ b/6.1/target/linux/ipq40xx/image/uboot_fw/appsboardconfig_premium_tlt @@ -0,0 +1,80 @@ +[ipq40xx] +dirname=ipq40xx +nand_available=true +nor_available=true +emmc_available=true +spi_nand_available=true +norplusnand_available=true +norplusemmc_available=false +nand_pagesize=2048 +nand_pages_per_block=64 +nand_total_blocks=4096 +nand_partition=nand-partition.xml +nor_pagesize=256 +nor_pages_per_block=256 +nor_total_blocks=512 +nor_partition=nor-partition.xml +bootconfig=bootconfig.xml +nand_bootconfig=nand_bootconfig.bin +nor_bootconfig=nor_bootconfig.bin +bootconfig1=bootconfig1.xml +nand_bootconfig1=nand_bootconfig1.bin +nor_bootconfig1=nor_bootconfig1.bin +emmc_pagesize=512 +emmc_blocksize=512 +emmc_total_blocks=7634944 +emmc_partition=emmc-partition.xml +smem_info=["smem-ipq40xx.xml"] +cdt_info=["pcddr_40xx.xml"] +cdt_info_default=pcddr_40xx.xml +nand_partition_mbn=nand-system-partition-ipq40xx.bin +nor_partition_mbn=nor-system-partition-ipq40xx.bin +emmc_partition_mbn=gpt_main0.bin +nand_flash_conf=nand-apps-flash.conf +nor_flash_conf=nor-apps-flash.conf +emmc_flash_conf=emmc-apps-flash.conf +machid=0x8010000 +norplusnand_partition=nor-plus-nand-parition.xml +norplusnand_flash_conf=norplusnand-apps-flash.conf +norplusnand_partition_mbn=norplusnand-system-partition-ipq40xx.bin + + +[AP.DK01.1-C2] +dirname=AP.DK01.1-C2 +nand_available=false +nor_available=false +emmc_available=false +spi_nand_available=true +norplusnand_available=true +norplusemmc_available=false +nand_pagesize=2048 +nand_pages_per_block=64 +nand_total_blocks=4096 +nand_partition=nand-partition.xml +nor_pagesize=256 +nor_pages_per_block=256 +nor_total_blocks=512 +nor_partition=nor-partition.xml +bootconfig=bootconfig.xml +nand_bootconfig=nand_bootconfig.bin +nor_bootconfig=nor_bootconfig.bin +bootconfig1=bootconfig1.xml +nand_bootconfig1=nand_bootconfig1.bin +nor_bootconfig1=nor_bootconfig1.bin +emmc_pagesize=512 +emmc_blocksize=512 +emmc_total_blocks=7634944 +emmc_partition=emmc-partition.xml +smem_info=["smem-AP.DK01.1-C2.xml"] +cdt_info=["pcddr_AP.DK01.1-C2_64M16.xml", "pcddr_AP.DK01.1-C2_128M16.xml", "pcddr_AP.DK01.1-C2_256M16.xml"] +cdt_info_default=pcddr_AP.DK01.1-C2.xml +nand_partition_mbn=nand-system-partition-ipq40xx.bin +nor_partition_mbn=nor-system-partition-ipq40xx.bin +emmc_partition_mbn=gpt_main0.bin +nand_flash_conf=nand-apps-flash.conf +nor_flash_conf=nor-apps-flash.conf +emmc_flash_conf=emmc-apps-flash.conf +machid=0x8010100 +norplusnand_partition=nor-plus-nand-parition.xml +norplusnand_flash_conf=norplusnand-apps-flash.conf +norplusnand_partition_mbn=norplusnand-system-partition-ipq40xx.bin diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/boardconfig_premium_tlt b/6.1/target/linux/ipq40xx/image/uboot_fw/boardconfig_premium_tlt new file mode 100755 index 00000000..5c2a75fd --- /dev/null +++ b/6.1/target/linux/ipq40xx/image/uboot_fw/boardconfig_premium_tlt @@ -0,0 +1,79 @@ +[ipq40xx] +dirname=ipq40xx +nand_available=true +nor_available=true +emmc_available=true +spi_nand_available=true +norplusnand_available=true +norplusemmc_available=false +nand_pagesize=2048 +nand_pages_per_block=64 +nand_total_blocks=4096 +nand_partition=nand-partition.xml +nor_pagesize=256 +nor_pages_per_block=256 +nor_total_blocks=512 +nor_partition=nor-partition.xml +bootconfig=bootconfig.xml +nand_bootconfig=nand_bootconfig.bin +nor_bootconfig=nor_bootconfig.bin +bootconfig1=bootconfig1.xml +nand_bootconfig1=nand_bootconfig1.bin +nor_bootconfig1=nor_bootconfig1.bin +emmc_pagesize=512 +emmc_blocksize=512 +emmc_total_blocks=7634944 +emmc_partition=emmc-partition.xml +smem_info=["smem-ipq40xx.xml"] +cdt_info=["pcddr_40xx.xml"] +cdt_info_default=pcddr_40xx.xml +nand_partition_mbn=nand-system-partition-ipq40xx.bin +nor_partition_mbn=nor-system-partition-ipq40xx.bin +emmc_partition_mbn=gpt_main0.bin +nand_flash_conf=nand-flash.conf +nor_flash_conf=nor-flash.conf +emmc_flash_conf=emmc-flash.conf +machid=0x8010000 +norplusnand_partition=nor-plus-nand-parition.xml +norplusnand_flash_conf=norplusnand-flash.conf +norplusnand_partition_mbn=norplusnand-system-partition-ipq40xx.bin + +[AP.DK01.1-C2] +dirname=AP.DK01.1-C2 +nand_available=false +nor_available=false +emmc_available=false +spi_nand_available=true +norplusnand_available=true +norplusemmc_available=false +nand_pagesize=2048 +nand_pages_per_block=64 +nand_total_blocks=4096 +nand_partition=nand-partition.xml +nor_pagesize=256 +nor_pages_per_block=256 +nor_total_blocks=512 +nor_partition=nor-partition.xml +bootconfig=bootconfig.xml +nand_bootconfig=nand_bootconfig.bin +nor_bootconfig=nor_bootconfig.bin +bootconfig1=bootconfig1.xml +nand_bootconfig1=nand_bootconfig1.bin +nor_bootconfig1=nor_bootconfig1.bin +emmc_pagesize=512 +emmc_blocksize=512 +emmc_total_blocks=7634944 +emmc_partition=emmc-partition.xml +smem_info=["smem-AP.DK01.1-C2.xml"] +cdt_info=["pcddr_AP.DK01.1-C2_64M16.xml", "pcddr_AP.DK01.1-C2_128M16.xml", "pcddr_AP.DK01.1-C2_256M16.xml"] +cdt_info_default=pcddr_AP.DK01.1-C2.xml +nand_partition_mbn=nand-system-partition-ipq40xx.bin +nor_partition_mbn=nor-system-partition-ipq40xx.bin +emmc_partition_mbn=gpt_main0.bin +nand_flash_conf=nand-flash.conf +nor_flash_conf=nor-flash.conf +emmc_flash_conf=emmc-flash.conf +machid=0x8010100 +norplusnand_partition=nor-plus-nand-parition.xml +norplusnand_flash_conf=norplusnand-flash.conf +norplusnand_partition_mbn=norplusnand-system-partition-ipq40xx.bin diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-apps-flash.conf b/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-apps-flash.conf new file mode 100644 index 00000000..406ebc19 --- /dev/null +++ b/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-apps-flash.conf @@ -0,0 +1,17 @@ +[ubi] +partition = rootfs +filename = file.ubi + +[ubi_1] +partition = rootfs_1 +filename = file.ubi +primary = ubi + +[u-boot] +partition = 0:APPSBL +filename = file.elf + +[u-boot_1] +partition = 0:APPSBL_1 +filename = file.elf +primary = u-boot diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-flash.conf b/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-flash.conf new file mode 100644 index 00000000..ae91c361 --- /dev/null +++ b/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-flash.conf @@ -0,0 +1,53 @@ +[mibib] +partition = 0:MIBIB +filename = norplusnand-system-partition-ipq40xx.bin + +[sbl1] +partition = 0:SBL1 +filename = sbl1_nor.mbn + +[bootconfig] +partition = 0:BOOTCONFIG +filename = nor_bootconfig.bin + +[bootconfig_1] +partition = 0:BOOTCONFIG1 +filename = nor_bootconfig1.bin + +[ddr-teltonika,rutx] +partition = 0:CDT +filename = cdt-AP.DK01.1-C2.bin +if_machid = 0x8010100 + +[ddr-teltonika,rutx_1] +partition = 0:CDT_1 +filename = cdt-AP.DK01.1-C2.bin +if_machid = 0x8010100 +primary = ddr-teltonika,rutx + +[tz] +partition = 0:QSEE +filename = tz.mbn + +[tz_1] +partition = 0:QSEE_1 +filename = tz.mbn +primary = tz + +[u-boot] +partition = 0:APPSBL +filename = file.elf + +[u-boot_1] +partition = 0:APPSBL_1 +filename = file.elf +primary = u-boot + +[ubi] +partition = rootfs +filename = file.ubi + +[ubi_1] +partition = rootfs_1 +filename = file.ubi +primary = ubi diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-system-partition-ipq40xx.bin b/6.1/target/linux/ipq40xx/image/uboot_fw/norplusnand-system-partition-ipq40xx.bin new file mode 100755 index 0000000000000000000000000000000000000000..d3a2b5acfb93e8c6ceb4ea25708a57af6ed45450 GIT binary patch literal 65536 zcmeIyyKWOf6b9fmLI|j$AaN~ds3Ejewi5%ElGxbBbflw=L{cF|_&JaeqK$ZjzzZN6 zS|l1e3M5_tb7t4KNnD3Wd?St5o_}X&{Oz9o@NW3$)#~dn=ZmV1|Fd?u_v`7mkI#Rk z|Gyf2?Loh}d4Ga2IizenPT5ww*>29lG=45+^_9q)oz7srv;DCBD4lR&nw9hBS-SMa zEPK*#wPIk>F2^y=t=3D~&TKa;S+>40n9NCstI=!Gt9g;lrxn+-Y-6L>ZS)#j{TMBZ z>si+5cH{52wufbQV@Xy9@o_VH+H195HE+7)ojmI;?(=SB3;UdT#c*+NNw(8_mZD-U z%UZ+M_MpGnDXEJDbSZk;%gf!}{TF-jW3k1JimX;;(_O|1=>|@+#nXNNcLJyV`gwEf z;PB}2!R_=YEUo|auttmLXMDW=M`aROeI>Gaji=#RR?eGe=~>OQy#7bodU^flSziD3 zxNd6IKJ)som&r8C>p#!(`d^k!E>(=ui!WNWUS9vlvaJ5=<*ezv`TH^rFUzL&pJ#df z*BAD3vi?(8EBAS#{)>4QCuwIu;I!-i{inv;pI^WKPG$Fb|4RR~*S8)40t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ L009C7&Z@v)%aWl& literal 0 HcmV?d00001 diff --git a/6.1/target/linux/ipq40xx/image/uboot_fw/pack.py b/6.1/target/linux/ipq40xx/image/uboot_fw/pack.py new file mode 100755 index 00000000..f4de45a5 --- /dev/null +++ b/6.1/target/linux/ipq40xx/image/uboot_fw/pack.py @@ -0,0 +1,1908 @@ +# +# Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. +# +""" +Script to create a U-Boot flashable multi-image blob. + +This script creates a multi-image blob, from a bunch of images, and +adds a U-Boot shell script to the blob, that can flash the images from +within U-Boot. The procedure to use this script is listed below. + + 1. Create an images folder. Ex: my-pack + + 2. Copy all the images to be flashed into the folder. + + 3. Copy the partition MBN file into the folder. The file should be + named 'partition.mbn'. This is used to determine the offsets for + each of the named partitions. + + 4. Create a flash configuration file, specifying the images be + flashed, and the partition in which the images is to be + flashed. The flash configuration file can be specified using the + -f option, default is flash.conf. + + 5. Invoke 'pack' with the folder name as argument, pass flash + parameters as arguments if required. A single image file will + be created, out side the images folder, with .img suffix. Ex: + my-pack.img + + 6. Transfer the file into a valid SDRAM address and invoke the + following U-Boot command to flash the images. Replace 0x41000000, + with address location where the image has been loaded. The script + expects the variable 'imgaddr' to be set. + + u-boot> imgaddr=0x88000000 source $imgaddr:script + +Host-side Pre-req + + * Python >= 2.6 + * ordereddict >= 1.1 (for Python 2.6) + * mkimage >= 2012.07 + * dtc >= 1.2.0 + +Target-side Pre-req + +The following U-Boot config macros should be enabled, for the +generated flashing script to work. + + * CONFIG_FIT -- FIT image format support + * CONFIG_SYS_HUSH_PARSER -- bash style scripting support + * CONFIG_SYS_NULLDEV -- redirecting command output support + * CONFIG_CMD_XIMG -- extracting sub-images support + * CONFIG_CMD_NAND -- NAND Flash commands support + * CONFIG_CMD_NAND_YAFFS -- NAND YAFFS2 write support + * CONFIG_CMD_SF -- SPI Flash commands support +""" + +from configparser import ConfigParser +from configparser import Error as ConfigParserError +from os.path import getsize +from getopt import getopt +from getopt import GetoptError +from collections import namedtuple +from string import Template +from unittest import TestCase +from tempfile import mkdtemp +from shutil import rmtree + +import os +import sys +import os.path +import subprocess +import struct +import re +import hashlib + +version = "1.1" + +# +# Python 2.6 and earlier did not have OrderedDict use the backport +# from ordereddict package. If that is not available report error. +# +try: + from collections import OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict + except ImportError: + print("error: this script requires the 'ordereddict' class.") + print("Try 'pip install --user ordereddict'") + print("Or 'easy_install --user ordereddict'") + sys.exit(1) + +__all__ = [] + +KB = 1024 +MB = 1024 * KB + +def error(msg, ex=None): + """Print an error message and exit. + + msg -- string, the message to print + ex -- exception, the associate exception, if any + """ + + sys.stderr.write("pack: %s" % msg) + if ex != None: sys.stderr.write(": %s" % str(ex)) + sys.stderr.write("\n") + sys.exit(1) + +FlashInfo = namedtuple("FlashInfo", "type pagesize blocksize chipsize") +ImageInfo = namedtuple("ProgInfo", "name filename type primary") +PartInfo = namedtuple("PartInfo", "name offset length which_flash") + +def roundup(value, roundto): + """Return the next largest multiple of 'roundto'.""" + + return ((value + roundto - 1) // roundto) * roundto + +class GPT(object): + GPTheader = namedtuple("GPTheader", "signature revision header_size" + " crc32 current_lba backup_lba first_usable_lba" + " last_usable_lba disk_guid start_lba_part_entry" + " num_part_entry part_entry_size part_crc32") + GPT_SIGNATURE = 'EFI PART' + GPT_REVISION = '\x00\x00\x01\x00' + GPT_HEADER_SIZE = 0x5C + GPT_HEADER_FMT = "<8s4sLL4xQQQQ16sQLLL" + + GPTtable = namedtuple("GPTtable", "part_type unique_guid first_lba" + " last_lba attribute_flag part_name") + GPT_TABLE_FMT = "<16s16sQQQ72s" + + def __init__(self, filename, pagesize, blocksize, chipsize): + self.filename = filename + self.pagesize = pagesize + self.blocksize = blocksize + self.chipsize = chipsize + self.__partitions = OrderedDict() + + def __validate_and_read_parts(self, part_fp): + """Validate the GPT and read the partition""" + part_fp.seek(self.blocksize, os.SEEK_SET) + gptheader_str = part_fp.read(struct.calcsize(GPT.GPT_HEADER_FMT)) + gptheader = struct.unpack(GPT.GPT_HEADER_FMT, gptheader_str) + gptheader = GPT.GPTheader._make(gptheader) + + if gptheader.signature != GPT.GPT_SIGNATURE: + error("Invalid signature") + + if gptheader.revision != GPT.GPT_REVISION: + error("Unsupported GPT Revision") + + if gptheader.header_size != GPT.GPT_HEADER_SIZE: + error("Invalid Header size") + + # Adding GPT partition info. This has to be flashed first. + # GPT Header starts at LBA1 so (current_lba -1) will give the + # starting of primary GPT. + # blocksize will equal to gptheader.first_usuable_lba - current_lba + 1 + + name = "0:GPT" + block_start = gptheader.current_lba - 1 + block_count = gptheader.first_usable_lba - gptheader.current_lba + 1 + which_flash = 0 + part_info = PartInfo(name, block_start, block_count, which_flash) + self.__partitions[name] = part_info + + part_fp.seek(2 * self.blocksize, os.SEEK_SET) + + for i in range(gptheader.num_part_entry): + gpt_table_str = part_fp.read(struct.calcsize(GPT.GPT_TABLE_FMT)) + gpt_table = struct.unpack(GPT.GPT_TABLE_FMT, gpt_table_str) + gpt_table = GPT.GPTtable._make(gpt_table) + + block_start = gpt_table.first_lba + block_count = gpt_table.last_lba - gpt_table.first_lba + 1 + + part_name = gpt_table.part_name.strip(chr(0)) + name = part_name.replace('\0','') + part_info = PartInfo(name, block_start, block_count, which_flash) + self.__partitions[name] = part_info + + # Adding the GPT Backup partition. + # GPT header backup_lba gives block number where the GPT backup header will be. + # GPT Backup header will start from offset of 32 blocks before + # the GPTheader.backup_lba. Backup GPT size is 33 blocks. + name = "0:GPTBACKUP" + block_start = gptheader.backup_lba - 32 + block_count = 33 + part_info = PartInfo(name, block_start, block_count, which_flash) + self.__partitions[name] = part_info + + def get_parts(self): + """Returns a list of partitions present in the GPT.""" + + try: + with open(self.filename, "r") as part_fp: + self.__validate_and_read_parts(part_fp) + except IOError as e: + error("error opening %s" % self.filename, e) + + return self.__partitions + +class MIBIB(object): + Header = namedtuple("Header", "magic1 magic2 version age") + HEADER_FMT = " 0: + if yaffs: + self.append("nand write.yaffs $fileaddr 0x%08x 0x%08x" + % (offset, size)) + else: + size = roundup(size, self.pagesize) + self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, size)) + + def switch_layout(self, layout): + """Generate code, to switch between sbl/linux layouts.""" + + self.append("ipq_nand %s" % layout) + + def probe(self): + if self.spi_nand == "true": + self.append("nand device 1") + else: + self.append("nand device 0") + +class NorScript(FlashScript): + """Class for creating NAND flash scripts.""" + + def __init__(self, flinfo, spi_nand): + FlashScript.__init__(self, flinfo) + self.spi_nand = spi_nand + + def erase(self, offset, size): + """Generate code, to erase the specified partition.""" + + size = roundup(size, self.blocksize) + self.append("sf erase 0x%08x +0x%08x" % (offset, size)) + + def write(self, offset, size, yaffs): + """Generate code, to write to a partition.""" + + if size > 0: + self.append("sf write $fileaddr 0x%08x 0x%08x" % (offset, size)) + + def nand_write(self, offset, part_size, img_size): + """Handle the NOR + NAND case + All binaries upto HLOS will go to NOR and Root FS will go to NAND + Assumed all nand page sizes are less than are equal to 8KB + """ + if self.spi_nand == "true": + self.append("nand device 1 && nand erase 0x%08x 0x%08x" % (offset, part_size)) + else: + self.append("nand device 0 && nand erase 0x%08x 0x%08x" % (offset, part_size)) + + if img_size > 0: + self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, img_size)) + + + def probe(self): + self.append("sf probe") + + def switch_layout(self, layout): + pass + +class EmmcScript(FlashScript): + """Class for creating EMMC scripts.""" + + def __init__(self, flinfo): + FlashScript.__init__(self, flinfo) + + def erase(self, offset, size): + """Generate code, to erase the specified partition.""" + + self.append("mmc erase 0x%08x %x" % (offset, size)) + + def write(self, offset, size, yaffs): + """Generate code, to write to a partition.""" + if size > 0: + size = roundup(size, self.blocksize) + blk_cnt = size / self.blocksize + self.append("mmc write $fileaddr 0x%08x %x" % (offset, blk_cnt)) + + def switch_layout(self, layout): + pass + + def probe(self): + pass + +its_tmpl = Template(""" +/dts-v1/; + +/ { + description = "${desc}"; + images { +${images} + }; +}; +""") + +its_image_tmpl = Template(""" + ${name} { + description = "${desc}"; + data = /incbin/("${fname}"); + type = "${imtype}"; + arch = "arm"; + compression = "none"; + hash@1 { algo = "crc32"; }; + }; +""") + + +def sha1(message): + """Returns SHA1 digest in hex format of the message.""" + + m = hashlib.sha1() + m.update(message.encode()) + return m.hexdigest() + + +class Pack(object): + """Class to create a flashable, multi-image blob. + + Combine multiple images present in a directory, and generate a + U-Boot script to flash the images. + """ + # The maximum rootfs size is 64MB + norplusnand_rootfs_img_size = (64 * 1024 * 1024) + + def __init__(self): + self.flinfo = None + self.images_dname = None + self.ipq_nand = None + self.spi_nand = "false" + self.partitions = {} + + self.fconf_fname = None + self.scr_fname = None + self.its_fname = None + self.img_fname = None + + def __get_yaffs(self, info, section): + """Get the yaffs flag for a section. + + info -- ConfigParser object, containing image flashing info + section -- section to check if yaffs flag is set + """ + try: + yaffs = info.get(section, "yaffs") + if yaffs.lower() in ["0", "no"]: + yaffs = False + elif yaffs.lower() in ["1", "yes"]: + yaffs = True + else: + error("invalid value for 'yaffs' in '%s'" % section) + except ConfigParserError as e: + yaffs = False + + if self.flinfo.type == "nor" and yaffs == True: + error("yaffs cannot be used with NOR flash type") + + return yaffs + + def __get_layout(self, info, section): + """Get the layout for a section. + + info -- ConfigParser object, containing image flashing info + section - section to retreive the layout from + """ + try: + layout = info.get(section, "layout") + except ConfigParserError as e: + layout = None + + if self.ipq_nand and layout == None: + error("layout not specified for IPQ device") + + if not self.ipq_nand and layout != None: + error("layout specified for a non IPQ device") + + if layout not in ("sbl", "linux", None): + error("invalid layout in '%s'" % section) + + return layout + + def __get_machid(self, info, section): + """Get the machid for a section. + + info -- ConfigParser object, containing image flashing info + section -- section to retreive the machid from + """ + try: + machid = info.get(section, "if_machid") + machid = int(machid, 0) + machid = "%x" % machid + except ConfigParserError as e: + machid = None + except ValueError as e: + error("invalid value for machid, should be integer") + + return machid + + def __get_img_size(self, filename): + """Get the size of the image to be flashed + + filaneme -- string, filename of the image to be flashed + """ + + if filename.lower() == "none": + return 0 + try: + return getsize(os.path.join(self.images_dname, filename)) + except OSError as e: + error("error getting image size '%s'" % filename, e) + + def __get_part_info(self, partition): + """Return partition info for the specified partition. + + partition -- string, partition name + """ + try: + return self.partitions[partition] + except KeyError as e: + return None + + def __gen_flash_script(self, info, script, flinfo): + """Generate the script to flash the images. + + info -- ConfigParser object, containing image flashing info + script -- Script object, to append commands to + """ + count = 0 + + for section in info.sections(): + try: + filename = info.get(section, "filename") + partition = info.get(section, "partition") + include = info.get(section, "include") + except ConfigParserError as e: + error("error getting image info in section '%s'" % section, e) + + try: + primary = info.get(section, "primary") + except ConfigParserError as e: + primary = "0" + + if include.lower() in ["0", "no"]: + continue + + machid = self.__get_machid(info, section) + layout = self.__get_layout(info, section) + yaffs = self.__get_yaffs(info, section) + + img_size = self.__get_img_size(filename) + part_info = self.__get_part_info(partition) + + if self.flinfo.type == 'nand': + size = roundup(img_size, flinfo.pagesize) + tr = ' | tr \"\\000\" \"\\377\"' + + if self.flinfo.type == 'emmc': + size = roundup(img_size, flinfo.blocksize) + tr = '' + + if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)): + pad_size = size - img_size + filename_abs = os.path.join(self.images_dname, filename) + filename_abs_pad = filename_abs + ".padded" + cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad) + ret = subprocess.call(cmd, shell=True) + if ret != 0: + error("failed to copy image") + cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad) + cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null' + ret = subprocess.call(cmd, shell=True) + if ret != 0: + error("failed to create padded image from script") + + if self.flinfo.type != "emmc": + if part_info == None: + if self.flinfo.type == 'norplusnand': + if count > 2: + error("More than 2 NAND images for NOR+NAND is not allowed") + elif img_size > part_info.length: + error("img size is larger than part. len in '%s'" % section) + else: + if part_info != None: + if (img_size > 0): + if img_size > (part_info.length * self.flinfo.blocksize): + error("img size is larger than part. len in '%s'" % section) + + if part_info == None and self.flinfo.type != 'norplusnand': + continue + + if machid: + script.start_if("machid", machid) + + script.start_activity("Flashing %s:" % section) + if self.ipq_nand: script.switch_layout(layout) + if img_size > 0: + if primary != "0": + section = primary + if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)): + filename_pad = filename + ".padded" + script.imxtract(section + "-" + sha1(filename_pad)) + else: + script.imxtract(section + "-" + sha1(filename)) + + if part_info == None: + if self.flinfo.type == 'norplusnand': + offset = count * Pack.norplusnand_rootfs_img_size + part_size = Pack.norplusnand_rootfs_img_size + script.nand_write(offset, part_size, img_size) + count = count + 1 + else: + if part_info.which_flash == 0: + offset = part_info.offset + script.erase(offset, part_info.length) + script.write(offset, img_size, yaffs) + else: + offset = part_info.offset + script.nand_write(offset, part_info.length, img_size) + + script.finish_activity() + + if machid: + script.end_if() + + if part_info == None and self.flinfo.type != 'norplusnand': + print("Flash type is norplusemmc") + else: + script.end() + + def __gen_script(self, script_fp, info_fp, script, images, flinfo): + """Generate the script to flash the multi-image blob. + + script_fp -- file object, to write script to + info_fp -- file object, to read flashing information from + script -- Script object, to append the commands to + images -- list of ImageInfo, appended to, based on images in config + """ + try: + info = ConfigParser({"include": "yes"}) + info.read_file(info_fp) + except ConfigParserError as e: + error("error parsing info file '%s'" % self.fconf_fname, e) + + self.__gen_flash_script(info, script, flinfo) + + for section in info.sections(): + if info.get(section, "include").lower() in ["0", "no"]: + continue + + partition = info.get(section, "partition") + part_info = self.__get_part_info(partition) + + if part_info == None and self.flinfo.type != 'norplusnand': + continue + + filename = info.get(section, "filename") + if self.flinfo.type == 'nand': + img_size = self.__get_img_size(filename) + size = roundup(img_size, flinfo.pagesize) + if ( size != img_size ): + filename = filename + ".padded" + if self.flinfo.type == 'emmc': + img_size = self.__get_img_size(filename) + size = roundup(img_size, flinfo.blocksize) + if ( size != img_size ): + filename = filename + ".padded" + try: + primary = info.get(section, "primary") + except ConfigParserError as e: + primary = "0" + + if primary != "0": + print("primary: %s" % primary) + image_info = ImageInfo(section + "-" + sha1(filename), + filename, "firmware", primary) + if filename.lower() != "none": + if image_info not in images: + images.append(image_info) + + def __its_escape(self, string): + """Return string with ITS special characters escaped. + + string -- string to be escape. + + String in ITS files, consider 'slash' as special + character. Escape them by prefixing them with a slash. + """ + return string.replace("\\", "\\\\") + + def __mkimage(self, images): + """Create the multi-image blob. + + images -- list of ImageInfo, containing images to be part of the blob + """ + try: + its_fp = open(self.its_fname, "w") + except IOError as e: + error("error opening its file '%s'" % self.its_fname, e) + + desc = "Flashing %s %x %x" + desc = desc % (self.flinfo.type, self.flinfo.pagesize, + self.flinfo.blocksize) + + image_data = [] + for (section, fname, imtype, primary) in images: + if primary != "0": + continue + fname = self.__its_escape(fname) + subs = dict(name=section, desc=fname, fname=fname, imtype=imtype) + image_data.append(its_image_tmpl.substitute(subs)) + + image_data = "".join(image_data) + its_data = its_tmpl.substitute(desc=desc, images=image_data) + + its_fp.write(its_data) + its_fp.close() + + try: + cmd = ["mkimage", "-f", self.its_fname, self.img_fname] + ret = subprocess.call(cmd) + if ret != 0: + error("failed to create u-boot image from script") + except OSError as e: + error("error executing mkimage", e) + + def __create_fnames(self): + """Populate the filenames.""" + + self.scr_fname = os.path.join(self.images_dname, "flash.scr") + self.its_fname = os.path.join(self.images_dname, "flash.its") + + def __gen_board_script(self, board_section, machid, flinfo, + part_fname, fconf_fname, images): + """Generate the flashing script for one board. + + board_section -- string, board section in board config file + machid -- string, board machine ID in hex format + flinfo -- FlashInfo object, contains board specific flash params + part_fname -- string, partition file specific to the board + fconf_fname -- string, flash config file specific to the board + images -- list of ImageInfo, append images used by the board here + """ + script_fp = open(self.scr_fname, "a") + + try: + fconf_fp = open(fconf_fname) + except IOError as e: + error("error opening flash config file '%s'" % fconf_fname, e) + + if flinfo.type != "emmc": + nand_pagesize = int(self.bconf.get(board_section, "nand_pagesize")) + nand_pages_per_block = int(self.bconf.get(board_section, + "nand_pages_per_block")) + nand_blocks_per_chip = int(self.bconf.get(board_section, + "nand_total_blocks")) + + nand_blocksize = nand_pages_per_block * nand_pagesize + nand_chipsize = nand_blocks_per_chip * nand_blocksize + + mibib = MIBIB(part_fname, flinfo.pagesize, flinfo.blocksize, + flinfo.chipsize, nand_blocksize, nand_chipsize) + self.partitions = mibib.get_parts() + else: + gpt = GPT(part_fname, flinfo.pagesize, flinfo.blocksize, flinfo.chipsize) + self.partitions = gpt.get_parts() + + self.flinfo = flinfo + if flinfo.type == "nand": + self.ipq_nand = False + script = NandScript(flinfo, self.ipq_nand, self.spi_nand) + elif flinfo.type == "nor" or flinfo.type == "norplusnand": + self.spi_nand = self.bconf.get(board_section, "spi_nand_available") + self.ipq_nand = False + script = NorScript(flinfo, self.spi_nand) + elif flinfo.type == "emmc": + self.ipq_nand = False + script = EmmcScript(flinfo) + else: + error("error, flash type unspecified.") + + script.start_if("machid", machid) + script.probe() + self.__gen_script(script_fp, fconf_fp, script, images, flinfo) + script.end_if() + + try: + script_fp.write(script.dumps()) + except IOError as e: + error("error writing to script '%s'" % script_fp.name, e) + + script_fp.close() + + def __process_board_flash_emmc(self, ftype, board_section, machid, images): + """Extract board info from config and generate the flash script. + + ftype -- string, flash type 'emmc' + board_section -- string, board section in config file + machid -- string, board machine ID in hex format + images -- list of ImageInfo, append images used by the board here + """ + + pagesize_param = "%s_pagesize" % ftype + blocksize_param = "%s_blocksize" % "emmc" + blocks_per_chip_param = "%s_total_blocks" % "emmc" + part_fname_param = "%s_partition_mbn" % ftype + fconf_fname_param = "%s_flash_conf" % ftype + + if ftype == "norplusemmc": + part_fname_param = "%s_gpt_bin" % ftype + + try: + pagesize = int(self.bconf.get(board_section, pagesize_param)) + blocksize = int(self.bconf.get(board_section, blocksize_param)) + chipsize = int(self.bconf.get(board_section, + blocks_per_chip_param)) + except ConfigParserError as e: + error("missing flash info in section '%s'" % board_section, e) + except ValueError as e: + error("invalid flash info in section '%s'" % board_section, e) + + if ftype == "norplusemmc": + ftype = "emmc" + + flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize) + + try: + part_fname = self.bconf.get(board_section, part_fname_param) + if not os.path.isabs(part_fname): + part_fname = os.path.join(self.images_dname, part_fname) + except ConfigParserError as e: + error("missing partition file in section '%s'" % board_section, e) + + try: + fconf_fname = self.bconf.get(board_section, fconf_fname_param) + if not os.path.isabs(fconf_fname): + fconf_fname = os.path.join(self.images_dname, fconf_fname) + except ConfigParserError as e: + error("missing NAND config in section '%s'" % board_section, e) + + self.__gen_board_script(board_section, machid, flinfo, + part_fname, fconf_fname, images) + + def __process_board_flash(self, ftype, board_section, machid, images): + """Extract board info from config and generate the flash script. + + ftype -- string, flash type 'nand' or 'nor' or 'emmc' or 'norplusnand' + board_section -- string, board section in config file + machid -- string, board machine ID in hex format + images -- list of ImageInfo, append images used by the board here + """ + + pagesize_param = "%s_pagesize" % ftype + pages_per_block_param = "%s_pages_per_block" % ftype + blocks_per_chip_param = "%s_total_blocks" % ftype + part_fname_param = "%s_partition_mbn" % ftype + fconf_fname_param = "%s_flash_conf" % ftype + + if ftype == "norplusnand" or ftype == "norplusemmc": + pagesize_param = "%s_pagesize" % "nor" + pages_per_block_param = "%s_pages_per_block" % "nor" + blocks_per_chip_param = "%s_total_blocks" % "nor" + + try: + pagesize = int(self.bconf.get(board_section, pagesize_param)) + pages_per_block = int(self.bconf.get(board_section, + pages_per_block_param)) + blocks_per_chip = int(self.bconf.get(board_section, + blocks_per_chip_param)) + except ConfigParserError as e: + error("missing flash info in section '%s'" % board_section, e) + except ValueError as e: + error("invalid flash info in section '%s'" % board_section, e) + + blocksize = pages_per_block * pagesize + chipsize = blocks_per_chip * blocksize + if ftype == "norplusemmc": + ftype = "nor" + + flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize) + + try: + part_fname = self.bconf.get(board_section, part_fname_param) + if not os.path.isabs(part_fname): + part_fname = os.path.join(self.images_dname, part_fname) + except ConfigParserError as e: + error("missing partition file in section '%s'" % board_section, e) + + try: + fconf_fname = self.bconf.get(board_section, fconf_fname_param) + if not os.path.isabs(fconf_fname): + fconf_fname = os.path.join(self.images_dname, fconf_fname) + except ConfigParserError as e: + error("missing NAND config in section '%s'" % board_section, e) + + self.__gen_board_script(board_section, machid, flinfo, + part_fname, fconf_fname, images) + + def __process_board(self, board_section, images): + try: + machid = int(self.bconf.get(board_section, "machid"), 0) + machid = "%x" % machid + except ConfigParserError as e: + error("missing machid in section '%s'" % board_section, e) + except ValueError as e: + error("invalid machid in section '%s'" % board_section, e) + + try: + available = self.bconf.get(board_section, "nand_available") + if available == "true" and self.flash_type == "nand": + self.__process_board_flash("nand", board_section, machid, images) + except ConfigParserError as e: + error("error getting board info in section '%s'" % board_section, e) + + try: + available = self.bconf.get(board_section, "nor_available") + if available == "true" and self.flash_type == "nor": + self.__process_board_flash("nor", board_section, machid, images) + except ConfigParserError as e: + error("error getting board info in section '%s'" % board_section, e) + + try: + available = self.bconf.get(board_section, "emmc_available") + if available == "true" and self.flash_type == "emmc": + self.__process_board_flash_emmc("emmc", board_section, machid, images) + except ConfigParserError as e: + error("error getting board info in section '%s'" % board_section, e) + + try: + available = self.bconf.get(board_section, "norplusnand_available") + if available == "true" and self.flash_type == "norplusnand": + self.__process_board_flash("norplusnand", board_section, machid, images) + except ConfigParserError as e: + error("error getting board info in section '%s'" % board_section, e) + + try: + available = self.bconf.get(board_section, "norplusemmc_available") + if available == "true" and self.flash_type == "norplusemmc": + self.__process_board_flash("norplusemmc", board_section, machid, images) + self.__process_board_flash_emmc("norplusemmc", board_section, machid, images) + except ConfigParserError as e: + error("error getting board info in section '%s'" % board_section, e) + + + + def main_bconf(self, flash_type, images_dname, out_fname, brdconfig): + """Start the packing process, using board config. + + flash_type -- string, indicates flash type, 'nand' or 'nor' or 'emmc' or 'norplusnand' + images_dname -- string, name of images directory + out_fname -- string, output file path + """ + self.flash_type = flash_type + self.images_dname = images_dname + self.img_fname = out_fname + + self.__create_fnames() + + try: + os.unlink(self.scr_fname) + except OSError as e: + pass + + try: + bconf_fname = os.path.join(images_dname, brdconfig) + bconf_fp = open(bconf_fname) + self.bconf = ConfigParser() + self.bconf.read_file(bconf_fp) + bconf_fp.close() + except IOError as e: + error("error reading board configuration file", e) + except ConfigParserError as e: + error("error parsing board configuration file", e) + + images = [] + for section in self.bconf.sections(): + self.__process_board(section, images) + + images.insert(0, ImageInfo("script", "flash.scr", "script","0")) + self.__mkimage(images) + + def main(self, flinfo, images_dname, out_fname, part_fname, fconf_fname, ipq_nand): + """Start the packing process. + + flinfo -- FlashInfo object, containing flash parameters + images_dname -- string, name of images directory + out_fname -- string, output file path + part_fname -- string, partition file path + fconf_fname -- string, flash confing file path + ipq_nand -- bool, indicates whether this is an IPQ device + """ + self.flinfo = flinfo + self.images_dname = images_dname + self.img_fname = out_fname + self.ipq_nand = ipq_nand + + self.__create_fnames() + + if self.flinfo.type == "nand": + script = NandScript(self.flinfo, self.ipq_nand) + elif self.flinfo.type == "nor" or self.flinfo.type == "norplusnand": + script = NorScript(self.flinfo) + elif self.flinfo.type == "emmc": + script = EmmcScript(self.flinfo) + else: + error("Invalid flash type specified. It should be 'nand' or 'nor' or 'norplusnand'") + + if not os.path.isabs(part_fname): + part_fname = os.path.join(self.images_dname, part_fname) + + if not os.path.isabs(fconf_fname): + self.fconf_fname = os.path.join(self.images_dname, fconf_fname) + + nand_pagesize = int(self.bconf.get(board_section, "nand_pagesize")) + nand_pages_per_block = int(self.bconf.get(board_section, + "nand_pages_per_block")) + nand_blocks_per_chip = int(self.bconf.get(board_section, + "nand_total_blocks")) + + nand_blocksize = nand_pages_per_block * nand_pagesize + nand_chipsize = nand_blocks_per_chip * nand_blocksize + + mibib = MIBIB(part_fname, self.flinfo.pagesize, self.flinfo.blocksize, + self.flinfo.chipsize, nand_blocksize, nand_chipsize) + self.partitions = mibib.get_parts() + + script.echo("", verbose=True) + + script.start_activity("Check environment:") + script.check_isset("imgaddr") + script.check_isset("machid") + script.finish_activity() + + try: + info_fp = open(self.fconf_fname) + except IOError as e: + error("error opening info file '%s'" % self.fconf_fname, e) + + try: + scr_fp = open(self.scr_fname, "wb") + except IOError as e: + error("error opening script file '%s'" % self.scr_fname, e) + + images = [] + self.__gen_script(scr_fp, info_fp, script, images) + try: + scr_fp.write(script.dumps()) + except IOError as e: + error("error writing to script '%s'" % script_fp.name, e) + scr_fp.close() # Flush out all written commands + + images.insert(0, ImageInfo("script", "flash.scr", "script", "0")) + self.__mkimage(images) + +class UsageError(Exception): + """Indicates error in command arguments.""" + pass + +class ArgParser(object): + """Class to parse command-line arguments.""" + + DEFAULT_PAGESIZE = 4096 + DEFAULT_PAGES_PER_BLOCK = 64 + DEFAULT_BLOCKS_PER_CHIP = 1024 + DEFAULT_TYPE = "nand" + DEFAULT_PART_FNAME = "partition.mbn" + DEFAULT_FCONF_FNAME = "flash.conf" + + def __init__(self): + self.__pagesize = None + self.__pages_per_block = None + self.__blocksize = None + self.__chipsize = None + self.__flash_type = None + + self.flash_info = None + self.images_dname = None + self.ipq_nand = False + self.bconf = False + self.bconf_fname = "boardconfig" + self.part_fname = None + self.fconf_fname = None + + def __init_pagesize(self, pagesize): + """Set the pagesize, from the command line argument. + + pagesize -- string, flash page size + + Raise UsageError, if pagesize is invalid + """ + if pagesize == None: + self.__pagesize = ArgParser.DEFAULT_PAGESIZE + else: + try: + self.__pagesize = int(pagesize) + except ValueError: + raise UsageError("invalid page size '%s'" % pagesize) + + def __init_blocksize(self, pages_per_block): + """Set the blocksize, from the command line argument. + + pages_per_block -- string, no. of pages in a flash block + + Raise UsageError, if pages_per_block is invalid + """ + if pages_per_block == None: + self.__blocksize = (self.__pagesize + * ArgParser.DEFAULT_PAGES_PER_BLOCK) + else: + try: + self.__blocksize = self.__pagesize * int(pages_per_block) + except ValueError: + raise UsageError("invalid block size '%s'" % self.__blocksize) + + def __init_chipsize(self, blocks_per_chip): + """Set the chipsize, from the command line argument. + + blocks_per_chip -- string, no. of blocks in a flash chip + + Raise UsageError, if chips_per_block is invalid + """ + if blocks_per_chip == None: + self.__chipsize = (self.__blocksize + * ArgParser.DEFAULT_BLOCKS_PER_CHIP) + else: + try: + self.__chipsize = self.__blocksize * int(blocks_per_chip) + except ValueError: + raise UsageError("invalid chip size '%s'" % self.__chipsize) + + def __init_flash_info(self): + """Set flash_info from the parsed flash paramaters.""" + + self.flash_info = FlashInfo(self.__flash_type, + self.__pagesize, + self.__blocksize, + self.__chipsize) + + def __init_flash_type(self, flash_type): + """Set the flash_type, from the command line argument. + + flash_type -- string, nand or nor + + Raise UsageError, if flash_type is invalid + """ + + if flash_type == None: + self.__flash_type = ArgParser.DEFAULT_TYPE + elif flash_type in [ "nand", "nor", "emmc", "norplusnand", "norplusemmc" ]: + self.__flash_type = flash_type + else: + raise UsageError("invalid flash type '%s'" % flash_type) + + def __init_part_fname(self, part_fname): + """Set the partition filename from command line argument + + part_fname -- string, the partition filename + """ + + if part_fname == None: + self.part_fname = ArgParser.DEFAULT_PART_FNAME + else: + self.part_fname = part_fname + + def __init_fconf_fname(self, fconf_fname): + """Set the flash configuration filename from command line argument + + fconf_fname -- string, the flash configuration filename + """ + + if fconf_fname == None: + self.fconf_fname = ArgParser.DEFAULT_FCONF_FNAME + else: + self.fconf_fname = fconf_fname + + def __init_out_fname(self, out_fname, images_dname, flash_type, + pagesize, pages_per_block, blocks_per_chip, + bconf): + """Set the out_fname from the command line argument. + + out_fname -- string, the output filename + images_dname -- string, the images dirname + flash_type -- string, the flash type + pagesize -- int, the flash page size in bytes + pages_per_block -- int, the flash pages per block + blocks_per_chip -- int, the flash blocks per chip + bconf -- bool, whether is board config mode + """ + + if out_fname == None: + images_dname_norm = os.path.abspath(images_dname) + if bconf: + fmt = "%s-%s%simg" + self.out_fname = fmt % (images_dname_norm, flash_type, + os.path.extsep) + else: + fmt = "%s-%s-%d-%d-%d%simg" + self.out_fname = fmt % (images_dname_norm, flash_type, + pagesize, pages_per_block, + blocks_per_chip, os.path.extsep) + else: + if os.path.isabs(out_fname): + self.out_fname = out_fname + else: + images_dname_parent = os.path.dirname(images_dname) + self.out_fname = os.path.join(images_dname_parent, out_fname) + + def __init_images_dname(self, args): + """Set the images_dname from the command line argument. + + args -- list of string, command line args after stripping options + """ + self.images_dname = args[0] + + def parse(self, argv): + """Start the parsing process, and populate members with parsed value. + + argv -- list of string, the command line arguments + """ + flash_type = None + pagesize = None + pages_per_block = None + blocks_per_chip = None + ipq_nand = False + out_fname = None + part_fname = None + fconf_fname = None + bconf = False + bconf_fname = None + + try: + opts, args = getopt(argv[1:], "Bib:hp:t:o:c:m:f:F:") + except GetoptError as e: + raise UsageError(e.msg) + + for option, value in opts: + if option == "-t": + flash_type = value + elif option == "-i": + ipq_nand = True + elif option == "-p": + pagesize = value + elif option == "-b": + pages_per_block = value + elif option == '-c': + blocks_per_chip = value + elif option == "-o": + out_fname = value + elif option == "-m": + part_fname = value + elif option == "-f": + fconf_fname = value + elif option == "-B": + bconf = True + elif option == "-F": + bconf_fname = value + + if len(args) != 1: + raise UsageError("insufficient arguments") + + self.__init_flash_type(flash_type) + self.__init_pagesize(pagesize) + self.__init_blocksize(pages_per_block) + self.__init_chipsize(blocks_per_chip) + self.__init_flash_info() + self.__init_images_dname(args) + self.__init_out_fname(out_fname, self.images_dname, + self.__flash_type, self.__pagesize, + self.__blocksize / self.__pagesize, + self.__chipsize / self.__blocksize, + bconf) + self.__init_part_fname(part_fname) + self.__init_fconf_fname(fconf_fname) + + self.ipq_nand = ipq_nand + self.bconf = bconf + if bconf_fname != None: + self.bconf_fname = bconf_fname + + def usage(self, msg): + """Print error message and command usage information. + + msg -- string, the error message + """ + print("pack: %s" % msg) + print() + print("Usage: pack [options] IDIR") + print() + print("where IDIR is the path containing the images.") + print() + print(" -t TYPE specifies partition type, 'nand' or 'nor',") + print(" default is '%s'." % ArgParser.DEFAULT_TYPE) + print(" -p SIZE specifies the page size in bytes,") + print(" default is %d." % ArgParser.DEFAULT_PAGESIZE) + print(" -b COUNT specifies the pages per block,") + print(" default is %d." % ArgParser.DEFAULT_PAGES_PER_BLOCK) + print(" -c COUNT specifies the no. of blocks per chip") + print(" default is %d." % ArgParser.DEFAULT_BLOCKS_PER_CHIP) + print(" -i specifies IPQ processor specific NAND layout") + print(" switch, default disabled.") + print(" -m FILE specifies the partition filename") + print(" default is '%s'." % ArgParser.DEFAULT_PART_FNAME) + print(" -f FILE specifies the flash configuration filename") + print(" default is '%s'." % ArgParser.DEFAULT_FCONF_FNAME) + print(" -o FILE specifies the output filename") + print(" default is IDIR-TYPE-SIZE-COUNT.img") + print(" if the filename is relative, it is relative") + print(" to the parent of IDIR.") + print() + print("NOTE: The above invocation method of pack is deprecated.") + print("The new pack invocation uses a board config file to retrieve") + print("the board specific parameters. The new invocation is provided") + print("below.") + print() + print("Usage: pack [options] IDIR") + print() + print("where IDIR is the path containing the images.") + print() + print(" -t TYPE specifies partition type, 'nand' or 'nor', or 'emmc'") + print(" default is '%s'." % ArgParser.DEFAULT_TYPE) + print(" -B specifies board config should be used, for") + print(" flash parameters.") + print(" -F specifies board config file name should be used, for") + print(" flash parameters. Defaults to 'boardconfig'") + print(" -o FILE specifies the output filename") + print(" default is IDIR-TYPE.img") + print(" if the filename is relative, it is relative") + print(" to the parent of IDIR.") + print() + print("Pack Version: %s" % version) + + +def main(): + """Main script entry point. + + Created to avoid polluting the global namespace. + """ + try: + parser = ArgParser() + parser.parse(sys.argv) + except UsageError as e: + parser.usage(e.args[0]) + sys.exit(1) + + pack = Pack() + if parser.bconf: + pack.main_bconf(parser.flash_info.type, parser.images_dname, + parser.out_fname, parser.bconf_fname) + else: + pack.main(parser.flash_info, parser.images_dname, + parser.out_fname, parser.part_fname, + parser.fconf_fname, parser.ipq_nand) + +class ArgParserTestCase(TestCase): + def setUp(self): + self.parser = ArgParser() + + def test_defaults(self): + self.parser.parse(["pack.py", "itest"]) + self.assertEqual(self.parser.images_dname, "itest") + + fmt = "itest-%s-%d-%d-%d.img" + expected_fname = fmt % (ArgParser.DEFAULT_TYPE, + ArgParser.DEFAULT_PAGESIZE, + ArgParser.DEFAULT_PAGES_PER_BLOCK, + ArgParser.DEFAULT_BLOCKS_PER_CHIP) + self.assertEqual(self.parser.out_fname, expected_fname) + self.assertEqual(self.parser.ipq_nand, False) + self.assertEqual(self.parser.flash_info.type, + ArgParser.DEFAULT_TYPE) + self.assertEqual(self.parser.flash_info.pagesize, + ArgParser.DEFAULT_PAGESIZE) + self.assertEqual(self.parser.flash_info.blocksize, + ArgParser.DEFAULT_PAGES_PER_BLOCK + * ArgParser.DEFAULT_PAGESIZE) + self.assertEqual(self.parser.flash_info.chipsize, + ArgParser.DEFAULT_BLOCKS_PER_CHIP + * ArgParser.DEFAULT_PAGES_PER_BLOCK + * ArgParser.DEFAULT_PAGESIZE) + + def test_ipq_flag(self): + self.parser.parse(["pack.py", "-i", "itest"]) + self.assertEqual(self.parser.ipq_nand, True) + + def test_invalid_flag(self): + self.assertRaises(UsageError, self.parser.parse, + ["pack.py", "-x", "itest"]) + + def test_type_option(self): + self.parser.parse(["pack.py", "-t", "nor", "itest"]) + self.assertEqual(self.parser.flash_info.type, "nor") + + def test_invalid_type_option(self): + self.assertRaises(UsageError, self.parser.parse, + ["pack.py", "-t", "abcd", "itest"]) + + def test_pagesize_option(self): + self.parser.parse(["pack.py", "-p", "2048", "itest"]) + self.assertEqual(self.parser.flash_info.pagesize, 2048) + + def test_invalid_pagesize_option(self): + self.assertRaises(UsageError, self.parser.parse, + ["pack.py", "-p", "abcd", "itest"]) + + def test_pages_per_block_option(self): + self.parser.parse(["pack.py", "-b", "32", "itest"]) + self.assertEqual(self.parser.flash_info.blocksize, + ArgParser.DEFAULT_PAGESIZE * 32) + + def test_invalid_pages_per_block_option(self): + self.assertRaises(UsageError, self.parser.parse, + ["pack.py", "-b", "abcd", "itest"]) + + def test_blocks_per_chip_option(self): + self.parser.parse(["pack.py", "-c", "512", "itest"]) + self.assertEqual(self.parser.flash_info.chipsize, + ArgParser.DEFAULT_PAGESIZE + * ArgParser.DEFAULT_PAGES_PER_BLOCK + * 512) + + def test_out_fname_rel_option(self): + self.parser.parse(["pack.py", "-o", "abcd", "/tmp/test/itest"]) + self.assertEqual(self.parser.out_fname, "/tmp/test/abcd") + + def test_out_fname_abs_option(self): + self.parser.parse(["pack.py", "-o", "/tmp/abcd", "/tmp/test/itest"]) + self.assertEqual(self.parser.out_fname, "/tmp/abcd") + + def test_partition_option(self): + self.parser.parse(["pack.py", "-m", "abcd", "/tmp/test/itest"]) + self.assertEqual(self.parser.part_fname, "abcd") + + def test_flash_conf_option(self): + self.parser.parse(["pack.py", "-f", "abcd", "/tmp/test/itest"]) + self.assertEqual(self.parser.fconf_fname, "abcd") + +class PackTestCase(TestCase): + def setUp(self): + self.pack = Pack() + blocksize = (ArgParser.DEFAULT_PAGESIZE + * ArgParser.DEFAULT_PAGES_PER_BLOCK) + chipsize = blocksize * ArgParser.DEFAULT_BLOCKS_PER_CHIP + + self.flinfo = FlashInfo(ArgParser.DEFAULT_TYPE, + ArgParser.DEFAULT_PAGESIZE, + blocksize, chipsize) + self.img_dname = mkdtemp() + self.img_fname = self.img_dname + ".img" + self.part_fname = "partition.mbn" + self.fconf_fname = "flash.conf" + + sbl1_fp = open(os.path.join(self.img_dname, "sbl1.mbn"), "w") + sbl1_fp.write("#" * blocksize * 2) + sbl1_fp.close() + + self.__create_partition_mbn(blocksize, chipsize) + + def __create_partition_mbn(self, blocksize, chipsize): + part_fname = os.path.join(self.img_dname, self.part_fname) + + mibib = MIBIB(part_fname, ArgParser.DEFAULT_PAGESIZE, blocksize, + chipsize) + + offset = 0 + part_size = 2 * blocksize + mibib.add_part(PartInfo("0:SBL1", offset, part_size)) + + offset += part_size + part_size = 2 * blocksize + mibib.add_part(PartInfo("0:MIBIB", offset, part_size)) + + offset += part_size + part_size = 1 * blocksize + mibib.add_part(PartInfo("0:SBL2", offset, part_size)) + + offset += part_size + part_size = None + mibib.add_part(PartInfo("0:FS", offset, part_size)) + + mibib.write() + + def __mkconf(self, conf_str): + conf_fname = os.path.join(self.img_dname, self.fconf_fname) + conf_fp = open(conf_fname, "w") + conf_fp.write(conf_str) + conf_fp.close() + + def tearDown(self): + rmtree(self.img_dname) + try: + os.remove(self.img_fname) + except OSError: + pass + + def test_simple(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +""") + + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + self.assertEqual(os.path.exists(self.img_fname), True) + + def test_missing_conf(self): + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_nand_layout(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +layout = sbl +""") + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=True) + self.assertEqual(os.path.exists(self.img_fname), True) + + def test_invalid_layout(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +layout = abcd +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=True) + + def test_inconsistent_layout(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +layout = sbl +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_invalid_filename(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl10.mbn +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_special_chars_in_filename(self): + self.__mkconf(""" +[slash] +partition = 0:SBL1 +filename = sb\\l1.mbn +""") + + sbl1_fp = open(os.path.join(self.img_dname, "sb\\l1.mbn"), "w") + sbl1_fp.write("abcdef") + sbl1_fp.close() + + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + self.assertEqual(os.path.exists(self.img_fname), True) + + def __get_images(self): + mkimage_output = subprocess.check_output(["mkimage", "-l", self.img_fname]) + return re.findall(r"Image \d+ \((.*)\)", mkimage_output) + + def test_multi_image(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn + +[sbl2] +partition = 0:MIBIB +filename = partition.mbn +""") + + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + count = len(self.__get_images()) + self.assertEqual(count, 3) + + def test_include(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +include = no + +[sbl2] +partition = 0:MIBIB +filename = partition.mbn +""") + + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + images = self.__get_images() + print(images) + self.assertTrue("sbl2" in images) + self.assertTrue("sbl1" not in images) + + def test_yaffs_yes(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +yaffs = yes +""") + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + + def test_yaffs_no(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +yaffs = no +""") + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + + def test_yaffs_invalid(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +yaffs = abcd +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_invalid_partition(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL5 +filename = sbl1.mbn +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_img_larger_than_partition(self): + self.__mkconf(""" +[sbl2] +partition = 0:SBL2 +filename = sbl1.mbn +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + + def test_machid_in_hex(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +if_machid = 0x152 +""") + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + self.assertEqual(os.path.exists(self.img_fname), True) + + def test_machid_in_dec(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +if_machid = 256 +""") + self.pack.main(self.flinfo, self.img_dname, self.img_fname, + self.part_fname, self.fconf_fname, ipq_nand=False) + self.assertEqual(os.path.exists(self.img_fname), True) + + def test_machid_invalid(self): + self.__mkconf(""" +[sbl1] +partition = 0:SBL1 +filename = sbl1.mbn +if_machid = xyz +""") + self.assertRaises(SystemExit, + self.pack.main, + self.flinfo, + self.img_dname, + self.img_fname, + self.part_fname, + self.fconf_fname, + ipq_nand=False) + +if __name__ == "__main__": + main()