簡體   English   中英

u-boot:如何從Linux用戶空間訪問“ bootcount”?

[英]u-boot: how to access 'bootcount' from linux userspace?

我正在嘗試使用u-boot的“ bootcount”功能來檢測TI am335x設備(例如beaglebone黑色)上的多次引導失敗嘗試。在TI / Davinci平台上,bootcount值存儲在RTC_SCRATCH2寄存器( )中。 。 但是在Linux方面,我找不到任何將bootcount作為sysfs節點或設備公開的驅動程序,作為讀取和重置值的一種方式。 因此,似乎(主線)內核不支持此功能,但我想知道是否可以從用戶空間進行?

參考:

編輯:一個可行的實現

這是一個可行的解決方案,但是我有一個問題(請參閱下文...)

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_MAGIC不匹配):

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));

當我使用uint32_t *mem時, val仍應保持相同的值?

完整的源代碼可以在Github找到

當我使用uint32_t *mem時, val仍應保持相同的值?

如果您使用了正確的指針算術(沒有使用過),那么您將獲得正確的結果。

<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和其他指針計算的值來確認這些語句(或調試代碼)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM