Introduction
I been researching the radio interface layer (RIL) in Android devices during my leisure time, focusing on Qualcomm Mobile Station Modem (MSM) system-on-chip (SoC) devices.
For my research I used my second phone, a ZTE Axon 7 Qualcomm MSM8996 Snapdragon 820 running Lineage OS 14.1 that I build, sign and distribute.
The research was initiated because I wanted to understand what services the modem provides and what assets it own and are accessible.
Later to further understand the communication between the application processor (AP) high level operating system (HLOS) and baseband processor (BP) in Android Nougat.
The target of the research was to understand:
- the overall architecture of Android RIL linked to the test device source code,
- what services the BP provide, incl. hidden services,
- what assets are owned by the BP,
- the separation mechanism between AP and BP.
Table of content
Architecture
The reconnaissance of the topic appeared to be as challenging as expected.
Finding information, source code or architecture descriptions of the closed kingdom of Qualcomm was hard… very hard.
Therefore I do apologise if I say something that is incorrect. However, here are a couple recommended OSINT useful sources explaining the AP OS part of the RIL communication.
Other recommended resources are: (do buy them, they are excellent)
- Android Internals:: A Confectioner's Cookbook Vol.1
- Android Hacker's Handbook
- Android Security Internals: An In-Depth Guide to Android's Security Architecture
In short: RIL requests are can either be
- solicited, i.e. triggered by the AP
- synchronous, e.g. RIL_REQUEST_GET_SIM_STATUS.
- asynchronous, e.g. RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, defined in ril_commands.h.
- unsolicited, i.e. triggered by the BP
- acknowledged,
- unackowledged, defined in ril_unsol_commands.h.
The radio interface layer daemon rild acts on standard generic AT Hayes commands from the telephony services (RILJ), through the socket /dev/socket/rild and dispatch solicited requests to the BP. A debugging socket is accessible through the socket /dev/socket/rild-debug using the radiooptions command, or sending direct commands to the socket.
$ echo -ne "\x01\x00\x00\x00\x02\x00\x00\x00\x30\x31" | ./socat - UNIX:/dev/socket/rild-debug
where DWORD \x01\x00\x00\x00 indicates 1 parameter, \x02\x00\x00\x00 defines the length of arg0 and \x30\x31 is the parameter.
The daemon process dynamically loads the closed-sourced shared library that act as a driver between the HLOS and the modem device. This is referred as the vendor RIL. In case of unsolicited requests from the BP, the vendor RIL translate the close sourced proprietary Qualcomm MSM Interface (QMI) protocol to AT commands. The QMI protocol is a type-length-value (TLV) messaging format used to communicate between software components in the modem and other peripheral subsystems.
+------- QMI Service Message -------+
+------------+------+------+------+---------------------+
|Control Flag|TXN ID|MSG ID|Length| QMI Message |
+------------+------+------+------+--+--+--+---+--+--+--+
|T1|L1|V1|...|Tn|Ln|Vn|
+--+--+--+---+--+--+--+
Figure 1: Displays the QMI message format.
- Control flag (1 byte):
- QMI_REQUEST_CONTROL_FLAG 0x00
- QMI_RESPONSE_CONTROL_FLAG 0x02
- QMI_INDICATION_CONTROL_FLAG 0x04
- Transaction (TXN) ID corresponding to the message (2 bytes):
- Message (MSG) ID for the particular message (2 bytes).
- Length (n) of QMI Message (2 bytes).
- QMI Message (n bytes):
- TLV 1 is mandatory, 2…n is optional.
NOTE: TLV structure designs, especially recursive ones, are notoriously common sources of vulnerabilities. The goal of this study is not to hunt for bugs, and if I find any, I will not disclose them here, but it is a fact that such complex design will contain bugs.
QMI is the general term for all related messaging between processors and their software stacks on Qualcomm DSPs. QMI communication is based on a client-server model, where clients and servers exchange messages in QMI wire format. A module can act as a client of any number of QMI services and a QMI service can serve any number of clients. In the context of multi-processor Qualcomm chipsets, such as the MDM9615/9x07 used in cellular modems / data cards, or also in the case of Android smartphones, QMI ports are exposed to the Linux-running application CPU core inside the chip. There can be many different transport mechanisms, but in the case of modern integrated chips, it is primarily Shared Memory Device (SMD).
Figure 2: The Android Nougat RIL architecture.
In my device the BP and AP communicates using a SMD. A SMD channel is basically a pipe abstraction over Qualcomm's Shared Memory system. The Shared Memory (SMEM) system allows multiple processors to communicate at a low level using a segment of shared system memory that is accessible by any of the processors.
The SMEM system is an allocate-only heap structure, administered by AP, that consists of one of more memory areas that can be accessed by the processors in the SoC.
A SMEM client that wishes to allocate a SMEM item will provide the item identifier and a desired size in bytes. Assuming there is enough free space in the SMEM region to accommodate the request, the amount of desired bytes will be carved out, and the base address and size for the item will be stored in the
table of contents. The base address will be returned as a pointer to the
client, so that the client may use the SMEM item as if it were normal memory
allocated through malloc.
The main SMEM memory region is statically mapped at boot by the primary bootloader (PBL), referred as the Resource Power Manager (RPM), and the virtual address for the base of the region is stored in smem_ram_base. In my device the modem SMEM region is allocated at physical address 0x86000000 with 2MB size (qcom,smem@86000000).
smem_ram_base = ioremap_nocache(smem_ram_phys, smem_ram_size);
...
/* Initialize main SMEM region and SSR ramdump region */
smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area), GFP_KERNEL);
...
ramdump_segments_tmp = kcalloc(num_smem_areas, sizeof(struct ramdump_segment), GFP_KERNEL);
...
smem_areas_tmp[smem_idx].phys_addr = smem_ram_phys;
smem_areas_tmp[smem_idx].size = smem_ram_size;
smem_areas_tmp[smem_idx].virt_addr = smem_ram_base;
ramdump_segments_tmp[smem_idx].address = smem_ram_phys;
ramdump_segments_tmp[smem_idx].size = smem_ram_size;
...
/* Configure auxiliary SMEM regions */
while (1) {
scnprintf(temp_string, temp_string_size, "aux-mem%d", smem_idx);
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, temp_string);
if (!r)
break;
aux_mem_base = r->start;
aux_mem_size = resource_size(r);
ramdump_segments_tmp[smem_idx].address = aux_mem_base;
ramdump_segments_tmp[smem_idx].size = aux_mem_size;
smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
smem_areas_tmp[smem_idx].size = aux_mem_size;
smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(smem_areas_tmp[smem_idx].phys_addr, smem_areas_tmp[smem_idx].size);
...
}
smem_areas = smem_areas_tmp;
smem_ramdump_segments = ramdump_segments_tmp;
key = "qcom,mpu-enabled";
security_enabled = of_property_read_bool(pdev->dev.of_node, key);
if (security_enabled) {
SMEM_INFO("smem security enabled\n");
smem_init_security();
}
...
Listing 1: drivers/soc/qcom/smd.c:msm_smem_probe().
The optional device tree configuration qcom,mpu-enabled enables Memory Protection Unit (MPU) based security on the “smem” shared memory region. It is enabled in the test device. Each channels between the processors, SMD subsystems, are listed in the debugfs trace below.
| Identifier |
Description |
| APPS |
Android (Applications Processor) |
| MDMSW |
Modem firmware |
| ADSP |
Video, audio, machine learning DSP |
| TZ |
TrustZone |
| RPM |
Resource Power Manager |
| |
|
The SMD channels on my device are:
cat /sys/kernel/debug/smd/ch
Primary allocation table:
ID|CHANNEL NAME |T|PROC |STATE |FIFO SZ|RDPTR |WRPTR |FLAGS |DATAPEN
-------------------------------------------------------------------------------
1|GLINK_CTRL |P|APPS |OPENED |0x00400|0x00020|0x00020|DCCiwrsb|0x00000
| | |ADSP |OPENED |0x00400|0x00029|0x00029|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
2|GLINK_CTRL |P|ADSP | Access Restricted
| | |RPM | Access Restricted
-------------------------------------------------------------------------------
3|IPCRTR |P|APPS |OPENED |0x02000|0x00E04|0x00E04|DCCiwRsB|0x00000
| | |ADSP |OPENED |0x02000|0x019AC|0x019AC|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
4|fastrpcsmd-apps-dsp|P|APPS |OPENED |0x02000|0x011D0|0x011D0|DCCiwrsb|0x00000
| | |ADSP |OPENED |0x02000|0x00A8C|0x00A8C|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
5|LOOPBACK |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |ADSP |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
6|apr_audio_svc |P|APPS |OPENED |0x02000|0x0041C|0x0041C|DCCiwrsB|0x00000
| | |ADSP |OPENED |0x02000|0x0043C|0x0043C|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
7|apr_apps2 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |ADSP |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
8|GLINK_CTRL |P|APPS |OPENED |0x00400|0x00020|0x00020|DCCiwrsb|0x00000
| | |TZ |OPENED |0x00400|0x00029|0x00029|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
9|GLINK_CTRL |P|
| | |
-------------------------------------------------------------------------------
10|IPCRTR |P|APPS |OPENED |0x02000|0x00950|0x00950|DCCiwRsB|0x00000
| | |TZ |OPENED |0x02000|0x01128|0x01128|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
11|LOOPBACK |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |TZ |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
12|fastrpcsmd-apps-dsp|P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |TZ |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
13|GLINK_CTRL |P|MDMSW| Access Restricted
| | |RPM | Access Restricted
-------------------------------------------------------------------------------
APPS <-> MDMSW Primary allocation table:
ID|CHANNEL NAME |T|PROC |STATE |FIFO SZ|RDPTR |WRPTR |FLAGS |DATAPEN
-------------------------------------------------------------------------------
0|DS |S|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
1|GLINK_CTRL |P|APPS |OPENED |0x00400|0x00100|0x00100|DCCiwrsb|0x00000
| | |MDMSW|OPENED |0x00400|0x0013E|0x0013E|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
2|IPCRTR |P|APPS |OPENED |0x02000|0x000E8|0x000E8|DCCiwRsB|0x00000
| | |MDMSW|OPENED |0x02000|0x00D58|0x00D58|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
3|LOOPBACK |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
4|SSM_RTR_MODEM_APPS |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
5|sys_mon |P|APPS |CLOSED |0x00400|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x00400|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
6|apr_voice_svc |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
7|DATA1 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
8|DATA2 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
9|DATA3 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
10|DATA4 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
11|DATA11 |S|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |MDMSW|OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
APPS <-> ADSP Primary allocation table:
ID|CHANNEL NAME |T|PROC |STATE |FIFO SZ|RDPTR |WRPTR |FLAGS |DATAPEN
-------------------------------------------------------------------------------
1|GLINK_CTRL |P|APPS |OPENED |0x00400|0x00020|0x00020|DCCiwrsb|0x00000
| | |ADSP |OPENED |0x00400|0x00029|0x00029|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
2|IPCRTR |P|APPS |OPENED |0x02000|0x00E04|0x00E04|DCCiwRsB|0x00000
| | |ADSP |OPENED |0x02000|0x019AC|0x019AC|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
3|fastrpcsmd-apps-dsp|P|APPS |OPENED |0x02000|0x011D0|0x011D0|DCCiwrsb|0x00000
| | |ADSP |OPENED |0x02000|0x00A8C|0x00A8C|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
4|LOOPBACK |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |ADSP |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
5|apr_audio_svc |P|APPS |OPENED |0x02000|0x0041C|0x0041C|DCCiwrsB|0x00000
| | |ADSP |OPENED |0x02000|0x0043C|0x0043C|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
6|apr_apps2 |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |ADSP |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
APPS <-> TZ Primary allocation table:
ID|CHANNEL NAME |T|PROC |STATE |FIFO SZ|RDPTR |WRPTR |FLAGS |DATAPEN
-------------------------------------------------------------------------------
1|GLINK_CTRL |P|APPS |OPENED |0x00400|0x00020|0x00020|DCCiwrsb|0x00000
| | |TZ |OPENED |0x00400|0x00029|0x00029|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
2|IPCRTR |P|APPS |OPENED |0x02000|0x00950|0x00950|DCCiwRsB|0x00000
| | |TZ |OPENED |0x02000|0x01128|0x01128|DCCiwrsB|0x00000
-------------------------------------------------------------------------------
3|LOOPBACK |P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |TZ |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
4|fastrpcsmd-apps-dsp|P|APPS |CLOSED |0x02000|0x00000|0x00000|dcciwrsb|0x00000
| | |TZ |OPENING|0x02000|0x00000|0x00000|DCCiwrSb|0x00000
-------------------------------------------------------------------------------
Interesting channels are:
- fastrpcsmd-apps-dsp
- apr_audio_svc
- apr_apps2
- sys_mon
- apr_voice_svc
Qualcomm Hexagon
Qualcomm Hexagon, QDSP6, is the brand name for a family of digital signal processor (DSP) products from Qualcomm.
The Hexagon architecture is designed to deliver performance with low power over a variety of applications.
It has features such as hardware assisted multithreading, privilege levels, Very Long Instruction Word (VLIW), Single Instruction Multiple Data (SIMD), and instructions geared toward efficient signal processing.
The CPU is capable of in-order dispatching up to 4 instructions (the packet) to 4 Execution Units every clock.
Hexagon DSPs runs Qualcomm’s operating system Qualcomm Real Time OS (QuRT), that handles scheduling, resource management, address translation, etc.
The Hexagon firmware images are found under /firmware/images.
find /firmware/image -type f -exec sh -c 'file $0 | grep -E ELF.*hexagon' {} \;
/firmware/image/adsp.b00: ELF executable, 32-bit LSB hexagon, static, stripped
/firmware/image/adsp.mdt: ELF executable, 32-bit LSB hexagon, static, stripped
/firmware/image/modem.b00: ELF executable, 32-bit LSB hexagon, dynamic (), stripped
/firmware/image/modem.mdt: ELF executable, 32-bit LSB hexagon, dynamic (), stripped
/firmware/image/slpi.b00: ELF executable, 32-bit LSB hexagon, static, stripped
/firmware/image/slpi.mdt: ELF executable, 32-bit LSB hexagon, static, stripped
/firmware/image/mba.mbn: ELF executable, 32-bit LSB hexagon, static, stripped
The AP loads the peripheral modem firmware image is always loaded from physical address 0x88800000 (modem_region@88800000) to 0x8ea00000 (peripheral_region@8ea00000). The device tree configuration removed-dma-pool indicates a region of memory which is meant to be carved out and not exposed to kernel.
dmesg | grep pil-q6v5-mss
[01-01 02:00:00.826] [3][1: swapper/0]pil-q6v5-mss 2080000.qcom,mss: Failed to find the pas_id.
[01-01 02:00:02.606] [0][256: deferred_probe_]pil-q6v5-mss 2080000.qcom,mss: Failed to find the pas_id.
[01-01 02:00:02.606] [0][256: deferred_probe_]pil-q6v5-mss 2080000.qcom,mss: for modem segments only will be dumped.
[01-02 08:00:49.280] [1][558: Binder:519_1]pil-q6v5-mss 2080000.qcom,mss: modem: loading from 0x0000000088800000 to 0x000000008ea00000
[01-02 08:00:49.290] [1][558: Binder:519_1]pil-q6v5-mss 2080000.qcom,mss: Debug policy not present - msadp. Continue.
[01-02 08:00:49.290] [1][558: Binder:519_1]pil-q6v5-mss 2080000.qcom,mss: Loading MBA and DP (if present) from 0x00000000f6e00000 to 0x00000000f6f00000 size 100000
[01-02 08:00:49.440] [2][558: Binder:519_1]pil-q6v5-mss 2080000.qcom,mss: MBA boot done
[01-02 08:00:50.383] [3][558: Binder:519_1]pil-q6v5-mss 2080000.qcom,mss: modem: Brought out of reset
[01-02 08:00:50.463] [2][338: irq/640-modem]pil-q6v5-mss 2080000.qcom,mss: modem: Power/Clock ready interrupt received
[01-02 08:00:50.463] [0][655: e2fsck]pil-q6v5-mss 2080000.qcom,mss: Subsystem error monitoring/handling services are up
Modem firmwares are represented in the .mdt/.bXX format or mbn, and loaded by the kernel using the Qualcomm MSS QDSP6v5 Peripheral Image Loader (PIL) driver pil-qdsp6v5-mss.
It is used for loading QDSP6v5 (Hexagon) firmware images for modem subsystems into memory and preparing the subsystem's processor to execute code.
It requires the Modem Boot Authenticator (MBA) to be loaded (mba.mbn) before, see pil_mss_loadable_init():263, depending if the hardware requires self-authenticating images, see device tree configuration pil-self-auth.
I combined the modem.mdt and .bXX files using unify_trustlet to a ELF.
Running checksec on it indicates it does not have any security mechanisms.
pwn checksec --file modem.elf
Arch: 164-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0xc0000000)
RWX: Has RWX segments
I started reversing the modem firmware in radare2 and IDA with the hexagon module. To assist my study, I used an old modem source code.
However I wasn't available to debug the modem for now.
I will look into that in the future.
QMI services
The modem defines 46 QMI services.
NOTE: Remember that the list differ in more recent releases.
grep -rhoEI "struct qmi_idl_service_object ([a-zA-Z0-9_]+)" modem | sort | uniq
SNS_SAM_AMD_SVC_qmi_idl_service_object_v01 (? sensor)
SNS_SAM_PED_SVC_qmi_idl_service_object_v01 (pedometer sensor)
SNS_SAM_RMD_SVC_qmi_idl_service_object_v01 (? sensor)
SNS_SAM_SMD_SVC_qmi_idl_service_object_v01 (motion sensor)
SNS_SMGR_SVC_qmi_idl_service_object_v01 (sensor manager)
SNS_TIME2_SVC_qmi_idl_service_object_v02 (sensor time api)
atp_qmi_idl_service_object_v01 (application traffic pairing)
auth_qmi_idl_service_object_v01 (authentication) ***
cat_qmi_idl_service_object_v02 (card application toolkit)
coex_qmi_idl_service_object_v01 (coexistence v1)
coex_qmi_idl_service_object_v02 (coexistence v2)
csvt_qmi_idl_service_object_v01 (circuit switched video telephony) ***
ctl_qmi_idl_service_object_v01 (control) ***
dfs_qmi_idl_service_object_v01 (data filter)
dhms_qmi_idl_service_object_v01 (dynamic heap memory sharing) ***
dms_qmi_idl_service_object_v01 (device management)
dsd_qmi_idl_service_object_v01 (data system determination)
fds_qmi_idl_service_object_v01 (flash driver)
imsa_qmi_idl_service_object_v01 (ip multimedia subsystem application)
imss_qmi_idl_service_object_v01 (ip multimedia subsystem settings)
loc_qmi_idl_service_object_v02 (location) ***
mfs_qmi_idl_service_object_v01 (modem filesystem) ***
nas_qmi_idl_service_object_v01 (network access)
otdt_qmi_idl_service_object_v01 (on target data tests)
pbm_qmi_idl_service_object_v01 (phonebook manager)
pdc_qmi_idl_service_object_v01 (persistent device configuration)
qchat_qmi_idl_service_object_v01 (qualcomm chat)
qcmap_qmi_idl_service_object_v01 (qualcomm mobile access point)
qdssc_qmi_idl_service_object_v01 (qualcomm debug subsystem control [-DEBUG-]) ***
rfrpe_qmi_idl_service_object_v01 (radio frequency radiated performance enhancement)
rfsa_qmi_idl_service_object_v01 (remote filesystem access)
rmtfs_qmi_idl_service_object_v01 (remote storage)
sap_qmi_idl_service_object_v01 (access proxy)
sar_qmi_idl_service_object_v01 (specific absorption rate)
slimbus_qmi_idl_service_object_v01 (slimbus)
ssctl_qmi_idl_service_object_v01 (subsystem control v1 [-DEBUG-]) ***
ssctl_qmi_idl_service_object_v02 (subsystem control v2 [-DEBUG-]) ***
ssreq_qmi_idl_service_object_v01 (subsystem request)
test_qmi_idl_service_object_v01 (test [-DEBUG-]) ***
time_qmi_idl_service_object_v01 (time)
tmd_qmi_idl_service_object_v01 (thermal mitigation device)
ts_qmi_idl_service_object_v01 (thermal sensor)
uim_qmi_idl_service_object_v01 (user identify module)
uim_remote_qmi_idl_service_object_v01 (user identity module remote) ***
voice_qmi_idl_service_object_v02 (voice) ***
wda_qmi_idl_service_object_v01 (wireless data administrative)
wds_qmi_idl_service_object_v01 (wireless data)
wms_qmi_idl_service_object_v01 (wireless messaging)
***: part of this study
I found it extra interesting which services exist in the modem but isn’t included in the vendor RIL. Those are either internal or shall not be exposed to the AP.
REGEX="struct qmi_idl_service_object ([a-zA-Z0-9_]+)"; \
diff -ru \
<(find linux \( -name "*.c" -or -name "*.h" \) -and -exec grep -rhoEI "$REGEX" {} \; | sort | uniq) \
<(find modem \( -name "*.c" -or -name "*.h" \) -and -exec grep -rhoEI "$REGEX" {} \; | sort | uniq) \
| tail -n +4 | sed -nE "s/\+$REGEX/\1/p"
auth_qmi_idl_service_object_v01 (authentication)
coex_qmi_idl_service_object_v01 (coexistence v1)
coex_qmi_idl_service_object_v01 (coexistence v2)
dhms_qmi_idl_service_object_v01 (dynamic heap memory sharing)
fds_qmi_idl_service_object_v01 (flash driver)
loc_qmi_idl_service_object_v02 (location)
mfs_qmi_idl_service_object_v01 (modem filesystem)
qchat_qmi_idl_service_object_v01 (qualcomm chat)
qdssc_qmi_idl_service_object_v01 (qualcomm debug subsystem control [-DEBUG-])
slimbus_qmi_idl_service_object_v01 (slimbus)
ssctl_qmi_idl_service_object_v02 (subsystem control v2 [-DEBUG-])
ssreq_qmi_idl_service_object_v01 (subsystem request)
Therefore I began investigating them, except SLIMbus and Qualcomm chat.
Authentication service
The authentication service auth_qmi_idl_service_object_v01 (0x07) handles the device authentication against the network. Authentication is implemented using the Extensible Authentication Protocol (EAP) authentication framework defined in RFC 3748 and updated in RFC 5247.
The service interface supports following requests:
- Start the EAP session.
- Send and receive EAP packets.
- Run the AKA algorithm.
- Associate the requesting control point with the requested subscription.
- Set the registration state of the QMI_AUTH indication for the requesting control point.
Following EAP methods are supported:
- EAP Subscriber Identity Module (EAP-SIM): Is used for authentication and session key distribution using the subscriber identity module (SIM) from the Global System for Mobile Communications (GSM). EAP-SIM is defined in RFC 4186.
- EAP Authentication and Key Agreement (EAP-AKA): Is an EAP mechanism for authentication and session key distribution using the UMTS Subscriber Identity Module (USIM). EAP-AKA is defined in RFC 4187.
- EAP Authentication and Key Agreement prime (EAP-AKA’): Is a variant of EAP-AKA. It is used for non-3GPP access to a 3GPP core network. For example, via EVDO, Wi-Fi, or WiMax. EAP-AKA’ is defined in RFC 5448.
With following EAP APA algorithms:
- EAP AKA NONE (all EAP methods are supported) (?)
- EAP AKA SHA-1
- EAP AKA MILENAGE
- EAP AKA CAVE
- EAP SIM GSM
- EAP SIM USIM GSM
Coexistence service
The coexistence service coex_qmi_idl_service_object_v0[1,2] (0x22) implements the WWAN network configurations depending on type: LTE, TD-SCDMA, GSM, CDMA2000, HDR or WCDMA. This includes resource and rate limits, what operating band frequencies to use for uplink, downlink and what dimensions the ranges refers to: FDD, TDD, or both.
This module also support WLAN scanning and establishment for close range communications, I assume e.g. for picocell support.
Dynamic heap memory sharing service
The dynamic heap memory sharing service dhms_qmi_idl_service_object_v01 (0x34) implements the modem’s memory management.
The service includes:
- Allocate
uint32_t number of bytes physically continous memory block from the server memory subsystem with specified alignment.
- Free physically continous memory block on the HLOS that was previously allocated.
NOTE: If the requested amount of memory is not available, a smaller memory block can be returned.
Flash driver service
The flash driver service fds_qmi_idl_service_object_v01 (0x2D) provides interface to the flash system.
The service includes:
- Invoke a flash scrub operation.
- Retrieve the status of a previously issued scrub request.
- Perform a Firmware Over the AIR (FOTA) update.
- Indicate when to start applications processor side scrubbing, including scrubbing all partitions the applications processor requires and maintains.
Location service
The location service loc_qmi_idl_service_object_v02 (0x10) provides the interface to the device’s location engine. It is one of the larger QMI services in the modem. It is possible to write a complete post about the location service, therefore I only will provide a summary.
The location engine uses a long list of sources to keep track of a device’s position:
- Global Navigation Satellite Systems (GNSS) position and satellite report event indications from:
- Global Positioning System (GPS)
- Globalnaya Navigatsionnaya Sputnikovaya Sistema (GLONASS)
- Satellite-based Augmentation System (SBAS)
- BeiDou Navigation Satellite System (BDS)
- GALILEO
- COMPASS
- National Marine Electronics Association (NMEA), supporting following types:
- Global Positioning System Fix Data (GNGGA)
- Recommended Minimum Specific GPS/TRANSIT Data (RMC)
- Satellites in View (GSV)
- DOP and Active Satellites (GSA)
- Track Made Good and Ground Speed (VTG)
- PQXFI (?)
- PSTIS (?)
- WWAN positioning data.
- Wi-Fi positioning data.
- Device sensor data, e.g. accelerometer and gyroscope sensors.
- On-vehicle sensor data, e.g. vehicle accelerometer, vehicle angular rate, vehicle odometry, etc.
The location engine allows following functions:
- Connect to location server. I am not sure if this is part of the GNSS or part of the WWAN.
- Detect time injection request event indications to synchronise time.
- …
Geofencing functionality
The location engine allows for geofencing, either network-initiated or initiated by the device. The geofence functionality can detect geofence breaches and inform if changes are made that affect a geofence, e.g., if GPS is turned off or if the network is unavailable.
I can only assume this is reported to the location service.
Circuit switched video telephony service
The circuit switched video telephony service csvt_qmi_idl_service_object_v01 (0x1D) provides the functionality to orginate, confirm, answer, end and modify calls. It also provides subscription binding, call statistics, etc.
An call modification can either initiated by the UE or the network.
A call can either be asynchronous, synchronous or video telephony, and transparent or non-transparent. This is provided by the RLP frame header.
Control service
The control service ctl_qmi_idl_service_object_v01 (0x00) handles QMI client ID management and versioning for other QMI services.
The QMI command range is divided into:
| Range |
Description |
| 0x0000-0x5555 |
QC EXTERNAL QMI COMMAND RANGE |
| 0x5556-0xAAAA |
VENDOR SPECIFIC QMI COMMAND RANGE |
| 0xAAAB-0xFFFE |
RESERVED QC QMI COMMAND RANGE |
| |
|
When looking into QMI implementations, the range 0x5556-0xAAAA is interesting.
Modem filesystem service
The modem filesystem service mfs_qmi_idl_service_object_v01 (0x15) provides loading and storing files in the modem filesystem. The modem uses the second generation of Qualcomm’s proprietary Embedded File System (EFS2), that can be used on flash, NAND, RAM or remote MMC devices.
# EFS2 file system - jojo@utulsa.edu
0 lelong 0x53000000 EFS2 Qualcomm filesystem super block, little endian,
>8 string !EFSSuper {invalid},
>4 leshort&0x01 1 NAND
>4 leshort&0x01 0 NOR
>4 leshort x version 0x%x,
>24 lelong x %d blocks,
>16 lelong x 0x%x pages per block,
>20 lelong x 0x%x bytes per page
0 belong 0x53000000 EFS2 Qualcomm filesystem super block, big endian,
>8 string !SSFErepu {invalid},
>4 beshort&0x01 1 NAND
>4 beshort&0x01 0 NOR
>4 beshort x version 0x%x,
>24 belong x %d blocks,
>16 belong x 0x%x pages per block,
>20 belong x 0x%x bytes per page
Listing 2: binwalk's EFS2 filesystem header.
The modem filesystem service exposes two request commands:
- QMI_MFS_PUT_REQ_V01 (0x0020).
- QMI_MFS_GET_REQ_V01 (0x0021).
When performing a PUT or GET request the requested file path is verified against an access check list.
static struct fs_qmi_service_access_check_entry
fs_qmi_service_access_check_list [] =
{
/* USB files */
{0, "/nv/item_files/hsusb/"},
{0, "/nv/item_files/conf/hsusb0.conf"},
{0, "/nv/item_files/conf/hsusb1.conf"},
{0, "/nv/item_files/conf/hsusb2.conf"},
{0, "/nv/item_files/conf/hsusb3.conf"},
{0, "/nv/item_files/conf/hsusb4.conf"},
{0, "/nv/item_files/conf/hsusb5.conf"},
{0, "/nv/item_files/conf/hsusb6.conf"},
{0, "/nv/item_files/conf/hsusb7.conf"},
{0, "/nv/item_files/conf/hsusb8.conf"},
{0, "/nv/item_files/conf/hsusb9.conf"},
{0, "/nv/item_files/conf/hsusb10.conf"},
/* Timer files */
{0, "/nvm/alpha/item_file/time/"},
/* RDM files */
{0, "/rdm_config.csv"},
/* Debugtools err files */
{0, "/nv/item_files/dnt/"},
{0, "/nv/item_files/f3_trace/"},
{0, "/nv/item_files/conf/dnt_err0.conf"},
{0, "/nv/item_files/conf/dnt_err1.conf"},
{0, "/nv/item_files/conf/dnt_err2.conf"},
{0, "/nv/item_files/conf/f3_trace0.conf"},
{0, "/nv/item_files/conf/f3_trace1.conf"},
{0, "/nv/item_files/conf/f3_trace2.conf"},
/* Power files */
{0, "/nv/item_files/apps_dcvs/"},
/* Sleep files */
{0, "/nv/item_files/sleep/"},
/* QBI files */
{0, "/nv/item_files/qbi/"},
/* Thermal-Engine config file */
{0, "/nv/item_files/thermal-engine/thermal-engine.conf"},
/* Sound-driver config file */
{0, "/nv/item_files/csd/csd.conf"}
};
It appears to be possible to write any file in a folder validating against the check list.
Debug subsystem control service
The qualcomm debug subsystem control service qdssc_qmi_idl_service_object_v01 (0x33) is not included in the vendor RIL library.
It provides the ability to:
- Get the state of SW tracing on the processor.
- Enable or disable all SW instrumented tracing on the processor.
- Get the state of SW tracing from an entity on the processor.
- Enable or disable SW trace from an entity on the processor.
- Enable or disable SW trace from all entities on the processor.
- Get the state of SW tracing for a SW event on the processor.
- Enable or disable tracing of a SW event on the processor.
- Configure SW events on the RPM processor.
- Configure device for a HW event.
- Enable or disable ETM’s trace on the processor.
- Enable or disable ETM’s trace on the RPM processor.
It appears that it might be possible to use this service for debugging the modem and the RPM processor.
I will look further into how to use this service for debugging purposes.
Subsystem control/request services
The subsystem control service ssctl_qmi_idl_service_object_v0[1,2] (0x2B) and ssreq_qmi_idl_service_object_v01 (0x35) provides the functionality to restart or shutdown a subsystem, and it can subscribe to subsystem events, e.g. shutdown or powerup.
It is not obvious why version 2 exist, as it is identical except the version numbers.
Test service
The test service test_qmi_idl_service_object_v01 (0x0F) provides the functionality to test a QMI service or subsystem, e.g. pinging, NULL-requests, service quering.
- Tests a basic message passing between the client and the service.
- Tests variably sized messages.
- Tests large variably sized messages.
- Registers for variably sized indications.
- Queries the service for its name.
Summary
It is very hard to get an insight in the Qualcomm SoCs’ architecture, and therefore what your device is doing in the background.
In this post I have talked about different Qualcomm Hexagon DSP modem services.
I have much more to learn and investigate.
References