Small software and fun with an ESP8266

I enjoy building small, self-contained software for the pure joy of simplifying what you build. Building complex software is easy; small and maintainable software is not (not always anyway).
To take that same vein of thought, I have been working on a floppy-sized Linux distro (fluxflop) for the pure fun of how small I can build the Linux kernel, while keeping it usable. Running make tinyconfig is easy enough, but how small can you truly make the kernel? 

In my quest to find any resources on this, I stumbled upon Linux Tiny. It's a set of patches (with the intention of getting the patches merged into mainline to make future builds easier) that can slim down the kernel and add additional Kconfig options for reducing the compiled size. The project has not been updated since approx 2007 and uses Linux 2.6.23.0. Backporting these patches (whats the opposite of backport with newer software? haha) would take time and it's not guaranteed that the patch intention would work the same. Well, with too much time on my hands, I dug deep and did just that. You can see the git repo here with updated patches for Linux 6.9. Now, they are not guaranteed to work for everyone and every arch, but for i386 I was able to shave off about ~80KB which doesn't seem like much, but it all adds up in the end. For fluxflop, I was able to trim bzImage down to 712KB, and an aarach64 kernel down to about 820KB. 

I found this presentation that Matt Mackall gave in 2004 for the introduction of Linux Tiny. In the slides, it is mentioned that the Linux kernel produced, with net, EXT2, a NIC (not mentioned which one) and IDE, was 363KB! Very impressive. For my project, that 712KB is without /dev/ram, no filesystems, network capabilities, VGA and not even PS/2. All over serial too, so good luck having it be any use on a desktop box. Still, this is something to aim for. I would be curious to replicate the results in the presentation to build a 720KB floppy-sized Linux distro.
 




Two years ago this summer, I purchased an ESP8266 from Aliexpress for less than $5 CAD. As well, as DHT11 air sensors and a capacative soil moisture sensor. Somehow all the parts have been sitting in a drawer all this time, and I finally got around to building something. Microcontrollers of this nature, including the Arduino, have never interested me very much and I think it's due to having no real-world application of them. Living rurally as I do now, having a wifi weather station connected at home is mostly useless. You can just look out side and look up. Sure, having a forecast of the weather of the days or weeks to come can be productive to plan gardening or hiking in the forest, but it doesn't really matter too much. I find that out here, time ceases to exist. It is either daytime or nighttime. You wake up when the sun rises, and go to bed a few hours after sunset. Working remotely has given me the ultimate freedom in my life in that regard, and I am thankful. Except for 9am standups.

Anyway, plugging the sensors into a breadboard and writing some Python code for the ESP8266 was exhilarating. I realized how much I have missed working with electronics like this, using ICs and DIP switches and doing the calculations to find the resistance of a resistor. Through some thorough reading of MicroPythons documentation (which is fantastic by the way), I was able to flash MicroPython, get a working REPL accessible over wifi and start building.

What I built was a very simple weather station. From the DHT11 sensor, I receive the air temperature and humidity. There is no precision to it and readings are output in whole numbers. Not that I needed to know if it was 11C or 11.1C outside anyway. Using the capacative soil sensor, I was able to read from the output voltage using the AD0 pin. 

Power usage is the next task to complete. My ESP8266 has a built in micro USB port which is very convenient for using off the shelf phone battery packs. From some quick research, it seems that with the board running + wifi I could expect around 65-80mA. Using deepsleep I could expect around 20mA which is impressive, but not sure if it's possible using the built-in linear regulator the micro USB port uses. Regardless, at 75mA consumption and using a 9000mAh battery pack, I could expect around 120 hours. Which doesn't seem like very much, but that is having the board on the entire time. I have some more configuring to do, and build a nice case out of it so I can actually put outside (and most likely forget about it in my yard somewhere).


 


Reading from sensors isn't enough in 2024. No, you must log data, send network requests and have other companies store your precious data. So like any sane person, I did just that. Using the Adafruit IO platform, they offer an easy way for storing and building pretty dashboards for your IoT boards.


 

I had a lot of fun building something that was a bit hardware and a bit software. And all for less than $10 which is staggering. I can see why these boards are so popular ;) 


You can download the source code to my boot.py here: https://geekness.eu/sites/default/files/boot.py



 

Tags

Linux 4.15.2 on SnackLinux

Quick update to SnackLinux, rolled out Linux 4.15.2 with Busybox 1.28.0. Also switched over to x86_64 only (for now at least) since it simplifies a lot of things. I removed the need to staticly link everything and get rid of that niche, since a few other smaller distros cover that (Alpine Linux for example). Again, this simplifies building packages and running into less issues. Check it out on Github for build instructions, or the getting started page on getting SnackLinux running.

Remote code execution with Hitron CGNM-2250

Edit: This has been fixed in the latest firmare update 4.5.10.25

The routers that you receive from your ISP are almost always garbage: not many options to configure and pitiful wifi range. The router/modem that Shaw customers receive is the Hitron CGNM-2250 thankfully isn't completely terrible, 802.11ac plus gigabit ports. I was poking about and researching the model and came upon an exploit for a similar model version for remote code execution. The CGNM-2250 is vulnerable as well, for reference my software version is 4.5.8.20 with hardware version 1A. The input for the ping utility through the web interface isn't sanitized so you can enter arbitrary input. I discovered that it has a few basic utilities, including Dropbear.

 

From there you can ssh into your router with

ssh mso@192.168.0.1 -p 29

The password is msopassword (go figure!)

You'll be greeted with a fun menu driven interface. 

Most of the menus are for debugging and initial programming purposes. There is a menu option to set the TFTP download image URL to flash the device, so it might be possible to flash your own firmware though I don't know how possible that is.

Going back to the web interface, I was able to see what tools and programs are available on the router.

It is your basic Linux system, busybox plus some manufacturer utilities. For a full list of binaries available see below: #/sbin wlanconfig wifitool wifirrm watchdog vconfig utelnetd udhcpd udhcpc udevstart udevsend udevd udev ti_udhcpc ti_todc ti_tftp ti_syslogd ti_dhcp6c start-stop-daemon route rmmod reboot radartool poweroff pktlogdump pktlogconf manufacture_ath_throughput_sta manufacture_ath_throughput_ap makeVAP lsmod klogd killVAP iwpriv iwlist iwconfig insmod init ifconfig ht_wifi_ioctl ht_atom_cmd hostapd_cli hostapd halt fsck.ext3 fdisk cfg blockdev atomcmdlist athstatsclr athstats athcfg_api arp apup apstats apdown apcfg activateVAP 80211stats #/usr/bin which uptime traceroute6 traceroute tr top tftp test renice pstree pmap mkfifo logger killall hexdump head free flock find expr dirname cut crontab basename awk add-shell [[ [ #/bin xmlwf umount touch tar sync sleep sh sed rm pwd ps ping6 ping pcap-config netstat mv mount more mknod mkdir luac lua ls login ln kill iptunnel iprule iproute iplink ipaddr ip hostname grep getopt false echo dnsdomainname dmesg df dd date cp clnkstat clnkrst clnkqos clnkpm clnkmocamib clnkmem clnkmcast clnkhwtst clnkfwupd clnkcfg clinkd chown chmod cat busybox bash ash DCAP.46 DCAP.45 DCAP.44 DCAP.42 DCAP.41 DCAP.40 DCAP.38 DCAP.37 DCAP.35 DCAP.19 DCAP.18 DCAP.16 DCAP.137 DCAP.132 DCAP.126 DCAP.125 DCAP.123 DCAP.122 DCAP.116 DCAP.115 DCAP.112 DCAP.111 DCAP.110 DCAP.109 DCAP.107 DCAP.104 DCAP.103 DCAP.102 DCAP.101 DCAP.08 DCAP.03 DCAP.02 DCAP CandDdvr.ko ##/usr/sbin watchdog_rt upstream_manager_1q upstream_manager upgradebox update testmode_handle.sh testmode sync_app_np_reboot swdl2 sw_dl snmpcmd snmp_agent_cm setstartup setkey setenv sched runall rpc_reverse_server_util rpc_reverse_server rpc_management_server rpc_ifconfig rfs.cfg rfs regs qos_dsx_sm productionmode printenv pp_fw_download portmap pmap_set pmap_dump pcd nvtst nvread mptint mlx logger ledcfg l2switch_iram.img l2switch_init l2switch_dram.img iostat iccctl icc_genEvent htxvendordb ht_iwcmd ht_buttond hal_tuner_mgr hal_event_mbox hal_cmd_mbox gptimer gim getenv getPortByMAC.sh flash_eraseall fdump ext_switch_init eventmgr_cm energy_manager_app dpp_dev_init.sh downstream_manager docsis_mac_manager docsis_mac_driver docsis_init_once docsis_dl_box docsis_config_to_text dmg_provisioning dl dispatcher dfltr_class_init.sh ddl dbridge_mdf_init.sh dbridge_l2vpn_ds_init.sh dbridge_init crond cmdl cm_status cli_net.sh cli_mem.sh cli chroot cefdk cc_init_once brctl bpi_tek bpi_sa_map bpi_auth MxL_HRCLS_FW_4.1.5.5.mbin MxL_HRCLS_FW.mbin FwUpstreamDocsis3_I.bin FwUpstreamDocsis3_D.bin FwUpstreamDocsis2_I.bin FwUpstreamDocsis2_D.bin Through digging in the CLI menu I found that /etc/scripts/sys_startup.sh is ran on startup, making it a easier to inject any commands you want to run at startup. I haven't been able to get to a shell yet, since logging in with the 'mso' user it takes you to the CLI menu. But cat /etc/passwd reveals:

root:$1$27272727:0:0::/:/bin/false
nobody:$1$27272727:65535:65535::/:/bin/false
mso:$1$1w7AswO3$IJCko5PwRk6ChJrIYgMQs/:100:100::/:/usr/sbin/cli

One should be able to symlink /bin/sh to /usr/sbin/cli so upon login it would drop to a shell. Entering commands via the web interface is a bit tricky since it doesn't like pipes (|), it's just a matter of getting around the JS validation. Once I can get to a shell I'll write a followup to this post Issue patched in version 4.5.10.25

 

SnackLinux update

SnackLinux now has a whopping 31 packages, which include a (somewhat) working gcc toolchain and other fun GNU utilities (vitetris included!). I was able to add Docker support as well, which is just tarballed userland. Getting a working gcc toolchain was a bit of a pain in the butt. Pain in the butt because musl doesn't play nice with every piece of software out there, since most (that I have encountered anyway) think we're using glibc. And since SnackLinux is focused on every packaging being staticly compiled, not every package plays nice with that either. For example, there is a Python 2.7.9 package in the repository that is missing quite a few modules, see below:

_codecs_cn         _codecs_hk         _codecs_iso2022 
 _codecs_jp         _codecs_kr         _codecs_tw      
 _ctypes            _ctypes_test       _curses         
 _curses_panel      _hashlib           _hotshot        
 _json              _lsprof            _multibytecodec 
 _multiprocessing   audioop            bz2                
 dl                 future_builtins 
 imageop            linuxaudiodev      ossaudiodev     
 readline           syslog      

Fortunately, it works. Sort of. I wouldn't recommend using it at all. This is why gcc 4.9.2 needs to be patched for musl to get around this. That being said, most of the current packages are natively compiled on SnackLinux itself, so at least it's somewhat self sufficient ;)

 

I just got Nim working, as well as Lua. Perl is possible through staticperl. It's suprising the amount of software that depends on Perl, pkg-config and syslinux come to mind. With a working Python implementation being the last holdout, SnackLinux may finally gain some traction....in whichever niche it fits in... I suppose.

Nimrod language

 I have recently discovered the Nimrod programming language. I usually don't branch out on languages because, well, stuff you don't know can be scary. I'm surprised how easy it is to get going though, it reminds me quite a bit of Python. I put up a test project on Github that fetches the weather for a given location.

Tags

Building a distro that almost works

 For the most part, SnackLinux works. I've been having problems with Busybox, so I've made packages for coreutils, binutils, sed, grep and gawk. When compiling anything, I get:

segfault at 0 ip    (null) sp bfdb1cbc error 4 in busybox[8048000+e8000]

or something along the lines of that. I used the newest Buildroot, 2013.11, to create a new toolchain and cross compile uClibc 0.9.33 for SnackLinux. I have yet to recompile Busybox yet, but I'm working on getting gcc natively working on SnackLinux. Once that is completed, I should be able to compile SnackLinux from within SnackLinux.

Getting a terminal IBM Model M to work with PS/2

 I recently bought another IBM Model M (1395660) on eBay the other day, not thinking that it is actually a terminal keyboard. I thought it has a detachable SDL cable like my current Model M (1391401). I was wrong. Turns out it has a non-removable RJ-45 plug instead, thus being a terminal keyboard. Well, aftering some researching, some were able to get it to work by using an ATMega. I was able to find a pinout of the RJ45 plug on the keyboard, and simply just wire it up to a PS/2 cable. Though apparently, the colour of wire for PS/2 is not standardized, which led to testing each pin to see what it does. I cannibalized an old Microsoft keyboard for the cable and was able to hook the wires up straight to each other.

PS/2 cable wires on a breadboard, original connector above.

 

For this specific PS/2 cable, the pinout is as follows:
IBM -> PS/2 Cable
black -> red         +5V 
red -> white         data 
yellow -> brown  clock
white -> black     ground 
 
The last wire (next to the white wire) on the breadboard is ground, which I have on the metal body of the keyboard. Thankfully everything mostly works. The "Print" key on the left hand side of the board is somehow F5 and the blank key above it is CTRL+F. Next step is a neat soldering job and it's good to go!

SnackLinux, an intro to building your own distro

 I've spent the last week or two working on SnackLinux, a small Linux distro. I managed to get uClibc in there, as well as tcc, which makes it somewhat useful. The source of it all is there, so you can compile the distro yourself (sans the packages). There are also ISOs which you can download here and fire them up in a virtual machine.