Skip to content

Instantly share code, notes, and snippets.

@carlocaione
Created March 18, 2016 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlocaione/9294411dfc18292bc84b to your computer and use it in GitHub Desktop.
Save carlocaione/9294411dfc18292bc84b to your computer and use it in GitHub Desktop.
#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