gooftool: Remove hwid v2 functions, add command verify_hwid for v3.

As discussed in CL:377579, we would like to add verify_hwid_v3 as a
command to make it waivable.

1. Remove hwid v2 related functions, gooftool only supports hwid v3 now.
2. Add VerifyHWIDv3 as a command: 'verify_hwid'.

BUG=None
TEST=Run `gooftool verify` and `gooftool verify_hwid`

CQ-DEPEND=CL:377579

Change-Id: Ia9509dea05fef0c8df6521a5c3b02aaadc74f847
Reviewed-on: https://chromium-review.googlesource.com/380420
Commit-Ready: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/py/gooftool/commands.py b/py/gooftool/commands.py
index aadcee7..0da0653 100755
--- a/py/gooftool/commands.py
+++ b/py/gooftool/commands.py
@@ -33,12 +33,9 @@
 from cros.factory.gooftool.core import Gooftool
 from cros.factory.gooftool.common import ExecFactoryPar
 from cros.factory.gooftool.common import Shell
-from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
-from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
+from cros.factory.gooftool.probe import Probe
+from cros.factory.gooftool.probe import ReadRoVpd
 from cros.factory.gooftool.probe import CalculateFirmwareHashes
-from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
-from cros.factory.hwid.v2 import hwid_tool
-from cros.factory.hwid.v2.yaml_datastore import YamlWrite
 from cros.factory.hwid.v3 import common
 from cros.factory.hwid.v3 import hwid_utils
 from cros.factory.test import event_log
@@ -70,20 +67,10 @@
 
   if _global_gooftool is None:
     with _gooftool_lock:
-      hwid_version = getattr(options, 'hwid_version', 3)
-      if hwid_version == 2:
-        hwdb_path = getattr(options, 'hwdb_path', None)
-        component_db = (
-            hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
-            else None)
-        _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
-      elif hwid_version == 3:
-        board = getattr(options, 'board', None)
-        hwdb_path = getattr(options, 'hwdb_path', None)
-        _global_gooftool = Gooftool(hwid_version=3, board=board,
-                                    hwdb_path=hwdb_path)
-      else:
-        raise Error, 'Invalid HWID version: %r' % options.hwid_version
+      board = getattr(options, 'board', None)
+      hwdb_path = getattr(options, 'hwdb_path', None)
+      _global_gooftool = Gooftool(hwid_version=3, board=board,
+                                  hwdb_path=hwdb_path)
 
   return _global_gooftool
 
@@ -163,10 +150,6 @@
          'items. For example, branding verification or firmware bitmap '
          'locale settings).')
 
-_hwid_version_cmd_arg = CmdArg(
-    '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
-    help='Version of HWID to operate on. (default: %(default)s)')
-
 _enforced_release_channels_cmd_arg = CmdArg(
     '--enforced_release_channels', nargs='*', default=None,
     help='Enforced release image channels.')
@@ -212,182 +195,6 @@
          'Each item should be a sub-command of gooftool.'
          'e.g. "gooftool verify --waive_list verify_tpm clear_gbb_flags".')
 
-@Command('best_match_hwids',
-         _hwdb_path_cmd_arg,
-         CmdArg('-b', '--board', metavar='BOARD',
-                help='optional BOARD name, needed only if data is present '
-                'for more than one'),
-         CmdArg('--bom', metavar='BOM', help='BOM name'),
-         CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
-         CmdArg('--optimistic', action='store_true',
-                help='do not probe; assume singletons match'),
-         CmdArg('--comps', nargs='*', default=[],
-                help='list of canonical component names'),
-         CmdArg('--missing', nargs='*', default=[],
-                help='list component classes to be assumed missing'),
-         CmdArg('--status', nargs='*', default=['supported'],
-                help='consider only HWIDs within this list of status values'))
-def BestMatchHwids(options):
-  """Determine a list of possible HWIDs using provided args and probing.
-
-  VOLATILE can always be determined by probing.  To get a unique
-  result, VARIANT must be specified for all cases where the matching
-  BOM has more than one associated variant code, otherwise all HWID
-  variants will be returned.  Both VARIANT and BOM information can
-  alternatively be specified using the --stdin_comps argument, which
-  allows specifying a list of canonical names (one per line) on stdin,
-  one per line.  Based on what is known from BOM and stdin_comps,
-  determine a list of components to probe for, and use those probe
-  results to resolve a list of matching HWIDs.  If no boms,
-  components, or variant codes are specified, then a list of all HWIDs
-  that match probeable components will be returned.
-
-  Returns (on stdout): A list of HWIDs that match the available probe
-  results and argument contraints, one per line.
-
-  Example:
-
-  // Three ways to specify a keyboard (assuming it is a variant component)
-  gooftool best_match_hwids --missing keyboard
-  gooftool best_match_hwids --variant A or
-  gooftool best_match_hwids --comps us_kbd
-  """
-
-  map(hwid_tool.Validate.Status, options.status)
-  hw_db = hwid_tool.HardwareDb(options.hwdb_path)
-  comp_db = hw_db.comp_db
-  device = hw_db.GetDevice(options.board)
-  component_spec = hwid_tool.ComponentSpec.New()
-  if options.bom:
-    device.BomExists(options.bom)
-    component_spec = hwid_tool.CombineComponentSpecs(
-        component_spec, device.boms[options.bom].primary)
-  if options.variant:
-    device.VariantExists(options.variant)
-    variant_spec = device.variants[options.variant]
-    if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
-      sys.exit('ERROR: multiple specifications for these components:\n%s'
-               % YamlWrite(sorted(
-                   hwid_tool.ComponentSpecClasses(component_spec) &
-                   hwid_tool.ComponentSpecClasses(variant_spec))))
-    component_spec = hwid_tool.CombineComponentSpecs(
-        component_spec, variant_spec)
-  if options.comps or options.missing:
-    map(comp_db.CompExists, options.comps)
-    map(comp_db.CompClassExists, options.missing)
-    extra_comp_spec = comp_db.CreateComponentSpec(
-        components=options.comps,
-        missing=options.missing)
-    print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
-    if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
-      sys.exit('ERROR: multiple specifications for these components:\n%s'
-               % YamlWrite(sorted(
-                   hwid_tool.ComponentSpecClasses(component_spec) &
-                   hwid_tool.ComponentSpecClasses(extra_comp_spec))))
-    component_spec = hwid_tool.CombineComponentSpecs(
-        component_spec, extra_comp_spec)
-  spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
-  missing_classes = set(comp_db.all_comp_classes) - spec_classes
-  if missing_classes and not options.optimistic:
-    non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
-    if non_probeable_missing:
-      sys.exit('FAILURE: these classes are necessary, were not specified '
-               'as inputs, and cannot be probed for:\n%s'
-               'This problem can often be addressed by specifying all of '
-               'the missing components on the command line (see the command '
-               'help).' % YamlWrite(list(non_probeable_missing)))
-    print 'probing for missing classes:'
-    print YamlWrite(list(missing_classes))
-    probe_results = Probe(target_comp_classes=list(missing_classes),
-                          probe_volatile=False, probe_initial_config=False)
-    cooked_components = comp_db.MatchComponentProbeValues(
-        probe_results.found_probe_value_map)
-    if cooked_components.unmatched:
-      sys.exit('ERROR: some probed components are unrecognized:\n%s'
-               % YamlWrite(cooked_components.unmatched))
-    probed_comp_spec = comp_db.CreateComponentSpec(
-        components=cooked_components.matched,
-        missing=probe_results.missing_component_classes)
-    component_spec = hwid_tool.CombineComponentSpecs(
-        component_spec, probed_comp_spec)
-  print YamlWrite({'component data used for matching': {
-      'missing component classes': component_spec.classes_missing,
-      'found components': component_spec.components}})
-  component_data = hwid_tool.ComponentData(
-      extant_components=hwid_tool.ComponentSpecCompClassMap(
-          component_spec).keys(),
-      classes_missing=component_spec.classes_missing)
-  match_tree = device.BuildMatchTree(component_data)
-  if not match_tree:
-    sys.exit('FAILURE: NO matching BOMs found')
-  print 'potential BOMs/VARIANTs:'
-  potential_variants = set()
-  potential_volatiles = set()
-  for bom_name, variant_tree in match_tree.items():
-    print '  BOM: %-8s   VARIANTS: %s' % (
-        bom_name, ', '.join(sorted(variant_tree)))
-    for variant_code in variant_tree:
-      potential_variants.add(variant_code)
-      for volatile_code in device.volatiles:
-        status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
-        if status in options.status:
-          potential_volatiles.add(volatile_code)
-  print ''
-  if len(potential_variants) == 0:
-    sys.exit('FAILURE: no matching VARIANTs found')
-  if len(potential_volatiles) == 0:
-    sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
-             '(with specified status)')
-  if (options.optimistic and
-      len(match_tree) == 1 and
-      len(potential_variants) == 1 and
-      len(potential_volatiles) == 1):
-    print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
-                                                potential_variants.pop(),
-                                                potential_volatiles.pop()))
-    return
-  print ('probing VOLATILEs to resolve potential matches: %s\n' %
-         ', '.join(sorted(potential_volatiles)))
-  vol_probe_results = Probe(
-      target_comp_classes=[],
-      probe_volatile=True,
-      probe_initial_config=False)
-  cooked_volatiles = device.MatchVolatileValues(
-      vol_probe_results.found_volatile_values)
-  match_tree = device.BuildMatchTree(
-      component_data, cooked_volatiles.matched_tags)
-  matched_hwids = device.GetMatchTreeHwids(match_tree)
-  if matched_hwids:
-    for hwid in matched_hwids:
-      if matched_hwids[hwid] in options.status:
-        print 'MATCHING HWID: %s' % hwid
-    return
-  print 'exact HWID matching failed, but the following BOMs match: %s' % (
-      ', '.join(sorted(match_tree)))
-  if options.optimistic and len(match_tree) == 1:
-    bom_name = set(match_tree).pop()
-    bom = device.boms[bom_name]
-    variant_matches = match_tree[bom_name]
-    if len(variant_matches) == 1:
-      var_code = set(variant_matches).pop()
-    elif len(bom.variants) == 1:
-      var_code = set(bom.variants).pop()
-    else:
-      sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed  '
-               'because there were too many variants to choose from for BOM %r'
-               % bom_name)
-    hwids = [device.FmtHwid(bom_name, var_code, vol_code)
-             for vol_code in device.volatiles
-             if device.GetHwidStatus(bom_name, var_code, vol_code)
-             in options.status]
-    for hwid in hwids:
-      print 'MATCHING HWID: %s' % hwid
-    return
-  else:
-    print ('optimistic matching not attempted because either it was '
-           'not requested, or because the number of BOMs was <> 1\n')
-  sys.exit('FAILURE: NO matching HWIDs found')
-
 
 @Command('probe',
          CmdArg('--comps', nargs='*',
@@ -457,129 +264,6 @@
     print '\ncomponent verification SUCCESS'
 
 
-@Command('verify_hwid_v2',
-         _hwid_status_list_cmd_arg,
-         _hwdb_path_cmd_arg,
-         _probe_results_cmd_arg,
-         _hwid_cmd_arg)
-def VerifyHWIDv2(options):
-  """Verify system HWID properties match probed device properties.
-
-  First probe components, volatile and initial_config parameters for
-  the DUT.  Then use the available device data to produce a list of
-  candidate HWIDs.  Then verify the HWID from the DUT is present in
-  that list.  Then verify that the DUT initial config values match
-  those specified for its HWID.  Finally, verify that VPD contains all
-  the necessary fields as specified by the board data, and when
-  possible verify that values are legitimate.
-  """
-  def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
-    for key in ro_vpd_keys:
-      if key not in ro_vpd:
-        sys.exit('Missing required RO VPD field: %s' % key)
-      known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
-      value = ro_vpd[key]
-      if (known_valid_values is not None) and (value not in known_valid_values):
-        sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
-    for key in rw_vpd_keys:
-      if key not in rw_vpd:
-        sys.exit('Missing required RW VPD field: %s' % key)
-      known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
-      value = rw_vpd[key]
-      if (known_valid_values is not None) and (value not in known_valid_values):
-        sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
-    event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
-  map(hwid_tool.Validate.Status, options.status)
-
-  if options.hwid:
-    hwid_str = options.hwid
-  else:
-    main_fw_file = crosfw.LoadMainFirmware().GetFileName()
-    gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
-    hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
-  hwid = hwid_tool.ParseHwid(hwid_str)
-  hw_db = hwid_tool.HardwareDb(options.hwdb_path)
-  print 'Verifying HWID: %r\n' % hwid.hwid
-  device = hw_db.GetDevice(hwid.board)
-  hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
-  if hwid_status not in options.status:
-    sys.exit('HWID status must be one of [%s], found %r' %
-             (', '.join(options.status), hwid_status))
-  if options.probe_results:
-    # Pull in probe results (including VPD data) from the given file
-    # rather than probing the current system.
-    probe_results = hwid_tool.ProbeResults.Decode(
-        open(options.probe_results).read())
-    ro_vpd = {}
-    rw_vpd = {}
-    for k, v in probe_results.found_volatile_values.items():
-      match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
-      if match:
-        del probe_results.found_volatile_values[k]
-        (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
-  else:
-    probe_results = Probe()
-    ro_vpd = ReadRoVpd()
-    rw_vpd = ReadRwVpd()
-  cooked_components = hw_db.comp_db.MatchComponentProbeValues(
-      probe_results.found_probe_value_map)
-  cooked_volatiles = device.MatchVolatileValues(
-      probe_results.found_volatile_values)
-  cooked_initial_configs = device.MatchInitialConfigValues(
-      probe_results.initial_configs)
-  component_data = hwid_tool.ComponentData(
-      extant_components=cooked_components.matched,
-      classes_missing=probe_results.missing_component_classes)
-  match_tree = device.BuildMatchTree(
-      component_data, cooked_volatiles.matched_tags)
-  matched_hwids = device.GetMatchTreeHwids(match_tree)
-  print 'HWID status: %s\n' % hwid_status
-  print 'probed system components:'
-  print YamlWrite(cooked_components.__dict__)
-  print 'missing component classes:'
-  print YamlWrite(probe_results.missing_component_classes)
-  print 'probed volatiles:'
-  print YamlWrite(cooked_volatiles.__dict__)
-  print 'probed initial_configs:'
-  print YamlWrite(cooked_initial_configs)
-  print 'hwid match tree:'
-  print YamlWrite(match_tree)
-  event_log.Log(
-      'probe',
-      found_components=cooked_components.__dict__,
-      missing_component_classes=probe_results.missing_component_classes,
-      volatiles=cooked_volatiles.__dict__,
-      initial_configs=cooked_initial_configs)
-  if hwid.hwid not in matched_hwids:
-    err_msg = 'HWID verification FAILED.\n'
-    if cooked_components.unmatched:
-      sys.exit(err_msg + 'some components could not be indentified:\n%s' %
-               YamlWrite(cooked_components.unmatched))
-    if not match_tree:
-      sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
-               component_data.Encode())
-    if hwid.bom not in match_tree:
-      sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
-               (', '.join(sorted(match_tree)), hwid.bom))
-    err_msg += 'target bom %r matches components' % hwid.bom
-    if hwid.bom not in device.IntersectBomsAndInitialConfigs(
-        cooked_initial_configs):
-      sys.exit(err_msg + ', but failed initial config verification')
-    matched_variants = match_tree.get(hwid.bom, {})
-    if hwid.variant not in matched_variants:
-      sys.exit(err_msg + ', but target variant_code %r did not match' %
-               hwid.variant)
-    matched_volatiles = matched_variants.get(hwid.variant, {})
-    if hwid.volatile not in matched_volatiles:
-      sys.exit(err_msg + ', but target volatile_code %r did not match' %
-               hwid.volatile)
-    found_status = matched_volatiles.get(hwid.volatile, None)
-    sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
-  VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
-  event_log.Log('verified_hwid', hwid=hwid)
-  print 'Verification SUCCESS!'
-
-
 @Command('verify_keys',
          _release_rootfs_cmd_arg,
          _firmware_path_cmd_arg)
@@ -799,7 +483,6 @@
 @Command('verify',
          CmdArg('--no_write_protect', action='store_true',
                 help='Do not check write protection switch state.'),
-         _hwid_version_cmd_arg,
          _hwid_status_list_cmd_arg,
          _hwdb_path_cmd_arg,
          _board_cmd_arg,
@@ -824,12 +507,7 @@
     VerifyWPSwitch(options)
     VerifyManagementEngineLocked(options)
   VerifyDevSwitch(options)
-  if options.hwid_version == 2:
-    VerifyHWIDv2(options)
-  elif options.hwid_version == 3:
-    VerifyHWIDv3(options)
-  else:
-    raise Error, 'Invalid HWID version: %r' % options.hwid_version
+  VerifyHWID(options)
   VerifySystemTime(options)
   VerifyKeys(options)
   VerifyRootFs(options)
@@ -990,7 +668,6 @@
                 help='Start factory wiping in place without reboot.'),
          _cutoff_args_cmd_arg,
          _shopfloor_url_args_cmd_arg,
-         _hwid_version_cmd_arg,
          _hwdb_path_cmd_arg,
          _hwid_status_list_cmd_arg,
          _upload_method_cmd_arg,
@@ -1060,7 +737,12 @@
     PrepareWipe(options)
 
 
-def VerifyHWIDv3(options):
+@Command('verify_hwid',
+         _probe_results_cmd_arg,
+         _hwdb_path_cmd_arg,
+         _hwid_cmd_arg,
+         _rma_mode_cmd_arg)
+def VerifyHWID(options):
   """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
 
   This is mainly for Gooftool to verify v3 HWID during finalize.  For testing
@@ -1129,9 +811,7 @@
   """Run sub-command specified by the command line args."""
 
   options = ParseCmdline(
-      ('Perform Google required factory tests. All the HWID-related functions '
-       'provided here are mainly for the deprecated HWID v2. To access HWID '
-       'v3-related utilities, please use `hwid` command.'),
+      'Perform Google required factory tests.',
       CmdArg('-l', '--log', metavar='PATH',
              help='Write logs to this file.'),
       CmdArg('--suppress-event-logs', action='store_true',