Skip to content

Instantly share code, notes, and snippets.

@gamelaster
Last active September 19, 2021 14:07
Show Gist options
  • Save gamelaster/c34c70261692694904dc84df1c496879 to your computer and use it in GitHub Desktop.
Save gamelaster/c34c70261692694904dc84df1c496879 to your computer and use it in GitHub Desktop.
Sunxi SID eFuse burning code
/**
* Usage: <offset> <value>
*
* Tested on Allwinner H3. Burning to OEM_PROGRAM and NV2 works good, but to burning bits to NV1 area don't work.
* Use it at your own risk! I'm not responsible for any accidentally/wrongly blown fuses and voided warranties.
**/
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
static inline void writel(uint32_t val, void* addr)
{
*((volatile uint32_t*)addr) = val;
}
static inline uint32_t readl(void* addr)
{
return *((volatile uint32_t*) addr);
}
int main(int argc, char** argv)
{
uint32_t offset = (uint32_t)strtol(argv[1], NULL, 0);
uint32_t value = (uint32_t)strtol(argv[2], NULL, 0);
int fd;
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
printf("Failed to open /dev/mem\n");
return 1;
}
void* map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x01c14000 & ~MAP_MASK);
/* Code to read eFuse
uint32_t* virt_addr = map_base + (0x40);
uint32_t ctrl = (0x00) << 16;
ctrl |= (0xAC << 8) | (1 << 1);
*virt_addr = ctrl;
while ((*virt_addr) & (1 << 1)) {}
virt_addr = map_base + (0x60);
printf("Data: %X\n", *virt_addr); */
/* Code to write eFuse
virt_addr = map_base + (0x50);
*virt_addr = 0x000005BB;
virt_addr = map_base + (0x40);
uint32_t ctrl = (0x14) << 16;
ctrl |= (0xAC << 8) | (0x1);
printf("%X\n", ctrl);
*virt_addr = ctrl;
while ((*virt_addr) & (0x1)) {
printf("%X\n", *virt_addr);
}*/
// Writing to eFuses as made by Allwinner
void* SID_PRKEY = map_base + (0x50);
void* SID_PRCTL = map_base + (0x40);
uint32_t key_value = value;
uint32_t key_index = offset;
uint32_t reg_val;
#define SID_OP_LOCK (0xAC)
writel(key_value, SID_PRKEY);
reg_val = readl(SID_PRCTL);
reg_val &= ~((0x1ff<<16)|0x3);
reg_val |= key_index<<16;
writel(reg_val, SID_PRCTL);
reg_val &= ~((0xff<<8)|0x3);
reg_val |= (SID_OP_LOCK<<8) | 0x1;
writel(reg_val, SID_PRCTL);
while (readl(SID_PRCTL) & 0x1) {
;
}
reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
writel(reg_val, SID_PRCTL);
munmap(map_base, MAP_SIZE);
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment