Chromium Code Reviews| Index: chromeos_interface.py |
| diff --git a/chromeos_interface.py b/chromeos_interface.py |
| index 0df860969df5b950d49b0a2f61d8237cb262519c..5cb5258a90c91258a61c1baf6ab2a0abd6b75cbd 100755 |
| --- a/chromeos_interface.py |
| +++ b/chromeos_interface.py |
| @@ -21,9 +21,114 @@ class ChromeOSInterfaceError(Exception): |
| class Crossystem(object): |
| '''A wrapper for the crossystem utility.''' |
| + # Code dedicated for user triggering recovery mode through crossystem. |
| + USER_RECOVERY_REQUEST_CODE = '193' |
| + |
| + ''' |
| + The first three legacy boot vector digits are the boot vector base (the |
| + entire vector consists of 5 digits). They used to be reported by the BIOS |
| + through ACPI, but that scheme has been superseded by the 'crossystem' |
| + interface. |
| + |
| + The digits of the boot vector base have the following significance |
| + |
| + - first digit - |
| + 1 - normal boot |
| + 2 - developer mode boot |
| + 3 - recovery initialed by pressing the recovery button |
| + 4 - recovery from developer mode warning screen |
| + 5 - recovery caused by both firmware images being invalid |
| + 6 - recovery caused by both kernel images being invalid |
| + 8 - recovery initiated by user |
| + |
| + - second digit - |
| + 0 - recovery firmware |
| + 1 - rewritable firmware A |
| + 2 - rewritable firmware B |
| + |
| + - third digit - |
| + 0 - Read only (recovery) EC firmware |
| + 1 - rewritable EC firmware |
| + |
| + |
| + Below is a list of dictionaries to map current system state as reported by |
| + 'crossystem' into the 'legacy' boot vector digits. |
| + |
| + The three elements of the list represent the three digits of the boot |
| + vector. Each list element is a dictionary where the key is the legacy boot |
| + vector value in the appropriate position, and the value is in turn a |
| + dictionary of name-value pairs. |
| + |
| + If all name-value pairs of a dictionary element match those reported by |
| + crossystem, the legacy representation number is considered the appropriate |
| + vector digit. |
| + |
| + Note that on some platforms (namely, Mario) same parameters returned by |
| + crossystem are set to a wrong value. The class init() routine adjust the |
| + list to support those platforms. |
| + ''' |
| + |
| + VECTOR_MAPS = [ |
| + { # first vector position |
| + '1': { |
| + 'devsw_boot': '0', |
| + 'mainfw_type': 'normal', |
| + 'recoverysw_boot': '0', |
| + }, |
| + '5': { |
| + 'devsw_boot': '0', |
| + 'recoverysw_boot': '0', |
| + 'recovery_reason' : '3', |
| + 'mainfw_type': 'recovery', |
| + }, |
| + '6': { |
| + 'devsw_boot': '0', |
| + 'recoverysw_boot': '0', |
| + 'recovery_reason' : '66', |
| + 'mainfw_type': 'recovery', |
| + }, |
| + '8': { |
| + 'devsw_boot': '0', |
| + 'recoverysw_boot': '0', |
| + 'recovery_reason' : USER_RECOVERY_REQUEST_CODE, |
| + 'mainfw_type': 'recovery', |
| + }, |
| + }, |
| + { # second vector position |
| + '0': {'mainfw_type': 'recovery',}, |
| + '1': { |
| + 'mainfw_type': 'normal', |
| + 'mainfw_act': 'A' |
| + }, |
| + '2': { |
| + 'mainfw_type': 'normal', |
| + 'mainfw_act': 'B' |
| + }, |
| + }, |
| + { # third vector position |
| + '0': {'ecfw_act': 'RO',}, |
| + '1': {'ecfw_act': 'RW',}, |
| + }, |
| + ] |
| + |
| def init(self, cros_if): |
| + '''Init the instance. If running on Mario - adjust the map.''' |
| + |
| self.cros_if = cros_if |
| + # Hack Alert!!! Adjust vector map to work on Mario |
| + fwid = self.__getattr__('fwid').lower() |
| + if not 'mario' in fwid: |
| + return |
| + # Mario firmware is broken and always reports recovery switch as set |
| + # at boot time when booting up in recovery mode. This is why we |
| + # exclude recoverysw_boot from the map when running on mario. |
| + for state in self.VECTOR_MAPS[0].itervalues(): |
| + if state['mainfw_type'] != 'recovery': |
| + continue |
| + if 'recoverysw_boot' in state: |
| + del(state['recoverysw_boot']) |
| + |
| def __getattr__(self, name): |
| ''' |
| Retrieve a crosssystem attribute. |
| @@ -40,84 +145,27 @@ class Crossystem(object): |
| else: |
| self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value)) |
| + def request_recovery(self): |
| + '''Request recovery mode next time the target reboots.''' |
| - def get_boot_vector_base(self): |
| - ''' |
| - Convert system state into a legacy boot vector base. |
| - |
| - The first three legacy boot vector digits are the boot vector base |
| - (the entire vector consists of 5 digits). They used to be reported by |
| - the BIOS through ACPI, but that scheme has been superseded by the |
| - 'crossystem' interface. |
| + self.__setattr__('recovery_request', self.USER_RECOVERY_REQUEST_CODE) |
| - The digits of the boot vector base have the following significance |
| - |
| - - first digit - |
| - 1 - normal boot |
| - 2 - developer mode boot |
| - 3 - recovery initialed by pressing the recovery button |
| - 4 - recovery from developer mode warning screen |
| - 5 - recovery caused by both firmware images being invalid |
| - 6 - recovery caused by both kernel images being invalid |
| - |
| - - second digit - |
| - 0 - recovery firmware |
| - 1 - rewritable firmware A |
| - 2 - rewritable firmware B |
| - |
| - - third digit - |
| - 0 - Read only (recovery) EC firmware |
| - 1 - rewritable EC firmware |
| - |
| - |
| - This function uses a three tuple of dictionaries to map current system |
| - state as reported by 'crossystem' into the 'legacy' boot vector |
| - digits. |
| - |
| - Each tuple element is a dictionary, where the key is the 'legacy' |
| - representation of the state, and the value is a yet another dictionary |
| - of name-value pairs. |
| - |
| - If all name-value pairs match those in the crossystem output, the |
| - legacy representation number is returned as the appropriate vector |
| - number. |
| + def get_boot_vector_base(self): |
| + '''Convert system state into a legacy boot vector base. |
| - The function returns a list of three digits in symbolic representation. |
| + The function looks up the VECTOR_MAPS list above to find the digits |
| + matching the current crossystem output, and returns a list of three |
| + digits in symbolic representation, which become the base of the 5 |
| + digit boot state vecotr. |
| - Should it be impossible to interpret the state, the function returns a |
| + Should it be impossible to interpret the state, the function returns |
| partially built list, which is an indication of a problem for the |
|
Randall Spangler
2011/04/19 19:40:32
'a partially built list'
vb
2011/04/19 21:15:22
Done.
|
| caller (list shorter than 3 elements). |
| ''' |
| - vector_maps = ( |
| - { # first vector position |
| - '1': { |
| - 'devsw_boot': '0', |
| - 'recoverysw_boot': '0', |
| - 'recovery_reason' : '0', |
| - 'tried_fwb' : '0', |
| - }, |
| - }, |
| - { # second vector position |
| - '0': {'mainfw_type': 'recovery',}, |
| - '1': { |
| - 'mainfw_type': 'normal', |
| - 'mainfw_act': 'A' |
| - }, |
| - '2': { |
| - 'mainfw_type': 'normal', |
| - 'mainfw_act': 'B' |
| - }, |
| - }, |
| - { # third vector position |
| - '0': {'ecfw_act': 'RO',}, |
| - '1': {'ecfw_act': 'RW',}, |
| - }, |
| - ) |
| - |
| boot_vector = [] |
| - for vector_map in vector_maps: |
| + for vector_map in self.VECTOR_MAPS: |
| for (digit, values) in vector_map.iteritems(): |
| for (name, value) in values.iteritems(): |
| if self.__getattr__(name) != value: |
| @@ -129,7 +177,8 @@ class Crossystem(object): |
| return boot_vector |
| def dump(self): |
| - '''Dump all values as multiline text.''' |
| + '''Dump all crossystem values as multiline text.''' |
| + |
| return '\n'.join(self.cros_if.run_shell_command_get_output( |
| 'crossystem')) |