Last active
September 19, 2021 14:07
-
-
Save gamelaster/c34c70261692694904dc84df1c496879 to your computer and use it in GitHub Desktop.
Sunxi SID eFuse burning code
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
/** | |
* 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