Merge Lean's source

This commit is contained in:
AmadeusGhost 2020-06-28 17:50:37 +08:00
commit 9bfbdcb765
42 changed files with 5425 additions and 1461 deletions

View File

@ -203,13 +203,12 @@ menu "Target Images"
depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_ISO || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS
select PACKAGE_grub2
select PACKAGE_grub2-efi
default n
default y
config GRUB_CONSOLE
bool "Use Console Terminal (in addition to Serial)"
depends on GRUB_IMAGES || EFI_IMAGES
default n if (TARGET_x86_generic_Soekris45xx || TARGET_x86_generic_Soekris48xx || TARGET_x86_net5501 || TARGET_x86_geos || TARGET_x86_alix2)
default y
default n
config GRUB_SERIAL
string "Serial port device"

View File

@ -36,7 +36,9 @@ zbtlink,zbt-wg2626)
linksys,ea7500-v2|\
xiaomi,mir3p|\
xiaomi,mir3g|\
xiaomi,mir4|\
xiaomi,miwifi-r3|\
xiaomi,mi-router-ac2100|\
xiaomi,redmi-router-ac2100)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x1000" "0x20000"
;;

View File

@ -2,14 +2,14 @@ msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"Last-Translator: ElonH <elonhhuang@gmail.com>\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: none\n"
"Language: zh-Hans\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.3.1\n"
#: luasrc/model/cbi/rclone.lua:121
msgid "FAQ"
@ -48,7 +48,7 @@ msgid ""
"commonly either http or socks5."
msgstr ""
"内容格式为: protocol://server:port\n"
"protocol 通常为 http 或者 socks5"
"protocol 通常为 http 或者 socks5"
#: luasrc/model/cbi/rclone.lua:43
msgid "Webui React"
@ -140,7 +140,7 @@ msgstr "启动 rclone 后台服务"
#: luasrc/model/cbi/rclone.lua:80
msgid "than updaload configuration to here."
msgstr "然后上传配置文件到这里"
msgstr "然后上传配置文件到这里"
#: luasrc/model/cbi/rclone.lua:80
msgid "to setup configuration on pc,"

View File

@ -1,7 +1,15 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Last-Translator: Hsing-Wang Liao <kuoruan@gmail.com>\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "%d hour"
msgstr "%d 小时"
@ -318,7 +326,7 @@ msgid "Policy assigned"
msgstr "分配的策略"
msgid "Protocol"
msgstr "通信协议"
msgstr "协议"
msgid "Recovery interval"
msgstr "故障恢复间隔"
@ -551,13 +559,13 @@ msgid "never"
msgstr "从不"
msgid "restart"
msgstr ""
msgstr "重启"
msgid "start"
msgstr ""
msgstr "启动"
msgid "stop"
msgstr ""
msgstr "关闭"
msgid "unreachable (reject)"
msgstr "不可达(拒绝)"
@ -679,8 +687,8 @@ msgid ""
"specific date, e.g. every 3rd. Choose \"Fixed interval\" to restart the "
"accounting period exactly every N days, beginning at a given date."
msgstr ""
"选择“每月的某一天”来设置统计周期的重启时间,例如:每个月的第 3 天。选择“固定"
"期”来设置从给定日期开始每 N 天重启统计周期。"
"选择“每月的某一天”来设置统计周期的重启时间,例如:每个月的第 3 天。选择“固定"
"期”来设置从给定日期开始每 N 天重启统计周期。"
msgid "Commit interval"
msgstr "提交间隔"
@ -688,11 +696,8 @@ msgstr "提交间隔"
msgid "Compress database"
msgstr "压缩数据库"
msgid "Configuration"
msgstr "配置"
msgid "Conn."
msgstr "连接"
msgstr "连接。"
msgid "Connections"
msgstr "连接"
@ -716,8 +721,8 @@ msgid ""
"towards the end of month, e.g. \"-5\" to specify the 27th of July or the "
"24th of Februrary."
msgstr ""
"每个月重启统计周期的日期。使用负数表示从月底开始计算,例如:\"-5\" 可以表"
"7 月份的 27 号或者 2 月份的 24 号。"
"每个月重启统计周期的日期。使用负数表示从月底开始计算,例如:\"-5\" 可以表"
"7 月份的 27 号或者 2 月份的 24 号。"
msgid "Display"
msgstr "显示"
@ -750,7 +755,7 @@ msgid "Fixed interval"
msgstr "固定周期"
msgid "Force reload…"
msgstr "强制重新加载..."
msgstr "强制重新加载.."
msgid "General Settings"
msgstr "基本设置"
@ -767,9 +772,6 @@ msgstr "主机名:<big id=\"bubble-hostname\">example.org</big>"
msgid "IPv4 vs. IPv6"
msgstr "IPv4 与 IPv6"
msgid "IPv6"
msgstr "IPv6"
msgid "Interval"
msgstr "周期"
@ -830,9 +832,6 @@ msgstr "仅统计来自或目标为这些子网的连接流量。"
msgid "Preallocate database"
msgstr "预分配数据库"
msgid "Protocol"
msgstr "协议"
msgid "Protocol Mapping"
msgstr "协议映射"
@ -841,8 +840,8 @@ msgid ""
"line. The first value specifies the IP protocol, the second value the port "
"number and the third column is the name of the mapped protocol."
msgstr ""
"协议映射用于区分流量类型,每行一条。第一个值指定 IP 协议类型,第二个值是"
"端口号,第三个值是映射的协议名称。"
"协议映射用于区分流量类型,每行一条。第一个值指定 IP 协议类型,第二个值是端口"
"号,第三个值是映射的协议名称。"
msgid "Refresh interval"
msgstr "刷新间隔"
@ -872,8 +871,8 @@ msgid ""
"The Netlink Bandwidth Monitor (nlbwmon) is a lightweight, efficient traffic "
"accounting program keeping track of bandwidth usage per host and protocol."
msgstr ""
"网络带宽监视器nlbwmon是一个轻量、高效的流量统计程序可以统计每个主机和"
"议的带宽使用情况。"
"网络带宽监视器nlbwmon是一个轻量、高效的流量统计程序可以统计每个主机和"
"议的带宽使用情况。"
msgid "The following database files have been restored: %s"
msgstr "以下数据库文件已恢复:%s"
@ -926,15 +925,15 @@ msgstr "无流量数据"
msgid "other"
msgstr "其他"
msgid "Enable <abbr title=\"Internet Group Management Protocol\">IGMP</abbr> snooping"
msgstr "开启 <abbr title=\"Internet Group Management Protocol\">IGMP</abbr> snooping"
msgid ""
"Enable <abbr title=\"Internet Group Management Protocol\">IGMP</abbr> "
"snooping"
msgstr ""
"开启 <abbr title=\"Internet Group Management Protocol\">IGMP</abbr> snooping"
msgid "Enables IGMP snooping on this bridge"
msgstr "在此桥接上启用 IGMP snooping 组播(多播)"
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Action"
msgstr "动作"
@ -975,7 +974,7 @@ msgid "Reboot Device to an Alternative Partition"
msgstr "重启设备到备选分区"
msgid "Reboot to alternative partition..."
msgstr "重启到备选分区"
msgstr "重启到备选分区"
msgid "Reboot to current partition"
msgstr "重启到当前分区"
@ -995,6 +994,8 @@ msgid ""
"address of your computer to reach the device again, depending on your "
"settings."
msgstr ""
"系统正在重启。<br /> 请勿关闭设备电源!<br /> 请等待几分钟,然后再尝试重新连"
"接。根据您的设置,可能需要更新计算机的地址才能再次访问该设备。"
msgid ""
"The system is rebooting to an alternative partition now.<br /> DO NOT POWER "
@ -1002,12 +1003,16 @@ msgid ""
"might be necessary to renew the address of your computer to reach the device "
"again, depending on your settings."
msgstr ""
"系统正在重新引导到备用分区。<br /> 请勿关闭设备电源!<br /> 请等待几分钟,然"
"后再尝试重新连接。根据您的设置,可能需要更新计算机的地址才能再次访问该设备。"
msgid ""
"The system is shutting down now.<br /> DO NOT POWER OFF THE DEVICE!<br /> It "
"might be necessary to renew the address of your computer to reach the device "
"again, depending on your settings."
msgstr ""
"系统正在关闭。<br /> 请勿关闭设备电源!<br /> 根据您的设置,可能需要更新计算"
"机的地址才能再次访问该设备。"
msgid ""
"WARNING: An alternative partition might have its own settings and completely "
@ -1019,12 +1024,19 @@ msgid ""
"back to the currently active partition.<br /><br /> Click \"Proceed\" below "
"to reboot device to an alternative partition."
msgstr ""
"警告:备用分区可能具有自己的设置和完全不同的固件。<br /><br /> 由于备用分区上"
"的网络配置和WiFi SSID /密码可能有所不同,因此您可能必须调整计算机设置才能在设"
"备重启后访问设备。<br /><br /> 另请注意,备用分区固件可能无法提供切换活动分区"
"并引导回当前活动分区的简便方法。<br /><br /> 点击 \"继续\" 下面将设备重新引导"
"到备用分区。"
msgid ""
"WARNING: Power off might result in a reboot on a device which doesn't "
"support power off.<br /><br /> Click \"Proceed\" below to power off your "
"device."
msgstr ""
"警告: 关闭电源可能会导致不支持关闭电源的设备重新启动。<br /><br />单击下面的"
"\"继续\"以关闭设备电源。"
msgid "Warning: There are unsaved changes that will get lost on reboot!"
msgstr "警告:某些设置没有保存,重启将导致丢失这些配置!"

View File

@ -2,14 +2,14 @@ msgid ""
msgstr ""
"Project-Id-Version: luci-i18n-sqm\n"
"POT-Creation-Date: 2017-03-28 04:14+0800\n"
"PO-Revision-Date: 2017-03-28 04:15+0800\n"
"Last-Translator: \n"
"PO-Revision-Date: 2020-06-07 10:21+0800\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: player131 <player1311@gmail.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.10\n"
"X-Generator: Poedit 2.3.1\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Poedit-KeywordsList: translate\n"
@ -25,12 +25,9 @@ msgstr "智能队列管理"
#: usr/lib/lua/luci/model/cbi/sqm.lua:26
msgid ""
"With <abbr title=\"Smart Queue Management\">SQM</abbr> you can enable "
"traffic shaping, better mixing (Fair Queueing), active queue length "
"management (AQM) and prioritisation on one network interface."
msgstr ""
"使用 <abbr title=\"智能列队管理\">SQM</abbr> 你可以启用流量整形,更好的混合"
"(公平列队)主动列队管理(AQM) 并设置网络接口优先级。"
"With <abbr title=\"Smart Queue Management\">SQM</abbr> you can enable traffic shaping, better mixing (Fair Queueing), active queue length management "
"(AQM) and prioritisation on one network interface."
msgstr "使用 <abbr title=\"智能列队管理\">SQM</abbr> 你可以启用流量整形,更好的混合(公平列队)主动列队管理(AQM) 并设置网络接口优先级。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:32
msgid "Queues"
@ -50,57 +47,41 @@ msgstr "链路层适配"
#: usr/lib/lua/luci/model/cbi/sqm.lua:40
msgid "Enable this SQM instance."
msgstr "启用此SQM实例"
msgstr "启用此SQM实例"
#: usr/lib/lua/luci/model/cbi/sqm.lua:54
msgid ""
"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to "
"disable the sqm initscript manually under System Startup menu in case this "
"change was not wished for."
msgstr ""
"你刚刚开启了SQM随机启动功能如果你不希望SQM随机启动可以在系统启动菜单下手"
"动禁用。"
"The SQM GUI has just enabled the sqm initscript on your behalf. Remember to disable the sqm initscript manually under System Startup menu in case "
"this change was not wished for."
msgstr "你刚刚开启了SQM随机启动功能如果你不希望SQM随机启动可以在系统启动菜单下手动禁用。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:60
msgid "Interface name"
msgstr "接口名称"
#: usr/lib/lua/luci/model/cbi/sqm.lua:70
msgid ""
"Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress "
"shaping:"
msgid "Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress shaping:"
msgstr "下载速度(kbit/s)(入口)<br />设置为0关闭入口控制"
#: usr/lib/lua/luci/model/cbi/sqm.lua:74
msgid ""
"Upload speed (kbit/s) (egress) set to 0 to selectively disable egress "
"shaping:"
msgid "Upload speed (kbit/s) (egress) set to 0 to selectively disable egress shaping:"
msgstr "上传速度(kbit/s)(出口)<br />设置为0关闭出口控制"
#: usr/lib/lua/luci/model/cbi/sqm.lua:78
msgid ""
"Create log file for this SQM instance under /var/run/sqm/${Inerface_name}."
"debug.log. Make sure to delete log files manually."
msgstr ""
"创建日志文件到/var/run/sqm/<br />${Inerface_name}.debug.log。<br />请务必手动"
"删除日志文件。"
msgid "Create log file for this SQM instance under /var/run/sqm/${Inerface_name}.debug.log. Make sure to delete log files manually."
msgstr "创建日志文件到/var/run/sqm/<br />${Inerface_name}.debug.log。<br />请务必手动删除日志文件。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:82
msgid "Verbosity of SQM's output into the system log."
msgstr "SQM输出到系统日志的详细程度。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:86 usr/lib/lua/luci/model/cbi/sqm.lua:99
#: usr/lib/lua/luci/model/cbi/sqm.lua:148
#: usr/lib/lua/luci/model/cbi/sqm.lua:155
#: usr/lib/lua/luci/model/cbi/sqm.lua:202
#: usr/lib/lua/luci/model/cbi/sqm.lua:243
#: usr/lib/lua/luci/model/cbi/sqm.lua:86 usr/lib/lua/luci/model/cbi/sqm.lua:99 usr/lib/lua/luci/model/cbi/sqm.lua:148
#: usr/lib/lua/luci/model/cbi/sqm.lua:155 usr/lib/lua/luci/model/cbi/sqm.lua:202 usr/lib/lua/luci/model/cbi/sqm.lua:243
msgid "default"
msgstr "默认"
#: usr/lib/lua/luci/model/cbi/sqm.lua:98
msgid ""
"Queuing disciplines useable on this system. After installing a new qdisc, "
"you need to restart the router to see updates!"
msgid "Queuing disciplines useable on this system. After installing a new qdisc, you need to restart the router to see updates!"
msgstr "系统上可用的列队规则。安装新的队列规则后,重新启动路由器才会看到更新!"
#: usr/lib/lua/luci/model/cbi/sqm.lua:112
@ -108,9 +89,7 @@ msgid "Queue setup script"
msgstr "队列脚本设置"
#: usr/lib/lua/luci/model/cbi/sqm.lua:129
msgid ""
"Show and Use Advanced Configuration. Advanced options will only be used as "
"long as this box is checked."
msgid "Show and Use Advanced Configuration. Advanced options will only be used as long as this box is checked."
msgstr "选中该复选框显示高级配置。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:133
@ -119,22 +98,18 @@ msgstr "入站数据包压缩DSCP:"
#: usr/lib/lua/luci/model/cbi/sqm.lua:140
msgid "Ignore DSCP on ingress:"
msgstr "忽略入站DSCP"
msgstr "忽略入站DSCP"
#: usr/lib/lua/luci/model/cbi/sqm.lua:147
msgid ""
"Explicit congestion notification (ECN) status on inbound packets (ingress):"
msgstr "入站数据包的显式拥塞通知ECN状态"
msgid "Explicit congestion notification (ECN) status on inbound packets (ingress):"
msgstr "入站数据包的显式拥塞通知ECN状态"
#: usr/lib/lua/luci/model/cbi/sqm.lua:154
msgid ""
"Explicit congestion notification (ECN) status on outbound packets (egress)."
msgstr "出站数据包的显式拥塞通知ECN状态"
msgid "Explicit congestion notification (ECN) status on outbound packets (egress)."
msgstr "出站数据包的显式拥塞通知ECN状态。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:161
msgid ""
"Show and Use Dangerous Configuration. Dangerous options will only be used as "
"long as this box is checked."
msgid "Show and Use Dangerous Configuration. Dangerous options will only be used as long as this box is checked."
msgstr "选中该复选框显示危险配置。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:166
@ -154,16 +129,12 @@ msgid "Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty fo
msgstr "出站延迟目标,例如 5ms [单位: s, ms, 或 us]留空为自动选择default为列队规则默认值。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:192
msgid ""
"Advanced option string to pass to the ingress queueing disciplines; no error "
"checking, use very carefully."
msgstr "传递到入站队列规则的高级选项字符串;没有错误检查。请谨慎使用!"
msgid "Advanced option string to pass to the ingress queueing disciplines; no error checking, use very carefully."
msgstr "传递到入站队列规则的高级选项字符串;没有错误检查。请谨慎使用。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:196
msgid ""
"Advanced option string to pass to the egress queueing disciplines; no error "
"checking, use very carefully."
msgstr "传递到出站队列规则的高级选项字符串;没有错误检查。请谨慎使用!"
msgid "Advanced option string to pass to the egress queueing disciplines; no error checking, use very carefully."
msgstr "传递到出站队列规则的高级选项字符串;没有错误检查。请谨慎使用。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:201
msgid "Which link layer to account for:"
@ -171,31 +142,22 @@ msgstr "对哪个链路层生效:"
#: usr/lib/lua/luci/model/cbi/sqm.lua:207
msgid "Per Packet Overhead (byte):"
msgstr "每个数据包开销"
msgstr "每个数据包开销 (byte)"
#: usr/lib/lua/luci/model/cbi/sqm.lua:216
msgid ""
"Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced "
"options will only be used as long as this box is checked."
msgstr ""
"显示高级链路选项仅在MTU> 1500时才需要。 只有选中此框时,才会使用高级选"
"项。"
msgid "Show Advanced Linklayer Options, (only needed if MTU > 1500). Advanced options will only be used as long as this box is checked."
msgstr "显示高级链路选项仅在MTU> 1500时才需要。 只有选中此框时,才会使用高级选项。"
#: usr/lib/lua/luci/model/cbi/sqm.lua:221
msgid ""
"Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= "
"interface MTU + overhead:"
msgid "Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= interface MTU + overhead:"
msgstr "大小和速率计算的最大尺寸tcMTUbyte; 需要> =接口MTU +开销:"
#: usr/lib/lua/luci/model/cbi/sqm.lua:228
msgid ""
"Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU "
"+ 1) / 16:"
msgid "Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU + 1) / 16:"
msgstr "大小/速率表中的条目数TSIZE; 对于ATM选择TSIZE =tcMTU + 1/ 16"
#: usr/lib/lua/luci/model/cbi/sqm.lua:235
msgid ""
"Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:"
msgid "Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:"
msgstr "最小数据包大小MPUbyte; 在以太网中需要>0"
#: usr/lib/lua/luci/model/cbi/sqm.lua:242

View File

@ -1,3 +1,16 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "ADBYBY Plus +"
msgstr "广告屏蔽大师 Plus+"
@ -121,7 +134,6 @@ msgstr "内存运行模式"
msgid "Running Adbyby in RAM.More speed,less disk consumption"
msgstr "在内存中运行Adbyby。更快的速度更少的存储空间损耗"
msgid "User-defined Rule"
msgstr "用户自定义规则"
@ -129,7 +141,7 @@ msgid "<strong>Client Filter Mode Settings</strong>"
msgstr "<strong>客户端过滤模式设置</strong>"
msgid "Filter mode settings can be set to specific LAN clients ( <font color=blue> No filter , Global filter </font> ) . Does not need to be set by default."
msgstr "可以为局域网客户端分别设置不同的过滤模式 ( <font color=blue> 不过滤 , 全局过滤 </font> ) 。默认无需设置"
msgstr "可以为局域网客户端分别设置不同的过滤模式 ( <font color=blue> 不过滤 , 全局过滤 </font> ) 。默认无需设置"
msgid "IP Address"
msgstr "IP地址"
@ -150,7 +162,7 @@ msgid "!Will Always block these IP"
msgstr "拦截黑名单内的IP地址所有模式中生效"
msgid "Each line of the beginning exclamation mark is considered an annotation."
msgstr "每行一条规则,感叹号开头的被认为是注释"
msgstr "每行一条规则,感叹号开头的被认为是注释"
msgid "<strong><font color=blue>Adblock Plus Host List</font></strong>"
msgstr "<strong><font color=blue>Adblock Plus Host 列表:</font></strong>"
@ -171,10 +183,10 @@ msgid "Last Update Checked"
msgstr "上一次检查规则更新"
msgid "Lazy Rule"
msgstr "普通规则版本"
msgstr "正式版规则"
msgid "Video Rule"
msgstr "视频规则版本"
msgstr "测试版规则"
msgid "Adblock Plus Host List"
msgstr "广告屏蔽大师 Plus 规则列表"
@ -184,4 +196,3 @@ msgstr "域名黑名单"
msgid "Block IP List"
msgstr "IP黑名单"

View File

@ -1,3 +1,16 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "CPU Freq"
msgstr "CPU 性能优化调节"
@ -42,4 +55,3 @@ msgstr "CPU 切换周期"
msgid "The sampling rate determines how frequently the governor checks to tune the CPU (ms)"
msgstr "CPU 检查切换的周期 (ms) 。注意:过于频繁的切换频率会引起网络延迟抖动"

View File

@ -1,5 +1,15 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "Choose local file:"
msgstr "选择本地文件:"
@ -35,10 +45,10 @@ msgid "Modify time"
msgstr "修改时间"
msgid "No specify upload file."
msgstr "未指定上传文件"
msgstr "未指定上传文件"
msgid "Path on Route:"
msgstr "路由上目录"
msgstr "路由上目录"
msgid "Remove"
msgstr "移除"

View File

@ -1,3 +1,16 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "KodExplorer"
msgstr "可道云"
@ -56,7 +69,7 @@ msgid "Click to update"
msgstr "点击更新"
msgid "Updating..."
msgstr "更新中"
msgstr "更新中..."
msgid "Unexpected error"
msgstr "意外错误"
@ -65,13 +78,13 @@ msgid "Updating, are you sure to close?"
msgstr "正在更新,你确认要关闭吗?"
msgid "Downloading..."
msgstr "下载中"
msgstr "下载中..."
msgid "Unpacking..."
msgstr "解压中"
msgstr "解压中..."
msgid "Moving..."
msgstr "移动中"
msgstr "移动中..."
msgid "The latest version:"
msgstr "最新版本:"

View File

@ -2,16 +2,17 @@ msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-06-23 20:16+0800\n"
"PO-Revision-Date: 2015-06-23 20:17+0800\n"
"Last-Translator: coolsnowwolf <coolsnowwolf@gmail.com>\n"
"PO-Revision-Date: 2020-06-07 10:42+0800\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: PandoraBox Team\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.8.1\n"
"X-Generator: Poedit 2.3.1\n"
"X-Poedit-SourceCharset: UTF-8\n"
"Project-Id-Version: \n"
msgid "Music Remote Center"
msgstr "PCHiFi 数字转盘遥控"
@ -20,7 +21,7 @@ msgid "Open Web Interface"
msgstr "打开 Web 管理界面"
msgid "Music Remote Center is a DAAP (iTunes Remote), MPD (Music Player Daemon) and RSP (Roku) media server."
msgstr "PCHiFi 数字转盘遥控是一个基于 DAAP (iTunes Remote), MPD (Music Player Daemon) 和 RSP (Roku) media server 的服务器端播放器<br />后端输出支持 路由器本机声卡输出 /Airplay/ Chromecast"
msgstr "PCHiFi 数字转盘遥控是一个基于 DAAP (iTunes Remote), MPD (Music Player Daemon) 和 RSP (Roku) media server 的服务器端播放器<br />后端输出支持 路由器本机声卡输出 /Airplay/ Chromecast"
msgid "Database File Path"
msgstr "数据库文件路径"
@ -33,4 +34,3 @@ msgstr "使用须知"
msgid "About iOS Remote Pairing: <br />1. Open the web interface <br /> 2. Start iPhone Remote APP, go to Settings, Add Library<br />3. Enter the pair code in the web interface"
msgstr "关于 iOS 设备匹配: <br />1. 先打开 Web 管理界面,在 Setting 里面找到 Remotes & Outputs <br /> 2. 安装 iTunes 遥控器, 点击 手动连接,获取匹配码<br />3. 在 Remote Pairing 输入刚才获取的匹配码即可"

View File

@ -6,12 +6,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2019-01-03 22:28+0800\n"
"PO-Revision-Date: 2020-06-07 10:45+0800\n"
"Language-Team: <debian-l10n-chinese@lists.debian.org>\n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Gtranslator 3.30.1\n"
"Last-Translator: Yangfl <mmyangfl@gmail.com>\n"
"X-Generator: Poedit 2.3.1\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Language: zh_CN\n"
@ -23,7 +23,7 @@ msgstr "字节总数"
#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141
#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160
msgid "Collecting data..."
msgstr "正在收集数据"
msgstr "正在收集数据..."
#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224
msgid "Comment"

View File

@ -1,8 +1,21 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "PPPoE Relay"
msgstr "PPPoE 穿透"
msgid "Opening the PPPoE relay allows devices in the Intranet to create a separate PPPoE connection that can cross NAT."
msgstr "开启 PPPoE 中继允许内网中的设备创建一个可穿过 NAT 的独立 PPPoE 连接"
msgstr "开启 PPPoE 中继允许内网中的设备创建一个可穿过 NAT 的独立 PPPoE 连接"
msgid "Enable or disable the PPPoE Relay"
msgstr "启用或禁用PPPoE穿透"
@ -20,4 +33,4 @@ msgid "Specify the PPPoE client interface"
msgstr "指定PPPoE客户端接口"
msgid "Enabled"
msgstr "启用"
msgstr "启用"

View File

@ -3,18 +3,18 @@
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-10 03:40+0200\n"
"PO-Revision-Date: 2018-10-01 11:12+0800\n"
"Last-Translator: Yangfl <mmyangfl@gmail.com>\n"
"Language-Team: <debian-l10n-chinese@lists.debian.org>\n"
"PO-Revision-Date: 2020-06-07 11:21+0800\n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: <debian-l10n-chinese@lists.debian.org>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 2.91.7\n"
"X-Generator: Poedit 2.3.1\n"
#: applications/luci-app-samba4/luasrc/model/cbi/samba4.lua:78
msgid "Allow guests"
@ -66,7 +66,7 @@ msgstr "编辑模板"
#: applications/luci-app-samba4/luasrc/model/cbi/samba4.lua:34
msgid "Edit the template that is used for generating the samba configuration."
msgstr "编辑用来生成 samba 设置的模板"
msgstr "编辑用来生成 samba 设置的模板"
#: applications/luci-app-samba4/luasrc/model/cbi/samba4.lua:19
msgid "Enable macOS compatible shares"

View File

@ -1,16 +1,16 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-02-17 18:00+0800\n"\
"Last-Translator: Weijie Gao <hackpascal@gmail.com>\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Pootle 2.0.6\n"
"Language: zh_CN\n"
"X-Generator: Poedit 2.3.1\n"
msgid "NAS"
msgstr "网络存储"
@ -22,7 +22,7 @@ msgid "0 means no limitation"
msgstr "0 表明不限制"
msgid "A message will be displayed when entering a directory."
msgstr "在进入一个新目录时将显示的消息"
msgstr "在进入一个新目录时将显示的消息"
msgid "ASCII mode"
msgstr "ASCII 模式"
@ -233,4 +233,3 @@ msgstr "Pasv 模式最小端口"
msgid "Pasv Max Port"
msgstr "Pasv 模式最大端口"

View File

@ -5,6 +5,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: dingpengyu <dingpengyu06@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 2.3.1\n"
msgid "Web Admin"
msgstr "Web 管理"
@ -15,8 +21,8 @@ msgstr "Web 管理页面设置"
msgid "Web Admin Settings Page"
msgstr "设置更改Web管理页面端口绑定地址是否允许从互联网访问等"
msgid "HTTP listeners (address:port)""
msgstr "HTTP 监听 (IP地址:端口)""
msgid "HTTP listeners (address:port)\""
msgstr "HTTP 监听 (IP地址:端口)\""
msgid "Bind to specific interface:port (by specifying interface address"
msgstr "绑定到指定的IP地址:端口"
@ -38,4 +44,3 @@ msgstr "只允许内网访问"
msgid "Prevent access from private (RFC1918) IPs on an interface if it has an public IP address"
msgstr "拒绝从互联网访问Web管理页面"

View File

@ -65,7 +65,7 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=r8125
PKG_VERSION:=9.002.02
PKG_VERSION:=9.003.05
PKG_RELEASE:=1
#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2

View File

@ -37,8 +37,9 @@ CONFIG_DOWN_SPEED_100 = n
CONFIG_ASPM = y
ENABLE_S5WOL = y
ENABLE_S5_KEEP_CURR_MAC = n
ENABLE_EEE = n
ENABLE_EEE = y
ENABLE_S0_MAGIC_PACKET = n
ENABLE_TX_NO_CLOSE = y
ifneq ($(KERNELRELEASE),)
obj-m := r8125.o
@ -78,6 +79,9 @@ ifneq ($(KERNELRELEASE),)
ifeq ($(ENABLE_S0_MAGIC_PACKET), y)
EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
endif
ifeq ($(ENABLE_TX_NO_CLOSE), y)
EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE
endif
else
BASEDIR := /lib/modules/$(shell uname -r)
KERNELDIR ?= $(BASEDIR)/build

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@ -249,6 +249,14 @@ do { \
#define SUPPORTED_Asym_Pause (1 << 14)
#endif
#ifndef MDIO_EEE_100TX
#define MDIO_EEE_100TX 0x0002
#endif
#ifndef MDIO_EEE_1000T
#define MDIO_EEE_1000T 0x0004
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
#ifdef CONFIG_NET_POLL_CONTROLLER
#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll
@ -315,12 +323,12 @@ do { \
#define DASH_SUFFIX ""
#endif
#define RTL8125_VERSION "9.002.02" NAPI_SUFFIX DASH_SUFFIX
#define RTL8125_VERSION "9.003.05" NAPI_SUFFIX DASH_SUFFIX
#define MODULENAME "r8125"
#define PFX MODULENAME ": "
#define GPL_CLAIM "\
r8125 Copyright (C) 2019 Realtek NIC software team <nicfae@realtek.com> \n \
r8125 Copyright (C) 2020 Realtek NIC software team <nicfae@realtek.com> \n \
This program comes with ABSOLUTELY NO WARRANTY; for details, please see <http://www.gnu.org/licenses/>. \n \
This is free software, and you are welcome to redistribute it under certain conditions; see <http://www.gnu.org/licenses/>. \n"
@ -339,9 +347,6 @@ This is free software, and you are welcome to redistribute it under certain cond
#define R8125_MSG_DEFAULT \
(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
#define TX_BUFFS_AVAIL(tp) \
(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
#ifdef CONFIG_R8125_NAPI
#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb
#define rtl8125_rx_quota(count, quota) min(count, quota)
@ -417,13 +422,15 @@ This is free software, and you are welcome to redistribute it under certain cond
#define SHORT_PACKET_PADDING_BUF_SIZE 256
#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef
/* write/read MMIO register */
#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
#define RTL_R8(reg) readb (ioaddr + (reg))
#define RTL_R16(reg) readw (ioaddr + (reg))
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg))
#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg))
#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg))
#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg))
#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg))
#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg)))
#ifndef DMA_64BIT_MASK
#define DMA_64BIT_MASK 0xffffffffffffffffULL
@ -479,6 +486,10 @@ This is free software, and you are welcome to redistribute it under certain cond
#define RTK_ADVERTISE_2500FULL 0x80
/* Tx NO CLOSE */
#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000
#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF
/*****************************************************************************/
//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
@ -1099,6 +1110,9 @@ enum RTL8125_registers {
TIMER_INT1_8125 = 0x005C,
TIMER_INT2_8125 = 0x008C,
TIMER_INT3_8125 = 0x00F4,
EEE_TXIDLE_TIMER_8125 = 0x6048,
SW_TAIL_PTR0_8125 = 0x2800,
HW_CLO_PTR0_8125 = 0x2802,
};
enum RTL8125_register_content {
@ -1562,6 +1576,7 @@ struct rtl8125_private {
u8 ShortPacketSwChecksum;
u8 UseSwPaddingShortPkt;
u16 SwPaddingShortPktLen;
void *ShortPacketEmptyBuffer;
dma_addr_t ShortPacketEmptyBufferPhy;
@ -1576,6 +1591,10 @@ struct rtl8125_private {
u8 RequiredSecLanDonglePatch;
u8 RequirePhyMdiSwapPatch;
u8 RequireLSOPatch;
u32 HwFiberModeVer;
u32 HwFiberStat;
u8 HwSwitchMdiToFiber;
@ -1594,6 +1613,11 @@ struct rtl8125_private {
u32 HwPcieSNOffset;
u8 HwSuppTxNoCloseVer;
u8 EnableTxNoClose;
u32 NextHwDesCloPtr0;
u32 BeginHwDesCloPtr0;
//Dash+++++++++++++++++
u8 HwSuppDashVer;
u8 DASH;
@ -1683,6 +1707,9 @@ struct rtl8125_private {
//Realwow--------------
#endif //ENABLE_REALWOW_SUPPORT
u32 eee_adv_t;
u8 eee_enabled;
#ifdef ENABLE_R8125_PROCFS
//Procfs support
struct proc_dir_entry *proc_dir;
@ -1697,8 +1724,10 @@ enum eetype {
};
enum mcfg {
CFG_METHOD_2=0,
CFG_METHOD_2=2,
CFG_METHOD_3,
CFG_METHOD_4,
CFG_METHOD_5,
CFG_METHOD_MAX,
CFG_METHOD_DEFAULT = 0xFF
};
@ -1731,6 +1760,8 @@ enum mcfg {
//Ram Code Version
#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11)
#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33)
#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17)
#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b34)
//hwoptimize
#define HW_PATCH_SOC_LAN (BIT_0)
@ -1738,11 +1769,11 @@ enum mcfg {
void rtl8125_mdio_write(struct rtl8125_private *tp, u32 RegAddr, u32 value);
void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value);
void rtl8125_mdio_prot_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value);
void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value);
u32 rtl8125_mdio_read(struct rtl8125_private *tp, u32 RegAddr);
u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr);
u32 rtl8125_mdio_prot_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr);
void rtl8125_ephy_write(void __iomem *ioaddr, int RegAddr, int value);
u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr);
void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value);
void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value);
u16 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr);
void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask);
@ -1750,16 +1781,16 @@ void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask);
void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data);
void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd);
void rtl8125_init_ring_indexes(struct rtl8125_private *tp);
int rtl8125_eri_write(void __iomem *ioaddr, int addr, int len, u32 value, int type);
int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type);
void rtl8125_oob_mutex_lock(struct rtl8125_private *tp);
u32 rtl8125_mdio_read(struct rtl8125_private *tp, u32 RegAddr);
u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len);
u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address);
u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address);
u32 rtl8125_eri_read(void __iomem *ioaddr, int addr, int len, int type);
u32 rtl8125_eri_read_with_oob_base_address(void __iomem *ioaddr, int addr, int len, int type, u32 base_address);
int rtl8125_eri_write_with_oob_base_address(void __iomem *ioaddr, int addr, int len, u32 value, int type, u32 base_address);
u16 rtl8125_ephy_read(void __iomem *ioaddr, int RegAddr);
u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type);
u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address);
int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address);
u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr);
void rtl8125_wait_txrx_fifo_empty(struct net_device *dev);
void rtl8125_enable_now_is_oob(struct rtl8125_private *tp);
void rtl8125_disable_now_is_oob(struct rtl8125_private *tp);
@ -1771,6 +1802,7 @@ void rtl8125_dash2_enable_rx(struct rtl8125_private *tp);
void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev);
#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 )
#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
#define netdev_mc_count(dev) ((dev)->mc_count)

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@ -241,12 +241,12 @@ RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F
/* cmac write/read MMIO register */
#define RTL_CMAC_W8(reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W16(reg, val16) writew ((val16), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W32(reg, val32) writel ((val32), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R8(reg) readb (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R16(reg) readw (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R32(reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
void HandleDashInterrupt(struct net_device *dev);

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@ -52,18 +52,17 @@
//-------------------------------------------------------------------
void rtl8125_eeprom_type(struct rtl8125_private *tp)
{
void __iomem *ioaddr=tp->mmio_addr;
u16 magic = 0;
if (tp->mcfg == CFG_METHOD_DEFAULT)
goto out_no_eeprom;
if(RTL_R8(0xD2)&0x04) {
if(RTL_R8(tp, 0xD2)&0x04) {
//not support
//tp->eeprom_type = EEPROM_TWSI;
//tp->eeprom_len = 256;
goto out_no_eeprom;
} else if(RTL_R32(RxConfig) & RxCfg_9356SEL) {
} else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) {
tp->eeprom_type = EEPROM_TYPE_93C56;
tp->eeprom_len = 256;
} else {
@ -80,28 +79,28 @@ out_no_eeprom:
}
}
void rtl8125_eeprom_cleanup(void __iomem *ioaddr)
void rtl8125_eeprom_cleanup(struct rtl8125_private *tp)
{
u8 x;
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EECS);
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
rtl8125_raise_clock(&x, ioaddr);
rtl8125_lower_clock(&x, ioaddr);
rtl8125_raise_clock(tp, &x);
rtl8125_lower_clock(tp, &x);
}
int rtl8125_eeprom_cmd_done(void __iomem *ioaddr)
int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp)
{
u8 x;
int i;
rtl8125_stand_by(ioaddr);
rtl8125_stand_by(tp);
for (i = 0; i < 50000; i++) {
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
if (x & Cfg9346_EEDO) {
udelay(RTL_CLOCK_RATE * 2 * 3);
@ -119,7 +118,6 @@ int rtl8125_eeprom_cmd_done(void __iomem *ioaddr)
//-------------------------------------------------------------------
u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg)
{
void __iomem *ioaddr=tp->mmio_addr;
int addr_sz = 6;
u8 x;
u16 data;
@ -134,16 +132,16 @@ u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg)
addr_sz = 8;
x = Cfg9346_EEM1 | Cfg9346_EECS;
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
rtl8125_shift_out_bits(RTL_EEPROM_READ_OPCODE, 3, ioaddr);
rtl8125_shift_out_bits(reg, addr_sz, ioaddr);
rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3);
rtl8125_shift_out_bits(tp, reg, addr_sz);
data = rtl8125_shift_in_bits(ioaddr);
data = rtl8125_shift_in_bits(tp);
rtl8125_eeprom_cleanup(ioaddr);
rtl8125_eeprom_cleanup(tp);
RTL_W8(Cfg9346, 0);
RTL_W8(tp, Cfg9346, 0);
return data;
}
@ -154,7 +152,6 @@ u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg)
//-------------------------------------------------------------------
void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data)
{
void __iomem *ioaddr=tp->mmio_addr;
u8 x;
int addr_sz = 6;
int w_dummy_addr = 4;
@ -172,56 +169,56 @@ void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data)
}
x = Cfg9346_EEM1 | Cfg9346_EECS;
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
rtl8125_shift_out_bits(RTL_EEPROM_EWEN_OPCODE, 5, ioaddr);
rtl8125_shift_out_bits(reg, w_dummy_addr, ioaddr);
rtl8125_stand_by(ioaddr);
rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5);
rtl8125_shift_out_bits(tp, reg, w_dummy_addr);
rtl8125_stand_by(tp);
rtl8125_shift_out_bits(RTL_EEPROM_ERASE_OPCODE, 3, ioaddr);
rtl8125_shift_out_bits(reg, addr_sz, ioaddr);
if (rtl8125_eeprom_cmd_done(ioaddr) < 0) {
rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
rtl8125_shift_out_bits(tp, reg, addr_sz);
if (rtl8125_eeprom_cmd_done(tp) < 0) {
return;
}
rtl8125_stand_by(ioaddr);
rtl8125_stand_by(tp);
rtl8125_shift_out_bits(RTL_EEPROM_WRITE_OPCODE, 3, ioaddr);
rtl8125_shift_out_bits(reg, addr_sz, ioaddr);
rtl8125_shift_out_bits(data, 16, ioaddr);
if (rtl8125_eeprom_cmd_done(ioaddr) < 0) {
rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
rtl8125_shift_out_bits(tp, reg, addr_sz);
rtl8125_shift_out_bits(tp, data, 16);
if (rtl8125_eeprom_cmd_done(tp) < 0) {
return;
}
rtl8125_stand_by(ioaddr);
rtl8125_stand_by(tp);
rtl8125_shift_out_bits(RTL_EEPROM_EWDS_OPCODE, 5, ioaddr);
rtl8125_shift_out_bits(reg, w_dummy_addr, ioaddr);
rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
rtl8125_shift_out_bits(tp, reg, w_dummy_addr);
rtl8125_eeprom_cleanup(ioaddr);
RTL_W8(Cfg9346, 0);
rtl8125_eeprom_cleanup(tp);
RTL_W8(tp, Cfg9346, 0);
}
void rtl8125_raise_clock(u8 *x, void __iomem *ioaddr)
void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x)
{
*x = *x | Cfg9346_EESK;
RTL_W8(Cfg9346, *x);
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
}
void rtl8125_lower_clock(u8 *x, void __iomem *ioaddr)
void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x)
{
*x = *x & ~Cfg9346_EESK;
RTL_W8(Cfg9346, *x);
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
}
void rtl8125_shift_out_bits(int data, int count, void __iomem *ioaddr)
void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count)
{
u8 x;
int mask;
mask = 0x01 << (count - 1);
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
do {
@ -230,62 +227,62 @@ void rtl8125_shift_out_bits(int data, int count, void __iomem *ioaddr)
else
x &= ~Cfg9346_EEDI;
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
rtl8125_raise_clock(&x, ioaddr);
rtl8125_lower_clock(&x, ioaddr);
rtl8125_raise_clock(tp, &x);
rtl8125_lower_clock(tp, &x);
mask = mask >> 1;
} while(mask);
x &= ~Cfg9346_EEDI;
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
}
u16 rtl8125_shift_in_bits(void __iomem *ioaddr)
u16 rtl8125_shift_in_bits(struct rtl8125_private *tp)
{
u8 x;
u16 d, i;
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
d = 0;
for (i = 0; i < 16; i++) {
d = d << 1;
rtl8125_raise_clock(&x, ioaddr);
rtl8125_raise_clock(tp, &x);
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
x &= ~Cfg9346_EEDI;
if (x & Cfg9346_EEDO)
d |= 1;
rtl8125_lower_clock(&x, ioaddr);
rtl8125_lower_clock(tp, &x);
}
return d;
}
void rtl8125_stand_by(void __iomem *ioaddr)
void rtl8125_stand_by(struct rtl8125_private *tp)
{
u8 x;
x = RTL_R8(Cfg9346);
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EECS | Cfg9346_EESK);
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
x |= Cfg9346_EECS;
RTL_W8(Cfg9346, x);
RTL_W8(tp, Cfg9346, x);
}
void rtl8125_set_eeprom_sel_low(void __iomem *ioaddr)
void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp)
{
RTL_W8(Cfg9346, Cfg9346_EEM1);
RTL_W8(Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
udelay(20);
RTL_W8(Cfg9346, Cfg9346_EEM1);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
}

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@ -41,15 +41,12 @@
#define RTL_CLOCK_RATE 3
void rtl8125_eeprom_type(struct rtl8125_private *tp);
void rtl8125_eeprom_cleanup(void __iomem *ioaddr);
void rtl8125_eeprom_cleanup(struct rtl8125_private *tp);
u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg);
void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data);
void rtl8125_shift_out_bits(int data, int count, void __iomem *ioaddr);
u16 rtl8125_shift_in_bits(void __iomem *ioaddr);
void rtl8125_raise_clock(u8 *x, void __iomem *ioaddr);
void rtl8125_lower_clock(u8 *x, void __iomem *ioaddr);
void rtl8125_stand_by(void __iomem *ioaddr);
void rtl8125_set_eeprom_sel_low(void __iomem *ioaddr);
void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count);
u16 rtl8125_shift_in_bits(struct rtl8125_private *tp);
void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x);
void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x);
void rtl8125_stand_by(struct rtl8125_private *tp);
void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp);

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@ -121,7 +121,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
return -EPERM;
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8125_ephy_read(tp->mmio_addr, my_cmd.offset);
my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
@ -136,7 +136,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
return -EPERM;
spin_lock_irqsave(&tp->lock, flags);
rtl8125_ephy_write(tp->mmio_addr, my_cmd.offset, my_cmd.data);
rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
@ -144,7 +144,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
my_cmd.data = 0;
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8125_eri_read(tp->mmio_addr, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC);
my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC);
spin_unlock_irqrestore(&tp->lock, flags);
} else {
ret = -EOPNOTSUPP;
@ -167,7 +167,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
spin_lock_irqsave(&tp->lock, flags);
rtl8125_eri_write(tp->mmio_addr, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
spin_unlock_irqrestore(&tp->lock, flags);
} else {
ret = -EOPNOTSUPP;
@ -330,7 +330,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
return -EPERM;
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8125_mdio_prot_read_phy_ocp(tp, my_cmd.offset);
my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
@ -345,7 +345,7 @@ int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr)
return -EPERM;
spin_lock_irqsave(&tp->lock, flags);
rtl8125_mdio_prot_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;

View File

@ -4,7 +4,7 @@
# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2019 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2020 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@ -0,0 +1,19 @@
menuconfig MIKROTIK
bool "Platform support for MikroTik RouterBoard virtual devices"
default n
help
Say Y here to get to see options for the MikroTik RouterBoard platform.
This option alone does not add any kernel code.
if MIKROTIK
config MIKROTIK_RB_SYSFS
tristate "RouterBoot sysfs support"
depends on MTD
select LZO_DECOMPRESS
select CRC32
help
This driver exposes RouterBoot configuration in sysfs.
endif # MIKROTIK

View File

@ -0,0 +1,4 @@
#
# Makefile for MikroTik RouterBoard platform specific drivers
#
obj-$(CONFIG_MIKROTIK_RB_SYSFS) += routerboot.o rb_hardconfig.o rb_softconfig.o

View File

@ -0,0 +1,744 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for MikroTik RouterBoot hard config.
*
* Copyright (C) 2020 Thibaut VARÈNE <hacks+kernel@slashdirt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This driver exposes the data encoded in the "hard_config" flash segment of
* MikroTik RouterBOARDs devices. It presents the data in a sysfs folder
* named "hard_config". The WLAN calibration data is available on demand via
* the 'wlan_data' sysfs file in that folder.
*
* This driver permanently allocates a chunk of RAM as large as the hard_config
* MTD partition, although it is technically possible to operate entirely from
* the MTD device without using a local buffer (except when requesting WLAN
* calibration data), at the cost of a performance penalty.
*
* Note: PAGE_SIZE is assumed to be >= 4K, hence the device attribute show
* routines need not check for output overflow.
*
* Some constant defines extracted from routerboot.{c,h} by Gabor Juhos
* <juhosg@openwrt.org>
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kobject.h>
#include <linux/bitops.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/sysfs.h>
#include <linux/lzo.h>
#include "routerboot.h"
#define RB_HARDCONFIG_VER "0.04"
#define RB_HC_PR_PFX "[rb_hardconfig] "
/* ID values for hardware settings */
#define RB_ID_FLASH_INFO 0x03
#define RB_ID_MAC_ADDRESS_PACK 0x04
#define RB_ID_BOARD_PRODUCT_CODE 0x05
#define RB_ID_BIOS_VERSION 0x06
#define RB_ID_SDRAM_TIMINGS 0x08
#define RB_ID_DEVICE_TIMINGS 0x09
#define RB_ID_SOFTWARE_ID 0x0A
#define RB_ID_SERIAL_NUMBER 0x0B
#define RB_ID_MEMORY_SIZE 0x0D
#define RB_ID_MAC_ADDRESS_COUNT 0x0E
#define RB_ID_HW_OPTIONS 0x15
#define RB_ID_WLAN_DATA 0x16
#define RB_ID_BOARD_IDENTIFIER 0x17
#define RB_ID_PRODUCT_NAME 0x21
#define RB_ID_DEFCONF 0x26
/* Bit definitions for hardware options */
#define RB_HW_OPT_NO_UART BIT(0)
#define RB_HW_OPT_HAS_VOLTAGE BIT(1)
#define RB_HW_OPT_HAS_USB BIT(2)
#define RB_HW_OPT_HAS_ATTINY BIT(3)
#define RB_HW_OPT_PULSE_DUTY_CYCLE BIT(9)
#define RB_HW_OPT_NO_NAND BIT(14)
#define RB_HW_OPT_HAS_LCD BIT(15)
#define RB_HW_OPT_HAS_POE_OUT BIT(16)
#define RB_HW_OPT_HAS_uSD BIT(17)
#define RB_HW_OPT_HAS_SIM BIT(18)
#define RB_HW_OPT_HAS_SFP BIT(20)
#define RB_HW_OPT_HAS_WIFI BIT(21)
#define RB_HW_OPT_HAS_TS_FOR_ADC BIT(22)
#define RB_HW_OPT_HAS_PLC BIT(29)
static struct kobject *hc_kobj;
static u8 *hc_buf; // ro buffer after init(): no locking required
static size_t hc_buflen;
/*
* For LZOR style WLAN data unpacking.
* This binary blob is prepended to the data encoded on some devices as
* RB_ID_WLAN_DATA, the result is then first decompressed with LZO, and then
* finally RLE-decoded.
* This binary blob has been extracted from RouterOS by
* https://forum.openwrt.org/u/ius
*/
static const u8 hc_lzor_prefix[] = {
0x00, 0x05, 0x4c, 0x4c, 0x44, 0x00, 0x34, 0xfe,
0xfe, 0x34, 0x11, 0x3c, 0x1e, 0x3c, 0x2e, 0x3c,
0x4c, 0x34, 0x00, 0x52, 0x62, 0x92, 0xa2, 0xb2,
0xc3, 0x2a, 0x14, 0x00, 0x00, 0x05, 0xfe, 0x6a,
0x3c, 0x16, 0x32, 0x16, 0x11, 0x1e, 0x12, 0x46,
0x32, 0x46, 0x11, 0x4e, 0x12, 0x36, 0x32, 0x36,
0x11, 0x3e, 0x12, 0x5a, 0x9a, 0x64, 0x00, 0x04,
0xfe, 0x10, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x28,
0x0c, 0x00, 0x0f, 0xfe, 0x14, 0x00, 0x24, 0x24,
0x23, 0x24, 0x24, 0x23, 0x25, 0x22, 0x21, 0x21,
0x23, 0x22, 0x21, 0x22, 0x21, 0x2d, 0x38, 0x00,
0x0c, 0x25, 0x25, 0x24, 0x25, 0x25, 0x24, 0x23,
0x22, 0x21, 0x20, 0x23, 0x21, 0x21, 0x22, 0x21,
0x2d, 0x38, 0x00, 0x28, 0xb0, 0x00, 0x00, 0x22,
0x00, 0x00, 0xc0, 0xfe, 0x03, 0x00, 0xc0, 0x00,
0x62, 0xff, 0x62, 0xff, 0xfe, 0x06, 0x00, 0xbb,
0xff, 0xba, 0xff, 0xfe, 0x08, 0x00, 0x9e, 0xff,
0xfe, 0x0a, 0x00, 0x53, 0xff, 0xfe, 0x02, 0x00,
0x20, 0xff, 0xb1, 0xfe, 0xfe, 0xb2, 0xfe, 0xfe,
0xed, 0xfe, 0xfe, 0xfe, 0x04, 0x00, 0x3a, 0xff,
0x3a, 0xff, 0xde, 0xfd, 0x5f, 0x04, 0x33, 0xff,
0x4c, 0x74, 0x03, 0x05, 0x05, 0xff, 0x6d, 0xfe,
0xfe, 0x6d, 0xfe, 0xfe, 0xaf, 0x08, 0x63, 0xff,
0x64, 0x6f, 0x08, 0xac, 0xff, 0xbf, 0x6d, 0x08,
0x7a, 0x6d, 0x08, 0x96, 0x74, 0x04, 0x00, 0x08,
0x79, 0xff, 0xda, 0xfe, 0xfe, 0xdb, 0xfe, 0xfe,
0x56, 0xff, 0xfe, 0x04, 0x00, 0x5e, 0xff, 0x5e,
0xff, 0x6c, 0xfe, 0xfe, 0xfe, 0x06, 0x00, 0x41,
0xff, 0x7f, 0x74, 0x03, 0x00, 0x11, 0x44, 0xff,
0xa9, 0xfe, 0xfe, 0xa9, 0xfe, 0xfe, 0xa5, 0x8f,
0x01, 0x00, 0x08, 0x01, 0x01, 0x02, 0x04, 0x08,
0x02, 0x04, 0x08, 0x08, 0x01, 0x01, 0xfe, 0x22,
0x00, 0x4c, 0x60, 0x64, 0x8c, 0x90, 0xd0, 0xd4,
0xd8, 0x5c, 0x10, 0x09, 0xd8, 0xff, 0xb0, 0xff,
0x00, 0x00, 0xba, 0xff, 0x14, 0x00, 0xba, 0xff,
0x64, 0x00, 0x00, 0x08, 0xfe, 0x06, 0x00, 0x74,
0xff, 0x42, 0xff, 0xce, 0xff, 0x60, 0xff, 0x0a,
0x00, 0xb4, 0x00, 0xa0, 0x00, 0xa0, 0xfe, 0x07,
0x00, 0x0a, 0x00, 0xb0, 0xff, 0x96, 0x4d, 0x00,
0x56, 0x57, 0x18, 0xa6, 0xff, 0x92, 0x70, 0x11,
0x00, 0x12, 0x90, 0x90, 0x76, 0x5a, 0x54, 0x54,
0x4c, 0x46, 0x38, 0x00, 0x10, 0x10, 0x08, 0xfe,
0x05, 0x00, 0x38, 0x29, 0x25, 0x23, 0x22, 0x22,
0x1f, 0x00, 0x00, 0x00, 0xf6, 0xe1, 0xdd, 0xf8,
0xfe, 0x00, 0xfe, 0x15, 0x00, 0x00, 0xd0, 0x02,
0x74, 0x02, 0x08, 0xf8, 0xe5, 0xde, 0x02, 0x04,
0x04, 0xfd, 0x00, 0x00, 0x00, 0x07, 0x50, 0x2d,
0x01, 0x90, 0x90, 0x76, 0x60, 0xb0, 0x07, 0x07,
0x0c, 0x0c, 0x04, 0xfe, 0x05, 0x00, 0x66, 0x66,
0x5a, 0x56, 0xbc, 0x01, 0x06, 0xfc, 0xfc, 0xf1,
0xfe, 0x07, 0x00, 0x24, 0x95, 0x70, 0x64, 0x18,
0x06, 0x2c, 0xff, 0xb5, 0xfe, 0xfe, 0xb5, 0xfe,
0xfe, 0xe2, 0x8c, 0x24, 0x02, 0x2f, 0xff, 0x2f,
0xff, 0xb4, 0x78, 0x02, 0x05, 0x73, 0xff, 0xed,
0xfe, 0xfe, 0x4f, 0xff, 0x36, 0x74, 0x1e, 0x09,
0x4f, 0xff, 0x50, 0xff, 0xfe, 0x16, 0x00, 0x70,
0xac, 0x70, 0x8e, 0xac, 0x40, 0x0e, 0x01, 0x70,
0x7f, 0x8e, 0xac, 0x6c, 0x00, 0x0b, 0xfe, 0x02,
0x00, 0xfe, 0x0a, 0x2c, 0x2a, 0x2a, 0x28, 0x26,
0x1e, 0x1e, 0xfe, 0x02, 0x20, 0x65, 0x20, 0x00,
0x00, 0x05, 0x12, 0x00, 0x11, 0x1e, 0x11, 0x11,
0x41, 0x1e, 0x41, 0x11, 0x31, 0x1e, 0x31, 0x11,
0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
0x98, 0x30, 0x20, 0x00, 0x02, 0x00, 0xfe, 0x06,
0x3c, 0xbc, 0x32, 0x0c, 0x00, 0x00, 0x2a, 0x12,
0x1e, 0x12, 0x2e, 0x12, 0xcc, 0x12, 0x11, 0x1a,
0x1e, 0x1a, 0x2e, 0x1a, 0x4c, 0x10, 0x1e, 0x10,
0x11, 0x18, 0x1e, 0x42, 0x1e, 0x42, 0x2e, 0x42,
0xcc, 0x42, 0x11, 0x4a, 0x1e, 0x4a, 0x2e, 0x4a,
0x4c, 0x40, 0x1e, 0x40, 0x11, 0x48, 0x1e, 0x32,
0x1e, 0x32, 0x2e, 0x32, 0xcc, 0x32, 0x11, 0x3a,
0x1e, 0x3a, 0x2e, 0x3a, 0x4c, 0x30, 0x1e, 0x30,
0x11, 0x38, 0x1e, 0x27, 0x9a, 0x01, 0x9d, 0xa2,
0x2f, 0x28, 0x00, 0x00, 0x46, 0xde, 0xc4, 0xbf,
0xa6, 0x9d, 0x81, 0x7b, 0x5c, 0x61, 0x40, 0xc7,
0xc0, 0xae, 0xa9, 0x8c, 0x83, 0x6a, 0x62, 0x50,
0x3e, 0xce, 0xc2, 0xae, 0xa3, 0x8c, 0x7b, 0x6a,
0x5a, 0x50, 0x35, 0xd7, 0xc2, 0xb7, 0xa4, 0x95,
0x7e, 0x72, 0x5a, 0x59, 0x37, 0xfe, 0x02, 0xf8,
0x8c, 0x95, 0x90, 0x8f, 0x00, 0xd7, 0xc0, 0xb7,
0xa2, 0x95, 0x7b, 0x72, 0x56, 0x59, 0x32, 0xc7,
0xc3, 0xae, 0xad, 0x8c, 0x85, 0x6a, 0x63, 0x50,
0x3e, 0xce, 0xc3, 0xae, 0xa4, 0x8c, 0x7c, 0x6a,
0x59, 0x50, 0x34, 0xd7, 0xc2, 0xb7, 0xa5, 0x95,
0x7e, 0x72, 0x59, 0x59, 0x36, 0xfc, 0x05, 0x00,
0x02, 0xce, 0xc5, 0xae, 0xa5, 0x95, 0x83, 0x72,
0x5c, 0x59, 0x36, 0xbf, 0xc6, 0xa5, 0xab, 0x8c,
0x8c, 0x6a, 0x67, 0x50, 0x41, 0x64, 0x07, 0x00,
0x02, 0x95, 0x8c, 0x72, 0x65, 0x59, 0x3f, 0xce,
0xc7, 0xae, 0xa8, 0x95, 0x86, 0x72, 0x5f, 0x59,
0x39, 0xfe, 0x02, 0xf8, 0x8b, 0x7c, 0x0b, 0x09,
0xb7, 0xc2, 0x9d, 0xa4, 0x83, 0x85, 0x6a, 0x6b,
0x50, 0x44, 0xb7, 0xc1, 0x64, 0x01, 0x00, 0x06,
0x61, 0x5d, 0x48, 0x3d, 0xae, 0xc4, 0x9d, 0xad,
0x7b, 0x85, 0x61, 0x66, 0x48, 0x46, 0xae, 0xc3,
0x95, 0xa3, 0x72, 0x7c, 0x59, 0x56, 0x38, 0x31,
0x7c, 0x0b, 0x00, 0x0c, 0x96, 0x91, 0x8f, 0x00,
0xb7, 0xc0, 0xa5, 0xab, 0x8c, 0x8a, 0x6a, 0x64,
0x50, 0x3c, 0xb7, 0xc0, 0x9d, 0xa0, 0x83, 0x80,
0x6a, 0x64, 0x50, 0x3d, 0xb7, 0xc5, 0x9d, 0xa5,
0x83, 0x87, 0x6c, 0x08, 0x07, 0xae, 0xc0, 0x9d,
0xa8, 0x83, 0x88, 0x6a, 0x6d, 0x50, 0x46, 0xfc,
0x05, 0x00, 0x16, 0xbf, 0xc0, 0xa5, 0xa2, 0x8c,
0x7f, 0x6a, 0x57, 0x50, 0x2f, 0xb7, 0xc7, 0xa5,
0xb1, 0x8c, 0x8e, 0x72, 0x6d, 0x59, 0x45, 0xbf,
0xc6, 0xa5, 0xa8, 0x8c, 0x87, 0x6a, 0x5f, 0x50,
0x37, 0xbf, 0xc2, 0xa5, 0xa4, 0x8c, 0x83, 0x6a,
0x5c, 0x50, 0x34, 0xbc, 0x05, 0x00, 0x0e, 0x90,
0x00, 0xc7, 0xc2, 0xae, 0xaa, 0x95, 0x82, 0x7b,
0x60, 0x61, 0x3f, 0xb7, 0xc6, 0xa5, 0xb1, 0x8c,
0x8d, 0x72, 0x6b, 0x61, 0x51, 0xbf, 0xc4, 0xa5,
0xa5, 0x8c, 0x82, 0x72, 0x61, 0x59, 0x39, 0x6c,
0x26, 0x03, 0x95, 0x82, 0x7b, 0x61, 0x61, 0x40,
0xfc, 0x05, 0x00, 0x00, 0x7e, 0xd7, 0xc3, 0xb7,
0xa8, 0x9d, 0x80, 0x83, 0x5d, 0x6a, 0x3f, 0xbf,
0xc7, 0xa5, 0xa8, 0x8c, 0x84, 0x72, 0x60, 0x61,
0x46, 0xbf, 0xc2, 0xae, 0xb0, 0x9d, 0x92, 0x83,
0x6f, 0x6a, 0x50, 0xd7, 0xc3, 0xb7, 0xa7, 0x9d,
0x80, 0x83, 0x5e, 0x6a, 0x40, 0xfe, 0x02, 0xf8,
0x8d, 0x96, 0x90, 0x90, 0xfe, 0x05, 0x00, 0x8a,
0xc4, 0x63, 0xb8, 0x3c, 0xa6, 0x29, 0x97, 0x16,
0x81, 0x84, 0xb7, 0x5b, 0xa9, 0x33, 0x94, 0x1e,
0x83, 0x11, 0x70, 0xb8, 0xc2, 0x70, 0xb1, 0x4d,
0xa3, 0x2a, 0x8d, 0x1b, 0x7b, 0xa8, 0xbc, 0x68,
0xab, 0x47, 0x9d, 0x27, 0x87, 0x18, 0x75, 0xae,
0xc6, 0x7d, 0xbb, 0x4d, 0xaa, 0x1c, 0x84, 0x11,
0x72, 0xa3, 0xbb, 0x6e, 0xad, 0x3c, 0x97, 0x24,
0x85, 0x16, 0x71, 0x80, 0xb2, 0x57, 0xa4, 0x30,
0x8e, 0x1c, 0x7c, 0x10, 0x68, 0xbb, 0xbd, 0x75,
0xac, 0x4f, 0x9e, 0x2b, 0x87, 0x1a, 0x76, 0x96,
0xc5, 0x5e, 0xb5, 0x3e, 0xa5, 0x1f, 0x8c, 0x12,
0x7a, 0xc1, 0xc6, 0x42, 0x9f, 0x27, 0x8c, 0x16,
0x77, 0x0f, 0x67, 0x9d, 0xbc, 0x68, 0xad, 0x36,
0x95, 0x20, 0x83, 0x11, 0x6d, 0x9b, 0xb8, 0x67,
0xa8, 0x34, 0x90, 0x1f, 0x7c, 0x10, 0x67, 0x9e,
0xc9, 0x6a, 0xbb, 0x37, 0xa4, 0x20, 0x90, 0x11,
0x7b, 0xc6, 0xc8, 0x47, 0xa4, 0x2a, 0x90, 0x18,
0x7b, 0x10, 0x6c, 0xae, 0xc4, 0x5d, 0xad, 0x37,
0x9a, 0x1f, 0x85, 0x13, 0x75, 0x70, 0xad, 0x42,
0x99, 0x25, 0x84, 0x17, 0x74, 0x0b, 0x56, 0x87,
0xc8, 0x57, 0xb8, 0x2b, 0x9e, 0x19, 0x8a, 0x0d,
0x74, 0xa7, 0xc8, 0x6e, 0xb9, 0x36, 0xa0, 0x1f,
0x8b, 0x11, 0x75, 0x94, 0xbe, 0x4b, 0xa5, 0x2a,
0x92, 0x18, 0x7c, 0x0f, 0x6b, 0xaf, 0xc0, 0x58,
0xa8, 0x34, 0x94, 0x1d, 0x7d, 0x12, 0x6d, 0x82,
0xc0, 0x52, 0xb0, 0x25, 0x94, 0x14, 0x7f, 0x0c,
0x68, 0x84, 0xbf, 0x3e, 0xa4, 0x22, 0x8e, 0x10,
0x76, 0x0b, 0x65, 0x88, 0xb6, 0x42, 0x9b, 0x26,
0x87, 0x14, 0x70, 0x0c, 0x5f, 0xc5, 0xc2, 0x3e,
0x97, 0x23, 0x83, 0x13, 0x6c, 0x0c, 0x5c, 0xb1,
0xc9, 0x76, 0xbc, 0x4a, 0xaa, 0x20, 0x8d, 0x12,
0x78, 0x93, 0xbf, 0x46, 0xa3, 0x26, 0x8d, 0x14,
0x74, 0x0c, 0x62, 0xc8, 0xc4, 0x3b, 0x97, 0x21,
0x82, 0x11, 0x6a, 0x0a, 0x59, 0xa3, 0xb9, 0x68,
0xa9, 0x30, 0x8d, 0x1a, 0x78, 0x0f, 0x61, 0xa0,
0xc9, 0x73, 0xbe, 0x50, 0xb1, 0x30, 0x9f, 0x14,
0x80, 0x83, 0xb7, 0x3c, 0x9a, 0x20, 0x84, 0x0e,
0x6a, 0x0a, 0x57, 0xac, 0xc2, 0x68, 0xb0, 0x2e,
0x92, 0x19, 0x7c, 0x0d, 0x63, 0x93, 0xbe, 0x62,
0xb0, 0x3c, 0x9e, 0x1a, 0x80, 0x0e, 0x6b, 0xbb,
0x02, 0xa0, 0x02, 0xa0, 0x02, 0x6f, 0x00, 0x75,
0x00, 0x75, 0x00, 0x00, 0x00, 0xad, 0x02, 0xb3,
0x02, 0x6f, 0x00, 0x87, 0x00, 0x85, 0xfe, 0x03,
0x00, 0xc2, 0x02, 0x82, 0x4d, 0x92, 0x6e, 0x4d,
0xb1, 0xa8, 0x84, 0x01, 0x00, 0x07, 0x7e, 0x00,
0xa8, 0x02, 0xa4, 0x02, 0xa4, 0x02, 0xa2, 0x00,
0xa6, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xb4, 0x02,
0xb4, 0x02, 0x92, 0x00, 0x96, 0x00, 0x96, 0x46,
0x04, 0xb0, 0x02, 0x64, 0x02, 0x0a, 0x8c, 0x00,
0x90, 0x02, 0x98, 0x02, 0x98, 0x02, 0x0e, 0x01,
0x11, 0x01, 0x11, 0x50, 0xc3, 0x08, 0x88, 0x02,
0x88, 0x02, 0x19, 0x01, 0x02, 0x01, 0x02, 0x01,
0xf3, 0x2d, 0x00, 0x00
};
/* Array of known hw_options bits with human-friendly parsing */
static struct hc_hwopt {
const u32 bit;
const char *str;
} const hc_hwopts[] = {
{
.bit = RB_HW_OPT_NO_UART,
.str = "no UART\t\t",
}, {
.bit = RB_HW_OPT_HAS_VOLTAGE,
.str = "has Vreg\t",
}, {
.bit = RB_HW_OPT_HAS_USB,
.str = "has usb\t\t",
}, {
.bit = RB_HW_OPT_HAS_ATTINY,
.str = "has ATtiny\t",
}, {
.bit = RB_HW_OPT_NO_NAND,
.str = "no NAND\t\t",
}, {
.bit = RB_HW_OPT_HAS_LCD,
.str = "has LCD\t\t",
}, {
.bit = RB_HW_OPT_HAS_POE_OUT,
.str = "has POE out\t",
}, {
.bit = RB_HW_OPT_HAS_uSD,
.str = "has MicroSD\t",
}, {
.bit = RB_HW_OPT_HAS_SIM,
.str = "has SIM\t\t",
}, {
.bit = RB_HW_OPT_HAS_SFP,
.str = "has SFP\t\t",
}, {
.bit = RB_HW_OPT_HAS_WIFI,
.str = "has WiFi\t",
}, {
.bit = RB_HW_OPT_HAS_TS_FOR_ADC,
.str = "has TS ADC\t",
}, {
.bit = RB_HW_OPT_HAS_PLC,
.str = "has PLC\t\t",
},
};
/*
* The MAC is stored network-endian on all devices, in 2 32-bit segments:
* <XX:XX:XX:XX> <XX:XX:00:00>. Kernel print has us covered.
*/
static ssize_t hc_tag_show_mac(const u8 *pld, u16 pld_len, char *buf)
{
if (8 != pld_len)
return -EINVAL;
return sprintf(buf, "%pM\n", pld);
}
/*
* Print HW options in a human readable way:
* The raw number and in decoded form
*/
static ssize_t hc_tag_show_hwoptions(const u8 *pld, u16 pld_len, char *buf)
{
char *out = buf;
u32 data; // cpu-endian
int i;
if (sizeof(data) != pld_len)
return -EINVAL;
data = *(u32 *)pld;
out += sprintf(out, "raw\t\t: 0x%08x\n\n", data);
for (i = 0; i < ARRAY_SIZE(hc_hwopts); i++)
out += sprintf(out, "%s: %s\n", hc_hwopts[i].str,
(data & hc_hwopts[i].bit) ? "true" : "false");
return out - buf;
}
static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count);
static struct hc_wlan_attr {
struct bin_attribute battr;
u16 pld_ofs;
u16 pld_len;
} hc_wlandata_battr = {
.battr = __BIN_ATTR(wlan_data, S_IRUSR, hc_wlan_data_bin_read, NULL, 0),
};
static ssize_t hc_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
/* Array of known tags to publish in sysfs */
static struct hc_attr {
const u16 tag_id;
ssize_t (* const tshow)(const u8 *pld, u16 pld_len, char *buf);
struct kobj_attribute kattr;
u16 pld_ofs;
u16 pld_len;
} hc_attrs[] = {
{
.tag_id = RB_ID_FLASH_INFO,
.tshow = routerboot_tag_show_u32s,
.kattr = __ATTR(flash_info, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_MAC_ADDRESS_PACK,
.tshow = hc_tag_show_mac,
.kattr = __ATTR(mac_base, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_BOARD_PRODUCT_CODE,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(board_product_code, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_BIOS_VERSION,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(booter_version, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_SERIAL_NUMBER,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(board_serial, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_MEMORY_SIZE,
.tshow = routerboot_tag_show_u32s,
.kattr = __ATTR(mem_size, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_MAC_ADDRESS_COUNT,
.tshow = routerboot_tag_show_u32s,
.kattr = __ATTR(mac_count, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_HW_OPTIONS,
.tshow = hc_tag_show_hwoptions,
.kattr = __ATTR(hw_options, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_WLAN_DATA,
.tshow = NULL,
}, {
.tag_id = RB_ID_BOARD_IDENTIFIER,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(board_identifier, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_PRODUCT_NAME,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(product_name, S_IRUSR, hc_attr_show, NULL),
}, {
.tag_id = RB_ID_DEFCONF,
.tshow = routerboot_tag_show_string,
.kattr = __ATTR(defconf, S_IRUSR, hc_attr_show, NULL),
}
};
/*
* If the RB_ID_WLAN_DATA payload starts with RB_MAGIC_ERD, then past
* that magic number the payload itself contains a routerboot tag node
* locating the LZO-compressed calibration data at id 0x1.
*/
static int hc_wlan_data_unpack_erd(const u8 *inbuf, size_t inlen,
void *outbuf, size_t *outlen)
{
u16 lzo_ofs, lzo_len;
int ret;
/* Find embedded tag */
ret = routerboot_tag_find(inbuf, inlen, 0x1, // always id 1
&lzo_ofs, &lzo_len);
if (ret) {
pr_debug(RB_HC_PR_PFX "ERD data not found\n");
goto fail;
}
if (lzo_len > inlen) {
pr_debug(RB_HC_PR_PFX "Invalid ERD data length\n");
ret = -EINVAL;
goto fail;
}
ret = lzo1x_decompress_safe(inbuf+lzo_ofs, lzo_len, outbuf, outlen);
if (ret)
pr_debug(RB_HC_PR_PFX "LZO decompression error (%d)\n", ret);
fail:
return ret;
}
/*
* If the RB_ID_WLAN_DATA payload starts with RB_MAGIC_LZOR, then past
* that magic number is a payload that must be appended to the hc_lzor_prefix,
* the resulting blob is LZO-compressed. In the LZO decompression result,
* the RB_MAGIC_ERD magic number (aligned) must be located. Following that
* magic, there is a routerboot tag node (id 0x1) locating the RLE-encoded
* calibration data payload.
*/
static int hc_wlan_data_unpack_lzor(const u8 *inbuf, size_t inlen,
void *outbuf, size_t *outlen)
{
u16 rle_ofs, rle_len;
const u32 *needle;
u8 *tempbuf;
size_t templen, lzo_len;
int ret;
lzo_len = inlen + sizeof(hc_lzor_prefix);
if (lzo_len > *outlen)
return -EFBIG;
/* Temporary buffer same size as the outbuf */
templen = *outlen;
tempbuf = kmalloc(templen, GFP_KERNEL);
if (!outbuf)
return -ENOMEM;
/* Concatenate into the outbuf */
memcpy(outbuf, hc_lzor_prefix, sizeof(hc_lzor_prefix));
memcpy(outbuf + sizeof(hc_lzor_prefix), inbuf, inlen);
/* LZO-decompress lzo_len bytes of outbuf into the tempbuf */
ret = lzo1x_decompress_safe(outbuf, lzo_len, tempbuf, &templen);
if (ret) {
if (LZO_E_INPUT_NOT_CONSUMED == ret) {
/*
* The tag length appears to always be aligned (probably
* because it is the "root" RB_ID_WLAN_DATA tag), thus
* the LZO payload may be padded, which can trigger a
* spurious error which we ignore here.
*/
pr_debug(RB_HC_PR_PFX "LZOR: LZO EOF before buffer end - this may be harmless\n");
} else {
pr_debug(RB_HC_PR_PFX "LZOR: LZO decompression error (%d)\n", ret);
goto fail;
}
}
/*
* Post decompression we have a blob (possibly byproduct of the lzo
* dictionary). We need to find RB_MAGIC_ERD. The magic number seems to
* be 32bit-aligned in the decompression output.
*/
needle = (const u32 *)tempbuf;
while (RB_MAGIC_ERD != *needle++) {
if ((u8 *)needle >= tempbuf+templen) {
pr_debug(RB_HC_PR_PFX "LZOR: ERD magic not found\n");
ret = -ENODATA;
goto fail;
}
};
templen -= (u8 *)needle - tempbuf;
/* Past magic. Look for tag node */
ret = routerboot_tag_find((u8 *)needle, templen, 0x1, &rle_ofs, &rle_len);
if (ret) {
pr_debug(RB_HC_PR_PFX "LZOR: RLE data not found\n");
goto fail;
}
if (rle_len > templen) {
pr_debug(RB_HC_PR_PFX "LZOR: Invalid RLE data length\n");
ret = -EINVAL;
goto fail;
}
/* RLE-decode tempbuf from needle back into the outbuf */
ret = routerboot_rle_decode((u8 *)needle+rle_ofs, rle_len, outbuf, outlen);
if (ret)
pr_debug(RB_HC_PR_PFX "LZOR: RLE decoding error (%d)\n", ret);
fail:
kfree(tempbuf);
return ret;
}
static int hc_wlan_data_unpack(const size_t tofs, size_t tlen,
void *outbuf, size_t *outlen)
{
const u8 *lbuf;
u32 magic;
int ret;
/* Caller ensure tlen > 0. tofs is aligned */
if ((tofs + tlen) > hc_buflen)
return -EIO;
lbuf = hc_buf + tofs;
magic = *(u32 *)lbuf;
ret = -ENODATA;
switch (magic) {
case RB_MAGIC_LZOR:
/* Skip magic */
lbuf += sizeof(magic);
tlen -= sizeof(magic);
ret = hc_wlan_data_unpack_lzor(lbuf, tlen, outbuf, outlen);
break;
case RB_MAGIC_ERD:
/* Skip magic */
lbuf += sizeof(magic);
tlen -= sizeof(magic);
ret = hc_wlan_data_unpack_erd(lbuf, tlen, outbuf, outlen);
break;
default:
/*
* If the RB_ID_WLAN_DATA payload doesn't start with a
* magic number, the payload itself is the raw RLE-encoded
* calibration data.
*/
ret = routerboot_rle_decode(lbuf, tlen, outbuf, outlen);
if (ret)
pr_debug(RB_HC_PR_PFX "RLE decoding error (%d)\n", ret);
break;
}
return ret;
}
static ssize_t hc_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
const struct hc_attr *hc_attr;
const u8 *pld;
u16 pld_len;
hc_attr = container_of(attr, typeof(*hc_attr), kattr);
if (!hc_attr->pld_len)
return -ENOENT;
pld = hc_buf + hc_attr->pld_ofs;
pld_len = hc_attr->pld_len;
return hc_attr->tshow(pld, pld_len, buf);
}
/*
* This function will allocate and free memory every time it is called. This
* is not the fastest way to do this, but since the data is rarely read (mainly
* at boot time to load wlan caldata), this makes it possible to save memory for
* the system.
*/
static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct hc_wlan_attr *hc_wattr;
size_t outlen;
void *outbuf;
int ret;
hc_wattr = container_of(attr, typeof(*hc_wattr), battr);
if (!hc_wattr->pld_len)
return -ENOENT;
outlen = RB_ART_SIZE;
/* Don't bother unpacking if the source is already too large */
if (hc_wattr->pld_len > outlen)
return -EFBIG;
outbuf = kmalloc(outlen, GFP_KERNEL);
if (!outbuf)
return -ENOMEM;
ret = hc_wlan_data_unpack(hc_wattr->pld_ofs, hc_wattr->pld_len, outbuf, &outlen);
if (ret) {
kfree(outbuf);
return ret;
}
if (off >= outlen) {
kfree(outbuf);
return 0;
}
if (off + count > outlen)
count = outlen - off;
memcpy(buf, outbuf + off, count);
kfree(outbuf);
return count;
}
int __init rb_hardconfig_init(struct kobject *rb_kobj)
{
struct mtd_info *mtd;
size_t bytes_read, buflen;
const u8 *buf;
int i, ret;
u32 magic;
hc_buf = NULL;
hc_kobj = NULL;
// TODO allow override
mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG);
if (IS_ERR(mtd))
return -ENODEV;
hc_buflen = mtd->size;
hc_buf = kmalloc(hc_buflen, GFP_KERNEL);
if (!hc_buf)
return -ENOMEM;
ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf);
if (ret)
goto fail;
if (bytes_read != hc_buflen) {
ret = -EIO;
goto fail;
}
/* Check we have what we expect */
magic = *(const u32 *)hc_buf;
if (RB_MAGIC_HARD != magic) {
ret = -EINVAL;
goto fail;
}
/* Skip magic */
buf = hc_buf + sizeof(magic);
buflen = hc_buflen - sizeof(magic);
/* Populate sysfs */
ret = -ENOMEM;
hc_kobj = kobject_create_and_add(RB_MTD_HARD_CONFIG, rb_kobj);
if (!hc_kobj)
goto fail;
/* Locate and publish all known tags */
for (i = 0; i < ARRAY_SIZE(hc_attrs); i++) {
ret = routerboot_tag_find(buf, buflen, hc_attrs[i].tag_id,
&hc_attrs[i].pld_ofs, &hc_attrs[i].pld_len);
if (ret) {
hc_attrs[i].pld_ofs = hc_attrs[i].pld_len = 0;
continue;
}
/* Account for skipped magic */
hc_attrs[i].pld_ofs += sizeof(magic);
/* Special case RB_ID_WLAN_DATA to prep and create the binary attribute */
if ((RB_ID_WLAN_DATA == hc_attrs[i].tag_id) && hc_attrs[i].pld_len) {
hc_wlandata_battr.pld_ofs = hc_attrs[i].pld_ofs;
hc_wlandata_battr.pld_len = hc_attrs[i].pld_len;
ret = sysfs_create_bin_file(hc_kobj, &hc_wlandata_battr.battr);
if (ret)
pr_warn(RB_HC_PR_PFX "Could not create %s sysfs entry (%d)\n",
hc_wlandata_battr.battr.attr.name, ret);
}
/* All other tags are published via standard attributes */
else {
ret = sysfs_create_file(hc_kobj, &hc_attrs[i].kattr.attr);
if (ret)
pr_warn(RB_HC_PR_PFX "Could not create %s sysfs entry (%d)\n",
hc_attrs[i].kattr.attr.name, ret);
}
}
pr_info("MikroTik RouterBOARD hardware configuration sysfs driver v" RB_HARDCONFIG_VER "\n");
return 0;
fail:
kfree(hc_buf);
hc_buf = NULL;
return ret;
}
void __exit rb_hardconfig_exit(void)
{
kobject_put(hc_kobj);
kfree(hc_buf);
}

View File

@ -0,0 +1,754 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for MikroTik RouterBoot soft config.
*
* Copyright (C) 2020 Thibaut VARÈNE <hacks+kernel@slashdirt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This driver exposes the data encoded in the "soft_config" flash segment of
* MikroTik RouterBOARDs devices. It presents the data in a sysfs folder
* named "soft_config". The data is presented in a user/machine-friendly way
* with just as much parsing as can be generalized across mikrotik platforms
* (as inferred from reverse-engineering).
*
* The known soft_config tags are presented in the "soft_config" sysfs folder,
* with the addition of one specific file named "commit", which is only
* available if the driver supports writes to the mtd device: no modifications
* made to any of the other attributes are actually written back to flash media
* until a true value is input into this file (e.g. [Yy1]). This is to avoid
* unnecessary flash wear, and to permit to revert all changes by issuing a
* false value ([Nn0]). Reading the content of this file shows the current
* status of the driver: if the data in sysfs matches the content of the
* soft_config partition, the file will read "clean". Otherwise, it will read
* "dirty".
*
* The writeable sysfs files presented by this driver will accept only inputs
* which are in a valid range for the given tag. As a design choice, the driver
* will not assess whether the inputs are identical to the existing data.
*
* Note: PAGE_SIZE is assumed to be >= 4K, hence the device attribute show
* routines need not check for output overflow.
*
* Some constant defines extracted from rbcfg.h by Gabor Juhos
* <juhosg@openwrt.org>
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/sysfs.h>
#include <linux/version.h>
#include <linux/capability.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
#ifdef CONFIG_ATH79
#include <asm/mach-ath79/ath79.h>
#endif
#include "routerboot.h"
#define RB_SOFTCONFIG_VER "0.02"
#define RB_SC_PR_PFX "[rb_softconfig] "
/*
* mtd operations before 4.17 are asynchronous, not handled by this code
* Also make the driver act read-only if 4K_SECTORS are not enabled, since they
* are require to handle partial erasing of the small soft_config partition.
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) && defined(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS)
#define RB_SC_HAS_WRITE_SUPPORT true
#define RB_SC_WMODE S_IWUSR
#define RB_SC_RMODE S_IRUSR
#else
#define RB_SC_HAS_WRITE_SUPPORT false
#define RB_SC_WMODE 0
#define RB_SC_RMODE S_IRUSR
#endif
/* ID values for software settings */
#define RB_SCID_UART_SPEED 0x01 // u32*1
#define RB_SCID_BOOT_DELAY 0x02 // u32*1
#define RB_SCID_BOOT_DEVICE 0x03 // u32*1
#define RB_SCID_BOOT_KEY 0x04 // u32*1
#define RB_SCID_CPU_MODE 0x05 // u32*1
#define RB_SCID_BIOS_VERSION 0x06 // str
#define RB_SCID_BOOT_PROTOCOL 0x09 // u32*1
#define RB_SCID_CPU_FREQ_IDX 0x0C // u32*1
#define RB_SCID_BOOTER 0x0D // u32*1
#define RB_SCID_SILENT_BOOT 0x0F // u32*1
/*
* protected_routerboot seems to use tag 0x1F. It only works in combination with
* RouterOS, resulting in a wiped board otherwise, so it's not implemented here.
* The tag values are as follows:
* - off: 0x0
* - on: the lower halfword encodes the max value in s for the reset feature,
* the higher halfword encodes the min value in s for the reset feature.
* Default value when on: 0x00140258: 0x14 = 20s / 0x258= 600s
* See details here: https://wiki.mikrotik.com/wiki/Manual:RouterBOARD_settings#Protected_bootloader
*/
/* Tag values */
#define RB_UART_SPEED_115200 0
#define RB_UART_SPEED_57600 1
#define RB_UART_SPEED_38400 2
#define RB_UART_SPEED_19200 3
#define RB_UART_SPEED_9600 4
#define RB_UART_SPEED_4800 5
#define RB_UART_SPEED_2400 6
#define RB_UART_SPEED_1200 7
#define RB_UART_SPEED_OFF 8
/* valid boot delay: 1 - 9s in 1s increment */
#define RB_BOOT_DELAY_MIN 1
#define RB_BOOT_DELAY_MAX 9
#define RB_BOOT_DEVICE_ETHER 0 // "boot over Ethernet"
#define RB_BOOT_DEVICE_NANDETH 1 // "boot from NAND, if fail then Ethernet"
#define RB_BOOT_DEVICE_CFCARD 2 // (not available in rbcfg)
#define RB_BOOT_DEVICE_ETHONCE 3 // "boot Ethernet once, then NAND"
#define RB_BOOT_DEVICE_NANDONLY 5 // "boot from NAND only"
#define RB_BOOT_DEVICE_FLASHCFG 7 // "boot in flash configuration mode"
#define RB_BOOT_DEVICE_FLSHONCE 8 // "boot in flash configuration mode once, then NAND"
/*
* ATH79 CPU frequency indices.
* It is unknown if they apply to all ATH79 RBs, and some do not seem to feature
* the up levels (QCA955x), while U3 is presumably AR9344-only.
*/
#define RB_CPU_FREQ_IDX_ATH79_D2 (0 << 3)
#define RB_CPU_FREQ_IDX_ATH79_D1 (1 << 3) // 0x8
#define RB_CPU_FREQ_IDX_ATH79_N0 (2 << 3) // 0x10 - factory freq for many devices
#define RB_CPU_FREQ_IDX_ATH79_U1 (3 << 3) // 0x18
#define RB_CPU_FREQ_IDX_ATH79_U2 (4 << 3) // 0x20
#define RB_CPU_FREQ_IDX_ATH79_U3 (5 << 3) // 0x28
#define RB_CPU_FREQ_IDX_ATH79_MIN 0 // all devices support lowest setting
#define RB_CPU_FREQ_IDX_ATH79_AR9334_MAX 5 // stops at U3
#define RB_CPU_FREQ_IDX_ATH79_QCA953X_MAX 4 // stops at U2
#define RB_CPU_FREQ_IDX_ATH79_QCA9556_MAX 2 // stops at N0
#define RB_CPU_FREQ_IDX_ATH79_QCA9558_MAX 3 // stops at U1
#define RB_SC_CRC32_OFFSET 4 // located right after magic
static struct kobject *sc_kobj;
static u8 *sc_buf;
static size_t sc_buflen;
static rwlock_t sc_bufrwl; // rw lock to sc_buf
/* MUST be used with lock held */
#define RB_SC_CLRCRC() *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET) = 0
#define RB_SC_GETCRC() *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET)
#define RB_SC_SETCRC(_crc) *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET) = (_crc)
struct sc_u32tvs {
const u32 val;
const char *str;
};
#define RB_SC_TVS(_val, _str) { \
.val = (_val), \
.str = (_str), \
}
static ssize_t sc_tag_show_u32tvs(const u8 *pld, u16 pld_len, char *buf,
const struct sc_u32tvs tvs[], const int tvselmts)
{
const char *fmt;
char *out = buf;
u32 data; // cpu-endian
int i;
if (tvselmts < 0)
return tvselmts;
if (sizeof(data) != pld_len)
return -EINVAL;
read_lock(&sc_bufrwl);
data = *(u32 *)pld; // pld aliases sc_buf
read_unlock(&sc_bufrwl);
for (i = 0; i < tvselmts; i++) {
fmt = (tvs[i].val == data) ? "[%s] " : "%s ";
out += sprintf(out, fmt, tvs[i].str);
}
out += sprintf(out, "\n");
return out - buf;
}
static ssize_t sc_tag_store_u32tvs(const u8 *pld, u16 pld_len, const char *buf, size_t count,
const struct sc_u32tvs tvs[], const int tvselmts)
{
int i;
if (tvselmts < 0)
return tvselmts;
if (sizeof(u32) != pld_len)
return -EINVAL;
for (i = 0; i < tvselmts; i++) {
if (sysfs_streq(buf, tvs[i].str)) {
write_lock(&sc_bufrwl);
*(u32 *)pld = tvs[i].val; // pld aliases sc_buf
RB_SC_CLRCRC();
write_unlock(&sc_bufrwl);
return count;
}
}
return -EINVAL;
}
struct sc_boolts {
const char *strfalse;
const char *strtrue;
};
static ssize_t sc_tag_show_boolts(const u8 *pld, u16 pld_len, char *buf,
const struct sc_boolts *bts)
{
const char *fmt;
char *out = buf;
u32 data; // cpu-endian
if (sizeof(data) != pld_len)
return -EINVAL;
read_lock(&sc_bufrwl);
data = *(u32 *)pld; // pld aliases sc_buf
read_unlock(&sc_bufrwl);
fmt = (data) ? "%s [%s]\n" : "[%s] %s\n";
out += sprintf(out, fmt, bts->strfalse, bts->strtrue);
return out - buf;
}
static ssize_t sc_tag_store_boolts(const u8 *pld, u16 pld_len, const char *buf, size_t count,
const struct sc_boolts *bts)
{
u32 data; // cpu-endian
if (sizeof(data) != pld_len)
return -EINVAL;
if (sysfs_streq(buf, bts->strfalse))
data = 0;
else if (sysfs_streq(buf, bts->strtrue))
data = 1;
else
return -EINVAL;
write_lock(&sc_bufrwl);
*(u32 *)pld = data; // pld aliases sc_buf
RB_SC_CLRCRC();
write_unlock(&sc_bufrwl);
return count;
}
static struct sc_u32tvs const sc_uartspeeds[] = {
RB_SC_TVS(RB_UART_SPEED_OFF, "off"),
RB_SC_TVS(RB_UART_SPEED_1200, "1200"),
RB_SC_TVS(RB_UART_SPEED_2400, "2400"),
RB_SC_TVS(RB_UART_SPEED_4800, "4800"),
RB_SC_TVS(RB_UART_SPEED_9600, "9600"),
RB_SC_TVS(RB_UART_SPEED_19200, "19200"),
RB_SC_TVS(RB_UART_SPEED_38400, "38400"),
RB_SC_TVS(RB_UART_SPEED_57600, "57600"),
RB_SC_TVS(RB_UART_SPEED_115200, "115200"),
};
/*
* While the defines are carried over from rbcfg, use strings that more clearly
* show the actual setting purpose (especially since the NAND* settings apply
* to both nand- and nor-based devices). "cfcard" was disabled in rbcfg: disable
* it here too.
*/
static struct sc_u32tvs const sc_bootdevices[] = {
RB_SC_TVS(RB_BOOT_DEVICE_ETHER, "eth"),
RB_SC_TVS(RB_BOOT_DEVICE_NANDETH, "flasheth"),
//RB_SC_TVS(RB_BOOT_DEVICE_CFCARD, "cfcard"),
RB_SC_TVS(RB_BOOT_DEVICE_ETHONCE, "ethonce"),
RB_SC_TVS(RB_BOOT_DEVICE_NANDONLY, "flash"),
RB_SC_TVS(RB_BOOT_DEVICE_FLASHCFG, "cfg"),
RB_SC_TVS(RB_BOOT_DEVICE_FLSHONCE, "cfgonce"),
};
static struct sc_boolts const sc_bootkey = {
.strfalse = "any",
.strtrue = "del",
};
static struct sc_boolts const sc_cpumode = {
.strfalse = "powersave",
.strtrue = "regular",
};
static struct sc_boolts const sc_bootproto = {
.strfalse = "bootp",
.strtrue = "dhcp",
};
static struct sc_boolts const sc_booter = {
.strfalse = "regular",
.strtrue = "backup",
};
static struct sc_boolts const sc_silent_boot = {
.strfalse = "off",
.strtrue = "on",
};
#define SC_TAG_SHOW_STORE_U32TVS_FUNCS(_name) \
static ssize_t sc_tag_show_##_name(const u8 *pld, u16 pld_len, char *buf) \
{ \
return sc_tag_show_u32tvs(pld, pld_len, buf, sc_##_name, ARRAY_SIZE(sc_##_name)); \
} \
static ssize_t sc_tag_store_##_name(const u8 *pld, u16 pld_len, const char *buf, size_t count) \
{ \
return sc_tag_store_u32tvs(pld, pld_len, buf, count, sc_##_name, ARRAY_SIZE(sc_##_name)); \
}
#define SC_TAG_SHOW_STORE_BOOLTS_FUNCS(_name) \
static ssize_t sc_tag_show_##_name(const u8 *pld, u16 pld_len, char *buf) \
{ \
return sc_tag_show_boolts(pld, pld_len, buf, &sc_##_name); \
} \
static ssize_t sc_tag_store_##_name(const u8 *pld, u16 pld_len, const char *buf, size_t count) \
{ \
return sc_tag_store_boolts(pld, pld_len, buf, count, &sc_##_name); \
}
SC_TAG_SHOW_STORE_U32TVS_FUNCS(uartspeeds)
SC_TAG_SHOW_STORE_U32TVS_FUNCS(bootdevices)
SC_TAG_SHOW_STORE_BOOLTS_FUNCS(bootkey)
SC_TAG_SHOW_STORE_BOOLTS_FUNCS(cpumode)
SC_TAG_SHOW_STORE_BOOLTS_FUNCS(bootproto)
SC_TAG_SHOW_STORE_BOOLTS_FUNCS(booter)
SC_TAG_SHOW_STORE_BOOLTS_FUNCS(silent_boot)
static ssize_t sc_tag_show_bootdelays(const u8 *pld, u16 pld_len, char *buf)
{
const char *fmt;
char *out = buf;
u32 data; // cpu-endian
int i;
if (sizeof(data) != pld_len)
return -EINVAL;
read_lock(&sc_bufrwl);
data = *(u32 *)pld; // pld aliases sc_buf
read_unlock(&sc_bufrwl);
for (i = RB_BOOT_DELAY_MIN; i <= RB_BOOT_DELAY_MAX; i++) {
fmt = (i == data) ? "[%d] " : "%d ";
out += sprintf(out, fmt, i);
}
out += sprintf(out, "\n");
return out - buf;
}
static ssize_t sc_tag_store_bootdelays(const u8 *pld, u16 pld_len, const char *buf, size_t count)
{
u32 data; // cpu-endian
int ret;
if (sizeof(data) != pld_len)
return -EINVAL;
ret = kstrtou32(buf, 10, &data);
if (ret)
return ret;
if ((data < RB_BOOT_DELAY_MIN) || (RB_BOOT_DELAY_MAX < data))
return -EINVAL;
write_lock(&sc_bufrwl);
*(u32 *)pld = data; // pld aliases sc_buf
RB_SC_CLRCRC();
write_unlock(&sc_bufrwl);
return count;
}
/* Support CPU frequency accessors only when the tag format has been asserted */
#if defined(CONFIG_ATH79)
static struct sc_u32tvs const sc_cpufreq_indexes_ath79[] = {
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_D2, "-2"),
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_D1, "-1"),
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_N0, "0"),
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_U1, "+1"),
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_U2, "+2"),
RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_U3, "+3"),
};
static int sc_tag_cpufreq_ath79_idxmax(void)
{
int idx_max = -EOPNOTSUPP;
if (soc_is_ar9344())
idx_max = RB_CPU_FREQ_IDX_ATH79_AR9334_MAX;
else if (soc_is_qca953x())
idx_max = RB_CPU_FREQ_IDX_ATH79_QCA953X_MAX;
else if (soc_is_qca9556())
idx_max = RB_CPU_FREQ_IDX_ATH79_QCA9556_MAX;
else if (soc_is_qca9558())
idx_max = RB_CPU_FREQ_IDX_ATH79_QCA9558_MAX;
return idx_max;
}
static ssize_t sc_tag_show_cpufreq_indexes(const u8 *pld, u16 pld_len, char * buf)
{
return sc_tag_show_u32tvs(pld, pld_len, buf, sc_cpufreq_indexes_ath79, sc_tag_cpufreq_ath79_idxmax()+1);
}
static ssize_t sc_tag_store_cpufreq_indexes(const u8 *pld, u16 pld_len, const char *buf, size_t count)
{
return sc_tag_store_u32tvs(pld, pld_len, buf, count, sc_cpufreq_indexes_ath79, sc_tag_cpufreq_ath79_idxmax()+1);
}
#else
/* By default we only show the raw value to help with reverse-engineering */
#define sc_tag_show_cpufreq_indexes routerboot_tag_show_u32s
#define sc_tag_store_cpufreq_indexes NULL
#endif
static ssize_t sc_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
static ssize_t sc_attr_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count);
/* Array of known tags to publish in sysfs */
static struct sc_attr {
const u16 tag_id;
/* sysfs tag show attribute. Must lock sc_buf when dereferencing pld */
ssize_t (* const tshow)(const u8 *pld, u16 pld_len, char *buf);
/* sysfs tag store attribute. Must lock sc_buf when dereferencing pld */
ssize_t (* const tstore)(const u8 *pld, u16 pld_len, const char *buf, size_t count);
struct kobj_attribute kattr;
u16 pld_ofs;
u16 pld_len;
} sc_attrs[] = {
{
.tag_id = RB_SCID_UART_SPEED,
.tshow = sc_tag_show_uartspeeds,
.tstore = sc_tag_store_uartspeeds,
.kattr = __ATTR(uart_speed, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_BOOT_DELAY,
.tshow = sc_tag_show_bootdelays,
.tstore = sc_tag_store_bootdelays,
.kattr = __ATTR(boot_delay, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_BOOT_DEVICE,
.tshow = sc_tag_show_bootdevices,
.tstore = sc_tag_store_bootdevices,
.kattr = __ATTR(boot_device, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_BOOT_KEY,
.tshow = sc_tag_show_bootkey,
.tstore = sc_tag_store_bootkey,
.kattr = __ATTR(boot_key, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_CPU_MODE,
.tshow = sc_tag_show_cpumode,
.tstore = sc_tag_store_cpumode,
.kattr = __ATTR(cpu_mode, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_BIOS_VERSION,
.tshow = routerboot_tag_show_string,
.tstore = NULL,
.kattr = __ATTR(bios_version, RB_SC_RMODE, sc_attr_show, NULL),
}, {
.tag_id = RB_SCID_BOOT_PROTOCOL,
.tshow = sc_tag_show_bootproto,
.tstore = sc_tag_store_bootproto,
.kattr = __ATTR(boot_proto, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_CPU_FREQ_IDX,
.tshow = sc_tag_show_cpufreq_indexes,
.tstore = sc_tag_store_cpufreq_indexes,
.kattr = __ATTR(cpufreq_index, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_BOOTER,
.tshow = sc_tag_show_booter,
.tstore = sc_tag_store_booter,
.kattr = __ATTR(booter, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
}, {
.tag_id = RB_SCID_SILENT_BOOT,
.tshow = sc_tag_show_silent_boot,
.tstore = sc_tag_store_silent_boot,
.kattr = __ATTR(silent_boot, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store),
},
};
static ssize_t sc_attr_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
const struct sc_attr *sc_attr;
const u8 *pld;
u16 pld_len;
sc_attr = container_of(attr, typeof(*sc_attr), kattr);
if (!sc_attr->pld_len)
return -ENOENT;
pld = sc_buf + sc_attr->pld_ofs; // pld aliases sc_buf -> lock!
pld_len = sc_attr->pld_len;
return sc_attr->tshow(pld, pld_len, buf);
}
static ssize_t sc_attr_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
const struct sc_attr *sc_attr;
const u8 *pld;
u16 pld_len;
if (!RB_SC_HAS_WRITE_SUPPORT)
return -EOPNOTSUPP;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
sc_attr = container_of(attr, typeof(*sc_attr), kattr);
if (!sc_attr->tstore)
return -EOPNOTSUPP;
if (!sc_attr->pld_len)
return -ENOENT;
pld = sc_buf + sc_attr->pld_ofs; // pld aliases sc_buf -> lock!
pld_len = sc_attr->pld_len;
return sc_attr->tstore(pld, pld_len, buf, count);
}
/*
* Shows the current buffer status:
* "clean": the buffer is in sync with the mtd data
* "dirty": the buffer is out of sync with the mtd data
*/
static ssize_t sc_commit_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
const char *str;
char *out = buf;
u32 crc;
read_lock(&sc_bufrwl);
crc = RB_SC_GETCRC();
read_unlock(&sc_bufrwl);
str = (crc) ? "clean" : "dirty";
out += sprintf(out, "%s\n", str);
return out - buf;
}
/*
* Performs buffer flushing:
* This routine expects an input compatible with kstrtobool().
* - a "false" input discards the current changes and reads data back from mtd.
* - a "true" input commits the current changes to mtd.
* If there is no pending changes, this routine is a no-op.
* Handling failures is left as an exercise to userspace.
*/
static ssize_t sc_commit_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct mtd_info *mtd;
struct erase_info ei;
size_t bytes_rw, ret = count;
bool flush;
u32 crc;
if (!RB_SC_HAS_WRITE_SUPPORT)
return -EOPNOTSUPP;
read_lock(&sc_bufrwl);
crc = RB_SC_GETCRC();
read_unlock(&sc_bufrwl);
if (crc)
return count; // NO-OP
ret = kstrtobool(buf, &flush);
if (ret)
return ret;
mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG); // TODO allow override
if (IS_ERR(mtd))
return -ENODEV;
write_lock(&sc_bufrwl);
if (!flush) // reread
ret = mtd_read(mtd, 0, mtd->size, &bytes_rw, sc_buf);
else { // crc32 + commit
/*
* CRC32 is computed on the entire buffer, excluding the CRC
* value itself. CRC is already null when we reach this point,
* so we can compute the CRC32 on the buffer as is.
* The expected CRC32 is Ethernet FCS style, meaning the seed is
* ~0 and the final result is also bitflipped.
*/
crc = ~crc32(~0, sc_buf, sc_buflen);
RB_SC_SETCRC(crc);
/*
* The soft_config partition is assumed to be entirely contained
* in a single eraseblock.
*/
ei.addr = 0;
ei.len = mtd->size;
ret = mtd_erase(mtd, &ei);
if (!ret)
ret = mtd_write(mtd, 0, mtd->size, &bytes_rw, sc_buf);
/*
* Handling mtd_write() failure here is a tricky situation. The
* proposed approach is to let userspace deal with retrying,
* with the caveat that it must try to flush the buffer again as
* rereading the mtd contents could potentially read garbage.
* The rationale is: even if we keep a shadow buffer of the
* original content, there is no guarantee that we will ever be
* able to write it anyway.
* Regardless, it appears that RouterBOOT will ignore an invalid
* soft_config (including a completely wiped segment) and will
* write back factory defaults when it happens.
*/
}
write_unlock(&sc_bufrwl);
if (ret)
goto mtdfail;
if (bytes_rw != sc_buflen) {
ret = -EIO;
goto mtdfail;
}
return count;
mtdfail:
RB_SC_CLRCRC(); // mark buffer content as dirty/invalid
return ret;
}
static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store);
int __init rb_softconfig_init(struct kobject *rb_kobj)
{
struct mtd_info *mtd;
size_t bytes_read, buflen;
const u8 *buf;
int i, ret;
u32 magic;
sc_buf = NULL;
sc_kobj = NULL;
// TODO allow override
mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG);
if (IS_ERR(mtd))
return -ENODEV;
sc_buflen = mtd->size;
sc_buf = kmalloc(sc_buflen, GFP_KERNEL);
if (!sc_buf)
return -ENOMEM;
ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf);
if (ret)
goto fail;
if (bytes_read != sc_buflen) {
ret = -EIO;
goto fail;
}
/* Check we have what we expect */
magic = *(const u32 *)sc_buf;
if (RB_MAGIC_SOFT != magic) {
ret = -EINVAL;
goto fail;
}
/* Skip magic and 32bit CRC located immediately after */
buf = sc_buf + (sizeof(magic) + sizeof(u32));
buflen = sc_buflen - (sizeof(magic) + sizeof(u32));
/* Populate sysfs */
ret = -ENOMEM;
sc_kobj = kobject_create_and_add(RB_MTD_SOFT_CONFIG, rb_kobj);
if (!sc_kobj)
goto fail;
rwlock_init(&sc_bufrwl);
/* Locate and publish all known tags */
for (i = 0; i < ARRAY_SIZE(sc_attrs); i++) {
ret = routerboot_tag_find(buf, buflen, sc_attrs[i].tag_id,
&sc_attrs[i].pld_ofs, &sc_attrs[i].pld_len);
if (ret) {
sc_attrs[i].pld_ofs = sc_attrs[i].pld_len = 0;
continue;
}
/* Account for skipped magic and crc32 */
sc_attrs[i].pld_ofs += sizeof(magic) + sizeof(u32);
ret = sysfs_create_file(sc_kobj, &sc_attrs[i].kattr.attr);
if (ret)
pr_warn(RB_SC_PR_PFX "Could not create %s sysfs entry (%d)\n",
sc_attrs[i].kattr.attr.name, ret);
}
/* Finally add the 'commit' attribute */
if (RB_SC_HAS_WRITE_SUPPORT) {
ret = sysfs_create_file(sc_kobj, &sc_kattrcommit.attr);
if (ret) {
pr_err(RB_SC_PR_PFX "Could not create %s sysfs entry (%d), aborting!\n",
sc_kattrcommit.attr.name, ret);
goto sysfsfail; // required attribute
}
}
pr_info("MikroTik RouterBOARD software configuration sysfs driver v" RB_SOFTCONFIG_VER "\n");
return 0;
sysfsfail:
kobject_put(sc_kobj);
sc_kobj = NULL;
fail:
kfree(sc_buf);
sc_buf = NULL;
return ret;
}
void __exit rb_softconfig_exit(void)
{
kobject_put(sc_kobj);
kfree(sc_buf);
}

View File

@ -0,0 +1,218 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for MikroTik RouterBoot flash data. Common routines.
*
* Copyright (C) 2020 Thibaut VARÈNE <hacks+kernel@slashdirt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include "routerboot.h"
static struct kobject *rb_kobj;
/**
* routerboot_tag_find() - Locate a given tag in routerboot config data.
* @bufhead: the buffer to look into. Must start with a tag node.
* @buflen: size of bufhead
* @tag_id: the tag identifier to look for
* @pld_ofs: will be updated with tag payload offset in bufhead, if tag found
* @pld_len: will be updated with tag payload size, if tag found
*
* This incarnation of tag_find() does only that: it finds a specific routerboot
* tag node in the input buffer. Routerboot tag nodes are u32 values:
* - The low nibble is the tag identification number,
* - The high nibble is the tag payload length (node excluded) in bytes.
* The payload immediately follows the tag node. Tag nodes are 32bit-aligned.
* The returned pld_ofs will always be aligned. pld_len may not end on 32bit
* boundary (the only known case is when parsing ERD data).
* The nodes are cpu-endian on the flash media. The payload is cpu-endian when
* applicable. Tag nodes are not ordered (by ID) on flash.
*
* Return: 0 on success (tag found) or errno
*/
int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id,
u16 *pld_ofs, u16 *pld_len)
{
const u32 *datum, *bufend;
u32 node;
u16 id, len;
int ret;
if (!bufhead || !tag_id)
return -EINVAL;
ret = -ENOENT;
datum = (const u32 *)bufhead;
bufend = (const u32 *)(bufhead + buflen);
while (datum < bufend) {
node = *datum++;
/* Tag list ends with null node */
if (!node)
break;
id = node & 0xFFFF;
len = node >> 16;
if (tag_id == id) {
if (datum >= bufend)
break;
if (pld_ofs)
*pld_ofs = (u16)((u8 *)datum - bufhead);
if (pld_len)
*pld_len = len;
ret = 0;
break;
}
/*
* The only known situation where len may not end on 32bit
* boundary is within ERD data. Since we're only extracting
* one tag (the first and only one) from that data, we should
* never need to forcefully ALIGN(). Do it anyway, this is not a
* performance path.
*/
len = ALIGN(len, sizeof(*datum));
datum += len / sizeof(*datum);
}
return ret;
}
/**
* routerboot_rle_decode() - Simple RLE (MikroTik variant) decoding routine.
* @in: input buffer to decode
* @inlen: size of in
* @out: output buffer to write decoded data to
* @outlen: pointer to out size when function is called, will be updated with
* size of decoded output on return
*
* MikroTik's variant of RLE operates as follows, considering a signed run byte:
* - positive run => classic RLE
* - negative run => the next -<run> bytes must be copied verbatim
* The API is matched to the lzo1x routines for convenience.
*
* NB: The output buffer cannot overlap with the input buffer.
*
* Return: 0 on success or errno
*/
int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen)
{
int ret, run, nbytes; // use native types for speed
u8 byte;
if (!in || (inlen < 2) || !out)
return -EINVAL;
ret = -ENOSPC;
nbytes = 0;
while (inlen >= 2) {
run = *in++;
inlen--;
/* Verbatim copies */
if (run & 0x80) {
/* Invert run byte sign */
run = ~run & 0xFF;
run++;
if (run > inlen)
goto fail;
inlen -= run;
nbytes += run;
if (nbytes > *outlen)
goto fail;
/* Basic memcpy */
while (run-- > 0)
*out++ = *in++;
}
/* Stream of half-words RLE: <run><byte>. run == 0 is ignored */
else {
byte = *in++;
inlen--;
nbytes += run;
if (nbytes > *outlen)
goto fail;
while (run-- > 0)
*out++ = byte;
}
}
ret = 0;
fail:
*outlen = nbytes;
return ret;
}
static int __init routerboot_init(void)
{
rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj);
if (!rb_kobj)
return -ENOMEM;
/*
* We ignore the following return values and always register.
* These init() routines are designed so that their failed state is
* always manageable by the corresponding exit() calls.
*/
rb_hardconfig_init(rb_kobj);
rb_softconfig_init(rb_kobj);
return 0;
}
static void __exit routerboot_exit(void)
{
rb_softconfig_exit();
rb_hardconfig_exit();
kobject_put(rb_kobj); // recursive afaict
}
/* Common routines */
ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf)
{
return scnprintf(buf, pld_len+1, "%s\n", pld);
}
ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf)
{
char *out = buf;
u32 data; // cpu-endian
/* Caller ensures pld_len > 0 */
if (pld_len % sizeof(data))
return -EINVAL;
data = *(u32 *)pld;
do {
out += sprintf(out, "0x%08x\n", data);
data++;
} while ((pld_len -= sizeof(data)));
return out - buf;
}
module_init(routerboot_init);
module_exit(routerboot_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MikroTik RouterBoot sysfs support");
MODULE_AUTHOR("Thibaut VARENE");

View File

@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Common definitions for MikroTik RouterBoot data.
*
* Copyright (C) 2020 Thibaut VARÈNE <hacks+kernel@slashdirt.org>
*/
#ifndef _ROUTERBOOT_H_
#define _ROUTERBOOT_H_
#include <linux/types.h>
// these magic values are stored in cpu-endianness on flash
#define RB_MAGIC_HARD (('H') | ('a' << 8) | ('r' << 16) | ('d' << 24))
#define RB_MAGIC_SOFT (('S') | ('o' << 8) | ('f' << 16) | ('t' << 24))
#define RB_MAGIC_LZOR (('L') | ('Z' << 8) | ('O' << 16) | ('R' << 24))
#define RB_MAGIC_ERD (('E' << 16) | ('R' << 8) | ('D'))
#define RB_ART_SIZE 0x10000
#define RB_MTD_HARD_CONFIG "hard_config"
#define RB_MTD_SOFT_CONFIG "soft_config"
int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len);
int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen);
int __init rb_hardconfig_init(struct kobject *rb_kobj);
void __exit rb_hardconfig_exit(void);
int __init rb_softconfig_init(struct kobject *rb_kobj);
void __exit rb_softconfig_exit(void);
ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf);
ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf);
#endif /* _ROUTERBOOT_H_ */

View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include "mt7621_xiaomi_router-ac2100.dtsi"
/ {
compatible = "xiaomi,mi-router-ac2100", "mediatek,mt7621-soc";
model = "Xiaomi Mi Router AC2100";
aliases {
led-boot = &led_status_yellow;
led-failsafe = &led_status_yellow;
led-running = &led_status_blue;
led-upgrade = &led_status_blue;
};
leds {
compatible = "gpio-leds";
wan_yellow {
label = "mi-router-ac2100:yellow:wan";
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
wan_blue {
label = "mi-router-ac2100:blue:wan";
gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
};
led_status_yellow: status_yellow {
label = "mi-router-ac2100:yellow:status";
gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
};
led_status_blue: status_blue {
label = "mi-router-ac2100:blue:status";
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
};
};
};

View File

@ -0,0 +1,173 @@
/dts-v1/;
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
compatible = "xiaomi,mir4", "mediatek,mt7621-soc";
model = "Xiaomi Mi Router 4";
aliases {
led-boot = &led_status_yellow;
led-failsafe = &led_status_red;
led-running = &led_status_blue;
led-upgrade = &led_status_yellow;
};
chosen {
bootargs = "console=ttyS0,115200n8";
};
leds {
compatible = "gpio-leds";
led_status_red: status_red {
label = "mir4:red:status";
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
led_status_blue: status_blue {
label = "mir4:blue:status";
gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
};
led_status_yellow: status_yellow {
label = "mir4:yellow:status";
gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
};
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
minet {
label = "minet";
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
};
};
};
&nand {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "Bootloader";
reg = <0x0 0x80000>;
};
partition@80000 {
label = "Config";
reg = <0x80000 0x40000>;
};
partition@c0000 {
label = "Bdata";
reg = <0xc0000 0x40000>;
};
factory: partition@100000 {
label = "factory";
reg = <0x100000 0x40000>;
};
partition@140000 {
label = "crash";
reg = <0x140000 0x40000>;
};
partition@180000 {
label = "crash_syslog";
reg = <0x180000 0x40000>;
};
partition@1c0000 {
label = "reserved0";
reg = <0x1c0000 0x40000>;
};
/* uboot expects to find kernels at 0x200000 & 0x600000
* referred to as system 1 & system 2 respectively.
* a kernel is considered suitable for handing control over
* if its linux magic number exists & uImage CRC are correct.
* If either of those conditions fail, a matching sys'n'_fail flag
* is set in uboot env & a restart performed in the hope that the
* alternate kernel is okay.
* if neither kernel checksums ok and both are marked failed, system 2
* is booted anyway.
*
* Note uboot's tftp flash install writes the transferred
* image to both kernel partitions.
*/
partition@200000 {
label = "kernel_stock";
reg = <0x200000 0x400000>;
};
partition@600000 {
label = "kernel";
reg = <0x600000 0x400000>;
};
/* ubi partition is the result of squashing
* next consecutive stock partitions:
* - rootfs0 (rootfs partition for stock kernel0),
* - rootfs1 (rootfs partition for stock failsafe kernel1),
* - overlay (used as ubi overlay in stock fw)
* resulting 117,5MiB space for packages.
*/
partition@a00000 {
label = "ubi";
reg = <0xa00000 0x7580000>;
};
};
};
&pcie {
status = "okay";
};
&pcie0 {
wifi@0,0 {
compatible = "pci14c3,7603";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x0000>;
ieee80211-freq-limit = <2400000 2500000>;
};
};
&pcie1 {
wifi@0,0 {
compatible = "pci14c3,7662";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x8000>;
ieee80211-freq-limit = <5000000 6000000>;
};
};
&ethernet {
mtd-mac-address = <&factory 0xe000>;
mediatek,portmap = "llllw";
};
&state_default {
gpio {
ralink,group = "jtag", "uart2", "uart3", "wdt";
ralink,function = "gpio";
};
};

View File

@ -1,10 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include "mt7621_xiaomi_router-ac2100.dtsi"
/ {
compatible = "xiaomi,redmi-router-ac2100", "mediatek,mt7621-soc";
@ -17,10 +14,6 @@
led-upgrade = &led_status_white;
};
chosen {
bootargs = "console=ttyS0,115200n8";
};
leds {
compatible = "gpio-leds";
@ -44,111 +37,4 @@
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
};
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
};
&nand {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "Bootloader";
reg = <0x0 0x80000>;
};
partition@80000 {
label = "Config";
reg = <0x80000 0x40000>;
};
partition@c0000 {
label = "Bdata";
reg = <0xc0000 0x40000>;
read-only;
};
factory: partition@100000 {
label = "factory";
reg = <0x100000 0x40000>;
read-only;
};
partition@140000 {
label = "crash";
reg = <0x140000 0x40000>;
};
partition@180000 {
label = "crash_syslog";
reg = <0x180000 0x40000>;
};
partition@1c0000 {
label = "reserved0";
reg = <0x1c0000 0x40000>;
read-only;
};
/* We keep stock xiaomi firmware (kernel0) here */
partition@200000 {
label = "kernel_stock";
reg = <0x200000 0x400000>;
};
partition@600000 {
label = "kernel";
reg = <0x600000 0x400000>;
};
partition@a00000 {
label = "ubi";
reg = <0xa00000 0x7580000>;
};
};
};
&pcie {
status = "okay";
};
&pcie0 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x8000>;
ieee80211-freq-limit = <5000000 6000000>;
};
};
&pcie1 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x0000>;
ieee80211-freq-limit = <2400000 2500000>;
};
};
&ethernet {
mtd-mac-address = <&factory 0xe000>;
};
&state_default {
gpio {
ralink,group = "uart2", "uart3", "wdt";
ralink,function = "gpio";
};
};

View File

@ -0,0 +1,120 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
chosen {
bootargs = "console=ttyS0,115200n8";
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
};
&nand {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "Bootloader";
reg = <0x0 0x80000>;
};
partition@80000 {
label = "Config";
reg = <0x80000 0x40000>;
};
partition@c0000 {
label = "Bdata";
reg = <0xc0000 0x40000>;
read-only;
};
factory: partition@100000 {
label = "factory";
reg = <0x100000 0x40000>;
read-only;
};
partition@140000 {
label = "crash";
reg = <0x140000 0x40000>;
};
partition@180000 {
label = "crash_syslog";
reg = <0x180000 0x40000>;
};
partition@1c0000 {
label = "reserved0";
reg = <0x1c0000 0x40000>;
read-only;
};
/* We keep stock xiaomi firmware (kernel0) here */
partition@200000 {
label = "kernel_stock";
reg = <0x200000 0x400000>;
};
partition@600000 {
label = "kernel";
reg = <0x600000 0x400000>;
};
partition@a00000 {
label = "ubi";
reg = <0xa00000 0x7580000>;
};
};
};
&pcie {
status = "okay";
};
&pcie0 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x8000>;
ieee80211-freq-limit = <5000000 6000000>;
};
};
&pcie1 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
mediatek,mtd-eeprom = <&factory 0x0000>;
ieee80211-freq-limit = <2400000 2500000>;
};
};
&ethernet {
mtd-mac-address = <&factory 0xe000>;
};
&state_default {
gpio {
ralink,group = "uart2", "uart3", "wdt";
ralink,function = "gpio";
};
};

View File

@ -930,12 +930,44 @@ define Device/xiaomi_mir3p
endef
TARGET_DEVICES += xiaomi_mir3p
define Device/xiaomi_redmi-router-ac2100
define Device/xiaomi_mir4
BLOCKSIZE := 128k
PAGESIZE := 2048
KERNEL_SIZE := 4096k
IMAGE_SIZE := 124416k
UBINIZE_OPTS := -E 5
IMAGES += kernel1.bin rootfs0.bin
IMAGE/kernel1.bin := append-kernel
IMAGE/rootfs0.bin := append-ubi | check-size $$$$(IMAGE_SIZE)
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
DEVICE_VENDOR := Xiaomi
DEVICE_MODEL := Mi Router 4
DEVICE_PACKAGES := kmod-mt7603 kmod-mt76x2 wpad-openssl uboot-envtools
endef
TARGET_DEVICES += xiaomi_mir4
define Device/xiaomi_mi-router-ac2100
BLOCKSIZE := 128k
PAGESIZE := 2048
KERNEL_SIZE := 4096k
IMAGE_SIZE := 120320k
UBINIZE_OPTS := -E 5
IMAGES += kernel1.bin rootfs0.bin
IMAGE/kernel1.bin := append-kernel
IMAGE/rootfs0.bin := append-ubi | check-size $$$$(IMAGE_SIZE)
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
DEVICE_VENDOR := Xiaomi
DEVICE_MODEL := Mi Router AC2100
DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615e wpad-openssl uboot-envtools
endef
TARGET_DEVICES += xiaomi_mi-router-ac2100
define Device/xiaomi_redmi-router-ac2100
BLOCKSIZE := 128k
PAGESIZE := 2048
KERNEL_SIZE := 4096k
IMAGE_SIZE := 120320k
UBINIZE_OPTS := -E 5
IMAGES += kernel1.bin rootfs0.bin factory.bin
IMAGE/kernel1.bin := append-kernel
IMAGE/rootfs0.bin := append-ubi | check-size $$$$(IMAGE_SIZE)

View File

@ -92,6 +92,9 @@ xiaomi,mir3p)
xzwifi,creativebox-v1)
ucidef_set_led_switch "internet" "internet" "$boardname:blue:internet" "switch0" "0x10"
;;
xiaomi,mi-router-ac2100)
ucidef_set_led_netdev "wan" "wan" "$boardname:blue:wan" "wan"
;;
xiaomi,redmi-router-ac2100)
ucidef_set_led_netdev "wan" "wan" "$boardname:white:wan" "wan"
;;

View File

@ -156,6 +156,11 @@ ramips_setup_interfaces()
ucidef_add_switch "switch0" \
"1:lan:3" "2:lan:2" "3:lan:1" "4:wan" "6@eth0"
;;
xiaomi,mir4)
ucidef_add_switch "switch0" \
"1:lan:2" "2:lan:1" "4:wan" "6t@eth0"
;;
xiaomi,mi-router-ac2100|\
xiaomi,redmi-router-ac2100)
ucidef_add_switch "switch0" \
"2:lan" "3:lan" "4:lan" "0:wan" "6@eth0"
@ -245,6 +250,7 @@ ramips_setup_macs()
iodata,wn-ax1167gr2|\
iodata,wn-dx1167r|\
xiaomi,mir3g-v2|\
xiaomi,mi-router-ac2100|\
xiaomi,redmi-router-ac2100)
wan_mac=$(mtd_get_mac_binary factory 0xe006)
label_mac=$wan_mac
@ -297,7 +303,8 @@ ramips_setup_macs()
label_mac=$wan_mac
;;
xiaomi,mir3g|\
xiaomi,mir3p)
xiaomi,mir3p|\
xiaomi,mir4)
lan_mac=$(mtd_get_mac_binary factory 0xe006)
label_mac=$lan_mac
;;

View File

@ -55,6 +55,8 @@ platform_do_upgrade() {
netis,wf2881|\
xiaomi,mir3g|\
xiaomi,mir3p|\
xiaomi,mir4|\
xiaomi,mi-router-ac2100|\
xiaomi,redmi-router-ac2100)
nand_do_upgrade "$1"
;;

View File

@ -1,6 +1,6 @@
ARCH:=x86_64
BOARDNAME:=x64 64bit
DEFAULT_PACKAGES += kmod-button-hotplug kmod-e1000e kmod-e1000 kmod-r8169 kmod-igb kmod-bnx2
DEFAULT_PACKAGES += kmod-button-hotplug kmod-e1000e kmod-e1000 kmod-igb kmod-bnx2
define Target/Description
Build images for 64 bit systems including virtualized guests.

View File

@ -25,7 +25,7 @@ htop lm-sensors autocore-x86 automount autosamba luci-app-ipsec-vpnd luci-proto-
luci-app-airplay2 luci-app-music-remote-center luci-app-qbittorrent luci-app-amule luci-app-openvpn-server luci-app-unblockmusic \
ath10k-firmware-qca988x ath10k-firmware-qca9888 ath10k-firmware-qca9984 brcmfmac-firmware-43602a1-pcie \
kmod-sound-hda-core kmod-sound-hda-codec-realtek kmod-sound-hda-codec-via kmod-sound-via82xx kmod-sound-hda-intel kmod-sound-hda-codec-hdmi kmod-sound-i8x0 kmod-usb-audio \
kmod-usb-net kmod-usb-net-asix kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8150 kmod-usb-net-rtl8152
kmod-usb-net kmod-usb-net-asix kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8150 kmod-usb-net-rtl8152 kmod-mlx4-core kmod-mlx5-core
$(eval $(call BuildTarget))

View File

@ -326,7 +326,6 @@ CONFIG_IRQ_WORK=y
# CONFIG_ISA is not set
CONFIG_ISA_DMA_API=y
# CONFIG_ISCSI_IBFT is not set
# CONFIG_ISCSI_IBFT_FIND is not set
# CONFIG_IT8712F_WDT is not set
# CONFIG_IT87_WDT is not set
# CONFIG_ITCO_WDT is not set
@ -363,6 +362,18 @@ CONFIG_MIGRATION=y
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_CQHCI=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_RICOH_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PCI=y
# CONFIG_MMC_SDHCI_PLTFM is not set
CONFIG_MMC_TEST=y
# CONFIG_MMC_TIFM_SD is not set
# CONFIG_MMC_WBSD is not set
# CONFIG_MODIFY_LDT_SYSCALL is not set
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_MODULES_USE_ELF_REL=y
@ -438,6 +449,7 @@ CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GEMINILAKE is not set
# CONFIG_PINCTRL_LEWISBURG is not set
# CONFIG_PINCTRL_SUNRISEPOINT is not set
CONFIG_PLUGIN_HOSTCC="g++"
CONFIG_PMC_ATOM=y
# CONFIG_PMIC_OPREGION is not set
CONFIG_PNP=y
@ -478,6 +490,7 @@ CONFIG_SCx200=y
CONFIG_SCx200HR_TIMER=y
# CONFIG_SCx200_GPIO is not set
# CONFIG_SCx200_WDT is not set
CONFIG_SDIO_UART=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIO=y
@ -552,20 +565,18 @@ CONFIG_X86_CMPXCHG64=y
# CONFIG_X86_CPUFREQ_NFORCE2 is not set
# CONFIG_X86_CPUID is not set
# CONFIG_X86_DEBUG_FPU is not set
CONFIG_X86_DECODER_SELFTEST=n
# CONFIG_X86_DECODER_SELFTEST is not set
# CONFIG_X86_EXTENDED_PLATFORM is not set
# CONFIG_X86_E_POWERSAVER is not set
CONFIG_X86_F00F_BUG=y
CONFIG_X86_FEATURE_NAMES=y
CONFIG_X86_GENERIC=y
# CONFIG_X86_GX_SUSPMOD is not set
# CONFIG_X86_INTEL_MPX is not set
# CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set
CONFIG_X86_INTEL_LPSS=y
# CONFIG_X86_INTEL_PSTATE is not set
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
CONFIG_X86_INTEL_TSX_MODE_OFF=y
# CONFIG_X86_INTEL_TSX_MODE_ON is not set
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
CONFIG_X86_INTEL_UMIP=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6