aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-12-05 12:55:53 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-12-05 12:55:53 -0800
commita7e526129f6ea298513ef4ce7aa6db08fc069d14 (patch)
treedf86601ee9de6168e952725ae671afbccf520484
parent53b1f08612996c52fb590090803ad0bc184d667c (diff)
downloadltsi-kernel-a7e526129f6ea298513ef4ce7aa6db08fc069d14.tar.gz
axfs patches
-rw-r--r--patches.axfs/axfs-add-documentation.patch356
-rw-r--r--patches.axfs/axfs-axfs.h.patch120
-rw-r--r--patches.axfs/axfs-axfs_bdev.c.patch195
-rw-r--r--patches.axfs/axfs-axfs_fs.h.patch147
-rw-r--r--patches.axfs/axfs-axfs_fs_sb.h.patch110
-rw-r--r--patches.axfs/axfs-axfs_inode.c.patch660
-rw-r--r--patches.axfs/axfs-axfs_mtd.c.patch376
-rw-r--r--patches.axfs/axfs-axfs_physmem.c.patch89
-rw-r--r--patches.axfs/axfs-axfs_profiling.c.patch630
-rw-r--r--patches.axfs/axfs-axfs_super.c.patch1011
-rw-r--r--patches.axfs/axfs-axfs_uml.c.patch71
-rw-r--r--patches.axfs/axfs-axfs_uncompress.c.patch113
-rw-r--r--patches.axfs/axfs-kconfigs-and-makefiles.patch85
-rw-r--r--patches.axfs/axfs-mount-as-rootfs.patch93
-rw-r--r--patches.axfs/axfs-xip-debugging-support.patch303
-rw-r--r--series23
16 files changed, 4382 insertions, 0 deletions
diff --git a/patches.axfs/axfs-add-documentation.patch b/patches.axfs/axfs-add-documentation.patch
new file mode 100644
index 00000000000000..49f96559a9cbf0
--- /dev/null
+++ b/patches.axfs/axfs-add-documentation.patch
@@ -0,0 +1,356 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:56 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:15:14 +0530
+Subject: [PATCH v2 RESEND 14/15] AXFS: Add documentation
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF61CA.4020603@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+Documentation for AXFS.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ Documentation/filesystems/axfs.txt | 333 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 333 insertions(+)
+ create mode 100644 Documentation/filesystems/axfs.txt
+
+--- /dev/null
++++ b/Documentation/filesystems/axfs.txt
+@@ -0,0 +1,333 @@
++AXFS user manual
++
++
++1. Overview
++===========
++
++Advanced XIP File System (AXFS) is readonly file system for
++Linux. AXFS supports compression of file and execution of XIP
++(eXecute-In-Place).
++
++XIP can reduce system memory requirements. It doesn't load binary
++text to RAM and executes text directly from memory where they are
++stored. Devices such as NOR flash and memory which is directly
++addressable can be used.
++
++Whether a file is XIP or compressed can be specified in 1 page (4KB)
++units. By this, it is possible to make the image size smaller than a
++file system which is specified in file unit such as cramfs-xip.
++
++To determine which page in a file is XIP or compressed, AXFS provides
++profile utility.
++
++Refer to the following link for details of AXFS.
++
++ http://axfs.sourceforge.net/wordpress/
++ or:
++ http://elinux.org/AXFS
++
++
++2. AXFS specification overview
++==============================
++
++ Item | cramfs-xip | AXFS
++-----------+------------------------+----------------+----------------
++ | Compression of data | Y | Y
++ +------------------------+----------------+----------------
++ |Compression of metadata | N | N
++Compression+------------------------+----------------+----------------
++related + Fragment processing | N | Y
++ +------------------------+----------------+----------------
++ |Change of compression | N | Y
++ | algorithm| |
++-----------+------------------------+----------------+----------------
++ |Restoration of mode | Y | Y
++ +------------------------+----------------+----------------
++ |Restoration of uid ,gid | N | Y
++ +------------------------+----------------+----------------
++File |Restoration of file | N | N
++related | modify date & time| |
++ +------------------------+----------------+----------------
++ |Max Length of file name | 252 characters | 255 characters
++ +------------------------+----------------+----------------
++ |The maximum size of file| Less than 16MB | Less than 2GB *1
++ +------------------------+----------------+----------------
++ |The maximum size | 256MB | Less than 2GB *1
++ | of file system| |
++-----------+------------------------+----------------+----------------
++ |XIP Unit | File | Page, file
++ +------------------------+----------------+----------------
++XIP related|Binary XIP | Y | Y
++ +------------------------+----------------+----------------
++ |Shared Library XIP | Y | Y
++ +------------------------+----------------+----------------
++ |XIP profile | N | Y
++-----------+------------------------+----------------+----------------
++ |Supporting byte order | N | Y *2
++Others +------------------------+----------------+----------------
++ |Writable | N | N
++-----------+------------------------+----------------+----------------
++
++ *1. It is not confirmed on the actual device
++ *2. It is confirmed on source code but not tested on the actual device.
++
++
++3. AXFS configuration of kernel
++===============================
++
++Set it from make menuconfig of kernel as follows in order to use AXFS.
++
++ File systems --->
++ Miscellaneous filesystems --->
++ <*> Advanced XIP File System (AXFS) support (EXPERIMENTAL)
++ [*] Profiling extensions for AXFS (EXPERIMENTAL)
++ [ ] First Mount AXFS as Rootfs
++ [ ] AXFS debugging support
++
++Enabling "Profiling extensions for AXFS" makes profile function of
++AXFS valid. A CSV file which specifies which file and which page of
++this file to be XIP can be created based on the profile information
++which can be acquired by this configuration.
++
++In case of making AXFS image as rootfs, kernel mounts AXFS image prior
++to NFS when booting if "First Mount AXFS as Rootfs" is set.
++
++
++4. Using AXFS
++=============
++
++There are 2 tools for AXFS. They are mkfs.axfs and axfs_csv2xml.rb.
++mkfs.axfs is a tool to create AXFS image. axfs_csv2xml.rb is a tool to
++convert profile data of AXFS to XML format file which can be read by
++mkfs.axfs. mkfs.axfs reads the specified XML file and set the pages to
++be XIP. The mkfs.axfs tool can also read the csv file format and set
++the pages to be XIP.
++
++4.1. Creating AXFS image
++------------------------
++
++AXFS image can be created by mkfs.axfs tool. Usage of mkfs.axfs is as
++follows :
++
++ mkfs.axfs [-h] [-i infile] dirname outfile
++
++ -h : Output of help
++ -i infile: Specifies XML/CSV file of XIP information
++
++4.2. AXFS image
++---------------
++
++For example:
++
++ $ mkfs.axfs -i axfs-xip-profile.csv axfs-root-dir axfs-rootfs.image
++
++If it is successful, the following message will be outputted :
++
++ ......
++ number of files: 501
++ number of 4KB nodes: 2910
++ number of 4KB xip nodes: 235 <-
++ number of xip files: 9 <-
++ ......
++ Total image size: 8363941
++
++The above arrow parts are XIP information. In this case there are 9
++XIP files and the number of pages inside these XIP files are 235.
++
++4.3. Mounting and unmounting AXFS image
++---------------------------------------
++
++4.3.1. Mounting method
++----------------------
++
++The examples for mounting AXFS image are given below.
++
++4.3.1.1. AXFS mount on an embedded board: KZM-ARM11
++---------------------------------------------------
++
++The following example is to write AXFS image to NOR flash of KZM-ARM11
++target and then mount it.
++
++In this example, the AXFS image will be written to "root" partition of
++NOR flash. From the following output of the kernel booting message,
++
++ physmap platform flash device: 04000000 at a0000000
++ ...
++ 5 RedBoot partitions found on MTD device physmap-flash.0
++ Creating 5 MTD partitions on "physmap-flash.0":
++ 0x00000000-0x00060000 : "RedBoot"
++ 0x00080000-0x00280000 : "zImage"
++ 0x00400000-0x01400000 : "root" <- /dev/mtd2
++ 0x01400000-0x01600000 : "kernel"
++ 0x03fe0000-0x03fff000 : "FIS directory"
++
++It is clear that the "root" partition size is 16MB and its physical
++address is between
++ 0xa0400000-0xa1400000.
++
++AXFS image is assumed to be stored in /tmp/axfs.image.
++
++Flashcp is used in target.
++
++ $ flashcp -v /tmp/axfs.image /dev/mtd2
++ $ mount -t axfs -o physaddr=0xA0400000 none /mnt
++
++AXFS image can be unmounted by the following command :
++
++ $ umount /mnt
++
++4.3.1.2. AXFS mount on an embedded board : KZM-A9
++-------------------------------------------------
++
++The following example is to write AXFS image to RAM of KZM-A9
++and then mount it.
++
++From the following output of iomem that is read from proc entry
++
++ physmap platform RAM device: 0x50000000 to 0x5effffff
++
++ $ cat /proc/iomem
++ 20000000-2000ffff : smsc911x.0
++ 20000000-2000ffff : smsc911x
++ 40000000-486fffff : System RAM
++ 40020000-40375023 : Kernel text
++ 4038e000-403f0ae3 : Kernel data
++ 50000000-5effffff : System RAM <--Load to RAM start address + 256MB offset
++ e1020000-e102002b : serial
++ e1030000-e103002b : serial
++ ...
++
++Boot the target with following boot parameter and load axfs.image to RAM
++address 0x50000000.
++
++ console=ttyS1,115200n8 mem=240M rootfstype=axfs ip=on
++
++AXFS.image is assumed to stored in /tmp/axfs.image
++
++tools/axfs/bload.c is used to load axfs.image to System RAM address.
++
++ $ bload /tmp/axfs.image 0x50000000
++ $ mount -t axfs -o physaddr=0x50000000 none /mnt/
++
++AXFS image can be unmounted by the following command
++
++ $ umount /mnt/
++
++4.3.2. In case of rootfs
++------------------------
++
++The examples for mounting AXFS image as rootfs are given below.
++
++4.3.2.1. Mount AXFS as rootfs on KZM-ARM11
++------------------------------------------
++
++The following is an example of specifying /dev/mtd2 which is
++same as example in section 4.3.1.1 as rootfs in KZM-ARM11.
++Set the booting parameter of kernel as follows.
++
++ "console=ttymxc0 mem=128M root=/dev/null rootflags=physaddr=0xa0400000
++ rootfstype=axfs ip=on"
++
++If kernel option "First Mount AXFS as Rootfs" is set , kernel mounts
++AXFS image prior to NFS.
++
++4.3.2.2. Mount AXFS as rootfs on KZM-A9
++---------------------------------------
++
++Set the booting parameters of kernel as follows to mount axfs
++as rootfs for KZM-A9 Board.
++
++ "console=ttyS1,115200n8 root=/dev/null rootflags=physaddr=0x50000000
++ mem=240M rootfstype=axfs ip=on"
++
++kernel mounts AXFS prior to NFS on KZM-A9.
++
++4.4. XIP of AXFS
++----------------
++
++4.4.1. XIP of AXFS
++------------------
++
++XIP image can be created by specifying CSV file which contains the XIP
++information by "-i infile" option when creating AXFS image by
++mkfs.axfs tool.
++
++CSV file contains the following XIP information: file name to be XIP,
++size in page(4KB) unit and offset(page alignment) to be XIP in the
++file.
++
++In case of specifying the file size which is aligned by 4KB to size,
++the whole file becomes XIP.
++
++Whether to make the file in AXFS image compressed or XIP can be
++decided by profiling utility of AXFS.
++
++4.5. Profile utility of AXFS
++----------------------------
++
++Profile utility can be used if kernel option "Profiling extensions for
++AXFS" is set.
++
++With this option set, when AXFS image is mounted, /proc/ interface for
++profile will be created for each mounted image under /proc/axfs/.
++(e.g.: /proc/axfs/volume0)
++
++When Non-XIP program or library in AXFS image is executed, the
++information of executable pages which are paged in and out of RAM are
++recorded to profile.
++
++4.5.1. Acquiring profile data
++-----------------------------
++
++Data of this profile can be obtained by the following command.
++
++ $ cat /proc/axfs/volume0 > /tmp/axfs-xip.profile
++
++4.5.2. Converting profile data
++------------------------------
++
++Profile data of AXFS in CSV file format can be used by mkfs.axfs tool.
++
++
++5. Known problems
++=================
++
++ - 32 bit device file is not supported
++
++ A part of file system from Linux 2.6 supports 32 bit device file.
++ By using this, the value more than 255 can be set for major number
++ and minor number of device file.
++
++ AXFS supports only 16 bit device file.
++
++ - Sequence of mounting and unmounting several AXFS images
++
++ When AXFS profile option is set and several AXFS images are
++ mounted, error message will be outputted and profile of
++ /proc/axfs/ will not be deleted correctly unless unmounting is
++ done in the opposite sequence to the one of mounting.
++
++ e.g.:
++ When the following operation is done,
++
++ mount image 1 -> mount image 2 -> umount image 1 -> umount image 2
++
++ the following error message is outputted.
++
++ "axfs: Error removing proc file private data was NULL."
++
++ In this case, operate in the following sequence.
++
++ mount image 1 -> mount image 2 -> umount image 2 -> umount image 1
++
++
++6. Hints on using AXFS
++======================
++
++ - When using sytem RAM instead of NOR flash for loading and mounting
++ AXFS image, it should be made sure that the location where AXFS image
++ is being loaded is not used by any other component in the system.
++ For e.g. Just after the regular system RAM ('System RAM' from /proc/iomem)
++ there may be a memory which is reserved/isolated by dirvers using
++ memblock_remove().
++
diff --git a/patches.axfs/axfs-axfs.h.patch b/patches.axfs/axfs-axfs.h.patch
new file mode 100644
index 00000000000000..8795fe7a5b887d
--- /dev/null
+++ b/patches.axfs/axfs-axfs.h.patch
@@ -0,0 +1,120 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:32:57 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:57:13 +0530
+Subject: [PATCH v2 RESEND 02/15] AXFS: axfs.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5D91.3080207@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS header.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 96 insertions(+)
+ create mode 100644 fs/axfs/axfs.h
+
+--- /dev/null
++++ b/fs/axfs/axfs.h
+@@ -0,0 +1,96 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_H
++#define AXFS_H
++
++#include <linux/axfs_fs.h>
++#include <linux/axfs_fs_sb.h>
++
++#include <linux/pagemap.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++
++/* axfs_inode.c */
++struct inode *axfs_create_vfs_inode(struct super_block *, int);
++u64 axfs_get_mode(struct axfs_super *sbi, u64 index);
++u64 axfs_get_uid(struct axfs_super *sbi, u64 index);
++u64 axfs_get_gid(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index);
++u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index);
++char *axfs_get_inode_name(struct axfs_super *sbi, u64 index);
++
++/* axfs_super.c */
++u64 axfs_get_io_dev_size(struct super_block *sb);
++int axfs_fill_super(struct super_block *sb, void *data, int silent);
++
++struct dentry *axfs_get_sb(struct file_system_type *,
++ int, const char *, void *);
++int axfs_physaddr_is_valid(struct axfs_super *sbi);
++int axfs_virtaddr_is_valid(struct axfs_super *sbi);
++int axfs_is_iomem(struct axfs_super *sbi);
++int axfs_is_pointed(struct axfs_super *sbi);
++int axfs_can_xip(struct axfs_super *sbi);
++int axfs_is_physmem(struct axfs_super *sbi);
++int axfs_nodev(struct super_block *sb);
++u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset);
++extern void kfree(const void *objp);
++
++/* axfs_profiling.c */
++void axfs_profiling_add(struct axfs_super *, unsigned long, unsigned int);
++int axfs_init_profiling(struct axfs_super *);
++int axfs_shutdown_profiling(struct axfs_super *);
++
++/* axfs_mtd.c */
++int axfs_copy_mtd(struct super_block *, void *, u64, u64);
++struct dentry *axfs_get_sb_mtd(struct file_system_type *, int ,
++ const char *, struct axfs_super *);
++
++void axfs_kill_mtd_super(struct super_block *);
++int axfs_is_dev_mtd(char *, int *);
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err);
++int axfs_map_mtd(struct super_block *);
++void axfs_unmap_mtd(struct super_block *);
++struct mtd_info *axfs_mtd(struct super_block *sb);
++struct mtd_info *axfs_mtd0(struct super_block *sb);
++struct mtd_info *axfs_mtd1(struct super_block *sb);
++int axfs_has_mtd(struct super_block *sb);
++
++/* axfs_bdev.c */
++void axfs_copy_block(struct super_block *, void *, u64, u64);
++struct dentry *axfs_get_sb_bdev(struct file_system_type *, int,
++ const char *, struct axfs_super *);
++void axfs_kill_block_super(struct super_block *);
++int axfs_is_dev_bdev(char *);
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err);
++struct block_device *axfs_bdev(struct super_block *sb);
++int axfs_has_bdev(struct super_block *sb);
++
++/* axfs_uml.c */
++int axfs_get_uml_address(char *, unsigned long *, unsigned long *);
++
++#ifndef NO_PHYSMEM
++/* axfs_physmem.c */
++void axfs_map_physmem(struct axfs_super *, unsigned long);
++void axfs_unmap_physmem(struct super_block *);
++#endif
++
++#endif
diff --git a/patches.axfs/axfs-axfs_bdev.c.patch b/patches.axfs/axfs-axfs_bdev.c.patch
new file mode 100644
index 00000000000000..f77bc4b4ab0263
--- /dev/null
+++ b/patches.axfs/axfs-axfs_bdev.c.patch
@@ -0,0 +1,195 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:49:36 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:13:54 +0530
+Subject: [PATCH v2 RESEND 12/15] AXFS: axfs_bdev.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF617A.9000300@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use block devices or has dummy functions if block
+device support is compiled out of the kernel.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_bdev.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 170 insertions(+)
+ create mode 100644 fs/axfs/axfs_bdev.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_bdev.c
+@@ -0,0 +1,170 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_bdev.c -
++ * Allows axfs to use block devices or has dummy functions if block
++ * device support is compiled out of the kernel.
++ *
++ */
++#include "axfs.h"
++
++#include <linux/mount.h>
++#ifdef CONFIG_BLOCK
++#include <linux/buffer_head.h>
++#include <linux/namei.h>
++
++struct block_device *axfs_bdev(struct super_block *sb)
++{
++ return sb->s_bdev;
++}
++
++int axfs_has_bdev(struct super_block *sb)
++{
++ if (axfs_bdev(sb) == NULL)
++ return false;
++
++ return true;
++}
++
++struct dentry *axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
++ const char *dev_name, struct axfs_super *sbi)
++{
++ return mount_bdev(fs_type, flags, dev_name, sbi, axfs_fill_super);
++}
++
++void axfs_kill_block_super(struct super_block *sb)
++{
++ kill_block_super(sb);
++}
++
++void axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
++ u64 len)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 boffset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
++ u64 blksize = sb->s_blocksize;
++ unsigned long dst;
++ unsigned long src;
++ sector_t block;
++ size_t bytes;
++ struct buffer_head *bh;
++ u64 copied = 0;
++
++ if (len == 0)
++ return;
++
++ while (copied < len) {
++ /* Explicit casting for ARM linker errors. */
++ block = (sector_t) boffset + (sector_t) copied;
++ block = div64_u64(block, (sector_t) blksize);
++ bh = sb_bread(sb, block);
++ src = (unsigned long)bh->b_data;
++ dst = (unsigned long)dst_addr;
++ if (copied == 0) {
++ /* Explicit casting for ARM linker errors. */
++ bytes = (size_t) blksize;
++ bytes -= (size_t) boffset % (size_t) blksize;
++ if (bytes > len)
++ bytes = len;
++ /* Explicit casting for ARM linker errors. */
++ src += (unsigned long)boffset % (unsigned long)blksize;
++ } else {
++ dst += copied;
++ if ((len - copied) < blksize)
++ bytes = len - copied;
++ else
++ bytes = blksize;
++ }
++ memcpy((void *)dst, (void *)src, bytes);
++ copied += bytes;
++ brelse(bh);
++ }
++}
++
++int axfs_is_dev_bdev(char *path)
++{
++ struct nameidata nd;
++ int ret = false;
++
++ if (!path)
++ return false;
++ nd.flags |= LOOKUP_FOLLOW;
++ if (kern_path_parent(path, &nd))
++ return false;
++
++ if (S_ISBLK(nd.path.dentry->d_inode->i_mode))
++ ret = true;
++
++ path_put(&nd.path);
++ return ret;
++}
++
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
++{
++ u64 io_dev_size;
++ loff_t bdev_size;
++
++ *err = 0;
++
++ if (!axfs_has_bdev(sb))
++ return false;
++
++ io_dev_size = axfs_get_io_dev_size(sb);
++
++ if (!io_dev_size)
++ return false;
++
++ bdev_size = i_size_read(axfs_bdev(sb)->bd_inode);
++ if (io_dev_size <= bdev_size)
++ return true;
++
++ printk(KERN_ERR "axfs: image (%lluB) doesn't fit in blkdev(%lluB)\n",
++ io_dev_size, bdev_size);
++ *err = -EIO;
++ return true;
++}
++
++#else
++
++int axfs_get_sb_bdev(struct file_system_type *fs_type, int flags,
++ const char *dev_name, struct axfs_super *sbi,
++ struct vfsmount *mnt, int *err)
++{
++ return false;
++}
++
++void axfs_kill_block_super(struct super_block *sb)
++{
++}
++
++int axfs_copy_block(struct super_block *sb, void *dst_addr, u64 fsoffset,
++ u64 len)
++{
++ return -EINVAL;
++}
++
++int axfs_is_dev_bdev(char *path)
++{
++ return false;
++}
++
++int axfs_verify_bdev_sizes(struct super_block *sb, int *err)
++{
++ *err = 0;
++ return true;
++}
++
++#endif /* CONFIG_BLOCK */
diff --git a/patches.axfs/axfs-axfs_fs.h.patch b/patches.axfs/axfs-axfs_fs.h.patch
new file mode 100644
index 00000000000000..1debd34fe11e34
--- /dev/null
+++ b/patches.axfs/axfs-axfs_fs.h.patch
@@ -0,0 +1,147 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:34:37 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:58:55 +0530
+Subject: [PATCH v2 RESEND 03/15] AXFS: axfs_fs.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5DF7.1040709@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS on media superblock declaration.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ include/linux/axfs_fs.h | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 124 insertions(+)
+ create mode 100644 include/linux/axfs_fs.h
+
+--- /dev/null
++++ b/include/linux/axfs_fs.h
+@@ -0,0 +1,124 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_FS_H
++#define AXFS_FS_H
++
++#include <linux/axfs_fs_sb.h>
++
++#ifdef __KERNEL__
++#include <linux/rwsem.h>
++#endif
++#include <linux/errno.h>
++#include <linux/time.h>
++
++#include <linux/pagemap.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++
++#define AXFS_MAGIC 0x48A0E4CD /* some random number */
++#define AXFS_SIGNATURE "Advanced XIP FS"
++#define AXFS_MAXPATHLEN 255
++
++
++/* Uncompression interfaces to the underlying zlib */
++int axfs_uncompress_block(void *, int, void *, int);
++int axfs_uncompress_init(void);
++int axfs_uncompress_exit(void);
++
++struct axfs_profiling_data {
++ u64 inode_number;
++ unsigned long count;
++};
++
++enum axfs_node_types {
++ XIP = 0,
++ Compressed,
++ Byte_Aligned,
++};
++
++enum axfs_compression_types {
++ ZLIB = 0
++};
++
++/* on media struct describing a data region */
++struct axfs_region_desc_onmedia {
++ u64 fsoffset;
++ u64 size;
++ u64 compressed_size;
++ u64 max_index;
++ u8 table_byte_depth;
++ u8 incore;
++};
++
++/* on media format for the super block */
++struct axfs_super_onmedia {
++ __be32 magic; /* 0x48A0E4CD - random number */
++ u8 signature[16]; /* "Advanced XIP FS" */
++ u8 digest[40]; /* sha1 digest for checking data integrity */
++ __be32 cblock_size; /* maximum size of the block being compressed */
++ __be64 files; /* number of inodes/files in fs */
++ __be64 size; /* total image size */
++ __be64 blocks; /* number of nodes in fs */
++ __be64 mmap_size; /* size of the memory mapped part of image */
++ __be64 strings; /* offset to strings region descriptor */
++ __be64 xip; /* offset to xip region descriptor */
++ __be64 byte_aligned; /* offset to the byte aligned region desc */
++ __be64 compressed; /* offset to the compressed region desc */
++ __be64 node_type; /* offset to node type region desc */
++ __be64 node_index; /* offset to node index region desc */
++ __be64 cnode_offset; /* offset to cnode offset region desc */
++ __be64 cnode_index; /* offset to cnode index region desc */
++ __be64 banode_offset; /* offset to banode offset region desc */
++ __be64 cblock_offset; /* offset to cblock offset region desc */
++ __be64 inode_file_size; /* offset to inode file size desc */
++ __be64 inode_name_offset;/* offset to inode num_entries region desc */
++ __be64 inode_num_entries;/* offset to inode num_entries region desc */
++ __be64 inode_mode_index;/* offset to inode mode index region desc */
++ __be64 inode_array_index;/* offset to inode node index region desc */
++ __be64 modes; /* offset to mode mode region desc */
++ __be64 uids; /* offset to mode uid index region desc */
++ __be64 gids; /* offset to mode gid index region desc */
++ u8 version_major;
++ u8 version_minor;
++ u8 version_sub;
++ u8 compression_type; /* Identifies type of compression used on FS */
++ __be64 timestamp; /* UNIX time_t of filesystem build time */
++ u8 page_shift;
++};
++
++#define AXFS_SB(sb) ((struct axfs_super *)((sb)->s_fs_info))
++
++static inline u64 axfs_bytetable_stitch(u8 depth, u8 *table, u64 index)
++{
++ u64 i;
++ u64 output = 0;
++ u64 byte = 0;
++ u64 j;
++ u64 bits;
++
++ for (i = 0; i < depth; i++) {
++ j = index * depth + i;
++ bits = 8 * (depth - i - 1);
++ byte = table[j];
++ output += byte << bits;
++ }
++ return output;
++}
++#endif
diff --git a/patches.axfs/axfs-axfs_fs_sb.h.patch b/patches.axfs/axfs-axfs_fs_sb.h.patch
new file mode 100644
index 00000000000000..719a7ff2fccfc5
--- /dev/null
+++ b/patches.axfs/axfs-axfs_fs_sb.h.patch
@@ -0,0 +1,110 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:37:53 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:02:11 +0530
+Subject: [PATCH v2 RESEND 04/15] AXFS: axfs_fs_sb.h
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5EBB.7080202@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The AXFS superblock declaration.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ include/linux/axfs_fs_sb.h | 87 +++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 87 insertions(+)
+ create mode 100644 include/linux/axfs_fs_sb.h
+
+--- /dev/null
++++ b/include/linux/axfs_fs_sb.h
+@@ -0,0 +1,87 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ */
++
++#ifndef AXFS_FS_SB_H
++#define AXFS_FS_SB_H
++
++#ifdef __KERNEL__
++#include <linux/rwsem.h>
++#endif
++#include <linux/errno.h>
++#include <linux/time.h>
++
++/* in memory region descriptor */
++struct axfs_region_desc {
++ u64 fsoffset;
++ u64 size;
++ u64 compressed_size;
++ u64 max_index;
++ void *virt_addr;
++ u8 table_byte_depth;
++ u8 incore;
++};
++
++/* axfs super-block data in memory */
++struct axfs_super {
++ u32 magic;
++ u8 version_major;
++ u8 version_minor;
++ u8 version_sub;
++ u8 padding;
++ u64 files;
++ u64 size;
++ u64 blocks;
++ u64 mmap_size;
++ struct axfs_region_desc strings;
++ struct axfs_region_desc xip;
++ struct axfs_region_desc compressed;
++ struct axfs_region_desc byte_aligned;
++ struct axfs_region_desc node_type;
++ struct axfs_region_desc node_index;
++ struct axfs_region_desc cnode_offset;
++ struct axfs_region_desc cnode_index;
++ struct axfs_region_desc banode_offset;
++ struct axfs_region_desc cblock_offset;
++ struct axfs_region_desc inode_file_size;
++ struct axfs_region_desc inode_name_offset;
++ struct axfs_region_desc inode_num_entries;
++ struct axfs_region_desc inode_mode_index;
++ struct axfs_region_desc inode_array_index;
++ struct axfs_region_desc modes;
++ struct axfs_region_desc uids;
++ struct axfs_region_desc gids;
++ unsigned long phys_start_addr;
++ unsigned long virt_start_addr;
++ char *second_dev;
++ unsigned long iomem_size;
++ void *mtd0; /* primary device */
++ void *mtd1; /* secondary device */
++ u32 cblock_size;
++ u64 current_cnode_index;
++ void *cblock_buffer[2];
++ struct rw_semaphore lock;
++ struct axfs_profiling_data *profile_data_ptr;
++ u8 profiling_on; /* Determines if profiling is on or off */
++ u8 mtd_pointed;
++ u8 compression_type;
++ struct timespec timestamp;
++ u8 page_shift;
++};
++
++#endif
diff --git a/patches.axfs/axfs-axfs_inode.c.patch b/patches.axfs/axfs-axfs_inode.c.patch
new file mode 100644
index 00000000000000..18c73ad6956508
--- /dev/null
+++ b/patches.axfs/axfs-axfs_inode.c.patch
@@ -0,0 +1,660 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:39:18 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:03:35 +0530
+Subject: [PATCH v2 RESEND 05/15] AXFS: axfs_inode.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5F0F.8010403@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Contains the most of the filesystem logic with the major exception
+of the mounting infrastructure.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_inode.c | 636 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 636 insertions(+)
+ create mode 100644 fs/axfs/axfs_inode.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_inode.c
+@@ -0,0 +1,636 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2009, 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * Borrowed heavily from fs/cramfs/inode.c by Linus Torvalds
++ *
++ * axfs_inode.c -
++ * Contains the most of the filesystem logic with the major exception of the
++ * mounting infrastructure.
++ *
++ */
++#include "axfs.h"
++
++
++static const struct file_operations axfs_directory_operations;
++static const struct file_operations axfs_fops;
++static const struct address_space_operations axfs_aops;
++static struct inode_operations axfs_dir_inode_operations;
++static struct vm_operations_struct axfs_vm_ops;
++
++static inline u64 axfs_get_node_type(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->node_type.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->node_type.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_node_index(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->node_index.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->node_index.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_is_node_xip(struct axfs_super *sbi, u64 index)
++{
++ if (axfs_get_node_type(sbi, index) == XIP)
++ return true;
++
++ return false;
++}
++
++static inline u64 axfs_get_cnode_index(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->cnode_index.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->cnode_index.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_cnode_offset(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->cnode_offset.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->cnode_offset.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_banode_offset(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->banode_offset.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->banode_offset.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_cblock_offset(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->cblock_offset.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->cblock_offset.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++static inline u64 axfs_get_inode_file_size(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->inode_file_size.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->inode_file_size.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_mode(struct axfs_super *sbi, u64 index)
++{
++ u64 mode = axfs_get_inode_mode_index(sbi, index);
++ u64 depth = sbi->modes.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->modes.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_uid(struct axfs_super *sbi, u64 index)
++{
++ u64 mode = axfs_get_inode_mode_index(sbi, index);
++ u64 depth = sbi->uids.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->uids.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_gid(struct axfs_super *sbi, u64 index)
++{
++ u64 mode = axfs_get_inode_mode_index(sbi, index);
++ u64 depth = sbi->gids.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->gids.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, mode);
++}
++
++u64 axfs_get_inode_name_offset(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->inode_name_offset.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->inode_name_offset.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_num_entries(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->inode_num_entries.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->inode_num_entries.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_mode_index(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->inode_mode_index.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->inode_mode_index.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++u64 axfs_get_inode_array_index(struct axfs_super *sbi, u64 index)
++{
++ u64 depth = sbi->inode_array_index.table_byte_depth;
++ u8 *vaddr = (u8 *) sbi->inode_array_index.virt_addr;
++
++ return axfs_bytetable_stitch(depth, vaddr, index);
++}
++
++char *axfs_get_inode_name(struct axfs_super *sbi, u64 index)
++{
++ u64 ofs = axfs_get_inode_name_offset(sbi, index);
++ u8 *virt = sbi->strings.virt_addr;
++
++ return (char *)(ofs + virt);
++}
++
++static inline u64 axfs_get_xip_region_physaddr(struct axfs_super *sbi)
++{
++ return sbi->phys_start_addr + sbi->xip.fsoffset;
++}
++
++static inline int axfs_region_is_vmalloc(struct axfs_super *sbi,
++ struct axfs_region_desc *region)
++{
++ u64 va = (u32) region->virt_addr;
++ u64 vo = (u64) region->fsoffset + (u64) sbi->virt_start_addr;
++
++ if (va == 0)
++ return false;
++
++ if (vo != va)
++ return true;
++
++ return false;
++}
++
++static int axfs_copy_data(struct super_block *sb, void *dst,
++ struct axfs_region_desc *region, u64 offset, u64 len)
++{
++ u64 mmapped = 0;
++ u64 end = region->fsoffset + offset + len;
++ u64 begin = region->fsoffset + offset;
++ u64 left;
++ void *addr;
++ void *newdst;
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ if (len == 0)
++ return 0;
++
++ if (axfs_region_is_vmalloc(sbi, region)) {
++ mmapped = len;
++ } else if (region->virt_addr) {
++ if (sbi->mmap_size >= end)
++ mmapped = len;
++ else if (sbi->mmap_size > begin)
++ mmapped = sbi->mmap_size - begin;
++ }
++
++ if (mmapped) {
++ addr = (void *)(region->virt_addr + offset);
++ memcpy(dst, addr, mmapped);
++ }
++
++ newdst = (void *)(dst + mmapped);
++ left = len - mmapped;
++
++ if (left == 0)
++ return len;
++
++ if (axfs_has_bdev(sb))
++ axfs_copy_block(sb, newdst, begin + mmapped, left);
++ else if (axfs_has_mtd(sb))
++ return axfs_copy_mtd(sb, newdst, begin + mmapped, left);
++
++ return 0;
++}
++
++static int axfs_iget5_test(struct inode *inode, void *opaque)
++{
++ u64 *inode_number = (u64 *) opaque;
++
++ if (inode->i_sb == NULL) {
++ printk(KERN_ERR "axfs_iget5_test:"
++ " the super block is set to null\n");
++ }
++ if (inode->i_ino == *inode_number)
++ return 1; /* matches */
++ else
++ return 0; /* does not match */
++}
++
++static int axfs_iget5_set(struct inode *inode, void *opaque)
++{
++ u64 *inode_number = (u64 *) opaque;
++
++ if (inode->i_sb == NULL) {
++ printk(KERN_ERR "axfs_iget5_set:"
++ " the super block is set to null\n");
++ }
++ inode->i_ino = *inode_number;
++ return 0;
++}
++
++struct inode *axfs_create_vfs_inode(struct super_block *sb, int ino)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct inode *inode;
++ u64 size;
++
++ inode = iget5_locked(sb, ino, axfs_iget5_test, axfs_iget5_set, &ino);
++
++ if (!(inode && (inode->i_state & I_NEW)))
++ return inode;
++
++ inode->i_mode = axfs_get_mode(sbi, ino);
++ inode->i_uid = axfs_get_uid(sbi, ino);
++ size = axfs_get_inode_file_size(sbi, ino);
++ inode->i_size = size;
++ inode->i_blocks = axfs_get_inode_num_entries(sbi, ino);
++ inode->i_blkbits = PAGE_CACHE_SHIFT;
++ inode->i_gid = axfs_get_gid(sbi, ino);
++
++ inode->i_mtime = inode->i_atime = inode->i_ctime = sbi->timestamp;
++ inode->i_ino = ino;
++
++ if (S_ISREG(inode->i_mode)) {
++ inode->i_fop = &axfs_fops;
++ inode->i_data.a_ops = &axfs_aops;
++ inode->i_mapping->a_ops = &axfs_aops;
++ } else if (S_ISDIR(inode->i_mode)) {
++ inode->i_op = &axfs_dir_inode_operations;
++ inode->i_fop = &axfs_directory_operations;
++ } else if (S_ISLNK(inode->i_mode)) {
++ inode->i_op = &page_symlink_inode_operations;
++ inode->i_data.a_ops = &axfs_aops;
++ } else {
++ inode->i_size = 0;
++ inode->i_blocks = 0;
++ init_special_inode(inode, inode->i_mode, old_decode_dev(size));
++ }
++ unlock_new_inode(inode);
++
++ return inode;
++}
++
++static int axfs_get_xip_mem(struct address_space *mapping, pgoff_t offset,
++ int create, void **kaddr, unsigned long *pfn)
++{
++ struct inode *inode = mapping->host;
++ struct super_block *sb = inode->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 ino_number = inode->i_ino;
++ u64 ino_index, node_index;
++
++ ino_index = axfs_get_inode_array_index(sbi, ino_number);
++ ino_index += offset;
++
++ node_index = axfs_get_node_index(sbi, ino_index);
++
++ *kaddr = (void *)(sbi->xip.virt_addr + (node_index << PAGE_SHIFT));
++
++ if (axfs_region_is_vmalloc(sbi, &(sbi->xip))) {
++ *pfn = vmalloc_to_pfn(*kaddr);
++ } else if (axfs_physaddr_is_valid(sbi)) {
++ *pfn = (axfs_get_xip_region_physaddr(sbi) >> PAGE_SHIFT);
++ *pfn += node_index;
++ } else {
++ *pfn = page_to_pfn(virt_to_page(*kaddr));
++ }
++
++ return 0;
++}
++
++static int axfs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++
++ file_accessed(file);
++
++ vma->vm_ops = &axfs_vm_ops;
++
++#ifdef VM_MIXEDMAP
++#ifdef VM_CAN_NONLINEAR
++ vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP;
++#else
++ vma->vm_flags |= VM_IO | VM_MIXEDMAP;
++#endif
++#else
++#ifdef VM_PFNMAP
++ vma->vm_flags |= VM_IO | VM_PFNMAP;
++#else
++ vma->vm_flags |= VM_IO;
++#endif
++#endif
++#ifdef VM_XIP
++ vma->vm_flags |= VM_XIP;
++#endif
++
++ return 0;
++}
++
++/* The loop does a handful of things:
++ * - First we see if they're the same length, if not we don't care.
++ * - Then, we do a strncmp on two same-length strings:
++ * > -1 -> If the entry was in this directory, it would have been
++ * right before this one.
++ * > 1 -> It's somewhere farther along in this directory.
++ */
++static struct dentry *axfs_lookup(struct inode *dir, struct dentry *dentry,
++ struct nameidata *nd)
++{
++ struct super_block *sb = dir->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 ino_number = dir->i_ino;
++ u64 dir_index = 0;
++ u64 entry;
++ char *name;
++ int namelen, err;
++
++ while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
++ entry = axfs_get_inode_array_index(sbi, ino_number);
++ entry += dir_index;
++
++ name = axfs_get_inode_name(sbi, entry);
++ namelen = strlen(name);
++
++ dir_index++;
++
++ if (dentry->d_name.len != namelen)
++ continue;
++
++ err = strncmp(dentry->d_name.name, name, namelen);
++
++ if (err < 0)
++ break;
++
++ if (err > 0)
++ continue;
++
++ d_add(dentry, axfs_create_vfs_inode(dir->i_sb, entry));
++ goto out;
++
++ }
++ d_add(dentry, NULL);
++
++out:
++ return NULL;
++}
++
++static int axfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
++{
++ struct inode *inode = filp->f_dentry->d_inode;
++ struct super_block *sb = inode->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 ino_number = inode->i_ino;
++ u64 entry;
++ loff_t dir_index;
++ char *name;
++ int namelen, mode;
++ int err = 0;
++
++ /*
++ * Get the current index into the directory and verify it is not beyond
++ * the end of the list
++ */
++ dir_index = filp->f_pos;
++ if (dir_index >= axfs_get_inode_num_entries(sbi, ino_number))
++ goto out;
++
++ while (dir_index < axfs_get_inode_num_entries(sbi, ino_number)) {
++ entry = axfs_get_inode_array_index(sbi, ino_number) + dir_index;
++
++ name = axfs_get_inode_name(sbi, entry);
++ namelen = strlen(name);
++
++ mode = (int)axfs_get_mode(sbi, entry);
++ err = filldir(dirent, name, namelen, dir_index, entry, mode);
++
++ if (err)
++ break;
++
++ dir_index++;
++ filp->f_pos = dir_index;
++ }
++
++out:
++ return 0;
++}
++
++/******************************************************************************
++ *
++ * axfs_fault
++ *
++ * Description: This function is mapped into the VMA operations vector, and
++ * gets called on a page fault. Depending on whether the page
++ * is XIP or compressed, xip_file_fault or filemap_fault is
++ * called. This function also logs when a fault occurs when
++ * profiling is on.
++ *
++ * Parameters:
++ * (IN) vma - The virtual memory area corresponding to a file
++ *
++ * (IN) vmf - The fault info pass in by the fault handler
++ *
++ * Returns:
++ * 0 or error number
++ *
++ *****************************************************************************/
++static int axfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ struct file *file = vma->vm_file;
++ struct inode *inode = file->f_dentry->d_inode;
++ struct super_block *sb = inode->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 ino_number = inode->i_ino;
++ u64 array_index;
++
++ array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
++
++ /*
++ * if that pages are marked for write they will probably end up in RAM
++ * therefore we don't want their counts for being XIP'd
++ */
++ if (!(vma->vm_flags & VM_WRITE))
++ axfs_profiling_add(sbi, array_index, ino_number);
++
++ /*
++ * figure out if the node is XIP or compressed and call the
++ * appropriate function
++ */
++ if (axfs_is_node_xip(sbi, array_index))
++ return xip_file_fault(vma, vmf);
++ return filemap_fault(vma, vmf);
++}
++
++/******************************************************************************
++ *
++ * axfs_file_read
++ *
++ * Description: axfs_file_read is mapped into the file_operations vector for
++ * all axfs files. It loops through the pages to be read and calls
++ * either do_sync_read (if the page is a compressed one) or
++ * xip_file_read (if the page is XIP).
++ *
++ * Parameters:
++ * (IN) filp - file to be read
++ *
++ * (OUT) buf - user buffer that is filled with the data that we read.
++ *
++ * (IN) len - length of file to be read
++ *
++ * (IN) ppos - offset within the file to read from
++ *
++ * Returns:
++ * actual size of data read.
++ *
++ *****************************************************************************/
++static ssize_t axfs_file_read(struct file *filp, char __user *buf, size_t len,
++ loff_t *ppos)
++{
++ struct inode *inode = filp->f_dentry->d_inode;
++ struct super_block *sb = inode->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ size_t read = 0, total_read = 0;
++ size_t readlength, actual_size, file_size, remaining;
++ u64 ino_number = inode->i_ino;
++ u64 size, array_index;
++
++ file_size = axfs_get_inode_file_size(sbi, ino_number);
++ remaining = file_size - *ppos;
++ actual_size = len > remaining ? remaining : len;
++ readlength = actual_size < PAGE_SIZE ? actual_size : PAGE_SIZE;
++
++ for (size = actual_size; size > 0; size -= read) {
++ array_index = axfs_get_inode_array_index(sbi, ino_number);
++ array_index += *ppos >> PAGE_SHIFT;
++
++ if (axfs_is_node_xip(sbi, array_index))
++ read = xip_file_read(filp, buf, readlength, ppos);
++ else
++ read = do_sync_read(filp, buf, readlength, ppos);
++
++ buf += read;
++ total_read += read;
++
++ if ((len - total_read < PAGE_SIZE) && (total_read != len))
++ readlength = len - total_read;
++ }
++
++ return total_read;
++}
++
++static int axfs_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct super_block *sb = inode->i_sb;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 array_index, node_index, cnode_index, maxblock, ofs;
++ u64 ino_number = inode->i_ino;
++ u32 max_len, cnode_offset;
++ u32 cblk_size = sbi->cblock_size;
++ u32 len = 0;
++ u8 node_type;
++ void *pgdata;
++ void *src;
++ void *cblk0 = sbi->cblock_buffer[0];
++ void *cblk1 = sbi->cblock_buffer[1];
++
++ maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++ pgdata = kmap(page);
++
++ if (page->index >= maxblock)
++ goto out;
++
++ array_index = axfs_get_inode_array_index(sbi, ino_number);
++ array_index += page->index;
++
++ node_index = axfs_get_node_index(sbi, array_index);
++ node_type = axfs_get_node_type(sbi, array_index);
++
++ if (node_type == Compressed) {
++ /* node is in compessed region */
++ cnode_offset = axfs_get_cnode_offset(sbi, node_index);
++ cnode_index = axfs_get_cnode_index(sbi, node_index);
++ down_write(&sbi->lock);
++ if (cnode_index != sbi->current_cnode_index) {
++ /* uncompress only necessary if different cblock */
++ ofs = axfs_get_cblock_offset(sbi, cnode_index);
++ len = axfs_get_cblock_offset(sbi, cnode_index + 1);
++ len -= ofs;
++ axfs_copy_data(sb, cblk1, &(sbi->compressed), ofs, len);
++ axfs_uncompress_block(cblk0, cblk_size, cblk1, len);
++ sbi->current_cnode_index = cnode_index;
++ }
++ downgrade_write(&sbi->lock);
++ max_len = cblk_size - cnode_offset;
++ len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
++ src = (void *)((unsigned long)cblk0 + cnode_offset);
++ memcpy(pgdata, src, len);
++ up_read(&sbi->lock);
++ } else if (node_type == Byte_Aligned) {
++ /* node is in BA region */
++ ofs = axfs_get_banode_offset(sbi, node_index);
++ max_len = sbi->byte_aligned.size - ofs;
++ len = max_len > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : max_len;
++ axfs_copy_data(sb, pgdata, &(sbi->byte_aligned), ofs, len);
++ } else {
++ /* node is XIP */
++ ofs = node_index << PAGE_SHIFT;
++ len = PAGE_CACHE_SIZE;
++ axfs_copy_data(sb, pgdata, &(sbi->xip), ofs, len);
++ }
++
++out:
++ memset(pgdata + len, 0, PAGE_CACHE_SIZE - len);
++ kunmap(page);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ unlock_page(page);
++ return 0;
++}
++
++static const struct file_operations axfs_directory_operations = {
++ .llseek = generic_file_llseek,
++ .read = generic_read_dir,
++ .readdir = axfs_readdir,
++};
++
++static const struct file_operations axfs_fops = {
++ .read = axfs_file_read,
++ .aio_read = generic_file_aio_read,
++ .mmap = axfs_mmap,
++};
++
++static const struct address_space_operations axfs_aops = {
++ .readpage = axfs_readpage,
++ .get_xip_mem = axfs_get_xip_mem,
++};
++
++static struct inode_operations axfs_dir_inode_operations = {
++ .lookup = axfs_lookup,
++};
++
++static struct vm_operations_struct axfs_vm_ops = {
++ .fault = axfs_fault,
++};
diff --git a/patches.axfs/axfs-axfs_mtd.c.patch b/patches.axfs/axfs-axfs_mtd.c.patch
new file mode 100644
index 00000000000000..9aaf564040fc1f
--- /dev/null
+++ b/patches.axfs/axfs-axfs_mtd.c.patch
@@ -0,0 +1,376 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:40:42 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:04:58 +0530
+Subject: [PATCH v2 RESEND 06/15] AXFS: axfs_mtd.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5F62.3030809@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use mtd devices or has dummy functions if mtd
+device support is compiled out of the kernel.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_mtd.c | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 351 insertions(+)
+ create mode 100644 fs/axfs/axfs_mtd.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_mtd.c
+@@ -0,0 +1,351 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_mtd.c -
++ * Allows axfs to use mtd devices or has dummy functions if mtd
++ * device support is compiled out of the kernel.
++ */
++#include "axfs.h"
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/ctype.h>
++#include <linux/namei.h>
++
++#ifdef CONFIG_MTD
++#define AXFS_CONFIG_MTD
++#endif
++
++#ifdef AXFS_CONFIG_MTD
++#include <linux/mtd/super.h>
++
++struct mtd_info *axfs_mtd(struct super_block *sb)
++{
++ return (void *)sb->s_mtd;
++}
++
++struct mtd_info *axfs_mtd0(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ if (sbi->mtd0 != NULL)
++ return sbi->mtd0;
++ else
++ return axfs_mtd(sb);
++}
++
++struct mtd_info *axfs_mtd1(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ return sbi->mtd1;
++}
++
++int axfs_has_mtd(struct super_block *sb)
++{
++ if (sb->s_fs_info == NULL)
++ return false;
++
++ if (axfs_mtd0(sb))
++ return true;
++
++ if (axfs_mtd1(sb))
++ return true;
++
++ if (axfs_mtd(sb))
++ return true;
++
++ return false;
++}
++
++struct mtd_info *axfs_get_mtd_device(int mtdnr)
++{
++ struct mtd_info *device;
++
++ device = get_mtd_device(NULL, mtdnr);
++
++ if (!PTR_ERR(device))
++ return NULL;
++
++ return device;
++}
++
++int axfs_is_dev_mtd(char *path, int *mtdnr)
++{
++ char *off = NULL;
++ char *endptr = NULL;
++ char dev[] = "/dev/\0";
++ char mtd[] = "mtd\0";
++ char mtdblk[] = "mtdblock\0";
++
++ if (!path || !*path)
++ return false;
++
++ off = path;
++
++ if (strncmp(dev, off, strlen(dev)) == 0)
++ off += strlen(dev);
++
++ if (!strncmp(mtd, off, strlen(mtd)) && isdigit(off[strlen(mtd)]))
++ off += strlen(mtd);
++
++ if (!strncmp(mtdblk, off, strlen(mtdblk))
++ && isdigit(off[strlen(mtdblk)]))
++ off += strlen(mtdblk);
++
++ *mtdnr = simple_strtoul(off, &endptr, 0);
++
++ if (!*endptr)
++ return true;
++
++ return false;
++}
++
++static struct mtd_info *axfs_get_mtd_info(struct super_block *sb, u64 fsoffset)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ if (fsoffset == 0)
++ return (struct mtd_info *)axfs_mtd0(sb);
++
++ if (fsoffset < sbi->mmap_size)
++ return (struct mtd_info *)axfs_mtd0(sb);
++
++ if (axfs_mtd1(sb) != NULL)
++ return (struct mtd_info *)axfs_mtd1(sb);
++
++ return (struct mtd_info *)axfs_mtd0(sb);
++}
++
++int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 offset = axfs_fsoffset_to_devoffset(sbi, fsoffset);
++ struct mtd_info *mtd;
++ u_char *mtdbuf = (u_char *) dst;
++ size_t retlen;
++ int err = 0;
++
++ if (len == 0)
++ return 0;
++
++ mtd = axfs_get_mtd_info(sb, fsoffset);
++ err = mtd_read(mtd, (loff_t) offset, (size_t) len, &retlen, mtdbuf);
++
++ if (len != retlen)
++ return -EIO;
++
++ return err;
++}
++
++/******************************************************************************
++ *
++ * axfs_map_mtd
++ *
++ * Description: When provided, uses the mtd point() capability to map allow
++ * axfs a direct memory access to the filesystem.
++ *
++ * Parameters:
++ * (IN) sb - pointer to the super_block structure
++ *
++ * Returns:
++ * 0 or error number
++ *
++ *****************************************************************************/
++int axfs_map_mtd(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
++ size_t retlen;
++ int err = 0;
++ void *virt;
++ resource_size_t phys;
++
++ err = mtd_point(mtd, 0, sbi->mmap_size, &retlen, &virt, &phys);
++ if (err)
++ return err;
++
++ if (retlen != sbi->mmap_size) {
++ mtd_unpoint(mtd, 0, retlen);
++ return -EINVAL;
++ }
++
++ sbi->virt_start_addr = (unsigned long)virt;
++ sbi->phys_start_addr = (unsigned long)phys;
++ sbi->mtd_pointed = true;
++
++ return 0;
++}
++
++void axfs_unmap_mtd(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct mtd_info *mtd = (struct mtd_info *)axfs_mtd0(sb);
++
++ if (!sbi)
++ return;
++
++ if (axfs_mtd1(sb))
++ put_mtd_device((struct mtd_info *)axfs_mtd1(sb));
++
++ if (axfs_is_pointed(sbi)) {
++ mtd_unpoint(mtd, 0, sbi->mmap_size);
++ } else {
++ if (axfs_mtd0(sb))
++ put_mtd_device((struct mtd_info *)axfs_mtd0(sb));
++ }
++}
++
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct mtd_info *mtd0 = (struct mtd_info *)axfs_mtd0(sb);
++ struct mtd_info *mtd1 = (struct mtd_info *)axfs_mtd1(sb);
++ u64 io_dev_size;
++
++ *err = 0;
++ io_dev_size = axfs_get_io_dev_size(sb);
++
++ if (!mtd0 && !mtd1)
++ return false;
++
++ /* One mtd device entirely mmaped */
++ if (sbi->mtd_pointed && !io_dev_size) {
++ if (sbi->mmap_size != sbi->size) {
++ *err = -EINVAL;
++ return false;
++ }
++
++ return true;
++ }
++
++ if (!io_dev_size)
++ return false;
++
++ /* filesystem split across two mtd devs */
++ if (mtd1) {
++ if (io_dev_size > mtd1->size)
++ goto too_small;
++ else
++ return true;
++ }
++
++ /* One mtd device partially mmaped, partially io */
++ if (sbi->mtd_pointed) {
++ if (sbi->size > mtd0->size)
++ goto too_small;
++ else
++ return true;
++ }
++
++ /* One mtd device as a IO dev or split with physaddr */
++ if (io_dev_size > mtd0->size)
++ goto too_small;
++
++ return true;
++
++too_small:
++ printk(KERN_ERR "axfs: filesystem extends beyond end of MTD, ");
++ printk(KERN_ERR "expected 0x%llx ", io_dev_size);
++ printk(KERN_ERR "got 0x%llu\n", (mtd1) ? mtd1->size : mtd0->size);
++ *err = -EINVAL;
++ return true;
++}
++
++struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
++ const char *dev_name, struct axfs_super *sbi)
++{
++ int *err = ERR_PTR(-EINVAL);
++ int nflags, mtdnr;
++
++ if (axfs_is_dev_mtd(sbi->second_dev, &mtdnr)) {
++ sbi->mtd1 = (void *)axfs_get_mtd_device(mtdnr);
++ if (!sbi->mtd1) {
++ *err = -EINVAL;
++ return false;
++ }
++ }
++ nflags = flags & MS_SILENT;
++
++ return mount_mtd(fs_type, nflags, dev_name, sbi, axfs_fill_super);
++}
++
++void axfs_kill_mtd_super(struct super_block *sb)
++{
++ kill_mtd_super(sb);
++}
++#else
++struct mtd_info *axfs_mtd(struct super_block *sb)
++{
++ return NULL;
++}
++
++struct mtd_info *axfs_mtd0(struct super_block *sb)
++{
++ return NULL;
++}
++
++struct mtd_info *axfs_mtd1(struct super_block *sb)
++{
++ return NULL;
++}
++
++int axfs_has_mtd(struct super_block *sb)
++{
++ return false;
++}
++
++struct mtd_info *axfs_get_mtd_device(int mtdnr)
++{
++ return NULL;
++}
++
++int axfs_map_mtd(struct super_block *sb)
++{
++ return 0;
++}
++
++void axfs_unmap_mtd(struct super_block *sb)
++{
++}
++
++int axfs_copy_mtd(struct super_block *sb, void *dst, u64 fsoffset, u64 len)
++{
++ return -EINVAL;
++}
++
++struct dentry *axfs_get_sb_mtd(struct file_system_type *fs_type, int flags,
++ const char *dev_name, struct axfs_super *sbi)
++{
++ return false;
++}
++
++int axfs_is_dev_mtd(char *path, int *mtdnr)
++{
++ return false;
++}
++
++void axfs_kill_mtd_super(struct super_block *sb)
++{
++}
++
++int axfs_verify_mtd_sizes(struct super_block *sb, int *err)
++{
++ *err = 0;
++ return true;
++}
++
++#endif /* CONFIG_MTD */
diff --git a/patches.axfs/axfs-axfs_physmem.c.patch b/patches.axfs/axfs-axfs_physmem.c.patch
new file mode 100644
index 00000000000000..9a6c246b0e65d4
--- /dev/null
+++ b/patches.axfs/axfs-axfs_physmem.c.patch
@@ -0,0 +1,89 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:42:02 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:06:20 +0530
+Subject: [PATCH v2 RESEND 07/15] AXFS: axfs_physmem.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5FB4.4000102@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs to use striaght memory or has dummy functions if
+this is a UML system.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_physmem.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 65 insertions(+)
+ create mode 100644 fs/axfs/axfs_physmem.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_physmem.c
+@@ -0,0 +1,65 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_physmem.c -
++ * Allows axfs to use striaght memory or has dummy functions if
++ * this is a UML system.
++ */
++#include "axfs.h"
++
++#include <linux/fs.h>
++#ifdef CONFIG_UML
++
++void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
++{
++}
++
++void axfs_unmap_physmem(struct super_block *sb)
++{
++}
++
++#else
++#include <linux/io.h>
++
++#ifdef ioremap_cached
++#define AXFS_REMAP(a, b) (void __force *)ioremap_cached((a), (b))
++#else
++#define AXFS_REMAP(a, b) (void __force *)ioremap((a), (b))
++#endif /* ioremap_cached */
++
++void axfs_map_physmem(struct axfs_super *sbi, unsigned long size)
++{
++ void *addr;
++
++ if (axfs_is_physmem(sbi)) {
++ addr = AXFS_REMAP(sbi->phys_start_addr, size);
++ sbi->virt_start_addr = (unsigned long)addr;
++ }
++}
++
++void axfs_unmap_physmem(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ if (!sbi)
++ return;
++
++ if (axfs_is_physmem(sbi) && axfs_virtaddr_is_valid(sbi)) {
++ iounmap((void *)(sbi->virt_start_addr));
++ sbi->virt_start_addr = 0;
++ }
++}
++
++#endif /* CONFIG_UML */
diff --git a/patches.axfs/axfs-axfs_profiling.c.patch b/patches.axfs/axfs-axfs_profiling.c.patch
new file mode 100644
index 00000000000000..a3573c05f5cb53
--- /dev/null
+++ b/patches.axfs/axfs-axfs_profiling.c.patch
@@ -0,0 +1,630 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:43:37 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:07:55 +0530
+Subject: [PATCH v2 RESEND 08/15] AXFS: axfs_profiling.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6013.3080100@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Tracks pages of files that enter the page cache. Outputs through a proc
+file which generates a comma separated data file with path, page offset,
+count of times entered page cache.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_profiling.c | 605 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 605 insertions(+)
+ create mode 100644 fs/axfs/axfs_profiling.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_profiling.c
+@@ -0,0 +1,605 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * More info and current contacts at http://axfs.sourceforge.net
++ *
++ * axfs_profiling.c -
++ * Tracks pages of files that enter the page cache. Outputs through a proc
++ * file which generates a comma separated data file with path, page offset,
++ * count of times entered page cache.
++ */
++#include "axfs.h"
++
++#ifdef CONFIG_AXFS_PROFILING
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/proc_fs.h>
++
++#define AXFS_PROC_DIR_NAME "axfs"
++
++struct axfs_profiling_manager {
++ struct axfs_profiling_data *profiling_data;
++ struct axfs_super *sbi;
++ u32 *dir_structure;
++ u32 size;
++};
++
++#define MAX_STRING_LEN 1024
++
++/* Handles for our Directory and File */
++static struct proc_dir_entry *axfs_proc_dir;
++static u32 proc_name_inc;
++
++/******************************************************************************
++ *
++ * axfs_init_profile_dir_structure
++ *
++ * Description:
++ * Creates the structures for tracking the page usage data and creates the
++ * proc file that will be used to get the data.
++ *
++ * Parameters:
++ * (IN) manager - pointer to the profile manager for the filing system
++ *
++ * (IN) num_inodes - number of files in the system
++ *
++ * Returns:
++ * 0
++ *
++ *****************************************************************************/
++static int axfs_init_profile_dir_structure(struct axfs_profiling_manager
++ *manager, u32 num_inodes)
++{
++
++ struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
++ u32 child_index = 0, i, j;
++ u32 *dir_structure = manager->dir_structure;
++
++ /*
++ * loop through each inode in the image and find all
++ * of the directories and mark their children
++ */
++ for (i = 0; i < num_inodes; i++) {
++ /* determine if the entry is a directory */
++ if (!S_ISDIR(axfs_get_mode(sbi, i)))
++ continue;
++
++ /* get the index number for this directory */
++ child_index = axfs_get_inode_array_index(sbi, i);
++
++ /* get the offset to its children */
++ for (j = 0; j < axfs_get_inode_num_entries(sbi, i); j++) {
++ if (dir_structure[child_index + j] != 0) {
++ printk(KERN_ERR
++ "axfs: ERROR inode was already set old "
++ "%lu new %lu\n", (unsigned long)
++ dir_structure[child_index + j],
++ (unsigned long)i);
++ }
++ dir_structure[child_index + j] = i;
++ }
++ }
++
++ return 0;
++}
++
++/******************************************************************************
++ *
++ * axfs_get_directory_path
++ *
++ * Description:
++ * Determines the directory path of every file for printing the spreadsheet.
++ *
++ * Parameters:
++ * (IN) manager - Pointer to axfs profile manager
++ *
++ * (OUT) buffer - Pointer to the printable directory path for each file
++ *
++ * (IN) inode_number - Inode number of file to look up
++ *
++ * Returns:
++ * Size of the path to the file
++ *
++ *
++ **************************************************************************/
++static int axfs_get_directory_path(struct axfs_profiling_manager *manager,
++ char *buffer, u32 inode_number)
++{
++ u32 path_depth = 0;
++ u32 path_size = 0;
++ u32 string_len = 0;
++ u32 index = inode_number;
++ u32 dir_number;
++ u8 **path_array = NULL;
++ struct axfs_super *sbi = (struct axfs_super *)manager->sbi;
++ int i;
++
++ /*
++ * determine how deep the directory path is and how big the name
++ * string will be walk back until the root directory index is found
++ * (index 0 is root)
++ */
++ while (manager->dir_structure[index] != 0) {
++ path_depth++;
++ /* set the index to the index of the parent directory */
++ index = manager->dir_structure[index];
++ }
++
++ if (path_depth != 0) {
++ /*
++ * create an array that will hold a pointer for each of the
++ * directories names
++ */
++ path_array = vmalloc(path_depth * sizeof(*path_array));
++ if (path_array == NULL) {
++ printk(KERN_DEBUG
++ "axfs: directory_path vmalloc failed.\n");
++ goto out;
++ }
++ }
++
++ index = manager->dir_structure[inode_number];
++ for (i = path_depth; i > 0; i--) {
++ /*
++ * get the array_index for the directory corresponding to
++ * index
++ */
++ dir_number = axfs_get_inode_array_index(sbi, index);
++
++ /* store a pointer to the name in the array */
++ path_array[(i - 1)] = (u8 *) axfs_get_inode_name(sbi, index);
++
++ index = manager->dir_structure[index];
++ }
++
++ /* now print out the directory structure from the begining */
++ string_len = sprintf(buffer, "./");
++ path_size += string_len;
++ for (i = 0; i < path_depth; i++) {
++ buffer = buffer + string_len;
++ string_len = sprintf(buffer, "%s/", (char *)path_array[i]);
++ path_size += string_len;
++ }
++
++ vfree(path_array);
++
++out:
++ return path_size;
++
++}
++
++static ssize_t axfs_procfile_read(char *buffer,
++ char **buffer_location,
++ off_t offset, int buffer_length, int *eof,
++ void *data)
++{
++ struct axfs_profiling_manager *man;
++ struct axfs_profiling_data *profile;
++ struct axfs_super *sbi;
++ u64 array_index;
++ u64 loop_size, inode_page_offset, node_offset, inode_number;
++ u64 print_len = 0;
++ unsigned long addr;
++ int len = 0;
++ int i;
++ char *buff, *name = NULL;
++
++ man = (struct axfs_profiling_manager *)data;
++ sbi = man->sbi;
++
++ loop_size = man->size / sizeof(*profile);
++
++ /* If all data has been returned set EOF */
++ if (offset >= loop_size) {
++ *eof = 1;
++ return 0;
++ }
++
++ buff = buffer;
++ /* print as much as the buffer can take */
++ for (i = offset; i < loop_size; i++) {
++
++ if ((print_len + MAX_STRING_LEN) > buffer_length)
++ break;
++ /* get the first profile data structure */
++ profile = &(man->profiling_data[i]);
++
++ if (profile->count == 0)
++ continue;
++
++ inode_number = profile->inode_number;
++
++ /* file names can be duplicated so we must print out the path */
++ len = axfs_get_directory_path(man, buff, inode_number);
++
++ print_len += len;
++ buff += len;
++
++ /* get a pointer to the inode name */
++ array_index = axfs_get_inode_array_index(sbi, inode_number);
++ name = axfs_get_inode_name(sbi, inode_number);
++
++ /*
++ * need to convert the page number in the node area to
++ * the page number within the file
++ */
++ node_offset = i;
++ /*
++ * gives the offset of the node in the node list area
++ * then substract that from the
++ */
++ inode_page_offset = node_offset - array_index;
++
++ /* set everything up to print out */
++ addr = (unsigned long)(inode_page_offset * PAGE_SIZE);
++ len = sprintf(buff, "%s,%lu,%lu\n", name, addr, profile->count);
++
++ print_len += len;
++ buff += len;
++ }
++
++ /*
++ * return the number of items printed. This will be
++ * added to offset and passed back to us
++ */
++ *buffer_location = (char *)(i - offset);
++
++ return print_len;
++}
++
++static ssize_t axfs_procfile_write(struct file *file,
++ const char *buffer, unsigned long count,
++ void *data)
++{
++ struct axfs_profiling_manager *man_ptr =
++ (struct axfs_profiling_manager *)data;
++
++ if ((count >= 2) && (0 == memcmp(buffer, "on", 2))) {
++ man_ptr->sbi->profiling_on = true;
++ } else if ((count >= 3) && (0 == memcmp(buffer, "off", 3))) {
++ man_ptr->sbi->profiling_on = false;
++ } else if ((count >= 5) && (0 == memcmp(buffer, "clear", 5))) {
++ memset(man_ptr->profiling_data, 0, man_ptr->size);
++ } else {
++ printk(KERN_INFO
++ "axfs: Unknown command. Supported options are:\n");
++ printk(KERN_INFO "\t\"on\"\tTurn on profiling\n");
++ printk(KERN_INFO "\t\"off\"\tTurn off profiling\n");
++ printk(KERN_INFO "\t\"clear\"\tClear profiling buffer\n");
++ }
++
++ return count;
++}
++
++static int axfs_create_proc_directory(void)
++{
++ if (axfs_proc_dir == NULL) {
++ axfs_proc_dir = proc_mkdir(AXFS_PROC_DIR_NAME, NULL);
++ if (!axfs_proc_dir) {
++ printk(KERN_WARNING
++ "axfs: Failed to create directory\n");
++ return false;
++ }
++ }
++ return true;
++}
++
++static void axfs_delete_proc_directory(void)
++{
++ /*
++ * Determine if there are any directory elements
++ * and remove if all of the proc files are removed.
++ */
++ if (axfs_proc_dir != NULL) {
++ if (axfs_proc_dir->subdir == NULL) {
++ remove_proc_entry(AXFS_PROC_DIR_NAME, NULL);
++ axfs_proc_dir = NULL;
++ }
++ }
++}
++
++/******************************************************************************
++ *
++ * axfs_delete_proc_file
++ *
++ * Description:
++ * Will search through the proc directory for the correct proc file,
++ * then delete it
++ *
++ * Parameters:
++ * (IN) sbi- axfs superblock pointer to determine which proc file to remove
++ *
++ * Returns:
++ * The profiling manager pointer for the proc file.
++ *
++ *****************************************************************************/
++static struct axfs_profiling_manager *axfs_delete_proc_file(struct axfs_super
++ *sbi)
++{
++ struct proc_dir_entry *current_proc_file;
++ struct axfs_profiling_manager *manager;
++ void *rv = NULL;
++
++ if (!axfs_proc_dir)
++ return NULL;
++
++ /* Walk through the proc file entries to find the matching sbi */
++ current_proc_file = axfs_proc_dir->subdir;
++
++ while (current_proc_file != NULL) {
++ manager = current_proc_file->data;
++ if (manager == NULL) {
++ printk(KERN_WARNING
++ "axfs: Error removing proc file private "
++ "data was NULL.\n");
++ rv = NULL;
++ break;
++ }
++ if (manager->sbi == sbi) {
++ /* we found the match */
++ remove_proc_entry(current_proc_file->name,
++ axfs_proc_dir);
++ rv = (void *)manager;
++ break;
++ }
++ current_proc_file = axfs_proc_dir->next;
++ }
++ return (struct axfs_profiling_manager *)rv;
++}
++
++/******************************************************************************
++ *
++ * axfs_register_profiling_proc
++ *
++ * Description:
++ * Will register the instance of the proc file for a given volume.
++ *
++ * Parameters:
++ * (IN) manager - Pointer to the profiling manager for the axfs volume
++ *
++ * Returns:
++ * 0 or error number
++ *
++ *****************************************************************************/
++static int axfs_register_profiling_proc(struct axfs_profiling_manager *manager)
++{
++ int rv = 0;
++ struct proc_dir_entry *proc_file;
++ char file_name[20];
++
++ if (!axfs_create_proc_directory()) {
++ rv = -ENOMEM;
++ goto out;
++ }
++
++ sprintf(file_name, "volume%d", proc_name_inc);
++ proc_file = create_proc_entry(file_name, (mode_t) 0644, axfs_proc_dir);
++ if (proc_file == NULL) {
++ remove_proc_entry(file_name, axfs_proc_dir);
++ axfs_delete_proc_directory();
++ rv = -ENOMEM;
++ goto out;
++ }
++
++ proc_name_inc++;
++ proc_file->read_proc = axfs_procfile_read;
++ proc_file->write_proc = axfs_procfile_write;
++ proc_file->mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
++ proc_file->uid = 0;
++ proc_file->gid = 0;
++ proc_file->data = manager;
++
++ printk(KERN_DEBUG "axfs: Proc entry created\n");
++
++out:
++ return rv;
++}
++
++/******************************************************************************
++ *
++ * axfs_unregister_profiling_proc
++ *
++ * Description:
++ * Will unregister the instance of the proc file for the volume that was
++ * mounted. If this is the last volume mounted then the proc directory
++ * will also be removed.
++ *
++ * Parameters:
++ * (IN) sbi- axfs superblock pointer to determine which proc file to remove
++ *
++ * Returns:
++ * The profiling manager pointer for the proc file.
++ *
++ *****************************************************************************/
++static struct axfs_profiling_manager *axfs_unregister_profiling_proc(struct
++ axfs_super
++ *sbi)
++{
++ struct axfs_profiling_manager *manager;
++ manager = axfs_delete_proc_file(sbi);
++ axfs_delete_proc_directory();
++ return manager;
++}
++
++/******************************************************************************
++ *
++ * axfs_init_profiling
++ *
++ * Description:
++ * Creates the structures for tracking the page usage data and creates the
++ * proc file that will be used to get the data.
++ *
++ * Parameters:
++ * (IN) sbi- axfs superblock pointer
++ *
++ * Returns:
++ * true or false
++ *
++ *****************************************************************************/
++int axfs_init_profiling(struct axfs_super *sbi)
++{
++
++ u32 num_nodes, num_inodes;
++ struct axfs_profiling_manager *manager = NULL;
++ struct axfs_profiling_data *profile_data = NULL;
++ int err = -ENOMEM;
++
++ /* determine the max number of pages in the FS */
++ num_nodes = sbi->blocks;
++ if (!num_nodes)
++ return 0;
++
++ manager = vmalloc(sizeof(*manager));
++ if (!manager)
++ goto out;
++
++ profile_data = vmalloc(num_nodes * sizeof(*profile_data));
++ if (!profile_data)
++ goto out;
++
++ memset(profile_data, 0, num_nodes * sizeof(*profile_data));
++
++ /* determine the max number of inodes in the FS */
++ num_inodes = sbi->files;
++
++ manager->dir_structure = vmalloc(num_inodes * sizeof(u32 *));
++ if (!manager->dir_structure)
++ goto out;
++
++ memset(manager->dir_structure, 0, (num_inodes * sizeof(u32 *)));
++
++ manager->profiling_data = profile_data;
++ manager->size = num_nodes * sizeof(*profile_data);
++ manager->sbi = sbi;
++ sbi->profiling_on = true; /* Turn on profiling by default */
++ sbi->profile_data_ptr = profile_data;
++
++ err = axfs_init_profile_dir_structure(manager, num_inodes);
++ if (err)
++ goto out;
++
++ err = axfs_register_profiling_proc(manager);
++ if (err)
++ goto out;
++
++ return 0;
++
++out:
++ vfree(manager->dir_structure);
++ vfree(profile_data);
++ vfree(manager);
++ return err;
++}
++
++/******************************************************************************
++ *
++ * axfs_shutdown_profiling
++ *
++ * Description:
++ * Remove the proc file for this volume and release the memory in the
++ * profiling manager
++ *
++ * Parameters:
++ * (IN) sbi- axfs superblock pointer
++ *
++ * Returns:
++ * true or false
++ *
++ *****************************************************************************/
++int axfs_shutdown_profiling(struct axfs_super *sbi)
++{
++ struct axfs_profiling_manager *manager;
++ /*
++ * remove the proc file for this volume and release the memory in the
++ * profiling manager
++ */
++
++ if (!sbi)
++ return true;
++
++ if (!sbi->profile_data_ptr)
++ return true;
++
++ manager = axfs_unregister_profiling_proc(sbi);
++
++ if (manager == NULL)
++ return false;
++
++ vfree(manager->dir_structure);
++ vfree(manager->profiling_data);
++ vfree(manager);
++ return true;
++}
++
++/******************************************************************************
++ *
++ * axfs_profiling_add
++ *
++ * Description:
++ * Log when a node is paged into memory by incrementing the count in the
++ * array profile data structure.
++ *
++ * Parameters:
++ * (IN) sbi- axfs superblock pointer
++ *
++ * (IN) array_index - The offset into the nodes table of file (node number)
++ *
++ * (IN) axfs_inode_number - Inode of the node to determine file name later
++ *
++ * Returns:
++ * none
++ *
++ *****************************************************************************/
++void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
++ unsigned int axfs_inode_number)
++{
++ unsigned long addr;
++ struct axfs_profiling_data *profile_data;
++
++ if (sbi->profiling_on != true)
++ return;
++
++ addr = (unsigned long)sbi->profile_data_ptr;
++ addr += array_index * sizeof(*profile_data);
++
++ profile_data = (struct axfs_profiling_data *)addr;
++
++ /* Record the inode number to determine the file name later. */
++ profile_data->inode_number = axfs_inode_number;
++
++ /* Increment the number of times the node has been paged in */
++ profile_data->count++;
++}
++
++#else
++
++int axfs_init_profiling(struct axfs_super *sbi)
++{
++ return 0;
++}
++
++int axfs_shutdown_profiling(struct axfs_super *sbi)
++{
++ return 0;
++}
++
++void axfs_profiling_add(struct axfs_super *sbi, unsigned long array_index,
++ unsigned int axfs_inode_number)
++{
++}
++
++#endif /* CONFIG_AXFS_PROFILING */
diff --git a/patches.axfs/axfs-axfs_super.c.patch b/patches.axfs/axfs-axfs_super.c.patch
new file mode 100644
index 00000000000000..0e9fcb50ee0b2e
--- /dev/null
+++ b/patches.axfs/axfs-axfs_super.c.patch
@@ -0,0 +1,1011 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:44:39 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:08:56 +0530
+Subject: [PATCH v2 RESEND 09/15] AXFS: axfs_super.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6050.1060605@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Contains the core code used to mount the fs.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Thomas Rony Jose <thomas.jose@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_super.c | 987 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 987 insertions(+)
+ create mode 100644 fs/axfs/axfs_super.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_super.c
+@@ -0,0 +1,987 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ * Copyright 2011 Sony Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Eric Anderson
++ * Jared Hulbert <jaredeh@gmail.com>
++ * Sujaya Srinivasan
++ * Justin Treon
++ *
++ * More info and current contacts at http://axfs.sourceforge.net
++ *
++ * axfs_super.c -
++ * Contains the core code used to mount the fs.
++ *
++ */
++#include "axfs.h"
++
++#include <linux/vmalloc.h>
++#include <linux/parser.h>
++#include <linux/statfs.h>
++#include <linux/module.h>
++#include <linux/mount.h>
++#include <linux/mtd/mtd.h>
++#include <linux/slab.h>
++
++static struct super_operations axfs_sops;
++
++static int axfs_is_region_compressed(struct axfs_region_desc *region)
++{
++ if (region->compressed_size > 0)
++ return true;
++
++ return false;
++}
++
++static int axfs_is_mmapable(struct axfs_super *sbi, u64 offset)
++{
++ if (sbi->mmap_size > offset)
++ return true;
++
++ return false;
++}
++
++static int axfs_is_region_mmapable(struct axfs_super *sbi,
++ struct axfs_region_desc *region)
++{
++ if (axfs_is_mmapable(sbi, region->fsoffset))
++ if (axfs_virtaddr_is_valid(sbi))
++ return true;
++
++ return false;
++}
++
++static int axfs_is_offset_mmapable(struct axfs_super *sbi, u64 offset)
++{
++ if (axfs_is_mmapable(sbi, offset))
++ if (axfs_virtaddr_is_valid(sbi))
++ return true;
++
++ return false;
++}
++
++static int axfs_is_region_incore(struct axfs_region_desc *region)
++{
++ if (region->incore > 0)
++ return true;
++
++ return false;
++}
++
++static int axfs_is_region_xip(struct axfs_super *sbi,
++ struct axfs_region_desc *region)
++{
++ if (!axfs_can_xip(sbi))
++ return false;
++
++ if (!axfs_is_region_mmapable(sbi, region))
++ return false;
++
++ if (axfs_is_region_compressed(region))
++ return false;
++
++ if (axfs_is_region_incore(region))
++ return false;
++
++ return true;
++}
++
++int axfs_physaddr_is_valid(struct axfs_super *sbi)
++{
++ if (sbi->phys_start_addr > 0)
++ return true;
++
++ return false;
++}
++
++int axfs_virtaddr_is_valid(struct axfs_super *sbi)
++{
++ if (sbi->virt_start_addr > 0)
++ return true;
++
++ return false;
++}
++
++int axfs_is_iomem(struct axfs_super *sbi)
++{
++ if (sbi->iomem_size > 0)
++ return true;
++
++ return false;
++}
++
++int axfs_is_pointed(struct axfs_super *sbi)
++{
++ if (sbi->mtd_pointed > 0)
++ return true;
++
++ return false;
++}
++
++int axfs_can_xip(struct axfs_super *sbi)
++{
++ if (axfs_is_pointed(sbi)) {
++ if (!axfs_physaddr_is_valid(sbi))
++ return false;
++ }
++
++ if (!axfs_virtaddr_is_valid(sbi))
++ return false;
++
++ return true;
++}
++
++int axfs_is_physmem(struct axfs_super *sbi)
++{
++ int phys = axfs_physaddr_is_valid(sbi);
++ int iomem = axfs_is_iomem(sbi);
++ int point = axfs_is_pointed(sbi);
++
++ if (phys && !iomem && !point)
++ return true;
++
++ return false;
++}
++
++u64 axfs_fsoffset_to_devoffset(struct axfs_super *sbi, u64 fsoffset)
++{
++ if (sbi->phys_start_addr == 0)
++ return fsoffset;
++
++ if (sbi->mtd1 == NULL || sbi->second_dev == NULL)
++ return fsoffset;
++
++ if (fsoffset >= sbi->mmap_size)
++ return fsoffset - sbi->mmap_size;
++
++ return fsoffset;
++}
++
++int axfs_nodev(struct super_block *sb)
++{
++ if (!axfs_has_mtd(sb) && !axfs_has_bdev(sb))
++ return true;
++
++ return false;
++}
++
++static void axfs_free_region(struct axfs_super *sbi,
++ struct axfs_region_desc *region)
++{
++ if (!region)
++ return;
++
++ if (axfs_is_region_xip(sbi, region))
++ return;
++
++ vfree(region->virt_addr);
++}
++
++static struct axfs_super *axfs_get_sbi(void)
++{
++ struct axfs_super *sbi;
++
++ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
++ if (sbi)
++ return sbi;
++
++ return ERR_PTR(-ENOMEM);
++}
++
++static void axfs_put_sbi(struct axfs_super *sbi)
++{
++ if (!sbi)
++ return;
++
++ axfs_shutdown_profiling(sbi);
++
++ axfs_free_region(sbi, &sbi->strings);
++ axfs_free_region(sbi, &sbi->xip);
++ axfs_free_region(sbi, &sbi->compressed);
++ axfs_free_region(sbi, &sbi->byte_aligned);
++ axfs_free_region(sbi, &sbi->node_type);
++ axfs_free_region(sbi, &sbi->node_index);
++ axfs_free_region(sbi, &sbi->cnode_offset);
++ axfs_free_region(sbi, &sbi->cnode_index);
++ axfs_free_region(sbi, &sbi->banode_offset);
++ axfs_free_region(sbi, &sbi->cblock_offset);
++ axfs_free_region(sbi, &sbi->inode_file_size);
++ axfs_free_region(sbi, &sbi->inode_name_offset);
++ axfs_free_region(sbi, &sbi->inode_num_entries);
++ axfs_free_region(sbi, &sbi->inode_mode_index);
++ axfs_free_region(sbi, &sbi->inode_array_index);
++ axfs_free_region(sbi, &sbi->modes);
++ axfs_free_region(sbi, &sbi->uids);
++ axfs_free_region(sbi, &sbi->gids);
++
++ kfree(sbi->second_dev);
++ vfree(sbi->cblock_buffer[0]);
++ vfree(sbi->cblock_buffer[1]);
++ kfree(sbi);
++}
++
++static void axfs_put_super(struct super_block *sb)
++{
++ axfs_unmap_mtd(sb);
++ axfs_put_sbi(AXFS_SB(sb));
++
++#ifndef NO_PHYSMEM
++ axfs_unmap_physmem(sb);
++#endif
++ sb->s_fs_info = NULL;
++}
++
++static void axfs_copy_mem(struct super_block *sb, void *buf, u64 fsoffset,
++ u64 len)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ unsigned long addr;
++
++ addr = sbi->virt_start_addr + (unsigned long)fsoffset;
++
++ memcpy(buf, (void *)addr, (size_t) len);
++}
++
++static int axfs_copy_metadata(struct super_block *sb, void *buf, u64 fsoffset,
++ u64 len)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u64 end = fsoffset + len;
++ u64 a = sbi->mmap_size - fsoffset;
++ u64 b = end - sbi->mmap_size;
++ void *bb = (void *)((unsigned long)buf + (unsigned long)a);
++ int err = 0;
++
++ /* Catches case where sbi is not yet fully initialized. */
++ if ((sbi->magic == 0) && (sbi->virt_start_addr != 0)) {
++ axfs_copy_mem(sb, buf, fsoffset, len);
++ return 0;
++ }
++
++ if (fsoffset < sbi->mmap_size) {
++ if (end > sbi->mmap_size) {
++ err = axfs_copy_metadata(sb, buf, fsoffset, a);
++ if (err)
++ return err;
++ err = axfs_copy_metadata(sb, bb, sbi->mmap_size, b);
++ } else {
++ if (axfs_is_offset_mmapable(sbi, fsoffset))
++ axfs_copy_mem(sb, buf, fsoffset, len);
++ else if (axfs_has_bdev(sb))
++ axfs_copy_block(sb, buf, fsoffset, len);
++ else if (axfs_has_mtd(sb))
++ err = axfs_copy_mtd(sb, buf, fsoffset, len);
++ }
++ } else {
++ if (axfs_nodev(sb))
++ axfs_copy_mem(sb, buf, fsoffset, len);
++ else if (axfs_has_bdev(sb))
++ axfs_copy_block(sb, buf, fsoffset, len);
++ else if (axfs_has_mtd(sb))
++ err = axfs_copy_mtd(sb, buf, fsoffset, len);
++ }
++ return err;
++}
++
++static int axfs_fill_region_data(struct super_block *sb,
++ struct axfs_region_desc *region, int force)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ unsigned long addr;
++ void *buff = NULL;
++ void *vaddr;
++ int err = -ENOMEM;
++ u64 size = region->size;
++ u64 fsoffset = region->fsoffset;
++ u64 end = fsoffset + size;
++ u64 c_size = region->compressed_size;
++
++ if (size == 0)
++ return 0;
++
++ if (axfs_is_region_incore(region))
++ goto incore;
++
++ if (axfs_is_region_compressed(region))
++ goto incore;
++
++ if (axfs_is_region_xip(sbi, region)) {
++ if ((end > sbi->mmap_size) && (force))
++ goto incore;
++ addr = sbi->virt_start_addr;
++ addr += (unsigned long)fsoffset;
++ region->virt_addr = (void *)addr;
++ return 0;
++ }
++
++ if (force)
++ goto incore;
++
++ region->virt_addr = NULL;
++ return 0;
++
++incore:
++ region->virt_addr = vmalloc(size);
++ if (!region->virt_addr)
++ goto out;
++ vaddr = region->virt_addr;
++
++ if (axfs_is_region_compressed(region)) {
++ buff = vmalloc(c_size);
++ if (!buff)
++ goto out;
++ axfs_copy_metadata(sb, buff, fsoffset, c_size);
++ err = axfs_uncompress_block(vaddr, size, buff, c_size);
++ if (!err)
++ goto out;
++ vfree(buff);
++ } else {
++ axfs_copy_metadata(sb, vaddr, fsoffset, size);
++ }
++
++ return 0;
++
++out:
++ vfree(buff);
++ vfree(region->virt_addr);
++ return err;
++}
++
++static int axfs_fill_region_data_ptrs(struct super_block *sb)
++{
++ int err;
++ struct axfs_super *sbi = AXFS_SB(sb);
++
++ err = axfs_fill_region_data(sb, &sbi->strings, true);
++ if (err)
++ goto out;
++
++ err = axfs_fill_region_data(sb, &sbi->xip, true);
++ if (err)
++ goto out;
++
++ err = axfs_fill_region_data(sb, &sbi->compressed, false);
++ if (err)
++ goto out;
++
++ err = axfs_fill_region_data(sb, &sbi->byte_aligned, false);
++ if (err)
++ goto out;
++
++ err = axfs_fill_region_data(sb, &sbi->node_type, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->node_index, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->cnode_offset, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->cnode_index, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->banode_offset, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->cblock_offset, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->inode_file_size, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->inode_name_offset, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->inode_num_entries, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->inode_mode_index, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->inode_array_index, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->modes, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->uids, true);
++ if (err)
++ goto out;
++ err = axfs_fill_region_data(sb, &sbi->gids, true);
++ if (err)
++ goto out;
++
++out:
++ return err;
++}
++
++static int axfs_init_cblock_buffers(struct axfs_super *sbi)
++{
++ sbi->current_cnode_index = -1;
++ sbi->cblock_buffer[0] = vmalloc(sbi->cblock_size);
++ sbi->cblock_buffer[1] = vmalloc(sbi->cblock_size);
++ if ((!sbi->cblock_buffer[0]) || (!sbi->cblock_buffer[1]))
++ return -ENOMEM;
++
++ return 0;
++}
++
++static int axfs_fixup_devices(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ int err = 0;
++
++#ifndef NO_PHYSMEM
++ if (axfs_is_physmem(sbi)) {
++ axfs_map_physmem(sbi, sbi->mmap_size);
++ } else if (axfs_has_mtd(sb)) {
++#else
++ if (axfs_has_mtd(sb)) {
++#endif
++ err = axfs_map_mtd(sb);
++ } else if (axfs_is_iomem(sbi)) {
++ sbi->phys_start_addr = 0;
++ }
++
++ if (!(axfs_virtaddr_is_valid(sbi)))
++ sbi->mmap_size = 0;
++
++ return err;
++}
++
++static void axfs_fill_region_desc(struct super_block *sb,
++ struct axfs_region_desc_onmedia *out,
++ __be64 offset_be, struct axfs_region_desc *in)
++{
++ u64 offset = be64_to_cpu(offset_be);
++
++ axfs_copy_metadata(sb, (void *)out, offset, sizeof(*out));
++
++ in->fsoffset = be64_to_cpu(out->fsoffset);
++ in->size = be64_to_cpu(out->size);
++ in->compressed_size = be64_to_cpu(out->compressed_size);
++ in->max_index = be64_to_cpu(out->max_index);
++ in->table_byte_depth = out->table_byte_depth;
++ in->incore = out->incore;
++}
++
++static int axfs_fill_region_descriptors(struct super_block *sb,
++ struct axfs_super_onmedia *sbo)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct axfs_region_desc_onmedia *out;
++
++ out = kzalloc(sizeof(*out), GFP_KERNEL);
++ if (!out)
++ return -ENOMEM;
++
++ axfs_fill_region_desc(sb, out, sbo->strings, &sbi->strings);
++ axfs_fill_region_desc(sb, out, sbo->xip, &sbi->xip);
++ axfs_fill_region_desc(sb, out, sbo->compressed, &sbi->compressed);
++ axfs_fill_region_desc(sb, out, sbo->byte_aligned, &sbi->byte_aligned);
++ axfs_fill_region_desc(sb, out, sbo->node_type, &sbi->node_type);
++ axfs_fill_region_desc(sb, out, sbo->node_index, &sbi->node_index);
++ axfs_fill_region_desc(sb, out, sbo->cnode_offset, &sbi->cnode_offset);
++ axfs_fill_region_desc(sb, out, sbo->cnode_index, &sbi->cnode_index);
++ axfs_fill_region_desc(sb, out, sbo->banode_offset, &sbi->banode_offset);
++ axfs_fill_region_desc(sb, out, sbo->cblock_offset, &sbi->cblock_offset);
++ axfs_fill_region_desc(sb, out, sbo->inode_file_size,
++ &sbi->inode_file_size);
++ axfs_fill_region_desc(sb, out, sbo->inode_name_offset,
++ &sbi->inode_name_offset);
++ axfs_fill_region_desc(sb, out, sbo->inode_num_entries,
++ &sbi->inode_num_entries);
++ axfs_fill_region_desc(sb, out, sbo->inode_mode_index,
++ &sbi->inode_mode_index);
++ axfs_fill_region_desc(sb, out, sbo->inode_array_index,
++ &sbi->inode_array_index);
++ axfs_fill_region_desc(sb, out, sbo->modes, &sbi->modes);
++ axfs_fill_region_desc(sb, out, sbo->uids, &sbi->uids);
++ axfs_fill_region_desc(sb, out, sbo->gids, &sbi->gids);
++
++ kfree(out);
++
++ return 0;
++}
++
++static int axfs_check_page_shift(struct axfs_super *sbi)
++{
++ if (sbi->page_shift != PAGE_SHIFT) {
++ printk(KERN_ERR "axfs: Filesystem is AXFS, however "
++ "the page size does not match that\n"
++ "of the system. Cowardly refusing "
++ "to mount.\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int axfs_check_compression_type(struct axfs_super *sbi)
++{
++ if (sbi->compression_type != ZLIB) {
++ printk(KERN_ERR "axfs: Unknown compression type "
++ "specified in super block.\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int axfs_get_onmedia_super(struct super_block *sb)
++{
++ int err;
++ struct axfs_super *sbi = AXFS_SB(sb);
++ struct axfs_super_onmedia *sbo;
++
++ sbo = kmalloc(sizeof(*sbo), GFP_KERNEL);
++ if (!sbo)
++ return -ENOMEM;
++
++#ifndef NO_PHYSMEM
++ axfs_map_physmem(sbi, sizeof(*sbo));
++#endif
++ axfs_copy_metadata(sb, (void *)sbo, 0, sizeof(*sbo));
++
++ /* Do sanity checks on the superblock */
++ if (be32_to_cpu(sbo->magic) != AXFS_MAGIC) {
++ printk(KERN_ERR "axfs: wrong magic: got %x, expected %x\n",
++ be32_to_cpu(sbo->magic), AXFS_MAGIC);
++ err = -EINVAL;
++ goto out;
++ }
++
++ /* verify the signiture is correct */
++ if (strncmp(sbo->signature, AXFS_SIGNATURE, sizeof(AXFS_SIGNATURE))) {
++ printk(KERN_ERR "axfs: wrong signature: "
++ "got '%s', expected '%s'\n",
++ sbo->signature, AXFS_SIGNATURE);
++ err = -EINVAL;
++ goto out;
++ }
++
++ sbi->magic = be32_to_cpu(sbo->magic);
++ sbi->version_major = sbo->version_major;
++ sbi->version_minor = sbo->version_minor;
++ sbi->version_sub = sbo->version_sub;
++ sbi->files = be64_to_cpu(sbo->files);
++ sbi->size = be64_to_cpu(sbo->size);
++ sbi->blocks = be64_to_cpu(sbo->blocks);
++ sbi->mmap_size = be64_to_cpu(sbo->mmap_size);
++ sbi->cblock_size = be32_to_cpu(sbo->cblock_size);
++ sbi->timestamp.tv_sec = be64_to_cpu(sbo->timestamp);
++ sbi->timestamp.tv_nsec = 0;
++ sbi->compression_type = sbo->compression_type;
++ sbi->page_shift = sbo->page_shift;
++
++ err = axfs_check_page_shift(sbi);
++ if (err)
++ goto out;
++
++ err = axfs_check_compression_type(sbi);
++ if (err)
++ goto out;
++
++ /* If no block or MTD device, adjust mmapable to cover all image */
++ if (axfs_nodev(sb))
++ sbi->mmap_size = sbi->size;
++
++ err = axfs_fill_region_descriptors(sb, sbo);
++
++out:
++ kfree(sbo);
++#ifndef NO_PHYSMEM
++ axfs_unmap_physmem(sb);
++#endif
++ return err;
++}
++
++u64 axfs_get_io_dev_size(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ return sbi->size - sbi->mmap_size;
++}
++
++/*
++ * Verify that the size of the IO segment of a split filesystem
++ * is less than or equal to that of the device containing it.
++ */
++static int axfs_verify_device_sizes(struct super_block *sb)
++{
++ int err;
++
++ if (axfs_verify_bdev_sizes(sb, &err))
++ goto out;
++
++ if (axfs_verify_mtd_sizes(sb, &err))
++ goto out;
++
++out:
++ return err;
++}
++
++/*
++ * Read the last four bytes of the volume and make sure the
++ * AXFS magic is present.
++ */
++static int axfs_verify_eofs_magic(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ u32 eof_magic;
++ u64 fsoffset = sbi->size - sizeof(eof_magic);
++
++ if (axfs_copy_metadata(sb, &eof_magic, fsoffset, sizeof(eof_magic)))
++ return -EINVAL;
++
++ if (be32_to_cpu(eof_magic) == AXFS_MAGIC)
++ return 0;
++
++ printk(KERN_ERR "axfs: bad magic at end of image: got %x expected %x\n",
++ be32_to_cpu(eof_magic), AXFS_MAGIC);
++ return -EINVAL;
++}
++
++static int axfs_do_fill_super(struct super_block *sb)
++{
++ struct axfs_super *sbi = AXFS_SB(sb);
++ int err;
++
++ err = axfs_get_onmedia_super(sb);
++ if (err)
++ goto out;
++
++ err = axfs_fixup_devices(sb);
++ if (err)
++ goto out;
++
++ err = axfs_verify_device_sizes(sb);
++ if (err)
++ goto out;
++
++ err = axfs_verify_eofs_magic(sb);
++ if (err)
++ goto out;
++
++ err = axfs_fill_region_data_ptrs(sb);
++ if (err)
++ goto out;
++
++ /* Check that the root inode is in a sane state */
++ if (!S_ISDIR(axfs_get_mode(sbi, 0))) {
++ printk(KERN_ERR "axfs: root is not a directory\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ if (axfs_get_inode_num_entries(sbi, 0) == 0) {
++ printk(KERN_INFO "axfs: empty filesystem\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = axfs_init_cblock_buffers(sbi);
++ if (err)
++ goto out;
++
++ init_rwsem(&sbi->lock);
++
++ return 0;
++
++out:
++ return err;
++}
++
++int axfs_fill_super(struct super_block *sb, void *data, int silent)
++{
++ struct axfs_super *sbi;
++ struct inode *root;
++ int err;
++ struct axfs_super *sbi_in = (struct axfs_super *)data;
++
++ sbi = axfs_get_sbi();
++ if (IS_ERR(sbi))
++ return PTR_ERR(sbi);
++
++ sb->s_fs_info = (void *)sbi;
++
++ memcpy(sbi, sbi_in, sizeof(*sbi));
++
++ /* fully populate the incore superblock structures */
++ err = axfs_do_fill_super(sb);
++ if (err)
++ goto out;
++
++ sb->s_flags |= MS_RDONLY;
++
++ /* Setup the VFS super block now */
++ sb->s_op = &axfs_sops;
++ root = axfs_create_vfs_inode(sb, 0);
++ if (!root) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ sb->s_root = d_make_root(root);
++ if (!sb->s_root) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = axfs_init_profiling(sbi);
++ if (err)
++ goto out;
++
++ if (axfs_has_mtd(sb))
++ sbi->mtd0 = axfs_mtd(sb);
++ return 0;
++
++out:
++ axfs_put_super(sb);
++ return err;
++}
++
++static struct dentry *
++axfs_get_sb_address(struct file_system_type *fs_type,
++ int flags, struct axfs_super *sbi)
++{
++ int mtdnr;
++ char *sd = sbi->second_dev;
++
++ if (sbi->phys_start_addr == 0)
++ return false;
++
++ if (sbi->phys_start_addr & (PAGE_SIZE - 1)) {
++ printk(KERN_ERR
++ "axfs: address 0x%lx for axfs image isn't aligned "
++ "to a page boundary\n", sbi->phys_start_addr);
++ return ERR_PTR(-EINVAL);
++ }
++
++ if (axfs_is_dev_mtd(sd, &mtdnr))
++ return axfs_get_sb_mtd(fs_type, flags, sd, sbi);
++ else if (axfs_is_dev_bdev(sd))
++ return axfs_get_sb_bdev(fs_type, flags, sd, sbi);
++ else
++ return mount_nodev(fs_type, flags, sbi, axfs_fill_super);
++
++}
++
++/* helpers for parse_axfs_options */
++enum {
++ OPTION_ERR,
++ OPTION_SECOND_DEV,
++ OPTION_PHYSICAL_ADDRESS_LOWER_X,
++ OPTION_PHYSICAL_ADDRESS_UPPER_X,
++ OPTION_IOMEM
++};
++
++/* helpers for parse_axfs_options */
++static match_table_t tokens = {
++ {OPTION_SECOND_DEV, "second_dev=%s"},
++ {OPTION_PHYSICAL_ADDRESS_LOWER_X, "physaddr=0x%s"},
++ {OPTION_PHYSICAL_ADDRESS_UPPER_X, "physaddr=0X%s"},
++ {OPTION_IOMEM, "iomem=%s"},
++ {OPTION_ERR, NULL}
++};
++
++static int axfs_check_options(char *options, struct axfs_super *sbi)
++{
++ int err = -EINVAL;
++ unsigned long address = 0;
++ char *iomem = NULL;
++ unsigned long length = 0;
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
++
++ if (!options)
++ return 0;
++
++ if (!*options)
++ return 0;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
++ continue;
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case OPTION_SECOND_DEV:
++ sbi->second_dev = match_strdup(&args[0]);
++ if (!(sbi->second_dev)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ if (!*(sbi->second_dev))
++ goto bad_value;
++ break;
++ case OPTION_IOMEM:
++ iomem = match_strdup(&args[0]);
++ if (!(iomem)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ if (!*iomem)
++ goto bad_value;
++ break;
++ case OPTION_PHYSICAL_ADDRESS_LOWER_X:
++ case OPTION_PHYSICAL_ADDRESS_UPPER_X:
++ if (match_hex(&args[0], (int *)&address))
++ goto out;
++ if (!address)
++ goto bad_value;
++ break;
++ default:
++ printk(KERN_ERR
++ "axfs: unrecognized mount option '%s' "
++ "or missing value\n", p);
++ goto out;
++ }
++ }
++
++ if (iomem) {
++ if (address)
++ goto out;
++ err = axfs_get_uml_address(iomem, &address, &length);
++ kfree(iomem);
++ sbi->iomem_size = length;
++ sbi->virt_start_addr = address;
++ }
++
++ sbi->phys_start_addr = address;
++ return 0;
++
++bad_value:
++ printk(KERN_ERR
++ "axfs: unrecognized mount option '%s' "
++ "or missing value\n", p);
++
++out:
++ kfree(iomem);
++ return err;
++}
++
++struct dentry *axfs_get_sb(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data)
++{
++ struct axfs_super *sbi;
++ int err;
++ struct dentry *ret = ERR_PTR(-EINVAL);
++
++ sbi = axfs_get_sbi();
++ if (IS_ERR(sbi))
++ return ret;
++
++ err = axfs_check_options((char *)data, sbi);
++ if (err)
++ goto out;
++
++ /* First we check if we are mounting directly to memory */
++ ret = axfs_get_sb_address(fs_type, flags, sbi);
++ if (!(IS_ERR_OR_NULL(ret)))
++ goto out;
++
++ /* Next we assume there's a MTD device */
++ ret = axfs_get_sb_mtd(fs_type, flags, dev_name, sbi);
++ if (!(IS_ERR_OR_NULL(ret)))
++ goto out;
++
++ /* Now we assume it's a block device */
++ if (sbi->second_dev) {
++ printk(KERN_ERR
++ "axfs: can't specify secondary block device %s because "
++ "%s is assumed to be a block device\n", sbi->second_dev,
++ dev_name);
++ err = -EINVAL;
++ goto out;
++ }
++ ret = axfs_get_sb_bdev(fs_type, flags, dev_name, sbi);
++ if (!(IS_ERR_OR_NULL(ret)))
++ goto out;
++ err = -EINVAL;
++
++out:
++ axfs_put_sbi(sbi);
++ return ret;
++}
++
++static void axfs_kill_super(struct super_block *sb)
++{
++ if (axfs_nodev(sb))
++ return kill_anon_super(sb);
++
++ if (axfs_has_mtd(sb))
++ axfs_kill_mtd_super(sb);
++
++ if (axfs_has_bdev(sb))
++ axfs_kill_block_super(sb);
++}
++
++static int axfs_remount(struct super_block *sb, int *flags, char *data)
++{
++ *flags |= MS_RDONLY;
++ return 0;
++}
++
++static int axfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct axfs_super *sbi = AXFS_SB(dentry->d_sb);
++
++ buf->f_type = AXFS_MAGIC;
++ buf->f_bsize = (1 << sbi->page_shift);
++ buf->f_blocks = sbi->blocks;
++ buf->f_bfree = 0;
++ buf->f_bavail = 0;
++ buf->f_files = sbi->files;
++ buf->f_ffree = 0;
++ buf->f_namelen = AXFS_MAXPATHLEN;
++ return 0;
++}
++
++static struct super_operations axfs_sops = {
++ .put_super = axfs_put_super,
++ .remount_fs = axfs_remount,
++ .statfs = axfs_statfs,
++};
++
++static struct file_system_type axfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "axfs",
++ .mount = axfs_get_sb,
++ .kill_sb = axfs_kill_super,
++};
++
++static int __init init_axfs_fs(void)
++{
++ int err;
++
++ err = axfs_uncompress_init();
++ if (err)
++ return err;
++
++ err = register_filesystem(&axfs_fs_type);
++
++ if (!err)
++ return 0;
++
++ axfs_uncompress_exit();
++ return err;
++}
++
++static void __exit exit_axfs_fs(void)
++{
++ axfs_uncompress_exit();
++ unregister_filesystem(&axfs_fs_type);
++}
++
++module_init(init_axfs_fs);
++module_exit(exit_axfs_fs);
++MODULE_LICENSE("GPL");
diff --git a/patches.axfs/axfs-axfs_uml.c.patch b/patches.axfs/axfs-axfs_uml.c.patch
new file mode 100644
index 00000000000000..3a3f205a05a7f9
--- /dev/null
+++ b/patches.axfs/axfs-axfs_uml.c.patch
@@ -0,0 +1,71 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:46:32 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:10:49 +0530
+Subject: [PATCH v2 RESEND 10/15] AXFS: axfs_uml.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF60C1.5050301@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+Allows axfs in a UML kernel to use find_iomem() interface for the XIP device
+or dummy functions if this is not a UML build.
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_uml.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+ create mode 100644 fs/axfs/axfs_uml.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_uml.c
+@@ -0,0 +1,47 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Copyright(c) 2008 Numonyx
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Authors:
++ * Jared Hulbert <jaredeh@gmail.com>
++ *
++ * Project url: http://axfs.sourceforge.net
++ *
++ * axfs_uml.c -
++ * Allows axfs to a UML kernels find_iomem() interface as an XIP device or
++ * dummy functions if this is not a UML build.
++ */
++#include "axfs.h"
++
++#ifdef CONFIG_UML
++#include <mem_user.h>
++int axfs_get_uml_address(char *iomem, unsigned long *address,
++ unsigned long *length)
++{
++ *address = find_iomem(iomem, length);
++ if (!(*address)) {
++ printk(KERN_DEBUG "axfs: find_iomem() failed\n");
++ return -EINVAL;
++ }
++
++ if (*length < PAGE_SIZE) {
++ printk(KERN_DEBUG
++ "axfs: iomem() too small, must be at least %li Bytes\n",
++ PAGE_SIZE);
++ return -EINVAL;
++ }
++ return 0;
++}
++#else
++int axfs_get_uml_address(char *iomem, unsigned long *address,
++ unsigned long *length)
++{
++ return 0;
++}
++#endif /* CONFIG_UML */
diff --git a/patches.axfs/axfs-axfs_uncompress.c.patch b/patches.axfs/axfs-axfs_uncompress.c.patch
new file mode 100644
index 00000000000000..fc2559479e0105
--- /dev/null
+++ b/patches.axfs/axfs-axfs_uncompress.c.patch
@@ -0,0 +1,113 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:47:49 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:12:07 +0530
+Subject: [PATCH v2 RESEND 11/15] AXFS: axfs_uncompress.c
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF610F.3000208@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+AXFS interfaces to the uncompression library
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/axfs_uncompress.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 90 insertions(+)
+ create mode 100644 fs/axfs/axfs_uncompress.c
+
+--- /dev/null
++++ b/fs/axfs/axfs_uncompress.c
+@@ -0,0 +1,90 @@
++/*
++ * Advanced XIP File System for Linux - AXFS
++ * Readonly, compressed, and XIP filesystem for Linux systems big and small
++ *
++ * Modified in 2006 by Eric Anderson
++ * from the cramfs sources fs/cramfs/uncompress.c
++ *
++ * (C) Copyright 1999 Linus Torvalds
++ *
++ * axfs_uncompress.c -
++ * axfs interfaces to the uncompression library. There's really just
++ * three entrypoints:
++ *
++ * - axfs_uncompress_init() - called to initialize the thing.
++ * - axfs_uncompress_exit() - tell me when you're done
++ * - axfs_uncompress_block() - uncompress a block.
++ *
++ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
++ * only have one stream, and we'll initialize it only once even if it
++ * then is used by multiple filesystems.
++ *
++ */
++
++#include <linux/errno.h>
++#include <linux/vmalloc.h>
++#include <linux/zlib.h>
++#include <linux/init.h>
++#include <linux/mutex.h>
++
++static z_stream stream;
++static DEFINE_MUTEX(axfs_uncmp_mutex);
++
++int axfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
++{
++ int err;
++ int out;
++
++ mutex_lock(&axfs_uncmp_mutex);
++
++ stream.next_in = src;
++ stream.avail_in = srclen;
++
++ stream.next_out = dst;
++ stream.avail_out = dstlen;
++
++ err = zlib_inflateReset(&stream);
++ if (err != Z_OK) {
++ printk(KERN_ERR "axfs: zlib_inflateReset error %d\n", err);
++ zlib_inflateEnd(&stream);
++ zlib_inflateInit(&stream);
++ }
++
++ err = zlib_inflate(&stream, Z_FINISH);
++ if (err != Z_STREAM_END)
++ goto err;
++
++ out = stream.total_out;
++
++ mutex_unlock(&axfs_uncmp_mutex);
++
++ return out;
++
++err:
++
++ mutex_unlock(&axfs_uncmp_mutex);
++
++ printk(KERN_ERR "axfs: error %d while decompressing!\n", err);
++ printk(KERN_ERR "%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
++ return 0;
++}
++
++int __init axfs_uncompress_init(void)
++{
++
++ stream.workspace = vmalloc(zlib_inflate_workspacesize());
++ if (!stream.workspace)
++ return -ENOMEM;
++ stream.next_in = NULL;
++ stream.avail_in = 0;
++ zlib_inflateInit(&stream);
++
++ return 0;
++}
++
++int axfs_uncompress_exit(void)
++{
++ zlib_inflateEnd(&stream);
++ vfree(stream.workspace);
++ return 0;
++}
diff --git a/patches.axfs/axfs-kconfigs-and-makefiles.patch b/patches.axfs/axfs-kconfigs-and-makefiles.patch
new file mode 100644
index 00000000000000..881aedbe3d51fc
--- /dev/null
+++ b/patches.axfs/axfs-kconfigs-and-makefiles.patch
@@ -0,0 +1,85 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:29:51 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 16:54:09 +0530
+Subject: [PATCH v2 RESEND 01/15] AXFS: Kconfigs and Makefiles
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF5CD9.2040206@ap.sony.com>
+
+
+From: Jared Hulbert <jaredeh@gmail.com>
+
+The Kconfigs and Makefiles for AXFS
+
+Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/Kconfig | 3 ++-
+ fs/Makefile | 1 +
+ fs/axfs/Kconfig | 18 ++++++++++++++++++
+ fs/axfs/Makefile | 8 ++++++++
+ 4 files changed, 29 insertions(+), 1 deletion(-)
+ create mode 100644 fs/axfs/Kconfig
+ create mode 100644 fs/axfs/Makefile
+
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -17,7 +17,7 @@ source "fs/ext4/Kconfig"
+ config FS_XIP
+ # execute in place
+ bool
+- depends on EXT2_FS_XIP || PRAMFS_XIP
++ depends on EXT2_FS_XIP || PRAMFS_XIP || AXFS
+ default y
+
+ source "fs/jbd/Kconfig"
+@@ -221,6 +221,7 @@ source "fs/pstore/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
+ source "fs/pramfs/Kconfig"
++source "fs/axfs/Kconfig"
+ source "fs/exofs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -72,6 +72,7 @@ obj-$(CONFIG_EXT4_FS) += ext4/
+ obj-$(CONFIG_JBD) += jbd/
+ obj-$(CONFIG_JBD2) += jbd2/
+ obj-$(CONFIG_CRAMFS) += cramfs/
++obj-$(CONFIG_AXFS) += axfs/
+ obj-$(CONFIG_SQUASHFS) += squashfs/
+ obj-y += ramfs/
+ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
+--- /dev/null
++++ b/fs/axfs/Kconfig
+@@ -0,0 +1,18 @@
++config AXFS
++ tristate "Advanced XIP File System (AXFS) support (EXPERIMENTAL)"
++ select FS_XIP
++ select ZLIB_INFLATE
++ help
++ The Advanced XIP File System or (AXFS) is a highly compressed
++ readonly filesystem like cramfs or squashfs. It also can be
++ configured to store individual pages of files compressed or
++ uncompressed as XIP pages. This allows for faster boot up and
++ application launch time with a smaller memory footprint.
++
++config AXFS_PROFILING
++ bool "Profiling extensions for AXFS (EXPERIMENTAL)"
++ depends on AXFS
++ help
++ Profiling tooling used to identify what pages in the filesystem
++ image are actually accessed and how much.
++
+--- /dev/null
++++ b/fs/axfs/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for axfs
++#
++
++obj-$(CONFIG_AXFS) += axfs.o
++
++axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
++ axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
diff --git a/patches.axfs/axfs-mount-as-rootfs.patch b/patches.axfs/axfs-mount-as-rootfs.patch
new file mode 100644
index 00000000000000..854e8e909aa872
--- /dev/null
+++ b/patches.axfs/axfs-mount-as-rootfs.patch
@@ -0,0 +1,93 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:51:22 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:15:41 +0530
+Subject: [PATCH v2 RESEND 15/15] AXFS: mount as rootfs
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF61E5.4080108@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+Add support to mount AXFS as root file system first.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/Kconfig | 15 +++++++++++++++
+ fs/axfs/axfs_super.c | 6 ++++++
+ init/do_mounts.c | 20 ++++++++++++++++++++
+ 3 files changed, 41 insertions(+)
+
+--- a/fs/axfs/Kconfig
++++ b/fs/axfs/Kconfig
+@@ -34,3 +34,18 @@ config AXFS_DEBUG_XIP_RECORDS_NUM
+ help
+ The number of records which /porc/axfs_xip can record. one record
+ takes about 64 bytes of memory.
++
++config AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++ bool "First Mount AXFS as Rootfs"
++ depends on AXFS
++ help
++ Say Y if you have enabled axfs, and you want to mount the axfs
++ image as a root file system first when the kernel boots. This option
++ makes the kernel boottime a little faster when the command line is
++ properly set. Before having the kernel mount this axfs image
++ as a root file system, you must pass the command line parameter:
++ "root=/dev/null rootflags=physaddr=0x********" to the kernel
++ (replace 0x******** with the physical address location of the
++ axfs image to boot with).
++
++ If unsure, say N.
+--- a/fs/axfs/axfs_super.c
++++ b/fs/axfs/axfs_super.c
+@@ -884,6 +884,12 @@ struct dentry *axfs_get_sb(struct file_s
+ if (err)
+ goto out;
+
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++ printk(KERN_INFO "AXFS: Checking AXFS filesystem at virtaddr: 0x%08lx "
++ "(physaddr=0x%08lx).\n", sbi->virt_start_addr,
++ sbi->phys_start_addr);
++#endif
++
+ /* First we check if we are mounting directly to memory */
+ ret = axfs_get_sb_address(fs_type, flags, sbi);
+ if (!(IS_ERR_OR_NULL(ret)))
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -439,6 +439,19 @@ static int __init mount_nfs_root(void)
+ }
+ #endif
+
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++static int __init mount_axfs_root(void)
++{
++ create_dev("/dev/root", ROOT_DEV);
++ if (root_mount_data &&
++ do_mount_root("/dev/root", "axfs", root_mountflags,
++ root_mount_data) == 0)
++ return 1;
++ return 0;
++}
++#endif
++
++
+ #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
+ void __init change_floppy(char *fmt, ...)
+ {
+@@ -471,6 +484,13 @@ void __init change_floppy(char *fmt, ...
+
+ void __init mount_root(void)
+ {
++#ifdef CONFIG_AXFS_FIRST_MOUNT_AXFS_AS_ROOTFS
++ if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
++ if (mount_axfs_root())
++ return;
++ printk(KERN_ERR "VFS: Unable to mount axfs root.\n");
++ }
++#endif
+ #ifdef CONFIG_ROOT_NFS
+ if (ROOT_DEV == Root_NFS) {
+ if (mount_nfs_root())
diff --git a/patches.axfs/axfs-xip-debugging-support.patch b/patches.axfs/axfs-xip-debugging-support.patch
new file mode 100644
index 00000000000000..fb03b2fd06025f
--- /dev/null
+++ b/patches.axfs/axfs-xip-debugging-support.patch
@@ -0,0 +1,303 @@
+From Aaditya.Kumar@ap.sony.com Fri Nov 23 03:50:07 2012
+From: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+Date: Fri, 23 Nov 2012 17:14:25 +0530
+Subject: [PATCH v2 RESEND 13/15] AXFS: XIP debugging support.
+To: Greg KH <gregkh@linuxfoundation.org>
+Cc: "ltsi-dev@lists.linuxfoundation.org" <ltsi-dev@lists.linuxfoundation.org>, tim.bird@am.sony.com, frank.rowand@am.sony.com, takuzo.ohara@ap.sony.com, amit.agarwal@ap.sony.com, kan.iibuchi@jp.sony.com, aaditya.kumar.30@gmail.com
+Message-ID: <50AF6199.7040801@ap.sony.com>
+
+
+From: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+
+This code augments debugg infrastructure for AXFS.
+It captures access of XIP mapped pages of files in a
+proc entry at /proc/axfs_xip.
+
+Signed-off-by: Takuzo Ohara <Takuzo.Ohara@ap.sony.com>
+Signed-off-by: Aaditya Kumar <aaditya.kumar@ap.sony.com>
+---
+ fs/axfs/Kconfig | 18 +++++
+ fs/axfs/Makefile | 2
+ fs/axfs/axfs_inode.c | 35 +++++++++-
+ fs/axfs/axfs_super.c | 4 -
+ fs/axfs/axfs_xip_profile.c | 154 +++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/axfs_fs.h | 7 ++
+ 6 files changed, 216 insertions(+), 4 deletions(-)
+ create mode 100644 fs/axfs/axfs_xip_profile.c
+
+--- a/fs/axfs/Kconfig
++++ b/fs/axfs/Kconfig
+@@ -16,3 +16,21 @@ config AXFS_PROFILING
+ Profiling tooling used to identify what pages in the filesystem
+ image are actually accessed and how much.
+
++config AXFS_DEBUG
++ bool "AXFS debugging support"
++ depends on AXFS
++ help
++ If you are experiencing any problems with the AXFS filesystem, say
++ Y here. This will create a profile entry at /proc/axfs_xip. In this
++ profile, the XIP mapped pages of files are recorded.
++
++ If unsure, say N.
++
++config AXFS_DEBUG_XIP_RECORDS_NUM
++ int "Number of axfs xip profile records (100 - 1000)"
++ range 100 1000
++ depends on AXFS_DEBUG
++ default 500
++ help
++ The number of records which /porc/axfs_xip can record. one record
++ takes about 64 bytes of memory.
+--- a/fs/axfs/Makefile
++++ b/fs/axfs/Makefile
+@@ -6,3 +6,5 @@ obj-$(CONFIG_AXFS) += axfs.o
+
+ axfs-y := axfs_inode.o axfs_super.o axfs_uncompress.o axfs_profiling.o \
+ axfs_uml.o axfs_mtd.o axfs_bdev.o axfs_physmem.o
++
++obj-$(CONFIG_AXFS_DEBUG) += axfs_xip_profile.o
+--- a/fs/axfs/axfs_inode.c
++++ b/fs/axfs/axfs_inode.c
+@@ -464,6 +464,10 @@ static int axfs_fault(struct vm_area_str
+ struct axfs_super *sbi = AXFS_SB(sb);
+ u64 ino_number = inode->i_ino;
+ u64 array_index;
++#ifdef CONFIG_AXFS_DEBUG
++ unsigned long xip_node_address, offset, length;
++ unsigned int numpages, count;
++#endif
+
+ array_index = axfs_get_inode_array_index(sbi, ino_number) + vmf->pgoff;
+
+@@ -474,12 +478,39 @@ static int axfs_fault(struct vm_area_str
+ if (!(vma->vm_flags & VM_WRITE))
+ axfs_profiling_add(sbi, array_index, ino_number);
+
++#ifdef CONFIG_AXFS_DEBUG
++ offset = vma->vm_pgoff;
++ length = vma->vm_end - vma->vm_start;
++
++ if (length > inode->i_size)
++ length = inode->i_size;
++
++ length = PAGE_ALIGN(length);
++ numpages = length >> PAGE_SHIFT;
++#endif
++
+ /*
+ * figure out if the node is XIP or compressed and call the
+ * appropriate function
+ */
+- if (axfs_is_node_xip(sbi, array_index))
+- return xip_file_fault(vma, vmf);
++#ifdef CONFIG_AXFS_DEBUG
++ for (count = 0; count < numpages; count++, array_index++) {
++#endif
++ if (axfs_is_node_xip(sbi, array_index)) {
++#ifdef CONFIG_AXFS_DEBUG
++ xip_node_address = axfs_get_xip_region_physaddr(sbi);
++ xip_node_address += ((axfs_get_inode_num_entries(sbi, array_index)) << PAGE_SHIFT);
++ axfs_xip_record((unsigned char *)file->f_dentry->d_name.name,
++ xip_node_address,
++ vma->vm_start + (PAGE_SIZE * count),
++ (unsigned int)(PAGE_SIZE),
++ pgprot_val(vma->vm_page_prot));
++#endif
++ return xip_file_fault(vma, vmf);
++ }
++#ifdef CONFIG_AXFS_DEBUG
++ }
++#endif
+ return filemap_fault(vma, vmf);
+ }
+
+--- a/fs/axfs/axfs_super.c
++++ b/fs/axfs/axfs_super.c
+@@ -681,11 +681,11 @@ static int axfs_do_fill_super(struct sup
+ goto out;
+ }
+
++#ifdef CONFIG_AXFS_DEBUG
+ if (axfs_get_inode_num_entries(sbi, 0) == 0) {
+ printk(KERN_INFO "axfs: empty filesystem\n");
+- err = -EINVAL;
+- goto out;
+ }
++#endif
+
+ err = axfs_init_cblock_buffers(sbi);
+ if (err)
+--- /dev/null
++++ b/fs/axfs/axfs_xip_profile.c
+@@ -0,0 +1,154 @@
++/*
++ * fs/axfs/axfs_xip_profile.c
++ *
++ * profiler: /proc/axfs_xip
++ *
++ * Copyright 2005-2007 Sony Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ *
++ *
++ */
++
++#ifdef CONFIG_AXFS_DEBUG
++
++#include <linux/types.h>
++#include <linux/proc_fs.h>
++
++
++#ifndef CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
++#define CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM 500
++#endif
++
++#define RECORDS CONFIG_AXFS_DEBUG_XIP_RECORDS_NUM
++
++#define MAX_FILE_NAME_LEN 48
++
++static DEFINE_SEMAPHORE(record_index_sem);
++
++/* each record is 64 bytes */
++struct axfs_xip_record {
++ char filename[MAX_FILE_NAME_LEN]; /* XIP mapped file name */
++ unsigned long physaddr; /* XIP mapped physaddr */
++ unsigned long virtaddr; /* XIP mapped virtaddr */
++ unsigned int size; /* XIP mapped size */
++ unsigned long pgprot; /* XIP mapped page prot */
++};
++
++static struct axfs_xip_record axfs_xip_records[RECORDS];
++static unsigned long record_index;
++
++/* record function */
++int axfs_xip_record(unsigned char *name, unsigned long physaddr,
++ unsigned long virtaddr, unsigned int size,
++ unsigned long pgprot)
++{
++
++ int namelen = 0;
++ if (down_interruptible(&record_index_sem))
++ return -EINTR;
++
++ if (record_index >= RECORDS)
++ goto out;
++
++ axfs_xip_records[record_index].physaddr = physaddr;
++ axfs_xip_records[record_index].virtaddr = virtaddr;
++ axfs_xip_records[record_index].size = size;
++ axfs_xip_records[record_index].pgprot = pgprot;
++ memset(axfs_xip_records[record_index].filename, 0, MAX_FILE_NAME_LEN);
++ namelen = strlen(name);
++ strncpy(axfs_xip_records[record_index].filename, name,
++ (namelen >= MAX_FILE_NAME_LEN) ? MAX_FILE_NAME_LEN-1 : namelen);
++
++ record_index++;
++
++out:
++ up(&record_index_sem);
++ return 0;
++}
++
++static int axfs_xip_record_to_string(struct axfs_xip_record *record,
++ char *buf, int len)
++{
++
++ return snprintf(buf, len,
++ "0x%08lx to 0x%08lx 0x%x 0x%lx %s\n",
++ record->physaddr, record->virtaddr,
++ record->size, record->pgprot, record->filename) ;
++}
++
++
++static unsigned int is_first_line = 1;
++#define PROFILE_HEADINGS "\nXIP: physaddr, virtaddr, size, pgprot, filename\n"
++#define HEADINGS_LEN sizeof(PROFILE_HEADINGS)
++
++static int axfs_xip_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ unsigned long tlen = 0;
++ unsigned long index = record_index;
++ struct axfs_xip_record *record;
++
++ if (down_interruptible(&record_index_sem))
++ return -EINTR;
++
++ if (off >= index) {
++ *eof = 1;
++ is_first_line = 1;
++ goto out;
++ }
++ record = &axfs_xip_records[off];
++
++ if (is_first_line) {
++ strncpy(page+tlen, PROFILE_HEADINGS, HEADINGS_LEN);
++ tlen += HEADINGS_LEN - 1;
++ is_first_line = 0;
++ }
++ tlen += axfs_xip_record_to_string(record, page+tlen, PAGE_SIZE-tlen);
++ *start = (char *)1;
++ out:
++ up(&record_index_sem);
++ return tlen > count ? 0 : tlen;
++}
++
++/* Write to Clear */
++static int axfs_xip_proc_write(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++ if (down_interruptible(&record_index_sem))
++ return -EINTR;
++
++ record_index = 0;
++
++ up(&record_index_sem);
++ return count;
++}
++
++static int __init axfs_xip_proc_profile(void)
++{
++ struct proc_dir_entry *ent;
++ ent = create_proc_entry("axfs_xip", S_IFREG|S_IRUGO|S_IWUSR, NULL);
++ if (!ent) {
++ printk(KERN_ERR "create axfs_xip proc entry failed\n");
++ return -ENOMEM;
++ }
++ ent->read_proc = axfs_xip_proc_read;
++ ent->write_proc = axfs_xip_proc_write;
++ return 0;
++}
++late_initcall(axfs_xip_proc_profile);
++
++#endif /* CONFIG_AXFS_DEBUG */
+--- a/include/linux/axfs_fs.h
++++ b/include/linux/axfs_fs.h
+@@ -42,6 +42,13 @@ int axfs_uncompress_block(void *, int, v
+ int axfs_uncompress_init(void);
+ int axfs_uncompress_exit(void);
+
++#ifdef CONFIG_AXFS_DEBUG
++int axfs_xip_record(unsigned char *name, unsigned long physaddr,
++ unsigned long virtaddr,
++ unsigned int size,
++ unsigned long pgprot);
++#endif
++
+ struct axfs_profiling_data {
+ u64 inode_number;
+ unsigned long count;
diff --git a/series b/series
index 61664d011b8d47..874b96dc6f4ed6 100644
--- a/series
+++ b/series
@@ -112,6 +112,28 @@ patches.pramfs/17-pramfs-makefile-and-kconfig.patch
#############################################################################
+# pramfs
+#
+# Currently broken, so don't enable, but leave here for the placeholder.
+#
+patches.axfs/axfs-kconfigs-and-makefiles.patch
+patches.axfs/axfs-axfs.h.patch
+patches.axfs/axfs-axfs_fs.h.patch
+patches.axfs/axfs-axfs_fs_sb.h.patch
+patches.axfs/axfs-axfs_inode.c.patch
+patches.axfs/axfs-axfs_mtd.c.patch
+patches.axfs/axfs-axfs_physmem.c.patch
+patches.axfs/axfs-axfs_profiling.c.patch
+patches.axfs/axfs-axfs_super.c.patch
+patches.axfs/axfs-axfs_uml.c.patch
+patches.axfs/axfs-axfs_uncompress.c.patch
+patches.axfs/axfs-axfs_bdev.c.patch
+patches.axfs/axfs-xip-debugging-support.patch
+patches.axfs/axfs-add-documentation.patch
+patches.axfs/axfs-mount-as-rootfs.patch
+
+
+#############################################################################
# Marzen board support
#
patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch
@@ -577,3 +599,4 @@ patches.at91/0251-ARM-at91-i2c-change-id-to-let-i2c-at91-work.patch
patches.at91/0252-net-macb-align-ring-buffer-function-with-mainline.patch
patches.at91/0253-net-macb-move-to-circ_buf-macros-and-fix-initial-con.patch
+