📄 jffs2_nand_1pass.c
字号:
{ strncpy(working_tmp, tmp, c - tmp); working_tmp[c - tmp] = '\0';#if 0 putstr("search_inode: tmp = "); putstr(tmp); putstr("\r\n"); putstr("search_inode: wtmp = "); putstr(working_tmp); putstr("\r\n"); putstr("search_inode: c = "); putstr(c); putstr("\r\n");#endif for (i = 0; i < strlen(c) - 1; i++) tmp[i] = c[i + 1]; tmp[i] = '\0';#if 0 putstr("search_inode: post tmp = "); putstr(tmp); putstr("\r\n");#endif if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino))) { putstr("find_inode failed for name="); putstr(working_tmp); putstr("\r\n"); return 0; } } /* this is for the bare filename, directories have already been mapped */ if (!(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } return pino;}static u32jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino){ struct b_dirent *jDir; struct b_inode *jNode; u8 jDirFoundType = 0; u32 jDirFoundIno = 0; u32 jDirFoundPino = 0; char tmp[JFFS2_MAX_NAME_LEN + 1]; u32 version = 0; u32 pino; /* we need to search all and return the inode with the highest version */ for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { if (ino == jDir->ino) { if (jDir->version < version) continue; if (jDir->version == version && jDirFoundType) { /* I'm pretty sure this isn't legal */ putstr(" ** ERROR ** ");/* putnstr(jDir->name, jDir->nsize); *//* putLabeledWord(" has dup version (resolve) = ", *//* version); */ } jDirFoundType = jDir->type; jDirFoundIno = jDir->ino; jDirFoundPino = jDir->pino; version = jDir->version; } } /* now we found the right entry again. (shoulda returned inode*) */ if (jDirFoundType != DT_LNK) return jDirFoundIno; /* it's a soft link so we follow it again. */ for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { if (jNode->ino == jDirFoundIno) { size_t len = jNode->csize; nand_read(nand, jNode->offset + sizeof(struct jffs2_raw_inode), &len, &tmp); tmp[jNode->csize] = '\0'; break; } } /* ok so the name of the new file to find is in tmp */ /* if it starts with a slash it is root based else shared dirs */ if (tmp[0] == '/') pino = 1; else pino = jDirFoundPino; return jffs2_1pass_search_inode(pL, tmp, pino);}static u32jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino){ int i; char tmp[256]; char working_tmp[256]; char *c; /* discard any leading slash */ i = 0; while (fname[i] == '/') i++; strcpy(tmp, &fname[i]); working_tmp[0] = '\0'; while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */ { strncpy(working_tmp, tmp, c - tmp); working_tmp[c - tmp] = '\0'; for (i = 0; i < strlen(c) - 1; i++) tmp[i] = c[i + 1]; tmp[i] = '\0'; /* only a failure if we arent looking at top level */ if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) { putstr("find_inode failed for name="); putstr(working_tmp); putstr("\r\n"); return 0; } } if (tmp[0] && !(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } /* this is for the bare filename, directories have already been mapped */ if (!(pino = jffs2_1pass_list_inodes(pL, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } return pino;}unsigned charjffs2_1pass_rescan_needed(struct part_info *part){ struct b_node *b; struct jffs2_unknown_node onode; struct jffs2_unknown_node *node; struct b_lists *pL = (struct b_lists *)part->jffs2_priv; if (part->jffs2_priv == 0){ DEBUGF ("rescan: First time in use\n"); return 1; } /* if we have no list, we need to rescan */ if (pL->frag.listCount == 0) { DEBUGF ("rescan: fraglist zero\n"); return 1; } /* or if we are scanning a new partition */ if (pL->partOffset != part->offset) { DEBUGF ("rescan: different partition\n"); return 1; } /* FIXME */#if 0 /* but suppose someone reflashed a partition at the same offset... */ b = pL->dir.listHead; while (b) { node = (struct jffs2_unknown_node *) get_fl_mem(b->offset, sizeof(onode), &onode); if (node->nodetype != JFFS2_NODETYPE_DIRENT) { DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset); return 1; } b = b->next; }#endif return 0;}#ifdef DEBUG_FRAGMENTSstatic voiddump_fragments(struct b_lists *pL){ struct b_node *b; struct jffs2_raw_inode ojNode; struct jffs2_raw_inode *jNode; putstr("\r\n\r\n******The fragment Entries******\r\n"); b = pL->frag.listHead; while (b) { jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, sizeof(ojNode), &ojNode); putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); putLabeledWord("\tbuild_list: inode = ", jNode->ino); putLabeledWord("\tbuild_list: version = ", jNode->version); putLabeledWord("\tbuild_list: isize = ", jNode->isize); putLabeledWord("\tbuild_list: atime = ", jNode->atime); putLabeledWord("\tbuild_list: offset = ", jNode->offset); putLabeledWord("\tbuild_list: csize = ", jNode->csize); putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); putLabeledWord("\tbuild_list: compr = ", jNode->compr); putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); putLabeledWord("\tbuild_list: flags = ", jNode->flags); putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ b = b->next; }}#endif#ifdef DEBUG_DIRENTSstatic voiddump_dirents(struct b_lists *pL){ struct b_node *b; struct jffs2_raw_dirent *jDir; putstr("\r\n\r\n******The directory Entries******\r\n"); b = pL->dir.listHead; while (b) { jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); putstr("\r\n"); putnstr(jDir->name, jDir->nsize); putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); putLabeledWord("\tbuild_list: pino = ", jDir->pino); putLabeledWord("\tbuild_list: version = ", jDir->version); putLabeledWord("\tbuild_list: ino = ", jDir->ino); putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); putLabeledWord("\tbuild_list: type = ", jDir->type); putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ b = b->next; put_fl_mem(jDir); }}#endifstatic intjffs2_fill_scan_buf(nand_info_t *nand, unsigned char *buf, unsigned ofs, unsigned len){ int ret; unsigned olen; olen = len; ret = nand_read(nand, ofs, &olen, buf); if (ret) { printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret); return ret; } if (olen < len) { printf("Read at 0x%x gave only 0x%x bytes\n", ofs, olen); return -1; } return 0;}#define EMPTY_SCAN_SIZE 1024static u32jffs2_1pass_build_lists(struct part_info * part){ struct b_lists *pL; struct jffs2_unknown_node *node; unsigned nr_blocks, sectorsize, ofs, offset; char *buf; int i; u32 counter = 0; u32 counter4 = 0; u32 counterF = 0; u32 counterN = 0; struct mtdids *id = part->dev->id; nand = nand_info + id->num; /* if we are building a list we need to refresh the cache. */ jffs_init_1pass_list(part); pL = (struct b_lists *)part->jffs2_priv; pL->partOffset = part->offset; puts ("Scanning JFFS2 FS: "); sectorsize = nand->erasesize; nr_blocks = part->size / sectorsize; buf = malloc(sectorsize); if (!buf) return 0; for (i = 0; i < nr_blocks; i++) { printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]); offset = part->offset + i * sectorsize; if (nand_block_isbad(nand, offset)) continue; if (jffs2_fill_scan_buf(nand, buf, offset, EMPTY_SCAN_SIZE)) return 0; ofs = 0; /* Scan only 4KiB of 0xFF before declaring it's empty */ while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) ofs += 4; if (ofs == EMPTY_SCAN_SIZE) continue; if (jffs2_fill_scan_buf(nand, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE)) return 0; offset += ofs; while (ofs < sectorsize - sizeof(struct jffs2_unknown_node)) { node = (struct jffs2_unknown_node *)&buf[ofs]; if (node->magic != JFFS2_MAGIC_BITMASK || !hdr_crc(node)) { offset += 4; ofs += 4; counter4++; continue; } /* if its a fragment add it */ if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) { if (insert_inode(&pL->frag, (struct jffs2_raw_inode *) node, offset) == NULL) { return 0; } } else if (node->nodetype == JFFS2_NODETYPE_DIRENT && dirent_crc((struct jffs2_raw_dirent *) node) && dirent_name_crc((struct jffs2_raw_dirent *) node)) { if (! (counterN%100)) puts ("\b\b. "); if (insert_dirent(&pL->dir, (struct jffs2_raw_dirent *) node, offset) == NULL) { return 0; } counterN++; } else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) { if (node->totlen != sizeof(struct jffs2_unknown_node)) printf("OOPS Cleanmarker has bad size " "%d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node)); } else if (node->nodetype == JFFS2_NODETYPE_PADDING) { if (node->totlen < sizeof(struct jffs2_unknown_node)) printf("OOPS Padding has bad size " "%d < %d\n", node->totlen, sizeof(struct jffs2_unknown_node)); } else { printf("Unknown node type: %x len %d " "offset 0x%x\n", node->nodetype, node->totlen, offset); } offset += ((node->totlen + 3) & ~3); ofs += ((node->totlen + 3) & ~3); counterF++; } } putstr("\b\b done.\r\n"); /* close off the dots */#if 0 putLabeledWord("dir entries = ", pL->dir.listCount); putLabeledWord("frag entries = ", pL->frag.listCount); putLabeledWord("+4 increments = ", counter4); putLabeledWord("+file_offset increments = ", counterF);#endif#ifdef DEBUG_DIRENTS dump_dirents(pL);#endif#ifdef DEBUG_FRAGMENTS dump_fragments(pL);#endif /* give visual feedback that we are done scanning the flash */ led_blink(0x0, 0x0, 0x1, 0x1); /* off, forever, on 100ms, off 100ms */ free(buf); return 1;}static u32jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL){ struct b_node *b; struct jffs2_raw_inode ojNode; struct jffs2_raw_inode *jNode; int i; for (i = 0; i < JFFS2_NUM_COMPR; i++) { piL->compr_info[i].num_frags = 0; piL->compr_info[i].compr_sum = 0; piL->compr_info[i].decompr_sum = 0; }/* FIXME b = pL->frag.listHead; while (b) { jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, sizeof(ojNode), &ojNode); if (jNode->compr < JFFS2_NUM_COMPR) { piL->compr_info[jNode->compr].num_frags++; piL->compr_info[jNode->compr].compr_sum += jNode->csize; piL->compr_info[jNode->compr].decompr_sum += jNode->dsize; } b = b->next; }*/ return 0;}static struct b_lists *jffs2_get_list(struct part_info * part, const char *who){ if (jffs2_1pass_rescan_needed(part)) { if (!jffs2_1pass_build_lists(part)) { printf("%s: Failed to scan JFFSv2 file structure\n", who); return NULL; } } return (struct b_lists *)part->jffs2_priv;}/* Print directory / file contents */u32jffs2_1pass_ls(struct part_info * part, const char *fname){ struct b_lists *pl; long ret = 0; u32 inode; if (! (pl = jffs2_get_list(part, "ls"))) return 0; if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) { putstr("ls: Failed to scan jffs2 file structure\r\n"); return 0; }#if 0 putLabeledWord("found file at inode = ", inode); putLabeledWord("read_inode returns = ", ret);#endif return ret;}/* Load a file from flash into memory. fname can be a full path */u32jffs2_1pass_load(char *dest, struct part_info * part, const char *fname){ struct b_lists *pl; long ret = 0; u32 inode; if (! (pl = jffs2_get_list(part, "load"))) return 0; if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) { putstr("load: Failed to find inode\r\n"); return 0; } /* Resolve symlinks */ if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) { putstr("load: Failed to resolve inode structure\r\n"); return 0; } if ((ret = jffs2_1pass_read_inode(pl, inode, dest, NULL)) < 0) { putstr("load: Failed to read inode\r\n"); return 0; } DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname, (unsigned long) dest, ret); return ret;}/* Return information about the fs on this partition */u32jffs2_1pass_info(struct part_info * part){ struct b_jffs2_info info; struct b_lists *pl; int i; if (! (pl = jffs2_get_list(part, "info"))) return 0; jffs2_1pass_fill_info(pl, &info); for (i = 0; i < JFFS2_NUM_COMPR; i++) { printf ("Compression: %s\n" "\tfrag count: %d\n" "\tcompressed sum: %d\n" "\tuncompressed sum: %d\n", compr_names[i], info.compr_info[i].num_frags, info.compr_info[i].compr_sum, info.compr_info[i].decompr_sum); } return 1;}#endif /* CFG_CMD_JFFS2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -