DragonBoard 410c w/ UEFI

DragonBoard 410c runs Windows RT 8.1

I purchased a Qualcomm DragonBoard 410c for some specific purpose (generally, for fun). All DragonBoard 410c ship with Android, but I want Windows IoT and UEFI so I flashed it.

Dragonboard 410c runs Windows RT 8.1
Dragonboard 410c runs Windows RT 8.1

Well, you can boot Windows RT 8.1 on it, as long as you got critical HAL extensions. But the most important one, USB controller, is not available on DragonBoard 410c. It utilizes USB Role Switch, which is officially supported in Windows 10, not in Windows 8.1. I posted how to boot Windows RT 8.1 installation disk on XDA Developers forum, if you are interested in that, please search it.

Note: USB will not be a problem for DragonBoard 800 because Snapdragon 800 has more than one USB channel, while Snapdragon 410 has only one USB channel.

Windows failed to load with Bugcheck code 0x5c
Windows failed to load with Bugcheck code 0x5c

I think there’s something weird with the internal EFI shell. It seems that all GOP operations will let the firmware hang, however, you can run EFI applications with GOP in the internal EBL(yet another lightweight EFI shell). What’s more, if you boot any Windows OS releases from EFI shell, it will crash during HAL initialization. Such situation doesn’t exist on any Qualcomm-based Windows Phones (MSM8960), so I believe it is a bug specific to 410c’s firmware.

Huaji PC Boot Logo
Huaji PC Boot Logo

All ACPI-related files, including boot logo, is stored in a small hidden FAT16 partition called PLAT. You can replace files – but I haven’t tested customized ACPI DSDT table. Maybe we can let USB controller work by removing device URS0 and expose device USB0 to root.

GRUB-EFI (ARMHF) works on Qemu emulator, but it will hang on 410c’s firmware. I haven’t got a USB UART cable yet, so I didn’t know what happened.

Rule-based Routing & Traffic Forwarding with IPsec Site to Site VPN and Linux

This article is adapted from https://www.v2ex.com/t/180070 and http://hjc.im/shi-yong-strongswanda-jian-ipsecikev2-vpn/. The major difference is ShadowVPN is replaced by StrongSwan IPsec VPN in this article.

Readiness Check

  • Upgrade your staging/production environment to the latest version. Make sure all security patches are installed.
  • Make sure you have packages libpam0g-dev libssl-dev make gcc installed.

Building StrongSwan

Download the latest version here: http://download.strongswan.org/strongswan.tar.gz

Unarchive it, and configure using the following params:

./configure  --enable-eap-identity --enable-eap-md5 
--enable-eap-mschapv2 --enable-eap-tls --enable-eap-ttls --enable-eap-peap  
--enable-eap-tnc --enable-eap-dynamic --enable-eap-radius --enable-xauth-eap  
--enable-xauth-pam  --enable-dhcp  --enable-openssl  --enable-addrblock --enable-unity  
--enable-certexpire --enable-radattr --enable-tools --enable-openssl --disable-gmp --enable-kernel-libipsec

We have to specify routing table’s priority on client server(not IPsec Access Server) since we wants to specify routing table manually: –with-routing-table-prio=32800.  Also, TAP/TUN device is enabled instead of StrongSwan’s own kernel module. It will simplify the configuration later.

Then make and install it.

Configure IPsec Access Server

Just a reminder, if you have any issues about IP range, please refer to the demo topology graph. The image is unavailable right now for some reason. I’ll fix it ASAP.

Go to /usr/local/etc. Edit ipsec.secrets:


Go to /usr/local/etc. Edit ipsec.conf:

config setup

conn s2sbj1_xauth_psk

Go to /usr/local/etc. Edit strongswan.conf:

 charon {
         load_modular = yes
         duplicheck.enable = no
         compress = yes
         plugins {
                 include strongswan.d/charon/*.conf
         # In China, please consider about replacing to They do offer correct DNS query results outside mainland China, as long as you have configured the Chinese routing exception for it(route to non-mainland China outbound server)
         dns1 =
         dns2 =
         nbns1 =
         nbns2 =
 include strongswan.d/*.conf

Turn on IPv4 forwarding in sysctl.conf.

Edit iptables. The following configuration is for Ubuntu 14.04 LTS. For other Linux distro, check out its documentation.

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s  -j ACCEPT
iptables -A FORWARD -s  -j ACCEPT
iptables -A FORWARD -s  -j ACCEPT
iptables -A INPUT -i eth0 -p esp -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport 500 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 500 -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport 4500 -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport 1701 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 1723 -j ACCEPT
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

Save it

iptables-save > /etc/iptables.rules
cat > /etc/network/if-up.d/iptables<<EOF
iptables-restore < /etc/iptables.rules
chmod +x /etc/network/if-up.d/iptables

Configure IPsec client

Suppose you have the correct StrongSwan with TAP/TUN and routing table priority installed.

Go to /usr/local/etc, edit ipsec.secrets, just put what you have in the previous step.

Go to /usr/local/etc, edit ipsec.conf:

config setup

conn s2sbj1
    # Enable this will cause authentication failure
    left=<eth0's IP address>
    # Ask your server
    right=<Your IPsec VPN Server's public IP address>
    # For Microsoft Azure and other service providers who use SNAT, specify that to prevent IKE_SA failure

Establish Connection

On your IPsec VPN server, type sudo ipsec start .

On your client server, type:

sudo ipsec start
sudo ipsec up s2sbj1

It should get connected shortly. Go to ifconfig and you should find a new network adapter called ipsec0.

Configure rule-based routing

Create a new routing table.

user@ibntwkstgepbj1:~$  sudo vim /etc/iproute2/rt_tables
200 bj1s2s

Get the routing configuration in table 220 (IPsec table).

user@ibntwkstgepdm1:~$  sudo ip route list table 220
default dev ipsec0  proto static  src via dev eth0  proto static  src

Specify the default route for this table (copy it from 220):

user@ibntwkstgepdm1:~$  sudo ip route add default dev ipsec0  proto static  src table bj1s2s

(You don’t have to copy the second line I guess, but I added that)

Add IP rules.

user@ibntwkstgepdm1:~$  ip rule add from <IP Range> table bj1s2s

Refresh routing table.

user@ibntwkstgepdm1~$  ip route flush cache

Compose a shell script if you want to compelte that automatically for every reconnection.


We implemented a simple line optimization using rule-based routing in this example. For application-based service, you are all set and ready to go. For VPN access services, configuration for iptables is needed in order to tag data packets and route them correctly. Check out this article for more details.

I didn’t offer a auto routing script in this example. I strongly recommend you to write it since it saves your time by configuring routing table automatically.

For multiple IPsec connections and routings, just specify the source IP, which is and in routing tables. They use the same adapter.

Using WASAPI Exclusive mode in Universal Windows Apps (Desktop)

Windows Audio Session API (WASAPI) was first introduced in Windows Vista. It offers advanced audio control and playback features for Windows Apps. Since it mitigates SRC issue in some aspects, WASAPI Exclusive Mode gains its popularity among music lovers. Windows Runtime supports a small subset of WASAPI APIs, including WASAPI Exclusive mode (in Windows 10).

However, here is one thing you should know: Windows 10 Mobile doesn’t support WASAPI Exclusive mode (by design).  As far as I know, only desktop platform is supported yet. Luckily, modern Windows Phone devices can choose the best format for shared mode using input wave’s format, so you don’t have to worry that (at least on Lumia 950 and Lumia 950 XL).

Audio Format

There’s no IMMDevice available in Windows Runtime. Try to create it via CLSID & IID will throw HRESULT Class Not Registered. It will cause some trouble getting all natively supported formats for Exclusive mode. A possible solution is using Properties property in DeviceInformation class in Windows Runtime instead of IMMDevice class & OpenPropertyStore method. Then, query the format using IsFormatSupported in IAudioClient2. Remember that in Exclusive Mode, system won’t return the best-fit wave format in this method, so you have to try all formats and select the best wave format by yourself. In my sample, I specified 44.1kHz / 16Bit / WaveFormat = 0x1, which is supported by my Surface Pro’s audio subsystem.

Initialize Audio Client

Then you can initialize IAudioClient2 in exclusive mode. Simply pass AUDCLNT_SHAREMODE_EXCLUSIVE in, specify Buffer Length and Wave Format. You may get some HRESULTs like AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED or AUDCLNT_E_BUFFER_SIZE_ERROR. Just check out this page and find solutions.

Perform Playback

Like HW-Offload mode, you don’t have to calculate available frames by yourself In event-based playback mode. The value for padding frames is exactly the same as available frames. Then return audio samples as what you do in shared mode.


It should supports Windows 8.1 desktop, but I haven’t test it on Windows 8.1 since I don’t have a Windows 8.1 desktop device.

I often noticed weird noise during playback when the system average load is high. I believe the root cause is process priority.

Windows 10 removed Background Audio category in WASAPI headers. In order to implement background playback, a customized out-of-process COM server or Media Foundation extension is required.

I don’t offer a demo program here, because it’s pretty easy to adapt the official sample to WASAPI Exclusive mode. 🙂

玩物丧志 · Yubikey 4 (智能卡登录)

Yubikey 是很早就有的东西了,然而受限于经济能力还有海关,直到最近有人提出来要团购我才买了个一个玩玩。我主要拿来做智能卡登录。


虽然我用的电脑都装备有了 TPM ,但是这样还是有一些不方便的:

  • TPM 的数据基本上只留在这台电脑了(这也是优点)
  • 虽然我的电脑很轻,但是我不一定天天带出去,万一有事情需要连接到服务器上还是比较麻烦
  • 虚拟智能卡基本上一直在域账号里使用比较有效,然而我平时还是以登录个人账号为主(虽然电脑已经加入域)
 Yubikey 可以解决移动性的问题,而且出门不需要输入一个几十位复杂脑残的密码。
也许我哪天要玩玩 U2F 呢?这大概是以后的文章了。


假定电脑已经加入域,域环境中已经部署了 Active Directory Certificate Services,并且 CS 服务器已经发布到 AD 中。

登录域账号,打开 Certificate Management,并 Request New Certificate。
一路往下,选择 Smart Card User / Smart Card  Logon 模板(我选的是前者)。
在 Private Key Configuration 下把私钥长度设置为 2048/4096,然后 CSP 不用动。
注:如果你选择了 Smart Card Crypto Service Provider,那么默认情况下在有 TPM 而且虚拟智能卡开启的情况下,会选择的是虚拟智能卡,在 Windows 证书选择里表示为“安全设备凭据”而不是“智能卡凭据”,但是功能类似。然后勾选允许导出私钥。
打开 Yubikey PIV Manager,并导入证书。
Screenshot of Yubikey PIV Manager
Screenshot of Yubikey PIV Manager


如果是要给 Active Directory Federation Services 打开智能卡登录支持呢?

很简单。进入 AD CS 管理界面,找到认证选项,在对应的 Intranet / External 认证模式里勾选证书登录,AD FS Web Proxy 启用49443端口即可。

Smartcard and ADFS
Smartcard and ADFS



自制 Federation STS: MediaWiki x ASP.NET OWIN Identity

最近在做一个和 MediaWiki 扩展管理的项目时遇到一个问题:如何安全地把身份凭据传递给ASP.NET MVC的后端,而且共用一套账号系统。


了解 WS-Federation

在 ASP.NET OWIN Identity 里,最方便的实现 Claim Identity 凭据的方法也就是 WS-Federation。WS-Federation 最典型的一个例子就是Active Directory Federation Service,其具体工作流程可以简化为以下的图表:

WS-Fed workflow from docs.oasis-open.org
WS-Fed workflow from docs.oasis-open.org

在本文的场景中,MediaWiki 将充当 IdP 的角色。

获得 Federation Metadata

Federation Metadata是一个XML-Dsig签名后的XML文件,包含了 SP 需要的所有信息,诸如提供的 Claim Identity 类型,公钥,访问端点。一个简化的 Federation Metadata 如下文所示:

<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="_3ef47b02-f5a9-4a32-a48d-3ba56d6b270f" entityID="">
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <!-- 这里是签名,是 enveloped-signature + xml-exc-c14n -->
  <!-- 推荐 sha256RSA -->
  <!-- 记得带上公钥 -->
    <RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        <KeyDescriptor use="signing">
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
     <!-- 用于STS签名的公钥, base64 encoded -->
   <!-- 提供的 Claim Identity Types,下面举例四个 -->
            <auth:ClaimType xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" Optional="true">
                <auth:Description>User Principal Name</auth:Description>
            <auth:ClaimType xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" Optional="true">
                <auth:DisplayName>User Name</auth:DisplayName>
                <auth:Description>The mutable display name of the user.</auth:Description>
            <auth:ClaimType xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" Optional="true">
                <auth:Description>Email address of the user.</auth:Description>
            <auth:ClaimType xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" Uri="http://schemas.microsoft.com/ws/2008/06/identity/claims/groups" Optional="true">
                <auth:Description>Groups of the user.</auth:Description>
  <!-- 服务Endpoint -->
            <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
            <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
    <RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fed="http://docs.oasis-open.org/wsfed/federation/200706" xsi:type="fed:SecurityTokenServiceType" protocolSupportEnumeration="http://docs.oasis-open.org/wsfed/federation/200706">
        <KeyDescriptor use="signing">
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
     <!-- 用于STS签名的公钥, base64 encoded -->
  <!-- 服务Scope -->
  <!-- 确保Scope和后续的Audience匹配 -->
            <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
  <!-- 服务Endpoint -->
            <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
            <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
    <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <KeyDescriptor use="signing">
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
     <!-- 用于STS签名的公钥, base64 encoded -->
  <!-- 服务Endpoint -->
        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location=""/>
        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location=""/>
        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location=""/>

STS 服务

SP在解析 Federation Metadata 后会发起请求。一般在OWIN-based里会带上如下的参数:
– wa: 动作。可以是wsignin1.0 (登录) 和 wsignout1.0 (登出)
– wctx: 上下文。附上即可
– wp: 可能有
– wreply: 如果手动指定,则返回到这个页面;如果不指定,根据应用默认注册情况来
– wtrealm: 应用ID

所有的参数都在 Query String 里。在收到 STS 请求后,IdP首先根据情况判断有无再次输入密码必要。然后判断身份,签发凭据。签发的凭据也是一个XML文档,里面包含有一个SAML文档(XML-Dsig),简化的格式如下:

<?xml version="1.0" encoding="utf-8"?>
<t:RequestSecurityTokenResponse xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<!-- 需要标注有效时间 -->
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-02-12T05:13:30+0000</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-02-12T06:13:30+0000</wsu:Expires>
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<t:RequestedSecurityToken xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<!-- 需要标注有效时间,AssertionID一般就是一个UUID -->
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" MajorVersion="1" MinorVersion="1" AssertionID="_7529070a-0300-4b65-bdee-df0e55c2c775" Issuer="签发者,参考metadata" IssueInstant="2016-02-12T05:13:30+0000">
<saml:Conditions NotBefore="2016-02-12T05:13:30+0000" NotAfter="2016-02-12T06:13:30+0000">
<!- 请注意这个必须和Scope匹配 -->
<!-- 各种 Claim Identity结果 -->
<!-- 请注意不能有空的Attribute -->
<saml:Attribute AttributeName="upn" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:Attribute AttributeName="emailaddress" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:Attribute AttributeName="name" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" AuthenticationInstant="2016-02-12T05:13:30+0000">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<!-- 签名段,只需要对SAML签名。参考前面的XML签名 -->

然后将其进行 HTML 表单编码,封装到返回里。提供一段PHP代码作参考:

 $output->addHTML("<form method="POST" name="hiddenform" action="{$escapedToken}/">");
        $output->addHTML(' <input type="hidden" name="wa" value="wsignin1.0" />');
        $output->addHTML(" <input type="hidden" name="wresult" value="{$resultXml}" />");
        $output->addHTML(" <input type="hidden" name="wctx" value="{$this->wCtx}" />");
            $output->addHTML(" <input type="hidden" name="wp" value="{$this->wp}" />");
        $output->addHTML(' <noscript><p>Script is disabled. Click Submit to continue.</p><input type="submit" value="Submit" /></noscript>');
        $output->addHTML(' </form>');
        $output->addHTML(' <script language="javascript"> window.setTimeout('document.forms[0].submit()', 0); </script>');

在 MediaWiki 的工作流程

通过 MediaWiki 的 User.php 里的函数获得必要的信息。
写 SOAP XML 和 SAML XML。用 xmlseclibs 对 SAML XML 签名,封入 SOAP XML,封入表单,返回特殊页面。
ASP.NET OWIN Identity 完成后续验证。


新建 ASP.NET MVC v4.6 项目,认证模式选择 Work and School account,然后选择 On-Premise。输入 Federation Metadata 位置,输入 URI (如果实现了 App 注册,请输入对应的URI)


MediaWiki 的特殊页面输出非 text/html 有点麻烦,我选择了直接暴露一个在 extensions/文件夹/StsMetadata.php 的文件来暴露。
STS 所需的证书可以用 OpenSSL 生成。
由于 xmlseclib 在 URI 处的一些处理原因,目前似乎无法和 Azure ACS 直接工作,但是可以跟 ASP.NET OWIN Identity 工作。
一般来说,wsignout1.0 的处理就是销毁 Cookie ,注销 ST S这边的登录,ASP.NET 这儿会有 OWIN 自己处理,然后跟 wsignin1.0 的表单类似,但是不需要返回SAML数据。


Understanding WS-Federation – MSDN
Web Services Federation Language (WS-Federation) Version 1.2


“You will pay.”






Screenshot (475)

于是今天是动用最终决定权解除一位前辈的管理员权限。给的理由也是很奇怪:“其行为越发偏执,从11月开始计算到2月,四个月间蓝羽是投诉数量最高的管理员(没有之一, 编辑数/投诉量 率也是最低的),也是用户意见最严重的管理员。用户反感主要集中在专行独断不接受他人意见和双重标准上。 ” 然后并没有提供其他的有效证据来支持上述结论。所谓“这个问题已经严重到连萌百管理群体内忆兔等巡查管理都开始受不了其刻薄言辞”也只是一笔带过,并没有其他证据。而且,投诉数量/编辑数这个奇怪的判断方法,真是让人摸不着头脑。现实很简单,小学生确实存在;如果有编辑,必定有投诉。在某些情况下,即使蓝羽有被大量投诉,也应该拿出统计数据来说服人。有没有学过统计学啊……



空明流转菊苣说得对,团队的事情是不是做得好,大佬能不能make sense确实非常重要。然而在遇到leader一意孤行的情况下,我不看好事情的走向,除非在哪天有了重大事情能让leader突然醒悟过来。大概这就是“头碰圆”吧? 我很少这么写文章,议论别人其实并不是我的一贯作风。But You will pay.



几年前初中的班长写过随笔讲了语言的力量。那个时候他提醒了我们不恰当的说话方式可能会造成非常严重的后果。前两天我发过一篇文章, 又让我回想起这随笔。很早以前还看到过D君的一篇文章,也讲了一些因为争吵而造成的不快的事情,总之是没有这次的这么严重。