FreeCalypso > hg > freecalypso-tools
view loadtools/flutil.c @ 465:003e48f8ebe1
rvinterf/etmsync/fsnew.c: cast 0 to (char *) for execl sentinel
I generally don't use NULL and use plain 0 instead, based on a "NULL
considered harmful" discussion on the classiccmp mailing list many aeons
ago (I couldn't find it, and I reason that it must have been 2005 or
earlier), but a recent complaint by a packager sent me searching, and I
found this:
https://ewontfix.com/11/
While I don't give a @#$% about "modern" systems and code-nazi tools,
I realized that passing a plain 0 as a pointer sentinel in execl is wrong
because it will break on systems where pointers are longer than the plain
int type. Again, I don't give a @#$% about the abomination of x86_64 and
the like, but if anyone ever manages to port my code to something like a
PDP-11 (16-bit int, 32-bit long and pointers), then passing a plain 0
as a function argument where a pointer is expected most definitely won't
work: if the most natural stack slot and SP alignment unit is 16 bits,
fitting an int, with longs and pointers taking up two such slots, then
the call stack will be totally wrong with a plain 0 passed for a pointer.
Casting the 0 to (char *) ought to be the most kosher solution for the
most retro systems possible.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 11 Feb 2019 00:00:19 +0000 |
parents | e7502631a0f9 |
children | 7bf0d909c87e |
line wrap: on
line source
/* * Miscellaneous utility functions for flash support */ #include <sys/types.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include "flash.h" extern struct flash_bank_info flash_bank_info[2]; extern struct flash_cmdset flash_cmdset_amd; extern struct flash_cmdset flash_cmdset_intel; static int cfi_read_byte(bi, off, ret16p) struct flash_bank_info *bi; int off; uint16_t *ret16p; { return do_r16(bi->base_addr + (off << 1), ret16p); } static int cfi_read_twobyte(bi, off, retptr) struct flash_bank_info *bi; int off; uint16_t *retptr; { uint16_t lo, hi; if (cfi_read_byte(bi, off, &lo) < 0) return(-1); lo &= 0xFF; if (cfi_read_byte(bi, off + 1, &hi) < 0) return(-1); hi &= 0xFF; *retptr = (hi << 8) | lo; return(0); } flash_get_cfi(bank) { struct flash_bank_info *bi; struct flash_geom *geom; struct flash_region_desc *reg; int nr; uint16_t rdval, cmdset_id; uint32_t size_check; bi = flash_bank_info + bank; if (bi->geom) return(0); printf("Performing CFI query\n"); if (do_w16(bi->base_addr + 0xAA, 0x98)) { fprintf(stderr, "unexpected response to w16 - aborting\n"); return(-1); } /* if do_r16() returns -1, error msg has already been printed */ if (cfi_read_byte(bi, 0x10, &rdval) < 0) return(-1); if (rdval != 'Q') { noqry: fprintf(stderr, "error: no QRY response from flash\n"); amd_reset_cmd(bi); return(-1); } if (cfi_read_byte(bi, 0x11, &rdval) < 0) return(-1); if (rdval != 'R') goto noqry; if (cfi_read_byte(bi, 0x12, &rdval) < 0) return(-1); if (rdval != 'Y') goto noqry; if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0) return(-1); if (!bi->ops) { switch (cmdset_id) { case 2: bi->ops = &flash_cmdset_amd; break; case 3: bi->ops = &flash_cmdset_intel; break; default: fprintf(stderr, "error: command set %04X unsupported\n", cmdset_id); amd_reset_cmd(bi); return(-1); } } geom = malloc(sizeof(struct flash_geom)); if (!geom) { fprintf(stderr, "unable to malloc buffer for flash bank %d CFI geometry structure\n", bank); bi->ops->reset_cmd(bi); return(-1); } /* total device size */ if (cfi_read_byte(bi, 0x27, &rdval) < 0) { free_and_immed_out: free(geom); return(-1); } if (rdval < 20 || rdval > 24) { fprintf(stderr, "error: CFI reports unreasonable device size\n"); free_and_clean_out: free(geom); bi->ops->reset_cmd(bi); return(-1); } geom->total_size = 1 << rdval; if (geom->total_size > bi->bank_desc->align_size) { fprintf(stderr, "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", (u_long) geom->total_size, bi->bank_desc->align_size); goto free_and_clean_out; } if (cfi_read_byte(bi, 0x2C, &rdval) < 0) goto free_and_immed_out; if (rdval < 1 || rdval > CFI_MAX_REGIONS) { fprintf(stderr, "error: CFI reports unreasonable # of erase regions\n"); goto free_and_clean_out; } geom->nregions = rdval; geom->total_sectors = 0; size_check = 0; for (nr = 0; nr < geom->nregions; nr++) { reg = geom->regions + nr; if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval > 255) { fprintf(stderr, "error: CFI reports unreasonable # of sectors in region %d\n", nr); goto free_and_clean_out; } reg->nsectors = rdval + 1; geom->total_sectors += reg->nsectors; if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval < 0x20 || rdval > 0x400) { fprintf(stderr, "error: CFI reports unreasonable sector size in region %d\n", nr); goto free_and_clean_out; } reg->sector_size = rdval << 8; size_check += reg->sector_size * reg->nsectors; } if (bi->ops->reset_cmd(bi) < 0) { /* error msg already printed */ free(geom); return(-1); } if (size_check != geom->total_size) { fprintf(stderr, "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n", (u_long) size_check, (u_long) geom->total_size); free(geom); return(-1); } /* all checks passed */ bi->geom = geom; printf( "CFI query successful: total size %lx, %u sectors, command set style %04X\n", (u_long) geom->total_size, geom->total_sectors, cmdset_id); return(1); } get_flash_sector_table(bank) { struct flash_bank_info *bi; struct flash_geom *geom; struct flash_region_desc *reg; struct sector_info *sp; uint32_t offset; int nr, i; bi = flash_bank_info + bank; if (bi->sectors) return(0); i = flash_get_cfi(bank); if (i < 0) return(i); geom = bi->geom; sp = (struct sector_info *) malloc(sizeof(struct sector_info) * (geom->total_sectors + 1)); if (!sp) { fprintf(stderr, "unable to malloc buffer for flash bank %d sector table\n", bank); return(-1); } bi->sectors = sp; /* now fill it */ offset = 0; for (nr = 0; nr < geom->nregions; nr++) { reg = geom->regions + nr; for (i = 0; i < reg->nsectors; i++) { sp->start = offset; sp->size = reg->sector_size; sp++; offset += reg->sector_size; } } /* sanity checks */ if (sp - bi->sectors != geom->total_sectors) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong # of sectors at the end\n"); abort(); } if (offset != geom->total_size) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong offset at the end\n"); abort(); } /* finish */ sp->start = 0; sp->size = 0; return(0); } flashcmd_sectors(argc, argv, bank) char **argv; { struct flash_bank_info *bi; struct sector_info *sp; if (argc > 2) { fprintf(stderr, "error: too many arguments\n"); return(-1); } if (get_flash_sector_table(bank) < 0) return(-1); bi = flash_bank_info + bank; printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank); printf("Offset Size\n"); for (sp = bi->sectors; sp->size; sp++) printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size); return(0); } get_flash_sector_range(bi, useroff, userlen, startp, endp) struct flash_bank_info *bi; u_long useroff, userlen; struct sector_info **startp, **endp; { struct sector_info *sp; uint32_t remlen; for (sp = bi->sectors; sp->size; sp++) if (sp->start == useroff) break; if (!sp->size) { fprintf(stderr, "error: specified offset not aligned to a flash sector boundary\n"); return(-1); } *startp = sp; for (remlen = userlen; remlen; ) { if (remlen < sp->size) { fprintf(stderr, "error: specified length not aligned to a flash sector boundary\n"); return(-1); } remlen -= sp->size; sp++; } *endp = sp; return(0); } build_flashw_hex_string(bin, strbuf, nwords, m0src) u_char *bin; char *strbuf; int nwords, m0src; { int i; u_char *dp; char *s; for (dp = bin, s = strbuf, i = 0; i < nwords; dp += 2, s += 4, i++) { if (m0src) sprintf(s, "%02X%02X", dp[0], dp[1]); else sprintf(s, "%02X%02X", dp[1], dp[0]); } *s = '\0'; } flash_id_check(bank, repeat) { struct flash_bank_info *bi; struct flash_bank_desc *bd; struct flash_idcheck *id; int stat, fail; uint16_t rdval; unsigned cnt; bi = flash_bank_info + bank; if (bi->idcheck_done && !repeat) return(0); bd = bi->bank_desc; if (!bd->idcheck_table || !bd->idcheck_num) return(0); printf("Performing flash ID check\n"); stat = do_w16(bi->base_addr + 0xAAA, 0xAA); if (stat) { bad_w16: fprintf(stderr, "unexpected response to w16 in read ID cmd sequence - aborting\n"); return(-1); } stat = do_w16(bi->base_addr + 0x554, 0x55); if (stat) goto bad_w16; stat = do_w16(bi->base_addr + 0xAAA, 0x90); if (stat) goto bad_w16; id = bd->idcheck_table; fail = 0; for (cnt = 0; cnt < bd->idcheck_num; cnt++) { stat = do_r16(bi->base_addr + id->offset, &rdval); if (stat) return(stat); /* error msg already printed */ printf("offset %02X: %04X -- ", (int)id->offset, (int)rdval); if (rdval == id->expect_val) printf("PASS\n"); else { printf("FAIL: expected %04X\n", (int)id->expect_val); fail = 1; break; } id++; } /* reset flash to read mode */ stat = do_w16(bi->base_addr + 0xAAA, 0xF0); if (stat) { fprintf(stderr, "unexpected response to w16 when resetting flash to read mode!\n"); return(-1); } if (fail) return(-1); bi->idcheck_done = 1; return(0); }