view target-utils/loadagent/intelflash.c @ 769:f18db0f00ad8
target-utils: simagent application started
author |
Mychaela Falconia <falcon@freecalypso.org> |
date |
Fri, 12 Mar 2021 06:40:24 +0000 (2021-03-12) |
parents |
b34384991094 |
children |
|
line source
/*
* This module implements the INFB and INFW commands for programming
* Intel-style flash memories. The syntax and operation are exactly
* the same as the AMD flash counterparts AMFB and AMFW.
*
* The intel-rewrite-sector command (erase+program with a minimum of
* vulnerability for brickable-boot Compal phones) is implemented
* here as well.
*/
#include <sys/types.h>
#include "types.h"
static u32 base_addr;
void
cmd_INFB(argbulk)
char *argbulk;
{
char *argv[2];
u_long addr;
if (parse_args(argbulk, 1, 1, argv, 0) < 0)
return;
if (parse_hexarg(argv[0], 8, &addr) < 0) {
printf("ERROR: argument must be a valid 32-bit hex address\n");
return;
}
if (addr & 1) {
printf("ERROR: odd address\n");
return;
}
base_addr = addr;
}
void
cmd_INFW(argbulk)
char *argbulk;
{
char *argv[3], *s;
u_long offset;
volatile u16 *flashptr;
u32 datum; /* needs to be u32 for decode_hex_digits() */
u16 stat;
int i;
if (parse_args(argbulk, 2, 2, argv, 0) < 0)
return;
if (parse_hexarg(argv[0], 8, &offset) < 0) {
printf("ERROR: offset argument must a valid 32-bit hex value\n");
return;
}
if (offset & 1) {
printf("ERROR: odd offset argument\n");
return;
}
flashptr = (volatile u16 *)(base_addr + offset);
for (s = argv[1]; *s; flashptr++, s += 4) {
if (decode_hex_digits(s, 4, &datum) < 0) {
printf("ERROR: bad INFW hex string argument\n");
return;
}
*flashptr = 0x40;
*flashptr = datum;
for (i = 10000; i; i--) {
stat = *flashptr;
if (stat & 0x80)
break;
}
if (!i) {
printf("ERROR: flash write timeout at %08X\n",
(u_long) flashptr);
return;
}
if (stat & 0x10) {
printf("ERROR: program operation failed at %08X\n",
(u_long) flashptr);
return;
}
}
}
intelflash_binary_prog(offset, nwords, data)
u32 offset;
unsigned nwords;
u16 *data;
{
volatile u16 *flashptr;
u16 stat;
int i;
flashptr = (volatile u16 *)(base_addr + offset);
while (nwords) {
*flashptr = 0x40;
*flashptr = *data;
for (i = 10000; i; i--) {
stat = *flashptr;
if (stat & 0x80)
break;
}
if (!i) {
serial_out(0x15); /* NAK */
printf("ERROR: flash write timeout at %08X\n",
(u_long) flashptr);
return(-1);
}
if (stat & 0x10) {
serial_out(0x15); /* NAK */
printf("ERROR: program operation failed at %08X\n",
(u_long) flashptr);
return(-1);
}
flashptr++;
data++;
nwords--;
}
return(0);
}
void
cmd_INFWB()
{
binary_flash_prog_main(intelflash_binary_prog);
}
void
cmd_intel_rewrite_sector(argbulk)
char *argbulk;
{
char *argv[4];
u_long srcaddr, dstaddr, len;
const u16 *srcptr;
volatile u16 *flashptr;
u16 stat;
if (parse_args(argbulk, 3, 3, argv, 0) < 0)
return;
if (parse_hexarg(argv[0], 8, &srcaddr) < 0) {
invarg: printf("ERROR: invalid argument(s)\n");
return;
}
if (parse_hexarg(argv[1], 8, &dstaddr) < 0)
goto invarg;
if (parse_hexarg(argv[2], 8, &len) < 0)
goto invarg;
if (srcaddr & 1 || dstaddr & 1 || len & 1) {
printf("ERROR: all 3 arguments must be even\n");
return;
}
srcptr = (const u16 *) srcaddr;
flashptr = (volatile u16 *) dstaddr;
/* unlock the flash sector first */
*flashptr = 0x60;
*flashptr = 0xD0;
/* clear SR */
*flashptr = 0x50;
/* erase */
*flashptr = 0x20;
*flashptr = 0xD0;
/* wait for erase completion */
for (;;) {
stat = *flashptr;
if (stat & 0x80)
break;
}
if (stat & 0x30) {
printf("ERROR: erase operation failed!\n");
return;
}
/* now program the new content */
for (; len; len -= 2) {
*flashptr = 0x40;
*flashptr = *srcptr++;
for (;;) {
stat = *flashptr;
if (stat & 0x80)
break;
}
flashptr++;
}
printf("Operation complete, final SR: %02X\n", stat & 0xFF);
}