gooftool: add 'verify_cros_config'
This command will:
* Check if RLZ code is nonempty and not 'ZZCR'
* Compare the content of /usr/share/chromeos-config/yaml/config.yaml,
check if current model has the same set of identity and brand-code
defined.
BUG=b:147011183
TEST=make test
Change-Id: I3e7cf00eda0837e2c1fecfb913642a6ba7601219
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/1986595
Reviewed-by: Yong Hong <yhong@chromium.org>
Reviewed-by: Philip Chen <philipchen@chromium.org>
Commit-Queue: Wei-Han Chen <stimim@chromium.org>
Tested-by: Wei-Han Chen <stimim@chromium.org>
diff --git a/py/gooftool/commands.py b/py/gooftool/commands.py
index 657561b..fa59fc0 100755
--- a/py/gooftool/commands.py
+++ b/py/gooftool/commands.py
@@ -357,6 +357,12 @@
options.enforced_release_channels)
+@Command('verify_cros_config')
+def VerifyCrosConfig(options):
+ """Verify entries in cros config make sense."""
+ return GetGooftool(options).VerifyCrosConfig()
+
+
@Command('write_protect')
def EnableFwWp(options):
"""Enable then verify firmware write protection."""
@@ -545,6 +551,7 @@
VerifyTPM(options)
VerifyVPD(options)
VerifyReleaseChannel(options)
+ VerifyCrosConfig(options)
@Command('untar_stateful_files')
diff --git a/py/gooftool/core.py b/py/gooftool/core.py
index 1711ed7..d8657ed 100644
--- a/py/gooftool/core.py
+++ b/py/gooftool/core.py
@@ -18,6 +18,7 @@
from six import iteritems
from six import reraise as raise_
+import yaml
import factory_common # pylint: disable=unused-import
from cros.factory.gooftool.bmpblk import unpack_bmpblock
@@ -36,6 +37,8 @@
from cros.factory.test.rules.registration_codes import RegistrationCode
from cros.factory.utils import config_utils
from cros.factory.utils import file_utils
+from cros.factory.utils import json_utils
+from cros.factory.utils import sys_utils
from cros.factory.utils.type_utils import Error
# The mismatch result tuple.
@@ -448,6 +451,54 @@
'Enforced channels are %s.' % (
release_channel, enforced_channels))
+ def VerifyCrosConfig(self):
+ """Verify that entries in cros config make sense."""
+ if phase.GetPhase() >= phase.PVT_DOGFOOD:
+ # The value actually comes from "cros_config / brand-code", however,
+ # most scripts are still using "mosys platform brand" to get the value,
+ # so we also check the value by mosys command.
+ rlz = self._util.shell(['mosys', 'platform', 'brand']).stdout.strip()
+ if not rlz or rlz == 'ZZCR':
+ # this is incorrect...
+ raise Error('RLZ code "%s" is not allowed in PVT' % rlz)
+
+ model = self._util.shell(['mosys', 'platform', 'model']).stdout.strip()
+ if not model:
+ raise Error('Model name is empty')
+
+ def _ParseCrosConfig(config_path):
+ with open(config_path) as f:
+ obj = yaml.load(f)
+ fields = ['name', 'identity', 'brand-code']
+ configs = [
+ {
+ field: config[field] for field in fields
+ }
+ for config in obj['chromeos']['configs']
+ if config['name'] == model
+ ]
+ configs = {
+ # set sort_keys=True to make the result stable.
+ json_utils.DumpStr(config, sort_keys=True) for config in configs
+ }
+ return configs
+
+ # Load config.yaml from release image (FSI) and test image, and compare the
+ # fields we cared about.
+ config_path = 'usr/share/chromeos-config/yaml/config.yaml'
+ test_configs = _ParseCrosConfig(os.path.join('/', config_path))
+ with sys_utils.Mountpartition(
+ self._util.GetReleaseRootPartitionPath()) as root:
+ release_configs = _ParseCrosConfig(os.path.join(root, config_path))
+
+ if test_configs != release_configs:
+ error = ['Detect different chromeos-config between test image and FSI.']
+ error += ['Configs in test image:']
+ error += ['\t' + config for config in test_configs]
+ error += ['Configs in FSI:']
+ error += ['\t' + config for config in release_configs]
+ raise Error('\n'.join(error))
+
def ClearGBBFlags(self):
"""Zero out the GBB flags, in preparation for transition to release state.