0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013
0014 #include <linux/kernel.h>
0015 #include <linux/slab.h>
0016 #include <linux/crc32.h>
0017 #include <linux/pagemap.h>
0018 #include <linux/mtd/mtd.h>
0019 #include <linux/compiler.h>
0020 #include "nodelist.h"
0021 #include "compr.h"
0022
0023 int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0024 struct jffs2_full_dnode *fd, unsigned char *buf,
0025 int ofs, int len)
0026 {
0027 struct jffs2_raw_inode *ri;
0028 size_t readlen;
0029 uint32_t crc;
0030 unsigned char *decomprbuf = NULL;
0031 unsigned char *readbuf = NULL;
0032 int ret = 0;
0033
0034 ri = jffs2_alloc_raw_inode();
0035 if (!ri)
0036 return -ENOMEM;
0037
0038 ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri);
0039 if (ret) {
0040 jffs2_free_raw_inode(ri);
0041 pr_warn("Error reading node from 0x%08x: %d\n",
0042 ref_offset(fd->raw), ret);
0043 return ret;
0044 }
0045 if (readlen != sizeof(*ri)) {
0046 jffs2_free_raw_inode(ri);
0047 pr_warn("Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n",
0048 ref_offset(fd->raw), sizeof(*ri), readlen);
0049 return -EIO;
0050 }
0051 crc = crc32(0, ri, sizeof(*ri)-8);
0052
0053 jffs2_dbg(1, "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
0054 ref_offset(fd->raw), je32_to_cpu(ri->node_crc),
0055 crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize),
0056 je32_to_cpu(ri->offset), buf);
0057 if (crc != je32_to_cpu(ri->node_crc)) {
0058 pr_warn("Node CRC %08x != calculated CRC %08x for node at %08x\n",
0059 je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw));
0060 ret = -EIO;
0061 goto out_ri;
0062 }
0063
0064
0065 if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) &&
0066 je32_to_cpu(ri->csize)) {
0067 ri->dsize = ri->csize;
0068 ri->csize = cpu_to_je32(0);
0069 }
0070
0071 D1(if(ofs + len > je32_to_cpu(ri->dsize)) {
0072 pr_warn("jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
0073 len, ofs, je32_to_cpu(ri->dsize));
0074 ret = -EINVAL;
0075 goto out_ri;
0076 });
0077
0078
0079 if (ri->compr == JFFS2_COMPR_ZERO) {
0080 memset(buf, 0, len);
0081 goto out_ri;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090 if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) {
0091 readbuf = buf;
0092 } else {
0093 readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL);
0094 if (!readbuf) {
0095 ret = -ENOMEM;
0096 goto out_ri;
0097 }
0098 }
0099 if (ri->compr != JFFS2_COMPR_NONE) {
0100 if (len < je32_to_cpu(ri->dsize)) {
0101 decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL);
0102 if (!decomprbuf) {
0103 ret = -ENOMEM;
0104 goto out_readbuf;
0105 }
0106 } else {
0107 decomprbuf = buf;
0108 }
0109 } else {
0110 decomprbuf = readbuf;
0111 }
0112
0113 jffs2_dbg(2, "Read %d bytes to %p\n", je32_to_cpu(ri->csize),
0114 readbuf);
0115 ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri),
0116 je32_to_cpu(ri->csize), &readlen, readbuf);
0117
0118 if (!ret && readlen != je32_to_cpu(ri->csize))
0119 ret = -EIO;
0120 if (ret)
0121 goto out_decomprbuf;
0122
0123 crc = crc32(0, readbuf, je32_to_cpu(ri->csize));
0124 if (crc != je32_to_cpu(ri->data_crc)) {
0125 pr_warn("Data CRC %08x != calculated CRC %08x for node at %08x\n",
0126 je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw));
0127 ret = -EIO;
0128 goto out_decomprbuf;
0129 }
0130 jffs2_dbg(2, "Data CRC matches calculated CRC %08x\n", crc);
0131 if (ri->compr != JFFS2_COMPR_NONE) {
0132 jffs2_dbg(2, "Decompress %d bytes from %p to %d bytes at %p\n",
0133 je32_to_cpu(ri->csize), readbuf,
0134 je32_to_cpu(ri->dsize), decomprbuf);
0135 ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize));
0136 if (ret) {
0137 pr_warn("Error: jffs2_decompress returned %d\n", ret);
0138 goto out_decomprbuf;
0139 }
0140 }
0141
0142 if (len < je32_to_cpu(ri->dsize)) {
0143 memcpy(buf, decomprbuf+ofs, len);
0144 }
0145 out_decomprbuf:
0146 if(decomprbuf != buf && decomprbuf != readbuf)
0147 kfree(decomprbuf);
0148 out_readbuf:
0149 if(readbuf != buf)
0150 kfree(readbuf);
0151 out_ri:
0152 jffs2_free_raw_inode(ri);
0153
0154 return ret;
0155 }
0156
0157 int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0158 unsigned char *buf, uint32_t offset, uint32_t len)
0159 {
0160 uint32_t end = offset + len;
0161 struct jffs2_node_frag *frag;
0162 int ret;
0163
0164 jffs2_dbg(1, "%s(): ino #%u, range 0x%08x-0x%08x\n",
0165 __func__, f->inocache->ino, offset, offset + len);
0166
0167 frag = jffs2_lookup_node_frag(&f->fragtree, offset);
0168
0169
0170
0171
0172
0173
0174 while(offset < end) {
0175 jffs2_dbg(2, "%s(): offset %d, end %d\n",
0176 __func__, offset, end);
0177 if (unlikely(!frag || frag->ofs > offset ||
0178 frag->ofs + frag->size <= offset)) {
0179 uint32_t holesize = end - offset;
0180 if (frag && frag->ofs > offset) {
0181 jffs2_dbg(1, "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n",
0182 f->inocache->ino, frag->ofs, offset);
0183 holesize = min(holesize, frag->ofs - offset);
0184 }
0185 jffs2_dbg(1, "Filling non-frag hole from %d-%d\n",
0186 offset, offset + holesize);
0187 memset(buf, 0, holesize);
0188 buf += holesize;
0189 offset += holesize;
0190 continue;
0191 } else if (unlikely(!frag->node)) {
0192 uint32_t holeend = min(end, frag->ofs + frag->size);
0193 jffs2_dbg(1, "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n",
0194 offset, holeend, frag->ofs,
0195 frag->ofs + frag->size);
0196 memset(buf, 0, holeend - offset);
0197 buf += holeend - offset;
0198 offset = holeend;
0199 frag = frag_next(frag);
0200 continue;
0201 } else {
0202 uint32_t readlen;
0203 uint32_t fragofs;
0204
0205 fragofs = offset - frag->ofs;
0206 readlen = min(frag->size - fragofs, end - offset);
0207 jffs2_dbg(1, "Reading %d-%d from node at 0x%08x (%d)\n",
0208 frag->ofs+fragofs,
0209 frag->ofs + fragofs+readlen,
0210 ref_offset(frag->node->raw),
0211 ref_flags(frag->node->raw));
0212 ret = jffs2_read_dnode(c, f, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen);
0213 jffs2_dbg(2, "node read done\n");
0214 if (ret) {
0215 jffs2_dbg(1, "%s(): error %d\n",
0216 __func__, ret);
0217 memset(buf, 0, readlen);
0218 return ret;
0219 }
0220 buf += readlen;
0221 offset += readlen;
0222 frag = frag_next(frag);
0223 jffs2_dbg(2, "node read was OK. Looping\n");
0224 }
0225 }
0226 return 0;
0227 }
0228