From 5b1ed5f8913d54fd9856d66421ae0f8e0b5769a9 Mon Sep 17 00:00:00 2001 From: charles Date: Thu, 23 Dec 2004 03:15:56 +0000 Subject: [PATCH] *** empty log message *** --- README | 28 ++ linux-kernel/README | 6 + Makefile => linux-module/Makefile | 15 +- nand_ecc.c | 223 --------- yaffs-header.c | 13 - yaffsdev.c | 731 ------------------------------ yaffsdev.proj | Bin 53248 -> 0 bytes 7 files changed, 46 insertions(+), 970 deletions(-) create mode 100644 README create mode 100644 linux-kernel/README rename Makefile => linux-module/Makefile (92%) delete mode 100644 nand_ecc.c delete mode 100644 yaffs-header.c delete mode 100644 yaffsdev.c delete mode 100644 yaffsdev.proj diff --git a/README b/README new file mode 100644 index 0000000..ef26980 --- /dev/null +++ b/README @@ -0,0 +1,28 @@ +Welcome to YAFFS, the first file system developed specifically for NAND flash. + +Before you go too far, you might consider looking at YAFFS2. + +A note on licencing +------------------- +YAFFS is available under GPL and via alternative licensing arrangements with +Alpeh One. Generally, if you're using YAFFS as a Linux kernel file system +you can use the GPL and in other cases you need to discuss licensing issues +with Aleph One. + + +Where do you want to go today? +------------------------------ +direct This is the userspace/RTOS variant of YAFFS. This is used for yaffs + core development and for embedding YAFFS in products that don't use + Linux or WinCE +linux-module This allows you to build YAFFS as a free-standing Linux kernel + module. By "free standing", I mean that this build happens + outside the kernel tree. Generally you'd use this for testing. +linux-kernel This allows you to hook YAFFS into the kernel tree, to build + YAFFS within the kernel tree. +utils These are some utilities for Linux. +wince Windows CE support. Horribly dated. Contact Aleph One is you're + considering YAFFS for a WinCE project. +mtdemul An mtd NAND emulation driver for testing YAFFS under Linux. +Documentation Some YAFFS documents. Also visit www.aleph1.co.uk. + diff --git a/linux-kernel/README b/linux-kernel/README new file mode 100644 index 0000000..f259622 --- /dev/null +++ b/linux-kernel/README @@ -0,0 +1,6 @@ +To build YAFFS in the Linux kernel tree you need to run the patch-in-yaffs +script. + +After you've run the script, go back tou your normal kernel making procedure +and configure the yaffs settings you want. + diff --git a/Makefile b/linux-module/Makefile similarity index 92% rename from Makefile rename to linux-module/Makefile index 9b084cb..dc10880 100644 --- a/Makefile +++ b/linux-module/Makefile @@ -1,4 +1,4 @@ -#Makefile for YAFFS as a module + # # NB this is not yet suitable for putting into the kernel tree. # YAFFS: Yet another FFS. A NAND-flash specific file system. @@ -12,9 +12,15 @@ # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # -# $Id: Makefile,v 1.13 2004-10-20 20:12:43 charles Exp $ +# $Id: Makefile,v 1.1 2004-12-23 03:15:57 charles Exp $ # +#Makefile for manually hacking YAFFS as a module. + + +SYMLINKS = yaffs_fs.c yaffs_guts.c yaffs_guts.h yaffs_ecc.c yaffs_ecc.h yaffs_mtdif.c yaffs_mtdif.h yaffs_ramem.c yaffs_nandemul.h yportenv.h yaffsinterface.h devextras.h + + ## Change or override KERNELDIR to your kernel ## comment out USE_xxxx if you don't want these features. @@ -114,7 +120,10 @@ CFLAGS = -D__KERNEL__ -DMODULE $(YAFFS_CONFIGS) -I $(KERNELDIR)/include -O2 -W OBJS = yaffs_fs.o yaffs_guts.o yaffs_ramem.o yaffs_mtdif.o yaffs_ecc.o -all: yaffs.o +all: $(SYMLINKS) yaffs.o + +$(SYMLINKS): + ln -s ../$@ $@ $(OBJS): %.o: %.c Makefile $(CC) -c $(CFLAGS) $< -o $@ diff --git a/nand_ecc.c b/nand_ecc.c deleted file mode 100644 index c22397b..0000000 --- a/nand_ecc.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * drivers/mtd/nand_ecc.c - * - * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) - * Toshiba America Electronics Components, Inc. - * - * $Id: nand_ecc.c,v 1.3 2002-09-27 20:50:50 charles Exp $ - * - * 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. - * - * This file contains an ECC algorithm from Toshiba that detects and - * corrects 1 bit errors in a 256 byte block of data. - */ - // Minor tweak by Charles Manning to prevent exporting symbols - // when compiled in with yaffs. - -const char *nand_ecc_c_version = "$Id: nand_ecc.c,v 1.3 2002-09-27 20:50:50 charles Exp $"; - -#if 0 -#include -#include -#include -#endif - -#include "yportenv.h" - -/* - * Pre-calculated 256-way 1 byte column parity - */ -static const u_char nand_ecc_precalc_table[] = { - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 -}; - - -/* - * Creates non-inverted ECC code from line parity - */ -static void nand_trans_result(u_char reg2, u_char reg3, - u_char *ecc_code) -{ - u_char a, b, i, tmp1, tmp2; - - /* Initialize variables */ - a = b = 0x80; - tmp1 = tmp2 = 0; - - /* Calculate first ECC byte */ - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - a >>= 1; - } - - /* Calculate second ECC byte */ - b = 0x80; - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - a >>= 1; - } - - /* Store two of the ECC bytes */ - ecc_code[0] = tmp1; - ecc_code[1] = tmp2; -} - -/* - * Calculate 3 byte ECC code for 256 byte block - */ -void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) -{ - u_char idx, reg1, reg2, reg3; - int j; - - /* Initialize variables */ - reg1 = reg2 = reg3 = 0; - ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; - - /* Build up column parity */ - for(j = 0; j < 256; j++) { - - /* Get CP0 - CP5 from table */ - idx = nand_ecc_precalc_table[dat[j]]; - reg1 ^= (idx & 0x3f); - - /* All bit XOR = 1 ? */ - if (idx & 0x40) { - reg3 ^= (u_char) j; - reg2 ^= ~((u_char) j); - } - } - - /* Create non-inverted ECC code from line parity */ - nand_trans_result(reg2, reg3, ecc_code); - - /* Calculate final ECC code */ - ecc_code[0] = ~ecc_code[0]; - ecc_code[1] = ~ecc_code[1]; - ecc_code[2] = ((~reg1) << 2) | 0x03; -} - -/* - * Detect and correct a 1 bit error for 256 byte block - */ -int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) -{ - u_char a, b, c, d1, d2, d3, add, bit, i; - - /* Do error detection */ - d1 = calc_ecc[0] ^ read_ecc[0]; - d2 = calc_ecc[1] ^ read_ecc[1]; - d3 = calc_ecc[2] ^ read_ecc[2]; - - if ((d1 | d2 | d3) == 0) { - /* No errors */ - return 0; - } - else { - a = (d1 ^ (d1 >> 1)) & 0x55; - b = (d2 ^ (d2 >> 1)) & 0x55; - c = (d3 ^ (d3 >> 1)) & 0x54; - - /* Found and will correct single bit error in the data */ - if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { - c = 0x80; - add = 0; - a = 0x80; - for (i=0; i<4; i++) { - if (d1 & c) - add |= a; - c >>= 2; - a >>= 1; - } - c = 0x80; - for (i=0; i<4; i++) { - if (d2 & c) - add |= a; - c >>= 2; - a >>= 1; - } - bit = 0; - b = 0x04; - c = 0x80; - for (i=0; i<3; i++) { - if (d3 & c) - bit |= b; - c >>= 2; - b >>= 1; - } - b = 0x01; - a = dat[add]; - a ^= (b << bit); - dat[add] = a; - return 1; - } - else { - i = 0; - while (d1) { - if (d1 & 0x01) - ++i; - d1 >>= 1; - } - while (d2) { - if (d2 & 0x01) - ++i; - d2 >>= 1; - } - while (d3) { - if (d3 & 0x01) - ++i; - d3 >>= 1; - } - if (i == 1) { - /* ECC Code Error Correction */ - read_ecc[0] = calc_ecc[0]; - read_ecc[1] = calc_ecc[1]; - read_ecc[2] = calc_ecc[2]; - return 2; - } - else { - /* Uncorrectable Error */ - return -1; - } - } - } - - /* Should never happen */ - return -1; -} - -#if 0 -EXPORT_SYMBOL(nand_calculate_ecc); -EXPORT_SYMBOL(nand_correct_data); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Steven J. Hill "); -MODULE_DESCRIPTION("Generic NAND ECC support"); -#endif diff --git a/yaffs-header.c b/yaffs-header.c deleted file mode 100644 index 7cb71e0..0000000 --- a/yaffs-header.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * - * Copyright (C) 2002 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * 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. - * - */ diff --git a/yaffsdev.c b/yaffsdev.c deleted file mode 100644 index f325b78..0000000 --- a/yaffsdev.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * yaffsdev.c - * - * Copyright (C) 2002 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * 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 "yaffsinterface.h" -#include "yportenv.h" - -#if YAFFS_FILEEM -#include "yaffs_fileem.h" -#else -#include "yaffs_nandemul.h" -#endif - -#include "yaffs_guts.h" -#include - -#include -#include -#include -#include - - - -unsigned yaffs_traceMask = 0xFFFFFFFF; - -yaffs_Device device; - - -char *testStr = "this is a test string"; - -char *testStr2 = "abcdefghijklmnopqrstuvwxyz1234567890"; - -void TestTimexxx(yaffs_Device *dev) -{ - yaffs_Object *f; - int x; - - - printf("Start\n"); - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - - x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename"); - -} - - -void TestTimeasasas(yaffs_Device *dev) -{ - yaffs_Object *f; - int x; - int i; - int b; - char data[200]; - int written; - - - printf("Start\n"); - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - - x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename"); - - - - for(i = 0; i < 10000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2)); - } - - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - printf("Flush\n"); - - yaffs_FlushFile(f,1); - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - yaffs_DumpObject(f); - - printf("Resize to 3000\n"); - yaffs_ResizeFile(f,3000); - printf("Resize to 2048\n"); - yaffs_ResizeFile(f,2048); - - yaffs_DumpObject(f); - - yaffs_FlushFile(f,1); - - - - -} - -void TestTimeBigDeletes(yaffs_Device *dev) -{ - yaffs_Object *f; - yaffs_Object *sl; - yaffs_Object *lnf; - - yaffs_Object *hl1; - yaffs_Object *hl2; - yaffs_Object *hl3; - yaffs_Object *d, *df; - - int x; - int i; - int b; - char data[200]; - - char * alias; - int written; - - - printf("Exisiting objects\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - printf("Exisiting objects in lost+found\n"); - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject); - - printf("Start\n"); - - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - for(i = 0; i < 100000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2)); - } - - yaffs_FlushFile(f,1); - yaffs_DeleteFile(f); - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - for(i = 0; i < 100000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2)); - } - - yaffs_FlushFile(f,1); - yaffs_DeleteFile(f); - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - for(i = 0; i < 100000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2)); - } - - yaffs_FlushFile(f,1); - yaffs_DeleteFile(f); - -} - -void TestTime(yaffs_Device *dev) -{ - yaffs_Object *f; - yaffs_Object *sl; - yaffs_Object *lnf; - - yaffs_Object *hl1; - yaffs_Object *hl2; - yaffs_Object *hl3; - yaffs_Object *d, *df; - - int x; - int i; - int b; - char data[200]; - - char * alias; - int written; - - - printf("Exisiting objects\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - printf("Exisiting objects in lost+found\n"); - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject); - - printf("Start\n"); - - - // Test the problem of: - // Create file - // Delete file - // Create file with same name - // Delete file <== crash - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - yaffs_Unlink(yaffs_Root(dev),"Name1"); - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - yaffs_Unlink(yaffs_Root(dev),"Name1"); - - - - // Other tests - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - - x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename"); - -// Write a file with overwrite, then read it back and save outside yaffs -// This is to test that write caching works. - - for(i = 0; i < 100; i++) - { - unsigned char x[500]; - - memset(x,i,500); - - written = yaffs_WriteDataToFile(f,x,i*500,500); - } - - for(i = 0; i < 100; i++) - { - unsigned char x; - - x = i+5; - - written = yaffs_WriteDataToFile(f,&x,i*500 + 2,1); - } - - - { - int h; - - h = open("bork",O_RDWR | O_CREAT | O_TRUNC,0666); - for(i = 0; i < 100; i++) - { - unsigned char x[500]; - - yaffs_ReadDataFromFile(f,x,i*500,500); - write(h,x,500); - } - close(h); - - - } - -// Big write to fill disk - - written = 1; - for(i = 0; i < 1000000 && written > 0; i++) - { - unsigned char x[500]; - - memset(x,i,500); - - written = yaffs_WriteDataToFile(f,x,i*500,500); - } - if(written <= 0) - { - printf("YAFFS full\n"); - } - - // some short reads - for(i = 1000; i < 50000; i+=2) - { - yaffs_ReadDataFromFile(f,data,i,20); - } - - - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - printf("Flush\n"); - - yaffs_FlushFile(f,1); - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - printf("File length is %d\n",yaffs_GetObjectFileLength(f)); - - sl = yaffs_MknodSymLink(yaffs_Root(dev),"sym-link",0,0,0,"/tmp/alias"); - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - printf("\n\nsymlink alias is \"%s\"\n",alias = yaffs_GetSymlinkAlias(sl)); - - free(alias); - - printf("Unlink symlink %d\n",yaffs_Unlink(yaffs_Root(dev),"sym-link")); - - - yaffs_ReadDataFromFile(f,data,1000,50); - data[50] = 0; - - printf("Read data is \"%s\"\n",data); - - yaffs_DumpObject(f); - - printf("Resize 3000\n"); - yaffs_ResizeFile(f,3000); - - printf("Resize 2050\n"); - yaffs_ResizeFile(f,2050); - printf("Resize 2049\n"); - yaffs_ResizeFile(f,2049); - printf("Resize 2048\n"); - yaffs_ResizeFile(f,2048); - - - printf("Resize 2000\n"); - yaffs_ResizeFile(f,2000); - - yaffs_DumpObject(f); - - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - - - - yaffs_FlushFile(f,1); - - - printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename")); - - yaffs_DeleteFile(f); - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - // Create a directory and play with it - - - printf("Find or Create directory and play with it\n"); - d = yaffs_FindObjectByName(yaffs_Root(dev),"direct"); - if(!d) - { - d = yaffs_MknodDirectory(yaffs_Root(dev),"direct",0,0,0); - } - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject); - - printf("Make file in directory\n"); - - df = yaffs_MknodFile(d,"file-in-directory",0,0,0); - yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject); - - - // Do some stuff with hardlinks - // - // NB Deleting hardlinked objects can mess up pointers to hardlinks. - // The mechanism is as follows: - // * If you unlink a file,softlink or directory that has one or more hardlinks, - // then the object is renamed to one of the hardlinks and that hardlink is unlinked. - // This means that a pointer to a hardlink so deleted will point to an invalid address. - // Thus, make sure that pointers to hardlinks are immediately dereferenced. - - - printf("Hard link tests\n"); - - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - hl1 = yaffs_Link(yaffs_Root(dev),"HardLink 1",f); - hl2 = yaffs_Link(yaffs_Root(dev),"HardLink 2",f); - hl3 = yaffs_Link(yaffs_Root(dev),"HardLink 3",hl2); - - printf("\n\nHard links created\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - yaffs_Unlink(yaffs_Root(dev),"HardLink 1"); - printf("\n\nHard link deleted\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - yaffs_Unlink(yaffs_Root(dev),"Name1"); - printf("\n\nHard linked file deleted\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - yaffs_Unlink(yaffs_Root(dev),"HardLink 2"); - printf("\n\nHard link 2 deleted\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - yaffs_Unlink(yaffs_Root(dev),"HardLink 3"); - - printf("\n\nHard link 3 deleted\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - // NB We don't allow unlinking or rename of the root or lost+found - // We allow setting attributes, but these must not be written to - // NAND since they are not real objects. - - printf("Attempt to rename lost+found - should have failed\n"); - x = yaffs_RenameObject(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME,NULL,"Renamed"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - - f = yaffs_MknodFile(yaffs_Root(dev),"pfile",0,0,0); - if(f) - { - yaffs_WriteDataToFile(f,testStr,0,strlen(testStr)); - } - - yaffs_Link(yaffs_Root(dev),"phl4",f); -} - -void TestTimeDeleteFocussed(yaffs_Device *dev) -{ - yaffs_Object *f; - yaffs_Object *lnf; - - - int x; - int i; - int b; - int written; - - - printf("Exisiting objects\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - printf("Exisiting objects in lost+found\n"); - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject); - - printf("Start\n"); - - - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - - x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename"); - - for(i = 0; i < 100000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2)); - } - - - - yaffs_FlushFile(f,1); - - - printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename")); - - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - -} - -void TestTimeTnodeFocussed(yaffs_Device *dev) -{ - yaffs_Object *f; - yaffs_Object *lnf; - - - int x; - int i; - int b; - int written; - - - printf("Exisiting objects\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - printf("Exisiting objects in lost+found\n"); - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject); - - printf("Start\n"); - - - - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - - x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename"); - - for(i = 0; i < 10000; i+=20) - { - - b++; - if(b & 1) - written = yaffs_WriteDataToFile(f,testStr,0,strlen(testStr)); - else - written = yaffs_WriteDataToFile(f,testStr2,0,strlen(testStr2)); - } - -} -void TestTimeBackgroundDeleteFocussed(yaffs_Device *dev) -{ - yaffs_Object *f; - yaffs_Object *lnf; - - - int x; - int i,j; - int b; - int written; - - - printf("Exisiting objects\n"); - yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject); - printf("Exisiting objects in lost+found\n"); - lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME); - yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject); - - printf("Start\n"); - - - for(j = 0; j < 20; j++) - { - printf("Run %d\n",j); - - f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1"); - if(f) - { - printf("Found\n"); - } - else - { - f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0); - printf("Created\n"); - } - - printf("@@@@@@@ Run %d, object %d\n",j,f->objectId); - - for(i = 0; i < 1000000; i+=20) - { - - written = yaffs_WriteDataToFile(f,testStr,i,100); - } - - yaffs_FlushFile(f,1); - - yaffs_DeleteFile(f); - } - -} - -int main(int argc,char *argv[]) -{ - - int nBlocks; - -#if YAFFS_FILEEM - nBlocks =(2 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK) ; - device.writeChunkToNAND = yaffs_FEWriteChunkToNAND; - device.readChunkFromNAND = yaffs_FEReadChunkFromNAND; - device.eraseBlockInNAND = yaffs_FEEraseBlockInNAND; - device.initialiseNAND = yaffs_FEInitialiseNAND; - - printf("Testing on file emulation\n"); -#else - nBlocks = (2 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); - device.writeChunkToNAND = nandemul_WriteChunkToNAND; - device.readChunkFromNAND = nandemul_ReadChunkFromNAND; - device.eraseBlockInNAND = nandemul_EraseBlockInNAND; - device.initialiseNAND = nandemul_InitialiseNAND; - - printf("Testing on RAM emulation\n"); -#endif - -#ifdef YAFFS_START - device.startBlock = YAFFS_START; // Don't use block 0 - device.endBlock = YAFFS_END; -#else - device.startBlock = 1; // Don't use block 0 - device.endBlock = nBlocks; -#endif - - device.nShortOpCaches = 10; - - - yaffs_GutsInitialise(&device); - - // yaffs_GutsTest(); - - TestTimeBackgroundDeleteFocussed(&device); - - printf("Cache hits %d\n",device.cacheHits); - printf("Retired blocks %d\n",device.nRetiredBlocks); - - printf("Deletions %d\n",device.nDeletions); - printf("Unmarked deletions %d\n",device.nUnmarkedDeletions); - - exit(0); -} diff --git a/yaffsdev.proj b/yaffsdev.proj deleted file mode 100644 index d93143da855a717b2eb41d9bb2ebc15985cd930c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53248 zcmeHw4VYwAb>OY)o?*J)p8)|SifdTm6C#wzzIvnV5pu>R<2Ra<+ zaG=A14hK3M=y0IJfer_L#W-*wd0Kf)xmWp&a+~sQ<*;(Kl2Xo8o{^uHzaamme6xIk z{G#-a(j(IC((g$pq^qQ~bcytL;zQzB#ZQYL7jG4B5pNK$7q1bIi5W31O7Q((!d~(7 z!nxwV7oHLpg+CY05v~=!9oZ{xK6V|2uM2csO!UxGOR& zygecc^O5gG-W2(7k*$$CB7f6Uiu~7}#mJ34!;uFgw?%G(5rT^xk(yQfKSwCJ}E*H!+>+9Kq zk;zhKRrk#@7KbcjMwYRO!I+gJqYe}HW(zIy!9vb2%*-xL(@ZMmYE3I0F-jFp&{9>Z z`BDuyvY{phVpquhGYvFUB?$2R&tt<&_d<3 zBV;Bubs%$COV+DZtyEjeR9Cec!Px!z<>`Du(=Es-#?ES5PG8WL>-j>?dNVj=Jz~O4 zy_8)`mW#zqDYrjg(yW&h!$Dn3LHgBItvXj?uoeL3FkQ&3UZx#SCzAkK#gI+Hq1iM5 zOdj07B+U$dm&)bB{&F@`%a=W_pEYiPNu2-{~v)0LhdZCs- zlrQDVM|Bcq-5R>KR@DcNR`WHD#8}*FwOp?lQ9HAGRp-mtsSeuP=UaeYI(JqDUzXbr8bl)XqB}XYgMEO&2s?SaSd?|)%EI7 zo>hQ4s16e2c|fPM4*-mog>I79bfVXbD(&wD=s9VX{>|%ZN-JnJOnXZ6yYI04>9^RMH*HmK^sKAJ&)v{~q+YU_b-#?cmx|XSC*SPT$vKh!iXM)~2kXtsm zb*!dUiv-5h!h7z}&##rnnuWnS7GIkLr^SzC2z$3|t9%A^XsD3=Py0egP6RIX~d zG*n*Bs&5=u2XfWS(E;QxROo!Qd^J2-l{yI3cQxees%eY`Fsx>+q(jHk$q<2YTGuLO zQ=+Id*{oKn4d^xKomtXnj#d4uRjtyG4Tofp=&YGlv-&{octs=YRjpQ4*I9Euge{R) z(NdXJ=K4xqE#`rw4Rt^}mH}F0YSb9s*}T#RFDZ@&DChu+0D0|*mbPXTK3lUL%tNzK z+s=_s9UwEaTsgIvQ&*~O6pf|~kVD33);MY(-VdDy%G7>t9xMTJZkgf#Z>tC#j@>h` z+MCPkhj&8HnMpN!-z2I3D@2yc>o_9k7V6xbpI&J4YVrVGC(!viAQ(*R2SlY9Lq zbz>?vC$4lZFd%R#ovRlsY2eqU5*;RU^X(>V7rv4XngUtIuRH8@02c6YDw)bC zTP~N`W}r#)b3ry?GzWP~Sa%7A4=bqJ_O&I^cT{QRG0o)+%0`cRHU24C&diN2$<*ctm}Aqtm}8f=Yw{F44eId z#|Sweet)r-kk`ZSEQA-~w|gHUuZG_mgfD{MZ4gHI>kRnwAdK*LLU;;(w;S-EHQ?W5 zz<U0<9tdN7o%1b5j|5??uN@FZdfs5b?}G595WdiW&lvE16h5b|WMFSda?7y3 zr#oW8HesdAk%6c>F*2$aU|Zz@!d}I%Hhe&6?@5Ey2Ba6Tseq-fM}WiD@aA8XqAXWo zhsujY=(>~QV6Up25Ck!kbuE|2HLkIBW8*wvqS1^77T3GNOTW{TP($Re8Yn1gG@1(Vg&Ad|s;69^X|gQnP>pe-`6x*8%+ zgY>Wtn`Z~@E@p6WOhVeanIu8tP}63$qjYO(2uB=wWX-n4819##MLDcC>8X6SlWvxs zf0CdXBD-n(oGDGC1gTk0F4&-1cnI8V7YNp^ZTSjzIa9{ctX#e+f|d?@14{0ulF6pb zm8_dl@uCE(wGri0&(qgfR zIIPmLnZjCGuMN_tT)CLZmsAjUm&!+BWkAXmt(4A}R?37_s#m8Acu|}i{|AuRTwe=4#e{18nUrc$e?(ho~qJxw663ZE!1c_ASnu5Bvw(* zp5;1ZbJy)@IdgMof)x25iMb)^vH^vFwBbQAT&1|q!rW+O<0~NH&jqQZ;2%zQ zJ{=BpIMCrhhXWlBbU4uAK!*bz4sIv2ptcJe<-0@D6l7NmdAA`g=v z{i(S7CN8dv{0(^w;@$;uzhT6O$s^=Jh`X7CJBxgc+y`;*hB(ED?;>9(pMkjl0AcFs z0DjLR-yk1>xLe@aROGWxXJ$%AGKG8&j)SN)KAFj`fi9)PC?E?)0mIQ)bTAr=t4GTD zoT>Ji(vIY_n%dV73eflkV*vp1=Q+mU>Rjfq>HtTBK2J-MyLWGN^YZ%Y_1* zc%t&Sm$-OrbPR}#sd*2MX;8jjYJi#+m>z;ci998a4#y0nB{-yJ$6&0$i|kB}78{D3 zhs8)9Lzf+-xhLiLSmYB@ZFq@`-mdgG(x4Qq8njYFUE5af@%4eG2C`Lb)INndx=DKxW@5f611 z@-_%cl|gk)tLC$;@igJr@W?P23t?}!JEqy<&|C?K_p~X0dgX1pW;XOW*h=JK$!mqRSXThSRre@bNRg=8<=%{zF@@CWqm3AE; zS}PZtFH+*;V_@UwTBO)RLwtOE%+tIZ;%|e-HpZ^_FwWqO#;*8?mwOG6zar!%#y$Ld z>Et!60iO=jvW6$TgMUN(ZLrYNxiA$&j8^4c55*JELmPD%TqnaSXdD+m@x-uqq0u0p z%}{D-hIna=#&Cjnc53g^)}Yi_#4W-Zxv|v8iNZSyS)`j8w?XvYYG%3V_9KqVjA(qs z927ZV???&sjZJtLmd;FCQ&&Wb>HSj+OSBz2ZHb3r#b#SbL$63!lNn1B(2f`n)OlrG z%i7g_HjaRtZolJ<8;{sIEf3Ejy>0O7ht+N7#KF+xbVbXQi)5pOfAr-6G|sj1&d!|Ffis^bg{*;v?d_#G<$&&WL-( zxOjnhmiQ&%(_sI9mvEDCLMRI%_{XcTpwz=>qeNmG#-r9t( z0nba@5{ka!+9z*h&6Y7utavtKN6W014LjV%_OJmBrrn0KFU3Tf71vUjom-|6IbU1< zCa=&90NQ@j5@2ahTTv(xPBU+7%Am^W^bfTY8|*VFrhSZcSC99CMkedz0C=Wo^s<>f zd;8VnQ>GkvR!~b!xd8QL2q**%Upl?%sv-NbjndIl z-(!1D%L?0thSuoos*3M6)b>o(n;E9R6cco>($)=*n|sZ4dHH&fwF z@CBg89!QvIwC!f@LJ%NJYiMCCwFPQMoxm9HsR@XK|1QQiKoo!kf5BG!ZQdVG00LOc zbv4G|1*e`$Sn2?o!NAT~jjPgRxsLKbZ~I^Kay?l4_n>z!<$R589Xo^53vcT-x0tQz zBt$#=kb7&vJECzc@a(DWbWL^?FD%lUtZVENx*RaEG(mN?39qTm*BZD#GMyz^>vG#A z51)%kKpzM=;-GBhspql}aJcTzmOqU{GG`qP?>R!IP2NTLQmB zN3@+-c;qOot@0%YqAAN|6@{T*(w4vrkpl={VGZD7(D7oLJf%FL{H5}F<#y$R%G;F< zMN@VtVdZD?}(gc~E|ptjNzxKL$C#Ur8U4K1lrnR;BC3 z6XH?vYVq%3Y+__ab`f&(^GZ%w5QBGAj-z%kBtD+|>Op7Yr9 z*VtY67q!}28Ji|^0oMIpY)cBnJ)$$SG(sGqwun zh3w5A*=cNkd7ME!Iq>w;oP!safww5Fbqq{5S9F(bs6shv&g};P9Vl|ZtuirPM!dvK zS~!ZxZPo{f>B|9pukt<|R`fwvxfwvK(wgXsRJLdG(Tk0~Z-vZcT>+L@R)h26!q=@l zY1GvvO|LEGi&{p4`NCv!hxEDb^Up2&NFNMqY>1 z4g^E(xaBc>0-Y6)qIXb}(P^Jz;nYciT5-lii_0{aYn$LSAX*@_ScYQ3)@-w&8nDiq z)saGq!;>s*Gd#zrzHaJ3J$}#ZG2I*3E*>FTfT{Y=+uis#; zj_wl!3J-#cCETI~{s5B+YH+p8A5}VK4>Y}F3(jqOQQSZRh$JWy&%ruwnj1?f@U1Bj zV~2%}kJ&9uu-|QXwvIqSJLn!q0`y3Evm` zr_e2-FNc;x?+cBGs-ahfW1m>`geyI6~8FV3r|GW zA}{oOqi3z>=i6@HW~kx+GW`UW`UC?E0u=;iMGpoAm5crMlmoYgkm=X7S?=X*lXQv0;aByX&!`0*TdZ@Rq_g8x(t)N5p2o_E=v`8Xm2uij~@N z<7f{AB5cYqG(zCohbSt*$Kmz|_QE^^gf$0?NEvn}4J-zHa$)m+ASGgY5Z{=#;R(>t zjU`M{JhZV06h<0~awddRJC@l#@PD0U^?`=cCV(++eQb{2HcH8#p8Duj4oAl)n(3wb zs4DUpTN47xbo2rMP=iQoU}J!-bJLqqYo=IxaH@jh?HI%H80s@Sw1w@yFr4sFXGTnIWW1o& zKox}z9fmGLFdu39QpcZB@3>aAh5qcd2=;>v2wrQKdxds8a zWM<6Ug{^$rppCA+OPN9%cQ$F7x0hEFyu#{ zRHcMP*@&zh~{2{2)DDUbWkd7y@kmRfGMc{6E) z!UIdG`Fd>;d!9|2$+q!foWq6<6IDlZ-%!VW%)&TqZP36(O;iYK(_phFPDhGnVBb7R6E~0gMe)j=*^om2(#B=1_;K2!x3QZ+SK%C(2h75@5jBQ zJBVn5cyry>h?TK1Y-uL(j1Y7B>xbb97D!`01~U${ZII)UQTwnn=3OQ+ikvpVU`Xd_ z_iprUP=-!Z=^Q;>t{SEDHzkdYCR%Z9bj)i5<&VD&0=<3OuV)Nn&v06uG#WS(6J9F4 znKY!(62zgaM)3Lmg7U2Lpz;9q0dS*ogOY)r{DN|Z@&oz%a0B3<$?uX+$Oq*m@c#d1 z`4`g9rH7^eA>9ey|8J2llFpURmVPSUDZW>Hr??Bg-w~oB+uq|Hd>4{6>2q+az|(R< z`INLK&4WLIZutY!Ti`~3n)n*=Q^MuK&*7%OROIQN-|xAg=e})g+qP}{*ctoJ_+=6i zbZF^tpu>R<2Ra=1b>l!E6bO{g2osd2=^})!RYKs@B_4$pb96k!)>do{OK5C-BosXs z4Xtlj{|OlcH0QW*olg9x6F2HHoKF0w6Zh$+{pG+98&&Oe@~DH`+h2cGd4lcnD|_#X~==lD}VVk7~x7`?a$b4*ygd4c}V6s zBgW$;xDPU@=DKwnWmSpu@f1zGv%weZR!GW zsu>PM=6hb5fHO0v$^r@SMixVDTzc&>_7{+oz#Vf>DPK@Nq}&1b|6Qm2E9FY%Vr4>k zHQ4??1-Ae9fd2p6oOZp)0 zgYazU`y|-`ako3-{+`GXcL&7TpYM^MfF zeZ&#>LvlC7{fQ&)N92zn?xT*lr^)pY_n)}9v&b`~3~~RNi|ZoKl1b=j+o0{<|6o7u z7ufIc`;7;Bc0c{e|Fdm72H-t@F??ru_m*wo7!-d)9Il{`W*S86_t{}YZl-Tz(nfgk z-AloJs>hA50zLPi0KUT)Y5P_D{N7eVz6cB-gK_N-p#Wz8=!}2pleRPd5%SAF{%wbL zt3n^dFZMwkKk$p=-&L@Nxf}+p-J`GCee>1}wmp9J$F|8`Z2ZGtb1cJjK|f}iM&ne_ zF^X!9F5|AzX(G+7_f2J6-i9{AHUWVXwh6wB7kVRU0UT)2g|_WLYqL28Oh@mhb6rjs z*ZI5ZM#o1cRJ44nWPLBEGj5|BOQ`YD1b9V`sfmdR{5=N07mXz@iVuT^ADpSKV5O*_ z7C;t{7xz>NyT5J7+@7HM90f^N;P5Vg45p=GCd&-$bkbWYqp8kL!hR_v8Hp0qdn%=A zeWxdD>A6x?;}o^oMmbZ^Dr+&85%qVJMq4oO!UCJ1s{3-i_I8{t^*jTpcv?6b?I}s% zog@jgf3!06>>3Sf19t=3RyWtKm+PymT6M0(x`f#X=(d#WtJsS9jh|y@h`GC9k%c}Q z<1Wbd>e#i5<#)XNKGe>G_IB3)TB`P@Envjks0DB&1a1plnn10BgGbsMtNYp{+ukA& z+H2=;;xXkrJ}Um)uAgTnZu z@C3$$kY~P@)+<^TOw83PNJhc=82r8D640IoI6Fv^nX|CGald_d?yJ&K}&qAM@suZKzc9aS4>G zOrL-+i<3UL>YATlt88<>Rw-)2vB=$=;q~z5&Zeo)tsx*H2mA-8iom7TzRZT2Vq;Cq zy0@TB+^*CCa%$jH&0=hT0#xqI zU$ZNK41!t5R{MNN^1T2h01KIA5w7Dl)er6Df%9@zSK!{q+du`#Y{v3nLc5#Zep_^7 z2#_hwY6d6t_6AJWX06msbFwB=cF{-hQN)q3X%^J~aC%{CacbeMQ>pZx{d3977TYY6 zFOH_Unocp=sVOr}Q^btBdmYz<*z;NQ@xri*w5o=hM7g?SKMX3~F3IN?fIKj@pt|`p zrP?OF^SUtv$aDehn`o})Jp%3Uo-xjYB0#n@OXK!4yCMRQ1a|VKdA)7V!M%K=<@_jk zrUl3w{#(viF{v+ZOPKF%77#SM}OUguO9X)OE)|7v|l6Fw8@AjO3f;u?_H3}1rbLq9cc zeBdC&zsONP`j*ju(juHI*L8*xZ&6JqiTumm3}2k#L$4ifeBe5#eSEa-L??XOBE)S1AMgmtG2CaY7j#y9=vlboLe-adsDU`G$7KMsIPpZbIu?^~Z~OP)f&HMaf0KRi558feQ=iPy<#&th8TVRxDk&G#-YL`sj*{w@x=C(AZc#iOVHf> zD?pC7{qcl(-@XDQmgpIu&eLT?y#mD03skwbgyC0$463fh(}5AM03mGP0v~eesoBXr z`==Zo&GWKN0u!UBU<_bHz|mQHif=+(^eaIX-?Lz>1Sg;7pvAv|K{NZZk5H>x2^{KW zO`R5-GRKQ{nRW_l67@d#D#UP`WW1C~#X4ffxrKNqzv;!aG114zopb$gd~9@Vvy=Vw z%>JpV19-^XOvBt(xVO%vQ4QTxHg9Drz{7Hi={{H+=%~9O-Pbu#6BYYH1@jhMx)KEi z)4^;b)pZwM1WWl^&f9>N5rNGw{)$2~PtLl6rU-ZigUd32V@CrXTjX${zAUx?d1V6L T4!~7JPUji8(&Sc1iunHl9PXlS -- 2.30.2