avbtool: Add --print_required_libavb_version option.

This can be used with make_vbmeta_image, add_hash_footer, and
add_hashtree_footer to figure out what will be put in the
required_libavb_version_{major, minor} fields in the VBMeta
struct. This is useful if you also want to store this value in a file
inside system.img before adding a hashtree and integrity data to it.

Right now "1.0" will be printed out since we're still at 1.0. In the
future this may get more complicated.

As with --calc_max_image_size the caller is supposed to pass all the
same options (except --output and --image) that they would pass when
not using the option. This is because options will influence what
minimum libavb version will be required - for example, if using an
algorithm introduced post-1.0 this would be expressed with the
--algorithm option.

Bug: 62077941
Test: New unit test and all unit tests pass.
Change-Id: I97a26f5b51eb4a8c63ca7903a406b174eb88bacb
diff --git a/avbtool b/avbtool
index 5df31b4..75bae27 100755
--- a/avbtool
+++ b/avbtool
@@ -2336,7 +2336,8 @@
                         setup_rootfs_from_kernel,
                         include_descriptors_from_image, signing_helper,
                         release_string,
-                        append_to_release_string):
+                        append_to_release_string,
+                        print_required_libavb_version):
     """Implements the 'make_vbmeta_image' command.
 
     Arguments:
@@ -2355,11 +2356,22 @@
       signing_helper: Program which signs a hash and return signature.
       release_string: None or avbtool release string to use instead of default.
       append_to_release_string: None or string to append.
+      print_required_libavb_version: True to only print required libavb version.
 
     Raises:
       AvbError: If a chained partition is malformed.
     """
 
+    # If we're asked to calculate minimum required libavb version, we're done.
+    #
+    # NOTE: When we get to 1.1 and later this will get more complicated.
+    if print_required_libavb_version:
+      print '1.0'
+      return
+
+    if not output:
+      raise AvbError('No output file given')
+
     descriptors = []
     ht_desc_to_setup = None
     vbmeta_blob = self._generate_vbmeta_blob(
@@ -2694,7 +2706,8 @@
                       setup_rootfs_from_kernel,
                       include_descriptors_from_image, calc_max_image_size,
                       signing_helper, release_string, append_to_release_string,
-                      output_vbmeta_image, do_not_append_vbmeta_image):
+                      output_vbmeta_image, do_not_append_vbmeta_image,
+                      print_required_libavb_version):
     """Implementation of the add_hash_footer on unsparse images.
 
     Arguments:
@@ -2724,10 +2737,19 @@
       append_to_release_string: None or string to append.
       output_vbmeta_image: If not None, also write vbmeta struct to this file.
       do_not_append_vbmeta_image: If True, don't append vbmeta struct.
+      print_required_libavb_version: True to only print required libavb version.
 
     Raises:
       AvbError: If an argument is incorrect.
     """
+
+    # If we're asked to calculate minimum required libavb version, we're done.
+    #
+    # NOTE: When we get to 1.1 and later this will get more complicated.
+    if print_required_libavb_version:
+      print '1.0'
+      return
+
     # First, calculate the maximum image size such that an image
     # this size + metadata (footer + vbmeta struct) fits in
     # |partition_size|.
@@ -2862,7 +2884,8 @@
                           include_descriptors_from_image,
                           calc_max_image_size, signing_helper,
                           release_string, append_to_release_string,
-                          output_vbmeta_image, do_not_append_vbmeta_image):
+                          output_vbmeta_image, do_not_append_vbmeta_image,
+                          print_required_libavb_version):
     """Implements the 'add_hashtree_footer' command.
 
     See https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for
@@ -2900,10 +2923,19 @@
       append_to_release_string: None or string to append.
       output_vbmeta_image: If not None, also write vbmeta struct to this file.
       do_not_append_vbmeta_image: If True, don't append vbmeta struct.
+      print_required_libavb_version: True to only print required libavb version.
 
     Raises:
       AvbError: If an argument is incorrect.
     """
+
+    # If we're asked to calculate minimum required libavb version, we're done.
+    #
+    # NOTE: When we get to 1.1 and later this will get more complicated.
+    if print_required_libavb_version:
+      print '1.0'
+      return
+
     digest_size = len(hashlib.new(name=hash_algorithm).digest())
     digest_padding = round_to_pow2(digest_size) - digest_size
 
@@ -3404,6 +3436,11 @@
                             metavar='IMAGE',
                             action='append',
                             type=argparse.FileType('rb'))
+    sub_parser.add_argument('--print_required_libavb_version',
+                            help=('Don\'t store the footer - '
+                                  'instead calculate the required libavb '
+                                  'version for the given options.'),
+                            action='store_true')
     # These are only allowed from top-level vbmeta and boot-in-lieu-of-vbmeta.
     sub_parser.add_argument('--chain_partition',
                             help='Allow signed integrity-data for partition',
@@ -3458,8 +3495,7 @@
                                        help='Makes a vbmeta image.')
     sub_parser.add_argument('--output',
                             help='Output file name',
-                            type=argparse.FileType('wb'),
-                            required=True)
+                            type=argparse.FileType('wb'))
     self._add_common_args(sub_parser)
     sub_parser.set_defaults(func=self.make_vbmeta_image)
 
@@ -3470,8 +3506,7 @@
                             type=argparse.FileType('rab+'))
     sub_parser.add_argument('--partition_size',
                             help='Partition size',
-                            type=parse_number,
-                            required=True)
+                            type=parse_number)
     sub_parser.add_argument('--partition_name',
                             help='Partition name',
                             default=None)
@@ -3517,8 +3552,7 @@
                             type=argparse.FileType('rab+'))
     sub_parser.add_argument('--partition_size',
                             help='Partition size',
-                            type=parse_number,
-                            required=True)
+                            type=parse_number)
     sub_parser.add_argument('--partition_name',
                             help='Partition name',
                             default=None)
@@ -3731,7 +3765,8 @@
                                args.include_descriptors_from_image,
                                args.signing_helper,
                                args.internal_release_string,
-                               args.append_to_release_string)
+                               args.append_to_release_string,
+                               args.print_required_libavb_version)
 
   def append_vbmeta_image(self, args):
     """Implements the 'append_vbmeta_image' sub-command."""
@@ -3755,7 +3790,8 @@
                              args.internal_release_string,
                              args.append_to_release_string,
                              args.output_vbmeta_image,
-                             args.do_not_append_vbmeta_image)
+                             args.do_not_append_vbmeta_image,
+                             args.print_required_libavb_version)
 
   def add_hashtree_footer(self, args):
     """Implements the 'add_hashtree_footer' sub-command."""
@@ -3783,7 +3819,8 @@
                                  args.internal_release_string,
                                  args.append_to_release_string,
                                  args.output_vbmeta_image,
-                                 args.do_not_append_vbmeta_image)
+                                 args.do_not_append_vbmeta_image,
+                                 args.print_required_libavb_version)
 
   def erase_footer(self, args):
     """Implements the 'erase_footer' sub-command."""