Reading From DCD or Flash Memory

Hi,

I’m trying to figure out how to read from DCD1 or more exactly trying to get the Server Public Key to read out the Address and also to read what mode the Server connection is in (IE if it’s in UDP or TCP).

The nearest search I’ve found is from [Reading RSA Private Key from DCT with user space firmware] but this user has had no reply.

Can anyone help?

Cheers

Hi @johnnyfp

I spent some time tonight digging the GitHub sources and don’t think you can do this easily today without building locally (i.e. run gcc on your computer) and possibly only in monolithic mode (one big chuck-o-software instead of the normal multi part system and user software). If you do that, it is easy to call the right functions but they are not exposed to the user level right now.

There are some notes in the source that the “get” should be brought out to the user software level but it is not there yet. In the system code, the DCT area has to be unlocked/locked for safety and has a sector scheme for flash writes so it is not as simple as reading at a particular location.

You can set these values using the System.set() command doc’ed here:

https://docs.particle.io/reference/firmware/photon/#system-config-set-

I believe you could also read this via DFU mode when connected to a PC. The DFU code knows how to find the valid DCT data.

The DCT is stored in FLASH sectors so that unless you know which sector is currently valid, it is hard to use the offsets given in the memory map to find the data you want. This code below dumps the entire 16kb region to USB serial and when I wrote it, I thought that the sectors were 4096 bytes but that does not look to be how it works since the public key is 1438 bytes from what I called sector 2 on my device whereas the offset given in the doc is 2082. I have looked at the cloud public key for Photon in hex and it is easy to find the key in the dump by eye, but without the sector valid information, it is difficult to find programmatically. I’m sure you could dig around the sources and understand how it works under the hood, but I think you really want Particle to provide an API similar to System.set()

char data;

void setup() {
    Serial.begin(9600);
}

void loop() {
    delay(10000);
    Serial.println("Starting read to DCT:");
    for(int sector=0;sector<4;sector++) {
        char *p = (char *)(0x8004000+(sector*4096));
        Serial.print("Sector:");
        Serial.println(sector);
        for(int i=0;i<4096;i++) {
            data = p[i];
            Serial.print(data,HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
}
1 Like

This post has the weird offsets you need in order to be able to read the data out. You first need to figure out whether you’re using DCT1 or DCT2 (the one that’s not blank with 0xffs), then compute the correct address to read from. Just create a pointer to the 0x08xxxxx address and read it like regular RAM.

1 Like

Thanks @rickkas7 ! Great information as always-demystifying the weirdness!

I will write up a little helper tonight and post it here.

1 Like

Thanks! Found the data I needed.

So what I don’t understand is the data was in DCD2 and not DCD1. What tells the system to use the second page over the first?

Also why is there is funny “Hidden” offset of 0x1d7c and why is this just not put in the documents that the DCD1 is actually at offset 0x8005D7C, is this a compile time calculation? Which means that it could change in a future or alternative compiler version.

The data is in either DCT1 or DCT2 depending on how many times it is written. Since this is FLASH memory, the other area is erased (all 0xFF) and the active area holds the data. Then if it needs to be rewritten, the erased area is written and the previously active area is erased. With FLASH memory you can’t rewrite directly in the same area.

As to the magic offset–that defies logic in my opinion.

The layout of the DCT area has grown over time but I don’t think there will be backwardly incompatible changes.

Ok that makes sense. But how does the firmware determine which area to use? Does it read the entire area and check that everything is 0xFF then determines that it needs to go to the other page? Or does it read one byte?

Also Docs for Electron call this area DCD while Photon call it DCT which is correct?

It’s more than a byte and less than the whole thing checked for 0xff. There’s also a checksum in 0.7.0 and later.

Also, remember that flash reads are fast on the STM32, you can read data out of the DCT as fast as you can read it out of RAM. Code executes directly off flash, it’s not copied into RAM. And the DCT flash is the same as the rest of the flash.

Under ideal conditions one sector will be all 0xff and the other will have data. The only case when both have data are if you managed to crash or reset while the sector was being copied to the other sector while updating. Basically, whenever you set a value in the DCT, the entire sector is copied over to the other one, with the changes made, and then the old one erased to 0xff.

DCD (device configuration data, the generic term) and the WICED DCT (device configuration table) are used pretty much interchangeably.

2 Likes

As for the mystery offset, I couldn’t even figure it out by reading the code. I ended up dumping out DCTs and searching for byte sequences that I knew, like keys and the device serial until I found the magic offset. It’s probably part of WICED, as I believe it has the beginning part of the DCT, and the Particle-specific stuff is after it, at the mystery offset.

2 Likes

So just to put a spanner in the works with this odd offset. On the electron the “funny Hidden” offset seems to be only 0x8

And to make matters worse, it seems that the other area is NOT erased to all 0xFF. Both DCT on an electron have very similar values except in the reserved2 area where there as subtle differences.