/*
* 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
+ * Copyright (C) 2002-2018 Aleph One Ltd.
*
* 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.
+ *
+ * This file handles yaffs1-style tags to allow compatibility with Yaffs1 style
+ * flash layouts.
*/
#include "yaffs_guts.h"
#include "yaffs_ecc.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_trace.h"
+#include "yaffs_endian.h"
static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
/********** Tags ECC calculations *********/
-
void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
{
/* Calculate an ecc */
/********** Tags **********/
-static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
+/*
+ * During tags storing/retireval we use a copy of the tags so that
+ * we can modify the endian etc without damaging the previous structure.
+ */
+static void yaffs_load_tags_to_spare(struct yaffs_dev *dev,
+ struct yaffs_spare *spare_ptr,
struct yaffs_tags *tags_ptr)
{
- union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
-
- yaffs_calc_tags_ecc(tags_ptr);
-
- spare_ptr->tb0 = tu->as_bytes[0];
- spare_ptr->tb1 = tu->as_bytes[1];
- spare_ptr->tb2 = tu->as_bytes[2];
- spare_ptr->tb3 = tu->as_bytes[3];
- spare_ptr->tb4 = tu->as_bytes[4];
- spare_ptr->tb5 = tu->as_bytes[5];
- spare_ptr->tb6 = tu->as_bytes[6];
- spare_ptr->tb7 = tu->as_bytes[7];
+ union yaffs_tags_union *tu_ptr = (union yaffs_tags_union *)tags_ptr;
+ union yaffs_tags_union tags_stored = *tu_ptr;
+
+ yaffs_calc_tags_ecc(&tags_stored.as_tags);
+
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+ spare_ptr->tb0 = tags_stored.as_bytes[0];
+ spare_ptr->tb1 = tags_stored.as_bytes[1];
+ spare_ptr->tb2 = tags_stored.as_bytes[2];
+ spare_ptr->tb3 = tags_stored.as_bytes[3];
+ spare_ptr->tb4 = tags_stored.as_bytes[4];
+ spare_ptr->tb5 = tags_stored.as_bytes[5];
+ spare_ptr->tb6 = tags_stored.as_bytes[6];
+ spare_ptr->tb7 = tags_stored.as_bytes[7];
}
static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
struct yaffs_tags *tags_ptr)
{
union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
+ union yaffs_tags_union tags_stored;
int result;
- tu->as_bytes[0] = spare_ptr->tb0;
- tu->as_bytes[1] = spare_ptr->tb1;
- tu->as_bytes[2] = spare_ptr->tb2;
- tu->as_bytes[3] = spare_ptr->tb3;
- tu->as_bytes[4] = spare_ptr->tb4;
- tu->as_bytes[5] = spare_ptr->tb5;
- tu->as_bytes[6] = spare_ptr->tb6;
- tu->as_bytes[7] = spare_ptr->tb7;
+ tags_stored.as_bytes[0] = spare_ptr->tb0;
+ tags_stored.as_bytes[1] = spare_ptr->tb1;
+ tags_stored.as_bytes[2] = spare_ptr->tb2;
+ tags_stored.as_bytes[3] = spare_ptr->tb3;
+ tags_stored.as_bytes[4] = spare_ptr->tb4;
+ tags_stored.as_bytes[5] = spare_ptr->tb5;
+ tags_stored.as_bytes[6] = spare_ptr->tb6;
+ tags_stored.as_bytes[7] = spare_ptr->tb7;
+
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+ *tu = tags_stored;
result = yaffs_check_tags_ecc(tags_ptr);
if (result > 0)
{
int data_size = dev->data_bytes_per_chunk;
- return dev->param.drv_write_chunk_fn(dev, nand_chunk,
+ return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
data, data_size,
(u8 *) spare, sizeof(*spare));
}
spare_size = sizeof(struct yaffs_spare);
if (dev->param.use_nand_ecc)
- return dev->param.drv_read_chunk_fn(dev, nand_chunk,
+ return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
data, data_size,
(u8 *) spare, spare_size,
ecc_result);
/* Handle the ECC at this level. */
- ret_val = dev->param.drv_read_chunk_fn(dev, nand_chunk,
+ ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
data, data_size,
(u8 *)spare, spare_size,
NULL);
yaffs_ecc_calc(&data[256], spare.ecc2);
}
- yaffs_load_tags_to_spare(&spare, &tags);
+ yaffs_load_tags_to_spare(dev, &spare, &tags);
}
return yaffs_wr_nand(dev, nand_chunk, data, &spare);
}
if (ext_tags->chunk_used) {
yaffs_get_tags_from_spare(dev, &spare, &tags);
+
ext_tags->obj_id = tags.obj_id;
ext_tags->chunk_id = tags.chunk_id;
ext_tags->n_bytes = tags.n_bytes_lsb;
*seq_number = 0;
+ /* Look for bad block markers in the first two chunks */
yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
NULL, &spare0, &dummy, 0);
yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
{
if(dev->param.is_yaffs2)
return;
- if(!dev->param.write_chunk_tags_fn)
- dev->param.write_chunk_tags_fn = yaffs_tags_compat_wr;
- if(!dev->param.read_chunk_tags_fn)
- dev->param.read_chunk_tags_fn = yaffs_tags_compat_rd;
- if(!dev->param.query_block_fn)
- dev->param.query_block_fn = yaffs_tags_compat_query_block;
- if(!dev->param.mark_bad_fn)
- dev->param.mark_bad_fn = yaffs_tags_compat_mark_bad;
+ if(!dev->tagger.write_chunk_tags_fn)
+ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
+ if(!dev->tagger.read_chunk_tags_fn)
+ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
+ if(!dev->tagger.query_block_fn)
+ dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
+ if(!dev->tagger.mark_bad_fn)
+ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
}