u-boot:如何从Linux用户空间访问“ bootcount”?

时间:2018-07-17 03:30:12

标签: c beagleboneblack u-boot

我正在尝试使用u-boot's "bootcount" feature在TI am335x设备(例如beaglebone黑色)上检测到多次失败的引导尝试。在TI / Davinci平台上,引导计数值存储在{{1}中}注册(source)。但是在Linux方面,我找不到任何将bootcount作为sysfs节点或设备公开的驱动程序,作为读取和重置值的一种方式。因此,(主线)内核似乎不支持此功能,但是我想知道是否可以从用户空间进行操作?

参考:

编辑:有效的实现方式

这是一个可行的解决方案,但是我有一个问题(请参阅下文...)

git ls-remote --heads git@github.com:user/repo.git existingbranch

现在,如果我将RTC_SCRATCH2的内存转换为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)); (如下所示),以避免以后进行类型转换,则我读回的值不正确(mmap不匹配):

uint32_t *

当我使用BOOTCOUNT_MAGICuint32_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)); 是否仍保持相同的值?

完整来源可以是found on Github

1 个答案:

答案 0 :(得分:2)

  

当我使用valuint32_t *mem是否仍保持相同的值?

如果您使用了正确的指针算法(没有使用过),那么您将获得正确的结果。

<pointer> + <scaler>的C表达式中,将<scaler>表示为一个大小与指针类型相同的数量(例如sizeof(struct foo))。
仅当指针是字节指针时,<scaler>才表示字节数。

如果我们有一个数组x,该数组由结构的100个元素组成,例如

struct foo x[100];

该数组的名称可用作指针。
因此,数组的第十个元素的地址可以引用为&x[9](x + 9)


所以在您的第一个代码示例

unsigned char *mem ...

mem被声明为字节指针。
因此,

中的指针计算
unsigned char *scratch2 = mem + page_offset;

产生期望的结果,因为sizeof(unsigned char)为1(字节),并且page_offset以字节数表示。


但是在第二个代码示例中

uint32_t *mem  ...

mem被声明为指向4字节字的指针。
因此

中的指针计算相同
unsigned char *scratch2 = mem + page_offset;

等同于

unsigned char *scratch2 = (unsigned char *)mem + (sizeof(uint32_t) * page_offset);

其中sizeof(uint32_t)是4(字节),并且所应用的偏移量是您预期的四倍。
这是因为page_offset仍然是字节数,但是在原始表达式中将其视为指针类型的缩放器计数,即4字节字。
您不能简单地更改指针类型(即从char更改为int),并期望指针算术不受影响。
当您将mem更改为uint32_t *时,指针计算需要重新编码以将字节偏移量转换为四字节偏移量:

unsigned char *scratch2 = mem + (page_offset / sizeof(uint32_t));

您可以使用 printf()报告memscratch2和其他指针计算的值来确认这些语句(或调试代码)。