Created
March 18, 2016 17:22
-
-
Save carlocaione/9294411dfc18292bc84b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <getopt.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) | |
#define EFUSE_RAW_DEVICE_NAME "/dev/efuse_raw" | |
#define MMC_DEVICE_NAME "/dev/mmcblk1boot0" | |
#define MAX_EFUSE_BYTES 512 | |
static int fd; | |
enum { | |
DEV_EFUSES = 0, | |
DEV_MMC, | |
DEV_NUM, | |
}; | |
static struct dev_item_t { | |
char *desc; | |
char *file; | |
int rewritable; | |
} dev_item[] = { | |
[DEV_EFUSES] = { "efuses", EFUSE_RAW_DEVICE_NAME, 0 }, | |
[DEV_MMC] = { "MMC", MMC_DEVICE_NAME, 1 }, | |
}; | |
static struct efuse_item_t { | |
char *desc; | |
loff_t pos; | |
size_t count; | |
int nissues; | |
int dev_idx; | |
} efuse_item[] = { | |
{ "whole efuses space", 0x0, MAX_EFUSE_BYTES, 1, DEV_EFUSES}, | |
/* field specific (efuses) */ | |
{ "endless magic value", 0x150, 2, 1, DEV_EFUSES }, | |
{ "endless product version", 0x162, 1, 1, DEV_EFUSES }, | |
{ /*sentinel */ }, | |
}; | |
static char short_options[] = "hld:w:"; | |
static struct option long_options[] = { | |
{ "help", 0, 0, 'h' }, | |
{ "list", 0, 0, 'l' }, | |
{ "id", 1, 0, 'd' }, | |
{ "write", 1, 0, 'w' }, | |
{ 0, 0, 0, 0 }, | |
}; | |
static void usage(void) | |
{ | |
printf("Usage: efuse_tool_raw [OPTIONS]... [DATA]...\n" | |
"\n" | |
" -h, --help help\n" | |
" -l, --list list efuse entries\n" | |
" -d, --id select efuse entry\n" | |
" -w, --write write data to efuse entry\n" | |
"\n" | |
" Examples:\n" | |
" (Reading the whole efuses content) efuse_tool_raw -d 0\n" | |
" (Reading the 3rd entry) efuse_tool_raw -d 3\n" | |
" (Writing data to the 2nd entry) efuse_tool_rat -d 2 -w aa:bb\n"); | |
exit(1); | |
} | |
static void print_list(void) | |
{ | |
int i = 0; | |
struct dev_item_t *dev; | |
printf("\n"); | |
for (; efuse_item[i].count; i++) { | |
dev = &dev_item[efuse_item[i].dev_idx]; | |
printf("id = %2d] %-25s (%s)\t (pos = 0x%04x, count = %-3d, #issues = %d, dev = %s)\n", | |
i, efuse_item[i].desc, dev->desc, (int) efuse_item[i].pos, | |
(int) efuse_item[i].count, efuse_item[i].nissues, | |
dev->file); | |
} | |
printf("\n"); | |
} | |
static void dump_buf(char *pbuf, int idx, int issue) | |
{ | |
int i; | |
printf("[ %s - issue %d ]\n", efuse_item[idx].desc, (issue + 1)); | |
for (i = 0; i < efuse_item[idx].count; i++) { | |
if (!(i % 16)) | |
printf("\n%04x: ", i); | |
printf("%02x ", pbuf[i]); | |
} | |
printf("\n\n"); | |
} | |
static int read_item(char *pbuf, int idx, int issue) | |
{ | |
loff_t pos = efuse_item[idx].pos; | |
size_t size, count = efuse_item[idx].count; | |
pos += (issue * count); | |
if (lseek(fd, pos, SEEK_SET) < 0) { | |
fprintf(stderr, "Error in seeking to %d\n", (int) pos); | |
return 1; | |
} | |
size = read(fd, pbuf, count); | |
if (size != count) { | |
fprintf(stderr, "Error during reading\n"); | |
return 1; | |
} | |
return 0; | |
} | |
static int write_item(char *pbuf, size_t size, int idx, int issue) | |
{ | |
loff_t pos = efuse_item[idx].pos; | |
size_t wsize, count = efuse_item[idx].count; | |
printf("Writing to issue: %d\n", (issue + 1)); | |
if (count != size) { | |
fprintf(stderr, "Wrong data size\n"); | |
return 1; | |
} | |
pos += (issue * count); | |
if (lseek(fd, pos, SEEK_SET) < 0) { | |
fprintf(stderr, "Error in seeking to %d\n", (int) pos); | |
return 1; | |
} | |
wsize = write(fd, pbuf, count); | |
if (wsize != size) { | |
fprintf(stderr, "Error during writing\n"); | |
return 1; | |
} | |
return 0; | |
} | |
static int write_id(char *wbuf, size_t size, int idx) | |
{ | |
int i, j; | |
int wissue = 0; | |
int found = 0; | |
char *pbuf; | |
struct dev_item_t *dev = &dev_item[efuse_item[idx].dev_idx]; | |
if (dev->rewritable) | |
return write_item(wbuf, size, idx, 0); | |
if (idx > ARRAY_SIZE(efuse_item)) { | |
fprintf(stderr, "Index %d does not exist\n", idx); | |
return 1; | |
} | |
if (!(pbuf = calloc(sizeof(char), efuse_item[idx].count))) { | |
fprintf(stderr, "Not enough memory\n"); | |
return 1; | |
} | |
for (i = (efuse_item[idx].nissues - 1); i >= 0; i--) { | |
memset(pbuf, 0, efuse_item[idx].count); | |
if (read_item(pbuf, idx, i)) { | |
free(pbuf); | |
return 1; | |
} | |
for (j = 0; j < efuse_item[idx].count; j++) { | |
if (pbuf[j] != 0) { | |
found = 1; | |
break; | |
} | |
} | |
if (found) | |
break; | |
} | |
free(pbuf); | |
if (i == (efuse_item[idx].nissues - 1)) { | |
printf("No free slots remaining for writing\n"); | |
return 1; | |
} | |
wissue = found ? ++i : 0; | |
return write_item(wbuf, size, idx, wissue); | |
} | |
static int read_id(int idx) | |
{ | |
int i; | |
char *pbuf; | |
if (idx > ARRAY_SIZE(efuse_item)) { | |
fprintf(stderr, "Index %d does not exist\n", idx); | |
return 1; | |
} | |
if (!(pbuf = calloc(sizeof(char), efuse_item[idx].count))) { | |
fprintf(stderr, "Not enough memory\n"); | |
return 1; | |
} | |
for (i = 0; i < efuse_item[idx].nissues; i++) { | |
if (read_item(pbuf, idx, i)) { | |
free(pbuf); | |
return 1; | |
} | |
dump_buf(pbuf, idx, i); | |
} | |
return 0; | |
} | |
static int efuse_str_to_data(char *data_buf, char *str_buf) | |
{ | |
int trans_size = 0; | |
char ret, *p; | |
p = strtok(str_buf, ":"); | |
while (p && trans_size < MAX_EFUSE_BYTES) { | |
ret = (char) strtol(p, NULL, 16); | |
data_buf[trans_size] = ret; | |
p = strtok(NULL, ":"); | |
trans_size++; | |
} | |
return trans_size; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int c, idx = -1; | |
int ret = 0; | |
char pbuf[MAX_EFUSE_BYTES] = { 0 }; | |
size_t size = 0; | |
if (argc < 2 || argc > 5) | |
usage(); | |
while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { | |
switch (c) { | |
case 'l': | |
print_list(); | |
return 0; | |
case 'w': | |
size = efuse_str_to_data(pbuf, optarg); | |
break; | |
case 'd': | |
idx = atoi(optarg); | |
break; | |
default: | |
usage(); | |
} | |
} | |
if (idx < 0) { | |
fprintf(stderr, "Please, select an index\n"); | |
usage(); | |
} | |
fd = open(dev_item[efuse_item[idx].dev_idx].file, O_RDWR); | |
if (fd < 0) { | |
fprintf(stderr, "Error in opening %s\n", EFUSE_RAW_DEVICE_NAME); | |
return 0; | |
} | |
if (size) | |
ret = write_id(pbuf, size, idx); | |
else | |
ret = read_id(idx); | |
close(fd); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment