Autotest: firmware_UpdateKernelVersion and firmware_UpdateKernelDataKeyVersion
These two tests individually modify kernel version and kernel data key version.
On runtime, they modify kernel b directly, and reboot. Then, check the version,
and recovery.
BUG=chrome-os-partner:12442
TEST=run_remote_tests.sh --remote=$REMOTE_IP --board=$BOARD --servo
firmware_UpdateKernelVersion(or firmware_UpdateKernelDataKeyVersion)
Change-Id: Ic3ad3caed47ed6cdffc41d6df6f4696b74d350b7
Reviewed-on: https://gerrit.chromium.org/gerrit/31208
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Commit-Ready: Chun-Ting Chang <ctchang@chromium.org>
Tested-by: Chun-Ting Chang <ctchang@chromium.org>
diff --git a/client/cros/faft_client.py b/client/cros/faft_client.py
index 12863a8..d3c88a9 100644
--- a/client/cros/faft_client.py
+++ b/client/cros/faft_client.py
@@ -472,6 +472,17 @@
"""Increase kernel version for the requested section."""
self._modify_kernel_version(section, 1)
+
+ def retrieve_kernel_version(self, section):
+ """Return kernel version."""
+ return self._kernel_handler.get_version(section)
+
+
+ def retrieve_kernel_datakey_version(self, section):
+ """Return kernel datakey version."""
+ return self._kernel_handler.get_datakey_version(section)
+
+
def diff_kernel_a_b(self):
"""Compare kernel A with B.
@@ -551,7 +562,7 @@
'RW_FWID_A'))
[fwid] = self.run_shell_command_get_output(
- 'eu-strings RW_FWID_A')
+ "cat RW_FWID_A | tr '\\0' '\\t' | cut -f1")
return fwid
@@ -657,6 +668,16 @@
return self._temp_path
+ def get_keys_path(self):
+ """Get keys path in temporary directory."""
+ return self._keys_path
+
+
+ def resign_kernel_with_keys(self, section, key_path=None):
+ """Resign kernel with temporary key."""
+ self._kernel_handler.resign_kernel(section, key_path)
+
+
def cleanup(self):
"""Cleanup for the RPC server. Currently nothing."""
pass
diff --git a/server/site_tests/firmware_UpdateKernelDataKeyVersion/control b/server/site_tests/firmware_UpdateKernelDataKeyVersion/control
new file mode 100644
index 0000000..3389cf4
--- /dev/null
+++ b/server/site_tests/firmware_UpdateKernelDataKeyVersion/control
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 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.
+
+AUTHOR = "Chrome OS Team"
+NAME = "firmware_UpdateKernelDataKeyVersion"
+PURPOSE = """
+Servo based kernel update test which checks the kernel data key version.
+"""
+CRITERIA = """
+This test will fail if one of the following conditions is met:
+1. In Normal Mode.
+2. After update, device restart with KERNEL A.
+3. Kernel datakey version does not increase after update.
+4. After recovery, device can't successfully restart.
+5. Kernel datakey version does not recover to original version after recovery.
+"""
+TIME = "LONG"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "firmware"
+TEST_TYPE = "server"
+
+DOC = """
+This test should run in developer mode. On runtime, this test modifies the
+kernel data key version of kernel b and modifies cgpt to reboot with kernel b.
+Check kernel data key version after reboot, and then recover kernel b's data
+key version to original version. Here also tries to reboot with kernel b after
+recovery. If sccuess, reboot with kernel a.
+"""
+
+def run_updatekerneldatakeyversion(machine):
+ host = hosts.create_host(machine)
+ job.run_test("firmware_UpdateKernelDataKeyVersion", host=host,
+ cmdline_args=args,use_faft=True, disable_sysinfo=True,
+ dev_mode=True, tag="dev")
+
+parallel_simple(run_updatekerneldatakeyversion, machines)
diff --git a/server/site_tests/firmware_UpdateKernelDataKeyVersion/files/make_keys.sh b/server/site_tests/firmware_UpdateKernelDataKeyVersion/files/make_keys.sh
new file mode 100755
index 0000000..ae37ce1
--- /dev/null
+++ b/server/site_tests/firmware_UpdateKernelDataKeyVersion/files/make_keys.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. "$(dirname "$0")/common.sh"
+
+KDATAKEY_VERSION=$1
+
+# TODO(ctchang) Modify this after adding dumpRSAPublicKey to image
+PATH=$PATH:/usr/local/sbin/firmware/saft
+export PATH
+
+pushd /var/tmp/faft/autest/keys
+
+make_pair "kernel_data_key" $KERNEL_DATAKEY_ALGOID $KDATAKEY_VERSION
+make_keyblock "kernel" $KERNEL_KEYBLOCK_MODE "kernel_data_key" "kernel_subkey"
+
+popd
diff --git a/server/site_tests/firmware_UpdateKernelDataKeyVersion/firmware_UpdateKernelDataKeyVersion.py b/server/site_tests/firmware_UpdateKernelDataKeyVersion/firmware_UpdateKernelDataKeyVersion.py
new file mode 100644
index 0000000..80e6f9f
--- /dev/null
+++ b/server/site_tests/firmware_UpdateKernelDataKeyVersion/firmware_UpdateKernelDataKeyVersion.py
@@ -0,0 +1,115 @@
+# Copyright (c) 2012 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 logging, os, time
+from autotest_lib.server.cros.faftsequence import FAFTSequence
+from autotest_lib.client.common_lib import error
+
+
+class firmware_UpdateKernelDataKeyVersion(FAFTSequence):
+ """
+ This test should run in developer mode. On runtime, this test modifies the
+ kernel data key version of kernel b and modifies cgpt to reboot with kernel
+ b. Check kernel data key version after reboot, and then recover kernel b's
+ data key version to original version. Here also tries to reboot with kernel
+ b after recovery. If sccuess, reboot with kernel a.
+ """
+ version = 1
+
+ def check_kernel_datakey_version(self, expected_ver):
+ actual_ver = self.faft_client.retrieve_kernel_datakey_version('b')
+ if actual_ver != expected_ver:
+ raise error.TestFail(
+ 'Kernel Version should be %s, but got %s.'
+ % (expected_ver, actual_ver))
+ else:
+ logging.info(
+ 'Update success, now version is %s'
+ % actual_ver)
+
+
+ def resign_kernel_datakey_version(self, host):
+ host.send_file(os.path.join(
+ '~/trunk/src/platform/vboot_reference/scripts',
+ 'keygeneration/common.sh'),
+ os.path.join(self.faft_client.get_temp_path(),
+ 'common.sh'))
+ host.send_file(os.path.join('~/trunk/src/third_party/autotest/files/',
+ 'server/site_tests',
+ 'firmware_UpdateKernelDataKeyVersion',
+ 'files/make_keys.sh'),
+ os.path.join(self.faft_client.get_temp_path(),
+ 'make_keys.sh'))
+ # TODO(ctchang) Delete this after adding dumpRSAPublicKey to image
+ host.send_file(os.path.join('/usr/bin/dumpRSAPublicKey'),
+ '/usr/local/sbin/firmware/saft/dumpRSAPublicKey')
+
+ self.faft_client.run_shell_command('/bin/bash %s %s' % (
+ os.path.join(self.faft_client.get_temp_path(), 'make_keys.sh'),
+ self._update_version))
+
+
+ def modify_kernel_b_and_set_cgpt_priority(self, delta, target_dev):
+ if delta == 1:
+ self.faft_client.resign_kernel_with_keys(
+ 'b', self.faft_client.get_keys_path())
+ elif delta == -1:
+ self.check_kernel_datakey_version(self._update_version)
+ self.faft_client.resign_kernel_with_keys('b')
+
+ if target_dev == 'a':
+ self.reset_and_prioritize_kernel('a')
+ else:
+ self.reset_and_prioritize_kernel('b')
+
+
+ def setup(self, host=None, dev_mode=True):
+ super(firmware_UpdateKernelDataKeyVersion, self).setup()
+
+ self.setup_dev_mode(dev_mode)
+
+ actual_ver = self.faft_client.retrieve_kernel_datakey_version('b')
+ logging.info('Original Kernel Version of KERN-B is %s' % actual_ver)
+
+ self._update_version = actual_ver + 1
+ logging.info('KERN-B will update to version %s' % self._update_version)
+
+ self.setup_kernel('a')
+ self.faft_client.setup_firmwareupdate_temp_dir()
+ self.resign_kernel_datakey_version(host)
+
+
+ def cleanup(self):
+ self.faft_client.cleanup_firmwareupdate_temp_dir()
+ super(firmware_UpdateKernelDataKeyVersion, self).cleanup()
+
+
+ def run_once(self, host=None):
+ self.register_faft_sequence((
+ { # Step 1, Update Kernel Data Key Version.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'a'),
+ 'userspace_action': (
+ self.modify_kernel_b_and_set_cgpt_priority,
+ 1, 'b')
+ },
+ { # Step 2, Check kernel data key version and rollback.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'b'),
+ 'userspace_action': (
+ self.modify_kernel_b_and_set_cgpt_priority,
+ -1, 'b')
+ },
+ { # Step 3, Boot with rollback kernel and change boot priority.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'b'),
+ 'userspace_action':(
+ self.modify_kernel_b_and_set_cgpt_priority,
+ 0, 'a')
+ },
+ { # Step 4, Check rollback version.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'a'),
+ 'userspace_action': (self.check_kernel_datakey_version,
+ self._update_version - 1)
+ }
+ ))
+
+ self.run_faft_sequence()
diff --git a/server/site_tests/firmware_UpdateKernelVersion/control b/server/site_tests/firmware_UpdateKernelVersion/control
new file mode 100644
index 0000000..8f8f64f
--- /dev/null
+++ b/server/site_tests/firmware_UpdateKernelVersion/control
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 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.
+
+AUTHOR = "Chrome OS Team"
+NAME = "firmware_UpdateKernelVersion"
+PURPOSE = "Servo based kernel update test which checks the kernel version."
+CRITERIA = """
+This test will fail if one of the following conditions is met:
+1. In Normal Mode.
+2. After update, device restart with KERNEL A.
+3. Kernel version does not increase after update.
+4. After recovery, device can't successfully restart.
+5. Kernel version does not recover to original version after recovery.
+"""
+TIME = "LONG"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "firmware"
+TEST_TYPE = "server"
+
+DOC = """
+This test should run in developer mode. On runtime, this test modifies the
+kernel version of kernel b and modifies cgpt to reboot with kernel b. Check
+kernel version after reboot, and then recover kernel b version to original
+version. Here also tries to reboot with kernel b after recovery. If sccuess,
+reboot with kernel a.
+"""
+
+def run_updatekernelversion(machine):
+ host = hosts.create_host(machine)
+ job.run_test("firmware_UpdateKernelVersion", host=host, cmdline_args=args,
+ use_faft=True, disable_sysinfo=True,
+ dev_mode=True, tag="dev")
+
+parallel_simple(run_updatekernelversion, machines)
diff --git a/server/site_tests/firmware_UpdateKernelVersion/firmware_UpdateKernelVersion.py b/server/site_tests/firmware_UpdateKernelVersion/firmware_UpdateKernelVersion.py
new file mode 100644
index 0000000..2c90d21
--- /dev/null
+++ b/server/site_tests/firmware_UpdateKernelVersion/firmware_UpdateKernelVersion.py
@@ -0,0 +1,91 @@
+# Copyright (c) 2012 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 logging, time
+from autotest_lib.server.cros.faftsequence import FAFTSequence
+from autotest_lib.client.common_lib import error
+
+
+class firmware_UpdateKernelVersion(FAFTSequence):
+ """
+ This is a servod based kernel update test which should run in developer
+ mode. On runtime, this test modifies the kernel version of kernel b and
+ modifies cgpt to reboot with kernel b. Check kernel version after reboot,
+ and then recover kernel b version to original version. Here also tries to
+ reboot with kernel b after recovery. If sccuess, reboot with kernel a.
+ """
+ version = 1
+
+ def check_kernel_version(self, expected_ver):
+ actual_ver = self.faft_client.retrieve_kernel_version('b')
+ if actual_ver != expected_ver:
+ raise error.TestFail(
+ 'Kernel Version should be %s, but got %s.'
+ % (expected_ver, actual_ver))
+ else:
+ logging.info(
+ 'Update success, now version is %s'
+ % actual_ver)
+
+
+ def modify_kernel_b_and_set_cgpt_priority(self, delta, target_dev):
+ if delta == 1:
+ self.faft_client.move_kernel_forward('b')
+ elif delta == -1:
+ self.check_kernel_version(self._update_version)
+ self.faft_client.move_kernel_backward('b')
+
+ if target_dev == 'a':
+ self.reset_and_prioritize_kernel('a')
+ else:
+ self.reset_and_prioritize_kernel('b')
+
+
+ def setup(self, dev_mode=True):
+ super(firmware_UpdateKernelVersion, self).setup()
+
+ self.setup_dev_mode(dev_mode)
+
+ actual_ver = self.faft_client.retrieve_kernel_version('b')
+ logging.info('Original Kernel Version of KERN-B is %s' % actual_ver)
+
+ self._update_version = actual_ver + 1
+ logging.info('KERN-B will update to version %s' % self._update_version)
+
+ self.setup_kernel('a')
+
+
+ def cleanup(self):
+ super(firmware_UpdateKernelVersion, self).cleanup()
+
+
+ def run_once(self, host=None):
+ self.register_faft_sequence((
+ { # Step 1, Update Kernel Version.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'a'),
+ 'userspace_action': (
+ self.modify_kernel_b_and_set_cgpt_priority,
+ 1, 'b'
+ )
+ },
+ { # Step 2, Check kernel version and rollback.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'b'),
+ 'userspace_action': (
+ self.modify_kernel_b_and_set_cgpt_priority,
+ -1, 'b')
+ },
+ { # Step 3, Boot with rollback kernel and change boot priority.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'b'),
+ 'userspace_action':(
+ self.modify_kernel_b_and_set_cgpt_priority,
+ 0, 'a')
+ },
+ { # Step 4, Check rollback version.
+ 'state_checker': (self.check_root_part_on_non_recovery, 'a'),
+ 'userspace_action': (self.check_kernel_version,
+ self._update_version - 1)
+ }
+ ))
+
+ self.run_faft_sequence()