2015-12-24 13:59:23 -05:00
|
|
|
# LG LAF Protocol
|
|
|
|
This document is a reverse-engineered protocol description for "LG LAG", the
|
|
|
|
download mode offered by various LG models. It is based on analysis on the
|
|
|
|
`Send_Command.exe` utility and `LGD855_20140526_LGFLASHv160.dll` file and a USB
|
|
|
|
trace using Wireshark and usbmon on Linux. Some commands were found in the
|
|
|
|
`/sbin/lafd` binary.
|
|
|
|
|
2015-12-26 15:30:14 -05:00
|
|
|
This document uses the following conventions for types:
|
|
|
|
|
|
|
|
- `\xaa\xbb\xcc\xdd` denotes a byte pattern `aa bb cc dd`.
|
|
|
|
- `0xddccbbaa` denotes a 32-bit integer in hexadecimal format. It represents
|
|
|
|
the same byte pattern as `\xaa\xbb\xcc\xdd`.
|
|
|
|
|
2015-12-24 13:59:23 -05:00
|
|
|
## Overview
|
|
|
|
LAF is a simple request/response protocol operating over USB. The USB details
|
|
|
|
are described at the end of the document, the messages are described below.
|
|
|
|
|
|
|
|
Each message consists of a header, followed by an optional body. The header
|
|
|
|
contains 32-bit DWORDs, integers are encoded in little-endian form:
|
|
|
|
|
|
|
|
| Offset (hex) | Offset (dec) | Type | Description
|
|
|
|
| ----:| --:| ---
|
|
|
|
| 0x00 | 0 | char[4] | Command
|
|
|
|
| 0x04 | 4 | var | Argument 1
|
|
|
|
| 0x08 | 8 | var | Argument 2
|
|
|
|
| 0x0c | 12 | var | Argument 3
|
|
|
|
| 0x10 | 16 | var | Argument 4 (not encountered)
|
|
|
|
| 0x14 | 20 | int | Body length
|
|
|
|
| 0x18 | 24 | int | CRC-16
|
|
|
|
| 0x1c | 28 | char[4] | Bit-wise invertion of command at offset 0
|
|
|
|
|
|
|
|
Arguments can be integers or character sequences depending on the command.
|
|
|
|
|
|
|
|
The CRC field is the CRC-16-CCITT calculation (LSB-first) over the header and
|
|
|
|
the body with zeroes in place of CRC.
|
|
|
|
|
|
|
|
Each request is followed by a response with a matching command field. If an
|
|
|
|
error occurs, the response contains command is `FAIL` with argument 1 being the
|
|
|
|
error code and the original request header as body.
|
|
|
|
|
|
|
|
## Commands
|
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
### OPEN - Open File
|
|
|
|
Opens a file path.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
Arguments:
|
|
|
|
- arg1 (response): DWORD file descriptor.
|
|
|
|
Request body: NUL-terminated file path that should be opened for reading or an
|
|
|
|
empty string to open `/dev/block/mmcblk0` in read/write mode.
|
|
|
|
(at most 276 (0x114) bytes?)
|
|
|
|
|
|
|
|
Non-existing files result in FAIL with error code 0x80000001.
|
|
|
|
|
|
|
|
### CLSE - Close File
|
|
|
|
Closes a file descriptor which was returned by the `OPEN` command.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
- arg1: DWORD file descriptor (same in request and response).
|
|
|
|
|
|
|
|
Note: this allows you to close any file descriptor that are in use by the `lafd`
|
|
|
|
process, not just the one returned by `OPEN`. You can discover the current file
|
|
|
|
descriptors via `ls -l /proc/$pid/fd` where `$pid` is found by `ps | grep lafd`.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
|
|
|
### HELO - Hello
|
|
|
|
Arguments:
|
|
|
|
- arg1: DWORD Protocol Version (`\1\0\0\1`) (resp must match req.)
|
|
|
|
- arg2 (response): Minimum Protocol Version (`\0\0\x80\0` was observed)
|
|
|
|
|
|
|
|
### CTRL - Control
|
|
|
|
Arguments:
|
2015-12-26 08:52:26 -05:00
|
|
|
- arg1: "RSET" (reboots device) or "ONRS"
|
2015-12-24 13:59:23 -05:00
|
|
|
|
|
|
|
Note: `CTRL(RSET)` with no body is sent by the `Send_Command.exe` utility for
|
|
|
|
the `LEAVE` command.
|
|
|
|
|
2015-12-26 08:52:26 -05:00
|
|
|
LG Flash DLL waits 5000 milliseconds after this command.
|
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
### WRTE - Write File
|
|
|
|
Writes to a file descriptor.
|
|
|
|
|
2015-12-24 13:59:23 -05:00
|
|
|
Arguments:
|
2015-12-25 09:08:26 -05:00
|
|
|
- arg1: file descriptor (must be open for writing!)
|
2015-12-26 15:30:14 -05:00
|
|
|
- arg2 (request): offset in **blocks** (multiple of 512 bytes).
|
|
|
|
- arg2 (response): offset in **bytes**.
|
2015-12-25 09:08:26 -05:00
|
|
|
Request body: the data to be written. Can be of any size (including 1 or 513).
|
|
|
|
|
|
|
|
Note: writing to a file descriptor which was opened for reading results in FAIL
|
|
|
|
with code 0x82000002. This command is likely used for writing to partitions.
|
|
|
|
|
2015-12-26 15:30:14 -05:00
|
|
|
Integer overflow in the response offset is ignored. That is, the block offset
|
|
|
|
30736384 (0x1d50000) is 0x3aa000000 bytes, but will appear as 0xaa000000.
|
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
### READ - Read File
|
|
|
|
Reads from a file descriptor.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
|
|
|
Arguments:
|
2015-12-25 09:08:26 -05:00
|
|
|
- arg1: file descriptor
|
|
|
|
- arg2: offset in **blocks** (multiple of 512 bytes).
|
2015-12-26 08:52:26 -05:00
|
|
|
- arg3: requested length in bytes (at most 8MiB).
|
2015-12-25 09:08:26 -05:00
|
|
|
Response body: data in file at given offset and requested length.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
Note: be sure not to read past the end of the file (512 * offset + length), this
|
|
|
|
will hang the communication, requiring a reset (pull out battery)!
|
2015-12-24 13:59:23 -05:00
|
|
|
|
2015-12-26 08:52:26 -05:00
|
|
|
If the length is larger than somewhere between 227 MiB and 228 MiB, an
|
|
|
|
0x80000001 error will be raised (observed with /dev/block/mmcblk0). Requesting
|
|
|
|
lengths larger than 8 MiB however already seem to hang the communication.
|
|
|
|
|
2015-12-24 13:59:23 -05:00
|
|
|
### ERSE - Erase
|
|
|
|
Arguments:
|
|
|
|
- arg1: ?
|
|
|
|
- arg2: ?
|
|
|
|
- arg3: ?
|
|
|
|
|
|
|
|
### EXEC - Execute Command
|
|
|
|
Arguments: none
|
|
|
|
Request body: NUL-terminated command.
|
|
|
|
Response body: standard output of the command.
|
|
|
|
|
|
|
|
The command is probably split on space and then passes to `execve`. In order to
|
|
|
|
see standard error, use variables and globbing, use a command such as:
|
|
|
|
|
|
|
|
sh -c "$@" -- eval 2>&1 echo $PATH
|
|
|
|
|
2015-12-25 09:08:26 -05:00
|
|
|
### INFO
|
2015-12-24 13:59:23 -05:00
|
|
|
Arguments:
|
|
|
|
- arg1: action (`GPRO` - Get Properties, `SPRO` - Set Properties)
|
2015-12-25 09:08:26 -05:00
|
|
|
Request body: must begin with two bytes (`08 0b`).
|
|
|
|
Response body: 2824 (0xb08) bytes of binary info.
|
|
|
|
|
|
|
|
See [scripts/parse-props.py](scripts/parse-props.py) for the structure of the
|
|
|
|
property body.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
2015-12-27 12:45:31 -05:00
|
|
|
### UNLK - Unlink
|
|
|
|
Delete a file.
|
|
|
|
|
2015-12-24 13:59:23 -05:00
|
|
|
Arguments: none
|
2015-12-27 12:45:31 -05:00
|
|
|
Request body: NUL-terminated file name
|
|
|
|
|
|
|
|
Responds with FAIL code 0x80000001 if the file name is invalid (missing) or
|
|
|
|
file does not exist. Deleting directories is also not possible, giving the same
|
|
|
|
FAIL code 0x80000001.
|
2015-12-24 13:59:23 -05:00
|
|
|
|
|
|
|
### RSVD - Reserved
|
|
|
|
Arguments: none
|
|
|
|
|
2015-12-27 12:45:31 -05:00
|
|
|
### IOCT - ioctl
|
2015-12-24 13:59:23 -05:00
|
|
|
Unknown.
|
|
|
|
|
|
|
|
### MISC
|
|
|
|
Unknown.
|
|
|
|
|
|
|
|
### KILO
|
|
|
|
Unknown.
|
|
|
|
|
|
|
|
### DIFF
|
|
|
|
Unknown.
|
|
|
|
|
|
|
|
## USB layer
|
|
|
|
The LG Windows driver (via `LGMobileDriver_WHQL_Ver_4.0.3.exe`) exposes two
|
|
|
|
serial ports, `LGANDNETMDM0` and `LGANDNETDIAG1`. The `LGANDNETDIAG1` port is
|
|
|
|
used for LAF.
|
|
|
|
|
|
|
|
The LG G3 (D855) has Vendor ID 0x1004 and Product ID 0x633e.
|
|
|
|
|
|
|
|
There is only one configuration descriptor and LAF uses bulk transfers over
|
|
|
|
endpoints 5 (for input from the device) and endpoint 3 (for output to the
|
|
|
|
device).
|
|
|
|
|
|
|
|
For other descriptors, see [info/lsusb.txt](info/lsusb.txt).
|