We've been doing a RPi CM3 Computer Board projet since awhile and we are done with the hardware part, but the software part makes me frankly depressed as of late.
I'm trying to make a small software to flash RPi CM3, so that our production team can flash about a hundred of them each day.
What I don't understand is how can I also checksum the eMMC flash for quality control, right after flashing?
If I do (granted the CM3 was rpiboot'ed properly and is connected to my computer as a USB MSD, designed by /dev/sdb under linux):
Code: Select all
dd if=./sdcard.img of=/dev/sdb conv=fsync
Code: Select all
#define _GNU_SOURCE
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <zlib.h>
int main(int argc, char **argv) {
int fd;
ssize_t numRead;
size_t length, alignment;
off_t offset;
char *buf;
const char *img_file = "./sdcard.img";
const char *dev_file = "/dev/sdb";
struct stat img_stat;
stat(img_file, &img_stat);
length = img_stat.st_size;
offset = 0;
alignment = 4096;
fd = open(dev_file, O_RDONLY | O_DIRECT);
if (fd == -1) {
printf("error: open");
return 1;
}
/* memalign() allocates a block of memory aligned on an address that
is a multiple of its first argument. By specifying this argument as
2 * 'alignment' and then adding 'alignment' to the returned pointer,
we ensure that 'buf' is aligned on a non-power-of-two multiple of
'alignment'. We do this to ensure that if, for example, we ask
for a 256-byte aligned buffer, we don't accidentally get
a buffer that is also aligned on a 512-byte boundary. */
buf = memalign(alignment * 2, length + alignment);
if (!buf) {
printf("error: memalign");
return 1;
}
buf += alignment;
if (lseek(fd, offset, SEEK_SET) == -1) {
printf("error: lseek");
return 1;
}
numRead = read(fd, buf, length);
if (numRead == -1) {
printf("error: read");
return 1;
}
printf("Read %ld bytes\n", (long)numRead);
Here are my questions.
- When resetting USB power and doing a new rpiboot, the checksum are different, despite the partitions being correct. I suppose this is some kind of wear leveling/TRIM/block redordering done by the eMMC? Would there be a way to circumvent this? Basically be able to checksum the flash even after a power off? TL;DR How can we checksum N bytes on the eMMC consistently?
- When using dd, the checksum is often wrong (after writing with fsync) even though power wasn't turned off. On the other hand, when using something like usb-creator-gtk (on Ubuntu), the checksum is systematically correct. Checking their source code, it seems the latter software relies on udisks. I wonder if anybody has an idea on why it doesn't work correctly with dd, but does with Canonical's usb-creator-gtk.
Any help would be greatly appreciated.