I know, holy thread necro and all that, but I've been apparently wasting my time reverse-engineering the 3.17 firmware since there was no (to my ability to find) public information on any of this stuff. That's over here:
https://www.arcade-projects.com/threads/netboot-naomi-with-eeprom-presets.18977/page-2
I am replying since I can explain basically every part of that command, so hopefully for the curious I can demystify why it does what it does and what's actually going on. Okay, so, the bytes are as such:
Code:
00 00 00 01 1a 00 81 04 01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00
Let's break it down. The net dimm protocol uses the first 4 bytes as a packet header. The first two bytes are little-endian length of any additional packet data. The next byte is a flag byte. I don't know what the top bit is supposed to signify, but the bottom bit is set to 1 for the "last" packet and 0 for any additional. Most packets do not use this since most of them are standalone. The dimm send and dimm receive packets do. This is why the dimm send packet has a "mark" bit in triforcetools.py. Similarly, if you request more than 0x2000 bytes from the dimm receive packet, the firmware will split it into multiple responses each with maximum length of 0x2000 data, setting the "last" flag to 0 for all packets it sends except for the final packet. The final byte is the packet type. If there is a length set, then "length" bytes will follow, and should be viewed as data for that packet.
This holds for responses as well, so you can decode any response you get from the net dimm in a similar manner.
Okay, so now we have this:
Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.
1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 f0 ff fe 3f 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 26 bytes of data (as specified in length above) for this packet.
Okay cool. First, packet 0x01 is a "NOP" packet. In fw 3.17 the handler simply returns success, does not matter. I don't know why tools send this, maybe in some version of firmware this enabled some communications? Anyway, triforcetools does not bother with this, but official tools send this.
It is safe to drop this from the request, it does nothing. Second, packet 0x04 is "send to dimm". It is the same packet that is used for uploading games to the DIMM, funny enough. It has access to the entire memory space for the dimm, but it also has access to the special pool of memory reserved for the net dimm itself. Since this is battery-backed, anything written here gets stored until your battery dies. It has the following format. First 4 bytes are a little-endian integer specifying the sequence number. This can be ignored or set to whatever you want in practice, dimm fw 3.17 ignores this. However, official tools start at sequence number 1 and increment every data packet sent. Similarly, if you use command 0x05 (receive from dimm) and you ask for too much data, when it splits the response into multiple packets the sequence number will be incremented for each packet, starting at 1. The second 4 bytes are the memory address to write to. Normally you start at 0 for game upload. Special system config lives at the top of RAM. The net dimm firmware, at least in 3.17 will calculate the maximum memory size based on the inserted memory modules, subtract some amount for its own memory and always stick thet system config there, so
the addresses are the same no matter how much memory you put in your dimm. The address here is "0x3ffefff0". Note that this is mirrored. In my own tools, I send instead to "0xfffefff0" and it works just the same. The next 2 bytes are always zero. At least in fw 3.17 it does not even attempt to parse them. They are just there to be useless. The remaining data (packet length - 10 bytes) is the bytes that get written starting at the memory address.
Okay, so now we have this:
Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.
1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0.
Okay cool, so this is how that packet works. But why that particular address? What makes it so special. For that, lets go to 3.17 firmware reverse engineering. In the bootup state machine we find this:
I've renamed a lot of stuff from disassembly garbage names to make the code more clear. The top circled bit looks up the base dimm address. The second chunk of code calls the vxWorks DIMM read driver function with the address base + 0xfffefff0 (simply 0xfffefff0 from the send to dimm/receive from dimm packet's perspective). Remember how I said that was mirrored. That's the same address as 0x3ffefff0. Okay cool. It reads 16 bytes into the "memory values" buffer which is set currently to 4 32-bit values. Then, the critical bit of code compares the first 32-bit value to the bitwise inverse of the 3rd, and the 2nd 32-bit value to the bitwise inverse of the 4th. If they match, then it prints "non crc mode" to the debug console serial and sets the system CRC status to 5. Otherwise it goes on to CRC the data that is in the DIMM.
Side node, the CRC status is retrievable using a "read from dimm" command to another system memory location "0xfffeffe0". You can read it with the "read from dimm" command 0x05. It has the following values: 0 or 1 - we have not finished checking CRC. The system will be displaying "NOW CHECKING" on the screen. 2 - CRC is good, game should boot, 3 - CRC is bad, don't boot, 4 - Your DIMM memory has something wrong with it, 5 - CRC checking is disabled, we will boot without checking.
Okay, cool, so let's put this all together.
Code:
00 00 = packet length (0 bytes of data)
00 = packet flags (do not care for this packet type)
01 = packet type. 01 is a "NOP" packet.
1a 00 = packet length (26 bytes of data)
81 = packet flags (do not know what 0x80 is, 0x01 means this is the last packet for uploading data)
04 = packet type. 04 is "send to dimm" packet.
01 00 00 00 = sequence number 1
f0 ff fe 3f = please write to address 0x3ffefff0
00 00 = useless short, maybe for some expansion in the future?
ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 = 16 bytes to write starting at address 0x3ffefff0. The first and 3rd "integer" are bitwise opposite (0xffffffff = ~0x00000000) and the second and 4th "integer" are also bitwise opposite! The magic flag values to make CRC checking disable. So, in reality according to the code we should be able to put anything we want here as long as the 3rd and 4th 4-byte integers are bitwise opposite of the 1st and 2nd integers respectively. It also tells us why setting all 0's here re-enables the CRC check.
And that's why this packet does what it does. For more comments on what's actually going on, when I reverse-engineered the firmware because I couldn't find any public documentation, I wrote a TON of documentation here:
https://github.com/DragonMinded/netboot/blob/trunk/netboot/netboot.py As another aside, the "set information" packet that sends the CRC and length is just writing to special location 0xffff0000 with a CRC32 over the first 28 bytes in byte location 28-32. So you can read 4 bytes back at location 0xffff0004 to get the set size of the game that's running. You can also read 0xffff0000 to get the CRC of the game, but that's already available in the "get information" packet. There are probably a lot more system values in that section that I haven't begun to reverse-engineer. For instance the net dimm firmware knows what target it is running on and I suspect that it might be possible to find that info somewhere in the system section.