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 from
adbd
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. :)