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

The source (bload.c) specified in Appendix section 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. Appendix
===========

/*
 * Copyright 2006 Sony Corporation
 *
 * bload.c
 *    load an image file to memory
 * Usage:
 *    bload FILE PHYSADDR
 *
 *      FILE: file pathname
 *      PHYSADDR: address, eg: 0x80000000
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

#define PAGEMASK 0xfff
#define BUFFER_SIZE 16384

int main(int argc, char **argv)
{
	const char *file;
        unsigned long physaddr, page, offset, end, pagedsize;
        struct stat statbuf;
        int ans, infd, memfd, nread;
        off_t size;
        void *mapped;
        char *ptr;
        static char buf[BUFFER_SIZE];

        if (argc != 3) {
                fprintf(stderr, "usage: %s FILE PHYSADDR\n", argv[0]);
                exit(1);
        }
        file = argv[1];
        physaddr = strtoul(argv[2], NULL, 0);

        ans = stat(file, &statbuf);
        if (ans < 0) {
                perror("bload: stat");
                exit(1);
        }
        size = statbuf.st_size;

        page = physaddr & ~PAGEMASK;
        offset = physaddr & PAGEMASK;
        end = offset + size;
        pagedsize = (end + PAGEMASK) & ~PAGEMASK;
        printf("filesize=0x%lx addr=0x%lx pagedsize=0x%lx\n",
               size, physaddr, pagedsize);

        infd = open(file, O_RDONLY);
        if (infd < 0) {
                perror("bload: open(file)");
                exit(1);
        }

        memfd = open("/dev/mem", O_RDWR|O_SYNC);
        if (memfd < 0) {
                perror("bload: open(/dev/mem)");
                exit(1);
        }
        printf("pagedsize : %d , page %d \n", pagedsize,page);
        mapped = mmap(NULL, pagedsize, PROT_WRITE, MAP_SHARED,
                      memfd, page);
        if (mapped == MAP_FAILED) {
                perror("bload: mmap");
                exit(1);
        }
        ptr = (char *)mapped + offset;
        while ((nread = read(infd, buf, BUFFER_SIZE)) > 0) {
                memcpy(ptr, buf, nread);
                ptr += nread;
        }
        if (nread < 0) {
                perror("bload: read");
                exit(1);
        }

        if (munmap(mapped, pagedsize) < 0) {
                perror("bload: munmap");
                exit(1);
        }
        close(memfd);
        close(infd);
        return 0;
}
