Remove factory.* items from VPD in finalize.
BUG=chrome-os-partner:19472
TEST=unit tests, manual on device
Change-Id: Ia2df23b4a6291fbe88fb39f6fdef95905227d7f6
Reviewed-on: https://gerrit.chromium.org/gerrit/51272
Tested-by: Jon Salz <jsalz@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Commit-Queue: Jon Salz <jsalz@chromium.org>
diff --git a/py/gooftool/__init__.py b/py/gooftool/__init__.py
index 63463c9..c547109 100644
--- a/py/gooftool/__init__.py
+++ b/py/gooftool/__init__.py
@@ -4,6 +4,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import logging
import os
import re
@@ -22,7 +23,9 @@
from cros.factory.hwid import Database
from cros.factory.hwid.decoder import Decode
from cros.factory.hwid.encoder import Encode
+from cros.factory.privacy import FilterDict
from cros.factory.rule import Context
+from cros.factory.system import vpd
# A named tuple to store the probed component name and the error if any.
ProbedComponentResult = namedtuple('ProbedComponentResult',
@@ -633,10 +636,10 @@
hwid = self._hwid_decode(self.db, encoded_string)
hwid.VerifyProbeResult(probe_results.Encode())
- vpd = {'ro': {}, 'rw': {}}
- vpd['ro'].update(probed_ro_vpd)
- vpd['rw'].update(probed_rw_vpd)
- context = Context(hwid=hwid, vpd=vpd)
+ vpd_dict = {'ro': {}, 'rw': {}}
+ vpd_dict['ro'].update(probed_ro_vpd)
+ vpd_dict['rw'].update(probed_rw_vpd)
+ context = Context(hwid=hwid, vpd=vpd_dict)
self.db.rules.EvaluateRules(context, namespace="verify.*")
def DecodeHwidV3(self, encoded_string):
@@ -677,3 +680,14 @@
"""
# TODO(jcliang): Re-implement this after rule language refactoring.
pass
+
+ def ClearFactoryVPDEntries(self):
+ """Clears factory.* items in the RW VPD.
+
+ Returns:
+ A dict of the removed entries.
+ """
+ entries = dict((k, v) for k, v in vpd.rw.GetAll().items()
+ if k.startswith('factory.'))
+ logging.info('Removing VPD entries %s', FilterDict(entries))
+ vpd.rw.Delete(*entries.keys())
diff --git a/py/gooftool/gooftool.py b/py/gooftool/gooftool.py
index 6c140e3..8ee64da 100755
--- a/py/gooftool/gooftool.py
+++ b/py/gooftool/gooftool.py
@@ -576,6 +576,13 @@
event_log.Log('clear_gbb_flags')
+@Command('clear_factory_vpd_entries')
+def ClearFactoryVPDEntries(options): # pylint: disable=W0613
+ """Clears factory.* items in the RW VPD."""
+ entries = GetGooftool(options).ClearFactoryVPDEntries()
+ event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
+
+
@Command('prepare_wipe',
CmdArg('--fast', action='store_true',
help='use non-secure but faster wipe method.'))
@@ -705,17 +712,20 @@
def Finalize(options):
"""Verify system readiness and trigger transition into release state.
- This routine first verifies system state (see verify command), modifies
- firmware bitmaps to match locale, and then clears all of the factory-friendly
- flags from the GBB. If everything is fine, it enables firmware write
- protection (cannot rollback after this stage), uploads system logs & reports,
- and sets the necessary boot flags to cause wipe of the factory image on the
- next boot.
+ This routine does the following:
+ - Verifies system state (see verify command)
+ - Modifies firmware bitmaps to match locale
+ - Clears all factory-friendly flags from the GBB
+ - Removes factory-specific entries from RW_VPD (factory.*)
+ - Enables firmware write protection (cannot rollback after this)
+ - Uploads system logs & reports
+ - Sets the necessary boot flags to cause wipe of the factory image on the
+ next boot.
"""
-
Verify(options)
SetFirmwareBitmapLocale(options)
ClearGBBFlags(options)
+ ClearFactoryVPDEntries(options)
if options.no_write_protect:
logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
event_log.Log('wp', fw='both', status='skipped')
diff --git a/py/system/vpd.py b/py/system/vpd.py
index dcbe788..44099f1 100644
--- a/py/system/vpd.py
+++ b/py/system/vpd.py
@@ -47,6 +47,17 @@
"""
return self.GetAll().get(key, default)
+ def Delete(self, *keys):
+ """Deletes entries from the VPD.
+
+ Raises:
+ An error if any entries cannot be deleted. In this case some or
+ all other entries may have been deleted.
+ """
+ for k in keys:
+ Spawn(['vpd', '-i', self.name, '-d', k], check_call=True,
+ log_stderr_on_error=True)
+
def GetAll(self):
"""Returns the contents of the VPD as a dict."""
ret = {}
diff --git a/py/system/vpd_unittest.py b/py/system/vpd_unittest.py
index 934a7c7..1a664b4 100755
--- a/py/system/vpd_unittest.py
+++ b/py/system/vpd_unittest.py
@@ -100,6 +100,36 @@
vpd.rw.Update, {'a': '\"'}, log=False)
self.mox.VerifyAll()
+ def testDeleteNone(self):
+ self.mox.ReplayAll()
+ vpd.rw.Delete() # no-op
+ self.mox.VerifyAll()
+
+ def testDeleteOne(self):
+ vpd.Spawn(
+ ['vpd', '-i', 'RW_VPD', '-d', 'a'],
+ check_call=True, log_stderr_on_error=True)
+ self.mox.ReplayAll()
+ vpd.rw.Delete('a')
+ self.mox.VerifyAll()
+
+ def testDeleteTwo(self):
+ for k in ['a', 'b']:
+ vpd.Spawn(
+ ['vpd', '-i', 'RW_VPD', '-d', k],
+ check_call=True, log_stderr_on_error=True)
+ self.mox.ReplayAll()
+ vpd.rw.Delete('a', 'b')
+ self.mox.VerifyAll()
+
+ def testDeleteError(self):
+ vpd.Spawn(
+ ['vpd', '-i', 'RW_VPD', '-d', 'a'],
+ check_call=True, log_stderr_on_error=True).AndRaise(ValueError)
+ self.mox.ReplayAll()
+ self.assertRaises(ValueError, vpd.rw.Delete, 'a')
+ self.mox.VerifyAll()
+
if __name__ == '__main__':
unittest2.main()