关于波波

典型宅男,喜欢编程,喜欢自由,喜欢做梦。

怀旧文一篇

今天看别人的博客提到了unix-center.net和蒋清野先生,这也勾起了我的回忆。我大概是在大三的时候接触Linux,当时是看到别人不知道从那里得到的免费Ubuntu7或者是8 CD光盘。我也就在电脑上装了一个,记得安装过程好像比现在的复杂。可惜的是我在玩了一下Ubuntu中的一款penguin企鹅游戏后就放弃了,也没花精力深入研究,大概是GUI体验不是很好吧。

重回XP后,为了继续学习Linux就找到了这个当时在国内还是独一无二的unix-center.net,我记得很清楚的是提供很多发行版,好像还有采用龙芯CPU的服务器。我每次用putty远程登录,体验命令行操作,写几行C语言程序,再跟着鸟哥的网站测试一下学到的命令。当时感觉很神奇,很方便,受益匪浅。当时同时登录服务器的人很多,很多人的文件目录都是可以访问的,我当时的乐趣之一就是挨个翻一翻每个人的文件主目录,看看有什么好玩的东西(好东西不多,估计都是我这种小白),好像还可以通过命令互发消息,但我没试过。后来记得有一次蒋先生在网站上发公告说有人在服务器上运行破解密码的软件,占用了大量CPU等等,当时我就隐隐感觉网站的脆弱和孤立无源,网站好像也没什么赞助商什么的。

后来知道了unix-center.net是蒋清野先生独自创办的,花光了个人积蓄付网站的服务器和流量费用。但后来遇到了困难很难维持这个网站了,他在网站发公开信说:

我于2000年底硕士毕业之后,在美国工作了三年,又在中国工作了六年。在过去的两年半中,这个系统烧掉了我大部分的工资和积蓄。购买各种服务器设备的费用,大概是70万人民币;北京赛尔机房的服务器托管和带宽费用,大概是每年30万人民币。。。和我同年龄的人,现在大部分都有车有房了吧。而我最值钱的资产,是在保安严密的机房中的三个机柜。

后来我也一直没再关注过unix-center.net,现在也访问不了,应该是很早就停掉了。今天抽空看了一下蒋先生的近况。unix-center遇到困难后,他想方设法度过难关,后来估计不成功吧,就回到海南老家,看这篇帖子蒋先生的评论,好像回海南创业搞农业??最近
根据他博客的内容是在澳洲AWS搞云计算和在悉尼大学读博士(真是老当益壮啊)。

蒋先生也坦言自己是个纯粹的搞技术的,不懂如果把技术变现,估计也不屑于谈钱。这是技术人员的通病吧,很难找到既有技术又有商业头脑的人。中国的教育的一个短板就是强调专才教育而忽略了通识教育,固然专才教育可以提供大量的工程师满足当前的经济需求,但就当下提倡技术创新和全民创业来说就很那满足了,现在需要的就是既有技术专才又有情商高的通才。

OpenWRT第一次提交补丁

最近在工作中发现了MT7688 OpenWRT的一个看门狗BUG,简单的来说就是MT7688(包括MT7628/MT7621)设备树描述的看门狗寄存器地址与看门狗内核模块的寄存器地址不符导致不能工作。

所以我第一次向OpenWRT github提交了issue, 对方很nice,指出了我的不少提交错误格式。下次递交一定改正:)

最后等了很久终于合并进主仓库了,提交的注释还是对方帮我写的:)

MT7688看门狗模块还有个寄存器可以知道最近一次重启是看门狗导致的还是系统软重启,这个很有用,可以帮助判断是否死机过。

BTW: 最近空余时间在玩arduino,感觉这是单片机里的OpenWRT啊:),大大降低了开发单片机的难度,而且几个大的创客社区都提供现成的模块和软件包,与我之前上学时候玩的单片机是天壤之别啊,概况技术的进步!!! 最后抱怨一下电压是个坑,5V和3.3V模块混杂,这个有点头疼。

AM335X移植OpenWRT 二

上篇说到OK335xD开发板移植到OpenWRT后网口一直不行,装了tcpdump抓包发现数据能接受但不能发送。

最后搜索到这个TI官方论坛的帖子,说明可能是TCLK频率不对,因为RCLK是PHY芯片AR8031提供的,频率是25MHZ,但TCLK是AM335X提供的PLL分频后提供的,如果PLL配置不对TCLK会错误的频率导致发生失败。

enter image description here

AM335X 以太网Clock是通过CORE_CLKOUTM5提供的(250MHZ),一般来说TCLK千兆网口的话需要125MHZ,百兆网口需要25MHZ,十兆需要2.5MHZ, 我现在用的100M网口,TCLK需要达到25MHZ。

检查一下现在系统中的CORE_CLKOUTM5:

root@OpenWrt:/tmp# cat /sys/kernel/debug/clk/clk_summary | grep m5
         dpll_core_m5_ck              2            2   50000000          0 0  

发现只有50MHZ,所以问题出在这里,应该是uboot没配置好PLL参数,换了一个板子自带的就OK了:

root@OpenWrt:/tmp# cat /sys/kernel/debug/clk/clk_summary | grep m5
         dpll_core_m5_ck              2            2   250000000          0 0  

AM335X移植OpenWRT 一

我手上有一个forlinx的AM335X开发板OK335xD,自带的Linux内核是3.2的而且我测试发现一旦网络传输数据稍大kernel就panic,调试了好久都没搞好(我试了TI官方的SDK,也一样)。

最近看到LEDE是支持OMAP的,抱着试试看的精神就下了最新的LEDE 17.1.04试试。编译用了默认的AM33xx target profile,uboot随便找了个之前AM335x的uboot(这是个坑)。编译后bin目录里是内核,文件系统需要到build_dir的linux_omap里去找root.ext4,我嫌麻烦就上LEDE官网下了一个am335x-evm-ext4-sdcard.img.gz(别看是5M的压缩文件,解压后是256M大文件,估计里面都是0XFF或者是0x00,其实真正文件系统用到10M左右,这个以后可以优化缩小一下-_-!!!)烧到SD卡里,然后替换一下uboot和kernel。

接下来是device tree文件了,这个就要花时间调试了。参考TI EVM的am335x-evm.dts文件复制到forlinx.dts,修改dts/Makefile只编译forlinx.dtb。

需要注意的点是:

  1. 根据板子原理图电源管理芯片是tps65217,需要添加tps65217的节点,而且要根据原理图写好各个dcdc和LDO的节点。 TI的evm板子里DCDC2是MPU,DCDC3是core,而OK335xD反了一下,而且DCDC1用来控制DDR3。

    dcdc1_reg: regulator@0 {
        /* DDR3 VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
        regulator-name = "vdd_ddr3";
        regulator-min-microvolt = <925000>;
        regulator-max-microvolt = <1150000>;
        regulator-boot-on;
        regulator-always-on;
        regulator-always-on;
    };
    
    dcdc2_reg: regulator@1 {
        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
        regulator-name = "vdd_core";
        regulator-min-microvolt = <925000>;
        regulator-max-microvolt = <1150000>;
        regulator-boot-on;
        regulator-always-on;
    };
    
    dcdc3_reg: regulator@2 {
        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
        regulator-name = "vdd_mpu";
        regulator-min-microvolt = <925000>;
        regulator-max-microvolt = <1351500>;
        regulator-boot-on;
        regulator-always-on;
    };
    

    具体电压可以比对官方的datasheet的OPP:

    enter image description here

    上图能看到OPP turbo时能到720M,其实AM335x A8最高能支持到1G,好像最新LEDE主分支里合并了4.9支持1G了,我现在用的4.4.92还不支持,最高只能跑到720M,等下次更新了再说吧。

    root@OpenWrt:~# cat /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies 
    275000 500000 600000 720000 
    
  2. OK335xD用的是NAND(暂时不用),所以只有添加一个SD卡启动的MMC1就好了:

    &mmc1 {
        bus-width = <4>;
        vmmc-supply = <&vdd33>;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        disable-wp;
        status = "okay";
    };
    
  3. AM335X支持双网口(可以作为路由器),而OK335xD只用了网口1,PHY芯片用了AR8031,而且支持千兆网口(用了rgmii接口),一般rgmii接口信号线需要引入人为的delay,参考这篇有说明。我看了AR8031的datasheet和内核的代码,AR8031是直接支持tx和rx delay的,只要设置一下debug register就行了,内核驱动at803x.c里也是这么干的:

        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
            ret = phy_write(phydev, AT803X_DEBUG_ADDR,
                    AT803X_DEBUG_SYSTEM_MODE_CTRL);
            if (ret)
                return ret;
            ret = phy_write(phydev, AT803X_DEBUG_DATA,
                AT803X_DEBUG_RGMII_TX_CLK_DLY);
            if (ret)
                return ret;
        }
    

    但我没看到rgmii-rxid和rgmii-id的支持,所以至少对于我手上的4.4.92来说device tree只支持rgmii-txid:

    &mac {
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&cpsw_default>;
        pinctrl-1 = <&cpsw_sleep>;
        slaves = <1>;
        status = "okay";
    };
    
    &davinci_mdio {
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&davinci_mdio_default>;
        pinctrl-1 = <&davinci_mdio_sleep>;
        status = "okay";
    };
    
    &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
        phy-mode = "rgmii-txid";
    };
    

    mac集成在AM335X里,而且只用了一个网口, phy-mode是rgmii-txid。

好吧,先写到这里吧,还有很多东西没写,完整的dts在这里。下一篇要写写折腾了我很久的网口问题!!!

参考:

http://www.eefocus.com/marianna/blog/14-10/306285_18a90.html

Spectre和Meltdown相关

过完年第一天上班,我抽空看了一下Meltdown漏洞的机制,这里有一篇Raspberry Pi的Blog讲的很好。看完了解了个大概,感叹现代的处理器越来越先进复杂,触发漏洞的是不是单单一个子系统,而是CPU一堆子系统构成的机制(内存缓存、乱序执行、分支预判和Speculative execution),而且都是跟CPU性能相关的核心部件,所以修复起来肯定要伤筋动骨了。

这次的攻击是side-channel attack(翻译成旁路攻击吗?),就是类似观察系统执行指令消耗的时间去推测具体执行了什么(内存缓存对时间影响很大,所以可以判断出来地址时候缓存),这个攻击只能是查看内核或者别的进程的内存数据,还修改不了内存,不过跟之前的DRAM Row hammer结合起来就威力比较大了:)。

最后看了一下ARM受此漏洞的影响,看到A8受到影响,看来A8用了Speculative execution, Raspberry Pi用的是A7不受影响。

最近情绪低落中…

想起了 Lionel Richie 唱的 Say You Say Me :

Say you, say me
Say it for always
That's the way it should be
Say you, say me
Say it together, naturally
I had a dream, I had an awesome dream
People in the park
Playing game in the dark
And what they played
Was a masquerade
But from behind the walls of doubt
A voice was crying out 
。。。。

MT7688 AES硬件加速

最近我无聊翻翻MT7688的datasheet,注意到居然支持AES加速,赶紧搜github找到了一个能用的OpenWRT驱动MTK_AES

赶紧开搞,一路搞好好几天才慢慢摸索出linux的初步加密框架。内核的加密框架的应用层接口是AF_ALG 套接字形式,但是有一个专门的驱动模块crpytodev抽象出一个/dev/crypto设备,采用ioctl接口,而且根据官网数据对比性能更好。

于是选中OpenWRT自带的kmod-cryptodev模块,默认会选中kmod-crypto-core等一大堆依赖,其实最终只依赖aead.ko,编译好后全部加载驱动。由于系统库的加密是openssl提供的libcrypto加密库,所以需要开启openssl库的硬件加密选项 “Crypto acceleration support”(Libraries>SSL>libopenssl) ,顺便选中openssl-util工具进行测试。

  • 测试未开启AES硬件加速

    root@:/# openssl speed -evp aes-128-cbc
    Doing aes-128-cbc for 3s on 16 size blocks: 1242779 aes-128-cbc's in 2.96s
    Doing aes-128-cbc for 3s on 64 size blocks: 359528 aes-128-cbc's in 2.95s
    Doing aes-128-cbc for 3s on 256 size blocks: 93663 aes-128-cbc's in 2.95s
    Doing aes-128-cbc for 3s on 1024 size blocks: 23499 aes-128-cbc's in 2.92s
    Doing aes-128-cbc for 3s on 8192 size blocks: 2953 aes-128-cbc's in 2.96s
    bala...bala...
    The 'numbers' are in 1000s of bytes per second processed.
    type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
    aes-128-cbc       6717.72k     7799.93k     8128.04k     8240.75k   
    
  • 测试开启AES硬件加速

    root@:/# openssl speed -evp aes-128-cbc
    Doing aes-128-cbc for 3s on 16 size blocks: 276231 aes-128-cbc's in 0.65s
    Doing aes-128-cbc for 3s on 64 size blocks: 270678 aes-128-cbc's in 0.45s
    Doing aes-128-cbc for 3s on 256 size blocks: 243448 aes-128-cbc's in 0.29s
    Doing aes-128-cbc for 3s on 1024 size blocks: 179638 aes-128-cbc's in 0.34s
    Doing aes-128-cbc for 3s on 8192 size blocks: 45879 aes-128-cbc's in 0.11s
    bala...bala...
    type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
    aes-128-cbc       6799.53k    38496.43k   214905.82k   541027.39k  3416734.25k
    

主要是看最后一行的吞吐量测试,效果惊人啊!!!!

不开启加速时数据吞吐量变化不大,毕竟这里的性能瓶颈是在AES软件实现这块,而开启硬件加速后,数据块越大效果越好,最后的8192字节块效果就提升了414倍。

这里openssl需要开启-evp选项,这样底层的crpyto库会优先选择硬件加速。openssl里的cryptodev引擎是EVP接口形式提供的,所以如果使用openssl库需要加速,必须用EVP接口。不过openssl测试工具默认的加密引擎engine会自动选择cryptodev,不用再手动指定-engine cryptodev了。

这里比较郁闷的是mtk_aes支持AES的ECB和CBC,但是openssl的libcrypto库的enc_cryptodev.c里只支持CBC,所有最终能加速的只能是AES的CBC了,估计ECB不太安全吧,连CBC也不是很安全,现在普遍用CTR吧。CBC只是比ECB多了个IV矩阵,保证每次加密不重样。

static struct {
    int id;
    int nid;
    int ivmax;
    int keylen;
} ciphers[] = {
    {
        CRYPTO_ARC4, NID_rc4, 0, 16,
    },
    {
        CRYPTO_DES_CBC, NID_des_cbc, 8, 8,
    },
    {
        CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24,
    },
    {
        CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16,
    },
    {
        CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24,
    },
    {
        CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32,
    },
# ifdef CRYPTO_AES_CTR
    {
        CRYPTO_AES_CTR, NID_aes_128_ctr, 14, 16,
    },
    {
        CRYPTO_AES_CTR, NID_aes_192_ctr, 14, 24,
    },
    {
        CRYPTO_AES_CTR, NID_aes_256_ctr, 14, 32,
    },
# endif
    {
        CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16,
    },
    {
        CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16,
    },
    {
        CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0,
    },
    {
        0, NID_undef, 0, 0,
    },
};

接下来用AES CBC加密一个20M的文件:

root@:/tmp# head -c 20m /dev/zero >test

root@:/tmp# time openssl enc -e -aes-128-cbc -in test -out test.out -kfile pgrade_pass 
real 0m 0.74s
user 0m 0.10s 
sys 0m 0.63s

root@:/tmp# rmmod mtk_aes 
root@:/tmp# time openssl enc -e -aes-128-cbc -in test -out test.out -kfile upgrade_pass 
real 0m 3.33s
user 0m 2.93s 
sys 0m 0.38s

提升了5倍。

我这里的openssl的版本是1.0.2e,最新的1.1版本支持AES的ECB的,我没试过,Cryptodev是1.7版本。现在应用就是以后加解密文件有点用,如果是优化ssh和scp估计也不是很好,比较这些应用瓶颈往往是网速,并且如果是小数据加密的话效果差别不大,只在大数据吞吐时才有差别。

MT7688 AP-Client模式

最近我在研究MT7688的闭源WIFI源码,发现默认开启了AP和AP-Client模式,但STA模式默认没选中,估计要支持的话得修改代码。

MT7688我以及在用LEDE了,新的系统很流畅,所有顺便也把WIFI移植了,修改了几个不兼容的地方基本OK了。本来是想公开的,但这个是MTK闭源驱动-_-!!!,不能公开。

涉及到的MT7688.dat里的驱动参数是这么几个:

ApCliEnable
ApCliSsid
ApCliBssid // 这个不是必须,如果不提供,wifi驱动会自己去查找
ApCliAuthMode
ApCliEncrypType
ApCliWPAPSK

但是OpenWRT里默认的uci2dat支持这些参数有BUG,因为uci2dat默认只支持一个wifi-iface,但AP-Client模式必须有两个wifi-iface,一个做AP,一个做Client。修改uci2data:

@@ -1061,23 +1064,69 @@ void hooker(FILE * fp, param * p, const char * devname)
 #endif
    else if (0 == strmatch(p->dat_key, "ApCliEnable"))
    {
-       FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_enable.value);
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_enable.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_enable.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_enable.value);
    }
    else if (0 == strmatch(p->dat_key, "ApCliSsid"))
    {
-       FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_ssid.value);
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_ssid.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_ssid.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_ssid.value);
+   }
+   else if (0 == strmatch(p->dat_key, "ApCliBssid"))
+   {
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_bssid.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_bssid.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_bssid.value);
    }
    else if (0 == strmatch(p->dat_key, "ApCliAuthMode"))
    {
-       FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_authmode.value);
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_authmode.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_authmode.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_authmode.value);
    }
    else if (0 == strmatch(p->dat_key, "ApCliEncrypType"))
    {
-       FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_encryptype.value);
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_encryptype.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_encryptype.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_encryptype.value);
    }
    else if (0 == strmatch(p->dat_key, "ApCliWPAPSK"))
    {
-       FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_password.value);
+        int j;
+       for(j=0; j<wifi_cfg[N].vifnum; j++)
+       {
+           if (strlen(wifi_cfg[N].vifs[j].apcli_password.value) > 0)
+               FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_password.value);
+       }
+       if (j < wifi_cfg[N].vifnum)
+           FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_password.value);
    }
     /* the rest part is quite simple! */
     else

编辑/etc/config/wireless:

config wifi-device 'mt7628'
    option type 'mt7628'
    option vendor 'ralink'
    option band '2.4G'
    option channel '11'   // 这个必须是你要连接路由器的信道一致,否则会连不上的
    option country 'CN'
    option region '1'

config wifi-iface 'ap'
    option device 'mt7628'
    option ifname 'ra0'
    option network 'lan'
    option mode 'ap'
    option ssid 'AP名'
    option key 'AP密码'
    option encryption 'psk2'
    option wpa_crypto 'TKIP+AES'
    option hidden '1'

config wifi-iface 'sta'
    option device 'mt7628'
    option ifname 'apcli0'
    option network 'wan' // 作为外网接口
    option mode 'sta'   //  这个没用,uci2dat根本不解析
    option ApCliEnable '1'
    option ApCliSsid '路由器名'
    option ApCliAuthMode 'WPA2PSK'
    option encryption 'psk2'     // 这个必须,如果省略这个会导致WIFI驱动错误的认证协议
    option ApCliEncrypType 'TKIP'
    option ApCliWPAPSK '路由器密码'

在/etc/config/network里修改wan:

config interface 'wan'
    option ifname 'apcli0'
    option force_link '1'
    option proto  dhcp

一开始调试死活连不上,逼得只能看WIFI驱动代码发现底层的认证协议需要加上option encryption,还有就是如果是AP-Client模式的话就不能自动选择信道了,必须跟着路由器的信道来,其实把AP和Client做个桥接就是一个信号中继了,不过WIFI驱动底层好像支持MAC层上的中继,这个没空研究了。

在LEDE的iwinfo没法查看WIFI的Link Quality,而且iw也输出为空,原因就是WIFI驱动还没启用CFG80211支持。但是MT7688的WIFI驱动比较老,导致CFG80211的代码跟最新的内核不兼容,所以我疯狂的在github上一遍查找补丁,一遍修改代码。最后总算是能运行iw了,但是iwinfo输出的信息不全,估计是通过ioctl的方式与驱动打交道,驱动不支持,这个后面再修复。

我关于最近爆出的WIFI的WPA2漏洞KRACK,深感震惊!基本上所有WIFI设备没有幸免,那些IoT设备估计永远都没法更新补丁。根据漏洞描述,基本上是可以揭秘客户端或双向通信的数据,但不能破解WIFI密码!

BTW: 这个是几个礼拜前搞的了,放草稿箱里都要长草了,今天晚上抽空填了坑,近年来记忆力衰退,必须多记录!!!

MT7688开发板linux内核补丁记录

我手上的MT7688的开发板用的是Openwrt的系统,内核版本是3.18.23,有点老,调试过程中各种BUG,记录一下。

1. JFFS2 directory hardlinks BUG

在升级软件包重启后(保护删除文件的操作),报目录硬链接问题(JFFS2支持硬链接,目录不允许硬链接)

这个BUG在JFFS2官方的git软件仓库里修复了

2. JFFS2 incorrect i_nlink count after jffs2’s RENAME_EXCHANGE operations

删除文件和目录时报错:

[  291.190000] ------------[ cut here ]------------
[  291.190000] WARNING: CPU: 0 PID: 1218 at fs/inode.c:339 inc_nlink+0x50/0x74()
[  291.200000] Modules linked in: ...balabala...
[  291.290000] CPU: 0 PID: 1218 Comm: rm Not tainted 3.18.23 #25

这个补丁有人很早就提交给OpenWRT了,可惜都没合并进来,要找补丁可以去LEDE找,看人家多勤快。

3. MT7688的第二路SPI全双工模式挂了

这个我调了好久,MT7688有两路SPI,开发板上SPI0被用来连NOR FLASH做系统用了,我好奇找了另外一块NOR FLASH想连在SPI1上。可惜的是死活不行,检查了各种连线(SPI_CS1被MT7688做启动选项引脚了,启动必须拉低,但这样会片选NOR FLASH,不知道启动会不会有影响),无奈上网翻找补丁。

补丁在这里找到了SPI1全双工挂掉补丁

后记

OpenWRT看来老了,补丁更新不勤快,系统臃肿,是时候切换到LEDE了。

Flex和Bison

最近我想在程序中加一个命令行接口,同时可以作为简单的RPC调用协议使用。这个之前在看libiio里的iiod源码时接触到了Flex和Bison写的命令行接口RPC,

简单的例如:

send cmd 
返回SUCCESS或FAIL

这个虽然直接自己写一个也可以,但是效率和复杂度上有点顾虑。Flex的正则表达式能很好的处理命令行字符串,用Bison去处理命令行的组合虽然有点大材小用,不过万一以后写一个带逻辑语句的命令行就比较方便。

有一点麻烦的是,Flex和Bison的C++支持文档不是很多,大多是C的。不过还好Flex和Bison直接输出C++源码,边看源码边改还算方便。这里特别说一下OREILLY有本动物书是《flex&bison》,网上有PDF版,但用的版本老了点。

其他的没啥好写了,我也在学习中…

https://www.gnu.org/software/bison/manual/html_node/index.html#SEC_Contents