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