static int elfreadsyms (int fd, Elf32_Ehdr *eh, Elf32_Shdr *shtab, int flags) { Elf32_Shdr *sh, *strh, *shstrh, *ksh; Elf32_Sym *symtab; Elf32_Ehdr *keh; char *shstrtab, *strtab, *symend; int nsym, offs, size, i; int *symptr; /* Fix up twirl */ if (bootseg++ > 0) { fprintf (stderr, "\b + "); } /* * If we are loading symbols to support kernel DDB symbol handling * make room for an ELF header at _end and after that a section * header. DDB then finds the symbols using the data put here. */ if(flags & KFLAG) { tablebase = roundup(tablebase, sizeof(long)); symptr = (int *)tablebase; tablebase += sizeof(int *) * 2; keh = (Elf32_Ehdr *)tablebase; tablebase += sizeof(Elf32_Ehdr); tablebase = roundup(tablebase, sizeof(long)); ksh = (Elf32_Shdr *)tablebase; tablebase += roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long)); memcpy(ksh, shtab, roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long))); sh = ksh; } else { sh = shtab; } shstrh = &sh[eh->e_shstrndx]; for (i = 0; i < eh->e_shnum; sh++, i++) { if (sh->sh_type == SHT_SYMTAB) { break; } } if (i >= eh->e_shnum) { return (0); } if(flags & KFLAG) { strh = &ksh[sh->sh_link]; nsym = sh->sh_size / sh->sh_entsize; offs = sh->sh_offset; size = sh->sh_size; fprintf (stderr, "%d syms ", nsym); } else { strh = &shtab[sh->sh_link]; nsym = (sh->sh_size / sh->sh_entsize) - sh->sh_info; offs = sh->sh_offset + (sh->sh_info * sh->sh_entsize); size = nsym * sh->sh_entsize; fprintf (stderr, "%d syms ", nsym); } /* * Allocate tables in correct order so the kernel grooks it. * Then we read them in the order they are in the ELF file. */ shstrtab = gettable(shstrh->sh_size, "shstrtab", flags); strtab = gettable(strh->sh_size, "strtab", flags); symtab = gettable(size, "symtab", flags); symend = (char *)symtab + size; do { if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) { #if 0 /* * We would like to read the shstrtab from the file but since this * table is located in front of the shtab it is already gone. We can't * position backwards outside the current segment when using tftp. * Instead we create the names we need in the string table because * it can be reconstructed from the info we now have access to. */ if (!readtable (shstrh->sh_offset, (void *)shstrtab, shstrh->sh_size, "shstring", flags)) { return(0); } #else memset(shstrtab, 0, shstrh->sh_size); strcpy(shstrtab + shstrh->sh_name, ".shstrtab"); strcpy(shstrtab + strh->sh_name, ".strtab"); strcpy(shstrtab + sh->sh_name, ".symtab"); #endif shstrh->sh_offset = 0x7fffffff; } if (offs < strh->sh_offset && offs < shstrh->sh_offset) { if (!(readtable(fd, offs, (void *)symtab, size, "sym", flags))) { return (0); } offs = 0x7fffffff; } if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) { if (!(readtable (fd, strh->sh_offset, (void *)strtab, strh->sh_size, "string", flags))) { return (0); } strh->sh_offset = 0x7fffffff; } if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff && shstrh->sh_offset == 0x7fffffff) { break; } } while(1); if(flags & KFLAG) { /* * Update the kernel headers with the current info. */ shstrh->sh_offset = (Elf32_Off)shstrtab - (Elf32_Off)keh; strh->sh_offset = (Elf32_Off)strtab - (Elf32_Off)keh; sh->sh_offset = (Elf32_Off)symtab - (Elf32_Off)keh; memcpy(keh, eh, sizeof(Elf32_Ehdr)); keh->e_phoff = 0; keh->e_shoff = sizeof(Elf32_Ehdr); keh->e_phentsize = 0; keh->e_phnum = 0; printf("\nKernel debugger symbols ELF hdr @ %p", keh); symptr[0] = (int)keh; symptr[1] = roundup((int)symend, sizeof(int)); } else { /* * Add all global sybols to PMONs internal symbol table. */ for (i = 0; i < nsym; i++, symtab++) { int type; dotik (4000, 0); if (symtab->st_shndx == SHN_UNDEF || symtab->st_shndx == SHN_COMMON) { continue; } type = ELF_ST_TYPE (symtab->st_info); if (type == STT_SECTION || type == STT_FILE) { continue; } /* only use globals and functions */ if (ELF_ST_BIND(symtab->st_info) == STB_GLOBAL || type == STT_FUNC){ if (symtab->st_name >= strh->sh_size) { fprintf (stderr, "\ncorrupt string pointer"); return (0); } } if (!newsym (strtab + symtab->st_name, symtab->st_value)) { fprintf (stderr, "\nonly room for %d symbols", i); return (0); } } } return (1); }
/* * Verify flash contents to ram contents. */ int fl_verify_device(void *fl_base, void *data_base, int data_size, int verbose) { struct fl_map *map; struct fl_device *dev; void *fl_last; int ok; int i; dev = fl_devident(fl_base, &map); if(dev == NULL) { return(-3); /* No flash device found at address */ } if(data_size == -1 || (int)data_base == -1) { return(-4); /* Bad parameters */ } if((data_size + ((int)fl_base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* Size larger than device array */ } if(verbose) { printf("Verifying FLASH. "); } for(i = 0; i < data_size; i += map->fl_map_width) { fl_last = fl_base; switch(map->fl_map_bus) { case FL_BUS_8: ok = (*((u_char *)fl_base) == *((u_char *)data_base)); fl_base++; data_base++; break; case FL_BUS_16: ok = (*((u_short *)fl_base) == *((u_short *)data_base)); fl_base += 2; data_base += 2; break; case FL_BUS_32: ok = (*((u_int *)fl_base) == *((u_int *)data_base)); fl_base += 4; data_base += 4; break; case FL_BUS_64: movequad(&widedata, fl_base); ok = (bcmp(data_base, (void *)&widedata, 8) == 0); data_base += 8; fl_base += 8; break; case FL_BUS_8_ON_64: ok = (*((u_char *)map->fl_map_base + (((int)fl_base - map->fl_map_base) << 3)) == *(u_char *)data_base++); fl_base++; break; } if(verbose & !ok) { printf(" error offset %p\n", fl_last); { char str[100]; int timeout; printf("erase all chip(y/N)?"); gets(str); if(str[0]=='y'||str[0]=='Y') { tgt_flashwrite_enable(); fl_write_protect_unlock(map, dev, 0);/* Disable write protection of SST49LF040B/SST49LF008A */ printf("Erasing all FLASH blocks. "); (*dev->functions->erase_chip)(map, dev); delay(1000); for(timeout = 0 ; ((ok = (*dev->functions->isbusy)(map, dev, 0xffffffff,0, TRUE)) == 1) && (timeout < PFLASH_MAX_TIMEOUT); timeout++) { delay(1000); if(verbose) { dotik(256, 0); } } delay(1000); if(!(timeout < PFLASH_MAX_TIMEOUT)) { (*dev->functions->erase_suspend)(map, dev); } (*dev->functions->reset)(map, dev); tgt_flashwrite_disable(); fl_write_protect_lock(map, dev, 0);/* Enable write protection of SST49LF040B/SST49LF008A */ } } break; } else if(verbose) { dotik(32, 0); } } if(verbose && ok) { printf("\b No Errors found.\n"); } return(ok); }
/* * Program a flash device. Assumed that the area is erased already. */ int fl_program_device(void *fl_base, void *data_base, int data_size, int verbose) { struct fl_map *map; struct fl_device *dev; int ok; int i, off; if(tgt_flashwrite_enable() == 0) { return(-2); /* Flash can't be write enabled */ } dev = fl_devident(fl_base, &map); if(dev == NULL) { tgt_flashwrite_disable(); return(-3); /* No flash device found at address */ } if(data_size == -1 || (int)data_base == -1) { return(-4); /* Bad parameters */ } if((data_size + ((int)fl_base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* Size larger than device array */ } off = (int)(fl_base - map->fl_map_base) + map->fl_map_offset; if(verbose) { printf("Programming FLASH. "); } tgt_flashwrite_enable(); fl_write_protect_unlock(map, dev, 0);/* Disable write protection of SST49LF040B/SST49LF008A */ for(i = 0; i < data_size; i += map->fl_map_width) { ok = (*dev->functions->program)(map, dev, (int)off, data_base); switch(map->fl_map_bus) { case FL_BUS_8: case FL_BUS_8_ON_64: off++; data_base++; break; case FL_BUS_16: data_base += 2; off += 2; break; case FL_BUS_32: data_base += 4; off += 4; break; case FL_BUS_64: data_base += 8; off += 8; break; } if(verbose) { dotik(256, 0); } } (*dev->functions->reset)(map, dev); if(verbose) { printf("\b Done.\n"); } tgt_flashwrite_disable(); fl_write_protect_lock(map, dev, 0);/* Enable write protection of SST49LF040B/SST49LF008A */ return(ok); }
/* * Erase the flash device(s) addressed. */ int fl_erase_device(void *base, int size, int verbose) { struct fl_map *map; struct fl_device *dev; int mask, ok, block; int timeout; if(tgt_flashwrite_enable() == 0) { printf("Flash can't be write enabled\n"); return(-2); /* Flash can't be write enabled */ } dev = fl_devident(base, &map); if(dev == NULL) { printf("No flash found at %x\n",(u_int32_t)base); return(-3); /* No flash device found at address */ } /* * Sanity checks! */ if(size == -1 && (int)base == map->fl_map_base) { size = map->fl_map_size; /* Entire flash */ } if(dev->fl_varsecsize != NULL) { int offset = (int)(base - map->fl_map_base) + map->fl_map_offset; int totalsize; printf("offset=%x,base=%x\n",offset,map->fl_map_base); for(block=0, totalsize=0; totalsize < offset; block++) { totalsize += dev->fl_varsecsize[block] * map->fl_map_chips; } mask = ((dev->fl_varsecsize[block] * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; } else { mask = ((dev->fl_secsize * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; block = (int)base / map->fl_map_chips / dev->fl_secsize; size = (size + mask) & ~mask; /* Round up to catch entire flash */ } tgt_flashwrite_enable(); fl_write_protect_unlock(map, dev, 0);/* Disable write protection of SST49LF040B/SST49LF008A */ while(size > 0) { int boffs = (int)base; #if 0 if(size == map->fl_map_size && dev->fl_cap & (FL_CAP_DE|FL_CAP_A7)) { /* * Erase entire devices using the BULK erase feature */ if(verbose) { printf("Erasing all FLASH blocks. "); } (*dev->functions->erase_chip)(map, dev); size = 0; } else { #endif /* * Not entire flash or no BULK erase feature. We * use sector/block erase. */ if(verbose) { printf("\rErasing FLASH block %3d \b\b\b\b\b", block); } if((*dev->functions->erase_sector)(map, dev, boffs) != 0) { printf("\nError: Failed to enter erase mode\n"); (*dev->functions->erase_suspend)(map, dev); (*dev->functions->reset)(map, dev); return(-4); } if(dev->fl_varsecsize != NULL) { base += dev->fl_varsecsize[block] * map->fl_map_chips; size -= dev->fl_varsecsize[block] * map->fl_map_chips; block++; } else { base += dev->fl_secsize * map->fl_map_chips; size -= dev->fl_secsize * map->fl_map_chips; block++; } // } delay(1000); for(timeout = 0 ; ((ok = (*dev->functions->isbusy)(map, dev, 0xffffffff, boffs, TRUE)) == 1) && (timeout < PFLASH_MAX_TIMEOUT); timeout++) { delay(1000); if(verbose) { dotik(256, 0); } } delay(1000); if(!(timeout < PFLASH_MAX_TIMEOUT)) { (*dev->functions->erase_suspend)(map, dev); } (*dev->functions->reset)(map, dev); if(verbose) { if(!(timeout < PFLASH_MAX_TIMEOUT)) { /* XXX if timed out what should really happen here? This doesn't look right. */ printf("\b\b, command timed out!\n"); } else { printf("\b Done.\n"); } } } tgt_flashwrite_disable(); fl_write_protect_lock(map, dev, 0);/* Enable write protection of SST49LF040B/SST49LF008A */ return(ok); } int fl_program(void *fl_base, void *data_base, int data_size, int verbose) { char *nvrambuf; char *nvramsecbuf; char *nvram; int offs,count,left; struct fl_device *dev=fl_devident(fl_base,0); int nvram_size=dev->fl_secsize; nvramsecbuf = (char *)malloc(nvram_size); if(nvramsecbuf == 0) { printf("Warning! Unable to malloc nvrambuffer!\n"); return(-1); } nvram = fl_base; left = data_size; while(left) { offs = (int)nvram &(nvram_size - 1); nvram = (int)nvram & ~(nvram_size - 1); count = min(nvram_size-offs,left); memcpy(nvramsecbuf, nvram, nvram_size); nvrambuf = nvramsecbuf + offs; memcpy(nvrambuf,data_base,count); #ifdef NVRAM_IN_FLASH #ifndef LS3B_SPI_BOOT if(fl_erase_device(nvram, nvram_size, verbose)) { printf("Error! Nvram erase failed!\n"); free(nvramsecbuf); return(0); } if(fl_program_device(nvram, nvramsecbuf, nvram_size, verbose)) { printf("Error! Nvram program failed!\n"); free(nvramsecbuf); return(0); } #else spi_erase( (unsigned long)(nvram)- tgt_flashmap()->fl_map_base, nvram_size); if( spi_program(nvramsecbuf, (unsigned long)(nvram)- tgt_flashmap()->fl_map_base, nvram_size, 0) ) { printf("Error! Nvram program failed!\n"); free(nvramsecbuf); return(0); } #endif #endif data_base += count; nvram += nvram_size; left -= count; } free(nvramsecbuf); return 0; }
/* * Verify flash contents to ram contents. */ int fl_verify_device(void *fl_base, void *data_base, int data_size, int verbose) { struct fl_map *map; struct fl_device *dev; void *fl_last; int ok; int i; dev = fl_devident(fl_base, &map); if(dev == NULL) { return(-3); /* No flash device found at address */ } if(data_size == -1 || (int)data_base == -1) { return(-4); /* Bad parameters */ } if((data_size + ((int)fl_base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* Size larger than device array */ } if(verbose) { printf("Verifying FLASH. "); } for(i = 0; i < data_size; i += map->fl_map_width) { fl_last = fl_base; switch(map->fl_map_bus) { case FL_BUS_8: ok = (*((u_char *)fl_base) == *((u_char *)data_base)); fl_base += 1; data_base += 1; break; case FL_BUS_16: ok = (*(u_short *)fl_base == *((u_short *)data_base)); fl_base += 2; data_base += 2; break; case FL_BUS_32: ok = (*(u_int *)fl_base == *(u_int *)data_base); fl_base += 4; data_base += 4; break; case FL_BUS_64: movequad(&widedata, fl_base); ok = (bcmp(data_base, (void *)&widedata, 8) == 0); data_base += 8; fl_base += 8; break; case FL_BUS_8_ON_64: ok = (*((u_char *)map->fl_map_base + (((int)fl_base - map->fl_map_base) << 3)) == *(u_char *)data_base++); fl_base++; break; } if(verbose & !ok) { printf(" error offset %p\n", fl_last); { char str[100]; int timeout; printf("erase all chip(y/N)?"); gets(str); if(str[0]=='y'||str[0]=='Y') { tgt_flashwrite_enable(); printf("Erasing all FLASH blocks. "); fl_erase_device(map->fl_map_base,map->fl_map_size,FALSE); tgt_flashwrite_disable(); } } break; } else if(verbose) { dotik(32, 0); } } if(verbose && ok) { printf("\b No Errors found.\n"); } return(ok); }
__attribute__((weak))fl_erase_device(void *base, int size, int verbose) { struct fl_map *map; struct fl_device *dev; int mask, ok, block; int timeout; if(tgt_flashwrite_enable() == 0) { printf("Flash can't be write enabled\n"); return(-2); /* Flash can't be write enabled */ } dev = fl_devident(base, &map); if(dev == NULL) { printf("No flash found at %x\n",(u_int32_t)base); return(-3); /* No flash device found at address */ } /* * Sanity checks! */ if(size == -1 && (int)base == map->fl_map_base) { size = map->fl_map_size; /* Entire flash */ } if(dev->fl_varsecsize != NULL) { int offset = (int)(base - map->fl_map_base) + map->fl_map_offset; int totalsize; printf("offset=%x,base=%x\n",offset,map->fl_map_base); for(block=0, totalsize=0; totalsize < offset; block++) { totalsize += dev->fl_varsecsize[block] * map->fl_map_chips; } mask = ((dev->fl_varsecsize[block] * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; } else { mask = ((dev->fl_secsize * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; block = (int)base / map->fl_map_chips / dev->fl_secsize; size = (size + mask) & ~mask; /* Round up to catch entire flash */ } tgt_flashwrite_enable(); while(size > 0) { int boffs = (int)base; if(size == map->fl_map_size && dev->fl_cap & (FL_CAP_DE|FL_CAP_A7)) { /* * Erase entire devices using the BULK erase feature */ if(verbose) { printf("Erasing all FLASH blocks. "); } (*dev->functions->erase_chip)(map, dev); size = 0; } else { /* * Not entire flash or no BULK erase feature. We * use sector/block erase. */ if(verbose) { printf("\rErasing FLASH block %3d \b\b\b\b\b", block); } if((*dev->functions->erase_sector)(map, dev, boffs) != 0) { printf("\nError: Failed to enter erase mode\n"); (*dev->functions->erase_suspend)(map, dev); (*dev->functions->reset)(map, dev); return(-4); } if(dev->fl_varsecsize != NULL) { base += dev->fl_varsecsize[block] * map->fl_map_chips; size -= dev->fl_varsecsize[block] * map->fl_map_chips; block++; } else { base += dev->fl_secsize * map->fl_map_chips; size -= dev->fl_secsize * map->fl_map_chips; block++; } } delay(1000); for(timeout = 0 ; ((ok = (*dev->functions->isbusy)(map, dev, 0xffffffff, boffs, TRUE)) == 1) && (timeout < PFLASH_MAX_TIMEOUT); timeout++) { delay(1000); if(verbose) { dotik(256, 0); } } delay(1000); if(!(timeout < PFLASH_MAX_TIMEOUT)) { (*dev->functions->erase_suspend)(map, dev); } (*dev->functions->reset)(map, dev); if(verbose) { if(!(timeout < PFLASH_MAX_TIMEOUT)) { /* XXX if timed out what should really happen here? This doesn't look right. */ printf("\b\b, command timed out!\n"); } else { printf("\b Done.\n"); } } } tgt_flashwrite_disable(); return(ok); }