/* Process the summary node - called from jffs2_scan_eraseblock() */ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_summary *summary, uint32_t sumsize, uint32_t *pseudo_random) { struct jffs2_unknown_node crcnode; int ret, ofs; uint32_t crc; ofs = c->sector_size - sumsize; dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", jeb->offset, jeb->offset + ofs, sumsize); /* OK, now check for node validity and CRC */ crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); crcnode.totlen = summary->totlen; crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) { dbg_summary("Summary node header is corrupt (bad CRC or " "no summary at all)\n"); goto crc_err; } if (je32_to_cpu(summary->totlen) != sumsize) { dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); goto crc_err; } crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) { dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); if (je32_to_cpu(summary->sum_crc) != crc) { dbg_summary("Summary node data is corrupt (bad CRC)\n"); goto crc_err; } if ( je32_to_cpu(summary->cln_mkr) ) { dbg_summary("Summary : CLEANMARKER node \n"); ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); if (ret) return ret; if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) return ret; } else if (jeb->first_node) { dbg_summary("CLEANMARKER node not first node in block " "(0x%08x)\n", jeb->offset); if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) return ret; } else { jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, je32_to_cpu(summary->cln_mkr), NULL); } } ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full scan of this eraseblock. So return zero */ if (ret == -ENOTRECOVERABLE) return 0; if (ret) return ret; /* real error */ /* for PARANOIA_CHECK */ ret = jffs2_prealloc_raw_node_refs(c, jeb, 2); if (ret) return ret; sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL); if (unlikely(jeb->free_size)) { JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", jeb->free_size, jeb->offset); jeb->wasted_size += jeb->free_size; c->wasted_size += jeb->free_size; c->free_size -= jeb->free_size; jeb->free_size = 0; } return jffs2_scan_classify_jeb(c, jeb); crc_err: JFFS2_WARNING("Summary node crc error, skipping summary information.\n"); return 0; }
int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t ofs, uint32_t *pseudo_random) { struct jffs2_unknown_node crcnode; struct jffs2_raw_node_ref *cache_ref; struct jffs2_raw_summary *summary; int ret, sumsize; uint32_t crc; sumsize = c->sector_size - ofs; ofs += jeb->offset; dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", jeb->offset, ofs, sumsize); summary = kmalloc(sumsize, GFP_KERNEL); if (!summary) { return -ENOMEM; } ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize); if (ret) { kfree(summary); return ret; } /* OK, now check for node validity and CRC */ crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); crcnode.totlen = summary->totlen; crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) { dbg_summary("Summary node header is corrupt (bad CRC or " "no summary at all)\n"); goto crc_err; } if (je32_to_cpu(summary->totlen) != sumsize) { dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); goto crc_err; } crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) { dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); if (je32_to_cpu(summary->sum_crc) != crc) { dbg_summary("Summary node data is corrupt (bad CRC)\n"); goto crc_err; } if ( je32_to_cpu(summary->cln_mkr) ) { dbg_summary("Summary : CLEANMARKER node \n"); if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else if (jeb->first_node) { dbg_summary("CLEANMARKER node not first node in block " "(0x%08x)\n", jeb->offset); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else { struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); if (!marker_ref) { JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); kfree(summary); return -ENOMEM; } marker_ref->next_in_ino = NULL; marker_ref->next_phys = NULL; marker_ref->flash_offset = jeb->offset | REF_NORMAL; marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); jeb->first_node = jeb->last_node = marker_ref; USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); } } if (je32_to_cpu(summary->padded)) { DIRTY_SPACE(je32_to_cpu(summary->padded)); } ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); if (ret) return ret; /* for PARANOIA_CHECK */ cache_ref = jffs2_alloc_raw_node_ref(); if (!cache_ref) { JFFS2_NOTICE("Failed to allocate node ref for cache\n"); return -ENOMEM; } cache_ref->next_in_ino = NULL; cache_ref->next_phys = NULL; cache_ref->flash_offset = ofs | REF_NORMAL; cache_ref->__totlen = sumsize; if (!jeb->first_node) jeb->first_node = cache_ref; if (jeb->last_node) jeb->last_node->next_phys = cache_ref; jeb->last_node = cache_ref; USED_SPACE(sumsize); jeb->wasted_size += jeb->free_size; c->wasted_size += jeb->free_size; c->free_size -= jeb->free_size; jeb->free_size = 0; return jffs2_scan_classify_jeb(c, jeb); crc_err: JFFS2_WARNING("Summary node crc error, skipping summary information.\n"); return 0; }