[ATFT] Add TEST_MODE and PROVISION_STEPS to config.
Include TEST_MODE option and PROVISION_STEPS in the configuration
file. These two are optional arguments. TEST_MODE is set to false
by default. If TEST_MODE is set to true, no prerequisite step check
would be done, user could do the provision step by any order. User
could also modify PROVISION_STEP to change the provision steps that
would be executed in the auto provisioning mode.
Change-Id: I48de20d4f05d1af9ef85e22b3e70e4013f445ce6
Test: Manual test and unit test.
Bug: b/79164608
diff --git a/at-factory-tool/atft.py b/at-factory-tool/atft.py
index 4fb1c9a..470554a 100644
--- a/at-factory-tool/atft.py
+++ b/at-factory-tool/atft.py
@@ -46,11 +46,6 @@
from serialmapperwin import SerialMapper
-# If this is set to True, no prerequisites would be checked against manual
-# operation, such as you can do key provisioning before fusing the vboot key.
-TEST_MODE = False
-
-
class AtftException(Exception):
"""The exception class to include device and operation information.
"""
@@ -376,6 +371,14 @@
self.REBOOT_TIMEOUT = 0
self.PRODUCT_ATTRIBUTE_FILE_EXTENSION = '*.atpa'
+ # If this is set to True, no prerequisites would be checked against manual
+ # operation, such as you can do key provisioning before fusing the vboot key.
+ self.TEST_MODE = False
+
+ # The steps included in the auto provisioning process.
+ self.PROVISION_STEPS = ["FuseVbootKey", "FusePermAttr", "LockAvb",
+ "Provision"]
+
config_file_path = os.path.join(self._GetCurrentPath(), self.CONFIG_FILE)
if not os.path.exists(config_file_path):
return None
@@ -398,6 +401,10 @@
self.REBOOT_TIMEOUT = float(configs['REBOOT_TIMEOUT'])
self.PRODUCT_ATTRIBUTE_FILE_EXTENSION = str(
configs['PRODUCT_ATTRIBUTE_FILE_EXTENSION'])
+ if 'TEST_MODE' in configs:
+ self.TEST_MODE = configs['TEST_MODE']
+ if 'PROVISION_STEPS' in configs:
+ self.PROVISION_STEPS = configs['PROVISION_STEPS']
except (KeyError, ValueError):
return None
@@ -1242,6 +1249,27 @@
self.StopRefresh()
self.Destroy()
+ def _is_provision_success(self, target):
+ """Check if the target device has successfully finished provision steps.
+
+ Args:
+ target: The target device.
+ Returns:
+ success if the target device has already gone through the provision steps
+ successfully.
+ """
+ if len(self.PROVISION_STEPS) == 0:
+ return True;
+ if self.PROVISION_STEPS[-1] == 'Provision':
+ return target.provision_state.provisioned
+ if self.PROVISION_STEPS[-1] == 'LockAvb':
+ return target.provision_state.avb_locked
+ if self.PROVISION_STEPS[-1] == 'FusePermAttr':
+ return target.provision_state.avb_perm_attr_set
+ if self.PROVISION_STEPS[-1] == 'FuseVbootKey':
+ return target.provision_state.bootloader_locked
+ return True;
+
def _HandleAutoProv(self):
"""Do the state transition for devices if in auto provisioning mode.
@@ -1249,7 +1277,7 @@
# All idle devices -> waiting.
for target_dev in self.atft_manager.target_devs:
if (target_dev.serial_number not in self.auto_dev_serials and
- target_dev.provision_status != ProvisionStatus.PROVISION_SUCCESS and
+ not self._is_provision_success(target_dev) and
not ProvisionStatus.isFailed(target_dev.provision_status)
):
self.auto_dev_serials.append(target_dev.serial_number)
@@ -1603,7 +1631,7 @@
if not target:
continue
# Start state could be IDLE or FUSEVBOOT_FAILED
- if (TEST_MODE or not target.provision_state.bootloader_locked):
+ if (self.TEST_MODE or not target.provision_state.bootloader_locked):
target.provision_status = ProvisionStatus.WAITING
pending_targets.append(target)
else:
@@ -1721,7 +1749,7 @@
# Start state could be FUSEVBOOT_SUCCESS or REBOOT_SUCCESS
# or FUSEATTR_FAILED
# Note: Reboot to check vboot is optional, user can skip that manually.
- if (TEST_MODE or (
+ if (self.TEST_MODE or (
target.provision_state.bootloader_locked and
not target.provision_state.avb_perm_attr_set
)):
@@ -1767,7 +1795,7 @@
if not target:
continue
# Start state could be FUSEATTR_SUCCESS or LOCKAVB_FAIELD
- if (TEST_MODE or(
+ if (self.TEST_MODE or(
target.provision_state.bootloader_locked and
target.provision_state.avb_perm_attr_set and
not target.provision_state.avb_locked
@@ -1892,7 +1920,7 @@
continue
pending_targets.append(target_dev)
status = target_dev.provision_status
- if (TEST_MODE or (
+ if (self.TEST_MODE or (
target_dev.provision_state.bootloader_locked and
target_dev.provision_state.avb_perm_attr_set and
target_dev.provision_state.avb_locked and
@@ -1946,6 +1974,7 @@
"""
self.auto_prov_lock.acquire()
serial = target.serial_number
+ i = 0
while not ProvisionStatus.isFailed(target.provision_status):
target = self.atft_manager.GetTargetDevice(serial)
if not target:
@@ -1954,23 +1983,31 @@
if not self.auto_prov:
# Auto provision mode exited.
break
- if not target.provision_state.bootloader_locked:
+ if i == len(self.PROVISION_STEPS):
+ break
+ operation = self.PROVISION_STEPS[i]
+ i += 1
+ if (not target.provision_state.bootloader_locked and
+ operation == 'FuseVbootKey'):
self._FuseVbootKeyTarget(target)
continue
- elif not target.provision_state.avb_perm_attr_set:
+ elif (not target.provision_state.avb_perm_attr_set and
+ operation == 'FusePermAttr'):
self._FusePermAttrTarget(target)
continue
- elif not target.provision_state.avb_locked:
+ elif (not target.provision_state.avb_locked and
+ operation == 'LockAvb'):
self._LockAvbTarget(target)
continue
- elif not target.provision_state.provisioned:
+ elif (not target.provision_state.provisioned and
+ operation == 'Provision'):
self._ProvisionTarget(target)
if self.atft_manager.GetATFAKeysLeft() == 0:
# No keys left. If it's auto provisioning mode, exit.
self._SendAlertEvent(self.ALERT_NO_KEYS_LEFT_LEAVE_PROV)
self.toolbar.ToggleTool(self.ID_TOOL_PROVISION, False)
self.OnToggleAutoProv(None)
- break
+
self.auto_dev_serials.remove(serial)
self.auto_prov_lock.release()
diff --git a/at-factory-tool/atft_unittest.py b/at-factory-tool/atft_unittest.py
index 92b57a6..122704d 100644
--- a/at-factory-tool/atft_unittest.py
+++ b/at-factory-tool/atft_unittest.py
@@ -49,6 +49,10 @@
self.LANGUAGE = 'ENG'
self.REBOOT_TIMEOUT = 1.0
self.PRODUCT_ATTRIBUTE_FILE_EXTENSION = '*.atpa'
+ # Disable the test mode. (This mode is just for usage test, not unit test)
+ self.TEST_MODE = False
+ self.PROVISION_STEPS = ["FuseVbootKey", "FusePermAttr", "LockAvb",
+ "Provision"]
return {}
@@ -95,8 +99,6 @@
self.test_text_window = ''
self.atfa_keys = None
self.device_map = {}
- # Disable the test mode. (This mode is just for usage test, not unit test)
- atft.TEST_MODE = False
def AppendTargetDevice(self, device):
self.test_target_devs.append(device)
@@ -357,6 +359,7 @@
mock_atft = MockAtft()
test_dev1 = TestDeviceInfo(self.TEST_SERIAL1, self.TEST_LOCATION1,
ProvisionStatus.PROVISION_SUCCESS)
+ test_dev1.provision_state.provisioned = True
test_dev2 = TestDeviceInfo(self.TEST_SERIAL2, self.TEST_LOCATION1,
ProvisionStatus.IDLE)
mock_atft.atft_manager.target_devs = []