lglaf/protocol.md

164 lines
5.3 KiB
Markdown
Raw Normal View History

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.
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
### OPEN - Open File
Opens a file path.
2015-12-24 13:59:23 -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.
### WRTE - Write File
Writes to a file descriptor.
2015-12-24 13:59:23 -05:00
Arguments:
- arg1: file descriptor (must be open for writing!)
- arg2 (request): offset in **blocks** (multiple of 512 bytes).
- arg2 (response): offset in **bytes**.
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.
Integer overflow in the response offset is ignored. That is, the block offset
30736384 (0x1d50000) is 0x3aa000000 bytes, but will appear as 0xaa000000.
### READ - Read File
Reads from a file descriptor.
2015-12-24 13:59:23 -05:00
Arguments:
- 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).
Response body: data in file at given offset and requested length.
2015-12-24 13:59:23 -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
### INFO
2015-12-24 13:59:23 -05:00
Arguments:
- arg1: action (`GPRO` - Get Properties, `SPRO` - Set Properties)
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
### UNLK - Unlock
Arguments: none
### RSVD - Reserved
Arguments: none
### IOCT
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).