2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright © 2001-2007 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@infradead.org>
8 * For licensing information, see the file 'LICENCE' in this directory.
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
14 #include <linux/crc32.h>
15 #include <linux/pagemap.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/compiler.h>
21 int jffs2_read_dnode(struct jffs2_sb_info
*c
, struct jffs2_inode_info
*f
,
22 struct jffs2_full_dnode
*fd
, unsigned char *buf
,
25 struct jffs2_raw_inode
*ri
;
28 unsigned char *decomprbuf
= NULL
;
29 unsigned char *readbuf
= NULL
;
32 ri
= jffs2_alloc_raw_inode();
36 ret
= jffs2_flash_read(c
, ref_offset(fd
->raw
), sizeof(*ri
), &readlen
, (char *)ri
);
38 jffs2_free_raw_inode(ri
);
39 printk(KERN_WARNING
"Error reading node from 0x%08x: %d\n", ref_offset(fd
->raw
), ret
);
42 if (readlen
!= sizeof(*ri
)) {
43 jffs2_free_raw_inode(ri
);
44 printk(KERN_WARNING
"Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n",
45 ref_offset(fd
->raw
), sizeof(*ri
), readlen
);
48 crc
= crc32(0, ri
, sizeof(*ri
)-8);
50 D1(printk(KERN_DEBUG
"Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
51 ref_offset(fd
->raw
), je32_to_cpu(ri
->node_crc
),
52 crc
, je32_to_cpu(ri
->dsize
), je32_to_cpu(ri
->csize
),
53 je32_to_cpu(ri
->offset
), buf
));
54 if (crc
!= je32_to_cpu(ri
->node_crc
)) {
55 printk(KERN_WARNING
"Node CRC %08x != calculated CRC %08x for node at %08x\n",
56 je32_to_cpu(ri
->node_crc
), crc
, ref_offset(fd
->raw
));
60 /* There was a bug where we wrote hole nodes out with csize/dsize
61 swapped. Deal with it */
62 if (ri
->compr
== JFFS2_COMPR_ZERO
&& !je32_to_cpu(ri
->dsize
) &&
63 je32_to_cpu(ri
->csize
)) {
64 ri
->dsize
= ri
->csize
;
65 ri
->csize
= cpu_to_je32(0);
68 D1(if(ofs
+ len
> je32_to_cpu(ri
->dsize
)) {
69 printk(KERN_WARNING
"jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
70 len
, ofs
, je32_to_cpu(ri
->dsize
));
76 if (ri
->compr
== JFFS2_COMPR_ZERO
) {
82 Reading whole node and it's uncompressed - read directly to buffer provided, check CRC.
83 Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided
84 Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy
85 Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
87 if (ri
->compr
== JFFS2_COMPR_NONE
&& len
== je32_to_cpu(ri
->dsize
)) {
90 readbuf
= kmalloc(je32_to_cpu(ri
->csize
), GFP_KERNEL
);
96 if (ri
->compr
!= JFFS2_COMPR_NONE
) {
97 if (len
< je32_to_cpu(ri
->dsize
)) {
98 decomprbuf
= kmalloc(je32_to_cpu(ri
->dsize
), GFP_KERNEL
);
107 decomprbuf
= readbuf
;
110 D2(printk(KERN_DEBUG
"Read %d bytes to %p\n", je32_to_cpu(ri
->csize
),
112 ret
= jffs2_flash_read(c
, (ref_offset(fd
->raw
)) + sizeof(*ri
),
113 je32_to_cpu(ri
->csize
), &readlen
, readbuf
);
115 if (!ret
&& readlen
!= je32_to_cpu(ri
->csize
))
120 crc
= crc32(0, readbuf
, je32_to_cpu(ri
->csize
));
121 if (crc
!= je32_to_cpu(ri
->data_crc
)) {
122 printk(KERN_WARNING
"Data CRC %08x != calculated CRC %08x for node at %08x\n",
123 je32_to_cpu(ri
->data_crc
), crc
, ref_offset(fd
->raw
));
127 D2(printk(KERN_DEBUG
"Data CRC matches calculated CRC %08x\n", crc
));
128 if (ri
->compr
!= JFFS2_COMPR_NONE
) {
129 D2(printk(KERN_DEBUG
"Decompress %d bytes from %p to %d bytes at %p\n",
130 je32_to_cpu(ri
->csize
), readbuf
, je32_to_cpu(ri
->dsize
), decomprbuf
));
131 ret
= jffs2_decompress(c
, f
, ri
->compr
| (ri
->usercompr
<< 8), readbuf
, decomprbuf
, je32_to_cpu(ri
->csize
), je32_to_cpu(ri
->dsize
));
133 printk(KERN_WARNING
"Error: jffs2_decompress returned %d\n", ret
);
138 if (len
< je32_to_cpu(ri
->dsize
)) {
139 memcpy(buf
, decomprbuf
+ofs
, len
);
142 if(decomprbuf
!= buf
&& decomprbuf
!= readbuf
)
148 jffs2_free_raw_inode(ri
);
153 int jffs2_read_inode_range(struct jffs2_sb_info
*c
, struct jffs2_inode_info
*f
,
154 unsigned char *buf
, uint32_t offset
, uint32_t len
)
156 uint32_t end
= offset
+ len
;
157 struct jffs2_node_frag
*frag
;
160 D1(printk(KERN_DEBUG
"jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n",
161 f
->inocache
->ino
, offset
, offset
+len
));
163 frag
= jffs2_lookup_node_frag(&f
->fragtree
, offset
);
165 /* XXX FIXME: Where a single physical node actually shows up in two
166 frags, we read it twice. Don't do that. */
167 /* Now we're pointing at the first frag which overlaps our page */
168 while(offset
< end
) {
169 D2(printk(KERN_DEBUG
"jffs2_read_inode_range: offset %d, end %d\n", offset
, end
));
170 if (unlikely(!frag
|| frag
->ofs
> offset
)) {
171 uint32_t holesize
= end
- offset
;
173 D1(printk(KERN_NOTICE
"Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f
->inocache
->ino
, frag
->ofs
, offset
));
174 holesize
= min(holesize
, frag
->ofs
- offset
);
176 D1(printk(KERN_DEBUG
"Filling non-frag hole from %d-%d\n", offset
, offset
+holesize
));
177 memset(buf
, 0, holesize
);
181 } else if (unlikely(!frag
->node
)) {
182 uint32_t holeend
= min(end
, frag
->ofs
+ frag
->size
);
183 D1(printk(KERN_DEBUG
"Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset
, holeend
, frag
->ofs
, frag
->ofs
+ frag
->size
));
184 memset(buf
, 0, holeend
- offset
);
185 buf
+= holeend
- offset
;
187 frag
= frag_next(frag
);
191 uint32_t fragofs
; /* offset within the frag to start reading */
193 fragofs
= offset
- frag
->ofs
;
194 readlen
= min(frag
->size
- fragofs
, end
- offset
);
195 D1(printk(KERN_DEBUG
"Reading %d-%d from node at 0x%08x (%d)\n",
196 frag
->ofs
+fragofs
, frag
->ofs
+fragofs
+readlen
,
197 ref_offset(frag
->node
->raw
), ref_flags(frag
->node
->raw
)));
198 ret
= jffs2_read_dnode(c
, f
, frag
->node
, buf
, fragofs
+ frag
->ofs
- frag
->node
->ofs
, readlen
);
199 D2(printk(KERN_DEBUG
"node read done\n"));
201 D1(printk(KERN_DEBUG
"jffs2_read_inode_range error %d\n",ret
));
202 memset(buf
, 0, readlen
);
207 frag
= frag_next(frag
);
208 D2(printk(KERN_DEBUG
"node read was OK. Looping\n"));
This page took 0.035205 seconds and 5 git commands to generate.