autotest/factory: merge ToT changes to R12 factory, to support latest HWID
autotest/factory: separate hwid-matching and component test
Cherry-picked: http://gerrit.chromium.org/gerrit/2867
factory_ProbeHWID: Support simple UI to manually select HWID
Cherry-picked: http://gerrit.chromium.org/gerrit/5001
factory_ProbeHWID: improve error feedback in report
Cherry-picked: http://gerrit.chromium.org/gerrit/5551
BUG=none, prepare for next factory bundle release
TEST=none, factory will verify
Change-Id: I6fe9d123dadc10037659298c089b3a898914b03a
Reviewed-on: http://gerrit.chromium.org/gerrit/5648
Reviewed-by: Jay Kim <yongjaek@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/client/site_tests/factory_Finalize/factory_Finalize.py b/client/site_tests/factory_Finalize/factory_Finalize.py
index 9a51554..ce42a1e 100644
--- a/client/site_tests/factory_Finalize/factory_Finalize.py
+++ b/client/site_tests/factory_Finalize/factory_Finalize.py
@@ -99,15 +99,10 @@
# solve upload file names
upload_method = self.normalize_upload_method(upload_method)
- # build parameters
- db_path = os.path.join(self.bindir,
- '..',
- 'hardware_Components',
- 'data_*/components*')
args = ['gooftool',
'--finalize',
'--verbose',
- '--db_path "%s"' % db_path,
+ '--wipe_method "%s"' % ('secure' if secure_wipe else 'fast'),
'--upload_method "%s"' % upload_method,
]
if not check_and_enable_write_protect:
diff --git a/client/site_tests/factory_ProbeHWID/factory_ProbeHWID.py b/client/site_tests/factory_ProbeHWID/factory_ProbeHWID.py
new file mode 100644
index 0000000..e952dc1
--- /dev/null
+++ b/client/site_tests/factory_ProbeHWID/factory_ProbeHWID.py
@@ -0,0 +1,207 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import gtk
+import os
+import re
+from gtk import gdk
+
+from autotest_lib.client.bin import factory
+from autotest_lib.client.bin import factory_ui_lib as ful
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.cros import gooftools
+
+
+class factory_ProbeHWID(test.test):
+ version = 4
+ SELECTION_PER_PAGE = 10
+ HWID_AUTODETECT = None
+
+ def probe_hwid(self):
+ """ Finds out the matching HWID by detection.
+ This function must not use any GUI resources.
+ """
+ command = 'gooftool --probe --verbose'
+ pattern = 'Probed: '
+
+ (stdout, stderr, result) = gooftools.run(command, ignore_status=True)
+
+ # Decode successfully matched results
+ hwids = [hwid.lstrip(pattern)
+ for hwid in stdout.splitlines()
+ if hwid.startswith(pattern)]
+
+ # Decode unmatched results.
+ # Sample output:
+ # Unmatched for /usr/local/share/chromeos-hwid/components_BLAHBLAH:
+ # { 'part_id_3g': ['Actual: XXX', 'Expected: YYY']}
+ # Current System:
+ # { 'part_id_xxx': ['yyy'] },
+ str_unmatched = 'Unmatched '
+ str_current = 'Current System:'
+
+ start = stderr.find(str_unmatched)
+ if start < 0:
+ start = 0
+ end = stderr.rfind(str_current)
+ if end < 0:
+ unmatched = stderr[start:]
+ else:
+ unmatched = stderr[start:end]
+ # TODO(hungte) Sort and find best match candidate
+ unmatched = '\n'.join([line for line in unmatched.splitlines()
+ # 'gft_hwcomp' or 'probe' are debug message.
+ if not (line.startswith('gft_hwcomp:') or
+ line.startswith('probe:') or
+ (not line))])
+ # Report the results
+ if len(hwids) < 1:
+ raise error.TestFail('\n'.join(('No HWID matched.', unmatched)))
+ if len(hwids) > 1:
+ raise error.TestError('Multiple HWIDs match current system: ' +
+ ','.join(hwids))
+ if result != 0:
+ raise error.TestFail('HWID matched (%s) with unknown error: %s'
+ % hwids[0], result)
+ return hwids[0]
+
+ def update_hwid(self, path_to_file):
+ """ Updates component list file to shared data LAST_PROBED_HWID_NAME,
+ and then let factory_WriteGBB to update system. factory_Finalize
+ will verify if that's set correctly.
+ This function must not use any GUI resources.
+
+ TODO(hungte) Merge factory_WriteGBB into this test
+
+ Args:
+ path_to_component_list: A component list file containing HWID and
+ GBB information. Use HWID_AUTODETECT for detection.
+ """
+ if path_to_file == self.HWID_AUTODETECT:
+ path_to_file = self.probe_hwid()
+ # Set the factory state sharead data for factory_WriteGBB
+ factory.log('Set factory state shared data %s = %s' %
+ (factory.LAST_PROBED_HWID_NAME, path_to_file))
+ factory.set_shared_data(factory.LAST_PROBED_HWID_NAME, path_to_file)
+
+ def build_hwid_list(self):
+ files = glob.glob('/usr/local/share/chromeos-hwid/components*')
+ if not files:
+ files = glob.glob('/usr/share/chromeos-hwid/components*')
+ files.sort()
+
+ if not files:
+ raise error.TestError('No HWID component files found on system.')
+
+ # part_id_hwqual is required for every component list file.
+ hwids = [(eval(open(hwid_file).read())['part_id_hwqual'][0], hwid_file)
+ for hwid_file in files ]
+
+ # Add special entries
+ special_hwids = [('<Auto Detect>', self.HWID_AUTODETECT)]
+ for hwid in hwids:
+ if hwid[0] != self.current_hwid:
+ continue
+ special_hwids += [("<Current Value: %s>" % hwid[0], hwid[1])]
+ break
+
+ return special_hwids + hwids
+
+ def key_release_callback(self, widget, event):
+ if self.writing:
+ return True
+
+ # Process page navigation
+ KEY_PREV = [65361, 65362, ord('h'), ord('k')] # Left, Up
+ KEY_NEXT = [65363, 65364, ord('l'), ord('j')] # Right, Down
+ if event.keyval in KEY_PREV:
+ if self.page_index > 0:
+ self.page_index -= 1
+ self.render_page()
+ return True
+ if event.keyval in KEY_NEXT:
+ if self.page_index < self.pages - 1:
+ self.page_index += 1
+ self.render_page()
+ return True
+
+ char = chr(event.keyval) if event.keyval in range(32,127) else None
+ factory.log('key_release %s(%s)' % (event.keyval, char))
+ try:
+ select = int(char)
+ except ValueError:
+ factory.log('Need a number.')
+ return True
+
+ select = select + self.page_index * self.SELECTION_PER_PAGE
+ if select < 0 or select >= len(self.hwid_list):
+ factory.log('Invalid selection: %d' % select)
+ return True
+
+ data = self.hwid_list[select]
+ hwid_file = data[1]
+ if hwid_file == self.HWID_AUTODETECT:
+ self.label.set_text('Probing HWID, Please wait... (may take >30s)')
+ self.writing = True
+ gtk.main_iteration(False) # try to update screen
+ elif hwid_file:
+ factory.log('Selected: %s' % ', '.join(data).replace('\n', ' '))
+
+ try:
+ self.update_hwid(hwid_file)
+ except Exception, e:
+ self._fail_msg = '%s' % e
+
+ gtk.main_quit()
+ return True
+
+ def register_callbacks(self, window):
+ window.connect('key-release-event', self.key_release_callback)
+ window.add_events(gdk.KEY_RELEASE_MASK)
+
+ def render_page(self):
+ msg = 'Choose a HWID:\n\n'
+ start = self.page_index * self.SELECTION_PER_PAGE
+ end = start + self.SELECTION_PER_PAGE
+ for index, data in enumerate(self.hwid_list[start:end]):
+ msg += '%s) %s\n\n' % (index, data[0])
+ if self.pages > 1:
+ msg += '[Page %d / %d, navigate with arrow keys]' % (
+ self.page_index + 1, self.pages)
+ self.label.set_text(msg)
+
+ def run_once(self, autodetect=True):
+ factory.log('%s run_once' % self.__class__)
+ self._fail_msg = None
+
+ if autodetect:
+ self.update_hwid(self.HWID_AUTODETECT)
+ else:
+ # TODO(hungte) add timeout
+ self.page_index = 0
+ self.pages = 0
+ self.writing = False
+ with os.popen("crossystem hwid 2>/dev/null", "r") as hwid_proc:
+ self.current_hwid = hwid_proc.read()
+
+ self.hwid_list = self.build_hwid_list()
+ self.pages = len(self.hwid_list) / self.SELECTION_PER_PAGE
+ if len(self.hwid_list) % self.SELECTION_PER_PAGE:
+ self.pages += 1
+
+ self.label = ful.make_label('')
+ test_widget = gtk.EventBox()
+ test_widget.modify_bg(gtk.STATE_NORMAL, ful.BLACK)
+ test_widget.add(self.label)
+ self.render_page()
+
+ ful.run_test_widget(
+ self.job, test_widget,
+ window_registration_callback=self.register_callbacks)
+
+ factory.log('%s run_once finished' % repr(self.__class__))
+ if self._fail_msg:
+ raise error.TestFail(self._fail_msg)
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/firmware_data_key.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/firmware_data_key.vbpubk
deleted file mode 100644
index 804d566..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/firmware_data_key.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/kernel_data_key.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/kernel_data_key.vbpubk
deleted file mode 100644
index 80910b7..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/kernel_data_key.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/kernel_subkey.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/kernel_subkey.vbpubk
deleted file mode 100644
index a24a036..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/kernel_subkey.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/recovery_kernel_data_key.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/recovery_kernel_data_key.vbpubk
deleted file mode 100644
index 3e9e67c..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/recovery_kernel_data_key.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/recovery_key.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/recovery_key.vbpubk
deleted file mode 100644
index 86d2471..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/recovery_key.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/common_data/devkeys/root_key.vbpubk b/client/site_tests/hardware_Components/common_data/devkeys/root_key.vbpubk
deleted file mode 100644
index dfca9d0..0000000
--- a/client/site_tests/hardware_Components/common_data/devkeys/root_key.vbpubk
+++ /dev/null
Binary files differ
diff --git a/client/site_tests/hardware_Components/hardware_Components.py b/client/site_tests/hardware_Components/hardware_Components.py
index 0d8d310..5e8fb07 100644
--- a/client/site_tests/hardware_Components/hardware_Components.py
+++ b/client/site_tests/hardware_Components/hardware_Components.py
@@ -15,38 +15,20 @@
class hardware_Components(test.test):
version = 3
- def run_once(self, approved_dbs='approved_components', do_probe=True):
- # In probe mode, we have to find out the matching HWID, write that into
- # shared data LAST_PROBED_HWID_NAME, and then let factory_WriteGBB to
- # update system. factory_Finalize will verify if that's set correctly.
- #
- # In verify mode, we simply check if current system matches a hardware
- # configuration in the databases.
+ def run_once(self, approved_dbs='approved_components'):
+ # Checks if current system matches a hardware configuration in the
+ # databases.
+ # Currently the files are expected to be inside same folder with
+ # hardware_Components test.
- last_probed_hwid = None
- if not do_probe:
- # Verify, or trust previous probed HWID.
- try:
- last_probed_hwid = factory.get_shared_data(
- factory.LAST_PROBED_HWID_NAME)
- except Exception, e:
- # hardware_Components may run without factory environment
- factory.log('Failed getting shared data, ignored: %s' % repr(e))
-
- # If a hwid was probed, trust it. Otherwise, find best match.
- if last_probed_hwid:
- approved_dbs = last_probed_hwid
- else:
- # Currently the files are expected to be inside same folder with
- # hardware_Components test.
- approved_dbs = os.path.join(self.bindir, approved_dbs)
- sample_approved_dbs = os.path.join(self.bindir,
- 'approved_components.default')
- if (not glob.glob(approved_dbs)) and glob.glob(sample_approved_dbs):
- # Fallback to the default (sample) version
- approved_dbs = sample_approved_dbs
- factory.log('Using default (sample) approved component list: %s'
- % sample_approved_dbs)
+ approved_dbs = os.path.join(self.bindir, approved_dbs)
+ sample_approved_dbs = os.path.join(self.bindir,
+ 'approved_components.default')
+ if (not glob.glob(approved_dbs)) and glob.glob(sample_approved_dbs):
+ # Fallback to the default (sample) version
+ approved_dbs = sample_approved_dbs
+ factory.log('Using default (sample) approved component list: %s'
+ % sample_approved_dbs)
# approved_dbs supports shell-like filename expansion.
existing_dbs = glob.glob(approved_dbs)
@@ -54,15 +36,10 @@
raise error.TestError('Unable to find approved db: %s' %
approved_dbs)
- if do_probe:
- command = 'gooftool --probe --db_path "%s" --verbose' % approved_dbs
- pattern = 'Probed: '
- # The output format is "Probed: PATH"
- else:
- command = ('gooftool --verify_hwid --db_path "%s" --verbose' %
- approved_dbs)
- pattern = 'Verified: '
- # The output format is "Verified: PATH (HWID)", not a pure path.
+ command = ('gooftool --verify_hwid --db_path "%s" --verbose' %
+ approved_dbs)
+ pattern = 'Verified: '
+ # The output format is "Verified: PATH (HWID)", not a pure path.
(stdout, stderr, result) = gooftools.run(command, ignore_status=True)
@@ -96,15 +73,4 @@
raise error.TestFail('HWID matched (%s) with unknown error: %s'
% hwids[0], result)
- # Set the factory state sharead data for factory_WriteGBB
- if do_probe:
- factory.log('Set factory state shared data %s = %s' %
- (factory.LAST_PROBED_HWID_NAME, hwids[0]))
- try:
- factory.set_shared_data(factory.LAST_PROBED_HWID_NAME,
- hwids[0])
- except Exception, e:
- # hardware_Components may run without factory environment
- factory.log('Failed setting shared data, ignored: %s' %
- repr(e))
factory.log('Exact Matched: HWID=%s' % hwids[0])
diff --git a/client/site_tests/suite_Factory/test_list b/client/site_tests/suite_Factory/test_list
index 7462728..9f8000e 100644
--- a/client/site_tests/suite_Factory/test_list
+++ b/client/site_tests/suite_Factory/test_list
@@ -209,9 +209,8 @@
AutomatedSubTest(
label_en='hw-qual-id matching',
label_zw='型號匹配',
- autotest_name='hardware_Components',
- unique_name='hw-qual-id-match',
- dargs={'approved_dbs':'data_*/components*'}),
+ autotest_name='factory_ProbeHWID',
+ unique_name='hw-qual-id-match'),
AutomatedSubTest(
label_en='write GBB',