Index: src/platform/utils/reboot_mode.py |
diff --git a/src/platform/utils/reboot_mode.py b/src/platform/utils/reboot_mode.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..18f336fd565a9a047f3d7b0456cc7826ef2754fd |
--- /dev/null |
+++ b/src/platform/utils/reboot_mode.py |
@@ -0,0 +1,171 @@ |
+#!/usr/bin/python |
+ |
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""A script to manipulate ChromeOS CMOS reboot Field. |
+ |
+A few bits in a byte in CMOS (called RDB, short for 'Reboot Data Byte' |
+hereafter) are dedicated to information exchange between Linux and BIOS. |
+ |
+The CMOS contents are available through /dev/nvrom. The location of RDB is |
+reported by BIOS through ACPI. The few bits in RDB operated on by this script |
+are defined in the all_mode_fields dictionary below along with their |
+functions. |
+ |
+When invoked without parameters this script prints values of the fields. When |
+invoked with any of the bit field names as parameter(s), the script sets the |
+bit(s) as required. |
+ |
+Additional parameters allow to specify alternative ACPI and NVRAM files for |
+testing. |
+""" |
+ |
+__author__ = 'The Chromium OS Authors' |
+ |
+import optparse |
+import sys |
+ |
+class RebootModeError(Exception): |
+ pass |
+ |
+# global variables |
+parser = optparse.OptionParser() |
+acpi_file = '/sys/devices/platform/chromeos_acpi/CHNV' |
+nvram_file = '/dev/nvram' |
+ |
+# Offset of RDB in NVRAM |
+rdb_offset = 0 |
+ |
+# NVRAM contents read on startup |
+rdb_value = '' |
+ |
+# All bitfields in RDB this script provides access to. Field names prepended |
+# by `--' become this script's command line options |
+all_mode_fields = { |
+ 'recovery' : 0x80, |
+ 'debug_reset' : 0x40, |
+ 'try_firmware_b': 0x20 |
+ } |
+ |
+# A dictionary of fields to be updated as requested by the command line |
+# parameters |
+fields_to_set = {} |
+ |
+ |
+def OptionHandler(option, opt_str, value, p): |
+ """Process bit field name command line parameter. |
+ |
+ Verifies that the value is in range (0 or 1) and adds the appropriate |
+ element to fields_to_set dictionary. Should the same field specified in the |
+ command line more than once, only the last value will be used. |
+ |
+ Raises: |
+ RebootModeError in case the parameter value is out of range. |
+ """ |
+ |
+ global fields_to_set |
+ key = opt_str[2:] |
+ if value < 0 or value > 1: |
+ raise RebootModeError('--%s should be either 0 or 1' % key) |
+ |
+ fields_to_set[key] = value |
+ |
+ |
+def PrepareOptions(): |
+ global parser |
+ for field in all_mode_fields: |
+ parser.add_option('--' + field, action='callback', type='int', |
+ callback=OptionHandler) |
+ parser.add_option('--acpi_file', dest='acpi_file') |
+ parser.add_option('--nvram_file', dest='nvram_file') |
+ |
+ |
+def ParseOptions(): |
+ global acpi_file |
+ global nvram_file |
+ (opts, args) = parser.parse_args() |
+ |
+ if opts.acpi_file is not None: |
+ acpi_file = opts.acpi_file |
+ |
+ if opts.nvram_file is not None: |
+ nvram_file = opts.nvram_file |
+ |
+ |
+def GetRDBOffset(): |
+ global rdb_offset |
+ try: |
+ f = open(acpi_file, 'r') |
+ rdb_offset = int(f.read()) |
+ f.close() |
+ except IOError, e: |
+ raise RebootModeError('Trying to read %s got this: %s' % (acpi_file, e)) |
+ except ValueError: |
+ raise RebootModeError('%s contents are corrupted' % acpi_file) |
+ |
+ |
+def ReadNvram(): |
+ global rdb_value |
+ try: |
+ f = open(nvram_file, 'rb') |
+ f.seek(rdb_offset) |
+ rdb_value = ord(f.read(1)[0]) |
+ f.close() |
+ except IOError, e: |
+ if e[0] == 2: |
+ raise RebootModeError( |
+ '%s does not exist. Is nvram module installed?' % nvram_file) |
+ if e[0] == 13: |
+ raise RebootModeError('Access to %s denied. Are you root?' % nvram_file) |
+ raise RebootModeError(e[1]) |
+ except IndexError, e: |
+ raise RebootModeError('Failed reading mode byte from %s' % nvram_file) |
+ |
+ |
+def PrintCurrentMode(): |
+ print 'Current reboot mode settings:' |
+ for (field, mask) in all_mode_fields.iteritems(): |
+ print '%-15s: %d' % (field, int(not not (rdb_value & mask))) |
+ |
+ |
+def SetNewMode(): |
+ new_mode = 0 |
+ updated_bits_mask = 0 |
+ |
+ for (opt, value) in fields_to_set.iteritems(): |
+ mask = all_mode_fields[opt] |
+ if value: |
+ new_mode |= mask |
+ updated_bits_mask |= mask |
+ |
+ if (rdb_value & updated_bits_mask) == new_mode: |
+ print 'No update required' |
+ return |
+ |
+ f = open(nvram_file, 'rb+') |
+ f.seek(rdb_offset) |
+ new_mode |= (rdb_value & ~updated_bits_mask) |
+ f.write('%c' % new_mode) |
+ f.close() |
+ |
+ |
+def DoRebootMode(): |
+ PrepareOptions() |
+ ParseOptions() |
+ GetRDBOffset() |
+ ReadNvram() |
+ if fields_to_set: |
+ SetNewMode() |
+ else: |
+ PrintCurrentMode() |
+ |
+ |
+if __name__ == '__main__': |
+ try: |
+ DoRebootMode() |
+ except RebootModeError, e: |
+ print >> sys.stderr, '%s: %s' % (sys.argv[0].split('/')[-1], e) |
+ sys.exit(1) |
+ sys.exit(0) |