gooftool: Add VerifyCBIEEPROMWPStatus function
For some devices, we may want to use two different HW. One turns on HW
protection of the CBI EEPROM and the other doesn't after the factory
mode is disabled.
To make sure that the correct hardware is used, we need to check that
the CBI EEPROM behaves correctly after the factory mode is disabled.
New behavior of gooftool:
- By default, checks that the CBI EEPROM is locked.
- If '--cbi_eeprom_wp_status Unlocked' is specified, checks that the CBI
EEPROM is not locked.
- If '--cbi_eeprom_wp_status Absent' is specified, checks that the CBI
EEPROM is absent.
New behavior of GRTFinalize:
- By default, checks that the CBI EEPROM is locked in all phases.
- By setting constants.grt.cbi_eepromi_wp_status to 'Unlocked' in the
test list, checks that the CBI EEPROM is locked in PVT and the CBI
EEPROM is not locked in other phases.
- By setting constants.grt.cbi_eeprom_wp_status to 'Absent' in the test
list, checks that CBI EEPROM is absent.
BUG=b:173770418
TEST=gooftool -v 4 verify_cbi_eeprom_wp_status \
=> This checks CBI WP is enabled
TEST=gooftool -v 4 verify_cbi_eeprom_wp_status \
--cbi_eeprom_wp_status Unlocked => This checks CBI WP is disabled
TEST=gooftool -v 4 verify_cbi_eeprom_wp_status \
--cbi_eeprom_wp_status Absent => This checks CBI is absent
TEST=gooftool -v 4 verify
TEST=gooftool -v 4 verify --cbi_eeprom_wp_status Unlocked
TEST=gooftool -v 4 verify --cbi_eeprom_wp_status Absent
TEST=run GRTFinalize with constants.grt.cbi_eeprom_wp_status: "Locked"
TEST=run GRTFinalize with constants.grt.cbi_eeprom_wp_status: "Unlocked"
TEST=run GRTFinalize with constants.grt.cbi_eeprom_wp_status: "Absent"
Change-Id: I47ccc6329b8e8bae8e78ab60e735d92a2931b399
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/2560337
Reviewed-by: Cheng-Han Yang <chenghan@chromium.org>
Tested-by: Cheng Yueh <cyueh@chromium.org>
Commit-Queue: Cheng Yueh <cyueh@chromium.org>
diff --git a/py/gooftool/commands.py b/py/gooftool/commands.py
index a808d67..ed235ba 100755
--- a/py/gooftool/commands.py
+++ b/py/gooftool/commands.py
@@ -35,6 +35,7 @@
from cros.factory.test.rules import phase
from cros.factory.test.rules.privacy import FilterDict
from cros.factory.test import state
+from cros.factory.test.utils.cbi_utils import CbiEepromWpStatus
from cros.factory.utils import argparse_utils
from cros.factory.utils.argparse_utils import CmdArg
from cros.factory.utils.argparse_utils import ParseCmdline
@@ -270,6 +271,11 @@
'--enable_zero_touch', action='store_true',
help='Set attested_device_id for zero-touch feature.')
+_cbi_eeprom_wp_status_cmd_arg = CmdArg(
+ '--cbi_eeprom_wp_status', type=str, default=CbiEepromWpStatus.Locked,
+ choices=CbiEepromWpStatus,
+ help='The expected status of CBI EEPROM after factory mode disabled.')
+
@Command(
'verify_ec_key',
@@ -380,6 +386,22 @@
GetGooftool(options).VerifySnBits()
+@Command(
+ 'verify_cbi_eeprom_wp_status',
+ _cbi_eeprom_wp_status_cmd_arg,
+)
+def VerifyCBIEEPROMWPStatus(options):
+ """Verify CBI EEPROM status.
+
+ If cbi_eeprom_wp_status is Absent, CBI EEPROM must be absent. If
+ cbi_eeprom_wp_status is Locked, write protection must be on. Otherwise, write
+ protection must be off.
+ """
+
+ return GetGooftool(options).VerifyCBIEEPROMWPStatus(
+ options.cbi_eeprom_wp_status)
+
+
@Command('write_protect')
def EnableFwWp(options):
"""Enable then verify firmware write protection."""
@@ -572,27 +594,30 @@
options.test_umount)
-@Command('verify',
- _hwid_status_list_cmd_arg,
- _hwdb_path_cmd_arg,
- _project_cmd_arg,
- _probe_results_cmd_arg,
- _hwid_cmd_arg,
- _hwid_run_vpd_cmd_arg,
- _hwid_vpd_data_file_cmd_arg,
- _no_write_protect_cmd_arg,
- _rma_mode_cmd_arg,
- _cros_core_cmd_arg,
- _has_ec_pubkey_cmd_arg,
- _ec_pubkey_path_cmd_arg,
- _ec_pubkey_hash_cmd_arg,
- _release_rootfs_cmd_arg,
- _firmware_path_cmd_arg,
- _enforced_release_channels_cmd_arg,
- _waive_list_cmd_arg,
- _skip_list_cmd_arg,
- _no_ectool_cmd_arg,
- _enable_zero_touch_cmd_arg)
+@Command(
+ 'verify',
+ _hwid_status_list_cmd_arg,
+ _hwdb_path_cmd_arg,
+ _project_cmd_arg,
+ _probe_results_cmd_arg,
+ _hwid_cmd_arg,
+ _hwid_run_vpd_cmd_arg,
+ _hwid_vpd_data_file_cmd_arg,
+ _no_write_protect_cmd_arg,
+ _rma_mode_cmd_arg,
+ _cros_core_cmd_arg,
+ _has_ec_pubkey_cmd_arg,
+ _ec_pubkey_path_cmd_arg,
+ _ec_pubkey_hash_cmd_arg,
+ _release_rootfs_cmd_arg,
+ _firmware_path_cmd_arg,
+ _enforced_release_channels_cmd_arg,
+ _waive_list_cmd_arg,
+ _skip_list_cmd_arg,
+ _no_ectool_cmd_arg,
+ _enable_zero_touch_cmd_arg,
+ _cbi_eeprom_wp_status_cmd_arg,
+)
def Verify(options):
"""Verifies if whole factory process is ready for finalization.
@@ -605,6 +630,7 @@
if not options.no_write_protect:
VerifyWPSwitch(options)
VerifyManagementEngineLocked(options)
+ VerifyCBIEEPROMWPStatus(options)
VerifyHWID(options)
VerifySystemTime(options)
if options.has_ec_pubkey:
@@ -808,39 +834,42 @@
raise Error('unknown report upload method %r' % method)
-@Command('finalize',
- CmdArg('--fast', action='store_true',
- help='use non-secure but faster wipe method.'),
- _no_ectool_cmd_arg,
- _shopfloor_url_args_cmd_arg,
- _hwdb_path_cmd_arg,
- _hwid_status_list_cmd_arg,
- _upload_method_cmd_arg,
- _upload_max_retry_times_arg,
- _upload_retry_interval_arg,
- _upload_allow_fail_arg,
- _add_file_cmd_arg,
- _probe_results_cmd_arg,
- _hwid_cmd_arg,
- _hwid_run_vpd_cmd_arg,
- _hwid_vpd_data_file_cmd_arg,
- _no_write_protect_cmd_arg,
- _rma_mode_cmd_arg,
- _cros_core_cmd_arg,
- _has_ec_pubkey_cmd_arg,
- _ec_pubkey_path_cmd_arg,
- _ec_pubkey_hash_cmd_arg,
- _release_rootfs_cmd_arg,
- _firmware_path_cmd_arg,
- _enforced_release_channels_cmd_arg,
- _station_ip_cmd_arg,
- _station_port_cmd_arg,
- _wipe_finish_token_cmd_arg,
- _rlz_embargo_end_date_offset_cmd_arg,
- _waive_list_cmd_arg,
- _skip_list_cmd_arg,
- _no_generate_mfg_date_cmd_arg,
- _enable_zero_touch_cmd_arg)
+@Command(
+ 'finalize',
+ CmdArg('--fast', action='store_true',
+ help='use non-secure but faster wipe method.'),
+ _no_ectool_cmd_arg,
+ _shopfloor_url_args_cmd_arg,
+ _hwdb_path_cmd_arg,
+ _hwid_status_list_cmd_arg,
+ _upload_method_cmd_arg,
+ _upload_max_retry_times_arg,
+ _upload_retry_interval_arg,
+ _upload_allow_fail_arg,
+ _add_file_cmd_arg,
+ _probe_results_cmd_arg,
+ _hwid_cmd_arg,
+ _hwid_run_vpd_cmd_arg,
+ _hwid_vpd_data_file_cmd_arg,
+ _no_write_protect_cmd_arg,
+ _rma_mode_cmd_arg,
+ _cros_core_cmd_arg,
+ _has_ec_pubkey_cmd_arg,
+ _ec_pubkey_path_cmd_arg,
+ _ec_pubkey_hash_cmd_arg,
+ _release_rootfs_cmd_arg,
+ _firmware_path_cmd_arg,
+ _enforced_release_channels_cmd_arg,
+ _station_ip_cmd_arg,
+ _station_port_cmd_arg,
+ _wipe_finish_token_cmd_arg,
+ _rlz_embargo_end_date_offset_cmd_arg,
+ _waive_list_cmd_arg,
+ _skip_list_cmd_arg,
+ _no_generate_mfg_date_cmd_arg,
+ _enable_zero_touch_cmd_arg,
+ _cbi_eeprom_wp_status_cmd_arg,
+)
def Finalize(options):
"""Verify system readiness and trigger transition into release state.
diff --git a/py/gooftool/core.py b/py/gooftool/core.py
index 55426b2..eef96ec 100644
--- a/py/gooftool/core.py
+++ b/py/gooftool/core.py
@@ -34,6 +34,7 @@
from cros.factory.test.rules.privacy import FilterDict
from cros.factory.test.rules import registration_codes
from cros.factory.test.rules.registration_codes import RegistrationCode
+from cros.factory.test.utils import cbi_utils
from cros.factory.utils import config_utils
from cros.factory.utils import file_utils
from cros.factory.utils import json_utils
@@ -661,6 +662,12 @@
if 'BoardID is set' in stdout:
logging.warning('SN Bits cannot be set anymore.')
+ def VerifyCBIEEPROMWPStatus(self, cbi_eeprom_wp_status):
+ """Verifies CBI EEPROM write protection status."""
+
+ cbi_utils.VerifyCbiEepromWpStatus(self._util.sys_interface,
+ cbi_eeprom_wp_status)
+
def GetBitmapLocales(self, image_file):
"""Get bitmap locales
diff --git a/py/test/pytests/finalize.py b/py/test/pytests/finalize.py
index 5d6bf17..06abaaa 100644
--- a/py/test/pytests/finalize.py
+++ b/py/test/pytests/finalize.py
@@ -111,6 +111,7 @@
from cros.factory.test import session
from cros.factory.test import state
from cros.factory.test import test_case
+from cros.factory.test.utils import cbi_utils
from cros.factory.test.utils import deploy_utils
from cros.factory.test.utils import update_utils
from cros.factory.testlog import testlog
@@ -136,27 +137,24 @@
class Finalize(test_case.TestCase):
"""The main class for finalize pytest."""
ARGS = [
- Arg('write_protection', bool,
- 'Check and enable write protection.', default=None),
+ Arg('write_protection', bool, 'Check and enable write protection.',
+ default=None),
Arg('has_ectool', bool, 'Has ectool utility or not.', default=True),
Arg('secure_wipe', bool,
'Wipe the stateful partition securely (False for a fast wipe).',
default=True),
- Arg('upload_method', str,
- 'Upload method for "gooftool finalize"',
+ Arg('upload_method', str, 'Upload method for "gooftool finalize"',
default=None),
Arg('upload_max_retry_times', int,
- 'Number of tries to upload. 0 to retry infinitely.',
- default=0),
+ 'Number of tries to upload. 0 to retry infinitely.', default=0),
Arg('upload_retry_interval', int,
- 'Retry interval in seconds between retries.',
- default=None),
+ 'Retry interval in seconds between retries.', default=None),
Arg('upload_allow_fail', bool,
- 'Continue finalize if report upload fails, instead of raising error.',
- default=False),
- Arg('enable_factory_server', bool,
+ ('Continue finalize if report upload fails, instead of raising error.'
+ ), default=False),
+ Arg('enable_factory_server', bool, (
'Perform factory server operations: update HWID data and flush event '
- 'logs.', default=True),
+ 'logs.'), default=True),
Arg('hwid_need_vpd', bool,
'Whether the HWID validation process needs the vpd data.',
default=False),
@@ -166,35 +164,34 @@
Arg('is_cros_core', bool,
'For ChromeOS Core device, skip setting firmware bitmap locale.',
default=False),
- Arg('has_ec_pubkey', bool,
- 'Perform VerifyECKey.',
- default=None),
+ Arg('has_ec_pubkey', bool, 'Perform VerifyECKey.', default=None),
Arg('enforced_release_channels', list,
- 'A list of string indicating the enforced release image channels. '
- 'Each item should be one of "dev", "beta" or "stable".',
+ ('A list of string indicating the enforced release image channels. '
+ 'Each item should be one of "dev", "beta" or "stable".'),
default=None),
Arg('ec_pubkey_path', str,
('Path to public key in vb2 format. Verify EC key with pubkey file.'
- 'Verify by pubkey file should have higher priority.'),
- default=None),
+ 'Verify by pubkey file should have higher priority.'), default=None),
Arg('ec_pubkey_hash', str,
'A string for public key hash. Verify EC key with the given hash.',
default=None),
Arg('use_local_gooftool', bool,
- 'If DUT is local, use factory.par or local gooftool? If DUT is not '
- 'local, factory.par is always used.', default=True),
- Arg('station_ip', str,
- 'IP address of this station.', default=None),
+ ('If DUT is local, use factory.par or local gooftool? If DUT is not '
+ 'local, factory.par is always used.'), default=True),
+ Arg('station_ip', str, 'IP address of this station.', default=None),
Arg('gooftool_waive_list', list,
- 'A list of waived checks for "gooftool finalize", '
- 'see "gooftool finalize --help" for available items.',
- default=[]),
+ ('A list of waived checks for "gooftool finalize", '
+ 'see "gooftool finalize --help" for available items.'), default=[]),
Arg('gooftool_skip_list', list,
- 'A list of skipped checks for "gooftool finalize", '
- 'see "gooftool finalize --help" for available items.',
- default=[]),
- Arg('enable_zero_touch', bool,
- 'Set SN bits to enable zero-touch.', default=False)
+ ('A list of skipped checks for "gooftool finalize", '
+ 'see "gooftool finalize --help" for available items.'), default=[]),
+ Arg('enable_zero_touch', bool, 'Set SN bits to enable zero-touch.',
+ default=False),
+ Arg('cbi_eeprom_wp_status', cbi_utils.CbiEepromWpStatus,
+ ('If set to "Locked", checks that CBI EEPROM write protection is '
+ 'enabled. If set to "Unlocked", checks that CBI EEPROM write '
+ 'protection is disabled. If set to "Absent", checks that CBI EEPROM '
+ 'is absent.'), default=cbi_utils.CbiEepromWpStatus.Locked),
]
FINALIZE_TIMEOUT = 180
@@ -223,6 +220,11 @@
self.args.write_protection = phase.GetPhase() >= phase.PVT
phase.AssertStartingAtPhase(phase.PVT, self.args.write_protection,
'Write protection must be enabled')
+ if self.args.cbi_eeprom_wp_status != cbi_utils.CbiEepromWpStatus.Absent:
+ phase.AssertStartingAtPhase(
+ phase.PVT,
+ self.args.cbi_eeprom_wp_status == cbi_utils.CbiEepromWpStatus.Locked,
+ 'CBI Write protection must be enabled')
def GetState(v):
return (['<b style="color: green;">', MSG_ENABLED, '</b>']
@@ -332,6 +334,8 @@
if not self.args.write_protection:
self.Warn('WRITE PROTECTION IS DISABLED.')
command += ' --no_write_protect'
+ command += ' --cbi_eeprom_wp_status %s' % self.args.cbi_eeprom_wp_status
+
if not self.args.has_ectool:
command += ' --no_ectool'
if not self.args.secure_wipe:
diff --git a/py/test/test_lists/generic_grt.test_list.json b/py/test/test_lists/generic_grt.test_list.json
index f0a8b3e..a14c8f9 100644
--- a/py/test/test_lists/generic_grt.test_list.json
+++ b/py/test/test_lists/generic_grt.test_list.json
@@ -6,6 +6,8 @@
"grt": {
"force_write_protect": false,
"__comment_force_write_protect": "*** Write protection is required for mass production and shippable devices. By default we enable write protection starting from PVT stages, but you can start trying write protection earlier by this option.",
+ "cbi_eeprom_wp_status": "Locked",
+ "__comment_cbi_eeprom_wp_status": "Set this to 'Absent' for board without CBI EEPROM. Set this to 'Unlocked' for MLB layouts which requires CBI WP being disabled in pre-PVT and enabled in PVT.",
"ec_pubkey_path": null,
"ec_pubkey_hash": null,
"enable_zero_touch": false,
@@ -55,7 +57,8 @@
"rma_mode": "eval! constants.rma_mode",
"secure_wipe": "eval! constants.grt.secure_wipe",
"upload_method": "eval! 'shopfloor' if constants.enable_factory_server else 'none'",
- "write_protection": "eval! constants.grt.force_write_protect or options.phase == 'PVT'"
+ "write_protection": "eval! constants.grt.force_write_protect or options.phase == 'PVT'",
+ "cbi_eeprom_wp_status": "eval! 'Locked' if constants.grt.cbi_eeprom_wp_status != 'Absent' and options.phase == 'PVT' else constants.grt.cbi_eeprom_wp_status"
}
},
"GRTItems": {