Large diffs are not rendered by default.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -18,13 +18,13 @@

#include "yaffs_guts.h"

void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev);
void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev);
void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev);
void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev);

yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev);
void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn);
struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev);
void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn);

yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev);
void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj);
struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev);
void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj);

#endif
@@ -0,0 +1,124 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include "yaffs_guts.h"
#include "yaffs_attribs.h"

void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
{
obj->yst_uid = oh->yst_uid;
obj->yst_gid = oh->yst_gid;
obj->yst_atime = oh->yst_atime;
obj->yst_mtime = oh->yst_mtime;
obj->yst_ctime = oh->yst_ctime;
obj->yst_rdev = oh->yst_rdev;
}

void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
{
oh->yst_uid = obj->yst_uid;
oh->yst_gid = obj->yst_gid;
oh->yst_atime = obj->yst_atime;
oh->yst_mtime = obj->yst_mtime;
oh->yst_ctime = obj->yst_ctime;
oh->yst_rdev = obj->yst_rdev;

}

void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
{
obj->yst_mtime = Y_CURRENT_TIME;
if (do_a)
obj->yst_atime = obj->yst_mtime;
if (do_c)
obj->yst_ctime = obj->yst_mtime;
}

void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
{
yaffs_load_current_time(obj, 1, 1);
obj->yst_rdev = rdev;
obj->yst_uid = uid;
obj->yst_gid = gid;
}

loff_t yaffs_get_file_size(struct yaffs_obj *obj)
{
YCHAR *alias = NULL;
obj = yaffs_get_equivalent_obj(obj);

switch (obj->variant_type) {
case YAFFS_OBJECT_TYPE_FILE:
return obj->variant.file_variant.file_size;
case YAFFS_OBJECT_TYPE_SYMLINK:
alias = obj->variant.symlink_variant.alias;
if (!alias)
return 0;
return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH);
default:
return 0;
}
}

int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
{
unsigned int valid = attr->ia_valid;

if (valid & ATTR_MODE)
obj->yst_mode = attr->ia_mode;
if (valid & ATTR_UID)
obj->yst_uid = attr->ia_uid;
if (valid & ATTR_GID)
obj->yst_gid = attr->ia_gid;

if (valid & ATTR_ATIME)
obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
if (valid & ATTR_CTIME)
obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
if (valid & ATTR_MTIME)
obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);

if (valid & ATTR_SIZE)
yaffs_resize_file(obj, attr->ia_size);

yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);

return YAFFS_OK;

}

int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
{
unsigned int valid = 0;

attr->ia_mode = obj->yst_mode;
valid |= ATTR_MODE;
attr->ia_uid = obj->yst_uid;
valid |= ATTR_UID;
attr->ia_gid = obj->yst_gid;
valid |= ATTR_GID;

Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
valid |= ATTR_ATIME;
Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
valid |= ATTR_CTIME;
Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
valid |= ATTR_MTIME;

attr->ia_size = yaffs_get_file_size(obj);
valid |= ATTR_SIZE;

attr->ia_valid = valid;

return YAFFS_OK;
}
@@ -0,0 +1,28 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/

#ifndef __YAFFS_ATTRIBS_H__
#define __YAFFS_ATTRIBS_H__

#include "yaffs_guts.h"

void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);

#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -17,89 +17,81 @@
* Chunk bitmap manipulations
*/

static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
{
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
blk));
YBUG();
if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
yaffs_trace(YAFFS_TRACE_ERROR,
"BlockBits block %d is not valid",
blk);
BUG();
}
return dev->chunkBits +
(dev->chunkBitmapStride * (blk - dev->internalStartBlock));
return dev->chunk_bits +
(dev->chunk_bit_stride * (blk - dev->internal_start_block));
}

void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk)
void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
{
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock ||
chunk < 0 || chunk >= dev->param.nChunksPerBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),
blk, chunk));
YBUG();
if (blk < dev->internal_start_block || blk > dev->internal_end_block ||
chunk < 0 || chunk >= dev->param.chunks_per_block) {
yaffs_trace(YAFFS_TRACE_ERROR,
"Chunk Id (%d:%d) invalid",
blk, chunk);
BUG();
}
}

void yaffs_ClearChunkBits(yaffs_Device *dev, int blk)
void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
u8 *blk_bits = yaffs_block_bits(dev, blk);

memset(blkBits, 0, dev->chunkBitmapStride);
memset(blk_bits, 0, dev->chunk_bit_stride);
}

void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk)
void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
u8 *blk_bits = yaffs_block_bits(dev, blk);

yaffs_VerifyChunkBitId(dev, blk, chunk);

blkBits[chunk / 8] &= ~(1 << (chunk & 7));
yaffs_verify_chunk_bit_id(dev, blk, chunk);
blk_bits[chunk / 8] &= ~(1 << (chunk & 7));
}

void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk)
void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);

yaffs_VerifyChunkBitId(dev, blk, chunk);
u8 *blk_bits = yaffs_block_bits(dev, blk);

blkBits[chunk / 8] |= (1 << (chunk & 7));
yaffs_verify_chunk_bit_id(dev, blk, chunk);
blk_bits[chunk / 8] |= (1 << (chunk & 7));
}

int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk)
int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
yaffs_VerifyChunkBitId(dev, blk, chunk);
u8 *blk_bits = yaffs_block_bits(dev, blk);

return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
yaffs_verify_chunk_bit_id(dev, blk, chunk);
return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
}

int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk)
int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
u8 *blk_bits = yaffs_block_bits(dev, blk);
int i;
for (i = 0; i < dev->chunkBitmapStride; i++) {
if (*blkBits)

for (i = 0; i < dev->chunk_bit_stride; i++) {
if (*blk_bits)
return 1;
blkBits++;
blk_bits++;
}
return 0;
}

int yaffs_CountChunkBits(yaffs_Device *dev, int blk)
int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
u8 *blk_bits = yaffs_block_bits(dev, blk);
int i;
int n = 0;
for (i = 0; i < dev->chunkBitmapStride; i++) {
__u8 x = *blkBits;
while (x) {
if (x & 1)
n++;
x >>= 1;
}

blkBits++;
}

for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++)
n += hweight8(*blk_bits);

return n;
}

@@ -1,14 +1,16 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/

/*
@@ -20,12 +22,12 @@

#include "yaffs_guts.h"

void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk);
void yaffs_ClearChunkBits(yaffs_Device *dev, int blk);
void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk);
void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk);
int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk);
int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk);
int yaffs_CountChunkBits(yaffs_Device *dev, int blk);
void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk);
void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk);
void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk);
int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk);

#endif

Large diffs are not rendered by default.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -18,17 +18,16 @@

#include "yaffs_guts.h"

int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting);
int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing);

int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes);

int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes);

int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum);

int yaffs2_CheckpointClose(yaffs_Device *dev);

int yaffs2_CheckpointInvalidateStream(yaffs_Device *dev);
int yaffs_checkpt_close(struct yaffs_dev *dev);

int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev);

#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -16,22 +16,22 @@
*
* The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
* The two unused bit are set to 1.
* The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
* blocks are used on a 512-byte NAND page.
* The ECC can correct single bit errors in a 256-byte page of data. Thus, two
* such ECC blocks are used on a 512-byte NAND page.
*
*/

#include "yportenv.h"

#include "yaffs_ecc.h"

/* Table generated by gen-ecc.c
* Using a table means we do not have to calculate p1..p4 and p1'..p4'
* for each byte of data. These are instead provided in a table in bits7..2.
* Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore
* this bytes influence on the line parity.
* Bit 0 of each entry indicates whether the entry has an odd or even parity,
* and therefore this bytes influence on the line parity.
*/

#include "yportenv.h"

#include "yaffs_ecc.h"

static const unsigned char column_parity_table[] = {
0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
@@ -67,35 +67,11 @@ static const unsigned char column_parity_table[] = {
0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
};

/* Count the bits in an unsigned char or a U32 */

static int yaffs_CountBits(unsigned char x)
{
int r = 0;
while (x) {
if (x & 1)
r++;
x >>= 1;
}
return r;
}

static int yaffs_CountBits32(unsigned x)
{
int r = 0;
while (x) {
if (x & 1)
r++;
x >>= 1;
}
return r;
}

/* Calculate the ECC for a 256-byte block of data */
void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc)
{
unsigned int i;

unsigned char col_parity = 0;
unsigned char line_parity = 0;
unsigned char line_parity_prime = 0;
@@ -106,7 +82,7 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
b = column_parity_table[*data++];
col_parity ^= b;

if (b & 0x01) { /* odd number of bits in the byte */
if (b & 0x01) { /* odd number of bits in the byte */
line_parity ^= i;
line_parity_prime ^= ~i;
}
@@ -152,19 +128,12 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
t |= 0x01;
ecc[0] = ~t;

#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
/* Swap the bytes into the wrong order */
t = ecc[0];
ecc[0] = ecc[1];
ecc[1] = t;
#endif
}


/* Correct the ECC on a 256 byte block of data */

int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
const unsigned char *test_ecc)
int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
const unsigned char *test_ecc)
{
unsigned char d0, d1, d2; /* deltas */

@@ -173,7 +142,7 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
d2 = read_ecc[2] ^ test_ecc[2];

if ((d0 | d1 | d2) == 0)
return 0; /* no error */
return 0; /* no error */

if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
@@ -183,15 +152,6 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
unsigned byte;
unsigned bit;

#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
/* swap the bytes to correct for the wrong order */
unsigned char t;

t = d0;
d0 = d1;
d1 = t;
#endif

bit = byte = 0;

if (d1 & 0x80)
@@ -220,19 +180,17 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,

data[byte] ^= (1 << bit);

return 1; /* Corrected the error */
return 1; /* Corrected the error */
}

if ((yaffs_CountBits(d0) +
yaffs_CountBits(d1) +
yaffs_CountBits(d2)) == 1) {
if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
/* Reccoverable error in ecc */

read_ecc[0] = test_ecc[0];
read_ecc[1] = test_ecc[1];
read_ecc[2] = test_ecc[2];

return 1; /* Corrected the error */
return 1; /* Corrected the error */
}

/* Unrecoverable error */
@@ -241,80 +199,80 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,

}


/*
* ECCxxxOther does ECC calcs on arbitrary n bytes of data
*/
void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
yaffs_ECCOther *eccOther)
void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
struct yaffs_ecc_other *ecc_other)
{
unsigned int i;

unsigned char col_parity = 0;
unsigned line_parity = 0;
unsigned line_parity_prime = 0;
unsigned char b;

for (i = 0; i < nBytes; i++) {
for (i = 0; i < n_bytes; i++) {
b = column_parity_table[*data++];
col_parity ^= b;

if (b & 0x01) {
if (b & 0x01) {
/* odd number of bits in the byte */
line_parity ^= i;
line_parity_prime ^= ~i;
}

}

eccOther->colParity = (col_parity >> 2) & 0x3f;
eccOther->lineParity = line_parity;
eccOther->lineParityPrime = line_parity_prime;
ecc_other->col_parity = (col_parity >> 2) & 0x3f;
ecc_other->line_parity = line_parity;
ecc_other->line_parity_prime = line_parity_prime;
}

int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
yaffs_ECCOther *read_ecc,
const yaffs_ECCOther *test_ecc)
int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
struct yaffs_ecc_other *read_ecc,
const struct yaffs_ecc_other *test_ecc)
{
unsigned char cDelta; /* column parity delta */
unsigned lDelta; /* line parity delta */
unsigned lDeltaPrime; /* line parity delta */
unsigned char delta_col; /* column parity delta */
unsigned delta_line; /* line parity delta */
unsigned delta_line_prime; /* line parity delta */
unsigned bit;

cDelta = read_ecc->colParity ^ test_ecc->colParity;
lDelta = read_ecc->lineParity ^ test_ecc->lineParity;
lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime;
delta_col = read_ecc->col_parity ^ test_ecc->col_parity;
delta_line = read_ecc->line_parity ^ test_ecc->line_parity;
delta_line_prime =
read_ecc->line_parity_prime ^ test_ecc->line_parity_prime;

if ((cDelta | lDelta | lDeltaPrime) == 0)
return 0; /* no error */
if ((delta_col | delta_line | delta_line_prime) == 0)
return 0; /* no error */

if (lDelta == ~lDeltaPrime &&
(((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) {
if (delta_line == ~delta_line_prime &&
(((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) {
/* Single bit (recoverable) error in data */

bit = 0;

if (cDelta & 0x20)
if (delta_col & 0x20)
bit |= 0x04;
if (cDelta & 0x08)
if (delta_col & 0x08)
bit |= 0x02;
if (cDelta & 0x02)
if (delta_col & 0x02)
bit |= 0x01;

if (lDelta >= nBytes)
if (delta_line >= n_bytes)
return -1;

data[lDelta] ^= (1 << bit);
data[delta_line] ^= (1 << bit);

return 1; /* corrected */
return 1; /* corrected */
}

if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
yaffs_CountBits(cDelta)) == 1) {
if ((hweight32(delta_line) +
hweight32(delta_line_prime) +
hweight8(delta_col)) == 1) {
/* Reccoverable error in ecc */

*read_ecc = *test_ecc;
return 1; /* corrected */
return 1; /* corrected */
}

/* Unrecoverable error */
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -18,27 +18,27 @@
*
* The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
* The two unused bit are set to 1.
* The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
* blocks are used on a 512-byte NAND page.
* The ECC can correct single bit errors in a 256-byte page of data.
* Thus, two such ECC blocks are used on a 512-byte NAND page.
*
*/

#ifndef __YAFFS_ECC_H__
#define __YAFFS_ECC_H__

typedef struct {
unsigned char colParity;
unsigned lineParity;
unsigned lineParityPrime;
} yaffs_ECCOther;
struct yaffs_ecc_other {
unsigned char col_parity;
unsigned line_parity;
unsigned line_parity_prime;
};

void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
const unsigned char *test_ecc);
void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc);
int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
const unsigned char *test_ecc);

void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
yaffs_ECCOther *ecc);
int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
yaffs_ECCOther *read_ecc,
const yaffs_ECCOther *test_ecc);
void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
struct yaffs_ecc_other *ecc);
int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
struct yaffs_ecc_other *read_ecc,
const struct yaffs_ecc_other *test_ecc);
#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -20,16 +20,16 @@
#include "yaffs_trace.h"

/* Function to manipulate block info */
static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev
*dev, int blk)
{
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR
("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
blk));
YBUG();
if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
yaffs_trace(YAFFS_TRACE_ERROR,
"**>> yaffs: get_block_info block %d is not valid",
blk);
BUG();
}
return &dev->blockInfo[blk - dev->internalStartBlock];
return &dev->block_info[blk - dev->internal_start_block];
}

#endif

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -16,28 +16,26 @@
#ifndef __YAFFS_LINUX_H__
#define __YAFFS_LINUX_H__

#include "devextras.h"
#include "yportenv.h"

struct yaffs_LinuxContext {
struct ylist_head contextList; /* List of these we have mounted */
struct yaffs_DeviceStruct *dev;
struct super_block * superBlock;
struct task_struct *bgThread; /* Background thread for this device */
int bgRunning;
struct semaphore grossLock; /* Gross locking semaphore */
__u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
struct yaffs_linux_context {
struct list_head context_list; /* List of these we have mounted */
struct yaffs_dev *dev;
struct super_block *super;
struct task_struct *bg_thread; /* Background thread for this device */
int bg_running;
struct mutex gross_lock; /* Gross locking mutex*/
u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size
* at compile time so we have to allocate it.
*/
struct ylist_head searchContexts;
void (*putSuperFunc)(struct super_block *sb);
struct list_head search_contexts;
void (*put_super_fn) (struct super_block *sb);

struct task_struct *readdirProcess;
struct task_struct *readdir_process;
unsigned mount_id;
};

#define yaffs_DeviceToLC(dev) ((struct yaffs_LinuxContext *)((dev)->osContext))
#define yaffs_DeviceToMtd(dev) ((struct mtd_info *)((dev)->driverContext))
#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context))
#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context))

#endif

This file was deleted.

This file was deleted.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -13,7 +13,6 @@

#include "yportenv.h"


#include "yaffs_mtdif.h"

#include "linux/mtd/mtd.h"
@@ -23,19 +22,18 @@

#include "yaffs_linux.h"

int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
__u32 addr =
((loff_t) blockNumber) * dev->param.totalBytesPerChunk
* dev->param.nChunksPerBlock;
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
u32 addr =
((loff_t) block_no) * dev->param.total_bytes_per_chunk *
dev->param.chunks_per_block;
struct erase_info ei;

int retval = 0;

ei.mtd = mtd;
ei.addr = addr;
ei.len = dev->param.totalBytesPerChunk * dev->param.nChunksPerBlock;
ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
ei.time = 1000;
ei.retries = 2;
ei.callback = NULL;
@@ -45,12 +43,11 @@ int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)

if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;

return YAFFS_FAIL;
}

int nandmtd_InitialiseNAND(yaffs_Device *dev)
int nandmtd_initialise(struct yaffs_dev *dev)
{
return YAFFS_OK;
}

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -18,10 +18,6 @@

#include "yaffs_guts.h"

#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18))
extern struct nand_oobinfo yaffs_oobinfo;
extern struct nand_oobinfo yaffs_noeccinfo;
#endif
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int nandmtd_InitialiseNAND(yaffs_Device *dev);
int nandmtd_erase_block(struct yaffs_dev *dev, int block_no);
int nandmtd_initialise(struct yaffs_dev *dev);
#endif

Large diffs are not rendered by default.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* This program is free software; you can redistribute it and/or modify
@@ -14,15 +14,16 @@
#ifndef __YAFFS_MTDIF1_H__
#define __YAFFS_MTDIF1_H__

int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data, const yaffs_ExtendedTags *tags);
int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
const u8 *data,
const struct yaffs_ext_tags *tags);

int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *data, yaffs_ExtendedTags *tags);
int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
u8 *data, struct yaffs_ext_tags *tags);

int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no);

int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *state, __u32 *sequenceNumber);
int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
enum yaffs_block_state *state, u32 *seq_number);

#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -27,14 +27,14 @@
#include "yaffs_linux.h"

/* NB For use with inband tags....
* We assume that the data buffer is of size totalBytersPerChunk so that we can also
* use it to load the tags.
* We assume that the data buffer is of size total_bytes_per_chunk so
* that we can also use it to load the tags.
*/
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data,
const yaffs_ExtendedTags *tags)
int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
const u8 *data,
const struct yaffs_ext_tags *tags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#else
@@ -44,50 +44,54 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,

loff_t addr;

yaffs_PackedTags2 pt;
struct yaffs_packed_tags2 pt;

int packed_tags_size = dev->param.noTagsECC ? sizeof(pt.t) : sizeof(pt);
void * packed_tags_ptr = dev->param.noTagsECC ? (void *) &pt.t : (void *)&pt;
int packed_tags_size =
dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
void *packed_tags_ptr =
dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;

T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
yaffs_trace(YAFFS_TRACE_MTD,
"nandmtd2_write_chunk_tags chunk %d data %p tags %p",
nand_chunk, data, tags);


addr = ((loff_t) chunkInNAND) * dev->param.totalBytesPerChunk;
addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;

/* For yaffs2 writing there must be both data and tags.
* If we're using inband tags, then the tags are stuffed into
* the end of the data buffer.
*/
if (!data || !tags)
BUG();
else if (dev->param.inbandTags) {
yaffs_PackedTags2TagsPart *pt2tp;
pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
yaffs_PackTags2TagsPart(pt2tp, tags);
} else
yaffs_PackTags2(&pt, tags, !dev->param.noTagsECC);
else if (dev->param.inband_tags) {
struct yaffs_packed_tags2_tags_only *pt2tp;
pt2tp =
(struct yaffs_packed_tags2_tags_only *)(data +
dev->
data_bytes_per_chunk);
yaffs_pack_tags2_tags_only(pt2tp, tags);
} else {
yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
}

#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
ops.mode = MTD_OOB_AUTO;
ops.ooblen = (dev->param.inbandTags) ? 0 : packed_tags_size;
ops.len = dev->param.totalBytesPerChunk;
ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
ops.len = dev->param.total_bytes_per_chunk;
ops.ooboffs = 0;
ops.datbuf = (__u8 *)data;
ops.oobbuf = (dev->param.inbandTags) ? NULL : packed_tags_ptr;
ops.datbuf = (u8 *) data;
ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
retval = mtd->write_oob(mtd, addr, &ops);

#else
if (!dev->param.inbandTags) {
if (!dev->param.inband_tags) {
retval =
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, (__u8 *) packed_tags_ptr, NULL);
mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
&dummy, data, (u8 *) packed_tags_ptr, NULL);
} else {
retval =
mtd->write(mtd, addr, dev->param.totalBytesPerChunk, &dummy,
data);
mtd->write(mtd, addr, dev->param.total_bytes_per_chunk,
&dummy, data);
}
#endif

@@ -97,113 +101,117 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
return YAFFS_FAIL;
}

int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *data, yaffs_ExtendedTags *tags)
int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
u8 *data, struct yaffs_ext_tags *tags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#endif
size_t dummy;
int retval = 0;
int localData = 0;
int local_data = 0;

loff_t addr = ((loff_t) chunkInNAND) * dev->param.totalBytesPerChunk;
loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;

yaffs_PackedTags2 pt;
struct yaffs_packed_tags2 pt;

int packed_tags_size = dev->param.noTagsECC ? sizeof(pt.t) : sizeof(pt);
void * packed_tags_ptr = dev->param.noTagsECC ? (void *) &pt.t: (void *)&pt;
int packed_tags_size =
dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
void *packed_tags_ptr =
dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;

T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
yaffs_trace(YAFFS_TRACE_MTD,
"nandmtd2_read_chunk_tags chunk %d data %p tags %p",
nand_chunk, data, tags);

if (dev->param.inbandTags) {
if (dev->param.inband_tags) {

if (!data) {
localData = 1;
data = yaffs_GetTempBuffer(dev, __LINE__);
local_data = 1;
data = yaffs_get_temp_buffer(dev);
}


}


#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
if (dev->param.inbandTags || (data && !tags))
retval = mtd->read(mtd, addr, dev->param.totalBytesPerChunk,
&dummy, data);
if (dev->param.inband_tags || (data && !tags))
retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
&dummy, data);
else if (tags) {
ops.mode = MTD_OOB_AUTO;
ops.ooblen = packed_tags_size;
ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size;
ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
ops.ooboffs = 0;
ops.datbuf = data;
ops.oobbuf = yaffs_DeviceToLC(dev)->spareBuffer;
ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer;
retval = mtd->read_oob(mtd, addr, &ops);
}
#else
if (!dev->param.inbandTags && data && tags) {
if (!dev->param.inband_tags && data && tags) {

retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, dev->spareBuffer,
NULL);
retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
&dummy, data, dev->spare_buffer, NULL);
} else {
if (data)
retval =
mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
data);
if (!dev->param.inbandTags && tags)
mtd->read(mtd, addr, dev->data_bytes_per_chunk,
&dummy, data);
if (!dev->param.inband_tags && tags)
retval =
mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
dev->spareBuffer);
dev->spare_buffer);
}
#endif


if (dev->param.inbandTags) {
if (dev->param.inband_tags) {
if (tags) {
yaffs_PackedTags2TagsPart *pt2tp;
pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
yaffs_UnpackTags2TagsPart(tags, pt2tp);
struct yaffs_packed_tags2_tags_only *pt2tp;
pt2tp =
(struct yaffs_packed_tags2_tags_only *)
&data[dev->data_bytes_per_chunk];
yaffs_unpack_tags2_tags_only(tags, pt2tp);
}
} else {
if (tags) {
memcpy(packed_tags_ptr, yaffs_DeviceToLC(dev)->spareBuffer, packed_tags_size);
yaffs_UnpackTags2(tags, &pt, !dev->param.noTagsECC);
memcpy(packed_tags_ptr,
yaffs_dev_to_lc(dev)->spare_buffer,
packed_tags_size);
yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
}
}

if (localData)
yaffs_ReleaseTempBuffer(dev, data, __LINE__);
if (local_data)
yaffs_release_temp_buffer(dev, data);

if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) {
tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
dev->eccUnfixed++;
if (tags && retval == -EBADMSG
&& tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
dev->n_ecc_unfixed++;
}
if(tags && retval == -EUCLEAN && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) {
tags->eccResult = YAFFS_ECC_RESULT_FIXED;
dev->eccFixed++;
if (tags && retval == -EUCLEAN
&& tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
dev->n_ecc_fixed++;
}
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}

int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
yaffs_trace(YAFFS_TRACE_MTD,
"nandmtd2_mark_block_bad %d",
block_no);

retval =
mtd->block_markbad(mtd,
blockNo * dev->param.nChunksPerBlock *
dev->param.totalBytesPerChunk);
block_no * dev->param.chunks_per_block *
dev->param.total_bytes_per_chunk);

if (retval == 0)
return YAFFS_OK;
@@ -212,42 +220,39 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)

}

int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *state, __u32 *sequenceNumber)
int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
enum yaffs_block_state *state, u32 *seq_number)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
int retval;

T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no);
retval =
mtd->block_isbad(mtd,
blockNo * dev->param.nChunksPerBlock *
dev->param.totalBytesPerChunk);
block_no * dev->param.chunks_per_block *
dev->param.total_bytes_per_chunk);

if (retval) {
T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
yaffs_trace(YAFFS_TRACE_MTD, "block is bad");

*state = YAFFS_BLOCK_STATE_DEAD;
*sequenceNumber = 0;
*seq_number = 0;
} else {
yaffs_ExtendedTags t;
nandmtd2_ReadChunkWithTagsFromNAND(dev,
blockNo *
dev->param.nChunksPerBlock, NULL,
&t);

if (t.chunkUsed) {
*sequenceNumber = t.sequenceNumber;
*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
struct yaffs_ext_tags t;
nandmtd2_read_chunk_tags(dev, block_no *
dev->param.chunks_per_block, NULL, &t);

if (t.chunk_used) {
*seq_number = t.seq_number;
*state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
} else {
*sequenceNumber = 0;
*seq_number = 0;
*state = YAFFS_BLOCK_STATE_EMPTY;
}
}
T(YAFFS_TRACE_MTD,
(TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,
*state));
yaffs_trace(YAFFS_TRACE_MTD,
"block is bad seq %d state %d",
*seq_number, *state);

if (retval == 0)
return YAFFS_OK;
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -17,13 +17,13 @@
#define __YAFFS_MTDIF2_H__

#include "yaffs_guts.h"
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data,
const yaffs_ExtendedTags *tags);
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *data, yaffs_ExtendedTags *tags);
int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *state, __u32 *sequenceNumber);
int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
const u8 *data,
const struct yaffs_ext_tags *tags);
int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
u8 *data, struct yaffs_ext_tags *tags);
int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no);
int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
enum yaffs_block_state *state, u32 *seq_number);

#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -12,58 +12,57 @@
*/

/*
* This simple implementation of a name-value store assumes a small number of values and fits
* into a small finite buffer.
* This simple implementation of a name-value store assumes a small number of
* values and fits into a small finite buffer.
*
* Each attribute is stored as a record:
* sizeof(int) bytes record size.
* strnlen+1 bytes name null terminated.
* nbytes value.
* ----------
* total size stored in record size
* total size stored in record size
*
* This code has not been tested with unicode yet.
*/


#include "yaffs_nameval.h"

#include "yportenv.h"

static int nval_find(const char *xb, int xb_size, const YCHAR *name,
int *exist_size)
int *exist_size)
{
int pos=0;
int pos = 0;
int size;

memcpy(&size,xb,sizeof(int));
while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
if(yaffs_strncmp((YCHAR *)(xb+pos+sizeof(int)),name,size) == 0){
if(exist_size)
memcpy(&size, xb, sizeof(int));
while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
if (!strncmp((YCHAR *) (xb + pos + sizeof(int)), name, size)) {
if (exist_size)
*exist_size = size;
return pos;
}
pos += size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
if (pos < xb_size - sizeof(int))
memcpy(&size, xb + pos, sizeof(int));
else
size = 0;
}
if(exist_size)
if (exist_size)
*exist_size = 0;
return -1;
return -ENODATA;
}

static int nval_used(const char *xb, int xb_size)
{
int pos=0;
int pos = 0;
int size;

memcpy(&size,xb + pos,sizeof(int));
while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
memcpy(&size, xb + pos, sizeof(int));
while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
pos += size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
if (pos < xb_size - sizeof(int))
memcpy(&size, xb + pos, sizeof(int));
else
size = 0;
}
@@ -72,88 +71,96 @@ static int nval_used(const char *xb, int xb_size)

int nval_del(char *xb, int xb_size, const YCHAR *name)
{
int pos = nval_find(xb, xb_size, name, NULL);
int pos = nval_find(xb, xb_size, name, NULL);
int size;

if(pos >= 0 && pos < xb_size){
/* Find size, shift rest over this record, then zero out the rest of buffer */
memcpy(&size,xb+pos,sizeof(int));
memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
memset(xb + (xb_size - size),0,size);
return 0;
} else

if (pos < 0 || pos >= xb_size)
return -ENODATA;

/* Find size, shift rest over this record,
* then zero out the rest of buffer */
memcpy(&size, xb + pos, sizeof(int));
memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
memset(xb + (xb_size - size), 0, size);
return 0;
}

int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, int bsize, int flags)
int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf,
int bsize, int flags)
{
int pos;
int namelen = yaffs_strnlen(name,xb_size);
int namelen = strnlen(name, xb_size);
int reclen;
int size_exist = 0;
int space;
int start;

pos = nval_find(xb,xb_size,name, &size_exist);
pos = nval_find(xb, xb_size, name, &size_exist);

if(flags & XATTR_CREATE && pos >= 0)
if (flags & XATTR_CREATE && pos >= 0)
return -EEXIST;
if(flags & XATTR_REPLACE && pos < 0)
if (flags & XATTR_REPLACE && pos < 0)
return -ENODATA;

start = nval_used(xb,xb_size);
start = nval_used(xb, xb_size);
space = xb_size - start + size_exist;

reclen = (sizeof(int) + namelen + 1 + bsize);

if(reclen > space)
if (reclen > space)
return -ENOSPC;

if(pos >= 0){
nval_del(xb,xb_size,name);
if (pos >= 0) {
nval_del(xb, xb_size, name);
start = nval_used(xb, xb_size);
}

pos = start;

memcpy(xb + pos,&reclen,sizeof(int));
pos +=sizeof(int);
yaffs_strncpy((YCHAR *)(xb + pos), name, reclen);
pos+= (namelen+1);
memcpy(xb + pos,buf,bsize);
memcpy(xb + pos, &reclen, sizeof(int));
pos += sizeof(int);
strncpy((YCHAR *) (xb + pos), name, reclen);
pos += (namelen + 1);
memcpy(xb + pos, buf, bsize);
return 0;
}

int nval_get(const char *xb, int xb_size, const YCHAR *name, char *buf, int bsize)
int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
int bsize)
{
int pos = nval_find(xb,xb_size,name,NULL);
int pos = nval_find(xb, xb_size, name, NULL);
int size;
if(pos >= 0 && pos< xb_size){
memcpy(&size,xb +pos,sizeof(int));
pos+=sizeof(int); /* advance past record length */

if (pos >= 0 && pos < xb_size) {

memcpy(&size, xb + pos, sizeof(int));
pos += sizeof(int); /* advance past record length */
size -= sizeof(int);

/* Advance over name string */
while(xb[pos] && size > 0 && pos < xb_size){
while (xb[pos] && size > 0 && pos < xb_size) {
pos++;
size--;
}
/*Advance over NUL */
pos++;
size--;

if(size <= bsize){
memcpy(buf,xb + pos,size);
/* If bsize is zero then this is a size query.
* Return the size, but don't copy.
*/
if (!bsize)
return size;

if (size <= bsize) {
memcpy(buf, xb + pos, size);
return size;
}

}
if(pos >= 0)
if (pos >= 0)
return -ERANGE;
else
return -ENODATA;

return -ENODATA;
}

int nval_list(const char *xb, int xb_size, char *buf, int bsize)
@@ -164,33 +171,36 @@ int nval_list(const char *xb, int xb_size, char *buf, int bsize)
int ncopied = 0;
int filled = 0;

memcpy(&size,xb + pos,sizeof(int));
while(size > sizeof(int) && size <= xb_size && (pos + size) < xb_size && !filled){
pos+= sizeof(int);
size-=sizeof(int);
name_len = yaffs_strnlen((YCHAR *)(xb + pos), size);
if(ncopied + name_len + 1 < bsize){
memcpy(buf,xb+pos,name_len * sizeof(YCHAR));
buf+= name_len;
memcpy(&size, xb + pos, sizeof(int));
while (size > sizeof(int) &&
size <= xb_size &&
(pos + size) < xb_size &&
!filled) {
pos += sizeof(int);
size -= sizeof(int);
name_len = strnlen((YCHAR *) (xb + pos), size);
if (ncopied + name_len + 1 < bsize) {
memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
buf += name_len;
*buf = '\0';
buf++;
if(sizeof(YCHAR) > 1){
if (sizeof(YCHAR) > 1) {
*buf = '\0';
buf++;
}
ncopied += (name_len+1);
} else
ncopied += (name_len + 1);
} else {
filled = 1;
pos+=size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
}
pos += size;
if (pos < xb_size - sizeof(int))
memcpy(&size, xb + pos, sizeof(int));
else
size = 0;
}
return ncopied;
}


int nval_hasvalues(const char *xb, int xb_size)
{
return nval_used(xb, xb_size) > 0;
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -12,14 +12,17 @@
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/

#ifndef __NAMEVAL_H__
#define __NAMEVAL_H__

#include "yportenv.h"

int nval_del(char *xb, int xb_size, const YCHAR *name);
int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, int bsize, int flags);
int nval_get(const char *xb, int xb_size, const YCHAR *name, char *buf, int bsize);
int nval_del(char *xb, int xb_size, const YCHAR * name);
int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf,
int bsize, int flags);
int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
int bsize);
int nval_list(const char *xb, int xb_size, char *buf, int bsize);
int nval_hasvalues(const char *xb, int xb_size);
#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -13,128 +13,108 @@

#include "yaffs_nand.h"
#include "yaffs_tagscompat.h"
#include "yaffs_tagsvalidity.h"

#include "yaffs_getblockinfo.h"
#include "yaffs_summary.h"

int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *buffer,
yaffs_ExtendedTags *tags)
int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
u8 *buffer, struct yaffs_ext_tags *tags)
{
int result;
yaffs_ExtendedTags localTags;
struct yaffs_ext_tags local_tags;
int flash_chunk = nand_chunk - dev->chunk_offset;

int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
dev->n_page_reads++;

dev->nPageReads++;

/* If there are no tags provided, use local tags to get prioritised gc working */
/* If there are no tags provided use local tags. */
if (!tags)
tags = &localTags;
tags = &local_tags;

if (dev->param.readChunkWithTagsFromNAND)
result = dev->param.readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
tags);
if (dev->param.read_chunk_tags_fn)
result =
dev->param.read_chunk_tags_fn(dev, flash_chunk, buffer,
tags);
else
result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
realignedChunkInNAND,
buffer,
tags);
if (tags &&
tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR) {

yaffs_BlockInfo *bi;
bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->param.nChunksPerBlock);
yaffs_HandleChunkError(dev, bi);
result = yaffs_tags_compat_rd(dev,
flash_chunk, buffer, tags);
if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {

struct yaffs_block_info *bi;
bi = yaffs_get_block_info(dev,
nand_chunk /
dev->param.chunks_per_block);
yaffs_handle_chunk_error(dev, bi);
}

return result;
}

int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,
int chunkInNAND,
const __u8 *buffer,
yaffs_ExtendedTags *tags)
int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
int nand_chunk,
const u8 *buffer, struct yaffs_ext_tags *tags)
{
int result;
int flash_chunk = nand_chunk - dev->chunk_offset;

dev->nPageWrites++;

chunkInNAND -= dev->chunkOffset;

dev->n_page_writes++;

if (tags) {
tags->sequenceNumber = dev->sequenceNumber;
tags->chunkUsed = 1;
if (!yaffs_ValidateTags(tags)) {
T(YAFFS_TRACE_ERROR,
(TSTR("Writing uninitialised tags" TENDSTR)));
YBUG();
}
T(YAFFS_TRACE_WRITE,
(TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
tags->objectId, tags->chunkId));
tags->seq_number = dev->seq_number;
tags->chunk_used = 1;
yaffs_trace(YAFFS_TRACE_WRITE,
"Writing chunk %d tags %d %d",
nand_chunk, tags->obj_id, tags->chunk_id);
} else {
T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
YBUG();
yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
BUG();
return YAFFS_FAIL;
}

if (dev->param.writeChunkWithTagsToNAND)
return dev->param.writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
tags);
if (dev->param.write_chunk_tags_fn)
result = dev->param.write_chunk_tags_fn(dev, flash_chunk,
buffer, tags);
else
return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
chunkInNAND,
buffer,
tags);
result = yaffs_tags_compat_wr(dev, flash_chunk, buffer, tags);

yaffs_summary_add(dev, tags, nand_chunk);

return result;
}

int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)
int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
{
blockNo -= dev->blockOffset;

block_no -= dev->block_offset;
if (dev->param.bad_block_fn)
return dev->param.bad_block_fn(dev, block_no);

if (dev->param.markNANDBlockBad)
return dev->param.markNANDBlockBad(dev, blockNo);
else
return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
return yaffs_tags_compat_mark_bad(dev, block_no);
}

int yaffs_QueryInitialBlockState(yaffs_Device *dev,
int blockNo,
yaffs_BlockState *state,
__u32 *sequenceNumber)
int yaffs_query_init_block_state(struct yaffs_dev *dev,
int block_no,
enum yaffs_block_state *state,
u32 *seq_number)
{
blockNo -= dev->blockOffset;
block_no -= dev->block_offset;
if (dev->param.query_block_fn)
return dev->param.query_block_fn(dev, block_no, state,
seq_number);

if (dev->param.queryNANDBlock)
return dev->param.queryNANDBlock(dev, blockNo, state, sequenceNumber);
else
return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
state,
sequenceNumber);
return yaffs_tags_compat_query_block(dev, block_no, state, seq_number);
}


int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
int blockInNAND)
int yaffs_erase_block(struct yaffs_dev *dev, int flash_block)
{
int result;

blockInNAND -= dev->blockOffset;

dev->nBlockErasures++;

result = dev->param.eraseBlockInNAND(dev, blockInNAND);

flash_block -= dev->block_offset;
dev->n_erasures++;
result = dev->param.erase_fn(dev, flash_block);
return result;
}

int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
int yaffs_init_nand(struct yaffs_dev *dev)
{
if(dev->param.initialiseNAND)
return dev->param.initialiseNAND(dev);
if (dev->param.initialise_flash_fn)
return dev->param.initialise_flash_fn(dev);
return YAFFS_OK;
}



@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -17,28 +17,22 @@
#define __YAFFS_NAND_H__
#include "yaffs_guts.h"

int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
u8 *buffer, struct yaffs_ext_tags *tags);

int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
int nand_chunk,
const u8 *buffer, struct yaffs_ext_tags *tags);

int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *buffer,
yaffs_ExtendedTags *tags);
int yaffs_mark_bad(struct yaffs_dev *dev, int block_no);

int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,
int chunkInNAND,
const __u8 *buffer,
yaffs_ExtendedTags *tags);
int yaffs_query_init_block_state(struct yaffs_dev *dev,
int block_no,
enum yaffs_block_state *state,
unsigned *seq_number);

int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo);
int yaffs_erase_block(struct yaffs_dev *dev, int flash_block);

int yaffs_QueryInitialBlockState(yaffs_Device *dev,
int blockNo,
yaffs_BlockState *state,
unsigned *sequenceNumber);

int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
int blockInNAND);

int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev);
int yaffs_init_nand(struct yaffs_dev *dev);

#endif

This file was deleted.

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -14,37 +14,43 @@
#include "yaffs_packedtags1.h"
#include "yportenv.h"

void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t)
static const u8 all_ff[20] = {
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff
};

void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
const struct yaffs_ext_tags *t)
{
pt->chunkId = t->chunkId;
pt->serialNumber = t->serialNumber;
pt->byteCount = t->byteCount;
pt->objectId = t->objectId;
pt->chunk_id = t->chunk_id;
pt->serial_number = t->serial_number;
pt->n_bytes = t->n_bytes;
pt->obj_id = t->obj_id;
pt->ecc = 0;
pt->deleted = (t->chunkDeleted) ? 0 : 1;
pt->unusedStuff = 0;
pt->shouldBeFF = 0xFFFFFFFF;

pt->deleted = (t->is_deleted) ? 0 : 1;
pt->unused_stuff = 0;
pt->should_be_ff = 0xffffffff;
}

void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt)
void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
const struct yaffs_packed_tags1 *pt)
{
static const __u8 allFF[] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff };

if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) {
t->blockBad = 0;
if (pt->shouldBeFF != 0xFFFFFFFF)
t->blockBad = 1;
t->chunkUsed = 1;
t->objectId = pt->objectId;
t->chunkId = pt->chunkId;
t->byteCount = pt->byteCount;
t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
t->chunkDeleted = (pt->deleted) ? 0 : 1;
t->serialNumber = pt->serialNumber;
if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) {
t->block_bad = 0;
if (pt->should_be_ff != 0xffffffff)
t->block_bad = 1;
t->chunk_used = 1;
t->obj_id = pt->obj_id;
t->chunk_id = pt->chunk_id;
t->n_bytes = pt->n_bytes;
t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
t->is_deleted = (pt->deleted) ? 0 : 1;
t->serial_number = pt->serial_number;
} else {
memset(t, 0, sizeof(yaffs_ExtendedTags));
memset(t, 0, sizeof(struct yaffs_ext_tags));
}
}
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -20,18 +20,20 @@

#include "yaffs_guts.h"

typedef struct {
unsigned chunkId:20;
unsigned serialNumber:2;
unsigned byteCount:10;
unsigned objectId:18;
struct yaffs_packed_tags1 {
unsigned chunk_id:20;
unsigned serial_number:2;
unsigned n_bytes:10;
unsigned obj_id:18;
unsigned ecc:12;
unsigned deleted:1;
unsigned unusedStuff:1;
unsigned shouldBeFF;
unsigned unused_stuff:1;
unsigned should_be_ff;

} yaffs_PackedTags1;
};

void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t);
void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt);
void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
const struct yaffs_ext_tags *t);
void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
const struct yaffs_packed_tags1 *pt);
#endif
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -14,7 +14,6 @@
#include "yaffs_packedtags2.h"
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_tagsvalidity.h"

/* This code packs a set of extended tags into a binary structure for
* NAND storage
@@ -25,174 +24,158 @@
* This is defined by having the EXTRA_HEADER_INFO_FLAG set.
*/

/* Extra flags applied to chunkId */
/* Extra flags applied to chunk_id */

#define EXTRA_HEADER_INFO_FLAG 0x80000000
#define EXTRA_SHRINK_FLAG 0x40000000
#define EXTRA_SHADOWS_FLAG 0x20000000
#define EXTRA_SPARE_FLAGS 0x10000000

#define ALL_EXTRA_FLAGS 0xF0000000
#define ALL_EXTRA_FLAGS 0xf0000000

/* Also, the top 4 bits of the object Id are set to the object type. */
#define EXTRA_OBJECT_TYPE_SHIFT (28)
#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)


static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt)
static void yaffs_dump_packed_tags2_tags_only(
const struct yaffs_packed_tags2_tags_only *ptt)
{
T(YAFFS_TRACE_MTD,
(TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
ptt->objectId, ptt->chunkId, ptt->byteCount,
ptt->sequenceNumber));
yaffs_trace(YAFFS_TRACE_MTD,
"packed tags obj %d chunk %d byte %d seq %d",
ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number);
}
static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt)

static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt)
{
yaffs_DumpPackedTags2TagsPart(&pt->t);
yaffs_dump_packed_tags2_tags_only(&pt->t);
}

static void yaffs_DumpTags2(const yaffs_ExtendedTags *t)
static void yaffs_dump_tags2(const struct yaffs_ext_tags *t)
{
T(YAFFS_TRACE_MTD,
(TSTR
("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
t->sequenceNumber));
yaffs_trace(YAFFS_TRACE_MTD,
"ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
t->ecc_result, t->block_bad, t->chunk_used, t->obj_id,
t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number,
t->seq_number);

}

void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt,
const yaffs_ExtendedTags *t)
void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *ptt,
const struct yaffs_ext_tags *t)
{
ptt->chunkId = t->chunkId;
ptt->sequenceNumber = t->sequenceNumber;
ptt->byteCount = t->byteCount;
ptt->objectId = t->objectId;
ptt->chunk_id = t->chunk_id;
ptt->seq_number = t->seq_number;
ptt->n_bytes = t->n_bytes;
ptt->obj_id = t->obj_id;

if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
if (t->chunk_id == 0 && t->extra_available) {
/* Store the extra header info instead */
/* We save the parent object in the chunkId */
ptt->chunkId = EXTRA_HEADER_INFO_FLAG
| t->extraParentObjectId;
if (t->extraIsShrinkHeader)
ptt->chunkId |= EXTRA_SHRINK_FLAG;
if (t->extraShadows)
ptt->chunkId |= EXTRA_SHADOWS_FLAG;

ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
ptt->objectId |=
(t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);

if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
ptt->byteCount = t->extraEquivalentObjectId;
else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE)
ptt->byteCount = t->extraFileLength;
/* We save the parent object in the chunk_id */
ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id;
if (t->extra_is_shrink)
ptt->chunk_id |= EXTRA_SHRINK_FLAG;
if (t->extra_shadows)
ptt->chunk_id |= EXTRA_SHADOWS_FLAG;

ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT);

if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
ptt->n_bytes = t->extra_equiv_id;
else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
ptt->n_bytes = t->extra_length;
else
ptt->byteCount = 0;
ptt->n_bytes = 0;
}

yaffs_DumpPackedTags2TagsPart(ptt);
yaffs_DumpTags2(t);
yaffs_dump_packed_tags2_tags_only(ptt);
yaffs_dump_tags2(t);
}


void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t, int tagsECC)
void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
const struct yaffs_ext_tags *t, int tags_ecc)
{
yaffs_PackTags2TagsPart(&pt->t, t);
yaffs_pack_tags2_tags_only(&pt->t, t);

if(tagsECC)
yaffs_ECCCalculateOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&pt->ecc);
if (tags_ecc)
yaffs_ecc_calc_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&pt->ecc);
}


void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t,
yaffs_PackedTags2TagsPart *ptt)
void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
struct yaffs_packed_tags2_tags_only *ptt)
{

memset(t, 0, sizeof(yaffs_ExtendedTags));

yaffs_InitialiseTags(t);

if (ptt->sequenceNumber != 0xFFFFFFFF) {
t->blockBad = 0;
t->chunkUsed = 1;
t->objectId = ptt->objectId;
t->chunkId = ptt->chunkId;
t->byteCount = ptt->byteCount;
t->chunkDeleted = 0;
t->serialNumber = 0;
t->sequenceNumber = ptt->sequenceNumber;

/* Do extra header info stuff */

if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
t->chunkId = 0;
t->byteCount = 0;

t->extraHeaderInfoAvailable = 1;
t->extraParentObjectId =
ptt->chunkId & (~(ALL_EXTRA_FLAGS));
t->extraIsShrinkHeader =
(ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
t->extraShadows =
(ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
t->extraObjectType =
ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;

if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
t->extraEquivalentObjectId = ptt->byteCount;
else
t->extraFileLength = ptt->byteCount;
}
memset(t, 0, sizeof(struct yaffs_ext_tags));

if (ptt->seq_number == 0xffffffff)
return;

t->block_bad = 0;
t->chunk_used = 1;
t->obj_id = ptt->obj_id;
t->chunk_id = ptt->chunk_id;
t->n_bytes = ptt->n_bytes;
t->is_deleted = 0;
t->serial_number = 0;
t->seq_number = ptt->seq_number;

/* Do extra header info stuff */
if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) {
t->chunk_id = 0;
t->n_bytes = 0;

t->extra_available = 1;
t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS));
t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0;
t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0;
t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT;
t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;

if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
t->extra_equiv_id = ptt->n_bytes;
else
t->extra_length = ptt->n_bytes;
}

yaffs_DumpPackedTags2TagsPart(ptt);
yaffs_DumpTags2(t);

yaffs_dump_packed_tags2_tags_only(ptt);
yaffs_dump_tags2(t);
}


void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC)
void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
int tags_ecc)
{
enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR;

yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;

if (pt->t.sequenceNumber != 0xFFFFFFFF &&
tagsECC){
if (pt->t.seq_number != 0xffffffff && tags_ecc) {
/* Chunk is in use and we need to do ECC */
yaffs_ECCOther ecc;

struct yaffs_ecc_other ecc;
int result;
yaffs_ECCCalculateOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&ecc);
result = yaffs_ECCCorrectOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&pt->ecc, &ecc);
yaffs_ecc_calc_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&ecc);
result =
yaffs_ecc_correct_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&pt->ecc, &ecc);
switch (result) {
case 0:
eccResult = YAFFS_ECC_RESULT_NO_ERROR;
break;
case 1:
eccResult = YAFFS_ECC_RESULT_FIXED;
break;
case -1:
eccResult = YAFFS_ECC_RESULT_UNFIXED;
break;
default:
eccResult = YAFFS_ECC_RESULT_UNKNOWN;
case 0:
ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
break;
case 1:
ecc_result = YAFFS_ECC_RESULT_FIXED;
break;
case -1:
ecc_result = YAFFS_ECC_RESULT_UNFIXED;
break;
default:
ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
}
}
yaffs_unpack_tags2_tags_only(t, &pt->t);

yaffs_UnpackTags2TagsPart(t, &pt->t);

t->eccResult = eccResult;
t->ecc_result = ecc_result;

yaffs_DumpPackedTags2(pt);
yaffs_DumpTags2(t);
yaffs_dump_packed_tags2(pt);
yaffs_dump_tags2(t);
}

@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -21,23 +21,27 @@
#include "yaffs_guts.h"
#include "yaffs_ecc.h"

typedef struct {
unsigned sequenceNumber;
unsigned objectId;
unsigned chunkId;
unsigned byteCount;
} yaffs_PackedTags2TagsPart;
struct yaffs_packed_tags2_tags_only {
unsigned seq_number;
unsigned obj_id;
unsigned chunk_id;
unsigned n_bytes;
};

typedef struct {
yaffs_PackedTags2TagsPart t;
yaffs_ECCOther ecc;
} yaffs_PackedTags2;
struct yaffs_packed_tags2 {
struct yaffs_packed_tags2_tags_only t;
struct yaffs_ecc_other ecc;
};

/* Full packed tags with ECC, used for oob tags */
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t, int tagsECC);
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC);
void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
const struct yaffs_ext_tags *t, int tags_ecc);
void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
int tags_ecc);

/* Only the tags part (no ECC for use with inband tags */
void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);
void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, yaffs_PackedTags2TagsPart *pt);
void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *pt,
const struct yaffs_ext_tags *t);
void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
struct yaffs_packed_tags2_tags_only *pt);
#endif

This file was deleted.

This file was deleted.