firmware update
Dan Williams
dcbw at redhat.com
Mon Dec 14 09:44:36 PST 2015
On Mon, 2015-12-14 at 14:15 +0100, Bjørn Mork wrote:
> 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:
>
See also gobi-api/GobiAPI_1.0.40/Core/QDLBuffers.[cpp|h], gobi
-api/GobiAPI_1.0.40/Core/QDLEnum.h, and gobi
-api/GobiAPI_1.0.40/Core/QDLProtocolServer.cpp in libqmi repo.
Qualcomm released most of this in the GobiAPI drops. Not sure what
Sierra modified, but it looks mostly the same.
> 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:
That would be eQMI_DMS_SET_FIRMWARE_ID where the only applicable TLV
(0x01) is a 32-bit firmware ID. Clearly in your trace the device isn't
sending that TLV.
> < 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
The reply should be a result code consisting of the 16-bit status and a
16-bit code. Which matches your trace; there is no error.
> It is followed by an immediate reboot to "QDL mode"
So perhaps SetFirmwareID with no TLV is the "reboot to QDL mode"
trigger.
>
> 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].
Some bits in GobiAPI might be related, but it looks like they take
effect after the initial "Hello" packet:
ePROTOCOL_QDL_RX, // 09 QDL variant of streaming protocol (incoming)
ePROTOCOL_QDL_TX, // 10 QDL variant of streaming protocol (outgoing)
There are also the buffer definitions for "unframed" requests, which
makes sense WRT streaming since unframed would mean dropping the HDLC
framing.
> 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.
That part is odd, haven't found anything interesting about it. The
QCDM 0x70 command is DIAG_CMD_RAM_RW (but references calibration RAM)
so that's probably not anything related.
>
> 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..~
See sQDLHello::BuildHelloReq():
struct sQDLRawHelloReq {
BYTE mCommandCode; (eQDL_CMD_HELLO_REQ = 0x01)
BYTE mMagicNumber[32]; (QCOM high speed protocol)
BYTE mMaxVersion; (QDL_MIN_VERSION = 0x06)
BYTE mMinVersion; (QDL_MAX_VERSION = 0x06)
BYTE mFeatures; (QDL_FEATURE_GENERIC_UNFRAMED/0x10 | QDL_FEATURE_QDL_UNFRAMED/0x20 = 0x30)
};
struct sQDLRawHelloRsp {
BYTE mCommandCode; (eQDL_CMD_HELLO_RSP = 0x02)
BYTE mMagicNumber[24]; (same magic)
DWORD mReserved1; (0x20 0x74 0x67 0x74)
WORD mBootMajorVersion;(0x30 0x00)
WORD mBootMinorVersion;
BYTE mMaxVersion; (QDL_MIN_VERSION = 0x06)
BYTE mMinVersion; (QDL_MIN_VERSION = 0x06)
DWORD mReserved2;
DWORD mReserved3;
BYTE mReserved4;
WfORD mReserved5;
WORD mReserved6;
BYTE mFeatures; (QDL_FEATURE_GENERIC_UNFRAMED/0x10 | QDL_FEATURE_QDL_UNFRAMED/0x20 = 0x30)
};
> 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
See gobi-api/GobiAPI-1.0.40/Core/QDLEnum.h and gobi
-api/GobiAPI_1.0.40/Core/QDLBuffers.cpp:
0x25 = eQDL_CMD_OPEN_UNFRAMED_REQ
0x26 = eQDL_CMD_OPEN_UNFRAMED_RSP
> by data (0x27) and ack (0x28)
0x27 = eQDL_CMD_WRITE_UNFRAMED_REQ
0x28 = eQDL_CMD_WRITE_UNFRAMED_RSP
> 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.
gobi-api/GobiAPI_1.0.40/GobiQDLService/Main.cpp::Run() shows some of
this.
> 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
struct sQDLRawOpenUnframedReq {
BYTE mCommandCode; (0x25)
BYTE mImageType; (0x80) (used as eQDL_IMAGE_*)
DWORD mImageLength; (0x024f381c)
BYTE mWindowSize; (0x01, yes really 1)
DWORD mUnframedChunkSize; (0x024f368c)
WORD mReserved1; (0x0000)
};
Oddly GobiAPI sets the chunk size to QDL_MAX_CHUNK_SIZE = 1024 * 1024 *
64, so not sure where this one's coming from.
> 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../~
Your unknown is mStatus.
struct sQDLRawOpenUnframedRsp {
BYTE mCommandCode;
WORD mStatus;
BYTE mWindowSize;
DWORD mUnframedChunkSize;
};
>
> 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:
Odd; GobiAPI doesn't show any firmware data being attached to the
eQDL_CMD_OPEN_UNFRAMED_REQ, it sends the REQ, parses the RSP, then
starts sending data with eQDL_CMD_WRITE_UNFRAMED_REQ. I wonder if this
is Sierra-specific or it it's a Qualcomm enhancement since the GobiAPI
drops stopped in 2013.
> 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.~
eQDL_CMD_SESSION_DONE_REQ and eQDL_CMD_SESSION_DONE_RSP
>
> 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 ~-..~
eQDL_CMD_SESSION_CLOSE_REQ
Dan
> 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/
> _______________________________________________
> libqmi-devel mailing list
> libqmi-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/libqmi-devel
More information about the libqmi-devel
mailing list