mirror of
https://github.com/Lekensteyn/lglaf.git
synced 2024-11-30 10:56:49 -05:00
Update protocol.md
Add more commands and info [Peter: typo fix and formatting] Fixes https://github.com/Lekensteyn/lglaf/pull/18
This commit is contained in:
parent
8dc96c2178
commit
89be7edab6
1 changed files with 158 additions and 7 deletions
165
protocol.md
165
protocol.md
|
@ -45,12 +45,15 @@ Opens a file path.
|
|||
|
||||
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.
|
||||
|
||||
On newer versions, this requires authentication via `KILO` command.
|
||||
|
||||
### CLSE - Close File
|
||||
Closes a file descriptor which was returned by the `OPEN` command.
|
||||
|
||||
|
@ -67,14 +70,23 @@ Arguments:
|
|||
- arg2 (response): Minimum Protocol Version (`\0\0\x80\0` was observed)
|
||||
|
||||
### CTRL - Control
|
||||
Reboot or power off.
|
||||
Arguments:
|
||||
- arg1: "RSET" (reboots device), "POFF" (powers device off) or "ONRS"
|
||||
- arg1: sub-command:
|
||||
- `POFF`: power off
|
||||
- `RSON`: restart lafd
|
||||
- `RSET`: reboot with param `oem-90466252` (normal reboot)
|
||||
- `ONRS`: reboot with param `oem-02179092`
|
||||
- `AATD`: reboot with param `aat_enter`
|
||||
|
||||
Note: `CTRL(RSET)` with no body is sent by the `Send_Command.exe` utility for
|
||||
the `LEAVE` command.
|
||||
|
||||
LG Flash DLL waits 5000 milliseconds after this command.
|
||||
|
||||
Purpose of `ONRS` and `AATD` are unknown. Both seem to reboot normally. Probably
|
||||
one is meant to enter fastboot?
|
||||
|
||||
### WRTE - Write File
|
||||
Writes to a file descriptor.
|
||||
|
||||
|
@ -82,6 +94,7 @@ 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
|
||||
|
@ -90,6 +103,9 @@ 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.
|
||||
|
||||
This can be used to write to already-opened files without authentication, but
|
||||
lafd doesn't appear to have any files opened for writing by default.
|
||||
|
||||
### READ - Read File
|
||||
Reads from a file descriptor.
|
||||
|
||||
|
@ -98,6 +114,7 @@ Arguments:
|
|||
- arg2: offset in **blocks** (multiple of 512 bytes).
|
||||
- arg3: requested length in bytes (at most 8MiB).
|
||||
- arg4: "whence" seek mode (see below).
|
||||
|
||||
Response body: data in file at given offset and requested length.
|
||||
|
||||
Note: be sure not to read past the end of the file (512 * offset + length), this
|
||||
|
@ -109,11 +126,17 @@ Arg4 affects the seek mode, values for request:
|
|||
- 2 (`SEEK_END`) - kind of useless when all offsets are unsigned...
|
||||
- 3 (`SEEK_DATA`) - FAILs with 0x80000001 when used on `/proc/kmsg` or
|
||||
`/dev/block/mmcblk0p44`. Works on a regular file though.
|
||||
|
||||
The response matches the request (masked with 0x3).
|
||||
|
||||
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.
|
||||
lengths larger than 8 MiB however already seem to hang the communication. Length
|
||||
can be zero to test if a file is readable.
|
||||
|
||||
This can be used to read already-opened files without authentication, but lafd
|
||||
seems to only have PNG files and `/dev/null` open by default. Attempting to read
|
||||
`/dev/null` hangs communication.
|
||||
|
||||
### ERSE - Erase Block
|
||||
TRIMs a block (`IOCTL_TRIM_CMD`).
|
||||
|
@ -123,6 +146,7 @@ Arguments:
|
|||
- arg2: start address (in sectors).
|
||||
- arg3: count (in sectors).
|
||||
- arg4: unknown, set to zero.
|
||||
|
||||
Request body: none.
|
||||
|
||||
Note: after sending TRIM, reading the block still returned old values. After a
|
||||
|
@ -130,7 +154,9 @@ reboot, everything was zeroed out though.
|
|||
|
||||
### EXEC - Execute Command
|
||||
Arguments: none
|
||||
|
||||
Request body: NUL-terminated command, at most 255 bytes including terminator.
|
||||
|
||||
Response body: standard output of the command.
|
||||
|
||||
The command is split on spaces and then passed to `execvp`. In order to see
|
||||
|
@ -149,10 +175,15 @@ The maximum output size appears to be 0x800001 (`LAF_MAX_DATA_PAYLOAD`). Larger
|
|||
values result in an error. Output is read per byte, not very efficient for large
|
||||
output...
|
||||
|
||||
On newer versions, this requires authentication via `KILO` command, and few
|
||||
commands are allowed.
|
||||
|
||||
### INFO
|
||||
Arguments:
|
||||
- arg1: action (`GPRO` - Get Properties, `SPRO` - Set Properties)
|
||||
|
||||
Request body: a `laf_property` structure.
|
||||
|
||||
Response body: 2824 (0x00000b08) bytes of binary info.
|
||||
|
||||
See [scripts/parse-props.py](scripts/parse-props.py) for the structure of the
|
||||
|
@ -163,6 +194,7 @@ apparently the same as the expected length (2824 or `\x08\x0b\0\0`).
|
|||
Delete a file.
|
||||
|
||||
Arguments: none
|
||||
|
||||
Request body: NUL-terminated file name
|
||||
|
||||
Responds with FAIL code 0x80000001 if the file name is invalid (missing) or
|
||||
|
@ -170,19 +202,138 @@ file does not exist. Deleting directories is also not possible, giving the same
|
|||
FAIL code 0x80000001.
|
||||
|
||||
### RSVD - Reserved
|
||||
Arguments: none
|
||||
Miscellaneous commands.
|
||||
|
||||
Arguments:
|
||||
- arg1: Subcommand:
|
||||
- IDDD: create `/data/idt.cfg` ("indirect config file") and start IDT thread
|
||||
- PDDD: unzip DF file
|
||||
- QDDD: verify `/system/DFFileList.txt`
|
||||
- RDDD: execute `/system/DFFileList.txt`
|
||||
- SDDD: LCD test (turns screen grey)
|
||||
- TDDD: set properties and disable USB:
|
||||
- `ro.boot.laf = MID`
|
||||
- `sys.usb.config = none`
|
||||
|
||||
### IOCT - ioctl
|
||||
Unknown.
|
||||
Perform flash IOCTLs. (XXX document this)
|
||||
|
||||
### MISC
|
||||
Unknown.
|
||||
Read/write misc parttition.
|
||||
|
||||
Arguments:
|
||||
- arg1: Subcommand
|
||||
- `READ`
|
||||
- `WRTE`
|
||||
|
||||
XXX document this
|
||||
|
||||
### KILO
|
||||
Unknown.
|
||||
Challenge/response to authenticate for some commands.
|
||||
|
||||
Arguments:
|
||||
- arg1: `CENT` or `METR`
|
||||
- arg2: challenge/mode
|
||||
|
||||
1. Host sends `CENT` with arg2=0
|
||||
2. Device responds `CENT` with a random value in arg2
|
||||
3. Host responds `METR` with desired mode in arg2 and challenge response as body
|
||||
4. Device responds `METR` with no body, or `FAIL`
|
||||
|
||||
The response must decrypt to the bytes
|
||||
`00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F`. TODO: explain protocol
|
||||
|
||||
### DIFF
|
||||
Unknown.
|
||||
Execute a script of some sort, path specified in message body.
|
||||
|
||||
### FAIL
|
||||
Dummy command.
|
||||
|
||||
### new versions
|
||||
TODO: document these commands added in some version:
|
||||
CRCC, TOFF, COPY, CHCK, OPCM, SNIF, SEBP, SBLU, SLEI, SIGN, MBPT, WRZR, FUSE
|
||||
|
||||
|
||||
## HDLC commands
|
||||
These are sent through the same interface, but have a different structure:
|
||||
|
||||
* The packet must be at least 3 and at most 31 bytes long.
|
||||
* The last byte must be 0x7E.
|
||||
* Any 0x7D byte is skipped; the next byte is then XORed with 0x20. eg 0x7D 0x5E
|
||||
becomes 0x7E. (Not sure why this is done.)
|
||||
* The last two bytes of the body are a CRC16.
|
||||
|
||||
After decoding, the body is checked for an 0x7E byte (except the very last byte
|
||||
of the packet); if one is found, all bytes up to and including it are discarded.
|
||||
This is done before the checksum is validated. (for example, 0x7E marks the
|
||||
beginning of the body, but can be omitted, in which case the body starts at the
|
||||
first byte of the packet.)
|
||||
|
||||
The first byte of the body is a command:
|
||||
* 0x06: unknown. Always responds with 0x02?
|
||||
* 0x0A: Sets misc partition item 0x1C0 and reboots. (XXX investigate)
|
||||
* 0xEF: webdload_proc
|
||||
* 0xFA: testmode_proc
|
||||
|
||||
Additionally, sending a packet which decodes to an empty body (for example, a
|
||||
packet of only `0x7E 0x7E 0x7E 0x7E`) restarts lafd. Unsure if this is
|
||||
intentional.
|
||||
|
||||
### webdload_proc
|
||||
First byte of body (after 0xEF command byte) is subcommand:
|
||||
* 0x00: returns 0x05 and writes 0x04 at input[3]
|
||||
* 0xA0: returns device OS version, target operator, model, etc.
|
||||
* 0xA1, 0xA2, 0xB0, 0xB1, 0xB2, 0xB5: all return all-zero response.
|
||||
|
||||
These appear to also read/write some misc partition values.
|
||||
|
||||
### testmode_proc
|
||||
First two bytes (after 0xFA command byte) must be 0x94 0x00. Next byte after
|
||||
that is subcommand for `laf_testmode_bootloader_unlock_handler`:
|
||||
* 0x00: Check if unlocked. (`/sys/devices/platform/lge-msm8226-qfprom/unlock`
|
||||
contains 0x277F.)
|
||||
* 0x01: Always returns 0.
|
||||
* 0x02: Reads hex from `/sys/devices/platform/lge-msm8226-qfprom/unlock-extra`.
|
||||
* 0x03: Read `/persist/rct`.
|
||||
|
||||
Commands 0x00 and 0x02 don't work on some devices, since they have `lge-qfprom`
|
||||
instead of `lge-msm8226-qfprom` directory.
|
||||
|
||||
#### Return data
|
||||
0xFA 0x94 0x00 followed by response body followed by CRC16 and 0x7E, encoded the
|
||||
same way as the command packet.
|
||||
|
||||
First byte of response body is a status code:
|
||||
* 0x00: OK
|
||||
* 0x01: Failed
|
||||
* 0x02: Return from command 0x06 (might be LAF_ERROR_INVALID_PARAMETER? but it
|
||||
can only ever return this.)
|
||||
* 0x05: Return from webdload_proc subcommand 0x00 (might be
|
||||
LAF_ERROR_INTERNAL_ERROR?)
|
||||
* 0xFF: Invalid command
|
||||
|
||||
Following response bytes depend on the command:
|
||||
* testmode_proc: null-terminated string (eg "lock", "unlock", "fail") followed
|
||||
by unknown bytes (0x19 0xEA 0xE8 0x7F 0x00 0x00 observed)
|
||||
* webdload_proc: several strings of device info
|
||||
|
||||
|
||||
## Encoded commands
|
||||
For convenience, valid commands encoded with CRC:
|
||||
* 0xEF 0x00 0x00 0x00 0xAD 0xFA 0x7E
|
||||
* 0xEF 0xA0 0x00 0x00 0x7A 0xF5 0x7E
|
||||
* 0xEF 0xA1 0x00 0x00 0xA6 0xAF 0x7E
|
||||
* 0xEF 0xA2 0x00 0x00 0xC2 0x40 0x7E
|
||||
* 0xEF 0xB0 0x00 0x00 0xEF 0x70 0x7E
|
||||
* 0xEF 0xB1 0x00 0x00 0x33 0x2A 0x7E
|
||||
* 0xEF 0xB2 0x00 0x00 0x57 0xC5 0x7E
|
||||
* 0xEF 0xB5 0x00 0x00 0x52 0x49 0x7E
|
||||
* 0xFA 0x94 0x00 0x00 0x43 0xBD 0x7E
|
||||
* 0xFA 0x94 0x00 0x01 0xCA 0xAC 0x7E
|
||||
* 0xFA 0x94 0x00 0x02 0x51 0x9E 0x7E
|
||||
* 0xFA 0x94 0x00 0x03 0xD8 0x8F 0x7E
|
||||
* 0xFA 0x94 0x00 0x04 0x67 0xFB 0x7E
|
||||
|
||||
|
||||
## USB layer
|
||||
The LG Windows driver (via `LGMobileDriver_WHQL_Ver_4.0.3.exe`) exposes two
|
||||
|
|
Loading…
Reference in a new issue