GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,7 @@
config FS_JFFS2
bool "Enable JFFS2 filesystem support"
help
This provides support for reading images from JFFS2 (Journalling
Flash File System version 2). JFFS2 is a log-structured file system
for use with flash memory devices. It supports raw NAND devices,
hard links and compression.
@@ -0,0 +1,30 @@
The files in this directory and elsewhere which refer to this LICENCE
file are part of JFFS2, the Journalling Flash File System v2.
Copyright © 2001-2007 Red Hat, Inc. and others
JFFS2 is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 or (at your option) any later
version.
JFFS2 is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with JFFS2; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
As a special exception, if other files instantiate templates or use
macros or inline functions from these files, or you compile these
files and link them with other works to produce a work based on these
files, these files do not by themselves cause the resulting work to be
covered by the GNU General Public License. However the source code for
these files must still be made available in accordance with section (3)
of the GNU General Public License.
This exception does not invalidate any other reasons why a work based on
this file might be covered by the GNU General Public License.
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
obj-$(CONFIG_JFFS2_LZO) += compr_lzo.o
obj-y += compr_rtime.o
obj-y += compr_rubin.o
obj-y += compr_zlib.o
obj-y += jffs2_1pass.o
obj-$(CONFIG_SYS_JFFS2_SORT_FRAGMENTS) += mergesort.o
obj-y += mini_inflate.o
@@ -0,0 +1,401 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2004 Patrik Kluba,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in the
* jffs2 directory.
*
* $Id: compr_lzo.c,v 1.3 2004/06/23 16:34:39 havasi Exp $
*
*/
/*
LZO1X-1 (and -999) compression module for jffs2
based on the original LZO sources
*/
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
Original copyright notice follows:
lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
lzo_ptr.h -- low-level pointer constructs
lzo_swd.ch -- sliding window dictionary
lzoconf.h -- configuration for the LZO real-time data compression library
lzo_mchw.ch -- matching functions using a window
minilzo.c -- mini subset of the LZO real-time data compression library
config1x.h -- configuration for the LZO1X algorithm
lzo1x.h -- public interface of the LZO1X compression algorithm
These files are part of the LZO real-time data compression library.
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
*/
/*
2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
Initial release
-removed all 16 bit code
-all sensitive data will be on 4 byte boundary
-removed check parts for library use
-removed all but LZO1X-* compression
*/
#include <config.h>
#include <linux/stddef.h>
#include <jffs2/jffs2.h>
#include <jffs2/compr_rubin.h>
/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
typedef unsigned long lzo_ptr_t;
typedef long lzo_sptr_t;
/* data type definitions */
#define U32 unsigned long
#define S32 signed long
#define I32 long
#define U16 unsigned short
#define S16 signed short
#define I16 short
#define U8 unsigned char
#define S8 signed char
#define I8 char
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
#define M3_MAX_OFFSET 0x4000
#define M4_MAX_OFFSET 0xbfff
#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
#define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
#define TEST_IP (ip < ip_end)
#define TEST_OP (op <= op_end)
#define NEED_IP(x) \
if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
#define NEED_OP(x) \
if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
#define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
typedef U32 lzo_uint32;
typedef I32 lzo_int32;
typedef U32 lzo_uint;
typedef I32 lzo_int;
typedef int lzo_bool;
#define lzo_byte U8
#define lzo_bytep U8 *
#define lzo_charp char *
#define lzo_voidp void *
#define lzo_shortp short *
#define lzo_ushortp unsigned short *
#define lzo_uint32p lzo_uint32 *
#define lzo_int32p lzo_int32 *
#define lzo_uintp lzo_uint *
#define lzo_intp lzo_int *
#define lzo_voidpp lzo_voidp *
#define lzo_bytepp lzo_bytep *
#define lzo_sizeof_dict_t sizeof(lzo_bytep)
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define PTR(a) ((lzo_ptr_t) (a))
#define PTR_LINEAR(a) PTR(a)
#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
#define PTR_LT(a,b) (PTR(a) < PTR(b))
#define PTR_GE(a,b) (PTR(a) >= PTR(b))
#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
#define pd(a,b) ((lzo_uint) ((a)-(b)))
typedef ptrdiff_t lzo_ptrdiff_t;
static int
lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
{
register lzo_byte *op;
register const lzo_byte *ip;
register lzo_uint t;
register const lzo_byte *m_pos;
const lzo_byte *const ip_end = in + in_len;
lzo_byte *const op_end = out + *out_len;
*out_len = 0;
op = out;
ip = in;
if (*ip > 17)
{
t = *ip++ - 17;
if (t < 4)
goto match_next;
NEED_OP (t);
NEED_IP (t + 1);
do
*op++ = *ip++;
while (--t > 0);
goto first_literal_run;
}
while (TEST_IP && TEST_OP)
{
t = *ip++;
if (t >= 16)
goto match;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 15 + *ip++;
}
NEED_OP (t + 3);
NEED_IP (t + 4);
if (PTR_ALIGNED2_4 (op, ip))
{
COPY4 (op, ip);
op += 4;
ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do
{
COPY4 (op, ip);
op += 4;
ip += 4;
t -= 4;
}
while (t >= 4);
if (t > 0)
do
*op++ = *ip++;
while (--t > 0);
}
else
do
*op++ = *ip++;
while (--t > 0);
}
}
else
{
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
do
*op++ = *ip++;
while (--t > 0);
}
first_literal_run:
t = *ip++;
if (t >= 16)
goto match;
m_pos = op - (1 + M2_MAX_OFFSET);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (3);
*op++ = *m_pos++;
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
while (TEST_IP && TEST_OP)
{
match:
if (t >= 64)
{
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (t + 3 - 1);
goto copy_match;
}
else if (t >= 32)
{
t &= 31;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
}
else if (t >= 16)
{
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0)
{
NEED_IP (1);
while (*ip == 0)
{
t += 255;
ip++;
NEED_IP (1);
}
t += 7 + *ip++;
}
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
}
else
{
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (2);
*op++ = *m_pos++;
*op++ = *m_pos;
goto match_done;
}
TEST_LOOKBEHIND (m_pos, out);
NEED_OP (t + 3 - 1);
if (t >= 2 * 4 - (3 - 1)
&& PTR_ALIGNED2_4 (op, m_pos))
{
COPY4 (op, m_pos);
op += 4;
m_pos += 4;
t -= 4 - (3 - 1);
do
{
COPY4 (op, m_pos);
op += 4;
m_pos += 4;
t -= 4;
}
while (t >= 4);
if (t > 0)
do
*op++ = *m_pos++;
while (--t > 0);
}
else
{
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
do
*op++ = *m_pos++;
while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
NEED_OP (t);
NEED_IP (t + 1);
do
*op++ = *ip++;
while (--t > 0);
t = *ip++;
}
}
*out_len = op - out;
return LZO_E_EOF_NOT_FOUND;
eof_found:
*out_len = op - out;
return (ip == ip_end ? LZO_E_OK :
(ip <
ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
input_overrun:
*out_len = op - out;
return LZO_E_INPUT_OVERRUN;
output_overrun:
*out_len = op - out;
return LZO_E_OUTPUT_OVERRUN;
lookbehind_overrun:
*out_len = op - out;
return LZO_E_LOOKBEHIND_OVERRUN;
}
int lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
u32 srclen, u32 destlen)
{
lzo_uint outlen = destlen;
return lzo1x_decompress (data_in, srclen, cpage_out, &outlen, NULL);
}
@@ -0,0 +1,87 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rtime.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*
* Very simple lz77-ish encoder.
*
* Theory of operation: Both encoder and decoder have a list of "last
* occurances" for every possible source-value; after sending the
* first source-byte, the second byte indicated the "run" length of
* matches
*
* The algorithm is intended to only send "whole bytes", no bit-messing.
*
*/
#include <config.h>
#include <jffs2/jffs2.h>
void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out,
u32 srclen, u32 destlen)
{
int positions[256];
int outpos;
int pos;
int i;
outpos = pos = 0;
for (i = 0; i < 256; positions[i++] = 0);
while (outpos<destlen) {
unsigned char value;
int backoffs;
int repeat;
value = data_in[pos++];
cpage_out[outpos++] = value; /* first the verbatim copied byte */
repeat = data_in[pos++];
backoffs = positions[value];
positions[value]=outpos;
if (repeat) {
if (backoffs + repeat >= outpos) {
while(repeat) {
cpage_out[outpos++] = cpage_out[backoffs++];
repeat--;
}
} else {
for (i = 0; i < repeat; i++)
*(cpage_out + outpos + i) = *(cpage_out + backoffs + i);
outpos+=repeat;
}
}
}
}
@@ -0,0 +1,122 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* Heavily modified by Russ Dill <Russ.Dill@asu.edu> in an attempt at
* a little more speed.
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rubin.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*/
#include <config.h>
#include <jffs2/jffs2.h>
#include <jffs2/compr_rubin.h>
void rubin_do_decompress(unsigned char *bits, unsigned char *in,
unsigned char *page_out, __u32 destlen)
{
register char *curr = (char *)page_out;
char *end = (char *)(page_out + destlen);
register unsigned long temp;
register unsigned long result;
register unsigned long p;
register unsigned long q;
register unsigned long rec_q;
register unsigned long bit;
register long i0;
unsigned long i;
/* init_pushpull */
temp = *(u32 *) in;
bit = 16;
/* init_rubin */
q = 0;
p = (long) (2 * UPPER_BIT_RUBIN);
/* init_decode */
rec_q = (in[0] << 8) | in[1];
while (curr < end) {
/* in byte */
result = 0;
for (i = 0; i < 8; i++) {
/* decode */
while ((q & UPPER_BIT_RUBIN) || ((p + q) <= UPPER_BIT_RUBIN)) {
q &= ~UPPER_BIT_RUBIN;
q <<= 1;
p <<= 1;
rec_q &= ~UPPER_BIT_RUBIN;
rec_q <<= 1;
rec_q |= (temp >> (bit++ ^ 7)) & 1;
if (bit > 31) {
u32 *p = (u32 *)in;
bit = 0;
temp = *(++p);
in = (unsigned char *)p;
}
}
i0 = (bits[i] * p) >> 8;
if (i0 <= 0) i0 = 1;
/* if it fails, it fails, we have our crc
if (i0 >= p) i0 = p - 1; */
result >>= 1;
if (rec_q < q + i0) {
/* result |= 0x00; */
p = i0;
} else {
result |= 0x80;
p -= i0;
q += i0;
}
}
*(curr++) = result;
}
}
void dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out,
unsigned long sourcelen, unsigned long dstlen)
{
unsigned char bits[8];
int c;
for (c=0; c<8; c++)
bits[c] = (256 - data_in[c]);
rubin_do_decompress(bits, data_in+8, cpage_out, dstlen);
}
@@ -0,0 +1,48 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001 Red Hat, Inc.
*
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
*
* The original JFFS, from which the design for JFFS2 was derived,
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_zlib.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $
*
*/
#include <common.h>
#include <config.h>
#include <jffs2/jffs2.h>
#include <jffs2/mini_inflate.h>
long zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
__u32 srclen, __u32 destlen)
{
return (decompress_block(cpage_out, data_in + 2, (void *) ldr_memcpy));
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
#ifndef jffs2_private_h
#define jffs2_private_h
#include <jffs2/jffs2.h>
struct b_node {
u32 offset;
struct b_node *next;
enum { CRC_UNKNOWN = 0, CRC_OK, CRC_BAD } datacrc;
};
struct b_list {
struct b_node *listTail;
struct b_node *listHead;
#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
struct b_node *listLast;
int (*listCompare)(struct b_node *new, struct b_node *node);
u32 listLoops;
#endif
u32 listCount;
struct mem_block *listMemBase;
};
struct b_lists {
struct b_list dir;
struct b_list frag;
void *readbuf;
};
struct b_compr_info {
u32 num_frags;
u32 compr_sum;
u32 decompr_sum;
};
struct b_jffs2_info {
struct b_compr_info compr_info[JFFS2_NUM_COMPR];
};
static inline int
hdr_crc(struct jffs2_unknown_node *node)
{
#if 1
u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
#else
/* what's the semantics of this? why is this here? */
u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
crc ^= ~0;
#endif
if (node->hdr_crc != crc) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_crc(struct jffs2_raw_dirent *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_dirent) - 8)) {
return 0;
} else {
return 1;
}
}
static inline int
dirent_name_crc(struct jffs2_raw_dirent *node)
{
if (node->name_crc != crc32_no_comp(0, (unsigned char *)&(node->name), node->nsize)) {
return 0;
} else {
return 1;
}
}
static inline int
inode_crc(struct jffs2_raw_inode *node)
{
if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_inode) - 8)) {
return 0;
} else {
return 1;
}
}
static inline int
data_crc(struct jffs2_raw_inode *node)
{
if (node->data_crc != crc32_no_comp(0, (unsigned char *)
((int) &node->node_crc + sizeof (node->node_crc)),
node->csize)) {
return 0;
} else {
return 1;
}
}
#if defined(CONFIG_SYS_JFFS2_SORT_FRAGMENTS)
/* External merge sort. */
int sort_list(struct b_list *list);
#endif
#endif /* jffs2_private.h */
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
/*
* This file is copyright 2001 Simon Tatham.
* Rewritten from original source 2006 by Dan Merillat for use in u-boot.
*
* Original code can be found at:
* http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
*/
#include <common.h>
#include "jffs2_private.h"
int sort_list(struct b_list *list)
{
struct b_node *p, *q, *e, **tail;
int k, psize, qsize;
if (!list->listHead)
return 0;
for (k = 1; k < list->listCount; k *= 2) {
tail = &list->listHead;
for (p = q = list->listHead; p; p = q) {
/* step 'k' places from p; */
for (psize = 0; q && psize < k; psize++)
q = q->next;
qsize = k;
/* two lists, merge them. */
while (psize || (qsize && q)) {
/* merge the next element */
if (psize == 0 ||
((qsize && q) &&
list->listCompare(p, q))) {
/* p is empty, or p > q, so q next */
e = q;
q = q->next;
qsize--;
} else {
e = p;
p = p->next;
psize--;
}
e->next = NULL; /* break accidental loops. */
*tail = e;
tail = &e->next;
}
}
}
return 0;
}
@@ -0,0 +1,375 @@
// SPDX-License-Identifier: GPL-2.0+
/*-------------------------------------------------------------------------
* Filename: mini_inflate.c
* Version: $Id: mini_inflate.c,v 1.3 2002/01/24 22:58:42 rfeany Exp $
* Copyright: Copyright (C) 2001, Russ Dill
* Author: Russ Dill <Russ.Dill@asu.edu>
* Description: Mini inflate implementation (RFC 1951)
*-----------------------------------------------------------------------*/
#include <config.h>
#include <jffs2/mini_inflate.h>
/* The order that the code lengths in section 3.2.7 are in */
static unsigned char huffman_order[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
11, 4, 12, 3, 13, 2, 14, 1, 15};
static inline void cramfs_memset(int *s, const int c, size n)
{
n--;
for (;n > 0; n--) s[n] = c;
s[0] = c;
}
/* associate a stream with a block of data and reset the stream */
static void init_stream(struct bitstream *stream, unsigned char *data,
void *(*inflate_memcpy)(void *, const void *, size))
{
stream->error = NO_ERROR;
stream->memcpy = inflate_memcpy;
stream->decoded = 0;
stream->data = data;
stream->bit = 0; /* The first bit of the stream is the lsb of the
* first byte */
/* really sorry about all this initialization, think of a better way,
* let me know and it will get cleaned up */
stream->codes.bits = 8;
stream->codes.num_symbols = 19;
stream->codes.lengths = stream->code_lengths;
stream->codes.symbols = stream->code_symbols;
stream->codes.count = stream->code_count;
stream->codes.first = stream->code_first;
stream->codes.pos = stream->code_pos;
stream->lengths.bits = 16;
stream->lengths.num_symbols = 288;
stream->lengths.lengths = stream->length_lengths;
stream->lengths.symbols = stream->length_symbols;
stream->lengths.count = stream->length_count;
stream->lengths.first = stream->length_first;
stream->lengths.pos = stream->length_pos;
stream->distance.bits = 16;
stream->distance.num_symbols = 32;
stream->distance.lengths = stream->distance_lengths;
stream->distance.symbols = stream->distance_symbols;
stream->distance.count = stream->distance_count;
stream->distance.first = stream->distance_first;
stream->distance.pos = stream->distance_pos;
}
/* pull 'bits' bits out of the stream. The last bit pulled it returned as the
* msb. (section 3.1.1)
*/
static inline unsigned long pull_bits(struct bitstream *stream,
const unsigned int bits)
{
unsigned long ret;
int i;
ret = 0;
for (i = 0; i < bits; i++) {
ret += ((*(stream->data) >> stream->bit) & 1) << i;
/* if, before incrementing, we are on bit 7,
* go to the lsb of the next byte */
if (stream->bit++ == 7) {
stream->bit = 0;
stream->data++;
}
}
return ret;
}
static inline int pull_bit(struct bitstream *stream)
{
int ret = ((*(stream->data) >> stream->bit) & 1);
if (stream->bit++ == 7) {
stream->bit = 0;
stream->data++;
}
return ret;
}
/* discard bits up to the next whole byte */
static void discard_bits(struct bitstream *stream)
{
if (stream->bit != 0) {
stream->bit = 0;
stream->data++;
}
}
/* No decompression, the data is all literals (section 3.2.4) */
static void decompress_none(struct bitstream *stream, unsigned char *dest)
{
unsigned int length;
discard_bits(stream);
length = *(stream->data++);
length += *(stream->data++) << 8;
pull_bits(stream, 16); /* throw away the inverse of the size */
stream->decoded += length;
stream->memcpy(dest, stream->data, length);
stream->data += length;
}
/* Read in a symbol from the stream (section 3.2.2) */
static int read_symbol(struct bitstream *stream, struct huffman_set *set)
{
int bits = 0;
int code = 0;
while (!(set->count[bits] && code < set->first[bits] +
set->count[bits])) {
code = (code << 1) + pull_bit(stream);
if (++bits > set->bits) {
/* error decoding (corrupted data?) */
stream->error = CODE_NOT_FOUND;
return -1;
}
}
return set->symbols[set->pos[bits] + code - set->first[bits]];
}
/* decompress a stream of data encoded with the passed length and distance
* huffman codes */
static void decompress_huffman(struct bitstream *stream, unsigned char *dest)
{
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
int symbol, length, dist, i;
do {
if ((symbol = read_symbol(stream, lengths)) < 0) return;
if (symbol < 256) {
*(dest++) = symbol; /* symbol is a literal */
stream->decoded++;
} else if (symbol > 256) {
/* Determine the length of the repitition
* (section 3.2.5) */
if (symbol < 265) length = symbol - 254;
else if (symbol == 285) length = 258;
else {
length = pull_bits(stream, (symbol - 261) >> 2);
length += (4 << ((symbol - 261) >> 2)) + 3;
length += ((symbol - 1) % 4) <<
((symbol - 261) >> 2);
}
/* Determine how far back to go */
if ((symbol = read_symbol(stream, distance)) < 0)
return;
if (symbol < 4) dist = symbol + 1;
else {
dist = pull_bits(stream, (symbol - 2) >> 1);
dist += (2 << ((symbol - 2) >> 1)) + 1;
dist += (symbol % 2) << ((symbol - 2) >> 1);
}
stream->decoded += length;
for (i = 0; i < length; i++) {
*dest = dest[-dist];
dest++;
}
}
} while (symbol != 256); /* 256 is the end of the data block */
}
/* Fill the lookup tables (section 3.2.2) */
static void fill_code_tables(struct huffman_set *set)
{
int code = 0, i, length;
/* fill in the first code of each bit length, and the pos pointer */
set->pos[0] = 0;
for (i = 1; i < set->bits; i++) {
code = (code + set->count[i - 1]) << 1;
set->first[i] = code;
set->pos[i] = set->pos[i - 1] + set->count[i - 1];
}
/* Fill in the table of symbols in order of their huffman code */
for (i = 0; i < set->num_symbols; i++) {
if ((length = set->lengths[i]))
set->symbols[set->pos[length]++] = i;
}
/* reset the pos pointer */
for (i = 1; i < set->bits; i++) set->pos[i] -= set->count[i];
}
static void init_code_tables(struct huffman_set *set)
{
cramfs_memset(set->lengths, 0, set->num_symbols);
cramfs_memset(set->count, 0, set->bits);
cramfs_memset(set->first, 0, set->bits);
}
/* read in the huffman codes for dynamic decoding (section 3.2.7) */
static void decompress_dynamic(struct bitstream *stream, unsigned char *dest)
{
/* I tried my best to minimize the memory footprint here, while still
* keeping up performance. I really dislike the _lengths[] tables, but
* I see no way of eliminating them without a sizable performance
* impact. The first struct table keeps track of stats on each bit
* length. The _length table keeps a record of the bit length of each
* symbol. The _symbols table is for looking up symbols by the huffman
* code (the pos element points to the first place in the symbol table
* where that bit length occurs). I also hate the initization of these
* structs, if someone knows how to compact these, lemme know. */
struct huffman_set *codes = &(stream->codes);
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
int hlit = pull_bits(stream, 5) + 257;
int hdist = pull_bits(stream, 5) + 1;
int hclen = pull_bits(stream, 4) + 4;
int length, curr_code, symbol, i, last_code;
last_code = 0;
init_code_tables(codes);
init_code_tables(lengths);
init_code_tables(distance);
/* fill in the count of each bit length' as well as the lengths
* table */
for (i = 0; i < hclen; i++) {
length = pull_bits(stream, 3);
codes->lengths[huffman_order[i]] = length;
if (length) codes->count[length]++;
}
fill_code_tables(codes);
/* Do the same for the length codes, being carefull of wrap through
* to the distance table */
curr_code = 0;
while (curr_code < hlit) {
if ((symbol = read_symbol(stream, codes)) < 0) return;
if (symbol == 0) {
curr_code++;
last_code = 0;
} else if (symbol < 16) { /* Literal length */
lengths->lengths[curr_code] = last_code = symbol;
lengths->count[symbol]++;
curr_code++;
} else if (symbol == 16) { /* repeat the last symbol 3 - 6
* times */
length = 3 + pull_bits(stream, 2);
for (;length; length--, curr_code++)
if (curr_code < hlit) {
lengths->lengths[curr_code] =
last_code;
lengths->count[last_code]++;
} else { /* wrap to the distance table */
distance->lengths[curr_code - hlit] =
last_code;
distance->count[last_code]++;
}
} else if (symbol == 17) { /* repeat a bit length 0 */
curr_code += 3 + pull_bits(stream, 3);
last_code = 0;
} else { /* same, but more times */
curr_code += 11 + pull_bits(stream, 7);
last_code = 0;
}
}
fill_code_tables(lengths);
/* Fill the distance table, don't need to worry about wrapthrough
* here */
curr_code -= hlit;
while (curr_code < hdist) {
if ((symbol = read_symbol(stream, codes)) < 0) return;
if (symbol == 0) {
curr_code++;
last_code = 0;
} else if (symbol < 16) {
distance->lengths[curr_code] = last_code = symbol;
distance->count[symbol]++;
curr_code++;
} else if (symbol == 16) {
length = 3 + pull_bits(stream, 2);
for (;length; length--, curr_code++) {
distance->lengths[curr_code] =
last_code;
distance->count[last_code]++;
}
} else if (symbol == 17) {
curr_code += 3 + pull_bits(stream, 3);
last_code = 0;
} else {
curr_code += 11 + pull_bits(stream, 7);
last_code = 0;
}
}
fill_code_tables(distance);
decompress_huffman(stream, dest);
}
/* fill in the length and distance huffman codes for fixed encoding
* (section 3.2.6) */
static void decompress_fixed(struct bitstream *stream, unsigned char *dest)
{
/* let gcc fill in the initial values */
struct huffman_set *lengths = &(stream->lengths);
struct huffman_set *distance = &(stream->distance);
cramfs_memset(lengths->count, 0, 16);
cramfs_memset(lengths->first, 0, 16);
cramfs_memset(lengths->lengths, 8, 144);
cramfs_memset(lengths->lengths + 144, 9, 112);
cramfs_memset(lengths->lengths + 256, 7, 24);
cramfs_memset(lengths->lengths + 280, 8, 8);
lengths->count[7] = 24;
lengths->count[8] = 152;
lengths->count[9] = 112;
cramfs_memset(distance->count, 0, 16);
cramfs_memset(distance->first, 0, 16);
cramfs_memset(distance->lengths, 5, 32);
distance->count[5] = 32;
fill_code_tables(lengths);
fill_code_tables(distance);
decompress_huffman(stream, dest);
}
/* returns the number of bytes decoded, < 0 if there was an error. Note that
* this function assumes that the block starts on a byte boundry
* (non-compliant, but I don't see where this would happen). section 3.2.3 */
long decompress_block(unsigned char *dest, unsigned char *source,
void *(*inflate_memcpy)(void *, const void *, size))
{
int bfinal, btype;
struct bitstream stream;
init_stream(&stream, source, inflate_memcpy);
do {
bfinal = pull_bit(&stream);
btype = pull_bits(&stream, 2);
if (btype == NO_COMP) decompress_none(&stream, dest + stream.decoded);
else if (btype == DYNAMIC_COMP)
decompress_dynamic(&stream, dest + stream.decoded);
else if (btype == FIXED_COMP) decompress_fixed(&stream, dest + stream.decoded);
else stream.error = COMP_UNKNOWN;
} while (!bfinal && !stream.error);
#if 0
putstr("decompress_block start\r\n");
putLabeledWord("stream.error = ",stream.error);
putLabeledWord("stream.decoded = ",stream.decoded);
putLabeledWord("dest = ",dest);
putstr("decompress_block end\r\n");
#endif
return stream.error ? -stream.error : stream.decoded;
}
@@ -0,0 +1,163 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* Zoltan Sogor <weth@inf.u-szeged.hu>,
* Patrik Kluba <pajko@halom.u-szeged.hu>,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
#ifndef JFFS2_SUMMARY_H
#define JFFS2_SUMMARY_H
#define BLK_STATE_ALLFF 0
#define BLK_STATE_CLEAN 1
#define BLK_STATE_PARTDIRTY 2
#define BLK_STATE_CLEANMARKER 3
#define BLK_STATE_ALLDIRTY 4
#define BLK_STATE_BADBLOCK 5
#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
/* Summary structures used on flash */
struct jffs2_sum_unknown_flash
{
__u16 nodetype; /* node type */
};
struct jffs2_sum_inode_flash
{
__u16 nodetype; /* node type */
__u32 inode; /* inode number */
__u32 version; /* inode version */
__u32 offset; /* offset on jeb */
__u32 totlen; /* record length */
} __attribute__((packed));
struct jffs2_sum_dirent_flash
{
__u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
__u32 totlen; /* record length */
__u32 offset; /* offset on jeb */
__u32 pino; /* parent inode */
__u32 version; /* dirent version */
__u32 ino; /* == zero for unlink */
uint8_t nsize; /* dirent name size */
uint8_t type; /* dirent type */
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
struct jffs2_sum_xattr_flash
{
__u16 nodetype; /* == JFFS2_NODETYPE_XATR */
__u32 xid; /* xattr identifier */
__u32 version; /* version number */
__u32 offset; /* offset on jeb */
__u32 totlen; /* node length */
} __attribute__((packed));
struct jffs2_sum_xref_flash
{
__u16 nodetype; /* == JFFS2_NODETYPE_XREF */
__u32 offset; /* offset on jeb */
} __attribute__((packed));
union jffs2_sum_flash
{
struct jffs2_sum_unknown_flash u;
struct jffs2_sum_inode_flash i;
struct jffs2_sum_dirent_flash d;
struct jffs2_sum_xattr_flash x;
struct jffs2_sum_xref_flash r;
};
/* Summary structures used in the memory */
struct jffs2_sum_unknown_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* node type */
};
struct jffs2_sum_inode_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* node type */
__u32 inode; /* inode number */
__u32 version; /* inode version */
__u32 offset; /* offset on jeb */
__u32 totlen; /* record length */
} __attribute__((packed));
struct jffs2_sum_dirent_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
__u32 totlen; /* record length */
__u32 offset; /* ofset on jeb */
__u32 pino; /* parent inode */
__u32 version; /* dirent version */
__u32 ino; /* == zero for unlink */
uint8_t nsize; /* dirent name size */
uint8_t type; /* dirent type */
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
struct jffs2_sum_xattr_mem
{
union jffs2_sum_mem *next;
__u16 nodetype;
__u32 xid;
__u32 version;
__u32 offset;
__u32 totlen;
} __attribute__((packed));
struct jffs2_sum_xref_mem
{
union jffs2_sum_mem *next;
__u16 nodetype;
__u32 offset;
} __attribute__((packed));
union jffs2_sum_mem
{
struct jffs2_sum_unknown_mem u;
struct jffs2_sum_inode_mem i;
struct jffs2_sum_dirent_mem d;
struct jffs2_sum_xattr_mem x;
struct jffs2_sum_xref_mem r;
};
/* Summary related information stored in superblock */
struct jffs2_summary
{
uint32_t sum_size; /* collected summary information for nextblock */
uint32_t sum_num;
uint32_t sum_padded;
union jffs2_sum_mem *sum_list_head;
union jffs2_sum_mem *sum_list_tail;
__u32 *sum_buf; /* buffer for writing out summary */
};
/* Summary marker is stored at the end of every sumarized erase block */
struct jffs2_sum_marker
{
__u32 offset; /* offset of the summary node in the jeb */
__u32 magic; /* == JFFS2_SUM_MAGIC */
};
#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker))
#endif /* JFFS2_SUMMARY_H */