I'm trying to use u-boot's "bootcount" feature to detect multiple failed attempts to boot, on a TI am335x device (e.g. beaglebone black.) On TI/ Davinci platform, the bootcount value is stored in the RTC_SCRATCH2
register (source). However on the linux side, I can't find any driver that exposes bootcount as a sysfs node or device, as a means of reading and resetting the value. So it seems this is not supported in the (mainline) kernel, but I'm wondering if it's possible from userspace?
Ref:
- https://e2e.ti.com/support/embedded/linux/f/354/t/542737
- https://www.linuxquestions.org/questions/programming-9/am335x-read-and-write-some-rtc-registers-4175519888/
EDIT: a working implementation
Here's the meat of a working solution, however I have one question (see below...)
int fd = open("/dev/mem", O_SYNC | O_RDWR);
unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
if (mem == MAP_FAILED) {
perror("Can't map memory");
return -1;
}
unsigned char *scratch2 = mem + page_offset;
// Read value from SCRATCH2, verify magic number
uint32_t val = *(uint32_t *)scratch2;
//printf("%08" PRIx32 "\n", val);
// low two bytes are the value, high two bytes are magic
if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) {
fprintf(stderr, "Error: BOOTCOUNT_MAGIC does not match\n");
return -1;
}
printf("%d\n", (uint16_t)(val & 0x0000ffff));
Now, if I cast the mmap
'd memory as a uint32_t *
(shown below,) to avoid avoid later type casts, the value I read back is incorrect (the BOOTCOUNT_MAGIC
doesn't match):
uint32_t *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
uint32_t *scratch2 = mem + page_offset;
// Read value from SCRATCH2, verify magic number
uint32_t val = *scratch2;
//printf("%08" PRIx32 "\n", val);
// low two bytes are the value, high two bytes are magic
if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) {
fprintf(stderr, "Error: BOOTCOUNT_MAGIC does not match\n");
return -1;
}
printf("%d\n", (uint16_t)(val & 0x0000ffff));
Shouldn't val
still hold the same value when I use uint32_t *mem
?
Full source can be found on Github.