|
Zerocat Chipflasher
v0.4.3 (board-edition-1)
Flash free firmware to BIOS chips, kick the Manageability Engine.
|
Go to the documentation of this file.
46 #include "simpletext.h"
47 #include "simpletools.h"
144 outstr(
"Terminal Mode. Using reduced set of keys.\r\n");
171 outstr(
"You may now switch off the chipflasher board.\r\n");
172 for(
int n = 3; n; n--) {
187 sprinti(s,
"%s%d%s",
"Connected with ",
_cfg_baudrate,
" baud.\r\n");
215 unsigned int block_to_read;
217 sprinti(s,
"Block to read (hex 0..%x): ", blocks - 1);
219 block_to_read = getHex();
222 if(block_to_read >= blocks) {
228 unsigned char mode_screen_output;
229 mode_screen_output =
yes_no(
"Do you need output on screen", 0) << 7;
236 block_to_read * blocksize,
257 outstr(
"WIP_polling overflow.\r\n");
262 sprinti(s,
"WIP_polling: %d\r\n", r);
280 outstr(
"Out of range error!\r\n");
293 const unsigned char blockcmd
297 unsigned int first_block;
298 unsigned int last_block;
306 sprinti(s,
"First block to erase (hex 0..%x): ", blocks - 1);
308 first_block = getHex();
311 if(first_block >= blocks) {
318 sprinti(s,
"Last block to erase (hex %x..%x): ", first_block, blocks - 1);
320 last_block = getHex();
323 if( (last_block >= blocks) ||
324 (last_block < first_block) ) {
333 if(
yes_no(
"Sure to proceed", 0)) {
335 while(first_block <= last_block) {
336 unsigned int firstloc;
338 firstloc = first_block * blocksize;
346 sprinti(s,
"Block 0x%x... ", first_block++);
349 outstr(
"verifying...\r\n");
351 outstr(
"Verify error!\r\n");
388 unsigned char pswitch
392 if(
yes_no(
"Sure to proceed", 0)) {
421 unsigned char * key_is_valid,
428 keyinput = getChar();
429 while((
keymsg[keyid][1] != keyinput) &&
430 (
keymsg[keyid][3] != keyinput || keyinput ==
' ') &&
434 if(!(
keyreg & (1 << keyid))) {
447 outstr(
"The SPI bus has been powered off.\r\n");
474 unsigned char byte = 0;
477 unsigned char max_regno = 0;
478 unsigned char regno = 0;
479 unsigned char bitmask;
489 sprinti(s,
"Which config register to change (%d..%d)? ", 1, max_regno + 1);
491 regno = getDec() - 1;
492 if(regno < 0 || regno > max_regno) {
505 outstr(
"Bitname\tBit\tStatus\tValue?\r\n" \
506 "-------\t---\t------\t------\r\n" \
515 cstat =
byte & bit ?
'1' :
'0';
540 sprinti(s,
"New register value would be: %d\r\n",
byte);
543 if(
yes_no(
"Sure to proceed", 0)) {
547 sprinti(s,
"polling checks: %d\r\n",
WIP_polling());
610 }
while(powerup_extra--);
613 if(powerup_extra == 0xff) {
614 outstr(
"Power failure? Clip attached?\r\n");
626 outstr(
"No match in database.\r\n");
627 sprinti(s,
"Chip's JEDEC ID: 0x%06x\r\n",
id_JEDEC);
634 sprinti(s,
"Chip successfully detected: %s\r\n",
chip.
pspec->
name);
637 outstr(
"NOTE: The Status Register is not static, the SPI bus is kept powered until you quit.\r\n");
639 outstr(
"NOTE: You may set bit SRP in the status register to enable #WP control.\r\n");
650 unsigned int page_to_read;
652 sprinti(s,
"Page to read (hex 0..%x): ",
chip.
pages - 1);
654 page_to_read = getHex();
663 unsigned char mode_screen_output;
664 mode_screen_output =
yes_no(
"Do you need output on screen", 0) << 7;
667 unsigned int firstloc;
685 unsigned int startaddr;
689 startaddr = getHex();
698 unsigned int lastaddr;
700 sprinti(s,
"Last address (hex %08x..%08x): ", startaddr,
chip.
pspec->
chipsize - 1);
711 unsigned char mode_screen_output;
712 mode_screen_output =
yes_no(
"Do you need output on screen", 0) << 7;
720 lastaddr - startaddr + 1,
742 unsigned char mode_screen_output;
743 mode_screen_output =
yes_no(
"Do you need output on screen", 0) << 7;
773 if(
yes_no(
"Sure to proceed", 0)) {
776 outstr(
"verifying...\r\n");
778 outstr(
"Verify error!\r\n");
787 unsigned char screen_output;
788 screen_output =
yes_no(
"Do you need output on screen", 1);
794 if(
yes_no(
"Sure to proceed", 0))
833 outstr(
"Be aware: The Status Register 1 is not zero, some memory areas may be write protected.\r\n");
850 outstr(
"No SPI-plug detected!\r\n");
854 outstr(
"SPI-plug seems to be attached.\r\n");
871 unsigned char quit = 0;
872 unsigned char key_is_valid = 1;
891 outstr(
"\r\t\t\t\t\t\t\t\t0xFF: ");
894 sprinti(s,
"inline_%d\r\n", mode_0xff & 0b00011111);
944 unsigned char addrlen_in_bytes;
948 addrlen_in_bytes = 2;
950 addrlen_in_bytes = 1;
953 addrlen_in_bytes = 2;
955 addrlen_in_bytes = 3;
957 addrlen_in_bytes = 4;
960 return(addrlen_in_bytes << 3);
961 return(addrlen_in_bytes);
976 unsigned int reg =
keyreg;
1049 if(
keyreg & (k1 | k2 | k3)) {
1057 outstr(
"\r\t\t\t\t\t\t\t\t");
1123 unsigned int firstloc,
1124 unsigned int memsize
1127 unsigned char err = 0;
1168 unsigned char checksum;
1179 linebuf += sprinti(linebuf,
"S%01d", typeS->
bf.
num);
1183 linebuf += sprinti(linebuf,
"%02x", v);
1189 v = (linedat->
startaddr >> (n << 3)) & 0xff;
1190 linebuf += sprinti(linebuf,
"%02x", v);
1198 char byte = linedat->
buf[linedat->
rd++ & linedat->
mask];
1204 sprinti(linebuf,
"%02x\r\n", ~checksum & 0xff);
1285 struct tag_linedat r = { NULL, 0, 0, 0, lines, 0 };
1305 unsigned char level_rst
1312 outstr(
" (Y = yes | n = no)? ");
1332 unsigned char new_index
1347 unsigned int firstloc,
1348 unsigned int memsize,
1349 unsigned int * lines,
1354 #define SCANNING_DATA 0x00 //test != 0xff, test_old != 0xff
1355 #define DATA_START 0x01 //test != 0xff, test_old == 0xff
1356 #define FF_START 0x02 //test == 0xff, test_old != 0xff
1357 #define SCANNING_FF 0x03 //test == 0xff, test_old == 0xff
1359 #define APPLY_CUT 0x01
1360 #define HAS_NOT_BEEN_CUT_YET 0x02
1361 #define IS_0XFF 0x04
1363 #define MODE_0XFF filespec->mode_0xff
1364 #define INLINE_0XFF (MODE_0XFF & MODE_INLINE)
1365 #define PAYLOAD_DEFAULT (filespec->payload_default)
1375 unsigned char chars_tested = 0;
1376 unsigned char cut = 0;
1377 unsigned char test_old;
1383 unsigned char test = 0xff;
1394 if(chars_tested == memsize) {
1399 switch((((test == 0xff) << 1) | (test_old == 0xff))) {
1449 linedat.
buf[linedat.
wr++ & linedat.
mask] = test;
1452 if(test_old != 0xff)
1458 chars_tested -= cut;
1509 unsigned char addrlen_in_bits,
1510 unsigned int firstloc,
1511 unsigned int memsize,
1512 unsigned char screenmode
1516 unsigned int lines = 0;
1554 *linebuf = sprinti(linebuf,
"-#header: %s\r\n", header) - 1;
1563 *linebuf = sprinti(linebuf,
"-#lines: %d\r\n", lines) - 1;
1602 for(
int n = *p++; n; n--)
1636 while(*s !=
'\0' && n < 256) {
1665 char * linebuf = linebuf_orig;
1666 unsigned int prescan = linedat->
rd;
1667 unsigned char n, tab, fillup;
1673 linebuf += sprinti(linebuf,
"%08x: ", linedat->
startaddr);
1679 linebuf += sprinti(linebuf,
"%02x ", linedat->
buf[prescan++ & linedat->
mask]);
1685 linebuf += sprinti(linebuf,
" ");
1686 linebuf += sprinti(linebuf,
" #");
1689 test = linedat->
buf[linedat->
rd++ & linedat->
mask];
1690 *linebuf++ = isprint(test) ? test :
'.';
1700 *linebuf_orig = linebuf - linebuf_orig - 1;
1744 const unsigned char regno,
1745 const unsigned char byte
1748 unsigned char msbit = 7;
1749 unsigned int value = 0x00000000 | byte;
1807 const unsigned int addr,
1808 unsigned char * buffer
1811 unsigned int pageaddr;
1917 while((b &
CPM) && n);
1937 unsigned char status;
1943 sprinti(s,
"Bit No\t\t7\t6\t5\t4\t3\t2\t1\t0\r\n" \
1944 "Bitname\t\t%s\r\n" \
1948 for(
int n = 0b10000000; n; n >>= 1)
1949 outstr((status & n) != 0 ?
"1\t" :
"0\t");
1955 for(
int n = 0b10000000; n; n >>= 1)
1956 outstr((bitmask & n) != 0 ?
"w\t" :
"-\t");
1962 for(
int n = 0b10000000; n; n >>= 1)
1963 outstr((is_static & n) != 0 ?
"-\t" :
"v\t");
1984 unsigned int in = 0;
1998 const unsigned int value,
2018 const unsigned char cmd,
2019 const unsigned int value,
2036 id_JEDEC =
inbits(1 << 23);
2049 int dt = (CLKFREQ / 1000000) * 10;
2171 chip.pspec->sr_is_static[1] | \
2172 chip.pspec->sr_is_static[2];
2220 if(hnib == -1 || lnib == -1)
2222 return (hnib << 4) | lnib;
2230 unsigned char odd_tracker
2274 } led = { 0, 0, 0 };
2354 unsigned char odd_tracker = 0;
2355 unsigned int addr = 0;
2376 runctrl = load_lineaddr;
2385 runctrl = load_data;
2391 runctrl = check_flags;
2423 while(spacectr &&
queue) {
2435 runctrl = check_flags;
2445 runctrl = check_queue;
2486 char num = typeS->
bf.
num;
2512 typeS->
bf.
num = num;
2545 unsigned int * lines
2561 unsigned int lineaddr;
2591 unsigned char k = 0;
2592 unsigned char t = 0;
2595 vbin = c[1 + x] << (t << 2);
2596 lineaddr |= vbin << (k << 3);
2619 if(c[0] ==
' ' && (c[1] ==
'#' || c[1] ==
' ')) {
2630 if((errcode =
queue(px, vbin, &pwr)))
2680 unsigned int * lines,
2695 unsigned int lineaddr;
2696 unsigned char x = 0;
2697 unsigned char n = 0;
2698 unsigned char sum = 0;
2701 unsigned char c[2] = { 0, 0 };
2725 typeS.
bf.
num = vbin;
2745 #ifndef ERROR_MSG__LINE_TOO_LONG
2749 px->
pbuf = malloc(n);
2772 lineaddr |= vbin << (x << 3);
2781 cmax = hexmode ? 2 : 1;
2789 vbin = hexmode ?
hex2bin(c[0], c[1]) : c[0];
2796 if((errcode =
queue(px, vbin, &pwr)))
2812 if(vbin != (~sum & 0xff)) {
2852 if(reported_err != 0) {
2871 } rx = rx_stx_or_eot;
2873 unsigned int lines = 0;
2912 while(a !=
EOT && a !=
STX);
2969 while(a !=
ETX && a !=
CAN);
#define EXIT_CHAR_A
First char of Parallax' exit sequence.
#define CMD__CE_0XC7
Full Chip Erase (0xc7)
void menu(unsigned char mode)
Put the chipflasher menu on screen and invoke key_polling().
#define CAN
Ascii 'cancel'.
void greeting()
Put a small headline on terminal screen that helps to identify the program.
int main(void)
This is main() of kick, the firmware.
Common Bit Names of important SPI Flash Registers.
#define CMD__RDSR2
Read Status Register 2.
#define FILE_TO_CHIP
Send data to propeller and write to chip.
unsigned char payload_default
Pure data bytes per line.
char MOT_rxline(struct tag_xcog0 *px, unsigned int *lines, int hexmode)
Receive and parse a line in Motorola S-Record format. This func finishes successfully after having pa...
#define CMD__RDID
Read JEDEC Device ID.
void mirror(char *keymsg)
#define POWERUP_SPI
Give the attached system board some time to power up. Time in milliseconds.
#define CMD__SE
Sector Erase (4K)
#define CMD__RDSR3
Read Status Register 3.
void cmd_WREN(void)
Set Write Enable Latch bit.
unsigned int startaddr
Line’s startaddress.
#define CMD__READ
Read (at up to 25MHz)
#define CMD__RDSR
Read Status Register 1.
Entities that help to configure allowed key input. With these keys associated are predefined strings ...
unsigned char yes_no(char *question, unsigned char level_rst)
This function allows to put a question which expects true or false.
#define CMD__CP
Continuous Program.
#define GET_CHAR_GROUP(n)
void global_sector_protect(unsigned char pswitch)
Method to globally protect/unprotect all sectors.
volatile unsigned char queue_empty
Flag to indicate that the data queue is empty.
#define HAS_NOT_BEEN_CUT_YET
#define CMD__WRSR
Write Status Register 1.
void cmd(const unsigned char cmd, const unsigned int value, unsigned char bits)
Struct that characterizes a chip.
#define STACK_LEDSTAT
Stack size for ledstat().
#define ERRC__NO_HEX_DIGIT
#define CMD__PS
Protect Sector.
void SR_intro(unsigned char regno)
Provide each bit listing of an status register with a short header.
unsigned char abits
addrbits.
volatile unsigned char yellow
Switch for yellow LED usage.
int _cfg_modeterminal
configured through propeller-load
#define ACK
Ascii 'acknoledge'.
#define MODE_SCREEN_OUTPUT
void menu_options(void)
Put menu options on terminal screen.
#define CHIP_TO_FILE_NOSCREEN
Send data to terminal and save on disk, without feedback on screen.
void hr(char c, int n, char nl)
Put a horizontal line on screen.
unsigned int rd
Read pointer.
#define NEW_LINE
Ascii LF "\n" 'line feed'.
enum tag_spimode spimode
SPI mode to be used through the whole program.
volatile unsigned char green
Switch for green LED usage.
#define ARRAY_CHIPSPEC
Number of entries in chipspec database.
#define ERRC__JOB_CANCELLATION
char name[15]
chip's name, i.e. MX25L1605D
#define ERRC__LINE_TOO_LONG
#define MODE_SPI_POWEROFF
void MOT_summary(unsigned int lines, char *linebuf)
unsigned char get_addrlen(enum tag_type_of_addrlen type_of_addrlen, unsigned int addr)
Auxiliary function that returns the length of an address for different situations.
Struct that characterizes a data line.
struct tag_chipspec chipspec[ARRAY_CHIPSPEC]
Database of supported chips. These chips are usually found on motherboards, which are compatible with...
#define EXIT_CHAR_B
Second char of Parallax' exit sequence.
unsigned char cmd
Command to be used for writing.
int strpos(char *str, char c)
Report the position of a character in a string.
#define LED_YELLOW
Attached board or chip is powered.
void check_dryrun(void)
Checks wether a write fail should be expected. A function with very basic and poor functionality.
#define MENUWIDTH
width of menu headlines (in chars)
#define ERRC__HEXDUMP_PARSING_ERROR
int hex2bin(unsigned char a, unsigned char b)
Converts a pair of hexadecimal chars into binary value.
struct tag_xcog1 xcog1
Cog parameters for ledstat().
#define PIN_PLUGTESTn
This pin is used detect an adapter plug.
const unsigned int chipsize
Size of the chip.
signed char hexdigit2bin(unsigned char hexdigit)
Convert a hexadecimal digit into a binary value.
#define LED_ORANGE
SPI pins are actively driven, do not remove board's power.
#define CMD__WRSR2
Write Status Register 2.
#define CMD__CE_0X60
Full Chip Erase (0x60)
volatile unsigned char rq_spioff
Flag to request SPI off.
#define CMD__BE64K
Block Erase (64K)
Motorola S-Record Type Infos.
void MOT_typeS_fillup(union tag_typeS *typeS)
Generating and parsing a Motorola S-record line needs to have some specs available about the line in ...
void menu_line(unsigned int k1, char *k1msg, unsigned int k2, char *k2msg, unsigned int k3, char *k3msg)
Put a menu line with selected menu options on terminal screen.
unsigned char cmd_CE
Global chip erase command, may be overridden by key_config().
#define CMD__EWSR
Enable Write Status Register.
#define ERRC__LINE_COUNT_MISMATCH
int _cfg_rstdisable
configured through propeller-load
Function to print a char to the default terminal. This modified version does not prepend "\r" if "\n"...
unsigned int lineaddr
startaddress of data line.
void ledstat()
This function controls board LEDs. To be used with extra cog, to be stopped externally.
#define WIP
Write In Progress.
void MOT_header(char *header, char *linebuf)
This function invokes MOT_mkline(), but initializes parameters first with apropriate header data.
char HEXDUMP_rxline(struct tag_xcog0 *px, unsigned int *lines)
Parse a Hexdump line.
volatile unsigned char orange
Switch for orange LED usage.
Inline Code Macros with Assembler, that provide fast SPI Bus access.
void chip_rxfile(struct tag_xcog0 *px, char screen_output)
void cmd_WRSR(const unsigned char regno, const unsigned char byte)
Write to Status Registers.
unsigned char cmd_RDSR(unsigned char regno)
Read the status register.
#define CMD__BE32K
Block Erase (32K)
volatile unsigned int offrd
Buffer read pointer offset.
#define CMD__NOP
No Operation.
#define CMD__WREN
Write Enable.
void MOT_mkline(struct tag_linedat *linedat, union tag_typeS *typeS, char *linebuf)
This function wraps a binary payload into a Motorola S-record frame.
#define STX
Ascii 'start of text'.
volatile unsigned char rq_lineaddr
Flag to request the next line address.
#define SIZE_256
Usual page size.
unsigned char * pbuf
Pointer to ringbuffer.
#define SIZE_64K
Size of 64K-block.
unsigned int wr
Write pointer.
void chip_ini(unsigned char new_index)
void option_readblock(const enum tag_blocksize blocksize)
#define CMD__WRSR3
Write Status Register 3.
const int pagesize
If not applicable or unknown, clear cmdset.X02_PP.
#define tCLQV
CE# Low to Output valid.
Propeller Pin Usage and predefined Bit Values.
struct tag_filespec * pfspec
Pointer to specifications that are associated with selected format type.
const unsigned char sr_is_static[3]
True, if Status Register is not initialized during Power-Up.
void key_polling(unsigned char *key_is_valid, unsigned char *quit)
Essential function. Scans stdin for configured keys and issues the apropriate actions....
void exit_sequence(const char status)
Tell terminal to exit listening mode.
void outbits(const unsigned int value, unsigned int msbit)
#define CPM
Continously Program Mode.
#define ETX
Ascii 'end of text'.
void range_error(void)
Reports an Out-of-Range user input error and resets xcog1.inlevel.
struct tag_filespec filespec[2]
#define BAUDRATE_DEFAULT
propeller-load default baudrate
struct tag_xcog0 xcog0
Cog parameters for burn().
#define STACK_BURNBUF
Stack size for burn().
#define EOT
Ascii 'end of transmission'.
signed char linebuf_out(char *linebuf)
Put a formatted data line onto tty.
This file is useful for both, kick and connect.
Cog parameters for ledstat().
#define POWERUP_EXTRA
If chip detection fails, how often shall we retry?
void chip_erase(void)
This function calls the global chip erase command.
const int cmdset
selected commands
#define ERRC__BUFFER_OVERRUN
void SPI_ini(void)
Initialize SPI bus; activate hardware write protection.
char queue(struct tag_xcog0 *px, unsigned char vbin, unsigned int *pwr)
void chip_txfile(struct tag_filespec *filespec, unsigned char addrlen_in_bits, unsigned int firstloc, unsigned int memsize, unsigned char screenmode)
#define SIZE_128MBIT
Chipsize 128Mbit.
int pages
Number of pages (on a paged chip).
void report_err(char reported_err)
struct tag_chipspec * pspec
Pointer into chipspec database.
#define MAX_POLLING
Set a timeout value for the WIP polling routine.
#define SIZE_4K
Size of 4K-sector.
unsigned char addrlen_in_bits
Number of bits that are used feed an address into the SPI-bus.
const int id_JEDEC
If not applicable or unknown, clear cmdset.X9F_RDID.
void MOT_data(struct tag_linedat *linedat, char *linebuf)
void option_batchblockerase(const enum tag_blocksize blocksize, const unsigned char blockcmd)
Versatile block erase function, which allows erasing of multiple blocks of different sizes,...
volatile unsigned char inlevel
Current menu input level.
#define ERRC__CHECKSUM_MISMATCH
#define CMD__PP
Page Program.
#define CMD__DP
Deep Powerdown.
volatile unsigned int offwr
Buffer write pointer offset.
unsigned char SR_report(unsigned char regno)
Put status register's content on screen.
#define FILE_TO_CHIP_NOSCREEN
Send data to propeller and write to chip, without output on screen.
int plug_detect(void)
Check if an SPI-Plug is detected and put a message on screen.
#define CARR_RET
Ascii CR "\r" 'carriage return'.
#define NAK
Ascii 'neg. acknoledge'.
int do__WIP_polling(void)
Invoking WIP_polling() usually is accompanied by some checks and messages.
const unsigned char sr_wrmask[3]
maskout unwritable bits of the status register
#define ENQ
Ascii 'enquiry'.
#define LED_GREEN
SPI pins are tristate, you can safely attach/detach board.
unsigned int mask
Mask for read and write pointers.
void burn()
Wite data to chip.
#define CMD__WRDI
Write Disable.
Known SPI commands, one byte.
unsigned char verify_0xff(unsigned int firstloc, unsigned int memsize)
This function scans the specified chip memory for values different than 0xff. If a value different to...
#define NOT_APPLICABLE
some chipspec members may not make sense for some chips
unsigned int inbits(unsigned int msbit)
unsigned char bufsize
Size of ringbuffer.
unsigned int CPM_polling(void)
Poll CPM bit.
#define MODE_FORCE_SPI_OFF
#define CMD__BP
Byte Program.
#define POWERUP_OFFTIME
Separate multiple chip detections, time in µ-seconds.
#define ERRC__SUCCESS
Error codes.
int _cfg_baudrate
configured through propeller-load
#define POWERUP_SPILINES
Give SPI lines some time to power up (i.e. GA-G41M-ES2L).
Cog parameters for burn().
int * pcog
Cog info pointer, used by cog_end().
char * buf
Pointer to buffer, that holds the data.
void PGM_cycle(enum tag_cmdstat *cmdstat, unsigned char odd_tracker)
Chip specifications, provided within the source code.
unsigned char payload
Number of payload bytes.
char * sr_bitnames[3]
Status Register 0 Bit Names.
signed char chip_read(struct tag_filespec *filespec, unsigned int firstloc, unsigned int memsize, unsigned int *lines, char *linebuf)
void filespec_ini(int chipsize)
void HEXDUMP_mkline(struct tag_linedat *linedat, char *linebuf_orig)
This function transforms a binary payload into a row of ascii chars including line ending characters ...
#define CHIP_TO_FILE
Send data to terminal and save on disk.
void key_config(void)
Enable menu keys according to chip specs.
#define CMD__US
Unprotect Sector.
void SPI_off(int mode)
Switch SPI bus off.
void page_write(const unsigned int addr, unsigned char *buffer)
Write a page buffer to chip.
int WIP_polling(void)
Determine end of write cycle by polling the WIP bit.
#define SOH
Ascii 'start of header'.