Qfuses in the MSM8960
In order to simplify the design and satisfying the requirements for a wide
range of hardware external to the MSM. Qualcomm has incorporated a reserved
One-Time-Programmable (OTP aka PROM) memory region, onto their SoC's, that
they call QFPROM. This region contain a collection of all necessary HW related
configuration settings for the operation of the MSM itself, as well as for
most popular peripheral devices such as PMIC, HDMI, eMMC, SD, USB and many
others.
The actual content of the QFPROM in the MSM8960 is a 4KB (4096 byte) region
of registers, that can be burned (fused) permanently by either Qualcomm
and/or the OEMs like Samsung and HTC, by themselves. Most of the registers
are related to peripheral HW settings, but there is also a region specifically
allocated for various chip security features, such as configuring the boot
process and setting various locking, authentication, JTAG and other
accessibility and debug features.
In older Qualcomm SoC models the various PROM registers was referred
separately to as Efuse-registers and Security/Boot registers, etc. Now,
however, they just use the acronym "Qfuses" for this entire collection,
AFAIK...
Knowing what Qfused features are incorporated and activated in a particular
device, can be extremely helpful, if not necessary, for the debugging and
revival of "bricked" devices. In those cases where a recovery is possible, we
refer to the device as having been "soft-bricked". However, in some cases when
no other method of revival is possible, we label the device as "hard-bricked".
In the most extreme case, a company or government may choose to build their
devices so tightly locked down, that any manipulation attempts detected by the
IROM bootloader, may trigger a range of fuses to make the device impossible to
boot or extract information from.
For the developer community this is both a challenge and a pain in the arse.
We get bricks from left and right, but we have absolutely no useful or freely
accessible documentation for how to determine the internal HW settings that
can be useful to revive our phones and tablets. This is an attempt to lighten
those problems, by properly and openly documenting the interior functionality
of our PoP SoC chips. In this case the widely popular MSM8960 aka
"Snapdragon 4S".
As the QC empire only speaks in terms of $$$, we have to expect that there
will never be any publicly available documentation on this (or any future)
top-model chip-sets from Qualcomm. Security by obscurity is their motto,
because that is what their sales numbers and marketing officers are telling
them is right. So we have to collect the moldy bread-crumbs to glue together a
dough that we can hopefully bake into a piece of bread. The crumbs in question
are scattered throughout the Kernel source-code, old and outdated
documentation and reverse engineering of bootloaders and other firmware,
sprinkled with an occasional document leaks, that temporarily brighten our
dark days of hardware development.
The Qfuses discussed herein are separated into three categories:
- Boot-up and Security settings
- Other internal MSM settings
- External peripheral device settings
A Qfuse register map would of course have been heaven, but we'll have to
settle with trying to map out approximate locations and by time-consuming
trial-and-error methods.
Current Status
What we know so far can be summarized in a few lines. Below I have also added
some unreliable register specifications for some older chips, as a comparative
reference. Hopefully at least part of these will have some resemblance to
those used in the 8960.
One thing that seem fixed in all mobile phones PBL's and Kernel sources is
the QFPROM base address location. This can be somewhat confusing because
apparently the QFPROM fuses cannot be simply read directly at their base
addresses. Probably because some Kernel or HW security feature is preventing
these memory reads from user-land. Instead the Qfuse registers are shadowed
into another RAM region that is used by bootloaders to find the true Qfuse
values. According to some documents this shadow region also contain an error
correction value. However, it is not clear if the entire 4K region is
shadowed or only part of it...
From an older MSM document:
The CONFIG chain includes shadow registers that relatch sensed fuse values
upon completion of fuse-sense operations. This latching is done in the
security mode control block and is necessary because with JTAG access to the
CONFIG chain, it is possible to scan any value into fuse cell latches, making
a blown fuse appear unblown to the rest of the logic. Shadow registers store
the actual fuse values immediately after sensing and maintain them even if
different values are scanned into the fuse cells.
Code:
QFPROM BASE ADDRESS: IOMEM(0xFA700000)
QFPROM BASE PHYSICAL: 0x00700000
QFPROM SHADOW BASE: 0x00706000
QFPROM SIZE: 0x1000 (4K)
Reading Qfuse registers
So how can we use this info to read the values from the Qfuse block? Well,
its actually not very difficult at all. The hardest thing is to be able to
confirm that what you think you read, is what is actually there. There are
many ways to corrupt simple memory reads, ranging from
standard linux security
measures to Qualcomm-specific memory protection. Luckily, at the moment, these
are rarely implemented.
The easiest tool to use is
viewmem. There is also another tool called
devmem2,
(
src) originally made for the
RasberryPi, that also support writing to memory.
Both tools depend on the
/dev/mem device. If this is not present or accessible
on your system, these tools will not work. Finally there is a memory forensic
tool called
LiME (Linux Memory Extractor), which is a kernel module that take
an image snapshot of the entire system, regardless of
/dev/mem presence or
other memory protection schemes.
These are all general memory utilities. However, Qualcomm have their own tool
to read and write Qfuse blocks. The device driver is present in the CodeAurora
repository for their MSM specific Kernel here: ./drivers/misc/qfp_fuse.c
So for the real brave ones, you can try to compile your own Qfuse reader or
writer. (I'd like to have a copy!)
Now to the slighlty tricky part of correctly reading the memory. When reading
a memory register of, let's say, 32bits. It's important you understand how ARM
based Android devices handle
endianess. Although ARM processors are bi-endian
since version 3, the ARM is used as little endian by default when used in
Android mobile devices.
The
viewmem program uses
/dev/mem to output raw data to whatever device you
specify, or to your terminal if none is specified. In order to see this data
you need to either use a hexeditor or filter the output through
hexdump.
However,
hexdump have some little quirks when it come to data ordering. To get
the same byte ordering as in the raw file, you need to use the "
-C" switch,
otherwise the MSB and LSB, byte-pairs will be switched around with respect to
the raw input. So to make a few examples.
Example-1: Reading and displaying the
OEM_CONFIG0 Qfuse register
Code:
viewmem 0x706024 0x4 |hexdump -C
00000024 00 00 c0 19
Raw Hex: 00 00 C0 19
Little Endian:
=> Hex: [0000 C019]
=> Bin: [0000 0000 0000 0000 1100 0000 0001 1001]
| |
=> Byte#: LSB 4 3 2 1 MSB
Here "Byte#" refers to the byte number reading order, so if the above
4 bytes was an address, it would have been "0x19c00000".
Example-2: Reading/dumping the raw Qfuse region (probably provides false data)
Code:
viewmem 0x700000 0x1000 >/path_to_sd_card/qfprom_raw.bin
Example-3: Reading/dumping the Qfuse shadow region (?)
Code:
viewmem 0x706000 0x1000 >/path_to_sd_card/qfprom_shadow.bin
Example-4: Reading/dumping PBL from IROM
Code:
viewmem 0x0 0x18000 >/path_to_sd_card/pbl.bin
QFPROM Register Map for the MSM8260 / 8660
The document gods have been good, and we have been blessed with some 8660 documentation
that may help shed some light on the 8960. Here is the Qfuse (QFPROM) register map, showing the
2K block.
(The 8960 apparently use a
4K block!)
In addition the QFPROM programming algorithm is already included in the code.
(Probably in one of the secondary bootloaders; SBL1-3...)