2020–12–05: Alternate EG25G userspace project
I've been reverse engineering EG25G userspace on and off since mid July 2020.
I really dislike the Quectel's code. They took relatively clean (if a bit overengineered) Qualcomm code and made a total mess, that somehow barely holds together.
They manage to do things like
sprintf(buf, "echo %s > /dev/kmsg", barely_checked_user_input); system(buf);
in a superuser process, or system("rm /something")
instead of
unlink("/something")
, etc. None of their code inspires any
confidence in the modem's software as a whole.
Biktor has a nice bootloader/kernel cleanup project, so I decided to start a fully FOSS userspace rewrite project to complement it.
How it will look/work
Alternate FOSS userspace code will be very simple and will not depend on anything in the original root filesystem of the modem's firmware.
You'll be able to install the FOSS userspace along with the existing rootfs content and choose which one to boot to via my modem power manager:
# to power up the modem and boot the original userspace code echo 1 /sys/class/modem-power/modem-power/device/powered
or:
# to power up the modem and boot the FOSS userspace code echo N /sys/class/modem-power/modem-power/device/powered
Modem power manager will configure DTR and #W_ENABLE gpios to one of the 4 possible configurations, and then it will power up the modem. These two gpios can be relatively easily read from the modem's userspace during boot, and can be (a)bused to make boot decisions very early on after the kernel starts the /sbin/init process.
The existing firmware will need just a single simple and fairly safe
modification. The rest of the changes will be just addition of new files to the
root filesystem to a /foss/
directory.
In order to make boot decisions, the FOSS userspace will include a small
/sbin/init
binary that will be executed by the kernel instead of
the original one, and will check the status of the above mentioned gpios and
then execute either /foss/init.2
, /foss/init.3
,
/foss/init.4
, or the original firmware's
/sbin/init.sysvinit
. One of these will become the PID
1 process.
This will be the foundation for easy experimentation with the FOSS userspace for the modem's OS running on it's ARM CPU.
Anyone will be able to modify and test the FOSS userspace code quite
fearlessly. Recovery will be as simple as booting to the original userspace, or
keeping one of the /foss/init.*
binaries in an always known-good
state, and only experimenting with the others.
Plan / progress
- FOSS /sbin/init multiplexer (almost done, just needs testing)
- Play with /foss/init.2 (mount filesystems, init lo, setup USB configuration so that we can observe and interact with the new userspace via /dev/ttyUSB1 from A64 SoC)
- Properly handle shutdown (probably signalled via KEY_POWER input event by the modem's kernel)
- Perhaps run adbd for easy upload/download of files to/from the modem's root filesystem
- Run a custom static build of busybox from
/foss
as a shell fromadbd
and on/dev/ttyUSB1
- Capture alsa controls' status during a call and create a function to replicate the setup
- Start experimenting with modem initialization and internal QMI messaging setup
- Setup AT commands forwarding and processing in userspace (over QMI), try creating our own AT command handlers (or abuse the Quectel ones, if they kept the whitelist in the modem's FW)
- Watch for voice call indication messages and configure alsa controls for the call, and start the audio stream (so that necessary audio paths in the codec are enabled by DAPM?)
- At this point it should be possible to make the calls
- Figure out how to solve some of the call indication quirks in the original firmware.
This should hopefully be enough to be able to perform voice calls without having to use any part of the original Quectel's code that is present on the root filesystem of their firmware.
I expect the FOSS code to shrink the firmware quite a bit. Most of the heavy
lifting is done by the Qualcomm/Quectel Linux kernel and their modem's DSP
code. Userspace code just has to perform some setup tasks by modifying a few
files in sysfs
and keeping track of a few special needs the
modem's DSP code may have, like configuring the codec during the call, and some
other minor stuff.
This can probaly be easily handled all by a single 200kB static binary instead of a huge 80MB busybox based system with 15 interacting daemons, hundreds of shell scripts and hard to capture behavior.
And there will be 80MiB of newly released space for some actually interesting additional code to be run on the modem, if you choose to delete the original proprieatry code. :)