[LG V20 Guides, News, & Discussion] runningnak3d:
Another small update. I was working with some bad packet dumps. Some things weren't adding up so I took all new dumps.

I am posting this here mainly because some people are actually interested in this stuff, but also because I lost a LOT of documentation that I had made when I lost my drive. If it is posted here, then I can't lose it :)

I will do follow up posts describing the algorithm that is used to generate the response, and another post documenting all the opcodes and the arg / opts that I currently know.

-> means LG UP to lafd

<- means lafd to LG UP

All opcodes are 8 DWORDs (a DWORD is 4 bytes)

All arguments, options, and the CRC check are little endian

4 bytes for the command

4 bytes for arg0 (usually a sub-command)

4 bytes for arg1

4 bytes for opt0

4 bytes for opt1

4 bytes for payload length

4 bytes for a CRC16 check against the opcode command, arguments, options and payload replacing zeros for the CRC16 for the check.

4 bytes for a two's complement of the command

[LAF] laf_message.command =

[LAF] laf_message.arg0 =

[LAF] laf_message.arg1 =

[LAF] laf_message.arg_opt0 =

[LAF] laf_message.arg_opt1 =

[LAF] laf_message.data_length =

[LAF] laf_message.data_check =

[LAF] laf_message.magic =

Payload Two's complement
CMD ARG0 ARG1 OPT0 OP1 Length CRC16 of command
-> HELO 01 00 00 01 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 4c 3f 00 00 b7 ba b3 b0 // Must send this so that you can even talk -- HELO + version number
<- HELO 04 00 00 01 01 00 00 10 00 00 80 00 02 00 00 00 00 00 00 00 80 f2 00 00 b7 ba b3 b0 // lafd replies with the its version, but the version that it will accept. In this case lafs is version 1.0.0.4 but LG UP is version 1.0.0.1

-> KILO CENT 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e3 7b 00 00 b4 b6 b3 b0 // This is a start challenge request
<- KILO CENT ab 36 e4 78 00 00 00 00 00 00 00 00 00 00 00 00 21 7e 00 00 b4 b6 b3 b0 // This is the reply from lafd -- the challenge

-> KILO METR 00 00 00 00 04 00 00 00 00 00 00 00 10 00 00 00 fd d5 00 00 b4 b6 b3 b0 // fc d6 2f a6 f7 69 7a 72 cb 98 d3 12 e2 68 08 66 // LG UP sends this based on what lafd sent in KILO CENT -- the response (this will be documented in a seperate post)
<- KILO METR 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 2f 5d 00 00 b4 b6 b3 b0 // lafd verifying that the response was correct

-> KILO CENT 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e3 7b 00 00 b4 b6 b3 b0 // This is a start challenge request
<- KILO CENT be 7f 89 73 00 00 00 00 00 00 00 00 00 00 00 00 aa 48 00 00 b4 b6 b3 b0 // -- challenge

-> KILO METR 00 00 00 00 02 00 00 00 00 00 00 00 10 00 00 00 e1 24 00 00 b4 b6 b3 b0 // e7 84 44 ca f4 be fe 92 2d e6 cf be b1 75 55 0f // -- response
<- KILO METR 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 2f 5d 00 00 b4 b6 b3 b0 // lafd verifying that the response was correct

--- Full transaction for a write to /dev/block/sde. In this case I wrote the LAF partition ---

At the end of each restricted opcode, a CLSE is issued. So, technically this CLSE was the end of the last opcode, but I am including it for clarity

-> CLSE 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 57 cb 00 00 bc b3 ac ba // Close file descriptor 0x28. CLSE is the opcode, and arg0 is the file descriptor.
<- CLSE 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 57 cb 00 00 bc b3 ac ba // Close ACK

-> KILO CENT 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e3 7b 00 00 b4 b6 b3 b0 // start challenge
<- KILO CENT e4 28 71 68 00 00 00 00 00 00 00 00 00 00 00 00 3d 6e 00 00 b4 b6 b3 b0 // challenge as arg0
-> KILO METR 00 00 00 00 02 00 00 00 00 00 00 00 10 00 00 00 75 19 00 00 b4 b6 b3 b0 // a5 5e b4 58 4f ff f5 15 a0 53 a7 bf ee 2b 50 b5 // response as payload
<- KILO METR 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 2f 5d 00 00 b4 b6 b3 b0

-> OPEN 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 01 00 00 84 2b 00 00 b0 af ba b1 // And then the payload. // /dev/block/sde 00:06:fb:0f:00:00:30:b0:9d:06:42:00:00:00:00:00:00:00:00:00:00:00:04:00:00:00:30:b0:9d:06:00:00:00:00:dd:60:1a:10:48:52:9f:06:d8:4f:9d:06:06:00:00:00:00:00:00:00:58:52:9f:06:00:00:00:00:0c:00:06:00:04:00:00:00:60:ea:ff:03:eb:27:00:10:dc:ea:ff:03:30:b0:9d:06:64:ea:ff:03:41:76:1a:10:00:00:61:06:00:00:00:00:30:b0:9d:06:c0:ea:ff:03:be:e4:09:10:30:b0:9d:06:b6:d9:ee:d8:48:00:00:00:bc:52:a7:06:db:e4:09:10:30:b0:9d:06:30:c0:9d:06:30:c0:9d:06:00:00:00:00:dc:ea:ff:03:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:0f:00:00:00:00:00:00:00:b6:d9:ee:d8:fc:ea:ff:03:f0:9a:1d:10:48:00:00:00:10:00:00:00:08:eb:ff:03:7b:8c:03:10:10:00:00:00:8a:8c:03:10:7e:d8:ee:d8:ba:8c:03:10:00:6f:6f:74:00:d9:ee:d8:a0:e8:ff:03:9c:ec:ff:03:02:00:02:00:b6:81:00:00:00:00:b6:01:00:00:00:00:00:00:00:00
<- OPEN 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 51 7c 00 00 b0 af ba b1

-> WRTE 28 00 00 00 06 00 00 00 00 00 00 00 18 00 00 00 00 00 30 00 59 25 00 00 a8 ad ab ba // This also includes payload
-> // Just payload no opcode or header
-> // payload
-> // payload until
-> 1f e3 27 c1 a6 c6 82 ec 68 34 61 94 a9 e4 82 ff 6f d7 5a 7a 04 b1 ec cf c2 b4 2b 57 22 d6 37 be // Checksum?

This is what is holding me up. This is the last frame in a WRTE opcode. I thought it was just trailing data, but it is consistently 32 bytes and is not an opcode. SHA256? If so, is it a hash of just the payload, or the payload and the initial header?

<- WRTE 28 00 00 00 00 60 00 00 08 00 00 00 00 00 00 00 00 00 00 00 ff 6d 00 00 a8:ad:ab:ba // Reply from lafd verifying the write

-> WRTE 28 00 00 00 06 03 00 00 00 00 00 00 09 00 00 00 00 00 30 00 a7 5e 00 00 a8 ad ab ba
-> // Payload
-> // Payload
-> // Payload until
-> be af 4a 3f 0c 5b d5 43 28 69 6e 43 f3 d9 b0 36 6f c8 74 26 ec d4 4d 19 29 80 12 8f 2e 6d 7f a8 // Checksum
<- WRTE 28 00 00 00 00 60 30 00 08 00 00 00 01 00 00 00 00 00 00 00 70 a4 00 00 a8 ad ab ba

-> WRTE 28 00 00 00 06 06 00 00 00 00 00 00 09 00 00 00 00 00 30 00 b3 d6 00 00 a8 ad ab ba
-> // Payload
-> // Payload
-> // Payload until
-> 2a:08:6f:95:86:fb:ef:97:5c:2e:a2:8c:e0:89:5e:71:f3:a7:3f:97:0a:db:ef:55:8a:f8:60:8a:34:b2:ef:3e //Checksun
<- WRTE 28 00 00 00 00 60 60 00 08 00 00 00 01 00 00 00 00 00 00 00 d1 6c 00 00 a8 ad ab ba

-> WRTE 28 00 00 00 06 09 00 00 00 00 00 00 09 00 00 00 00 00 30 00 54 75 00 00 a8 ad ab ba
-> // Payload
-> // Payload
-> // Payload until
-> 32:5e:ba:b0:0d:1e:04:7d:3a:2c:ed:90:d9:81:b8:c9:42:e6:31:df:88:f7:19:cf:19:fc:3e:3a:6b:a7:67:af // Checksum
<- WRTE 28 00 00 00 00 60 90 00 08 00 00 00 01 00 00 00 00 00 00 00 23 3d 00 00 a8 ad ab ba

-> WRTE 28 00 00 00 06 0c 00 00 00 00 00 00 09 00 00 00 00 00 30 00 19 81 00 00 a8 ad ab ba
-> // Payload
-> // Payload
-> // Payload until
-> cb:06:8b:a5:be:25:df:f2:60:05:87:f3:d3:a5:0e:3d:a7:8c:f5:f5:3f:34:68:31:b1:07:ab:d7:be:ac:ba:e3 // Checksum
<- WRTE 28 00 00 00 00 60 c0 00 08 00 00 00 01 00 00 00 00 00 00 00 82 f5 00 00 a8 ad ab ba

-> WRTE 28 00 00 00 06 0f 00 00 00 00 00 00 29 00 00 00 d6 47 0e 00 74 5d 00 00 a8 ad ab ba
-> // Payload
-> // Payload
-> // Payload
NO CHECKSUM FOR THE FINAL WRITE?!?!? Is it included in the payload?!?
<- WRTE 28 00 00 00 00 60 f0 00 08 00 00 00 01 00 00 00 00 00 00 00 1d b2 00 00 a8 ad ab ba

Sorry for the formatting, the code tags didn't work out well, but the forum strips extra spacing without them. I will try and clean it up.

So, there are 3 things that I still need to solve to make this work:

1 - The checksum between write blocks

2 - The fact that there is no checksum in the final write block unless it is in the payload

3 - What the payload of the OPEN opcode means. There is a payload for both reading and writing, but without supplying it, I am able to read, so this is a "maybe".

-- Brian