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')) |