gooftool: Fix broken Verify, Finalize command.
The positional arguments for gooftool sub commands may cause chained
commands to fail. For example, in the command chain
finalize => verify => verify_keys,
If a parameter is defined only in verify_keys, when we invoke finalize
command then the arg in options would be missing (because the real one
gets parsed is "finalize").
The only solution is to not use positional arguments. Changed the
positional argument for verify_rootfs, verify_system_time to
'release_rootfs', and the argument for firmware in verify_keys to be
'firmware_path'.
New format:
gooftool verify_rootfs --release_rootfs /dev/mmcblk0p3
gooftool verify_systsem_time --release_rootfs /dev/sda3
gooftool verify_keys --release_rootfs /dev/sda3 --firmware_path image.bin
The shell script shortcuts are also removed to prevent confusion.
BUG=chromium:573933
TEST=make test; gooftool verify_keys; gooftool verify
Change-Id: I33af20faf1ab8ba7b1fa70e9aabaad0a5c393bc7
Reviewed-on: https://chromium-review.googlesource.com/339160
Commit-Ready: Hung-Te Lin <hungte@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/py/gooftool/commands.py b/py/gooftool/commands.py
index 48b59bc..dc17490 100755
--- a/py/gooftool/commands.py
+++ b/py/gooftool/commands.py
@@ -139,6 +139,11 @@
'--enforced_release_channels', nargs='*', default=None,
help='Enforced release image channels.')
+_release_rootfs_cmd_arg = CmdArg(
+ '--release_rootfs', help='Location of release image rootfs partition.')
+
+_firmware_path_cmd_arg = CmdArg(
+ '--firmware_path', help='Location of firmware image partition.')
@Command('best_match_hwids',
_hwdb_path_cmd_arg,
@@ -509,12 +514,12 @@
@Command('verify_keys',
- CmdArg('kernel_device', nargs='?', help='Kernel device to verify.'),
- CmdArg('main_firmware', nargs='?', help='Main firmware image file.'))
+ _release_rootfs_cmd_arg,
+ _firmware_path_cmd_arg)
def VerifyKeys(options): # pylint: disable=W0613
"""Verify keys in firmware and SSD match."""
return GetGooftool(options).VerifyKeys(
- options.kernel_device, options.main_firmware)
+ options.release_rootfs, options.firmware_path)
@Command('set_fw_bitmap_locale')
@@ -527,15 +532,15 @@
@Command('verify_system_time',
- CmdArg('root_dev', nargs='?', help='Root device to check.'))
+ _release_rootfs_cmd_arg)
def VerifySystemTime(options): # pylint: disable=W0613
"""Verify system time is later than release filesystem creation time."""
- return GetGooftool(options).VerifySystemTime(options.root_dev)
+ return GetGooftool(options).VerifySystemTime(options.release_rootfs)
@Command('verify_rootfs',
- CmdArg('release_rootfs', nargs='?', help='Release root file system.'))
+ _release_rootfs_cmd_arg)
def VerifyRootFs(options): # pylint: disable=W0613
"""Verify rootfs on SSD is valid by checking hash."""
@@ -724,6 +729,8 @@
_hwid_cmd_arg,
_rma_mode_cmd_arg,
_cros_core_cmd_arg,
+ _release_rootfs_cmd_arg,
+ _firmware_path_cmd_arg,
_enforced_release_channels_cmd_arg)
def Verify(options):
"""Verifies if whole factory process is ready for finalization.
@@ -906,6 +913,8 @@
_hwid_cmd_arg,
_rma_mode_cmd_arg,
_cros_core_cmd_arg,
+ _release_rootfs_cmd_arg,
+ _firmware_path_cmd_arg,
_enforced_release_channels_cmd_arg)
def Finalize(options):
"""Verify system readiness and trigger transition into release state.
diff --git a/py/gooftool/common.py b/py/gooftool/common.py
index 282911d..80fd2d3 100644
--- a/py/gooftool/common.py
+++ b/py/gooftool/common.py
@@ -104,6 +104,15 @@
return ''.join(re.findall(
r'(.*[^0-9][0-9]+)p[0-9]+|(.*[^0-9])[0-9]+', path)[0])
+ def GetDevicePartition(self, device, partition):
+ """Returns a partition path from device path string.
+
+ /dev/sda, 1 => /dev/sda1.
+ /dev/mmcblk0p, 2 => /dev/mmcblk0p2.
+ """
+ return ('%sp%s' if device[-1].isdigit() else '%s%s') % (device, partition)
+
+
def FindScript(self, script_name):
"""Finds the script under /usr/local/factory/sh
@@ -165,6 +174,15 @@
return self.GetPrimaryDevicePath(4)
+ def GetReleaseKernelPathFromRootPartition(self, rootfs_path):
+ """Gets the path for release kernel from given rootfs path.
+
+ This function assumes kernel partition is always located before rootfs.
+ """
+ device = self.GetPartitionDevice(rootfs_path)
+ kernel_index = int(rootfs_path[-1]) - 1
+ return self.GetDevicePartition(device, kernel_index)
+
def GetReleaseImageLsbData(self):
"""Gets the /etc/lsb-release content from release image partition.
diff --git a/py/gooftool/core.py b/py/gooftool/core.py
index c220bad..b6881b6 100644
--- a/py/gooftool/core.py
+++ b/py/gooftool/core.py
@@ -231,17 +231,24 @@
return mismatches
- def VerifyKeys(self, kernel_dev=None, firmware_path=None, _tmpexec=None):
+ def VerifyKeys(self, release_rootfs=None, firmware_path=None, _tmpexec=None):
"""Verify keys in firmware and SSD match.
+ The real partition needed is the kernel partition. However, in order to
+ share params with other commands, we use release_rootfs and calculate the
+ real kernel location from it.
+
Args:
- kernel_dev: A string for kernel device path.
+ release_rootfs: A string for release image rootfs path.
firmware_path: A string for firmware image file path.
_tmpexec: A function for overriding execution inside temp folder.
"""
+ if release_rootfs is None:
+ release_rootfs = self._util.GetReleaseRootPartitionPath()
- if kernel_dev is None:
- kernel_dev = self._util.GetReleaseKernelPartitionPath()
+ kernel_dev = self._util.GetReleaseKernelPathFromRootPartition(
+ release_rootfs)
+
if firmware_path is None:
firmware_path = self._crosfw.LoadMainFirmware().GetFileName()
firmware_image = self._crosfw.LoadMainFirmware().GetFirmwareImage()
@@ -331,33 +338,34 @@
logging.info('SUCCESS: Verification completed.')
- def VerifySystemTime(self, root_dev=None, system_time=None):
+ def VerifySystemTime(self, release_rootfs=None, system_time=None):
"""Verify system time is later than release filesystem creation time."""
- if root_dev is None:
- root_dev = self._util.GetReleaseRootPartitionPath()
+ if release_rootfs is None:
+ release_rootfs = self._util.GetReleaseRootPartitionPath()
if system_time is None:
system_time = time.time()
- e2header = self._util.shell('dumpe2fs -h %s' % root_dev)
+ e2header = self._util.shell('dumpe2fs -h %s' % release_rootfs)
if not e2header.success:
raise Error('Failed to read file system: %s, %s' %
- (root_dev, e2header.stderr))
+ (release_rootfs, e2header.stderr))
matched = re.findall(r'^Filesystem created: *(.*)', e2header.stdout,
re.MULTILINE)
if not matched:
- raise Error('Failed to find file system creation time: %s' % root_dev)
+ raise Error('Failed to find file system creation time: %s' %
+ release_rootfs)
created_time = time.mktime(time.strptime(matched[0]))
logging.debug('Comparing system time <%s> and filesystem time <%s>',
system_time, created_time)
if system_time < created_time:
raise Error('System time (%s) earlier than file system (%s) creation '
- 'time (%s)' % (system_time, root_dev, created_time))
+ 'time (%s)' % (system_time, release_rootfs, created_time))
- def VerifyRootFs(self, root_dev=None):
+ def VerifyRootFs(self, release_rootfs=None):
"""Verify rootfs on SSD is valid by checking hash."""
- if root_dev is None:
- root_dev = self._util.GetReleaseRootPartitionPath()
- device = self._util.GetPartitionDevice(root_dev)
+ if release_rootfs is None:
+ release_rootfs = self._util.GetReleaseRootPartitionPath()
+ device = self._util.GetPartitionDevice(release_rootfs)
# TODO(hungte) Using chromeos_invoke_postinst here is leaving a window
# where unexpected reboot or test exit may cause the system to boot into
@@ -367,7 +375,7 @@
try:
# Always rollback GPT changes.
curr_attrs = self._util.GetCgptAttributes(device)
- self._util.InvokeChromeOSPostInstall(root_dev)
+ self._util.InvokeChromeOSPostInstall(release_rootfs)
finally:
self._util.SetCgptAttributes(curr_attrs, device)
diff --git a/py/gooftool/gooftool_unittest.py b/py/gooftool/gooftool_unittest.py
index fe76dd4..3d6f2c4 100755
--- a/py/gooftool/gooftool_unittest.py
+++ b/py/gooftool/gooftool_unittest.py
@@ -300,6 +300,8 @@
ValueError, self._gooftool.FindBOMMismatches, 'BENDER', 'LEELA', None)
def testVerifyKey(self):
+ self._gooftool._util.GetReleaseKernelPathFromRootPartition(
+ '/dev/null').AndReturn('/dev/zero')
self._gooftool._crosfw.LoadMainFirmware().AndReturn(MockMainFirmware())
self._gooftool._crosfw.LoadMainFirmware().AndReturn(MockMainFirmware(
MockFirmwareImage({'GBB': 'GBB', 'FW_MAIN_A': 'MA', 'FW_MAIN_B': 'MB',
@@ -326,7 +328,7 @@
self._gooftool.VerifySystemTime(system_time=good_system_time)
self.assertRaises(Error, self._gooftool.VerifySystemTime,
- root_dev='root', system_time=bad_system_time)
+ release_rootfs='root', system_time=bad_system_time)
def testVerifyRootFs(self):
fake_attrs = {'test': 'value'}