/* FPGAedit */ %{ #include #include #include #include #include #include #include #include #include #include extern int errno; extern int fd; extern int debug, mmaped_access, readback; extern void *mem; unsigned int cur_position; typedef struct variable { struct variable *next; char *name; int val; } variable; unsigned long map_ofs = 0; unsigned long map_size = 0; int in_line = 0; #define LINELEN 16 int write_len; variable *vlist; void set_variable (char *param, int val); int get_variable (char *param); int hex_output (unsigned long offset, unsigned long len, unsigned long count); int fill_mem (int offset, int len, int count, int val); void print_help (void); extern void yyerror (const char *s); extern int zzlex (void); int yylex (void); %} %union { long val; char *tptr; } %left NUM %left ADD %left SUB %left MUL %left DIV %left NEG %left MOD %left RSHIFT %left LSHIFT %left OBRA %left CBRA %left FILENAME %left VARNAME %left OPEN %left CLOSE %left MAP %left UNMAP %left MD %left MM %left MF %left EQ %left AT %token EXIT %token HELP %token ENV %right CR %type num %type filename %% /* FPGAedit Grammar */ input: /* empty */ | input line ; line: CR | open CR | close CR | map CR | UNMAP CR {if (mmaped_access) munmap (mem, map_size);} | EXIT CR { exit(EXIT_SUCCESS); } | HELP CR { print_help(); } | ENV CR { variable *l; for (l = vlist; l; l = l->next) printf ("%s = 0x%x\n", l->name,l->val); } | VARNAME CR { printf ("%s = %d\n", $1, get_variable($1)); free($1); } | mem CR { printf ("\n"); } | VARNAME EQ num CR { set_variable ($1, $3); free($1); } | VARNAME EQ MD num CR { if (mmaped_access) { printf ("mmaped access: not implemented\n"); } else if (fd) { if (lseek (fd, $4, SEEK_SET) == -1) printf ("set offset %ld failed\n", $4); else { unsigned int c = 0; read(fd, &c, $3); set_variable ($1, c); free($1); } } else printf ("please open file\n"); } | error ; open: OPEN { printf ("open \n"); } | OPEN filename { char *filename = (char *)$2; if (fd>=0) close (fd); fd = open(filename, O_RDWR | O_SYNC); if (fd<0) printf ("open >%s< failed\n%s\n", filename, strerror(errno)); free (filename); } ; filename: FILENAME | VARNAME close: CLOSE { if (fd>0) { close (fd); fd = -1; mmaped_access = 0; } } ; map: MAP { printf("map \n"); } | MAP num num { if (fd>0) { printf("mapping offset 0x%08lx (size 0x%lx)\n",$2,$3); map_ofs = $2; map_size = $3; mem = mmap(0, $3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, $2); if(mem == MAP_FAILED) { perror("mmap"); } cur_position = 0; mmaped_access = 1; } else printf("load a file first\n"); } ; mem: MD { if (mem) cur_position = hex_output (cur_position, $1, 16); else printf ("no region mapped\n"); } | MD num { if (mem) { cur_position = hex_output ($2, $1, 16); } else printf ("no region mapped\n"); } | MD num num { if (mem) cur_position = hex_output ($2, $1, $3); else printf ("no region mapped\n"); } | MD AT num { if (mem) cur_position = hex_output ($3, $1, 16); else printf ("no region mapped\n"); } | MD AT num num { if (mem) cur_position = hex_output ($3, $1, $4); else printf ("no region mapped\n"); } | MF num num num { if (mem) fill_mem($2, $1, $3, $4); else printf ("no region mapped\n"); } | MM { printf ("mm [ ...]\n"); } | mm exp ; mm: MM { write_len = $1; if (debug > 3) printf ("write_len = %d\n", write_len);} ; exp: num { cur_position = $1; if (readback) printf ("new values:\n0x%08x: ",cur_position); } | exp num { unsigned int c = $2; if (mem) { switch (write_len) { case 1: c &= 0xff; *(volatile unsigned char *)(mem + cur_position) = c; if (readback) printf ("%02x ", *(volatile unsigned char *)(mem + cur_position)); break; case 2: c &= 0xffff; *(volatile unsigned short *)(mem + cur_position) = c; if (readback) printf ("%04x ", *(volatile unsigned short *)(mem + cur_position)); break; case 4: *(volatile unsigned long *)(mem + cur_position) = c; if (readback) printf ("%08lx ", *(volatile unsigned long *)(mem + cur_position)); break; } cur_position += write_len; } else printf ("no region mapped\n"); } ; num: NUM | num ADD num { $$ = $1 + $3; if (debug > 3) printf ("ADD: %ld\n", $$); } | num SUB num { $$ = $1 - $3; if (debug > 3) printf ("SUB: %ld\n", $$); } | num MUL num { $$ = $1 * $3; if (debug > 3) printf ("MUL: %ld\n", $$); } | num DIV num { $$ = $1 / $3; if (debug > 3) printf ("DIV: %ld\n", $$); } | num MOD num { $$ = $1 % $3; if (debug > 3) printf ("MOD: %ld\n", $$); } | num RSHIFT num { $$ = $1 >> $3; if (debug > 3) printf ("RSHIFT: %ld\n", $$); } | num LSHIFT num { $$ = $1 << $3; if (debug > 3) printf ("LSHIFT: %ld\n", $$); } | OBRA num CBRA { $$ = $2; if (debug > 3) printf ("BRA: %ld\n", $$); } | VARNAME { $$ = get_variable ($1); if (debug > 3) printf ("VAR: %ld\n", $$); free($1); } ; %% void print_help (void) { printf ("\n"); printf ("open open a file\n"); printf ("close close currently opened file\n"); printf ("map map memory starting at physical address \n"); printf (" into working buffer\n"); printf ("exit, quit quit\n"); printf ("help show this help text\n"); printf ("\n"); printf ("md [[@] []] mem display from current position\n"); printf (" or from for \n"); printf ("mm .. modify from value \n"); printf ("mf fill from for with \n"); printf ("env print all currently defined variables\n"); printf ("readback if true (default), read back values after write operation\n"); printf (" disable to avoid side-effects (e.g. for irq-registers)\n"); printf (" = set variable to \n"); printf (" print variable \n"); printf ("\n"); printf (" add add variables\n"); printf (" sub substract variables\n"); printf (" mul multiplicate variables\n"); printf (" div divide variables\n"); printf (" rshift shift (or >>)\n"); printf (" lshift shift (or >> or shift)\n"); printf ("\n"); printf ("Variables can be entered as decimals (without prefix), hex (prefixed with 0x)\n"); printf ("oct (0o) or bin (0b). For mm and md byte, word and long word access can be \n"); printf ("enabled with .b, .w and .l\n"); printf ("\n"); } void set_variable (char *param, int val) { variable *l, *tmp; if (strncmp (param, "readback", 8) == 0) { readback = val; printf ("readback = %d\n", readback); return; } if (strncmp (param, "debug", 5) == 0) { debug = val; printf ("debug = %d\n", debug); return; } if (debug > 3) printf ("param = >%s<\n", param); for (l = vlist; l; l = l->next) { if (debug > 3) printf ("l->name = >%s<\n", l->name); if (strcmp (l->name, param) == 0) { l->val = val; return; } } tmp = calloc (1, sizeof(variable)); if (!tmp) { printf ("no mem for variable %s!\n", param); return; } tmp->name = calloc(1 + strlen(param), sizeof(char)); if (!tmp->name) { printf ("no mem for variable %s!\n", param); free(tmp); return; } strcpy(tmp->name, param); tmp->val = val; tmp->next = vlist; vlist = tmp; } int get_variable (char *param) { int v = 0; variable *l; if (debug > 3) printf ("param = >%s<\n", param); for (l = vlist; l; l = l->next) { if (debug > 3) printf ("l->name = >%s<\n", l->name); if (strcmp (l->name, param) == 0) { v = l->val; break; } } return v; } int hex_output (unsigned long offset, unsigned long len, unsigned long count) { unsigned long c, j, t, bytes; unsigned char linebuf[LINELEN]; if (fd<0) { printf ("please open file\n"); return 0; } if( offset > map_size ) { printf("region not mapped\n"); return -1; } if( offset + count > map_size ) count = map_size - offset; while(1) { unsigned char *linechar = (unsigned char *)linebuf; unsigned int *lineint = (unsigned int *)linebuf; unsigned short *lineshort = (unsigned short *)linebuf; volatile unsigned int *rbuff32 = mem + offset; volatile unsigned short *rbuff16 = mem + offset; volatile unsigned char *rbuff8 = mem + offset; printf ("%08lx: ", offset); bytes = LINELEN > count ? count : LINELEN; if( bytes + offset > map_size ) bytes = map_size - offset; for( t=bytes; t>0; t-=len) { switch (len) { case 1: c = *rbuff8++; printf ("%02lx ", c); *linechar++ = c; break; case 2: c = *rbuff16++; printf ("%04lx ", c); *lineshort++ = c; break; case 4: c = *rbuff32++; printf ("%08lx ", c); *lineint++ = c; break; } } for (j = 0; j < bytes; j++) { if(isprint(linebuf[j])) printf("%c",linebuf[j]); else printf("."); } printf ("\n"); offset += bytes; count -= bytes; if(!count || offset == map_size) return offset; } } int fill_mem (int offset, int len, int count, int val) { int i; for (i = offset; i < offset + count; i += len) { switch (len) { case 1: val &= 0xff; *(volatile unsigned char *)(mem + i) = val; break; case 2: val &= 0xffff; *(volatile unsigned short *)(mem + i) = val; break; case 4: *(volatile unsigned long *)(mem + i) = val; break; } } return 0; } int yylex (void) { in_line++; return zzlex (); }