O:31:"Drupal\Core\Render\HtmlResponse":8:{s:7:"headers";O:50:"Symfony\Component\HttpFoundation\ResponseHeaderBag":5:{s:23:"*computedCacheControl";a:2:{s:7:"max-age";s:3:"300";s:6:"public";b:1;}s:10:"*cookies";a:0:{}s:14:"*headerNames";a:14:{s:12:"content-type";s:12:"Content-Type";s:13:"cache-control";s:13:"Cache-Control";s:4:"date";s:4:"Date";s:22:"x-drupal-dynamic-cache";s:22:"X-Drupal-Dynamic-Cache";s:4:"link";s:4:"Link";s:15:"x-ua-compatible";s:15:"X-UA-Compatible";s:16:"content-language";s:16:"Content-language";s:22:"x-content-type-options";s:22:"X-Content-Type-Options";s:15:"x-frame-options";s:15:"X-Frame-Options";s:7:"expires";s:7:"Expires";s:13:"last-modified";s:13:"Last-Modified";s:4:"etag";s:4:"ETag";s:4:"vary";s:4:"Vary";s:11:"x-generator";s:11:"X-Generator";}s:10:"*headers";a:14:{s:12:"content-type";a:1:{i:0;s:24:"text/html; charset=UTF-8";}s:13:"cache-control";a:1:{i:0;s:19:"max-age=300, public";}s:4:"date";a:1:{i:0;s:29:"Tue, 14 Nov 2017 11:04:05 GMT";}s:22:"x-drupal-dynamic-cache";a:1:{i:0;s:4:"MISS";}s:4:"link";a:6:{i:0;s:52:"</archives/yaffs-development-notes>; rel="canonical"";i:1;s:27:"</node/39>; rel="shortlink"";i:2;s:51:"</archives/yaffs-development-notes>; rel="revision"";i:3;s:108:"</sites/default/files/css/css_YGKHk3qOgVcGqV_6s_kZUGJkGYQEouHb462Ja18qfRA.css?ozekku>; rel=preload; as=style";i:4;s:108:"</sites/default/files/css/css_6qeLA6GBkZNPHWp9GdQIYovV3tYuKU-ts-HicZ-WeQQ.css?ozekku>; rel=preload; as=style";i:5;s:99:"</sites/default/files/js/js_2l0lF4i9o3aztHULbfajMT_RTqGCEN_lVC8JI48SILw.js>; rel=preload; as=script";}s:15:"x-ua-compatible";a:1:{i:0;s:7:"IE=edge";}s:16:"content-language";a:1:{i:0;s:2:"en";}s:22:"x-content-type-options";a:1:{i:0;s:7:"nosniff";}s:15:"x-frame-options";a:1:{i:0;s:10:"SAMEORIGIN";}s:7:"expires";a:1:{i:0;s:29:"Sun, 19 Nov 1978 05:00:00 GMT";}s:13:"last-modified";a:1:{i:0;s:29:"Tue, 14 Nov 2017 11:04:04 GMT";}s:4:"etag";a:1:{i:0;s:12:""1510657444"";}s:4:"vary";a:1:{i:0;s:6:"Cookie";}s:11:"x-generator";a:1:{i:0;s:33:"Drupal 8 (https://www.drupal.org)";}}s:15:"*cacheControl";a:2:{s:7:"max-age";s:3:"300";s:6:"public";b:1;}}s:10:"*content";s:29690:"<!DOCTYPE html>
<html  lang="en" dir="ltr" prefix="content: http://purl.org/rss/1.0/modules/content/  dc: http://purl.org/dc/terms/  foaf: http://xmlns.com/foaf/0.1/  og: http://ogp.me/ns#  rdfs: http://www.w3.org/2000/01/rdf-schema#  schema: http://schema.org/  sioc: http://rdfs.org/sioc/ns#  sioct: http://rdfs.org/sioc/types#  skos: http://www.w3.org/2004/02/skos/core#  xsd: http://www.w3.org/2001/XMLSchema# ">
  <head>
    <meta charset="utf-8" />
<meta name="title" content="Yaffs (Yaffs1) Development Notes | Yaffs - A Flash File System for embedded use" />
<meta name="news_keywords" content="Flash File System" />
<meta name="description" content="Notes on how to use Yaffs (Yaffs1) and some details of the internal structures - useful if you want to mess with the code. This document is included in the Yaffs1 download." />
<meta name="abstract" content="Yaffs (Yet Another Flash File System) is an open-source file system specifically designed to be fast, robust and suitable for embedded use with NAND and NOR Flash. It is widely used with Linux, RTOSs, or no OS at all, in consumer devices and critical infrastructure. It is available under GNU Public License, GPL, or on commercial terms from Aleph One." />
<meta name="keywords" content="flash File System, flash, file System, flash storage, NAND flash, NOR flash, Yaffs" />
<meta name="Generator" content="Drupal 8 (https://www.drupal.org)" />
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansRegular-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansItalic-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansBold-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifBold-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifBoldItalic-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifItalic-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifRegular-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="stylesheet" href="https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansBoldItalic-fontfacekit/fontyourface-stylesheet.css" media="all" />
<link rel="shortcut icon" href="/sites/default/files/yaffs_favicon.png" type="image/png" />
<link rel="canonical" href="/archives/yaffs-development-notes" />
<link rel="shortlink" href="/node/39" />
<link rel="revision" href="/archives/yaffs-development-notes" />

    <title>Yaffs (Yaffs1) Development Notes | Yaffs - A Flash File System for embedded use</title>
    <link rel="stylesheet" href="/sites/default/files/css/css_YGKHk3qOgVcGqV_6s_kZUGJkGYQEouHb462Ja18qfRA.css?ozekku" media="all" />
<link rel="stylesheet" href="/sites/default/files/css/css_6qeLA6GBkZNPHWp9GdQIYovV3tYuKU-ts-HicZ-WeQQ.css?ozekku" media="all" />

    
<!--[if lte IE 8]>
<script src="/sites/default/files/js/js_VtafjXmRvoUgAzqzYTA3Wrjkx9wcWhjP0G4ZnnqRamA.js"></script>
<![endif]-->

  </head>
  <body class="fontyourface path-node page-node-type-page navbar-is-fixed-top has-glyphicons">
    <a href="#main-content" class="visually-hidden focusable skip-link">
      Skip to main content
    </a>
    <div style="background-color: ; color: " id="environment-indicator">
  
    </div>

              <header class="navbar navbar-default navbar-fixed-top" id="navbar" role="banner">
              <div class="container">
            <div class="navbar-header">
          <div class="region region-navigation">
          <a class="logo navbar-btn pull-left" href="/" title="Home" rel="home">
      <img src="/themes/custom/yaffs/logo.svg" alt="Home" />
    </a>
      
  </div>

                          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
              </div>

                    <div id="navbar-collapse" class="navbar-collapse collapse">
            <div class="region region-navigation-collapsible">
    <nav role="navigation" aria-labelledby="block-mainnavigation-menu" id="block-mainnavigation">
            <h2 class="sr-only" id="block-mainnavigation-menu">Main navigation</h2>

      
              <ul class="menu nav navbar-nav">
                            <li>
        <a href="/" data-drupal-link-system-path="&lt;front&gt;">Home</a>
                  </li>
                        <li>
        <a href="/support" title="Help for Yaffs" data-drupal-link-system-path="node/380">Support</a>
                  </li>
                        <li>
        <a href="/documents" data-drupal-link-system-path="documents">Documents</a>
                  </li>
                        <li>
        <a href="/get-yaffs" data-drupal-link-system-path="node/382">Download</a>
                  </li>
                        <li>
        <a href="/about-us" data-drupal-link-system-path="node/325">About us</a>
                  </li>
                        <li>
        <a href="/contact" data-drupal-link-system-path="node/73">Contact</a>
                  </li>
        </ul>
  


  </nav>
<div class="search-block-form block block-search block-search-form-block" data-drupal-selector="search-block-form" id="block-searchform" role="search">
  
    
      <form action="/search/node" method="get" id="search-block-form" accept-charset="UTF-8">
  <div class="form-item js-form-item form-type-search js-form-type-search form-item-keys js-form-item-keys form-no-label form-group">
      <label for="edit-keys" class="control-label sr-only">Search</label>
  
  
  <div class="input-group"><input title="Enter the terms you wish to search for." data-drupal-selector="edit-keys" class="form-search form-control" placeholder="Search" type="search" id="edit-keys" name="keys" value="" size="15" maxlength="128" data-toggle="tooltip" /><span class="input-group-btn"><button type="submit" value="Search" class="button js-form-submit form-submit btn-primary btn icon-only" name=""><span class="sr-only">Search</span><span class="icon glyphicon glyphicon-search" aria-hidden="true"></span></button></span></div>

  
  
  </div>
<div class="form-actions form-group js-form-wrapper form-wrapper" data-drupal-selector="edit-actions" id="edit-actions"></div>

</form>

  </div>

  </div>

        </div>
                    </div>
          </header>
  
  <div role="main" class="main-container container js-quickedit-main-content">
    <div class="row">

            
            
                  <section class="col-sm-12">

                                      <div class="highlighted">  <div class="region region-highlighted">
      


  </div>
</div>
                  
                
                
                                      
                  
                          <a id="main-content"></a>
            <div class="region region-content">
        <h1 class="page-header"><span property="schema:name">Yaffs (Yaffs1) Development Notes</span>
</h1>

  <article role="article" about="/archives/yaffs-development-notes" typeof="schema:WebPage" class="page is-sticky full clearfix">

  
      <span property="schema:name" content="Yaffs (Yaffs1) Development Notes" class="hidden"></span>


  
  <div class="content">
    
            <div property="schema:text" class="field field--name-body field--type-text-with-summary field--label-hidden field--item">
<p><em>These notes relate to Yaffs1. Yaffs version 2, or Yaffs2, is the current version of Yaffs. While many of the details below remain the same, you can find up to date information split between the How Yaffs Works, Yaffs Tuning and Yaffs Direct documents.</em></p>
<p>&nbsp;</p>
<h2>Build options</h2>
<p>Yaffs1 can be built as either a kernel module (ie. a Linux file system) or as an application.</p>
<p>Of course the goal is to build Yaffs as a file system running on top of real NAND flash, but yaffs can be built to run on a RAM emulation layer for in-kernel testing without NAND flash in the system.</p>
<p>Building as an application allows the yaffs_guts algorithms to be tested/debugged in a more friendly debugging environment. The test harness is in yaffsdev.c</p>
<h3>Trying it out</h3>
<p>Yaffs1 can be built to run with either mtd or RAM emulation, or both. The file system that interfaces to mtd is called <strong>yaffs</strong>, the file system that uses internal ram is called <strong>yaffsram</strong>. Yaffs1 simultaneously supports both if they are enabled.</p>
<ol>
<li>
<p>Hack the Makefile and change the KERNELDIR define to your kernel directory.</p>
 </li>
<li>
<p>If you don't have mtd support in your kernel, then you might need to turn off USE_MTD otherwise the Yaffs module might not load.</p>
 </li>
<li>
<p>Type <strong>make clean; make</strong> to build yaffs</p>
 </li>
<li>
<p>Load Yaffs as a module by typing <strong>/sbin/insmod yaffs.o</strong> (ya gotta be root!).</p>
 </li>
<li>
<p>Create a mount point eg. <strong>mkdir /mnt/y</strong></p>
 </li>
<li>
<p>To mount the RAM emulation version of yaffs, <strong>mount -t yaffsram none /mnt/y</strong></p>
 </li>
<li>
<p>Alternatively, to mount the mtd version of yaffs, <strong>mount -t yaffs /dev/mtd0 /mnt/y</strong></p>
 </li>
</ol>
<p><br />
&nbsp;</p>
<h3>Yaffs1 Data structures</h3>
<p>All data types are defined in yaffs_guts.h</p>
<p>Yaffs1 uses the following major objects:</p>
<ul>
<li>
<p>yaffs_Object: A yaffs_Object can be a file, directory, symlink or hardlink. The yaffs_Objects "know" about their corresponding yaffs_ObjectHeader in NAND and the data for that object. yaffs_Objects also bind together the directory structure as follows:</p>
 </li>
<li>
<p>parent: pointer to the yaffs_Object that is a parent of this yaffs_Object in the directory structure.</p>
 </li>
<li>
<p>siblings: this field is used to link together a list of all the yaffs_Objects in the same directory.</p>
 </li>
<li>
<p>children: if the object is a directory, then children holds the head of the list of objects in the directory.</p>
 </li>
<li>
<p>yaffs_Tnode: yaffs_Tnodes form a tree structure that speeds up the search for data chunks in a file. As the file grows in size, the levels increase. The Tnodes are a constant size (32 bytes). Level 0 (ie the lowest level) comprise 16 2-byte entries giving an index used to search for the chunkId. Tnodes at other levels comprise 8 4-byte pointer entries to other tnodes lower in the tree.</p>
 </li>
<li>
<p>yaffs_Device: this holds the device context and is in some ways analogous to the VFS superblock. It stores the data used to access the mtd as well as function pointers to access the NAND data.</p>
 </li>
</ul>
<p>The Tnodes and Objects are allocated in groups to reduce memory allocation/freeing overheads. Freed up tnodes and objects are kept in a free list and re-used.</p>
<h3>yaffs_Object</h3>
<p>struct yaffs_ObjectStruct</p>
<p>{</p>
<p>__u8 fake:1; // A fake object has no presence on NAND.</p>
<p>__u8 renameAllowed:1; // Are we allowed to rename it?</p>
<p>__u8 unlinkAllowed:1; // Are we allowed to unlink it?</p>
<p>__u8 dirty:1; // the object needs to be written to flash</p>
<p>__u8 valid:1; // When the file system is being loaded up, this</p>
<p>// object might be created before the data</p>
<p>// is available (ie. file data records appear before the header).</p>
<p>__u8 serial; // serial number of chunk in NAND. Store here so we don't have to</p>
<p>// read back the old one to update.</p>
<p>__u16 sum; // sum of the name to speed searching</p>
<p>struct yaffs_DeviceStruct *myDev; // The device I'm on</p>
<p>struct list_head hashLink; // list of objects in this hash bucket</p>
<p>struct list_head hardLinks; // all the equivalent hard linked objects</p>
<p>// live on this list</p>
<p>// directory structure stuff</p>
<p>struct yaffs_ObjectStruct *parent; //my parent directory</p>
<p>struct list_head siblings; // siblings in a directory</p>
<p>// also used for linking up the free list</p>
<p>// Where's my data in NAND?</p>
<p>int chunkId; // where it lives</p>
<p>__u32 objectId; // the object id value</p>
<p>__u32 st_mode; // protection</p>
<p>__u32 st_uid; // user ID of owner</p>
<p>__u32 st_gid; // group ID of owner</p>
<p>__u32 st_atime; // time of last access</p>
<p>__u32 st_mtime; // time of last modification</p>
<p>__u32 st_ctime; // time of last change</p>
<p>yaffs_ObjectType variantType;</p>
<p>yaffs_ObjectVariant variant;</p>
<p>};</p>
<p><br />
&nbsp;</p>
<p>Obvious stuff skipped....</p>
<p>fake, renameAllowed, unlinkAllowed are special flags for handling "fake" objects which live in the file system but do not live on NAND. Currently there are only two such objects: the root object and the lost+found directory. None of these may be renamed or unlinked.</p>
<p>serial, sum: see yaffs_ObjectHeader.</p>
<p>dirty indicates that the object's contents has changed and a new yaffs_ObjectHeader must be written to flash.</p>
<p>valid indicates that the object has been loaded up. This is only used during scanning (yaffs_Scan()) since we can know of an object's existance - and thus need to create the object header - before we encounter the associated yaffs_ObjectHeader.</p>
<p>hashlink is a list of Objects in the same hash bucket.</p>
<p>The four variants hold extra info:</p>
<p>Files hold the file size and the top level and pointer to the tnode tree for the file.</p>
<p>Directories hold a list of children objects.</p>
<p>Symlinks hold a pointer to the alias string. This is probably inefficient, but that probably does not matter since we don't expect to see many of these.</p>
<p>Hardlinks hold information to identify the equivalent object.</p>
<p><br />
&nbsp;</p>
<h3>File structure (tnodes)</h3>
<p>File structures are done with a tiered indexing structure</p>
<p><br />
&nbsp;</p>
<p><img alt="" height="294" src="http://www.aleph1.co.uk/yaffs/sv9349341.gif" width="491" /><br />
<br />
&nbsp;</p>
<p>The file structure is maintained by a tree structure. Depending where it is in the tree, each tree node (<strong><em>tnode</em></strong>) (the blue/things) holds either:</p>
<ul>
<li>
<p>.... if it is at the lowest level, then 16 __u16s which identify the page.</p>
 </li>
<li>
<p>.... if it is at a higher level (ie an internal tnode), then 8 pointers to lowest-level tnodes.</p>
 </li>
</ul>
<p>When the file starts out, it is assigned only one low-level tnode. When the file expands past what a single tnode can hold, then it is assigned a second tnode and an internal node is added to point to the two tnodes. As the file grows, more low-level tnodes and high level tnodes are added.</p>
<p>Traversing the tnode tree to find a particular page in a file is quite simple: each internal tnode is selected from by using 3 bits of the page offset in the file. The level 0 page resolves 4 bits.</p>
<p>For example, finding page 0x235 (ie. the one starting at file position 0x46800 would proceed as follows:</p>
<p>0x235 is 0000001000110101, partitioned as follows. 000.000.100.011.0101</p>
<p>Level</p>
<p>Bits</p>
<p>Selected value</p>
<table>
<tbody>
 <tr>
 </tr>
 <tr>
  <td>
  <p>3 or more if they exist</p>
   </td>
  <td>
  <p>&gt;= 10</p>
   </td>
  <td>
  <p>Zero</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>2</p>
   </td>
  <td>
  <p>9 to 7</p>
   </td>
  <td>
  <p>100 binary = 4</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>1</p>
   </td>
  <td>
  <p>6 to 4</p>
   </td>
  <td>
  <p>011 binary = 3</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>0</p>
   </td>
  <td>
  <p>3 to 0</p>
   </td>
  <td>
  <p>0101 binary = 5</p>
   </td>
 </tr>
</tbody>
</table>
<p><br />
Free tnodes are stored in a list. When the list is exhausted, more are allocated.</p>
<p>Each tnode takes 32 bytes. Each file needs at least one level 0 tnode. How many do we need? A full 16MB file system needs at least 16MB/512/16 = 2000 level zero tnodes. More for internal tnodes. More for files smaller than optimal.</p>
<p>The tree grows as required. When the file is resized to a smaller size then it is pruned.</p>
<h3>NAND data</h3>
<p>Data is stored on NAND in "chunks". Currently each chunk is the same size as a NAND flash page (ie. 512 bytes + 16 byte spare). In the future we might decide to allow for different chunk sizes. Chunks can hold either:</p>
<ul>
<li>
<p>A yaffs_ObjectHeader. This is the way a yaffs_Object gets stored on NAND.</p>
 </li>
<li>
<p>A chunk of file data.</p>
 </li>
</ul>
<p>The 16 byte spare area contains:</p>
<ul>
<li>
<p>8 bytes of tags,</p>
 </li>
<li>
<p>6 bytes of ECC data</p>
 </li>
<li>
<p>1 byte block status (used to identify damaged blocks)</p>
 </li>
<li>
<p>1 byte data status (currently unused).</p>
 </li>
</ul>
<p>The tags are made up as follows:</p>
<p>typedef struct</p>
<p>{</p>
<p>unsigned chunkId:20; //chunk number in file</p>
<p>unsigned serialNumber:2; //serial number for chunk</p>
<p>unsigned byteCount:10; //number of bytes of data used in this chunk</p>
<p>unsigned objectId:18; //the object id that this chunk belongs to.</p>
<p>unsigned ecc:12; //ECC on tags</p>
<p>unsigned unusedStuff:2; //unused</p>
<p>} yaffs_Tags;</p>
<p>&nbsp;</p>
<p>A chunkId of zero indicates that this chunk holds a yaffs_ObjectHeader. A non zero value indicates that this is a data chunk and the position of the chunk in the file (ie. the first chunk - at offset 0 - has chunkId 1). See yaffs_guts.c:yaffs_Scan () to see how this is done.</p>
<p>When a chunk is repalced (eg. file details changed or a part of a file was overwritten), the new chunk is written before the old chunk is deleted. This means that we don't lose data if there is a power loss after the new chunk is created but before the old one is discarded, but it does mean that we can encounter the situation where we find both the old and the new chunks in flash. The serialNumber is incremented each time the chunk is written. 2 bits is sufficient to resolve any ambiguity.</p>
<p>bytecount applies only to data chunks and tells how many of the data bytes are valid.</p>
<p>objectId says which object this chunk belongs to.</p>
<p>ecc is used to perform error correction on the tags. Another ecc field is used to error correct the data.</p>
<h3>yaffs_ObjectHeader</h3>
<p>typedef struct</p>
<p>{</p>
<p>yaffs_ObjectType type;</p>
<p>&nbsp;</p>
<p>// Apply to everything</p>
<p>int parentObjectId;</p>
<p>__u16 sum; // checksum of name</p>
<p>char name[YAFFS_MAX_NAME_LENGTH + 1];</p>
<p>&nbsp;</p>
<p>// Thes following apply to directories, files, symlinks - not hard links</p>
<p>__u32 st_mode; // protection</p>
<p>__u32 st_uid; // user ID of owner</p>
<p>__u32 st_gid; // group ID of owner</p>
<p>__u32 st_atime; // time of last access</p>
<p>__u32 st_mtime; // time of last modification</p>
<p>__u32 st_ctime; // time of last change</p>
<p>&nbsp;</p>
<p>// File size applies to files only</p>
<p>int fileSize;</p>
<p>&nbsp;</p>
<p>// Equivalent object id applies to hard links only.</p>
<p>int equivalentObjectId;</p>
<p>// alias only applies to symlinks</p>
<p>char alias[YAFFS_MAX_ALIAS_LENGTH + 1];</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>} yaffs_ObjectHeader;</p>
<p>&nbsp;</p>
<p>A yaffs_ObjectHeader is stored in NAND for every yaffs_Object.</p>
<p>type holds the type of yaffs_Object (file,directory,hardlink or symlink).</p>
<p>parentObject is the objectId of this object's parent. name holds the object's name. Together these form the directory structure of the file system. Also worth mention is sum. This is a "checksum" on the name which speeds directory searching (ie. when searching the directory we only compare the name for those entries where sum matches).</p>
<p>Obvious stuff skipped....</p>
<p>equivalentObjectId is used by hardlinks. A hardlink to an object uses this field to specify the object that this links to. This way of doing things is a bit different than the normal Linux way of doing things (ie. keeping the links distinct from the inode) but is simpler and uses less space except for a few corner cases with hardlinks.</p>
<p>alias is used by symlinks to hold the symlink alias string. This limits the size of the symlink alias. In future we should expand Yaffs1 to use data chunks to store aliases too long to fit into the yaffs_ObjectHeader.</p>
<h3>NAND Interface</h3>
<p>All NAND access is performed via four functions pointed to by yaffs_Device. At the moment a chunk is a page.</p>
<ul>
<li>
<p>int WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare)</p>
 </li>
<li>
<p>int ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);</p>
 </li>
<li>
<p>int EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND);</p>
 </li>
<li>
<p>int InitialiseNAND(struct yaffs_DeviceStruct *dev);</p>
 </li>
</ul>
<p>In the Readxxx and Writexxx functions, the data and/or spare pointers may be NULL in which case these data transfers are ignored.</p>
<p>A quick note about NAND:</p>
<ul>
<li>
<p>NAND is not random access, but page oriented. Thus, we do all reads &amp; writes in pages.</p>
 </li>
<li>
<p>Each NAND page holds 512 bytes of data and 16 "spare" bytes. Yaffs structures the spare area with tags used to identify what is stored in the data area. There are 32 such pages to a block.</p>
 </li>
<li>
<p>NAND writes will only change 1 bits to 0. eg. if a byte holds 10110011 and you write 11011010 to it you will get the logical and of the two values: 10010010. The only way to get 1s again is to erase the entire block.</p>
 </li>
<li>
<p>You may only write to a page a few times before erasing the entire block. Yaffs lives within these limitations. Each page only gets written to twice (once when written and once when discarded).</p>
 </li>
<li>
<p>ECC is normally used with NAND to correct for single bit errors. Yaffs1 applies the ECC itself, so the MTD should not do this.</p>
 </li>
<li>
<p>The current mtd interfaces are not particularly well suited to Yaffs1 and we will address the issue with the mtd group. (The mtd interface does not support page-oriented read/write which Yaffs1 would prefer).</p>
 </li>
</ul>
<h3>mkyaffs</h3>
<p>mkyaffs is the tool to format a NAND mtd to be used for Yaffs1. This is quite simple, just erase all the undamaged blocks. Yaffs1 treats erased blocks as free (empty) space.</p>
<h2>Expected performance</h2>
<p>The following numbers should give an indication of the performance we should expect from Yaffs1.</p>
<p>As an example, I'll use the following numbers. Since the hardware is capable of 50ns read/write, these numbers allow for some other ovberheads. Clearly though, the performance can be degraded in various ways.</p>
<p>Seek</p>
<p>10uS/page</p>
<table>
<tbody>
 <tr>
 </tr>
 <tr>
  <td>
  <p>Read</p>
   </td>
  <td>
  <p>100nS/byte</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Write</p>
   </td>
  <td>
  <p>100nS/byte</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Program</p>
   </td>
  <td>
  <p>200uS/page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Erase</p>
   </td>
  <td>
  <p>2mS/block</p>
   </td>
 </tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>From this we can derive some higher-level numbers:</p>
<p>Operation</p>
<p>Time</p>
<p>Calculation</p>
<table>
<tbody>
 <tr>
 </tr>
 <tr>
  <td>
  <p>Read spare</p>
   </td>
  <td>
  <p>12uS</p>
   </td>
  <td>
  <p>seek + 16 * read</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Read page</p>
   </td>
  <td>
  <p>63 uS</p>
   </td>
  <td>
  <p>seek + 528 * read</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Write page</p>
   </td>
  <td>
  <p>326 uS</p>
   </td>
  <td>
  <p>seek + 528 * write + program + read page (for verification)</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Discard page</p>
   </td>
  <td>
  <p>212 uS</p>
   </td>
  <td>
  <p>seek + 16 * write + program</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Overwrite page</p>
   </td>
  <td>
  <p>538 uS</p>
   </td>
  <td>
  <p>write page + discard page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Erase overhead per page</p>
   </td>
  <td>
  <p>63uS</p>
   </td>
  <td>
  <p>erase/32</p>
   </td>
 </tr>
</tbody>
</table>
<p><br />
&nbsp;</p>
<p>From this we can infer the following flash access times:</p>
<p>Operation</p>
<p>Time</p>
<p>Calculation</p>
<table>
<tbody>
 <tr>
 </tr>
 <tr>
  <td>
  <p>Read 1MB file</p>
   </td>
  <td>
  <p>0.13s (about 7.5 MB/s)</p>
   </td>
  <td>
  <p>2000 * read page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Write 1MB (clean system)</p>
   </td>
  <td>
  <p>0.53s (about 1.8 MB/s)</p>
   </td>
  <td>
  <p>2000 * write page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Overwrite 1MB file (no gc)</p>
   </td>
  <td>
  <p>1.08s (about 0.9MB/s)</p>
   </td>
  <td>
  <p>2000 * overwrite page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Overwrite 1MB with 50% gc</p>
   </td>
  <td>
  <p>2.4s (about 0.4 MB/s)</p>
   </td>
  <td>
  <p>2000 * overwrite page + 2000 * page copy (== overwrite page) + 4000 * erase overhead</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Delete 1MB file</p>
   </td>
  <td>
  <p>0.43s (about 2.2 MB/s)</p>
   </td>
  <td>
  <p>2000 * discard page</p>
   </td>
 </tr>
 <tr>
  <td>
  <p>Delete 1MB file with 50% gc</p>
   </td>
  <td>
  <p>0.49s (about 2.0MB/s)</p>
   </td>
  <td>
  <p>2000 * discard page + 1000 * erase overhead</p>
   </td>
 </tr>
</tbody>
</table>
<p>&nbsp;</p>
</div>
      
  </div>

</article>


  </div>

              </section>

                </div>
  </div>

      <footer class="footer container" role="contentinfo">
        <div class="primary_footer row">
            <div class="col-sm-3">
                  <div class="region region-footer-col1">
    <section id="block-yaffs-block-6" class="block block-block-content block-block-content6c2d4b45-4dba-4b2d-8b9f-76701bf27533 clearfix">
  
    

      
            <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item">
<ul class="fa-ul">
<li><i class="fa-li fa fa-phone"></i>+44 (0)1223 811679</li>
<li><i class="fa-li fa fa-envelope"></i><a href="denied:mailto:info@aleph1.co.uk?Subject=Website contact" target="_top">info@aleph1.co.uk</a></li>
</ul>
</div>
      
  </section>


  </div>

            </div>
            <div class="col-sm-3">
                
            </div>
            <div class="col-sm-3">
                
            </div>
            <div class="col-sm-3">
                  <div class="region region-footer-col4">
    <section id="block-footerlegal" class="block block-block-content block-block-content78ab593d-35b6-4772-a141-30216e7fcbb2 clearfix">
  
    

      
            <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item">
<p class="text-align-right">&nbsp;<a href="/legal">Legal &amp; Cookies</a></p>
</div>
      
  </section>

<section id="block-cookieinfo" class="block block-block-content block-block-content4848c58d-90df-4819-81d8-0f9568eeeaac clearfix">
  
    

      
            <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item">
<p class="text-align-justify"><br />
We use <a href="/legal">cookies on this site</a>. By using it, you are giving us consent to set cookies.</p>
</div>
      
  </section>


  </div>

            </div>
        </div>
        <div class = "secondary_footer row">
            <div class="col-sm-12">
                <div class="region region-footer">
    <nav role="navigation" aria-labelledby="block-yaffs-account-menu-menu" id="block-yaffs-account-menu">
            <h2 class="sr-only" id="block-yaffs-account-menu-menu">User account menu</h2>

      
              <ul class="menu nav navbar-nav navbar-right">
                            <li>
        <a href="/user/login" data-drupal-link-system-path="user/login">Log in</a>
                  </li>
        </ul>
  


  </nav>

  </div>

            </div>
        </div>
    </footer>
  
    
    <script type="application/json" data-drupal-selector="drupal-settings-json">{"path":{"baseUrl":"\/","scriptPath":null,"pathPrefix":"","currentPath":"node\/39","currentPathIsAdmin":false,"isFront":false,"currentLanguage":"en"},"pluralDelimiter":"\u0003","bootstrap":{"forms_has_error_value_toggle":1,"modal_animation":1,"modal_backdrop":"true","modal_keyboard":1,"modal_show":1,"modal_size":"","popover_enabled":1,"popover_animation":1,"popover_container":"body","popover_content":"","popover_delay":"0","popover_html":0,"popover_placement":"right","popover_selector":"","popover_title":"","popover_trigger":"click","popover_trigger_autoclose":1,"tooltip_enabled":1,"tooltip_animation":1,"tooltip_container":"body","tooltip_delay":"0","tooltip_html":0,"tooltip_placement":"auto left","tooltip_selector":"","tooltip_trigger":"hover"},"ajaxTrustedUrl":{"\/search\/node":true},"user":{"uid":0,"permissionsHash":"aa7fc4c8fb40c7a8665ccd12fea07926dff0f59b9ee3346bc513c6399bee5b01"}}</script>
<script src="/sites/default/files/js/js_2l0lF4i9o3aztHULbfajMT_RTqGCEN_lVC8JI48SILw.js"></script>

  </body>
</html>
";s:10:"*version";s:3:"1.0";s:13:"*statusCode";i:200;s:13:"*statusText";s:2:"OK";s:10:"*charset";N;s:23:"*cacheabilityMetadata";O:35:"Drupal\Core\Cache\CacheableMetadata":3:{s:16:"*cacheContexts";a:18:{i:0;s:28:"languages:language_interface";i:1;s:5:"route";i:2;s:32:"route.menu_active_trails:account";i:3;s:29:"route.menu_active_trails:main";i:4;s:30:"route.menu_active_trails:tools";i:5;s:5:"theme";i:6;s:8:"timezone";i:7;s:3:"url";i:8;s:8:"url.path";i:9;s:17:"url.path.is_front";i:10;s:15:"url.path.parent";i:11;s:30:"url.query_args:_wrapper_format";i:12;s:4:"user";i:13;s:21:"user.node_grants:view";i:14;s:16:"user.permissions";i:15;s:10:"user.roles";i:16;s:20:"user.roles:anonymous";i:17;s:24:"user.roles:authenticated";}s:12:"*cacheTags";a:50:{i:0;s:16:"block_content:18";i:1;s:16:"block_content:23";i:2;s:15:"block_content:7";i:3;s:18:"block_content_view";i:4;s:10:"block_view";i:5;s:32:"config:block.block.choosingyaffs";i:6;s:29:"config:block.block.cookieinfo";i:7;s:32:"config:block.block.downloadyaffs";i:8;s:30:"config:block.block.footerlegal";i:9;s:39:"config:block.block.frontimagehighlight2";i:10;s:32:"config:block.block.frontpagehero";i:11;s:39:"config:block.block.frontpageprimeryaffs";i:12;s:33:"config:block.block.mainnavigation";i:13;s:35:"config:block.block.mainnavigation_2";i:14;s:29:"config:block.block.searchform";i:15;s:31:"config:block.block.sitebranding";i:16;s:66:"config:block.block.views_block__highlighted_yaffs_features_block_1";i:17;s:66:"config:block.block.views_block__yaffs_admin_recent_content_block_1";i:18;s:66:"config:block.block.views_block__yaffs_documents_highlights_block_1";i:19;s:56:"config:block.block.views_block__yaffs_user_logos_block_1";i:20;s:37:"config:block.block.yaffs_account_menu";i:21;s:33:"config:block.block.yaffs_block_10";i:22;s:32:"config:block.block.yaffs_block_5";i:23;s:32:"config:block.block.yaffs_block_6";i:24;s:32:"config:block.block.yaffs_block_8";i:25;s:32:"config:block.block.yaffs_block_9";i:26;s:36:"config:block.block.yaffs_breadcrumbs";i:27;s:32:"config:block.block.yaffs_content";i:28;s:29:"config:block.block.yaffs_help";i:29;s:36:"config:block.block.yaffs_local_tasks";i:30;s:33:"config:block.block.yaffs_messages";i:31;s:35:"config:block.block.yaffs_page_title";i:32;s:32:"config:block.block.yaffs_user_21";i:33;s:31:"config:block.block.yaffsinspace";i:34;s:17:"config:block_list";i:35;s:24:"config:color.theme.yaffs";i:36;s:30:"config:filter.format.full_html";i:37;s:29:"config:filter.format.raw_html";i:38;s:22:"config:search.settings";i:39;s:26:"config:system.menu.account";i:40;s:23:"config:system.menu.main";i:41;s:24:"config:system.menu.tools";i:42;s:18:"config:system.site";i:43;s:26:"config:user.role.anonymous";i:44;s:13:"http_response";i:45;s:7:"node:39";i:46;s:9:"node_view";i:47;s:8:"rendered";i:48;s:6:"user:0";i:49;s:6:"user:1";}s:14:"*cacheMaxAge";i:-1;}s:14:"*attachments";a:5:{s:7:"library";a:9:{i:0;s:14:"core/html5shiv";i:1;s:11:"system/base";i:2;s:15:"bootstrap/theme";i:3;s:20:"yaffs/global-styling";i:4;s:23:"yaffs/bootstrap-scripts";i:5;s:19:"yaffs/yaffs-helpers";i:6;s:17:"bootstrap/popover";i:7;s:17:"bootstrap/tooltip";i:8;s:50:"environment_indicator/drupal.environment_indicator";}s:9:"html_head";a:22:{i:0;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:5:"title";s:7:"content";s:79:"Yaffs (Yaffs1) Development Notes | Yaffs - A Flash File System for embedded use";}}i:1;s:5:"title";}i:1;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:13:"news_keywords";s:7:"content";s:17:"Flash File System";}}i:1;s:13:"news_keywords";}i:2;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:11:"description";s:7:"content";s:172:"Notes on how to use Yaffs (Yaffs1) and some details of the internal structures - useful if you want to mess with the code. This document is included in the Yaffs1 download.";}}i:1;s:11:"description";}i:3;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:8:"abstract";s:7:"content";s:352:"Yaffs (Yet Another Flash File System) is an open-source file system specifically designed to be fast, robust and suitable for embedded use with NAND and NOR Flash. It is widely used with Linux, RTOSs, or no OS at all, in consumer devices and critical infrastructure. It is available under GNU Public License, GPL, or on commercial terms from Aleph One.";}}i:1;s:8:"abstract";}i:4;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:8:"keywords";s:7:"content";s:82:"flash File System, flash, file System, flash storage, NAND flash, NOR flash, Yaffs";}}i:1;s:8:"keywords";}i:5;a:2:{i:0;a:3:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:1:{s:7:"charset";s:5:"utf-8";}s:7:"#weight";i:-1000;}i:1;s:24:"system_meta_content_type";}i:6;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:9:"Generator";s:7:"content";s:33:"Drupal 8 (https://www.drupal.org)";}}i:1;s:21:"system_meta_generator";}i:7;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:15:"MobileOptimized";s:7:"content";s:5:"width";}}i:1;s:15:"MobileOptimized";}i:8;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:16:"HandheldFriendly";s:7:"content";s:4:"true";}}i:1;s:16:"HandheldFriendly";}i:9;a:2:{i:0;a:2:{s:4:"#tag";s:4:"meta";s:11:"#attributes";a:2:{s:4:"name";s:8:"viewport";s:7:"content";s:37:"width=device-width, initial-scale=1.0";}}i:1;s:8:"viewport";}i:10;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:125:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansRegular-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1151";}i:11;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:124:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansItalic-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1152";}i:12;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:122:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansBold-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1153";}i:13;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:123:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifBold-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1149";}i:14;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:129:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifBoldItalic-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1150";}i:15;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:125:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifItalic-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1148";}i:16;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:126:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSerifRegular-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1147";}i:17;a:2:{i:0;a:3:{s:5:"#type";s:8:"html_tag";s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:10:"stylesheet";s:4:"href";s:128:"https://yaffs.net/sites/default/files/fontyourface/fontsquirrel/LiberationSansBoldItalic-fontfacekit/fontyourface-stylesheet.css";s:5:"media";s:3:"all";}}i:1;s:21:"fontsquirrel-api-1154";}i:18;a:2:{i:0;a:2:{s:4:"#tag";s:4:"link";s:11:"#attributes";a:3:{s:3:"rel";s:13:"shortcut icon";s:4:"href";s:38:"/sites/default/files/yaffs_favicon.png";s:4:"type";s:9:"image/png";}}i:1;s:67:"html_head_link:shortcut icon:/sites/default/files/yaffs_favicon.png";}i:19;a:2:{i:0;a:2:{s:4:"#tag";s:4:"link";s:11:"#attributes";a:2:{s:3:"rel";s:9:"canonical";s:4:"href";s:33:"/archives/yaffs-development-notes";}}i:1;s:58:"html_head_link:canonical:/archives/yaffs-development-notes";}i:20;a:2:{i:0;a:2:{s:4:"#tag";s:4:"link";s:11:"#attributes";a:2:{s:3:"rel";s:9:"shortlink";s:4:"href";s:8:"/node/39";}}i:1;s:33:"html_head_link:shortlink:/node/39";}i:21;a:2:{i:0;a:2:{s:4:"#tag";s:4:"link";s:11:"#attributes";a:2:{s:3:"rel";s:8:"revision";s:4:"href";s:33:"/archives/yaffs-development-notes";}}i:1;s:57:"html_head_link:revision:/archives/yaffs-development-notes";}}s:12:"placeholders";a:0:{}s:14:"drupalSettings";a:5:{s:4:"path";a:7:{s:7:"baseUrl";s:1:"/";s:10:"scriptPath";N;s:10:"pathPrefix";s:0:"";s:11:"currentPath";s:7:"node/39";s:18:"currentPathIsAdmin";b:0;s:7:"isFront";b:0;s:15:"currentLanguage";s:2:"en";}s:15:"pluralDelimiter";s:1:"";s:9:"bootstrap";a:25:{s:28:"forms_has_error_value_toggle";i:1;s:15:"modal_animation";i:1;s:14:"modal_backdrop";s:4:"true";s:14:"modal_keyboard";i:1;s:10:"modal_show";i:1;s:10:"modal_size";s:0:"";s:15:"popover_enabled";i:1;s:17:"popover_animation";i:1;s:17:"popover_container";s:4:"body";s:15:"popover_content";s:0:"";s:13:"popover_delay";s:1:"0";s:12:"popover_html";i:0;s:17:"popover_placement";s:5:"right";s:16:"popover_selector";s:0:"";s:13:"popover_title";s:0:"";s:15:"popover_trigger";s:5:"click";s:25:"popover_trigger_autoclose";i:1;s:15:"tooltip_enabled";i:1;s:17:"tooltip_animation";i:1;s:17:"tooltip_container";s:4:"body";s:13:"tooltip_delay";s:1:"0";s:12:"tooltip_html";i:0;s:17:"tooltip_placement";s:9:"auto left";s:16:"tooltip_selector";s:0:"";s:15:"tooltip_trigger";s:5:"hover";}s:14:"ajaxTrustedUrl";a:1:{s:12:"/search/node";b:1;}s:4:"user";a:2:{s:3:"uid";i:0;s:15:"permissionsHash";s:64:"aa7fc4c8fb40c7a8665ccd12fea07926dff0f59b9ee3346bc513c6399bee5b01";}}s:11:"http_header";a:3:{i:0;a:3:{i:0;s:4:"Link";i:1;s:52:"</archives/yaffs-development-notes>; rel="canonical"";i:2;b:0;}i:1;a:3:{i:0;s:4:"Link";i:1;s:27:"</node/39>; rel="shortlink"";i:2;b:0;}i:2;a:3:{i:0;s:4:"Link";i:1;s:51:"</archives/yaffs-development-notes>; rel="revision"";i:2;b:0;}}}}