| # Copyright 2019 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Check the board ID of the Cr50 firmware. |
| |
| Description |
| ----------- |
| This test checks the board ID in the Cr50 firmware matched the given |
| expectation or not. The test gains the board ID by invoking `gsctool` |
| utility on DUT. |
| |
| See https://chrome-internal.googlesource.com/ti50/common/ti50/+/main/docs/\ |
| board_id_flags.md#values-in-info-pages for available flags. |
| |
| Test Procedure |
| -------------- |
| This is an automatic test that doesn't need any user interaction. |
| |
| 1. Firstly, this test gets the board ID from the Cr50 firmware. |
| 2. If the argument ``board_id_type`` is set, the test checks if the |
| board ID type field is equal to the argument value or not. |
| 3. If the argument ``board_id_flags`` is set, the test checks if the |
| board ID flags field is equal to the argument value or not. |
| |
| Dependency |
| ---------- |
| - DUT link must be ready before running this test. |
| - `gsctool` on DUT. |
| |
| Examples |
| -------- |
| To check if the board ID is still unprogrammed, add this in test list: |
| |
| .. test_list:: |
| |
| generic_tpm_examples:CommonTests.AssertGSCBoardIDIsUnset |
| |
| To check if the board ID flags is set to normal prePVT, you can set the argument |
| ``board_id_flags`` to `PHASE_PREPVT`: |
| |
| .. test_list:: |
| |
| generic_tpm_examples:CommonTests.AssertGSCBoardIDIsPrePVT |
| |
| """ |
| |
| from cros.factory.device import device_utils |
| from cros.factory.test import session |
| from cros.factory.test import test_case |
| from cros.factory.testlog import testlog |
| from cros.factory.utils.arg_utils import Arg |
| |
| from cros.factory.external.chromeos_cli import gsctool |
| |
| |
| _non_inclusive_label = bytes.fromhex('57484954454c4142454c').decode('utf-8') |
| |
| class CheckCr50FirmwareBoardIDTest(test_case.TestCase): |
| related_components = (test_case.TestCategory.SECURE_ELEMENT, ) |
| _PREDEFINED_PHASES = { |
| 'PHASE_UNSET': 0xffffffff, |
| 'PHASE_UNKNOWN': 0x0000ff00, |
| 'PHASE_PREPVT': 0x00007f7f, |
| 'PHASE_PVT': 0x00007f80, |
| f'PHASE_{_non_inclusive_label}_PREPVT': 0x00003f7f, |
| f'PHASE_{_non_inclusive_label}': 0x00003f80, |
| 'PHASE_CUSTOM_LABEL_PREPVT': 0x00003f7f, |
| 'PHASE_CUSTOM_LABEL': 0x00003f80, |
| } |
| |
| ARGS = [ |
| Arg( |
| 'board_id_type', (int, str), 'The expected board ID type, can be ' |
| 'either an integer or a string of hex code.', default=None), |
| Arg( |
| 'board_id_flags', (int, str), 'The expected board ID flags, can be ' |
| 'either an integer or a string. If the value is a string, ' |
| 'the value can be either the hex code of the board ID flags or' + |
| ', '.join(f'{k} for {v:08x}' for k, v in _PREDEFINED_PHASES.items()), |
| default=None), |
| ] |
| |
| def setUp(self): |
| # Preprocesses the arguments. |
| # yapf: disable |
| if isinstance(self.args.board_id_type, str): # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| self.args.board_id_type = int(self.args.board_id_type, 16) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| if isinstance(self.args.board_id_flags, str): # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| if self.args.board_id_flags.startswith('PHASE_'): # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| self.args.board_id_flags = self._PREDEFINED_PHASES[ # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| self.args.board_id_flags] # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| else: |
| # yapf: disable |
| self.args.board_id_flags = int(self.args.board_id_flags, 16) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| |
| # Setups the DUT environments. |
| self.dut = device_utils.CreateDUTInterface() |
| self.gsctool = gsctool.GSCTool(dut=self.dut) |
| |
| # Setups the logging framework. |
| testlog.UpdateParam('board_id_type', |
| description='Board ID type in hex code') |
| testlog.UpdateParam('board_id_flags', |
| description='Board ID flags in hex code') |
| |
| def runTest(self): |
| board_id = self.gsctool.GetBoardID() |
| board_id_type_str = f'{board_id.type:08x}' |
| board_id_flags_str = f'{board_id.flags:08x}' |
| session.console.info('Board ID type: %s; Board ID flags: %s.', |
| board_id_type_str, board_id_flags_str) |
| testlog.LogParam('board_id_type', board_id_type_str) |
| testlog.LogParam('board_id_flags', board_id_flags_str) |
| |
| succ = True |
| # yapf: disable |
| if self.args.board_id_type is not None: # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| if board_id.type != self.args.board_id_type: # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| testlog.AddFailure('BoardIDTypeMismatch', '') |
| succ = False |
| # yapf: disable |
| if self.args.board_id_flags is not None: # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| # yapf: disable |
| if board_id.flags != self.args.board_id_flags: # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long |
| # yapf: enable |
| testlog.AddFailure('BoardIDFlagsMismatch', '') |
| succ = False |
| if not succ: |
| self.FailTask('Board ID mismatched.') |