Skip ab/6749736 in stage.

Merged-In: I883fd03c79f75966cefcae0f42fd08018d3b8247
Change-Id: I1fe00ea3e124351d47f51adf303483b934dd5761
diff --git a/OWNERS b/OWNERS
index f512bb3..906cba6 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1,3 @@
 bowgotsai@google.com
+hridya@google.com
 szuweilin@google.com
diff --git a/utils/src/mkdtboimg.py b/utils/src/mkdtboimg.py
index d24c455..bc33e1f 100755
--- a/utils/src/mkdtboimg.py
+++ b/utils/src/mkdtboimg.py
@@ -18,13 +18,13 @@
 """Tool for packing multiple DTB/DTBO files into a single image"""
 
 import argparse
-import os
 import fnmatch
+import os
+import struct
+import zlib
 from array import array
 from collections import namedtuple
-import struct
 from sys import stdout
-import zlib
 
 class CompressionFormat(object):
     """Enum representing DT compression format for a DT entry.
@@ -37,14 +37,18 @@
     """Provides individual DT image file arguments to be added to a DTBO.
 
     Attributes:
-        _REQUIRED_KEYS: 'keys' needed to be present in the dictionary passed to instantiate
-            an object of this class.
-        _COMPRESSION_FORMAT_MASK: Mask to retrieve compression info for DT entry from flags field
+        REQUIRED_KEYS_V0: 'keys' needed to be present in the dictionary passed to instantiate
+            an object of this class when a DTBO header of version 0 is used.
+        REQUIRED_KEYS_V1: 'keys' needed to be present in the dictionary passed to instantiate
+            an object of this class when a DTBO header of version 1 is used.
+        COMPRESSION_FORMAT_MASK: Mask to retrieve compression info for DT entry from flags field
             when a DTBO header of version 1 is used.
     """
-    _COMPRESSION_FORMAT_MASK = 0x0f
-    REQUIRED_KEYS = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev', 'flags',
-                     'custom0', 'custom1', 'custom2')
+    COMPRESSION_FORMAT_MASK = 0x0f
+    REQUIRED_KEYS_V0 = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev',
+                     'custom0', 'custom1', 'custom2', 'custom3')
+    REQUIRED_KEYS_V1 = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev',
+                     'flags', 'custom0', 'custom1', 'custom2')
 
     @staticmethod
     def __get_number_or_prop(arg):
@@ -83,7 +87,14 @@
                 the tuple (_REQUIRED_KEYS)
         """
 
-        missing_keys = set(self.REQUIRED_KEYS) - set(kwargs)
+        self.__version = kwargs['version']
+        required_keys = None
+        if self.__version == 0:
+            required_keys = self.REQUIRED_KEYS_V0
+        elif self.__version == 1:
+            required_keys = self.REQUIRED_KEYS_V1
+
+        missing_keys = set(required_keys) - set(kwargs)
         if missing_keys:
             raise ValueError('Missing keys in DtEntry constructor: %r' %
                              sorted(missing_keys))
@@ -93,10 +104,13 @@
         self.__dt_size = kwargs['dt_size']
         self.__id = self.__get_number_or_prop(kwargs['id'])
         self.__rev = self.__get_number_or_prop(kwargs['rev'])
-        self.__flags = self.__get_number_or_prop(kwargs['flags'])
+        if self.__version == 1:
+            self.__flags = self.__get_number_or_prop(kwargs['flags'])
         self.__custom0 = self.__get_number_or_prop(kwargs['custom0'])
         self.__custom1 = self.__get_number_or_prop(kwargs['custom1'])
         self.__custom2 = self.__get_number_or_prop(kwargs['custom2'])
+        if self.__version == 0:
+            self.__custom3 = self.__get_number_or_prop(kwargs['custom3'])
 
     def __str__(self):
         sb = []
@@ -108,26 +122,30 @@
                                                    value=self.__id))
         sb.append('{key:>20} = {value:08x}'.format(key='rev',
                                                    value=self.__rev))
+        if self.__version == 1:
+            sb.append('{key:>20} = {value:08x}'.format(key='flags',
+                                                       value=self.__flags))
         sb.append('{key:>20} = {value:08x}'.format(key='custom[0]',
-                                                   value=self.__flags))
-        sb.append('{key:>20} = {value:08x}'.format(key='custom[1]',
                                                    value=self.__custom0))
-        sb.append('{key:>20} = {value:08x}'.format(key='custom[2]',
+        sb.append('{key:>20} = {value:08x}'.format(key='custom[1]',
                                                    value=self.__custom1))
-        sb.append('{key:>20} = {value:08x}'.format(key='custom[3]',
+        sb.append('{key:>20} = {value:08x}'.format(key='custom[2]',
                                                    value=self.__custom2))
+        if self.__version == 0:
+            sb.append('{key:>20} = {value:08x}'.format(key='custom[3]',
+                                                       value=self.__custom3))
         return '\n'.join(sb)
 
-    def compression_info(self, version):
+    def compression_info(self):
         """CompressionFormat: compression format for DT image file.
 
            Args:
                 version: Version of DTBO header, compression is only
                          supported from version 1.
         """
-        if version is 0:
+        if self.__version == 0:
             return CompressionFormat.NO_COMPRESSION
-        return self.flags & self._COMPRESSION_FORMAT_MASK
+        return self.flags & self.COMPRESSION_FORMAT_MASK
 
     @property
     def dt_file(self):
@@ -182,6 +200,10 @@
         """int: DT entry custom2 for this DT image."""
         return self.__custom2
 
+    @property
+    def custom3(self):
+        """int: DT entry custom3 for this DT image."""
+        return self.__custom3
 
 class Dtbo(object):
     """
@@ -233,10 +255,17 @@
             dtbo_offset: Offset where the DT image file for this dt_entry can
                 be found in the resulting DTBO image.
         """
-        struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size,
-                         dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev,
-                         dt_entry.flags, dt_entry.custom0, dt_entry.custom1,
-                         dt_entry.custom2)
+        if self.version == 0:
+            struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size,
+                             dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev,
+                             dt_entry.custom0, dt_entry.custom1, dt_entry.custom2,
+                             dt_entry.custom3)
+        elif self.version == 1:
+            struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size,
+                             dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev,
+                             dt_entry.flags, dt_entry.custom0, dt_entry.custom1,
+                             dt_entry.custom2)
+
 
     def _update_metadata(self):
         """Updates the DTBO metadata.
@@ -245,7 +274,7 @@
         Tree table entries and update the DTBO header.
         """
 
-        self.__metadata = array('c', ' ' * self.__metadata_size)
+        self.__metadata = array('b', b' ' * self.__metadata_size)
         metadata_offset = self.header_size
         for dt_entry in self.__dt_entries:
             self._update_dt_entry_header(dt_entry, metadata_offset)
@@ -291,15 +320,21 @@
         if self.__dt_entries:
             raise ValueError('DTBO DT entries can be added only once')
 
-        offset = self.dt_entries_offset / 4
+        offset = self.dt_entries_offset // 4
         params = {}
+        params['version'] = self.version
         params['dt_file'] = None
         for i in range(0, self.dt_entry_count):
             dt_table_entry = self.__metadata[offset:offset + self._DT_ENTRY_HEADER_INTS]
             params['dt_size'] = dt_table_entry[0]
             params['dt_offset'] = dt_table_entry[1]
             for j in range(2, self._DT_ENTRY_HEADER_INTS):
-                params[DtEntry.REQUIRED_KEYS[j + 1]] = str(dt_table_entry[j])
+                required_keys = None
+                if self.version == 0:
+                    required_keys = DtEntry.REQUIRED_KEYS_V0
+                elif self.version == 1:
+                    required_keys = DtEntry.REQUIRED_KEYS_V1
+                params[required_keys[j + 1]] = str(dt_table_entry[j])
             dt_entry = DtEntry(**params)
             self.__dt_entries.append(dt_entry)
             offset += self._DT_ENTRY_HEADER_INTS
@@ -466,14 +501,13 @@
         dt_offset = (self.header_size +
                      dt_entry_count * self.dt_entry_size)
 
-        dt_entry_buf = ""
+        dt_entry_buf = b""
         for dt_entry in dt_entries:
             if not isinstance(dt_entry, DtEntry):
                 raise ValueError('Adding invalid DT entry object to DTBO')
             entry = self._find_dt_entry_with_same_file(dt_entry)
-            dt_entry_compression_info = dt_entry.compression_info(self.version)
-            if entry and (entry.compression_info(self.version)
-                          == dt_entry_compression_info):
+            dt_entry_compression_info = dt_entry.compression_info()
+            if entry and (entry.compression_info() == dt_entry_compression_info):
                 dt_entry.dt_offset = entry.dt_offset
                 dt_entry.size = entry.size
             else:
@@ -511,7 +545,7 @@
         offset = self.dt_entries[idx].dt_offset
         self.__file.seek(offset, 0)
         fout.seek(0)
-        compression_format = self.dt_entries[idx].compression_info(self.version)
+        compression_format = self.dt_entries[idx].compression_info()
         if decompress and compression_format:
             if (compression_format == CompressionFormat.ZLIB_COMPRESSION or
                 compression_format == CompressionFormat.GZIP_COMPRESSION):
@@ -581,6 +615,9 @@
     parser.add_argument('--custom2', type=str, dest='custom2',
                         action='store',
                         default=global_args.global_custom2)
+    parser.add_argument('--custom3', type=str, dest='custom3',
+                        action='store',
+                        default=global_args.global_custom3)
     return parser.parse_args(arglist)
 
 
@@ -613,7 +650,7 @@
         raise ValueError('Input DT images must be provided')
 
     total_images = len(img_file_idx)
-    for idx in xrange(total_images):
+    for idx in range(total_images):
         start_idx = img_file_idx[idx]
         if idx == total_images - 1:
             argv = arg_list[start_idx:]
@@ -622,6 +659,7 @@
             argv = arg_list[start_idx:end_idx]
         args = parse_dt_entry(global_args, argv)
         params = vars(args)
+        params['version'] = global_args.version
         params['dt_offset'] = 0
         params['dt_size'] = os.fstat(params['dt_file'].fileno()).st_size
         dt_entries.append(DtEntry(**params))
@@ -754,6 +792,8 @@
                         action='store', default='0')
     parser.add_argument('--custom2', type=str, dest='global_custom2',
                         action='store', default='0')
+    parser.add_argument('--custom3', type=str, dest='global_custom3',
+                        action='store', default='0')
     args = parser.parse_args(argv)
     return args, remainder
 
@@ -770,7 +810,7 @@
 
     parser = argparse.ArgumentParser(prog='dump')
     parser.add_argument('--output', '-o', nargs='?',
-                        type=argparse.FileType('wb'),
+                        type=argparse.FileType('w'),
                         dest='outfile',
                         default=stdout)
     parser.add_argument('--dtb', '-b', nargs='?', type=str,
@@ -790,7 +830,7 @@
     """
     parser = argparse.ArgumentParser(prog='cfg_create')
     parser.add_argument('conf_file', nargs='?',
-                        type=argparse.FileType('rb'),
+                        type=argparse.FileType('r'),
                         default=None)
     cwd = os.getcwd()
     parser.add_argument('--dtb-dir', '-d', nargs='?', type=str,
@@ -846,18 +886,22 @@
     if not args.conf_file:
         raise ValueError('Configuration file must be provided')
 
-    _DT_KEYS = ('id', 'rev', 'flags', 'custom0', 'custom1', 'custom2')
+    _DT_KEYS = ('id', 'rev', 'flags', 'custom0', 'custom1', 'custom2', 'custom3')
     _GLOBAL_KEY_TYPES = {'dt_type': str, 'page_size': int, 'version': int}
 
     global_args, dt_args = parse_config_file(args.conf_file,
                                              _DT_KEYS, _GLOBAL_KEY_TYPES)
+    version = global_args['version']
+
     params = {}
+    params['version'] = version
     dt_entries = []
     for dt_arg in dt_args:
-        filepath = None
-        for root, dirnames, filenames in os.walk(args.dtbdir):
-            for filename in fnmatch.filter(filenames, dt_arg['filename']):
-                filepath = os.path.join(root, filename)
+        filepath = dt_arg['filename']
+        if not os.path.isabs(filepath):
+            for root, dirnames, filenames in os.walk(args.dtbdir):
+                for filename in fnmatch.filter(filenames, os.path.basename(filepath)):
+                    filepath = os.path.join(root, filename)
         params['dt_file'] = open(filepath, 'rb')
         params['dt_offset'] = 0
         params['dt_size'] = os.fstat(params['dt_file'].fileno()).st_size
@@ -869,7 +913,7 @@
         dt_entries.append(DtEntry(**params))
 
     # Create and write DTBO file
-    dtbo = Dtbo(fout, global_args['dt_type'], global_args['page_size'], global_args['version'])
+    dtbo = Dtbo(fout, global_args['dt_type'], global_args['page_size'], version)
     dt_entry_buf = dtbo.add_dt_entries(dt_entries)
     dtbo.commit(dt_entry_buf)
     fout.close()
@@ -920,6 +964,7 @@
     sb.append('      --custom0=<number>')
     sb.append('      --custom1=<number>')
     sb.append('      --custom2=<number>\n')
+    sb.append('      --custom3=<number>\n')
 
     sb.append('      The value could be a number or a DT node path.')
     sb.append('      <number> could be a 32-bits digit or hex value, ex. 68000, 0x6800.')