firmware update
Bjørn Mork
bjorn at mork.no
Mon Dec 14 05:15:12 PST 2015
Aleksander Morgado <aleksander at aleksander.es> writes:
> On Mon, Dec 14, 2015 at 10:12 AM, dailijin <dailijin126 at 126.com> wrote:
>> Thanks your quick responds, this is bad news to me.
>>
>> I known the Sierra firmware updater worked with GobiNet and GobiSerial
>> driver, but the two driver will conflict with libqmi driver, this is indeed
>> not convenience for my dialing logic. Do you have planed to support this
>> feature in libqmi?
>
> Well, it's not much about libqmi itself, but about rewriting an
> updater program that plays nicely with qmi_wwan and the upstream
> serial drivers, e.g. using libqmi/qmicli to reboot into QDL download
> mode and then using an improved "gobi_loader" program to load the new
> firmware via the exposed TTY.
It seems simple to implement on paper, but there are a few issues to
keep in mind:
- It's very easy to end up with a (soft-)bricked device if anything
unexpected happens. And we don't know what to expect in general...
- There are no public docs of any of the involved protocols, which makes
it difficult to recover from a soft brick
- We don't know how to properly sanity check and verify the images. We
can only upload what we have and hope for the best
I have never tried this procedure, so be careful and read the above once
or twice before you try it, but the procedure seems to be:
a) several rounds of model and version checking using
DMS "Get Model" (0x0022)
DMS "Sierra Wireless Get Model???" (0x5556) [1]
DMS "Get Revision" (0x0023)
I guess this part can be ignored wrt image writing, but proper
download code should verify that the image file matches the modem,
both wrt hardware and currently running version. We don't know if
downgrades are supported, so let's assume the are not.
b) switch to QDL mode using DMS ??? (0x003e). This is a request with no
TLVs, and the reply has only TLV 0x02:
< 01 0C 00 00 02 02 00 09 00 3E 00 00 00
> 01 13 00 80 02 02 02 09 00 3E 00 07 00 02 04 00 00 00 00 00
It is followed by an immediate reboot to "QDL mode"
c) When in QDL mode, I believe you start out in a protocol known as
"DLOAD" or "DMSS Download Protocol" [2]. The first thing you do there
is to switch to another protocl, known as "Streaming DLOAD" or "SDP"
[3].
I have yet to find any docs of this switching request, but snooping
shows that it is this simple HDLC frame:
7e 70 00 00 14 46 7e
The "00 00" is a command parameter. I have no idea of the exact
meaning. I've only observed a 0 so far.
d) SDP is what the gobi-loader [4] speaks. It starts with a
semi-doumented hello request (0x01) and ack (0x02):
0040 7e 01 51 43 4f 4d 20 68 69 67 68 20 73 70 65 65 ~.QCOM high spee
0050 64 20 70 72 6f 74 6f 63 6f 6c 20 68 73 74 00 00 d protocol hst..
0060 00 00 06 06 30 00 00 00 de d3 7e ....0.....~
0040 7e 02 51 43 4f 4d 20 68 69 67 68 20 73 70 65 65 ~.QCOM high spee
0050 64 20 70 72 6f 74 6f 63 6f 6c 20 74 67 74 30 00 d protocol tgt0.
0060 00 00 06 06 00 00 00 00 00 00 00 00 00 00 00 00 ................
0070 00 30 d9 bc 7e .0..~
e) Then the Sierra Wireless downloader starts with a part of the
protocol I've found no docs for, but is implemented by the
gobi-loader. This is a start download (0x25) + ack (0x26), followed
by data (0x27) and ack (0x28)
The most difficult part here, is probably getting the 0x25 request
right. This will tell the firware what kind of file we are sending,
and the size it should expect to receive. If you look at the
gobi-loader, you'll see that it sends several files.
The Sierra downloader sends a single complete image, typically using a
request like this (from an upgrade of an MC7710 to 03.05.24):
0040 7e 25 80 1c 38 4f 02 01 8c 36 4f 02 00 00 01 01 ~%..8O...6O.....
0050 02 00 00 00 01 90 00 08 cb 4a 46 55 4c 4c 00 00 .........JFULL..
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 ................
0070 02 00 00 08 cc da 00 08 d1 72 46 55 4c 4c 00 00 .........rFULL..
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 ................
0090 00 00 00 11 9e 4c 02 3d 99 d0 46 55 4c 4c 00 00 .....L.=..FULL..
00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d8 2f .............../
0150 cf 2b 00 00 00 03 ff ff ff ff 53 50 4b 47 39 32 .+........SPKG92
0160 30 30 02 4f 36 8c 6d 11 b8 2a 39 39 39 39 39 39 00.O6.m..*999999
0170 39 5f 39 39 39 39 39 39 39 5f 39 32 30 30 5f 30 9_9999999_9200_0
0180 33 2e 30 35 2e 32 34 2e 30 30 5f 30 30 5f 67 65 3.05.24.00_00_ge
0190 6e 65 72 69 63 5f 30 30 30 2e 30 30 30 5f 30 30 neric_000.000_00
01a0 31 5f 53 50 4b 47 5f 4d 43 00 00 00 00 00 00 00 1_SPKG_MC.......
01b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 35 ..............05
01c0 2f 30 32 2f 31 33 00 00 00 00 00 00 00 00 00 00 /02/13..........
01d0 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ae da ................
01e0 7e ~
There is lots of interesting info in the above, but this part seems
important to understand the reply: 80 1c 38 4f 02 01 8c 36 4f 02
This looks like "byte, le32, byte, le32". The first "byte" appears to
tell what type of file this is (see gobi-loader). The second is
always(?) 1. And the two "le32" numbers look like image sizes. This is
also confirmed by gobi-loader. Match 0x024f368c (38745740) with this:
$ ls -l /tmp/9999999_9999999_9200_03.05.24.00_00_generic_000.000_001_SPKG_MC.cwe
-rw-r--r-- 1 bjorn bjorn 38746140 May 30 2013 /tmp/9999999_9999999_9200_03.05.24.00_00_generic_000.000_001_SPKG_MC.cwe
And notice the same sequence in the reply ack, preceded by an unknown
16bit zero parameter:
0040 7e 26 00 00 01 8c 36 4f 02 e7 2f 7e ~&....6O../~
There are two notable differences in the above 0x25 request compared
to the ones generated by gobi-loader
1) the above is much longer
2) the above has slightly different "size" numbers
The difference is 0x024f381c - 0x024f368c = 0x190 (400d), which is
exactly the number of "extra" data bytes in the 0x25 request. Those
400 bytes is the beginning of the firmware image:
00000000 01 01 02 00 00 00 01 90 00 08 cb 4a 46 55 4c 4c |...........JFULL|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 01 01 02 00 00 08 cc da 00 08 d1 72 46 55 4c 4c |...........rFULL|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 01 02 00 00 00 11 9e 4c 02 3d 99 d0 46 55 4c 4c |.......L.=..FULL|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 d8 2f cf 2b 00 00 00 03 ff ff ff ff 53 50 4b 47 |./.+........SPKG|
00000110 39 32 30 30 02 4f 36 8c 6d 11 b8 2a 39 39 39 39 |9200.O6.m..*9999|
00000120 39 39 39 5f 39 39 39 39 39 39 39 5f 39 32 30 30 |999_9999999_9200|
00000130 5f 30 33 2e 30 35 2e 32 34 2e 30 30 5f 30 30 5f |_03.05.24.00_00_|
00000140 67 65 6e 65 72 69 63 5f 30 30 30 2e 30 30 30 5f |generic_000.000_|
00000150 30 30 31 5f 53 50 4b 47 5f 4d 43 00 00 00 00 00 |001_SPKG_MC.....|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000170 30 35 2f 30 32 2f 31 33 00 00 00 00 00 00 00 00 |05/02/13........|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
f) so far we've seen HDLC framing. The 0x27 data frames following the
above is sent without framing. They have a 13-byte header, followed
by the next x bytes of the image. In my case, each of these were
split in four 0x800 byte URBs and one URB of 1661 bytes (all starting
at 0040 here due to the URB header, which I have removed):
0040 27 00 00 00 00 00 00 70 1e 00 00 73 82 00 00 00 '......p...s....
0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
..
0820 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0830 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
..
0820 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0830 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
..
0820 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0830 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
..
0690 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
06a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
06b0 ff ff ff ff ff ff ff ff ff ff ff ff ff .............
So what we see is a total of 13 header bytes and 3*2048+1648=7792 data
bytes. The header is a sequence number (le16 or le32?), followed by
an unknown 16 or 32 bit value (always? 0), the size of the data packet
(0x00001e70=7792d) and a checksum. I don't know if the checksum is
calculated over all the 7805 bytes, but I assume it is.
This is followed by reply starting with the same sequence number:
0040 7e 28 00 00 00 00 00 00 00 00 14 39 7e ~(.........9~
Then this is repeated again and again with exactly 0x2000 bytes
transfers (notice the sequence number being 0x00000001 here):
0040 27 01 00 00 00 00 00 00 20 00 00 a4 62 ff ff ff '....... ...b...
0050 ff ff ff ff ff ff ff ff ff ff ff ff ff d1 dc 4b ...............K
0060 84 34 10 d7 73 5a 43 0b 7d ff ff ff ff ff ff ff .4..sZC.}.......
0070 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
Until the last transfer which also is slightly shorter to match the
total:
0040 27 79 12 00 00 00 00 1c 18 00 00 86 54 78 a8 00 'y..........Tx..
0040 7e 28 79 12 00 00 00 00 00 00 1c 9f 7e ~(y.........~
So in total, we transferred
400 bytes in the 0x25 request
+ 0x1e70 bytes in the first 0x27 request
+ 0x1278 times 0x2000 bytes full sized 0x27 requests
+ 0x181c bytes in the last 0x27 request
= 38746140 bytes
Matching the image file size. Good. What we don't know is why the
first transfer is slightly shorter, or why we have the first 400
bytes transferred as part of the 0x25 request.
g) The procedure is terminated with a 0x29 request and 0x2a ack:
0040 7e 29 bb 4c 7e ~).L~
0040 7e 2a 00 00 00 00 4e e3 7e ~*....N.~
h) Then we send a 0x2d request, which is not part of the
gobi-loader. This request causes an immediate reboot into application
mode:
0040 7e 2d 9f 0a 7e ~-..~
The first reboot will take some time, and I believe it also could be
followed by more reboots before the process is complete. Then, if you
are lucky, the modem will boot a new firmware version in QMI mode.
If not, then you are most likely screwed and your modem is now an
expensive dummy slot filler.
Bjørn
[1] assumed vendor specific version info request. typical result:
QMI frame #0
>>>>>> QMUX:
>>>>>> length = 103
>>>>>> flags = 0x80
>>>>>> service = "dms"
>>>>>> client = 2
>>>>>> QMI:
>>>>>> flags = "response"
>>>>>> transaction = 5
>>>>>> tlv_length = 91
>>>>>> message = (0x5556)
>>>>>> TLV:
>>>>>> type = 0x02
>>>>>> length = 4
>>>>>> value = 00:00:00:00
>>>>>> TLV:
>>>>>> type = 0x16
>>>>>> length = 7
>>>>>> value = 30:30:30:2E:30:30:35
>>>>>> TLV:
>>>>>> type = 0x15
>>>>>> length = 2
>>>>>> value = 31:00
>>>>>> TLV:
>>>>>> type = 0x13
>>>>>> length = 8
>>>>>> value = 31:31:30:32:34:37:36:00
>>>>>> TLV:
>>>>>> type = 0x12
>>>>>> length = 21
>>>>>> value = 53:57:49:39:58:33:30:43:5F:30:31:2E:30:38:2E:30:37:2E:30:30:00
>>>>>> TLV:
>>>>>> type = 0x11
>>>>>> length = 21
>>>>>> value = 53:57:49:39:58:33:30:43:5F:30:31:2E:30:38:2E:30:37:2E:30:30:00
>>>>>> TLV:
>>>>>> type = 0x10
>>>>>> length = 7
>>>>>> value = 4D:43:37:34:35:35:00
(note that all these except 0x16 are 0x00 terminated)
0x10 => MC7455
0x11 => SWI9X30C_01.08.07.00
0x12 => SWI9X30C_01.08.07.00
0x13 => 1102476
0x15 => 1
0x16 => 000.005
[2] https://github.com/ghassani/openpst/blob/master/src/qc/dload.h
[3] https://github.com/ghassani/openpst/blob/master/src/qc/streaming_dload.h
[4] http://www.codon.org.uk/~mjg59/gobi_loader/
More information about the libqmi-devel
mailing list