lynxariushttps://lunarius.fe80.eu/blog/2023-09-30T23:43:00+02:00Recover a Shelly Dimmer v12023-09-30T23:43:00+02:002023-09-30T23:43:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2023-09-30:/blog/recover-shelly-dimmer-via-uart.html<p class="first last">How to recover a Shelly Dimmer (v1)</p>
<p>A friend of mine tried out tasmota on a Shelly Dimmer, but he decided
in the end to go back to the Shelly firmware because of the calibration
and more precise configuration of the dimmer.
The dimmer connected to a LED and you want to match
the lowest possible energy to start at an offset because the LED
won't turn on until you reach 50% duty cycle.</p>
<p>After trying flashing back from tasmota to Shelly, the dimmer
broke down and couldn't be controlled by wlan anymore.</p>
<p>To recovery the Shelly Dimmer you need to have:</p>
<ul class="simple">
<li>Debug connector <strong>1x6 RM 1.27</strong></li>
<li>USB UART for 3.3V</li>
<li>Shelly Recovery Firmware</li>
<li>esptool.py</li>
</ul>
<pre class="code literal-block">
Disconnect the 230 Volt connectors before connecting anything else to it!!!
</pre>
<p>The Shelly Dimmer comes with a debug connector which is accessable from outside
and it consist of <strong>1x6 RM 1.27</strong>.
You may find different pinouts for the Dimmer.
The correct pinout for the <strong>Shelly Dimmer v1</strong> is:</p>
<pre class="code literal-block">
[x][x][x][x][x] 230V connector
[] U0TXD
[] U0RXD
[] GPIO2
[] GPIO0
[] 3V3
[] GND
* Button
</pre>
<p>Most USB UARTs will provide a good enough power supply for the shelly to boot up.</p>
<p>You need to connect a 3.3V UART to U0TXD, U0RXD, 3V3 and GND.
Further you need to connect <strong>GPIO0 to GND</strong> to get the ESP8266 into boot mode.</p>
<p>Power cycle the ESP either by remove the 3.3V pin or by cycling the USB port.</p>
<p>There are multiple "recovery" firmwares around. I've used the following:</p>
<ul class="simple">
<li><dl class="first docutils">
<dt><a class="reference external" href="https://www.shelly-support.eu/filebase/entry/113-shelly-dimmer-recovery-firmware-1-5-10/">https://www.shelly-support.eu/filebase/entry/113-shelly-dimmer-recovery-firmware-1-5-10/</a></dt>
<dd><ul class="first last">
<li>sha256: dimmer.bin ca6f01534215838cd3858c7ca24a8f1a64b22e8da6b0d55746f71368ff2d47ee</li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>I'm strongly recommend you're doing a full backup before flashing the recovery firmware.
There might be calibration data in the firmware.</p>
<pre class="code literal-block">
# check if the connection works
esptool.py -p /dev/ttyUSB0 chip_id
# create a backup
esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x200000 shelly_dimmer_v1_backup.bin
# flash the recovery firmware
esptool.py -p /dev/ttyUSB0 write_flash 0x0 dimmer.bin
</pre>
<p><strong>Please disconnect now GPIO0 and U0TXD and U0RXD.</strong> U0RXD and U0TXD is used to communicate with an auxillary micro controller
which controls the 230V. If you don't disconnect the U0RXD/U0TXD, a firmware update will be stuck because it can't talk with the micro controller.</p>
<p>Now connect to the Accesspoint of the Shelly, connect it into your wireless network and do a firmware update.</p>
<p>The Shelly Dimmer should be ready to build it into your home again.</p>
Boot a u-boot via u-boot2022-11-16T10:10:00+01:002022-11-16T10:10:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2022-11-16:/blog/openwrt-u-boot-boot-u-boot.html<p class="first last">How to boot u-boot from u-boot? Before flashing a new boot loader testing would be great. Booting u-boot from u-boot allows to test higher levels of the u-boot firmware.</p>
<img alt="Simplified view of the boot process of the mt7622. Romloader to first u-boot to second u-boot to Linux/OpenWrt" src="https://lunarius.fe80.eu/blog/files/openwrt/how-to-boot-u-boot-with-uboot-mt7622-graph.png" />
<p>Having full control of the boot process is always great.
Either because you want to use features the original boot loader doesn't support. Most times a better compression, device-tree support or ubifs to improve resilance against bad blocks. Having the control also improves security because you know what you compiled and with reproducible builds there is also a relation between your source code and your binary.
The reasons against replacing the bootloader are usually breaking the device if something bad happens (and you don't have the tools available to get it back into a working state). Or if you want to make it easier to get back to the original state of the device with the OEM firmware. Both doesn't count if you develop a new device or product before it gets released.</p>
<p>For my current project I don't have JTAG working neither is the flash chip on a socket. So testing a new bootloader is hard. In case of a failure I would have to desolder the chip, flash it and solder it again. Flashing it ISP (In-System-Programming) doesn't work often with wifi router or CPEs. If I'm desoldering a flash I always try to add a socket. I can recommend the <a class="reference external" href="https://github.com/felixheld/qspimux">qspimux from Felix Held</a>. It comes with sockets and a qspimux to switch between the programmer and the board.</p>
<p>For testing the basic functions I would like to boot the u-boot from the current u-boot. At least I can test the higher functions.
Does ethernet works to load a second bootloader? Can I boot from the second u-boot via tftp my u-boot?</p>
<p>OpenWrt also have a history of booting u-boot from u-boot in case the old bootloader is too buggy or have other shortcomings, some platforms just add a second u-boot (e.g. kirkwood platform).</p>
<p>To allow us to boot u-boot from u-boot, we should know what's the job of the the first u-boot? Must the hardware in a specific state? And what would be the difference between the first and second u-boot?
To get started, everything depend on the architecture (arm, mips, arm64, ..) and the specific SoC what the first u-boot really does.</p>
<p>I've a board with a Mediatek mt7622 SoC based on arm64 (to be precise 4x ARM Cortex A53 cores). We could take a look into the arm manuals how its booting.
A summary can be found in the <a class="reference external" href="https://chromium.googlesource.com/chromiumos/third_party/arm-trusted-firmware/+/v1.0/docs/firmware-design.md">arm trusted firmware repository</a>.
The main question we have to find or just test, are there parts of the SoC or components which can't or must not be initialized twice?
We should not re-initialize the memory controller if our second u-boot lies in memory.</p>
<p>The good point is the u-boot doesn't do memory initialisation and training it's done by the arm trusted firmware. Another thing
we don't have to disable.
Let's create a first u-boot image for us using OpenWrt. I expect you already added your board to the u-boot.
Otherwise we could just use the already supported mt7622_bananapi_bpi-r64-snand.</p>
<pre class="code sh literal-block">
<span class="c1"># apt install quilt flex bison
</span><span class="nb">cd</span><span class="w"> </span>openwrt<span class="w">
</span><span class="c1"># I'm using OpenWrt, current master of revision c3322cf04a1b9ee826dcc56944750b6bbcb716ef
# Select your board, and config.
# Ensure Boot Loaders -> u-boot-mt7622_bananapi_bpi-r64-snand is enabled
</span>make<span class="w"> </span>menuconfig<span class="w">
</span>make<span class="w"> </span>package/boot/arm-trusted-firmware-mediatek/clean<span class="w"> </span>package/boot/arm-trusted-firmware-mediatek/compile<span class="w">
</span>make<span class="w"> </span>package/uboot-mediatek/clean<span class="w"> </span>package/uboot-mediatek/prepare<span class="w"> </span><span class="nv">QUILT</span><span class="o">=</span><span class="m">1</span><span class="w">
</span><span class="nb">cd</span><span class="w"> </span>build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/<span class="w">
</span>quilt<span class="w"> </span>push<span class="w"> </span>-a<span class="w">
</span><span class="c1"># now lets change the u-boot config
</span>make<span class="w"> </span>mt7622_bananapi_bpi-r64-snand_defconfig<span class="w">
</span>make<span class="w"> </span>menuconfig<span class="w">
</span><span class="c1"># choose
</span>*<span class="w"> </span><span class="s2">"Skip the call to lowlevel_init during early boot ONLY"</span><span class="w"> </span><span class="o">(</span>CONFIG_SKIP_LOWLEVEL_INIT_ONLY<span class="o">)</span><span class="w">
</span>*<span class="w"> </span><span class="s2">"Boot options"</span><span class="w"> </span>-><span class="w"> </span><span class="s2">"Boot Images"</span><span class="w"> </span>-><span class="w"> </span><span class="s2">"Text Base"</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>0x43e00000<span class="w"> </span><span class="o">(</span>CONFIG_SYS_TEXT_BASE<span class="o">)</span><span class="w">
</span><span class="c1"># now go back to the openwrt top dir (where you checkout OpenWrt)
</span><span class="nb">cd</span><span class="w"> </span>openwrt/<span class="w">
</span>make<span class="w"> </span>package/uboot-mediatek/compile<span class="w"> </span><span class="nv">V</span><span class="o">=</span>s<span class="w">
</span><span class="nb">cd</span><span class="w"> </span>build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/<span class="w">
</span>ls<span class="w"> </span>u-boot*<span class="w">
</span><span class="c1"># u-boot: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped
# u-boot-dtb.bin: u-boot binary with device-tree binary appeneded
# u-boot-nodtb.bin: u-boot binary without device-tree binary
# u-boot.bin: same as u-boot-dtb.bin
# u-boot.cfg: The build config as c defines
# u-boot.fip: u-boot binary packed to be loaded by the arm trusted firmware
# u-boot.lds: linker script (can be ignored)
# u-boot.map: linker map file (can be ignored)
</span><span class="w">
</span>cp<span class="w"> </span>u-boot-dtb.bin<span class="w"> </span>/srv/tftp/
</pre>
<p>Now I tried to upload the whole binary to from the first u-boot via tftp</p>
<pre class="code sh literal-block">
<span class="c1"># u-boot shell
</span>MT7622><span class="w"> </span>tftpboot<span class="w"> </span>0x43e00000<span class="w"> </span>u-boot-dtb.bin<span class="w">
</span>MT7622><span class="w"> </span>go<span class="w"> </span>0x43e00000<span class="w">
</span><span class="c1">## Starting application at 0x43e00000 ...
</span>data<span class="w"> </span>abort<span class="w">
</span>pc<span class="w"> </span>:<span class="w"> </span><span class="o">[</span><4007ff34><span class="o">]</span><span class="w"> </span>lr<span class="w"> </span>:<span class="w"> </span><span class="o">[</span><5ef571e4><span class="o">]</span><span class="w">
</span>sp<span class="w"> </span>:<span class="w"> </span>5cf4fe28<span class="w"> </span>ip<span class="w"> </span>:<span class="w"> </span><span class="m">00000030</span><span class="w"> </span>fp<span class="w"> </span>:<span class="w"> </span>5cf5a818<span class="w">
</span>r10:<span class="w"> </span><span class="m">00000002</span><span class="w"> </span>r9<span class="w"> </span>:<span class="w"> </span>5cf4ff40<span class="w"> </span>r8<span class="w"> </span>:<span class="w"> </span>5efa3784<span class="w">
</span>r7<span class="w"> </span>:<span class="w"> </span>5cf5b2d8<span class="w"> </span>r6<span class="w"> </span>:<span class="w"> </span>4007ff28<span class="w"> </span>r5<span class="w"> </span>:<span class="w"> </span><span class="m">00000002</span><span class="w"> </span>r4<span class="w"> </span>:<span class="w"> </span>5cf5b2dc<span class="w">
</span>r3<span class="w"> </span>:<span class="w"> </span>4007ff28<span class="w"> </span>r2<span class="w"> </span>:<span class="w"> </span>5cf5b2dc<span class="w"> </span>r1<span class="w"> </span>:<span class="w"> </span>5cf5b2dc<span class="w"> </span>r0<span class="w"> </span>:<span class="w"> </span><span class="m">00000001</span><span class="w">
</span>Flags:<span class="w"> </span>nZCv<span class="w"> </span>IRQs<span class="w"> </span>off<span class="w"> </span>FIQs<span class="w"> </span>off<span class="w"> </span>Mode<span class="w"> </span>SVC_32<span class="w">
</span>Resetting<span class="w"> </span>CPU<span class="w"> </span>...
</pre>
<p>And now it crashs.
Let's take a look back into the u-boot</p>
<pre class="code sh literal-block">
<span class="nb">cd</span><span class="w"> </span>openwrt<span class="w">
</span><span class="nb">cd</span><span class="w"> </span>build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/<span class="w">
</span><span class="c1"># first find instruction of the u-boot. It's usually the start.S. We're lazy and search for start.o. The compiled version.
</span>find<span class="w"> </span>-iname<span class="w"> </span><span class="s1">'start.o'</span><span class="w">
</span><span class="c1">## ./arch/arm/cpu/armv8/start.o
# The start.S is in the same directory. Lets have a look into it with your favourite editor
</span>vim<span class="w"> </span>./arch/arm/cpu/armv8/start.S
</pre>
<pre class="code asm literal-block">
<span class="c1">// [..]
#include <asm/arch/boot0.h>
#else
</span><span class="w"> </span><span class="nf">b</span><span class="w"> </span><span class="no">reset</span><span class="w">
</span><span class="c1">#endif
</span><span class="w">
</span><span class="na">.align</span><span class="w"> </span><span class="mi">3</span><span class="w">
</span><span class="na">.globl</span><span class="w"> </span><span class="no">_TEXT_BASE</span><span class="w">
</span><span class="nl">_TEXT_BASE:</span><span class="w">
</span><span class="na">.quad</span><span class="w"> </span><span class="no">CONFIG_SYS_TEXT_BASE</span><span class="w">
</span><span class="cm">/*
* These are defined in the linker script.
*/</span><span class="w">
</span><span class="na">.globl</span><span class="w"> </span><span class="no">_end_ofs</span><span class="w">
</span><span class="nl">_end_ofs:</span><span class="w">
</span><span class="na">.quad</span><span class="w"> </span><span class="no">_end</span><span class="w"> </span><span class="p">-</span><span class="w"> </span><span class="no">_start</span><span class="w">
</span><span class="na">.globl</span><span class="w"> </span><span class="no">_bss_start_ofs</span><span class="w">
</span><span class="nl">_bss_start_ofs:</span><span class="w">
</span><span class="na">.quad</span><span class="w"> </span><span class="no">__bss_start</span><span class="w"> </span><span class="p">-</span><span class="w"> </span><span class="no">_start</span><span class="w">
</span><span class="na">.globl</span><span class="w"> </span><span class="no">_bss_end_ofs</span><span class="w">
</span><span class="nl">_bss_end_ofs:</span><span class="w">
</span><span class="na">.quad</span><span class="w"> </span><span class="no">__bss_end</span><span class="w"> </span><span class="p">-</span><span class="w"> </span><span class="no">_start</span><span class="w">
</span><span class="nl">reset:</span><span class="w">
</span><span class="cm">/* Allow the board to save important registers */</span><span class="w">
</span><span class="nf">b</span><span class="w"> </span><span class="no">save_boot_params</span><span class="w">
</span><span class="na">.globl</span><span class="w"> </span><span class="no">save_boot_params_ret</span><span class="w">
</span><span class="nl">save_boot_params_ret:</span><span class="w">
</span><span class="c1">// [..]</span>
</pre>
<p>Ok The first instruction should be a branch (or jump) to the marker reset.
Let's have a short look into the u-boot-dtb.bin.</p>
<pre class="code sh literal-block">
<span class="nb">cd</span><span class="w"> </span>openwrt/<span class="w">
</span><span class="nb">export</span><span class="w"> </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span>/staging_dir/toolchain-aarch64_cortex-a53_gcc-11.3.0_musl/bin<span class="w">
</span><span class="nb">cd</span><span class="w"> </span>build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/<span class="w">
</span><span class="c1"># the u-boot file is a elf binary
</span>aarch64-openwrt-linux-objdump<span class="w"> </span>-D<span class="w"> </span>./u-boot
</pre>
<pre class="code literal-block">
0000000041e00000 <__image_copy_start>:
41e00000: 1400000a b 41e00028 <reset>
41e00004: d503201f nop
0000000041e00008 <_TEXT_BASE>:
41e00008: 41e00000 .inst 0x41e00000 ; undefined
41e0000c: 00000000 udf #0
0000000041e00010 <_end_ofs>:
41e00010: 000f21f8 .inst 0x000f21f8 ; undefined
41e00014: 00000000 udf #0
0000000041e00018 <_bss_start_ofs>:
41e00018: 000f21f8 .inst 0x000f21f8 ; undefined
41e0001c: 00000000 udf #0
0000000041e00020 <_bss_end_ofs>:
41e00020: 000fe8c8 .inst 0x000fe8c8 ; undefined
41e00024: 00000000 udf #0
0000000041e00028 <reset>:
41e00028: 14000053 b 41e00174 <save_boot_params>
0000000041e0002c <save_boot_params_ret>:
41e0002c: 10fffea0 adr x0, 41e00000 <__image_copy_start>
41e00030: f2402c00 ands x0, x0, #0xfff
41e00034: 54000060 b.eq 41e00040 <pie_fixup> // b.none
41e00038: d503207f wfi
41e0003c: 17ffffff b 41e00038 <save_boot_params_ret+0xc>
[..]
</pre>
<p>Ok. This looks good. Maybe the u-boot <cite>go</cite> command is missing some handover or doesn't initialize the some cpu register or other state?
My first u-boot doesn't support elf binary. But it supports the uimage file format.</p>
<pre class="code sh literal-block">
<span class="nb">cd</span><span class="w"> </span>openwrt/<span class="w">
</span><span class="nb">cd</span><span class="w"> </span>build_dir/target-aarch64_cortex-a53_musl/u-boot-mt7622_mt7622_bananapi_bpi-r64-snand/u-boot-2022.10/<span class="w">
</span>mkimage<span class="w"> </span>-A<span class="w"> </span>arm<span class="w"> </span>-O<span class="w"> </span>linux<span class="w"> </span>-T<span class="w"> </span>standalone<span class="w"> </span>-C<span class="w"> </span>none<span class="w"> </span>-a<span class="w"> </span>0x43e00000<span class="w"> </span>-e<span class="w"> </span>0x43e00000<span class="w"> </span>-d<span class="w"> </span>./u-boot-dtb.bin<span class="w"> </span>/srv/tftp/u-boot.image
</pre>
<pre class="code sh literal-block">
<span class="c1"># u-boot shell
</span>MT7622><span class="w"> </span>tftpboot<span class="w"> </span>0x41000000<span class="w"> </span>u-boot.image<span class="w">
</span>MT7622><span class="w"> </span>bootm<span class="w"> </span>0x41000000<span class="w">
</span>U-Boot<span class="w"> </span><span class="m">2022</span>.10-OpenWrt-r21176-c32b761842a8<span class="w"> </span><span class="o">(</span>Nov<span class="w"> </span><span class="m">15</span><span class="w"> </span><span class="m">2022</span><span class="w"> </span>-<span class="w"> </span><span class="m">19</span>:27:37<span class="w"> </span>+0000<span class="o">)</span><span class="w">
</span>CPU:<span class="w"> </span>MediaTek<span class="w"> </span>MT7622<span class="w">
</span>...
</pre>
<p>Finally we managed to boot it. Now we can test the u-boot-env, booting via tftpboot and so on.</p>
<p><em>EDIT</em>: Fixed 3x typos in the how to build receipt. The u-boot mediatek package in OpenWrt is called <cite>uboot-mediatek</cite> and not <cite>u-boot-mediatek</cite></p>
Mikrotik wAP R AC / wAP ac LTE / wAP ac LTE62022-11-13T02:23:00+01:002022-11-13T02:23:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2022-11-13:/blog/openwrt-mikrotik-wap-r-ac-wap-ac-lte.html<p class="first last">Mikrotik wAP R AC / wAP ac LTE pictures</p>
<ul class="simple">
<li>CPU: QCOM IPQ4018 / 4x ARM Cortex A7</li>
<li>RAM: 128MB DDR3L NT5CC64M16GP-DI NANYA 1909</li>
<li>flash: 16MB SPI-NOR Winbond 25Q128JVSM</li>
<li>wifi: 2x 802.11ac, 1x 2.4Ghz, 1x 5Ghz ipq4018 with external lna/pa</li>
<li>2x 1GBit ethernet ports, 1 PoE in, 1 normal ethernet<ul>
<li>QCA8072 dual port ethernet phy</li>
</ul>
</li>
<li>miniPCIe slot: usb2 & simcard but no pcie.</li>
<li>ZT2046Q: for voltage and temp sensing. A cheap touchscreen controller compatible to <a class="reference external" href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/input/touchscreen/ads7846.c">ads7846</a>.</li>
<li><a class="reference external" href="https://lunarius.fe80.eu/blog/files/openwrt/mikrotik-wap-r-ac_front.jpg">high_res_front</a> <a class="reference external" href="https://lunarius.fe80.eu/blog/files/openwrt/mikrotik-wap-r-ac_back.jpg">high_res_back</a></li>
</ul>
<img alt="PCBA of a Mikrotik wAP R AC frontside" src="https://lunarius.fe80.eu/blog/files/openwrt/mikrotik-wap-r-ac_front_small.jpg" />
<img alt="PCBA of a Mikrotik wAP R AC backside" src="https://lunarius.fe80.eu/blog/files/openwrt/mikrotik-wap-r-ac_back_small.jpg" />
d-link dir x-1860 - a mediatek ax board2020-12-13T02:23:00+01:002020-12-13T02:23:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2020-12-13:/blog/openwrt-d-link-x-1860-mt7915-ax.html<p class="first last">d-link dir x-1860 a mt7915 based device</p>
<ul class="simple">
<li>CPU mediatek 7621AT - a ramips based cpu with 2 cores</li>
<li>RAM: winbond w632... (too small to read ;)</li>
<li>flash: 128 MByte NAND winbond w29n01hvsinf</li>
<li>wifi: ax with a mt7915dan (2T2R 2.4 Ghz, 2T2R 5Ghz) + mt7975dn</li>
</ul>
<img alt="PCB of a d-link dir x 1860" src="https://lunarius.fe80.eu/blog/files/openwrt/d-link-dir-x-1860.jpg" style="width: 750px; height: 422px;" />
How to recover a supermicro board with a broken bios firmware2020-04-26T23:42:00+02:002020-04-26T23:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2020-04-26:/blog/supermicro-recover-broken-flash.html<p class="first last">How to recover a supermicro board with a broken bios firmware</p>
<p>I was asked to take a look on a supermicro server which has been damaged by an firmware update.
It was an Supermicro X10DRW-IT. The firmware update was tried by USB storage, but somehow failed.</p>
<p>After powering the system, it went like this:</p>
<ul class="simple">
<li>On with all fans for 5 sec</li>
<li>Off for 5 sec</li>
<li>On with all fans for 5 sec</li>
<li>[..]</li>
</ul>
<p>However it seems the IPMI is still booting through and won't be disconnected from the power as the remaining
mainboard does, but the IPMI doesn't accept any bios update anymore.</p>
<p>As preparation I read up on the coreboot support for the Supermicro X10SLM+-F [0]</p>
<p>The bios chip is hidden under the raid controller if you've one.</p>
<img alt="Supermicro mainboard. Source: Supermicro X10DRW-i/X10DRW-iT USER’S MANUAL Revision 1.2b" src="https://lunarius.fe80.eu/blog/files/hacking/supermicro-recover.png" style="height: 600px;" />
<p>First I've taken a look on the BIOS flash. To read the bios flash out, I've used a raspberry pi 3 with a SOIC-8 clip using the SPI bus.</p>
<p>Required tools:</p>
<ul class="simple">
<li>raspberry pi with raspian (apt-get install flashrom)</li>
<li>some wire cables to the SOIC8 test clip</li>
<li>a SOIC-8 test clip (either the cheap ones from aliexpress or the expensive, high quality pomona 5250 [1]).</li>
</ul>
<p>How you have to connect the SPI SOIC chip is described in [2].
Pin 1 of the SPI chip is where the small hole is on the.</p>
<p>Ensure you <strong>Disconnect both power supplies from the mainboard.</strong></p>
<pre class="code sh literal-block">
sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">1000</span><span class="w"> </span>-r<span class="w"> </span>bios<span class="w">
</span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">1000</span><span class="w"> </span>-r<span class="w"> </span>bios2<span class="w">
</span>sha256sum<span class="w"> </span>bios<span class="w"> </span>bios2<span class="w">
</span><span class="c1"># ensure the checksum is equal, to ensure you read real things.
</span><span class="w">
</span>strings<span class="w"> </span>-n<span class="w"> </span><span class="m">16</span><span class="w"> </span>bios<span class="w">
</span><span class="c1"># try to get some strings out of it, ensure you not only read 0xffff or 0x0000.</span>
</pre>
<p>Next I downloaded the supermicro bios update. Here you can find:</p>
<pre class="code sh literal-block">
tree<span class="w"> </span>.<span class="w">
</span>.<span class="w">
</span>├──<span class="w"> </span>DOS<span class="w">
</span>│<span class="w"> </span>├──<span class="w"> </span>AFUDOSU.SMC<span class="w">
</span>│<span class="w"> </span>├──<span class="w"> </span>CHOICE.SMC<span class="w">
</span>│<span class="w"> </span>├──<span class="w"> </span>FDT.smc<span class="w">
</span>│<span class="w"> </span>├──<span class="w"> </span>FLASH.BAT<span class="w">
</span>│<span class="w"> </span>├──<span class="w"> </span>Readme<span class="w"> </span><span class="k">for</span><span class="w"> </span>X10<span class="w"> </span>AMI<span class="w"> </span>BIOS-DOS+UEFI.txt<span class="w">
</span>│<span class="w"> </span>└──<span class="w"> </span>X10DRW9.B22<span class="w">
</span>└──<span class="w"> </span>UEFI<span class="w">
</span>├──<span class="w"> </span>Readme<span class="w"> </span><span class="k">for</span><span class="w"> </span>X10<span class="w"> </span>AMI<span class="w"> </span>BIOS-DOS+UEFI.txt<span class="w">
</span>├──<span class="w"> </span>X10DRW9.B22<span class="w">
</span>├──<span class="w"> </span>afuefi.smc<span class="w">
</span>├──<span class="w"> </span>fdt.smc<span class="w">
</span>└──<span class="w"> </span>flash.nsh<span class="w">
</span>ls<span class="w"> </span>-al<span class="w"> </span>X10DRW9.B22<span class="w">
</span>-rw-------<span class="w"> </span><span class="m">1</span><span class="w"> </span>lynxis<span class="w"> </span>users<span class="w"> </span><span class="m">16777216</span><span class="w"> </span>Nov<span class="w"> </span><span class="m">22</span><span class="w"> </span><span class="m">16</span>:07<span class="w"> </span>X10DRW9.B22
</pre>
<p>Sound good, it's size is exact 16 MB, the same size as the bios flash. file also tell me what it is.</p>
<pre class="code sh literal-block">
file<span class="w"> </span>X10DRW9.B22<span class="w">
</span>X10DRW9.B22:<span class="w"> </span>Intel<span class="w"> </span>serial<span class="w"> </span>flash<span class="w"> </span><span class="k">for</span><span class="w"> </span>PCH<span class="w"> </span>ROM
</pre>
<p>Great we found a firmware image with ifd (intel firmware descriptor).
Now I've looked on the BIOS backup we read with the raspberry pi.</p>
<p>I used <tt class="docutils literal">hexdump <span class="pre">-C</span> bios</tt> to see if the end contains a lot of 1s (or 0xffff in hex). Why?
Because if you want to write a SPI flash, you can not just write to it like a hard drive.
SPI flash chips are organised in blocks. A block is usally 64 kbyte.
A single bit on a flash chip can only be <em>written</em> to a 0. If you want to write a single bit with a 1
where a 0 was before (0 -> 1), you've to erase the whole block, not only the address.
An erase blocked is full of 1.
To find out, if we have a half written flash, we can try to look on the end of the flash if there are a lot of 1s (or 0xffffffff).</p>
<p>hexdump -C is showing it quite nice</p>
<pre class="code literal-block">
00c2ee20 4d 50 44 54 00 01 00 00 10 00 00 00 00 00 10 00 |MPDT............|
00c2ee30 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
01000000
</pre>
<p>This means, it only written up to 0x00c2ee30 (12.2 MB).
Now we can look into the downloaded image, if it looks similiar. Maybe here starts configuration data.
But no, it's missing some data here.</p>
<p>Next task is to flash the bios section. Bios section? The intel firmware description contains section. Similiar to a partition layout on a
hard drive. On this platform there are 3 different sections</p>
<pre class="code literal-block">
00000000:00000fff fd
00400000:00ffffff bios
00011000:003fffff me
</pre>
<ul class="simple">
<li>fd stands for firmware descriptor</li>
<li>bios stands for the x86 firmware or UEFI</li>
<li>me for the management engine (also called on servers "Server Platform Services")</li>
</ul>
<p>To flash only the partition you either have to use a recent flashrom version (at least 1.0) or you've to extract the layout file using
the ifdtool (from coreboot). You can also use the last code snipped as layout.</p>
<pre class="code sh literal-block">
flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">1000</span><span class="w"> </span>-l<span class="w"> </span>layout<span class="w"> </span>-i<span class="w"> </span>bios<span class="w"> </span>-w<span class="w"> </span>X10DRW9.B22
</pre>
<p>It verifies it after writing to it. But still it doesn't work. My next thought was maybe the IPMI flash got damaged as well. The SPI flash
of the IPMI is close by. So let's have a look. I was lucky to also have a SOIC-16 test clip available. I did the same procedure on the
IPMI flash. However the flashrom in raspian was too old. The flash chip wasn't known to this version flashrom. I had to compile it myself.</p>
<pre class="code sh literal-block">
sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>git<span class="w"> </span>build-essential<span class="w">
</span>git<span class="w"> </span>clone<span class="w"> </span>https://review.coreboot.org/flashrom.git<span class="w">
</span><span class="nb">cd</span><span class="w"> </span>flashrom<span class="w">
</span>make<span class="w"> </span><span class="nv">CONFIG_ENABLE_LIBPCI_PROGRAMMERS</span><span class="o">=</span>no<span class="w"> </span><span class="nv">CONFIG_ENABLE_LIBUSB1_PROGRAMMERS</span><span class="o">=</span>no<span class="w">
</span>./flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">1000</span><span class="w"> </span>-r<span class="w"> </span>ipmi
</pre>
<p>But it looks good so far. Running binwalk on it shows us</p>
<pre class="code sh literal-block">
binwalk<span class="w"> </span>ipmi<span class="w">
</span>DECIMAL<span class="w"> </span>HEXADECIMAL<span class="w"> </span>DESCRIPTION<span class="w">
</span>--------------------------------------------------------------------------------<span class="w">
</span><span class="m">103328</span><span class="w"> </span>0x193A0<span class="w"> </span>CRC32<span class="w"> </span>polynomial<span class="w"> </span>table,<span class="w"> </span>little<span class="w"> </span>endian<span class="w">
</span><span class="m">1048576</span><span class="w"> </span>0x100000<span class="w"> </span>JFFS2<span class="w"> </span>filesystem,<span class="w"> </span>little<span class="w"> </span>endian<span class="w">
</span><span class="m">4194304</span><span class="w"> </span>0x400000<span class="w"> </span>CramFS<span class="w"> </span>filesystem,<span class="w"> </span>little<span class="w"> </span>endian,<span class="w"> </span>size:<span class="w"> </span><span class="m">15216640</span>,<span class="w"> </span>version<span class="w"> </span><span class="m">2</span>,<span class="w"> </span>sorted_dirs,<span class="w"> </span>CRC<span class="w"> </span>0xB1031FF3,<span class="w"> </span>edition<span class="w"> </span><span class="m">0</span>,<span class="w"> </span><span class="m">8613</span><span class="w"> </span>blocks,<span class="w"> </span><span class="m">1099</span><span class="w"> </span>files<span class="w">
</span><span class="m">20971520</span><span class="w"> </span>0x1400000<span class="w"> </span>uImage<span class="w"> </span>header,<span class="w"> </span>header<span class="w"> </span>size:<span class="w"> </span><span class="m">64</span><span class="w"> </span>bytes,<span class="w"> </span>header<span class="w"> </span>CRC:<span class="w"> </span>0x3F1E0DA5,<span class="w"> </span>created:<span class="w"> </span><span class="m">2019</span>-11-15<span class="w"> </span><span class="m">08</span>:36:11,<span class="w"> </span>image<span class="w"> </span>size:<span class="w"> </span><span class="m">1537512</span><span class="w"> </span>bytes,<span class="w"> </span>Data<span class="w"> </span>Address:<span class="w"> </span>0x40008000,<span class="w"> </span>Entry<span class="w"> </span>Point:<span class="w"> </span>0x40008000,<span class="w"> </span>data<span class="w"> </span>CRC:<span class="w"> </span>0x310498CA,<span class="w"> </span>OS:<span class="w"> </span>Linux,<span class="w"> </span>CPU:<span class="w"> </span>ARM,<span class="w"> </span>image<span class="w"> </span>type:<span class="w"> </span>OS<span class="w"> </span>Kernel<span class="w"> </span>Image,<span class="w"> </span>compression<span class="w"> </span>type:<span class="w"> </span>gzip,<span class="w"> </span>image<span class="w"> </span>name:<span class="w"> </span><span class="s2">"21400000"</span><span class="w">
</span><span class="m">20971584</span><span class="w"> </span>0x1400040<span class="w"> </span>gzip<span class="w"> </span>compressed<span class="w"> </span>data,<span class="w"> </span>maximum<span class="w"> </span>compression,<span class="w"> </span>has<span class="w"> </span>original<span class="w"> </span>file<span class="w"> </span>name:<span class="w"> </span><span class="s2">"linux.bin"</span>,<span class="w"> </span>from<span class="w"> </span>Unix,<span class="w"> </span>last<span class="w"> </span>modified:<span class="w"> </span><span class="m">2019</span>-11-15<span class="w"> </span><span class="m">07</span>:25:15<span class="w">
</span><span class="m">24117248</span><span class="w"> </span>0x1700000<span class="w"> </span>CramFS<span class="w"> </span>filesystem,<span class="w"> </span>little<span class="w"> </span>endian,<span class="w"> </span>size:<span class="w"> </span><span class="m">7458816</span>,<span class="w"> </span>version<span class="w"> </span><span class="m">2</span>,<span class="w"> </span>sorted_dirs,<span class="w"> </span>CRC<span class="w"> </span>0xF5B9463B,<span class="w"> </span>edition<span class="w"> </span><span class="m">0</span>,<span class="w"> </span><span class="m">3108</span><span class="w"> </span>blocks,<span class="w"> </span><span class="m">466</span><span class="w"> </span>files
</pre>
<p>Looks also good, however I want to be sure, it's the fine. I did first a backup, second overwritten with a file from the IPMI firmware update.</p>
<p>Still no change.</p>
<p>So what's wrong here? Is the power management controller damaged? The power supply are controller digital via I2C. Maybe it's somehow
telling me something is wrong?</p>
<p>I was lucky, I didn't had a i2c sniffer around, otherwise I would have digged into it.
I nearly gave it up, before I found out, that the backup file didn't worked with <strong>ifdtool</strong>. I exported the layout using the firmware update file, and not with the backup file.
Usually firmware updates do not touch the ifd. It seems server boards are different. So the backup didn't contained an ifd. It wasn't only damaged in the end, also in the beginning. Not sure if this is a safety feature of the
update. It might ensure at the beginning of an update the partial flash wouldn't be recognized as a working image. It's not a good thing booting a half working image.</p>
<p>I flashed the bios firmware update image and the board is back. To be sure, I flashed the ipmi backup on the SPI chip.</p>
<p><strong>TLDR;</strong> So the fast way to recover a partial bios, do a backup first! Then flash the full image. At least for this generation it works.</p>
<p>Note: Depending on your specific hardware setup (cable length, test clip) you can increase or decrease the spispeed. spispeed=10000 => 10 MHz should
be still ok. You'll notice the wrong spispeed if the reading or flashing fails.</p>
<p>[0] <a class="reference external" href="https://doc.coreboot.org/mainboard/supermicro/x10slm-f.html">https://doc.coreboot.org/mainboard/supermicro/x10slm-f.html</a></p>
<p>[1] <a class="reference external" href="https://www.pomonaelectronics.com/products/test-clips/soic-clip-8-pin">https://www.pomonaelectronics.com/products/test-clips/soic-clip-8-pin</a></p>
<p>[2] <a class="reference external" href="https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi">https://github.com/bibanon/Coreboot-ThinkPads/wiki/Hardware-Flashing-with-Raspberry-Pi</a></p>
Joe the friendly coffee maker2020-01-13T01:23:00+01:002020-01-13T01:23:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2020-01-13:/blog/joe-friendly-coffe-maker.html<p class="first last">Joe is a BLE app to control jura coffee machine.</p>
<p>Last week I visited thomasdotwtf from eventphone who has a jura coffee machine.
We took one evening to look into it, how easy it is, to use a generic BLE device like a raspberry pi to control it.
He has a Jura Z8 Automatic Coffee Machine which supports an IOS/Android app via Bluetooh LE.</p>
<p>Jura released (at least) two different apps to control it.</p>
<ul class="simple">
<li>pl.mkssystems.juracoffee.household (Jura Coffee)</li>
<li>ch.toptronic.joe (J.O.E.)</li>
</ul>
<p>Both apps supports ordering, changing properties of a coffee (e.g. how much water do you want to have or how much coffee should be in
there?).
mkssystems.pl seems to went out-of-service, but the internet archive still have an old version
and they show a lot of coffee machine related products. As well as a small blue device [1].</p>
<p>This is the BlueFrog a bluetooth dongle to control Jura coffee machines.</p>
<div class="section" id="what-can-you-do-with-the-apps">
<h2>What can you do with the Apps?</h2>
<ul class="simple">
<li>Configure your Coffee</li>
<li>Produce a Coffee</li>
<li>Statistics</li>
<li>Firmware updates</li>
</ul>
</div>
<div class="section" id="how-we-looked-into">
<h2>How we looked into?</h2>
<blockquote>
<ul class="simple">
<li>bluetooth packettrace: We used the android btsnoop.log to retrieve a packet trace which we loaded into wireshark.</li>
<li>decompiled with different tools the .apk</li>
<li>loaded the source code into android studio</li>
</ul>
</blockquote>
</div>
<div class="section" id="what-we-found-out">
<h2>What we found out?</h2>
<p>The J.O.E. application is using XML files to be configured for the different coffee machines.
The XML defines products (e.g. a coffee, a green tea, ...), there are properties (e.g. how much coffee should be produced), statistics and
settings. The <em>article number</em> defines the XML file to be used.</p>
<p>A firmware process including the update urls and the new firmware.</p>
<p>We tried to find the same commands which should work on the RS232/serial in the bluetooth packet trace, but there wasn't any.
After looking further in the code, we found a lot UUIDs for characteristics including a human readable name.
We discovered also an "encryption" method which uses 2x hardcoded keys as well an additional input of 8 bit from the BLE advertisment.
The encryption look like a static key.</p>
<p>In the BLE advertisment, there are manufactoring data.
In our case, the manufactoring data contains 27 bytes. If 16 bit will be used, it's <strong>little endian</strong>.</p>
<pre class="code literal-block">
manufactoring data as hex (27 byte):
aa 05 06 03 d73a yyyy xxxx 5836 4435 01 c0 00 00 00 00 00 00 00 00 00 00 00
aa: key
05: BlueFrog Major Version
06: BlueFrog Minor Version
03: unused (maybe Patch Version?)
d73a: article number (the specific type of the machine)
yyyy: machine number
xxxx: serial number
5836: production date (Feb. 2017)
4435: production date UHCI (does UHCI means the bluefrog?) (Okt. 2016)
01: unused
c0: bitmask, define supported features
</pre>
<p>The production dates can be decoded and also validated using the application where it's shown in the connection fragment:</p>
<pre class="code literal-block">
days: (i & 31)
month: ((i & 480) >> 5)
year: ((i & 65024) >> 9) + 1990;
</pre>
</div>
<div class="section" id="what-to-do-next">
<h2>What to do next?</h2>
<p>Write a decrypt function which can parse pcap files and shows the message
or write a dissector (lua) for wireshark with decryption function.</p>
<p>Find out how to map the XML files into commands towards the BlueFrog.</p>
</div>
<div class="section" id="bluetooth-interface">
<h2>Bluetooth Interface</h2>
<p>The good thing of BLE is, it's standarzied in the communication.
BLE uses <strong>Bluetooth Attribute Protocol</strong> to communicate.
The <strong>Bluetooth Attribute Protocol</strong> uses services and characteristics.
A service is an object which can hold multiple characteristics. A characteristic can support one or more of the following operations
read, write, notification, indication.
Every service has a UUID as well a characteristic has a UUID. The Bluetooth Attribute Protocol has it's own methods to discover avaiable
services and characterics. For more information please take a closer look into Bluetooth Low Energy.</p>
<p>As a general BLE device, the BlueFrog annouce itself on the BLE.</p>
<pre class="code literal-block">
> hcitool lescan
LE Scan ...
C9:26:E8:4B:72:02 TT214H BlueFrog
> HCI Event: LE Meta Event (0x3e) plen 43 #8 [hci0] 8.466202
LE Advertising Report (0x02)
Num reports: 1
Event type: Scan response - SCAN_RSP (0x04)
Address type: Random (0x01)
Address: C9:26:E8:4B:72:02 (Static)
Data length: 31
Company: Ingenieur-Systemgruppe Zahn GmbH (171)
Data: aa050603d73a080402005836443501c00000000000000000000000
RSSI: -78 dBm (0xb2)
</pre>
<p>And further more we can also look for the services and characteristics via the <strong>gatttool</strong>.</p>
<pre class="code literal-block">
> gatttool -b C9:26:E8:4B:72:02 --services -t random
attr handle = 0x0001, end grp handle = 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle = 0x0008, end grp handle = 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle = 0x0009, end grp handle = 0x0033 uuid: 5a401523-ab2e-2548-c435-08c300000710
attr handle = 0x0034, end grp handle = 0x003a uuid: 5a401623-ab2e-2548-c435-08c300000710
attr handle = 0x003b, end grp handle = 0xffff uuid: 00001530-1212-efde-1523-785feabcd123
</pre>
<pre class="code literal-block">
> gatttool -b C9:26:E8:4B:72:02 --characteristics -t random
handle = 0x0002, char properties = 0x0a, char value handle = 0x0003, uuid = 00002a00-0000-1000-8000-00805f9b34fb
handle = 0x0004, char properties = 0x02, char value handle = 0x0005, uuid = 00002a01-0000-1000-8000-00805f9b34fb
handle = 0x0006, char properties = 0x02, char value handle = 0x0007, uuid = 00002a04-0000-1000-8000-00805f9b34fb
handle = 0x000a, char properties = 0x02, char value handle = 0x000b, uuid = 5a401524-ab2e-2548-c435-08c300000710
handle = 0x000d, char properties = 0x08, char value handle = 0x000e, uuid = 5a401525-ab2e-2548-c435-08c300000710
handle = 0x0010, char properties = 0x08, char value handle = 0x0011, uuid = 5a401529-ab2e-2548-c435-08c300000710
handle = 0x0013, char properties = 0x08, char value handle = 0x0014, uuid = 5a401528-ab2e-2548-c435-08c300000710
handle = 0x0016, char properties = 0x0a, char value handle = 0x0017, uuid = 5a401530-ab2e-2548-c435-08c300000710
handle = 0x0019, char properties = 0x02, char value handle = 0x001a, uuid = 5a401527-ab2e-2548-c435-08c300000710
handle = 0x001c, char properties = 0x02, char value handle = 0x001d, uuid = 5a401531-ab2e-2548-c435-08c300000710
handle = 0x001f, char properties = 0x0a, char value handle = 0x0020, uuid = 5a401532-ab2e-2548-c435-08c300000710
handle = 0x0022, char properties = 0x0a, char value handle = 0x0023, uuid = 5a401535-ab2e-2548-c435-08c300000710
handle = 0x0025, char properties = 0x0a, char value handle = 0x0026, uuid = 5a401533-ab2e-2548-c435-08c300000710
handle = 0x0028, char properties = 0x02, char value handle = 0x0029, uuid = 5a401534-ab2e-2548-c435-08c300000710
handle = 0x002b, char properties = 0x02, char value handle = 0x002c, uuid = 5a401536-ab2e-2548-c435-08c300000710
handle = 0x002e, char properties = 0x02, char value handle = 0x002f, uuid = 5a401537-ab2e-2548-c435-08c300000710
handle = 0x0031, char properties = 0x02, char value handle = 0x0032, uuid = 5a401538-ab2e-2548-c435-08c300000710
handle = 0x0035, char properties = 0x02, char value handle = 0x0036, uuid = 5a401624-ab2e-2548-c435-08c300000710
handle = 0x0038, char properties = 0x08, char value handle = 0x0039, uuid = 5a401625-ab2e-2548-c435-08c300000710
handle = 0x003c, char properties = 0x04, char value handle = 0x003d, uuid = 00001532-1212-efde-1523-785feabcd123
handle = 0x003e, char properties = 0x18, char value handle = 0x003f, uuid = 00001531-1212-efde-1523-785feabcd123
</pre>
</div>
<div class="section" id="bluetooth-services-and-characteristics">
<h2>Bluetooth Services and Characteristics</h2>
<table border="1" class="docutils">
<caption>service table</caption>
<colgroup>
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">start</th>
<th class="head">end</th>
<th class="head">uuid</th>
<th class="head">name</th>
<th class="head"> </th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0x0001</td>
<td>0x0007</td>
<td>0x1800</td>
<td>Generic Access Profile</td>
<td> </td>
</tr>
<tr><td>0x0008</td>
<td>0x0008</td>
<td>0x1801</td>
<td>Generic Attribute Profile</td>
<td> </td>
</tr>
<tr><td>0x0009</td>
<td>0x0033</td>
<td>5a401523-ab2e-2548-c435-08c300000710</td>
<td> </td>
<td> </td>
</tr>
<tr><td>0x0034</td>
<td>0x003a</td>
<td>5a401623-ab2e-2548-c435-08c300000710</td>
<td> </td>
<td> </td>
</tr>
<tr><td>0X003b</td>
<td>0xffff</td>
<td>00001530-1212-efde-1523-785feabcd123</td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<table border="1" class="docutils">
<caption>Generic Access Profile (GAP) 0x0001 .. 0x0007</caption>
<colgroup>
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">handle</th>
<th class="head">value handle</th>
<th class="head">properties</th>
<th class="head">uuid</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0x0002</td>
<td>0x0003</td>
<td>RW (0xa)</td>
<td>00002a00-0000-1000-8000-00805f9b34fb</td>
<td> </td>
</tr>
<tr><td>0x0004</td>
<td>0x0005</td>
<td>R (0x2)</td>
<td>00002a01-0000-1000-8000-00805f9b34fb</td>
<td> </td>
</tr>
<tr><td>0x0006</td>
<td>0x0007</td>
<td>R (0x2)</td>
<td>00002a04-0000-1000-8000-00805f9b34fb</td>
<td> </td>
</tr>
</tbody>
</table>
<table border="1" class="docutils">
<caption>5a401523-ab2e-2548-c435-08c300000710 0x0009 .. 0x0033a</caption>
<colgroup>
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">handle</th>
<th class="head">value handle</th>
<th class="head">properties</th>
<th class="head">uuid</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0x000a</td>
<td>0x000b</td>
<td>R (0x2)</td>
<td>5a401524-ab2e-2548-c435-08c300000710</td>
<td>Machine Status</td>
</tr>
<tr><td>0x000d</td>
<td>0x000e</td>
<td>W (0x8)</td>
<td>5a401525-ab2e-2548-c435-08c300000710</td>
<td>Product Start</td>
</tr>
<tr><td>0x0010</td>
<td>0x0011</td>
<td>W (0x8)</td>
<td>5a401529-ab2e-2548-c435-08c300000710</td>
<td>Service Control</td>
</tr>
<tr><td>0x0013</td>
<td>0x0014</td>
<td>W (0x8)</td>
<td>5a401528-ab2e-2548-c435-08c300000710</td>
<td>Update Product Progress</td>
</tr>
<tr><td>0x0016</td>
<td>0x0017</td>
<td>RW (0xa)</td>
<td>5a401530-ab2e-2548-c435-08c300000710</td>
<td>Product Progress</td>
</tr>
<tr><td>0x0019</td>
<td>0x001a</td>
<td>R (0x2)</td>
<td>5a401527-ab2e-2548-c435-08c300000710</td>
<td>About</td>
</tr>
<tr><td>0x001c</td>
<td>0x001d</td>
<td>R (0x2)</td>
<td>5a401531-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x001f</td>
<td>0x0020</td>
<td>RW (0xa)</td>
<td>5a401532-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x0022</td>
<td>0x0023</td>
<td>RW (0xa)</td>
<td>5a401535-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x0025</td>
<td>0x0026</td>
<td>RW (0xa)</td>
<td>5a401533-ab2e-2548-c435-08c300000710</td>
<td>Statistics command</td>
</tr>
<tr><td>0x0028</td>
<td>0x0029</td>
<td>R (0x2)</td>
<td>5a401534-ab2e-2548-c435-08c300000710</td>
<td>Statistics data</td>
</tr>
<tr><td>0x002b</td>
<td>0x002c</td>
<td>R (0x2)</td>
<td>5a401536-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x002e</td>
<td>0x002f</td>
<td>R (0x2)</td>
<td>5a401537-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x0031</td>
<td>0x0032</td>
<td>R (0x2)</td>
<td>5a401538-ab2e-2548-c435-08c300000710</td>
<td>Service Control Response</td>
</tr>
</tbody>
</table>
<table border="1" class="docutils">
<caption>5a401623-ab2e-2548-c435-08c300000710 0x0034 .. 0x003a</caption>
<colgroup>
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">handle</th>
<th class="head">value handle</th>
<th class="head">properties</th>
<th class="head">uuid</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0x0035</td>
<td>0x0036</td>
<td>R (0x2)</td>
<td>5a401624-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
<tr><td>0x0038</td>
<td>0x0039</td>
<td>W (0x8)</td>
<td>5a401625-ab2e-2548-c435-08c300000710</td>
<td> </td>
</tr>
</tbody>
</table>
<table border="1" class="docutils">
<caption>Nordic DFU 00001530-1212-efde-1523-785feabcd123 0x003b .. 0xffff</caption>
<colgroup>
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
<col width="20%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">handle</th>
<th class="head">value handle</th>
<th class="head">properties</th>
<th class="head">uuid</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>0x003c</td>
<td>0x003d</td>
<td>W- (0x4)</td>
<td>00001532-1212-efde-1523-785feabcd123</td>
<td>Nordic DFU_PACKET_CHARACTERISTI</td>
</tr>
<tr><td>0x003e</td>
<td>0x003f</td>
<td>W N (0x18)</td>
<td>00001531-1212-efde-1523-785feabcd123</td>
<td>Nordic DFU_CONTROL_POINT_CHARACTERISTIC</td>
</tr>
</tbody>
</table>
<ul class="simple">
<li>R means read</li>
<li>W mean write with response</li>
<li>W- means write without response</li>
<li>N means notification</li>
</ul>
</div>
<div class="section" id="additional-sources">
<h2>Additional sources</h2>
<ul class="simple">
<li>[1] <a class="reference external" href="https://www.thomas-electronic-online-shop.de/JURA-Smart-Connect">https://www.thomas-electronic-online-shop.de/JURA-Smart-Connect</a></li>
<li>[2] <a class="reference external" href="https://forum.fhem.de/index.php?topic=76957.0">https://forum.fhem.de/index.php?topic=76957.0</a></li>
<li>[3] <a class="reference external" href="https://community.home-assistant.io/t/control-your-jura-coffee-machine/26604">https://community.home-assistant.io/t/control-your-jura-coffee-machine/26604</a></li>
<li>[4] <a class="reference external" href="https://gitlab.com/Blueforcer/HA2JURA/snippets/1674496">https://gitlab.com/Blueforcer/HA2JURA/snippets/1674496</a></li>
<li>[5] <a class="reference external" href="https://github.com/hn/jura-coffee-machine">https://github.com/hn/jura-coffee-machine</a></li>
<li>[6] <a class="reference external" href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Flib_dfu_transport_ble.html">https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Flib_dfu_transport_ble.html</a></li>
</ul>
</div>
TP-Link TL-WR841v142019-03-28T13:37:00+01:002019-03-28T13:37:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2019-03-28:/blog/photos-tplink-tl-wr841v14.html<p class="first last">TP-Link 84v14 board photos</p>
<ul class="simple">
<li>ramips mt7628nn</li>
<li>4 MB flash</li>
<li>32 MB Memory</li>
</ul>
<img alt="TP-Link 841v14" src="https://lunarius.fe80.eu/blog/files/openwrt/tp-link-tl-wr841v14.jpg" style="width: 600px; height: 800px;" />
MirageOS retreat March 20192019-03-18T12:34:00+01:002019-03-18T12:34:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2019-03-18:/blog/mirageos-2019.html<p class="first last">MirageOS retreat 2019</p>
<p>I joined the <a class="reference external" href="http://retreat.mirage.io">MirageOS retreat</a> in March 2019. It's an 1 week event in Marrakech, Marocco.
It's a real nice house in the old city of Marrakech, the medina. The event itself doesn't
have much structure than a morning meeting and sometimes talks in the evening.</p>
<p><a class="reference external" href="https://mirage.io">MirageOS</a> is unikernel written in <a class="reference external" href="https://ocaml.org">OCaml</a>. MirageOS can run ontop of many backends, e.g. Unix process or xen, kvm, bhyve.
This retreat I took care of the Internet uplink. We had a slow and leaky 4MBit ADSL line from Marocco Telecom which we used as backup, while using LTE as main uplink. We used first imwi as provider. But imwi changes the IPs quites often and the implementation in OpenWrt uqmi does not follow the IP changes, which resulted in a stale LTE connection. Imwi is also filtering all UDP DNS queries, except those going to their own servers. We then switched to Orange as provider, because someone had a card available. Orange was fast enough, pretty stable 5MBit up&down. We consumed roughly 20 GB a day. This brought us the nice daily ritual, a walk to a small and nice mobile shop in the medina.
1 GB cost 10 Dh (1 Euro).
Our router, an APU2, runs OpenWrt, but we disabled DNS & DHCP and ran these services on a seperate APU using MirageOS.</p>
<p>Even I'm not such familiar with OCaml and functional languages, I tried to fix <a class="reference external" href="https://github.com/mirage/charrua-core/issues/84">a bug</a> in the DHCP Server implementation <a class="reference external" href="https://github.com/mirage/charrua-core/pull/97">PR#97</a>.
It worked for me, however after deploying it, it turned out, it <strong>only</strong> worked for me, I broke it for everybody else ;). This motivated me to start
looking on TTCN-3, a ETSI language to test network protocols. Later together with Hannes, we fixed the DHCP for real. Adding some TTCN-3 tests and create a simple base is still on my TODO. Another really nice OCaml service on side was a <strong>learn-ocaml</strong> instance. An interactive teaching web application for beginners and advances OCaml programmers including an annotate OCaml compiler. Sadly there is no instance in the internet yet, as the projects is not ready for release.</p>
<p>While there I also worked a lot on reproducible builds for OpenWrt. I fixed 2 packages. All OpenWrt base packages are 100 % reproducible.
Thanks to Daniel Golle, OpenWrt images can be cryptographically signed. This signature must be removed before looking for differences, this is also done
in the reproducible builds setup for OpenWrt. 100% of ar71xx images are reproducible and 98% of ramips. The remaining 2% are also signature problems, but these signatures are in the middle instead of the end of the image. I also found the time to integrate my package index parser into reproducible builds. It's much easier to just parse two packages list, than looking on the all package files to determine if they are reproducible or not. The package index files also contain metadata of the packages which it inserts into the reproducible builds database.</p>
<p>Some people from the QubesOS projects joined the retreat. For example there is a MirageOS firewall which replaces the QubesOS own one. There is also a Pong game, which can run as QubesOS-vm. Thanks to the QubesOS people for their help on my problems with disposable vms.</p>
<p>Furthermore I brought a beaglebone black with me to investigate bugs reported for that platform. While looking at it, I found out the last release of OpenWrt (18.06.2) doesn't work on this board (fs: squashfs), while master works. I also fixed builds issues with u-boot in OpenWrt for the beaglebone black when using a modern toolchain.</p>
<p>Since we used LTE as uplink, we wanted to know how much of our data volume was consumed. OpenWrt might have statistics, but those are stored only in memory and not saved anywhere. I didn't looked for any OpenWrt packages which fixes this problem, because the provider (Orange) is supporting a USSD code to retrieve the remaining volume.</p>
<p>What is USSD? USSD stands for Unstructured Supplementary Service Data. It's used on mobile phones to retrieve balance, your phone number, your IMEI, [..]. Most people have used them. Take your phone, open the phone application and call <strong>*#06#</strong>, it will return your phone unique identifier (IMEI). While SMS is a store-and-forward scheme, like email. USSD is real time message protocol, similiar to a TCP connection. The USSD codes are simple, do a request, get a response. Done. But Orange implemented a menu via USSD. So the USSD session will look like: Request, Response, Choose Your Menu, Response, Go Back, Choose different Point.
I've started writing USSD support for libqmi. Simple USSD codes can be requested and decoded, but not menus with user input.</p>
<p>And the biggest problem is: OpenWrt doesn't support USSD at all. Not even the simple ones.</p>
upowerd fails2018-06-14T15:01:00+02:002018-06-14T15:01:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2018-06-14:/blog/upowerd-fails-users.html<p>upowerd fails there users</p><p>Sometimes, when I'm not directly around or I forgot to put the powersupply into my laptop.
My laptop runs into the critical power action. Because I'm using upowerd, my machine
try to does this:</p>
<ul>
<li>HibernateSuspend (fails)</li>
<li>Hibernate (fails)</li>
<li>PowerOff</li>
</ul>
<p>Great! My machine <strong>shuts down</strong>, in the middle of doing something. It would take 2 minutes to get a powersupply,
but too late!!</p>
<p>But there might be a solution for this: <strong>Suspend</strong>.
My machine can survive more than 1 hour in suspend with this low battery.</p>
<p>It would help me NOT loosing my current unsaved work.</p>
<p>After looking into the upowerd, it's just a <strong>1 line code change</strong> to allow this.
It is not a good default, but there are people who like to use this.</p>
<p>But .. upowerd doesn't like. They not even want to <strong>allow</strong> the user to take this option. Indepentent that
I agree, this shouldn't be the default.
We're discussing this issue for years. Without any solution. Upowerd want to decide what users should do with there laptop and what not.</p>
<p><a href="https://bugs.freedesktop.org/show_bug.cgi?id=73435">Discussion Bugtracker</a></p>
<p><strong>How to resolve it?</strong></p>Convert a flashdump to sysupgrade (ar71xx)2017-08-18T03:42:00+02:002017-08-18T03:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2017-08-18:/blog/convert-flashdump-to-sysupgrade-ar71xx.html<p class="first last">Convert a flashdump to sysupgrade (ar71xx)</p>
<p>From time to time you need to test things with the old image.
But how do you test thing when the original build environment is lost
and you want to test sysuprade against this old release (actually 12.09).</p>
<p>First you've to create a flashdump of the <strong>firmware</strong> paritition.</p>
<pre class="code literal-block">
# grep firmware /proc/mtd
mtd5: 003d0000 00010000 "firmware"
# ssh root@192.168.1.1 dd if=/dev/mtd5 > /tmp/firmware_backup
</pre>
<p>Afterwards you can use <strong>binwalk</strong> to get the actual offsets of the different
parts inside.</p>
<pre class="code literal-block">
# binwalk /tmp/firmware_backup
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
512 0x200 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 2813832 bytes
930352 0xE3230 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2194094 bytes, 728 inodes, blocksize: 262144 bytes, created: 2014-03-05 14:58:48
3145728 0x300000 JFFS2 filesystem, big endian
</pre>
<p>So sysupgrade images for ar71xx is still using the (old) layout of</p>
<pre class="literal-block">
----------
|KERNEL |
----------
|squashfs|
----------
|jffs2 |
----------
</pre>
<p>While a sysupgrade image contains for those platforms:</p>
<pre class="literal-block">
--------------
|KERNEL |
--------------
|squashfs |
--------------
|jffs2-dummy |
--------------
</pre>
<p>So we will split-off the jffs2 Part and replace it with jffs2.</p>
<pre class="code literal-block">
# dd if=/tmp/firwmare_backup bs=3145728 count=1 of=/tmp/sysupgrade.img
</pre>
<p>Next we add this jffs2-dummy by using the same tool LEDE is using it:</p>
<pre class="code literal-block">
# /home/lynxis/lede/staging_dir/host/bin/padjffs2 /tmp/sysupgrade.img 64
</pre>
<p>The 64 means the padding size in kb. It's important to choose the right one, but for most devices this is 64k at least for ar71xx.</p>
<pre class="code literal-block">
ssh root@192.168.1.1 dd if=/dev/mtd5 > /tmp/firmware_backup
binwalk /tmp/firmware_backup
dd if=/tmp/firwmare_backup bs=3145728 count=1 of=/tmp/sysupgrade.img
/home/lynxis/lede/staging_dir/host/bin/padjffs2 /tmp/sysupgrade.img 64
</pre>
coreboot support in lenovo x1 carbon gen12017-08-11T13:37:00+02:002017-08-11T13:37:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2017-08-11:/blog/coreboot-x1-carbon-gen1.html<p class="first last">coreboot support in lenovo x1 carbon gen1</p>
<p>A friend gave me the his x1 carbon gen1 some time ago.
The x1 carbon is little bit different from other Thinkpad because it's a combination
of a Thinkpad and a Ultrabook.</p>
<ul class="simple">
<li>It has a Trackpoint (and even Trackpoint buttons).</li>
<li>It has soldered memory (only Elpida memory is support atm).</li>
<li>It has Full-HD. (missed that on x2xx).</li>
</ul>
<p>Looking under the hood. The x1 carbon gen1 look very likely as x230.</p>
<img alt="x1 carbon left side" src="https://lunarius.fe80.eu/blog/files/coreboot/lenovo_x1_left.jpg" style="width: 800px; height: 400px;" />
<img alt="x1 carbon right side" src="https://lunarius.fe80.eu/blog/files/coreboot/lenovo_x1_right.jpg" style="width: 800px; height: 400px;" />
mksquashfs2017-01-13T23:42:00+01:002017-01-13T23:42:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2017-01-13:/blog/mksquash-dot-graph.html<p class="first last">How mksquashfs 4.3 works</p>
<p>A graphic can describe a thing more than 1000 words.
This is how mksquashfs 4.3 works.</p>
<img alt="How squashfs tools." src="https://lunarius.fe80.eu/blog/files/hacking/mksquashfs_thread.png" />
<p><a class="reference external" href="https://lunarius.fe80.eu/blog/files/hacking/mksquashfs_thread.dot">mksquashfs source</a></p>
Write patches for LEDE2016-10-01T23:42:00+02:002016-10-01T23:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2016-10-01:/blog/lede-write-kernel-patches.html<p class="first last">Howto write kernel patches for LEDE</p>
<p>This howto will get your through a LEDE to create your own kernel patch using
the LEDE infrastructure. It's based on LEDE reboot-1279-gc769c1b.</p>
<p>LEDE has already a lot of patches. They are all applied on one tree.
We will create a new patch for lantiq.
To get started, let see how LEDE organize the patches.
First of all we take a look on /target/linux/*</p>
<!-- ls target/linux/
..
ar71xx
at91
ath25
..
generic
.. -->
<p>All of these folders represent a architecture target, except <strong>generic</strong>.
The generic target is used by all targets.</p>
<p>To continue, we need to know which kernel version your target architecture is running on.
This is written down into target/linux/lantiq/Makefile.</p>
<!-- sh
grep KERNEL_PATCHVER target/linux/lantiq/Makefile.
KERNEL_PATCHVER:=4.4 -->
<p>We're running a <strong>4.4.Y</strong> kernel. The Y is written down into <strong>/include/kernel-version.mk</strong>. We will
use .15.</p>
<p>Ok. Now let's see. When LEDE is preparing the kernel build directory, it search for a matching patch
directory.</p>
<ol class="arabic simple">
<li>download the kernel 4.4.x (x from /include/kernel-version.mk)</li>
<li>unpack the kernel under /build_dir/target-../linux-lantiq/linux-4.4.15</li>
<li>apply <strong>generic</strong> patches</li>
<li>apply <strong>lantiq</strong> patches</li>
<li>create .config</li>
</ol>
<p>But which is the right patches directory? It use the following make snippet from <strong>/include/kernel.mk</strong></p>
<!-- make
PATCH_DIR ?= $(CURDIR)/patches$(if $(wildcard ./patches-$(KERNEL_PATCHVER)),-$(KERNEL_PATCHVER)) -->
<p>Meaning it will use /patches-4.4 if exists or if not try to use /patches.</p>
<p>Now we know how patches are applied to the linux kernel tree.
We could go into the directory, create a new patches directory and use <strong>quilt</strong>...</p>
<p>Or we use the quilt target for that.</p>
<p><cite>make target/linux/clean</cite> -> to clean up the old directory.
Now <cite>make target/linux/prepare QUILT=1</cite> will <strong>unpack</strong> the source, copy all present patches into ./patches
and use quilt to apply.</p>
<p>With quilt you can move forwards and backwards between patches, aswell as modifying those.
<cite>cd ./build_dir/target-mips_34kc+dsp_uClibc-0.9.33.2/linux-lantiq/linux-4.5.15/</cite>
to switch into the linux directory.</p>
<ol class="arabic simple">
<li><cite>quilt push -a</cite> to apply all patches from LEDE.</li>
<li><cite>quilt new platform/999-mymodification.patch</cite> to add a new patch</li>
<li><cite>quilt add net/l2tp/l2tp_core.c</cite> to track this file.</li>
<li>Call your editor to modify this file.</li>
<li>With <cite>quilt refresh</cite> it adds your modifcation to the patch platform/999-mymodification.patch.</li>
</ol>
<p>Your modification is under <strong>./build_dir/../linux-4.4.15/patches/platform/</strong>.
With <cite>make target/linux/refresh</cite> it will refresh all patches and copy them to the correct folder under <strong>target/linux/*/patches</strong>.</p>
Find special GPIOs2016-05-26T17:42:00+02:002016-05-26T17:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2016-05-26:/blog/lede-find-ar71xx-special-gpios.html<p class="first last">How to find special GPIOs like the LNA (Low Noise Amplifier) pin.</p>
<p>The TP-Link CPE510, a nice outdoor device, got a bad rx behaviour when using it with LEDE.
I want to give a short overview how to debug those problems. It could also help you finding problems when facing
ath9k pci cards.</p>
<p>To get down to the device. The CPE510 based on a AR9344 SoC. The integrated wireless part is
supported by the ath9k driver. To get more knowledge about the AR9344 you should take a look into
the public available datasheet. (google for ar9344 datasheet ;)</p>
<p>The AR9344 supports using GPIOs for special purposes it's called a GPIO function. If the function is
enabled, the gpio is internally routed to the special purpose. Now the simple part comes
if you know which register to look into, just look into it.</p>
<p>After reading the pages 52/53 of the datasheet, it's clear that it can route everything signal to every gpio.
Remember the table, because it explains what value means what it's routed to the gpio.
We suggest LNA are missing because the receiving part of the CPE510 is bad. So the value 46 and 47 are the important ones,
46 LNA Chain 0, 47 LNA Chain 1. LNA stands for low noice amplifier.</p>
<p>Now we know how the GPIOs works, let's find the register controlling the GPIO function. The GPIO section start at 130, but the interesting part
is the GPIO IO Function 0 register at address 0x1804002c. It give you 8 bit to describe it's function, if it's 0x0 no function is selected and the
GPIO is used as normal output. So if you write 46 into the bit 0-7 you set the GPIO to become the LNA Chain 0 signal. Every GPIO from
GPIO0 to GPIO19 can configured using those register.</p>
<p>We know what registers are interesting (0x1804002c - 0x1804003c).
We know which values are interesting (decimal 46 and decimal 47).</p>
<p>But how can we read out those value from a running system?
First answer I hear is JTAG, but JTAG isn't easy to archive and more difficult to use on ar71xx, because the bootloader
usally deactivate JTAG as one of the first commands.</p>
<p>But we can ask the kernel. /dev/mem is quite usefull for that. It's a direct way to the memory, very dangerous, but also handy ;).
The easiest way to interface with /dev/mem is the simple utility called devmem or devmem2.
To compile a compatible devmem2 you should use the GPL sources of the firmware, but you can also
download the binary from here [1].</p>
<p>Copy devmem2 to /tmp via scp and start reading the values.
Because mips is a 32bit architecture we have to read the register</p>
<!-- 0x1804002c
0x18040030
0x18040034
0x18040038
0x1804003c -->
<p>Back to our LNA value. 46 and 47. In hex are those 0x2E and 0x2F. We have to look
for those values aligned to 8bit.</p>
<pre class="code sh literal-block">
<span class="c1"># ./devmem2 0x1804002c
</span>/dev/mem<span class="w"> </span>opened.<span class="w">
</span>Memory<span class="w"> </span>mapped<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x2aaae000.<span class="w">
</span>Value<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x1804002C<span class="w"> </span><span class="o">(</span>0x2aaae02c<span class="o">)</span>:<span class="w"> </span>0x0<span class="w">
</span><span class="c1"># ./devmem2 0x18040030
</span>/dev/mem<span class="w"> </span>opened.<span class="w">
</span>Memory<span class="w"> </span>mapped<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x2aaae000.<span class="w">
</span>Value<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x18040030<span class="w"> </span><span class="o">(</span>0x2aaae030<span class="o">)</span>:<span class="w"> </span>0xB0A0900<span class="w">
</span><span class="c1"># ./devmem2 0x18040034
</span>/dev/mem<span class="w"> </span>opened.<span class="w">
</span>Memory<span class="w"> </span>mapped<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x2aaae000.<span class="w">
</span>Value<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x18040034<span class="w"> </span><span class="o">(</span>0x2aaae034<span class="o">)</span>:<span class="w"> </span>0x2D180000<span class="w">
</span><span class="c1"># ./devmem2 0x18040038
</span>/dev/mem<span class="w"> </span>opened.<span class="w">
</span>Memory<span class="w"> </span>mapped<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x2aaae000.<span class="w">
</span>Value<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x18040038<span class="w"> </span><span class="o">(</span>0x2aaae038<span class="o">)</span>:<span class="w"> </span>0x2C<span class="w">
</span><span class="c1"># ./devmem2 0x1804003c
</span>/dev/mem<span class="w"> </span>opened.<span class="w">
</span>Memory<span class="w"> </span>mapped<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x2aaae000.<span class="w">
</span>Value<span class="w"> </span>at<span class="w"> </span>address<span class="w"> </span>0x1804003C<span class="w"> </span><span class="o">(</span>0x2aaae03c<span class="o">)</span>:<span class="w"> </span>0x2F2E0000<span class="w">
</span><span class="c1">#</span>
</pre>
<p>Found it in 0x1804003C. LNA 0 is GPIO 18 and LNA1 is GPIO 19.</p>
<p>[1] <a class="reference external" href="https://lunarius.fe80.eu/blog/files/lede/devmem2">https://lunarius.fe80.eu/blog/files/lede/devmem2</a></p>
Bisecting coreboot with LAVA2016-03-04T23:42:00+01:002016-03-04T23:42:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2016-03-04:/blog/coreboot-bisect-lava.html<p class="first last">Bisect coreboot commits using lava, an automatic validation system.</p>
<p>Since long time ago I was inspired of the features of LAVA (Linaro Automated Validation).
Lava was developed by Linaro to do automatic test on real hardware. It's written in python and based on a lot small daemons and one django application.
It's scheduling submitted tests on hardware depending on the rights and availability.
Setting up an own instance isn't so hard, there is an video howto. But Lava is changing it's basic device model to pipeline devices to make it more flexible because the old device model was quite limited.
Our instance is available under <a class="reference external" href="https://lava.coreboot.org">https://lava.coreboot.org</a>. Atm. there is only one device (x60) and we're looking for help to add more devices.</p>
<p>coreboot is under heavy development around 200 commits a month. Sometime breaks, most time because somebody refactored code and made it simpler.
There are many devices supported by coreboot, but commits aren't tested on every hardware. Which means it broke on some hardware. And here the bisect loop begins.</p>
<p>Lava is the perfect place to do bisecting. You can submit a Testjob via commandline, track Job and wait until it's done. Lava itself takes cares that a job doesn't take to long.
To break down the task into smaller peaces:</p>
<blockquote>
<ul class="simple">
<li>checkout a revision</li>
<li>compile coreboot</li>
<li>copy artefact somewhere where Lava can access it (http-server)</li>
<li>submit a lava testjob</li>
<li>lava deploys your image and do some tests</li>
</ul>
</blockquote>
<p>git-bisect does the binary search for the broken revision, checks out the next commit which needs to be tested.
But somebody have to tell git-bisect if this is a <em>good</em> or <em>bad</em> revision. Or you use <em>git bisect run</em>.
<em>git bisect run</em> a small script and uses the return code to know if this is a <em>good</em> or <em>bad</em> revision. There is also a third command <em>skip</em>, to skip the revision if the compilation fails.
git-bisect would do the full bisect job, but to use lava, it needs a <em>Lava Test Job</em>.
Under <a class="reference external" href="https://github.com/lynxis/coreboot-lava-bisect">https://github.com/lynxis/coreboot-lava-bisect</a> is my x60 <a class="reference external" href="https://github.com/lynxis/coreboot-lava-bisect/blob/master/bisect.sh">bisect script</a> together with a <a class="reference external" href="https://github.com/lynxis/coreboot-lava-bisect/blob/master/job_description.yml">Lava Test Job for the x60</a>. It only checks if coreboot is booting. But you might want to test something else. Is the cdrom is showing up? Is the wifi card properly detected? Checkout the <a class="reference external" href="https://validation.linaro.org/static/docs/index.html">lava documentation</a> for more information about how to write a Lava Testjob or a Lava Test.</p>
<p>To communicate with Lava on the shell you need to have lava-tool running on your workstation. See <a class="reference external" href="https://validation.linaro.org/static/docs/overview.html">https://validation.linaro.org/static/docs/overview.html</a></p>
<p>With <strong>lava-tool submit-job $URL job.yml</strong> you can submit a job and get the JobId.
And check the status of your job with <strong>lava-tool job-status $URL $JOBID</strong>. Depending on the job-status
the script must set the exit code. My bisect script for coreboot is <a class="reference external" href="https://github.com/lynxis/coreboot-lava-bisect">https://github.com/lynxis/coreboot-lava-bisect</a></p>
<pre class="code sh literal-block">
<span class="nb">cd</span><span class="w"> </span>coreboot<span class="w">
</span><span class="c1"># CPU make -j$CPU
</span><span class="nb">export</span><span class="w"> </span><span class="nv">CPU</span><span class="o">=</span><span class="m">4</span><span class="w">
</span><span class="c1"># your login user name for the lava.coreboot.org
# you can also use LAVAURL="https://$LAVAUSER@lava.coreboot.fe80.eu/RPC2"
</span><span class="nb">export</span><span class="w"> </span><span class="nv">LAVAUSER</span><span class="o">=</span>lynxis<span class="w">
</span><span class="c1"># used by lava to download the coreboot.rom
</span><span class="nb">export</span><span class="w"> </span><span class="nv">COREBOOTURL</span><span class="o">=</span>https://fe80.eu/bisect/coreboot.rom<span class="w">
</span><span class="c1"># used as a target by *scp*
</span><span class="nb">export</span><span class="w"> </span><span class="nv">COREBOOT_SCP_URL</span><span class="o">=</span>lynxis@fe80.eu:/var/www/bisect/coreboot.rom<span class="w">
</span>git<span class="w"> </span>bisect<span class="w"> </span>start<span class="w">
</span>git<span class="w"> </span>bisect<span class="w"> </span>bad<span class="w"> </span><REV><span class="w">
</span>git<span class="w"> </span>bisect<span class="w"> </span>good<span class="w"> </span><REV><span class="w">
</span>git<span class="w"> </span>bisect<span class="w"> </span>run<span class="w"> </span>/path/to/this/dir/bisect.sh
</pre>
T40 ec soldering2015-04-12T12:34:00+02:002015-04-12T12:34:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2015-04-12:/blog/coreboot-t40-ec-soldering.html<p class="first last">Soldering debug wires to the EC of a T40.</p>
<p>Some friends give me their old hardware to help me on my next project: Create an open source
embedded controller firmware for Lenovo Thinkpads. My target platform are all Lenovo Thinkpads
using a Renesas/Hitachi H8S as EC. These chips built into Thinkpads from very old one to new models like the X230.</p>
<p>So what can be better that using a very old laptop like a T40 to solder and do hardware mods?
The first step is flashing the chip independent from the Operating System running on the hardware.
Why that? Because the EC controls certain power regulators and take care of turning the mainboard
on. A broken EC would allow you to turn your Laptop on. The H8S supports different boot modes.
It can boot <em>normal</em> <em>advance</em> <em>boot</em>. The <em>boot</em> mode is
a special mode for developing and flashing. It receive their firmware over normal UART and execute it.
The H8S defines it boot mode over 2 pins - <em>MD0</em> and <em>MD1</em> - also named <em>mode0</em> and <em>mode1</em>.
After looking on the schematics (which is available on the internet) we need to solder the UART pin <em>RX</em>, <em>TX</em>,
<em>MD1</em>, <em>GND</em>. <em>MD0</em> isn't required, because it's already set to 0. I soldered the test pin <em>TP1</em>, <em>TP10</em> (I2C).
<em>/RES</em> was soldered too, because I miscounted the pins. <em>/RES</em> lies beside of <em>MD1</em>. But it can be useful later.
I colored the pins on the bottom picture.</p>
<table border="1" class="docutils">
<colgroup>
<col width="58%" />
<col width="42%" />
</colgroup>
<tbody valign="top">
<tr><td><em>color</em></td>
<td><em>pin</em></td>
</tr>
<tr><td>Red</td>
<td>MD1</td>
</tr>
<tr><td>Orange</td>
<td>GND</td>
</tr>
<tr><td>Blue</td>
<td>/RES</td>
</tr>
<tr><td>Green</td>
<td>RX</td>
</tr>
<tr><td>Yellow</td>
<td>TX</td>
</tr>
</tbody>
</table>
<img alt="T40 top. F2161B is EC." src="https://lunarius.fe80.eu/blog/files/coreboot/t40_top.png" />
<img alt="T40 bottom. Yellow RX, Green TX, Blue /RES, Red MD1, Orange GND" src="https://lunarius.fe80.eu/blog/files/coreboot/t40_bottom.png" />
<img alt="How it looks. MD1 is missing here." src="https://lunarius.fe80.eu/blog/files/coreboot/t40_result.png" />
<p>The soldered image is missing <em>MD1</em>.</p>
3com/HP Fix LACP Error 'The port is not configured properly.'2015-03-31T01:23:00+02:002015-03-31T01:23:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2015-03-31:/blog/network-fix-3com-hp-lacp-error.html<p>Howto fix 3com/HP LACP Error 'The port is not configured properly.'</p><p>I got the task to setup LACP witch an not so new 3com siwtch on one side and a Debian Jessie + OpenVSwitch on the other. Usally not a so big problem. Just keep in mind, 3com was bought by HP and is still using 3com software in their newer products.
It's even possible to update an 3com switch with HP firmware if you're lucky to know which HP product matches your HP switch.
Back to the task: setup LACP. I've done everything mentioned in the manual:
* Check all ports are the same media type
* All ports must be configured in the same way
* have the same LACP priority</p>
<p>Everything seems be ok. The documentation also say that all Ports will loose their individual port conifiguration when added.
On the switch side I can see the switch is showing my Linux Box as port partner, but still the link group isn't going into
'Active' state. Still showing <strong>'The port is not configured properly.'</strong>.
An update is not a option from remote, to much service depends on this switch.
Let's take a closer look on the VLAN configuration. The LACP group isn't configured yet for any VLAN. But the ports still
have an old configuration with tagged VLAN and is in <em>hybrid</em> mode? Why? It has a PVID configured, but not an untagged
vlan asigned. Looks strange.</p>
<p><strong>Go to VLAN -> Modify Port: Select both LACP ports as well as the LACP group and set them into <em>Trunk</em> mode without any VLAN.</strong>
Now the LACP changed to active. Maybe this changed in newer HP firmware versions.</p>Very short how to recover a dockstar2014-06-09T22:42:00+02:002014-06-09T22:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2014-06-09:/blog/openwrt-dockstar-jtag.html<p>How to recover a dockstar</p><p>There are lot of howtos written for this topic but most won't worked for me.
<a href="http://www.irky.org/home/pogoplug_jtag">Irky's howto is very good.</a>
I'm mirroring his files here and summarise his howto.
If you have any question look into his article.</p>
<p>The dockstar is special device, because it does not support <strong>serial boot</strong> like other Marvel kirkwood devices.
E.g. when you bricked a Seagate GoFlex you can recover it <strong>without jtag</strong> over serial boot.
<a href="http://forum.doozan.com/read.php?3,7852,7852">What is serial boot?</a>
<a href="http://wiki.openwrt.org/toh/seagate/goflexnet#recovery.of.a.bricked.uboot.without.jtag">Recover without jtag</a></p>
<p><strong>This howto is for the Seagate Dockstar tested on archlinux with openocd 0.8!</strong></p>
<p>You need only a buspirate with a jtag firmware, no serial
is needed here.</p>
<h1>Steps</h1>
<ul>
<li>Download <a href="https://lunarius.fe80.eu/blog/files/openwrt/dockstar/buspirate.cfg">buspirate.cfg</a> <a href="https://lunarius.fe80.eu/blog/files/openwrt/dockstar/dockstar.cfg">dockstar.cfg</a> <a href="https://lunarius.fe80.eu/blog/files/openwrt/dockstar/uboot.j.kwb">uboot.j.kwb</a> </li>
<li>change ttyUSB1 to your buspirate interface in <strong>buspirate.cfg</strong></li>
<li>connect buspirate to the dockstar <a href="https://lunarius.fe80.eu/blog/files/openwrt/dockstar/jtag-dockstar-pinout.png">Dockstar pinout</a> <a href="https://lunarius.fe80.eu/blog/files/openwrt/dockstar/jtag-buspirate-pinout.png">Buspirate pinout</a></li>
<li>power the dockstar</li>
<li><code>openocd -f dockstar.cfg</code></li>
<li>telnet localhost 4444</li>
<li>enter "halt" into telnet session but don't hit enter</li>
<li>press reset button and very shortly after press enter into telnet session</li>
<li>when openocd shows "target halted in <strong>ARM state</strong> due to debug-request, current mode: Supervisor" everything is good</li>
<li>when openocd shows "target halted in <strong>Thumb state</strong> due to debug-request, current mode: Supervisor" <strong>repeat halt + reset procedure</strong></li>
<li>telnet: <code>sheevaplug_init</code></li>
<li>telnet: <code>nand probe 0</code></li>
<li>telnet: <code>nand erase 0 0x0 0xa0000</code></li>
<li>telnet: <code>nand write 0 uboot.j.kwb 0 oob_softecc_kw</code></li>
<li>wait ~15 minutes</li>
<li>openocd shows a success message</li>
</ul>Using jabber on jolla with an own certificate2014-01-12T23:42:00+01:002014-01-12T23:42:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2014-01-12:/blog/jolla-jabber-certificate.html<p>How to add a jabber server certificate to jolla.</p><p>The Sailfish xmpp client integrates perfect into your contacts, but doesn't work
with your own jabber server as long you are using self-signed certificate.
This is because SailfishOS even checks per default the server certificate, which is great!
But there is no GUI to add you own CA or certificate, so you don't get any connection to an
server which uses an unknown certificate.
IMHO commercial Certificate Authority are broken by design, but that's another story :).
The usual answer for a working jabber is disable the certificate check for
your xmpp. <em>You are disabling every feature of ssl (which is not
much as long over hundrets of CA are in your chain).</em> With checking you have a little bit more
secury than nothing. As alternative you can add the certificates to the telepathy chain.
The jabber client (telepathy-gabble) have an additional folder of certificates. telepathy
add certificates from /home/nemo/.config/telepathy/certs/ before loading all certificates
from /etc/pki/tls/certs/ca-bundle.crt. Just put it into that folder.</p>
<div class="highlight"><pre><span></span><code><span class="c1"># mkdir -p /home/nemo/.config/telepathy/certs/</span>
<span class="c1"># cp /home/nemo/Downloads/jabber-ca_or_cert.crt /home/nemo/.config/telepathy/certs/</span>
</code></pre></div>
<p><strong>I've re-added my jabber account</strong> to make the certificate work. <strong>:Maybe</strong> a reboot will apply
your certificate as well.</p>hacking smartwatch 22013-09-12T23:42:00+02:002013-09-12T23:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2013-09-12:/blog/smartwatch2-first-steps.html<p>hacking smartwatch part #1</p><p>The smartwatch 2 is sony's new smartwatch. I got one from a hackerthon in Berlin, where everybody
who attended got one from Sony. I liked to open it, but I'm a litte bit scared broking it's waterproofness.
So I'll wait for ifixit or other disassembly website.
Still I'm interested what's inside and how does it works?</p>
<p>The software side heavily depending on your android phone. There are some applications running
direct on the watch. Like alarm clock, settings, countdown.
Everything else is running on your phone and using it's display as canvas. <strong>Yes, you are writing over bluetooth
into a canvas.</strong> When you are clicking on your watch, the Sony Smartwatch app on your phone is sending an broadcast intent
which is starting your app. But that is a service in the background.
For more information look into <a href="https://github.com/ligi/sony_smartwatch_toolchain">ligi's github repo</a>.</p>
<p>Now get into the firmware and hardware. As Sony already written for the <a href="http://developer.sonymobile.com/services/open-smartwatch-project/">smartwatch (1)</a> you can easy
access the dfu bootloader. It's a dfu compatable bootloader.
As already described on Sony's hacker documentation </p>
<ul>
<li>Shutdown your smartwatch</li>
<li>Disconnect usb cable</li>
<li>only connect micro usb connector to smartwatch</li>
<li>you have around 1sec for this: press the powerbutton, plug the other usb cable end to the computer and release the powerbutton</li>
</ul>
<p><code>dfu-util -l</code> will show you when it's connected.
You can read and write it. Let's look into it.
dfu-util -l</p>
<div class="highlight"><pre><span></span><code><span class="k">Found</span><span class="w"> </span><span class="nl">DFU</span><span class="p">:</span><span class="w"> </span><span class="o">[</span><span class="n">0fce:f0fa</span><span class="o">]</span><span class="w"> </span><span class="n">devnum</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">cfg</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">intf</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="o">=</span><span class="ss">"@Internal Flash /0x08000000/03*016Kg,01*016Kg,01*064Kg,07*128Kg,03*016Kg,01*016Kg,01*064Kg,07*128Kg"</span>
<span class="k">Found</span><span class="w"> </span><span class="nl">DFU</span><span class="p">:</span><span class="w"> </span><span class="o">[</span><span class="n">0fce:f0fa</span><span class="o">]</span><span class="w"> </span><span class="n">devnum</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">cfg</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">intf</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">alt</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="o">=</span><span class="ss">"@eMMC /0x00000000/01*512Mg"</span>
</code></pre></div>
<p>I think all firmware is placed within the first flash. It's the internal one. An eMMC is an soldered sdcard.
Because we have the same partition layout twice, I think this is used for OTA firmware update. It's a common case
on embedded device. Double size your flash and split it into 2 identical parts. I'll name the first part A and part B is the other half.
We are booting part A, now an OTA update comes, the firmware will write this into part B and tell the bootloader:
'Try the B partition but only once.' Now the device will reboot and the bootloader boot part B. When the new firmware successful booted it tells the bootloader 'Boot everytime B now'. If the new firmware fails in B, the device has to be reboot and falling back to boot part A. This can be done by a hardware watchdog automatically.</p>
<p>I believe on the emmc we'll find all additional icons and application name we installed over the android.
Remember the smartwatch is only a remote display with sensors. Nothing more.</p>
<p>Let's disassemble the firmware. Put your device into dfu mode.
dfu has also upload capabilities. Upload means from device to a file. Download is for firmware flashing.
Upload the 2M flash into a file.</p>
<div class="highlight"><pre><span></span><code>dfu-util -a 0 -U /tmp/smartwatch_internal -s 0x08000000:2097152
</code></pre></div>
<p>Now let's do a simple <code>strings /tmp/smartwatch_internal</code>.
As we know from the settings menu we have an <strong>STM32F42x</strong>, a Cortex M4.
Look at the filenames.</p>
<p><strong>Technical Details:</strong></p>
<div class="highlight"><pre><span></span><code><span class="nl">type</span><span class="p">:</span><span class="w"> </span><span class="n">chip</span><span class="w"> </span><span class="o">[</span><span class="n">interfaces</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">detailed</span><span class="w"> </span><span class="n">description</span><span class="p">)</span>
<span class="nl">CPU</span><span class="p">:</span><span class="w"> </span><span class="n">STM32F4xx</span><span class="w"> </span><span class="p">(</span><span class="n">STM32F</span><span class="o">-</span><span class="mi">427</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="mi">429</span><span class="p">)</span>
<span class="nl">RAM</span><span class="p">:</span><span class="w"> </span><span class="mi">256</span><span class="n">k</span>
<span class="n">ROM</span><span class="o">/</span><span class="nl">flash</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="n">M</span>
<span class="nl">eMMC</span><span class="p">:</span><span class="w"> </span><span class="mi">512</span><span class="n">M</span><span class="vm">?</span><span class="w"> </span><span class="o">[</span><span class="n">connected over sdio</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">maybe</span><span class="w"> </span><span class="k">less</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="k">only</span><span class="w"> </span><span class="k">load</span><span class="w"> </span><span class="mi">128</span><span class="n">M</span><span class="w"> </span><span class="k">over</span><span class="w"> </span><span class="n">dfu</span><span class="o">-</span><span class="n">util</span><span class="p">.</span><span class="w"> </span><span class="n">Could</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">also</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">edge</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">dfu</span><span class="o">-</span><span class="n">util</span><span class="p">)</span>
<span class="nl">BT</span><span class="p">:</span><span class="w"> </span><span class="n">STLC2690</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="nf">power</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="k">only</span><span class="w"> </span><span class="n">BT</span><span class="w"> </span><span class="mf">3.0</span><span class="p">.</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="n">guess</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="nf">power</span><span class="w"> </span><span class="n">means</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">BT4</span><span class="mf">.0</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="nf">power</span><span class="p">.</span><span class="w"> </span><span class="n">But</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">seems</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">own</span><span class="w"> </span><span class="n">cortex</span><span class="w"> </span><span class="n">m3</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fw</span><span class="w"> </span><span class="n">upgrade</span><span class="w"> </span><span class="n">functionality</span><span class="p">)</span>
<span class="nl">Accelerometer</span><span class="p">:</span><span class="w"> </span><span class="n">bma250</span><span class="w"> </span><span class="o">[</span><span class="n">SPI (4-wire, 3-wire), i2c, 2 interrupt pins</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">Bosch</span><span class="w"> </span><span class="n">Sensoric</span><span class="p">)</span>
<span class="nl">Compass</span><span class="p">:</span><span class="w"> </span><span class="n">ak8963</span><span class="w"> </span><span class="o">[</span><span class="n">SPI, I2C</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">really</span><span class="vm">?</span><span class="w"> </span><span class="n">sony</span><span class="w"> </span><span class="n">didn</span><span class="s1">'t exposed it or is this just a leftover from a debug board?)</span>
<span class="s1">NFC-tag: ntag203f [interupt pin for rf-activity] (only a tag - the mcu only knows if it got read)</span>
<span class="s1">Touch: ttsp3 (i'</span><span class="n">m</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">sure</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">Cypress</span><span class="w"> </span><span class="n">TTSP</span><span class="w"> </span><span class="k">with</span><span class="w"> </span><span class="n">i2c</span><span class="p">)</span>
<span class="nl">LiIonController</span><span class="p">:</span><span class="w"> </span><span class="n">Max17048</span><span class="w"> </span><span class="o">[</span><span class="n">i2c</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">fuel</span><span class="w"> </span><span class="n">gauge</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">battery</span><span class="w"> </span><span class="n">controller</span><span class="p">)</span>
<span class="n">Light</span><span class="o">/</span><span class="nl">AmbientSensor</span><span class="p">:</span><span class="w"> </span><span class="n">Taos</span><span class="w"> </span><span class="n">TSL2771</span><span class="w"> </span><span class="o">[</span><span class="n">I2C</span><span class="o">]</span>
<span class="nl">RTC</span><span class="p">:</span><span class="w"> </span><span class="n">included</span><span class="w"> </span><span class="n">CPU</span>
<span class="nl">Display</span><span class="p">:</span><span class="w"> </span><span class="n">TC358763XBG</span><span class="w"> </span><span class="o">[</span><span class="n">SPI (3,4 wire), SSI for display data; i2c, spi, pwm for control</span><span class="o">]</span><span class="w"> </span><span class="p">(</span><span class="n">Display</span><span class="w"> </span><span class="n">Controller</span><span class="p">)</span>
<span class="nl">Buzzer</span><span class="p">:</span><span class="w"> </span><span class="n">GPIO</span><span class="w"> </span><span class="n">wired</span>
</code></pre></div>
<p>Most of the sensors and actors are already supported by linux kernel because they are built in some (Sony) smartphones.
No I don't want run linux on it. But we have already working driver which we can adapt for an alternative firmware.</p>
<p>Search or github' search for STM32F4xx_StdPeriph_Driver which is freely available SDK.
I think they don't written a complete firmware from scratch. Because of some strings I guess it's a 'uCos' extended
to their needs.</p>
<p><strong>Sony please provide us with the correct wiring of the sensors and actors so we can build our own firmware?!</strong></p>first step on a longer journey2013-07-18T00:42:00+02:002013-07-18T00:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2013-07-18:/blog/pulseaudio-first-part.html<p>A first step within pulseaudio</p><p>After reading some documentation and a lot of code. A somehow working module
evolves. It supports simple module argument, it can connect to a remote server and
also plays audio.</p>
<p>But the problems starting here, because threads are nice and can hurt you because of context.
For the first version it is good to hear voices in my ears coming out of speakers over a network.
I implemented an early version with a lot of downsides:</p>
<ul>
<li>no latency informations</li>
<li>threading issues</li>
<li>no zerocopy</li>
<li>...</li>
</ul>
<p>What I've done wrong was attaching libpulse on pulse server mainloop. Every context and stream callback was run by the mainloop as well as read operations. Not good thing. Only pa_sink_render is working within the I/O thread.
Zero copy for now is broken by libpulse, because using pa_stream_write without a free_callback will copy the samples into an internal buffer.</p>
<p>But for the first version ok. Fixing my threading problem is easy move everything inside our thread.
What means create a mainloop for the libpulse. My first thought, that could not be hard, because epoll, a modern efficient select replacement supports chaining. Just chain or combine rt_poll with our libpulse mainloop.
Not a easy solution. Combining a mainloop poll and a rt poll is hard, because of two lists of filedescriptors which can not be simple appended. Both lists get generated each time poll runs.</p>
<p>Stepping a step back and asking why should I use rt_poll? Is there another solution which fits much more the concept of using a second mainloop?
A thread only working as a mainloop should also work. The only task what the thread must take case is the <code>pa_thread_mq</code>.</p>how pulse module are structured?2013-07-18T00:23:00+02:002013-07-18T00:23:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2013-07-18:/blog/pulseaudio-how-modules-works.html<p>How does pulseaudio modules are working?</p><p>On my journey to a new module-tunnel I took a closer look into other modules.
Pulseaudio got modules for event handling, got modules for os driver frameworks like alsa, oss, solaris.
Also there a drivers to communicate over the local network. Starting with mod-native-protocol-tcp to allow
remote pulseaudio connections, there is also support for esound, zeroconf, rtp or raop.
Modify sound stream samples is also possible, take a look into the filters.</p>
<p>To write a hardware driver or network based driver I would recommend reading null-sink, raop-sink and esound-sink. </p>
<p>After looking around into several pulse modules. It is clear that most of the module which act as a sink
have the following structure and nearby the same code beside from driver specific parts.
:::c
void thread_func() {
/<em> hard work </em>/
}</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="n">pa__init</span><span class="p">(</span><span class="n">pa_module</span><span class="o">*</span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* parse + validate + copy module arguments */</span>
<span class="w"> </span><span class="n">pa_modargs_new</span><span class="p">(</span><span class="n">m</span><span class="o">-></span><span class="n">argument</span><span class="p">,</span><span class="w"> </span><span class="n">valid_modargs</span><span class="p">)</span>
<span class="w"> </span><span class="cm">/* init driver specific */</span>
<span class="w"> </span><span class="cm">/* setup a real time poll */</span>
<span class="w"> </span><span class="n">u</span><span class="o">-></span><span class="n">rtpoll</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pa_rtpoll_new</span><span class="p">();</span>
<span class="w"> </span><span class="cm">/* setup a message queue */</span>
<span class="w"> </span><span class="n">pa_thread_mq_init</span><span class="p">(</span><span class="o">&</span><span class="n">u</span><span class="o">-></span><span class="n">thread_mq</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="o">-></span><span class="n">core</span><span class="o">-></span><span class="n">mainloop</span><span class="p">,</span><span class="w"> </span><span class="n">u</span><span class="o">-></span><span class="n">rtpoll</span>
<span class="w"> </span><span class="n">pa_sink_set_asyncmsgq</span><span class="p">(</span><span class="n">u</span><span class="o">-></span><span class="n">sink</span><span class="p">,</span><span class="w"> </span><span class="n">u</span><span class="o">-></span><span class="n">thread_mq</span><span class="p">.</span><span class="n">inq</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* create a thread */</span>
<span class="w"> </span><span class="n">pa_thread_new</span><span class="p">(</span><span class="s">"null-sink"</span><span class="p">,</span><span class="w"> </span><span class="n">thread_func</span><span class="p">,</span><span class="w"> </span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="cm">/* register sink */</span>
<span class="w"> </span><span class="n">pa_sink_put</span><span class="p">(</span><span class="n">u</span><span class="o">-></span><span class="n">sink</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">pa__done</span><span class="p">(</span><span class="n">pa_module</span><span class="o">*</span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* deinit private structure + free everything */</span>
<span class="p">}</span>
</code></pre></div>
<p>All sink modules have a real time poll running in a seperated thread, often also caled I/O thread. This is because of [http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Threading/|the threading model]. In summary it says "don't block the mainloop and do the hard work within the I/O loop."
Back to our thread, is has to do the real work of our module. It's dequeuing data from
a sink buffer, mixing and adjusting volumes. This set of tasks is named <strong>rendering</strong>. It is done by <code>pa_sink_render</code>.</p>
<p>Syncronisation is done by message queues between mainloop and I/O loop named <code>pa_thread_mq</code> which has 2 <code>pa_asyncmsgq</code> one input queue for message to the thread and one <em>output</em> queue from thread to the mainloop.
rtpoll is not as powerfull a mainloop is, but you can register at least a filehandler packed within rt_poll_item. When you write a network protocol this will be your socket.</p>My gsoc project pulseaudio mod-tunnel2013-07-17T23:42:00+02:002013-07-17T23:42:00+02:00Alexander Couzenstag:lunarius.fe80.eu,2013-07-17:/blog/pulseaudio-starting-blogging.html<p>Starting blogging about gsoc</p><p>After one month here comes my first blog post about it.
My gsoc project is creating a new mod-tunnel using libpulse api.</p>
<p>You can use module-tunnel to connect your local pulseaudio to a remote pulseaudio.
This is quite usefull, because you can stream over the network your audio from laptop to a dedicated sound system
with real speakers. With pavucontrol you can move simple move a stream from local output device to the remote one.
In combination with mod-zeroconf-discover and mod-zeroconf-publish it will automatic find other pulseaudio servers and
connects to them.</p>
<p>What module-tunnel really does is creating a virtual sound card on your local pulseaudio server. On the remote site
it creates a client as every other normal sound application like mplayer, vlc, [...]</p>
<p><em>Why I'm rewriting a complete module?'</em>
Before saying anything about it, mod-tunnel seems to be a very old module from the beginning.
But it has a lot of downside beside the good one that it works as long you have a stable connection to the remote server.</p>
<ul>
<li>It can not recover from any kind of errors.</li>
<li>mod-tunnel doing all the client protocol stack on its own instead of using the well-tested and well-written libpulse with callbacks and state machines.</li>
<li>adding new features is difficult because of it's simple structure</li>
</ul>graphitecollectdnl80211n setup2012-01-06T14:32:00+01:002012-01-06T14:32:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2012-01-06:/blog/nl80211n-collectd-graphite.html<p>How to create a statistics setup for nl80211 infos from openWRT based APs</p><p>While providing a working wireless network you want some statistics data. This small howto will create
a small statistic setup using graphite and collectd.</p>
<p>We'll use the kernel interface <em>nl80211</em> which is also used by hostapd to collect all statistics data
from AP.
A collectd plugin will communicate with the kernel via nl80211 at AP. Collectd will also transfer these data
over network to our statistics host where graphite runs. On the graphite host will be a collectd which
receive statistics and push it into graphite.</p>
<p>'picture made with dia shows kernel,nl80211,ap,network,collectd,graphitehost,graphite'</p>
<h1>Install statistics host</h1>
<h2>Install graphite</h2>
<p>Let setup our graphite host. I will use a debian testing, because of a newer collectd version.
Collectd v5 contians a plugin for graphite. Collectd v4 can only used via python plugin.</p>
<p>graphite install:
code:</p>
<div class="highlight"><pre><span></span><code>apt-get<span class="w"> </span>install<span class="w"> </span>python-django-tagging<span class="w"> </span>python-cairo<span class="w"> </span>libapache2-mod-wsgi<span class="w"> </span>python-twisted<span class="w"> </span>python-memcache<span class="w"> </span>python-pysqlite2<span class="w"> </span>python-simplejson<span class="w"> </span>python-django
pip<span class="w"> </span>install<span class="w"> </span>whisper
pip<span class="w"> </span>install<span class="w"> </span>carbon
pip<span class="w"> </span>install<span class="w"> </span>graphite-web
<span class="nb">cd</span><span class="w"> </span>/opt/graphite/conf
cp<span class="w"> </span>carbon.conf.example<span class="w"> </span>carbon.conf
cp<span class="w"> </span>storage-schemas.conf.example<span class="w"> </span>storage-schemas.conf
<span class="nb">cd</span><span class="w"> </span>/opt/graphite/webapp/graphite/
python<span class="w"> </span>manage.py<span class="w"> </span>syncdb
</code></pre></div>
<p>You should change at least the storage-schemas.conf. Increase default retentions upto 14 days.</p>
<div class="highlight"><pre><span></span><code>/opt/graphite/bin/carbon-cache.py<span class="w"> </span>start
</code></pre></div>
<p>src: http://linuxracker.com/2012/03/31/setting-up-graphite-server-on-debian-squeeze/</p>
<h2>Install collectd</h2>
<p>collectd install:</p>
<div class="highlight"><pre><span></span><code>apt-get<span class="w"> </span>install<span class="w"> </span>collectd-core
</code></pre></div>
<p>Add these lines to types.db ( /usr/share/collectd/types.db )</p>
<div class="highlight"><pre><span></span><code><span class="s s-Atom">stations</span> <span class="nb">val</span><span class="s s-Atom">ue</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">256</span>
<span class="s s-Atom">nl_station</span> <span class="s s-Atom">connection_time</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">inactive_time</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">rx_bytes</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">tx_bytes</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">rx_packages</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">tx_packages</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">tx_retried</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">tx_failed</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">signal</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:-</span><span class="mi">255</span><span class="o">:</span><span class="mi">255</span> <span class="s s-Atom">nl80211_mask</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">nl80211_beacon_loss</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">4294967295</span> <span class="s s-Atom">signal_avg</span><span class="o">:</span><span class="nv">GAUGE</span><span class="o">:-</span><span class="mi">255</span><span class="o">:</span><span class="mi">255</span>
<span class="s s-Atom">nl_survey</span> <span class="s s-Atom">noise</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:-</span><span class="mi">255</span><span class="o">:</span><span class="mi">255</span> <span class="s s-Atom">active</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">18446744073709551615</span> <span class="s s-Atom">busy</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">18446744073709551615</span> <span class="s s-Atom">extbusy</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">18446744073709551615</span> <span class="s s-Atom">transmit</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">18446744073709551615</span> <span class="s s-Atom">receive</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">18446744073709551615</span> <span class="s s-Atom">inuse</span><span class="p">:</span><span class="nv">GAUGE</span><span class="o">:</span><span class="mi">0</span><span class="o">:</span><span class="mi">1</span>
</code></pre></div>
<p>add following lines to /etc/collectd.conf</p>
<div class="highlight"><pre><span></span><code><span class="nb">LoadPlugin</span><span class="w"> </span>network
<span class="nb">LoadPlugin</span><span class="w"> </span>write_graphite
<span class="nt"><Plugin</span><span class="w"> </span><span class="s">network</span><span class="nt">></span>
<span class="w"> </span><span class="nb">Listen</span><span class="w"> </span><span class="s2">"0.0.0.0"</span><span class="w"> </span><span class="s2">"25826"</span>
<span class="nt"></Plugin></span>
<span class="nt"><Plugin</span><span class="w"> </span><span class="s">write_graphite</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><Carbon></span>
<span class="w"> </span><span class="nb">Host</span><span class="w"> </span><span class="s2">"localhost"</span>
<span class="w"> </span><span class="nb">Port</span><span class="w"> </span><span class="s2">"2003"</span>
<span class="w"> </span><span class="nt"></Carbon></span>
<span class="nt"></Plugin></span>
</code></pre></div>
<p>.</p>
<div class="highlight"><pre><span></span><code>/etc/init.d/collectd<span class="w"> </span>restart
</code></pre></div>
<p>We are done with our graphite host. Start within screen the django development server. For production setup of graphite use memcache + wsgi.</p>
<div class="highlight"><pre><span></span><code><span class="nb">cd</span><span class="w"> </span>/opt/graphite/webapp/graphite/
python<span class="w"> </span>manage.py<span class="w"> </span>runserver
</code></pre></div>
<h1>Configuring AP</h1>
<p>You can build your own openWRT image or use this <a href="http://lynxis.crew.c-base.org/openwrt/lazus_7/">one</a>.</p>
<h2>Howto build our openWRT image</h2>
<div class="highlight"><pre><span></span><code>mkdir<span class="w"> </span>openwrt-collectd
<span class="nb">cd</span><span class="w"> </span>openwrt-collectd
<span class="nb">export</span><span class="w"> </span><span class="nv">SRCROOT</span><span class="o">=</span><span class="nv">$PWD</span>
git<span class="w"> </span>clone<span class="w"> </span>git://nbd.name/openwrt.git
<span class="nb">cd</span><span class="w"> </span>openwrt
./scripts/feeds<span class="w"> </span>update
./scripts/feeds<span class="w"> </span>install<span class="w"> </span>collectd
<span class="nb">cd</span><span class="w"> </span>..
git<span class="w"> </span>clone<span class="w"> </span>git://dev.c-base.org/collect-nl80211/collectd-nl80211.git
<span class="nb">cd</span><span class="w"> </span>collectd-nl80211
sh<span class="w"> </span>create-openwrt-collectd-patch.sh
cp<span class="w"> </span><span class="m">999</span>-nl80211.patch<span class="w"> </span>../openwrt/feeds/packages/utils/collectd/patches
<span class="nb">cd</span><span class="w"> </span>../openwrt/feeds/packages/
cat<span class="w"> </span><span class="nv">$SRCROOT</span>/collectd-nl80211/openwrt-collectd-makefile.patch<span class="w"> </span><span class="p">|</span><span class="w"> </span>patch<span class="w"> </span>-p0
<span class="nb">cd</span><span class="w"> </span><span class="nv">$SRCROOT</span>/openwrt
</code></pre></div>
<p>This will patch collectd Makefile. You can select now nl80211 within openwrt build system
With <code>make menuconfig</code> select from collectd the nl80211 module. Make sure you compiled
collectd + collectd-mod-network + collectd-mod-nl80211 hard into your image and not as module.</p>
<h2>Flash your AP</h2>
<div class="highlight"><pre><span></span><code>scp<span class="w"> </span><span class="nv">$SRCROOT</span>/openwrt/bin/ar71xx/openwrt-ar71xx-generic-tl-wdr4300-v1-jffs2-sysupgrade.bin<span class="w"> </span>root@192.168.1.1:/tmp
ssh<span class="w"> </span>root@192.168.1.1
sysupgrade<span class="w"> </span>/tmp/openwrt-ar71xx-generic-tl-wdr4300-v1-jffs2-sysupgrade.bin
</code></pre></div>
<h2>Configuring openWRT</h2>
<p><a href="http://lynxis.crew.c-base.org/blog/collectd.conf">collectd.conf</a></p>
<div class="highlight"><pre><span></span><code><span class="c1"># enable default wireless OpenWRT</span>
uci<span class="w"> </span><span class="nb">set</span><span class="w"> </span>wireless.radio0.disabled<span class="o">=</span><span class="m">0</span>
uci<span class="w"> </span>commit
<span class="c1"># modify network config + wifi interface to match your configuration</span>
scp<span class="w"> </span>collectd-example.conf<span class="w"> </span>root@192.168.1.1:/etc/collectd.conf
</code></pre></div>rsyslog listen on udp:514 + filtering logfile by ip2012-01-06T14:32:00+01:002012-01-06T14:32:00+01:00Alexander Couzenstag:lunarius.fe80.eu,2012-01-06:/blog/rsyslog-udp-filter.html<p>rsyslog listen on udp:514 + filtering logfile by ip</p><p>This snippet is usefull for openWRT setups and other rsyslog sending systems.
Add this near head of <em>/etc/rsyslog.conf</em>. ServerAddress is <em>optional</em></p>
<div class="highlight"><pre><span></span><code>$ModLoad imudp
$UDPServerAddress 10.0.23.43
$UDPServerRun 514
</code></pre></div>
<p>This to <em>/etc/rsyslog.d/aps.conf</em></p>
<div class="highlight"><pre><span></span><code><span class="p">:</span><span class="n">fromhost</span><span class="o">-</span><span class="n">ip</span><span class="p">,</span><span class="w"> </span><span class="n">isequal</span><span class="p">,</span><span class="w"> </span><span class="s2">"10.0.23.42"</span><span class="w"> </span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nb">log</span><span class="o">/</span><span class="n">ap</span><span class="o">-</span><span class="n">mainhall</span><span class="o">-</span><span class="n">ng</span>
<span class="o">&</span><span class="w"> </span><span class="o">~</span>
</code></pre></div>
<p><strong>&~</strong> means don't log further that line which match 10.0.23.42. Otherwise it will also log into
e.g. /var/log/syslog syslog events. You also use this for a more generic way:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="n">template</span><span class="w"> </span><span class="n">DynFile</span><span class="p">,</span><span class="s2">"/var/log/system-%HOSTNAME%.log"</span>
<span class="p">:</span><span class="n">fromhost</span><span class="o">-</span><span class="n">ip</span><span class="p">,</span><span class="w"> </span><span class="o">!</span><span class="n">isequal</span><span class="p">,</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="w"> </span><span class="err">?</span><span class="n">DynFile</span>
<span class="o">&</span><span class="w"> </span><span class="o">~</span>
</code></pre></div>
<p>Also usefull if you want to provide a pipe-file for further processing.</p>
<div class="highlight"><pre><span></span><code><span class="p">:</span><span class="n">programname</span><span class="p">,</span><span class="w"> </span><span class="n">isequal</span><span class="p">,</span><span class="w"> </span><span class="s2">"freeradius"</span><span class="w"> </span><span class="o">|/</span><span class="k">var</span><span class="o">/</span><span class="n">run</span><span class="o">/</span><span class="n">rsyslog</span><span class="o">-</span><span class="n">freeradius</span><span class="o">.</span><span class="n">pipe</span>
</code></pre></div>