support for per-partition fs_type

Include the recovery.fstab file in the recovery image.  Remove the
global fs_type and partition_type values from the target-files
key/value dict, and parse the recovery.fstab file instead to find
types for each partition.

(Cherrypicked from gingerbread w/some edits to resolve conflicts.)

Change-Id: Ic3ed85ac5672d8fe20280dacf43d5b82053311bb
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 328700f..a61ecf5 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -21,6 +21,10 @@
   """Class to generate scripts in the 'edify' recovery script language
   used from donut onwards."""
 
+  # map recovery.fstab's fs_types to mount/format "partition types"
+  PARTITION_TYPES = { "yaffs2": "MTD", "mtd": "MTD",
+                      "ext4": "EMMC", "emmc": "EMMC" }
+
   def __init__(self, version, info):
     self.script = []
     self.mounts = set()
@@ -131,15 +135,22 @@
     available on /cache."""
     self.script.append("assert(apply_patch_space(%d));" % (amount,))
 
-  def Mount(self, what, mount_point):
-    """Mount the given 'what' at the given path.  'what' should be a
-    partition name for an MTD partition, or a block device for
-    anything else."""
-    what = self.info.get("partition_path", "") + what
-    self.script.append('mount("%s", "%s", "%s", "%s");' %
-                       (self.info["fs_type"], self.info["partition_type"],
-                        what, mount_point))
-    self.mounts.add(mount_point)
+  def Mount(self, mount_point):
+    """Mount the partition with the given mount_point."""
+    fstab = self.info.get("fstab", None)
+    if fstab:
+      p = fstab[mount_point]
+      self.script.append('mount("%s", "%s", "%s", "%s");' %
+                         (p.fs_type, self.PARTITION_TYPES[p.fs_type],
+                          p.device, p.mount_point))
+      self.mounts.add(p.mount_point)
+    else:
+      what = mount_point.lstrip("/")
+      what = self.info.get("partition_path", "") + what
+      self.script.append('mount("%s", "%s", "%s", "%s");' %
+                         (self.info["fs_type"], self.info["partition_type"],
+                          what, mount_point))
+      self.mounts.add(mount_point)
 
   def UnpackPackageDir(self, src, dst):
     """Unpack a given directory from the OTA package into the given
@@ -158,11 +169,20 @@
     self.script.append('ui_print("%s");' % (message,))
 
   def FormatPartition(self, partition):
-    """Format the given partition."""
-    partition = self.info.get("partition_path", "") + partition
-    self.script.append('format("%s", "%s", "%s");' %
-                       (self.info["fs_type"], self.info["partition_type"],
-                        partition))
+    """Format the given partition, specified by its mount point (eg,
+    "/system")."""
+
+    fstab = self.info.get("fstab", None)
+    if fstab:
+      p = fstab[partition]
+      self.script.append('format("%s", "%s", "%s");' %
+                         (p.fs_type, self.PARTITION_TYPES[p.fs_type], p.device))
+    else:
+      # older target-files without per-partition types
+      partition = self.info.get("partition_path", "") + partition
+      self.script.append('format("%s", "%s", "%s");' %
+                         (self.info["fs_type"], self.info["partition_type"],
+                          partition))
 
   def DeleteFiles(self, file_list):
     """Delete all files in file_list."""
@@ -196,24 +216,42 @@
       self.script.append(
           'write_firmware_image("PACKAGE:%s", "%s");' % (fn, kind))
 
-  def WriteRawImage(self, partition, fn):
-    """Write the given package file into the given partition."""
+  def WriteRawImage(self, mount_point, fn):
+    """Write the given package file into the partition for the given
+    mount point."""
 
-    if self.info["partition_type"] == "MTD":
-      self.script.append(
-          ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n'
-           '       write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n'
-           '       delete("/tmp/%(partition)s.img"));')
-          % {'partition': partition, 'fn': fn})
-    elif self.info["partition_type"] == "EMMC":
-      self.script.append(
-          ('package_extract_file("%(fn)s", "%(dir)s%(partition)s");')
-          % {'partition': partition, 'fn': fn,
-             'dir': self.info.get("partition_path", ""),
-             })
+    fstab = self.info["fstab"]
+    if fstab:
+      p = fstab[mount_point]
+      partition_type = self.PARTITION_TYPES[p.fs_type]
+      args = {'device': p.device, 'fn': fn}
+      if partition_type == "MTD":
+        self.script.append(
+            ('assert(package_extract_file("%(fn)s", "/tmp/%(device)s.img"),\n'
+             '       write_raw_image("/tmp/%(device)s.img", "%(device)s"),\n'
+             '       delete("/tmp/%(device)s.img"));') % args)
+      elif partition_type == "EMMC":
+        self.script.append(
+            'package_extract_file("%(fn)s", "%(device)s");' % args)
+      else:
+        raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,))
     else:
-      raise ValueError("don't know how to write \"%s\" partitions" %
-                       (self.info["partition_type"],))
+      # backward compatibility with older target-files that lack recovery.fstab
+      if self.info["partition_type"] == "MTD":
+        self.script.append(
+            ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n'
+             '       write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n'
+             '       delete("/tmp/%(partition)s.img"));')
+            % {'partition': partition, 'fn': fn})
+      elif self.info["partition_type"] == "EMMC":
+        self.script.append(
+            ('package_extract_file("%(fn)s", "%(dir)s%(partition)s");')
+            % {'partition': partition, 'fn': fn,
+               'dir': self.info.get("partition_path", ""),
+               })
+      else:
+        raise ValueError("don't know how to write \"%s\" partitions" %
+                         (self.info["partition_type"],))
 
   def SetPermissions(self, fn, uid, gid, mode):
     """Set file ownership and permissions."""