May 11, 2025
Getting Quectel RM520N-GL to work in Manjaro Linux
I’ve recently purchased a new Lenovo laptop with the built-in spy equipment (mobile broadband modem) for convenience. Alas, little have I…

By Elad Nachmias
6 min read
I've recently purchased a new Lenovo laptop with the built-in spy equipment (mobile broadband modem) for convenience. Alas, little have I known that getting this thing to work would require significant amount of work. Furthermore, the modem is marketed by Lenovo as having "Optional eSIM capabilities". It isn't clear what "Optional" means here, while the Quectel website (which unfortunately, if you're here and have probably learned, is utterly useless) mentions something equally as vague and obscure about the module.
The good news is that the modem does support eSIMs.
The bad news is that documentation is sparse, the firmware is unstable (with the stock firmware the modem is essentially unresponsive to AT commands at large and the updated one frequently resetting itself), and most of it comes down to a monkey emitting terminal commands hoping it will all work, and it isn't clear whether this is going to be viable for daily layperson usage.
My system runs Manjaro Sway, and I will try to walk you through what you need in order to get this to work (or in other words, how more or less I did).
Update the modem firmware
This is not optional. You must do this, and this must be done with fwupdmgr . For this, please first uninstall any ModemManager you may have installed in any way, and make sure the dependencies are removed too — libmbim and libqmi . Then, download fwupd version 1.9.x (the modem cannot be updated with the latest fwupd version for compatibility issues, you must downgrade otherwise this won't work) from the Arch Archive (click). Then install it (plus deps) with pacman -U <filename> .
Afterwards, use fwupdmgr refresh --force , make sure the modem appears when you fwupdmgr get-devices and finally, use the update command and update the relevant modules. Once this is done, reboot the system and try to use minicom -D /dev/wwan0at0 .
At this point you should be able to write AT and hit return, the modem should respond with OK . Sending ATI should respond with the new firmware version you've just installed.
Hurray! You're good for the next step.
Get lpac and modem-manager
Either download a release from their website, or from the AUR ( lpac-git). You'll need to also get pcsclite and ccid as dependencies via pacman . Then enable the relevant service and socket.
Keep handy the lpac USAGE and ENVVARS pages since the binary does not have any --help section. Also handy is to have the reference AT command document from Quectel. mmcli man pages too.
Also, install the modemmanager package. I've used the snapcraft version as it is newer but the normal Arch version might/should/would work too.
At this point you're almost ready. However, there's a small problem that needs to be rectified first. If you query your modem with mmcli and see that the first SIM card is activated, bad luck, and nothing beyond this point would work. I personally could not get around this without an AT command, and mmcli could not do the trick. The first SIM card slot is your physical SIM, and when you use lpac you must do so while the modem is using the second SIM slot (eSIM slot). I could not get mmcli to switch the slots, and lpac's documentation mentions that the UIM_SLOT is only used in MBIM or QMI modes, not AT (which we will be using).
Solution? Switch over to the second slot using AT command (make sure ModemManager service is stopped before issuing AT commands):
sudo minicom -D /dev/wwan0at0
AT+QUIMSLOT=?
# replies (1,2)
AT+QUIMSLOT?
# should reply 1
AT+QUIMSLOT=2
# switches over to slot 2
AT+QUIMSLOT?
# should now reply 2
<exit minicom now>sudo minicom -D /dev/wwan0at0
AT+QUIMSLOT=?
# replies (1,2)
AT+QUIMSLOT?
# should reply 1
AT+QUIMSLOT=2
# switches over to slot 2
AT+QUIMSLOT?
# should now reply 2
<exit minicom now>Start modemmanager again and query the modem, it should show that you're using the second slot.
And now some lpac sanity tests:
AT_DEBUG=1 LPAC_APDU=at AT_DEVICE=/dev/wwan0at0 lpac chip info
# should output a bunch of OKs and the chip dataAT_DEBUG=1 LPAC_APDU=at AT_DEVICE=/dev/wwan0at0 lpac chip info
# should output a bunch of OKs and the chip dataGet an eSIM and use lpac to activate it
Once you get your eSIM, you'll need the SM-DP+ server address and the activation code. If you have a QR code, this can be extracted from it too, as the data is usually encoded in the format of:
1$<smdp-addr>$activation-code
Once you have those, you can use lpac to download the profile to the modem:
AT_DEBUG=1 LPAC_APDU=at AT_DEVICE=/dev/wwan0at0 lpac profile download -s smdp-server-addr -m "ACTIVATION-CODE"AT_DEBUG=1 LPAC_APDU=at AT_DEVICE=/dev/wwan0at0 lpac profile download -s smdp-server-addr -m "ACTIVATION-CODE"lpac should finish with a message saying the download is complete and successful. You need an internet connection for this to work. If you broke it, you might have to delete the non-finalized profile. If you can't, you might need to switch to the real SIM card again so that you could disable and then delete the ICC profile using lpac. Then rinse and try again.
Verify that the profile was downloaded to the modem with lpac profile list and then enable it with lpac profile enable <ICCID> . You can also create a nickname for the profile so that you don't need to lookup the ICCID always: lpac profile nickname <ICCID> "nickname" .
At this point you may want to restart the modem, the computer, pray to your favorite deity and hang some garlic on your porch. As for restarting the modem, it is done by sending an AT+CFUN=1,1 . Fun!
Connect to the internet
Here, unfortunately is the most difficult part. Before you read on, memorize the following commands:
$ mmcli -m <modem> --enable
$ mmcli -m <modem> --reset
$ mmcli -m <modem> --disable
$ mbimcli --device-open-proxy --device="/dev/wwan0mbim0" --quectel-set-radio-state=on$ mmcli -m <modem> --enable
$ mmcli -m <modem> --reset
$ mmcli -m <modem> --disable
$ mbimcli --device-open-proxy --device="/dev/wwan0mbim0" --quectel-set-radio-state=onThis is really where the voodoo comes into play. The modem, at least for me, has been dropping out, reappearing, remanifesting and reincarnating as different modems with different numbers in mmcli . If you can't do anything with mmcli this means the modem is FCC locked. In turn you will need to execute the mbimcli command with the set-radio flag which unlocks the modem and allows it to become responsive to commands (this is what the FCC unlock script from modemmanger does). You should then — enable the modem through mmcli . If you see "transition invalid" errors from mmcli when you try to enable the modem (if it is in the "disabled" status) then you must issue the mbim command to reenable it again. Sometimes it would completely go into some bizarre erroneous state and then the AT+CFUN=1,1 command becomes handy again. If you hit rock bottom, try to hibernate or restart the machine altogether.
As for connecting to the internet, there are a few components to this:
Registering with a carrier
Here, you may want to scan for the different networks and select the appropriate one:
$ mmcli -m <modem> --3gpp-scan
# will output a bunch of carriers
$ mmcli -m <modem> --3gpp-register-in-operator=<five digit operator code=MCC+MNC code>
# this may time out or die$ mmcli -m <modem> --3gpp-scan
# will output a bunch of carriers
$ mmcli -m <modem> --3gpp-register-in-operator=<five digit operator code=MCC+MNC code>
# this may time out or dieMy impression was that the modem may attempt to register with a carrier automatically, but this carrier may not be able to provide you service (i.e. your SIM can't roam or this is not your operator in your home country). Therefore, you may need to register in your own operator or an operator you know will provide you service as part of roaming. You can also use the mmcli -m <modem> --3gpp-register-home command to register with your local carrier.
Executing the register commands may die, time-out, yield MBIM protocol errors, among others. You may need to reset the modem occasionally.
Once you finally query the modem state with mmcli -m <modem> you should see that the modem is in the enabled state and the 3GPP carrier is the one you want to be connected to.
Connecting
At least in theory, this should be rather simple: mmcli -m <modem> --simple-connect="apn=your_apn_here_no_quotes_are_needed" . You should be connected now. You should see your Bearer status by querying the relevant packet data bearer settings with mmcli -m <modem> -b <bearer index> . If you are connected, you should see IP address settings showing up with the packet bearer info. If you aren't — fiddle around, rinse, try to figure out what went wrong and repeat. You might be on the wrong carrier, the modem might be disabled, etc.
If you are connected the "state: connected" should show up when querying the modem with mmcli -m <modem> . If you're not, it won't show as connected (just stating the obvious).
Making sure the settings propagate to the network adapter
Congratulations! If you've made it so far, you should be connected!
The bad news is that mmcli manages modems, but not network adapters. Therefore, you have to propagate the settings to the proper network adapter, in my case wwan0 . To do this, I note down which bearer index has the IP settings, then feed the number as an argument to the following script (which assumes you're getting a static IPv4 setting from your carrier):
#!/bin/bash
set -e
IFACE="wwan0"
# Get the first available modem index
MODEM=$(mmcli -L | grep -o '/org/freedesktop/ModemManager1/Modem/[0-9]\+' | tail -n1 | awk -F'/' '{print $NF}')
if [ -z "$MODEM" ]; then
echo "No modem found."
exit 1
fi
echo "Using modem index: $MODEM"
echo "Using bearer: $1"
BEARER=$1
# Fetch bearer IP config
INFO=$(mmcli -b "$BEARER" --output-keyvalue)
IP=$(echo "$INFO" | grep "bearer.ipv4-config.address" | cut -d ":" -f2)
PREFIX=$(echo "$INFO" | grep "bearer.ipv4-config.prefix" | cut -d ":" -f2)
GATEWAY=$(echo "$INFO" | grep 'bearer.ipv4-config.gateway' | cut -d ":" -f2)
# Sanity check
if [ -z "$IP" ] || [ -z "$GATEWAY" ]; then
echo "Missing IP or gateway info."
exit 1
fi
# Apply network config
ip link set "$IFACE" up
ip addr flush dev "$IFACE"
ip addr add "${IP}/${PREFIX}" dev "$IFACE"
ip route add default via "$GATEWAY" dev "$IFACE"
echo "Network configuration applied to $IFACE"#!/bin/bash
set -e
IFACE="wwan0"
# Get the first available modem index
MODEM=$(mmcli -L | grep -o '/org/freedesktop/ModemManager1/Modem/[0-9]\+' | tail -n1 | awk -F'/' '{print $NF}')
if [ -z "$MODEM" ]; then
echo "No modem found."
exit 1
fi
echo "Using modem index: $MODEM"
echo "Using bearer: $1"
BEARER=$1
# Fetch bearer IP config
INFO=$(mmcli -b "$BEARER" --output-keyvalue)
IP=$(echo "$INFO" | grep "bearer.ipv4-config.address" | cut -d ":" -f2)
PREFIX=$(echo "$INFO" | grep "bearer.ipv4-config.prefix" | cut -d ":" -f2)
GATEWAY=$(echo "$INFO" | grep 'bearer.ipv4-config.gateway' | cut -d ":" -f2)
# Sanity check
if [ -z "$IP" ] || [ -z "$GATEWAY" ]; then
echo "Missing IP or gateway info."
exit 1
fi
# Apply network config
ip link set "$IFACE" up
ip addr flush dev "$IFACE"
ip addr add "${IP}/${PREFIX}" dev "$IFACE"
ip route add default via "$GATEWAY" dev "$IFACE"
echo "Network configuration applied to $IFACE"If your carrier supports DHCP, you should be able to just run dhclient on the interface, however I haven't tested this out yet.
This can be improved by using nmcli , just create a profile for your provider like nmcli connection add type gsm ifname "*" con-name my-con-name apn <apn> . Then you can just nmcli connection up my-con-name .
Enjoy!
References:
- https://github.com/estkme-group/lpac
- https://www.freedesktop.org/software/ModemManager/man/1.24.0/mmcli.1.html
- https://wiki.soprani.ca/eSIM%20Adapter/lpac
- https://andreas-mausch.de/blog/2025-03-23-esim/
- https://github.com/estkme-group/lpac/issues/182
- https://techship.com/blog/how-to-use-an-esim-in-linux-7/
- https://www.waveshare.com/wiki/RM520N-GL_5G_HAT#5G_Network_Card_Dial-up_Method
- https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/954
- https://forums.quectel.com/t/esim-with-quectel-rm520n-gl-in-linux-lpac-modemmanager/44479
- https://wiki.archlinux.org/title/Lenovo_ThinkPad_X1_Carbon_(Gen_12)