os_interface.py revision c0168917ffb61c59c7746cd39fc53c1dd134723b
1c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam#!/usr/bin/python 2c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 3c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Use of this source code is governed by a BSD-style license that can be 4c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# found in the LICENSE file. 5c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 6c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam'''A module to provide interface to ChromeOS services.''' 7c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 8c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport datetime 9c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport os 10c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport re 11c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport shutil 12c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport struct 13c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport subprocess 14c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport tempfile 15c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport time 16c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 17c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass ChromeOSInterfaceError(Exception): 18c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''ChromeOS interface specific exception.''' 19c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pass 20c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 21c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass Crossystem(object): 22c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''A wrapper for the crossystem utility.''' 23c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 24c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Code dedicated for user triggering recovery mode through crossystem. 25c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam USER_RECOVERY_REQUEST_CODE = '193' 26c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 27c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 28c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The first three legacy boot vector digits are the boot vector base (the 29c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam entire vector consists of 5 digits). They used to be reported by the BIOS 30c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam through ACPI, but that scheme has been superseded by the 'crossystem' 31c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam interface. 32c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 33c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The digits of the boot vector base have the following significance 34c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 35c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam - first digit - 36c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1 - normal boot 37c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2 - developer mode boot 38c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 3 - recovery initialed by pressing the recovery button 39c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 4 - recovery from developer mode warning screen 40c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 5 - recovery caused by both firmware images being invalid 41c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 6 - recovery caused by both kernel images being invalid 42c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 8 - recovery initiated by user 43c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 44c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam - second digit - 45c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 0 - recovery firmware 46c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1 - rewritable firmware A 47c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2 - rewritable firmware B 48c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 49c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam - third digit - 50c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 0 - Read only (recovery) EC firmware 51c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1 - rewritable EC firmware 52c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 53c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 54c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Below is a list of dictionaries to map current system state as reported by 55c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'crossystem' into the 'legacy' boot vector digits. 56c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 57c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The three elements of the list represent the three digits of the boot 58c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam vector. Each list element is a dictionary where the key is the legacy boot 59c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam vector value in the appropriate position, and the value is in turn a 60c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam dictionary of name-value pairs. 61c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 62c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam If all name-value pairs of a dictionary element match those reported by 63c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam crossystem, the legacy representation number is considered the appropriate 64c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam vector digit. 65c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 66c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Note that on some platforms (namely, Mario) same parameters returned by 67c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam crossystem are set to a wrong value. The class init() routine adjust the 68c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam list to support those platforms. 69c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 70c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 71c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam VECTOR_MAPS = [ 72c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam { # first vector position 73c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '1': { 74c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '0', 75c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'normal', 76c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 77c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 78c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '2': { 79c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '1', 80c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'developer', 81c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 82c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 83c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '3': { 84c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '0', 85c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'recovery', 86c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recovery_reason' : '2', 87c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '1', 88c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 89c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '4': { 90c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '1', 91c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'recovery', 92c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recovery_reason' : '65', 93c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 94c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 95c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '5': { 96c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '0', 97c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'recovery', 98c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recovery_reason' : ('3', '23', '27'), 99c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 100c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 101c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '6': { 102c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '0', 103c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'recovery', 104c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recovery_reason' : '66', 105c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 106c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 107c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '8': { 108c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'devsw_boot': '0', 109c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mainfw_type': 'recovery', 110c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recovery_reason' : USER_RECOVERY_REQUEST_CODE, 111c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'recoverysw_boot': '0', 112c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 113c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 114c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam { # second vector position 115c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '0': {'mainfw_type': 'recovery',}, 116c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '1': {'mainfw_act': 'A',}, 117c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '2': {'mainfw_act': 'B',}, 118c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 119c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam { # third vector position 120c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '0': {'ecfw_act': 'RO',}, 121c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '1': {'ecfw_act': 'RW',}, 122c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam }, 123c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ] 124c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 125c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def init(self, cros_if): 126c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Init the instance. If running on Mario - adjust the map.''' 127c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 128c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.cros_if = cros_if 129c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 130c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Hack Alert!!! Adjust vector map to work on Mario 131c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam fwid = self.__getattr__('fwid').lower() 132c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not 'mario' in fwid: 133c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 134c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Mario firmware is broken and always reports recovery switch as set 135c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # at boot time when booting up in recovery mode. This is why we 136c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # exclude recoverysw_boot from the map when running on mario. 137c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for state in self.VECTOR_MAPS[0].itervalues(): 138c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if state['mainfw_type'] != 'recovery': 139c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 140c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if 'recoverysw_boot' in state: 141c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam del(state['recoverysw_boot']) 142c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if state['recovery_reason'] == self.USER_RECOVERY_REQUEST_CODE: 143c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # This is the only recovery reason Mario knows about 144c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state['recovery_reason'] = '1' 145c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 146c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __getattr__(self, name): 147c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 148c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Retrieve a crosssystem attribute. 149c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 150c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attempt to access crossystemobject.name will invoke `crossystem name' 151c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam and return the stdout as the value. 152c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 153c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.cros_if.run_shell_command_get_output( 154c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'crossystem %s' % name)[0] 155c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 156c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __setattr__(self, name, value): 157c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if name in ('cros_if',): 158c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.__dict__[name] = value 159c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 160c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.cros_if.run_shell_command('crossystem "%s=%s"' % (name, value)) 161c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 162c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def request_recovery(self): 163c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Request recovery mode next time the target reboots.''' 164c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 165c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.__setattr__('recovery_request', self.USER_RECOVERY_REQUEST_CODE) 166c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 167c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_boot_vector_base(self): 168c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Convert system state into a legacy boot vector base. 169c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 170c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The function looks up the VECTOR_MAPS list above to find the digits 171c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam matching the current crossystem output, and returns a list of three 172c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam digits in symbolic representation, which become the base of the 5 173c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam digit boot state vector. 174c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 175c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Should it be impossible to interpret the state, the function returns 176c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam a partially built list, which is an indication of a problem for the 177c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam caller (list shorter than 3 elements). 178c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 179c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 180c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam boot_vector = [] 181c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 182c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for vector_map in self.VECTOR_MAPS: 183c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for (digit, values) in vector_map.iteritems(): 184c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for (name, value) in values.iteritems(): 185c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Get the actual attribute value from crossystem. 186c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam attr_value = self.__getattr__(name) 187c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if isinstance(value, str): 188c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if attr_value != value: 189c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam break 190c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 191c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # 'value' is a tuple of possible actual values. 192c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if attr_value not in value: 193c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam break 194c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 195c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam boot_vector.append(digit) 196c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam break 197c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 198c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return boot_vector 199c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 200c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def dump(self): 201c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Dump all crossystem values as multiline text.''' 202c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 203c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return '\n'.join(self.cros_if.run_shell_command_get_output( 204c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'crossystem')) 205c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 206c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 207c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass ChromeOSInterface(object): 208c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''An object to encapsulate OS services functions.''' 209c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 210c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __init__(self, silent): 211c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Object construction time initialization. 212c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 213c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The only parameter is the Boolean 'silent', when True the instance 214c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam does not duplicate log messages on the console. 215c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 216c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 217c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.silent = silent 218c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.state_dir = None 219c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log_file = None 220c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.cs = Crossystem() 221c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 222c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def init(self, state_dir=None, log_file=None): 223c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Initialize the ChromeOS interface object. 224c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Args: 225c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state_dir - a string, the name of the directory (as defined by the 226c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam caller). The contents of this directory persist over 227c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam system restarts and power cycles. 228c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam log_file - a string, the name of the log file kept in the state 229c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam directory. 230c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 231c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Default argument values support unit testing. 232c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 233c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 234c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.cs.init(self) 235c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.state_dir = state_dir 236c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 237c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.state_dir: 238c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not os.path.exists(self.state_dir): 239c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam try: 240c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam os.mkdir(self.state_dir) 241c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam except OSError, err: 242c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise ChromeOSInterfaceError(err) 243c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if log_file: 244c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if log_file[0] == '/': 245c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log_file = log_file 246c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 247c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log_file = os.path.join(state_dir, log_file) 248c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 249c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def target_hosted(self): 250c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Return True if running on a ChromeOS target.''' 251c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam signature = open('/etc/lsb-release', 'r').readlines()[0] 252c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return re.search(r'chrom(ium|e)os', signature, re.IGNORECASE) != None 253c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 254c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def state_dir_file(self, file_name): 255c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Get a full path of a file in the state directory.''' 256c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return os.path.join(self.state_dir, file_name) 257c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 258c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def init_environment(self): 259c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Initialize Chrome OS interface environment. 260c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 261c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam If state dir was not set up by the constructor, create a temp 262c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam directory, otherwise create the directory defined during construction 263c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam of this object. 264c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 265c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Return the state directory name. 266c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 267c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 268c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.state_dir: 269c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.state_dir = tempfile.mkdtemp(suffix='_saft') 270c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 271c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Wipe out state directory, to start the state machine clean. 272c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam shutil.rmtree(self.state_dir) 273c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # And recreate it 274c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.init(self.state_dir, self.log_file) 275c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 276c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.state_dir 277c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 278c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def shut_down(self, new_log='/var/saft_log.txt'): 279c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Destroy temporary environment so that the test can be restarted.''' 280c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if os.path.exists(self.log_file): 281c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam shutil.copyfile(self.log_file, new_log) 282c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam shutil.rmtree(self.state_dir) 283c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 284c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def log(self, text): 285c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Write text to the log file and print it on the screen, if enabled. 286c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 287c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The entire log (maintained across reboots) can be found in 288c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log_file. 289c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 290c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 291c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Don't print on the screen unless enabled. 292c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.silent: 293c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam print text 294c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 295c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.log_file or not os.path.exists(self.state_dir): 296c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Called before environment was initialized, ignore. 297c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 298c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 299c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam timestamp = datetime.datetime.strftime( 300c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam datetime.datetime.now(), '%I:%M:%S %p:') 301c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 302c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam log_f = open(self.log_file, 'a') 303c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam log_f.write('%s %s\n' % (timestamp, text)) 304c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam log_f.close() 305c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 306c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def exec_exists(self, program): 307c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Check if the passed in string is a valid executable found in PATH.''' 308c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 309c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for path in os.environ['PATH'].split(os.pathsep): 310c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam exe_file = os.path.join(path, program) 311c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if (os.path.isfile(exe_file) or os.path.islink(exe_file) 312c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ) and os.access(exe_file, os.X_OK): 313c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return True 314c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return False 315c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 316c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def run_shell_command(self, cmd): 317c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Run a shell command. 318c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 319c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam In case of the command returning an error print its stdout and stderr 320c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam outputs on the console and dump them into the log. Otherwise suppress all 321c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam output. 322c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 323c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam In case of command error raise an OSInterfaceError exception. 324c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 325c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Return the subprocess.Popen() instance to provide access to console 326c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam output in case command succeeded. 327c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 328c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 329c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log('Executing %s' % cmd) 330c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 331c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam stderr=subprocess.PIPE) 332c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam process.wait() 333c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if process.returncode: 334c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam err = ['Failed running: %s' % cmd] 335c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam err.append('stdout:') 336c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam err.append(process.stdout.read()) 337c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam err.append('stderr:') 338c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam err.append(process.stderr.read()) 339c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam text = '\n'.join(err) 340c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam print text 341c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.log(text) 342c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise ChromeOSInterfaceError('command %s failed' % cmd) 343c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return process 344c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 345c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def is_removable_device(self, device): 346c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Check if a certain storage device is removable. 347c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 348c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device - a string, file name of a storage device or a device partition 349c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (as in /dev/sda[0-9] or /dev/mmcblk0p[0-9]). 350c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 351c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns True if the device is removable, False if not. 352c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 353c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 354c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.target_hosted(): 355c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return False 356c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 357c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Drop trailing digit(s) and letter(s) (if any) 358c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base_dev = self.strip_part(device.split('/')[2]) 359c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam removable = int(open('/sys/block/%s/removable' % base_dev, 'r').read()) 360c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 361c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return removable == 1 362c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 363c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_internal_disk(self, device): 364c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Get the internal disk by given the current disk. 365c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 366c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam If device is removable device, internal disk is decided by which kind 367c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam of divice (arm or x86). Otherwise, return device itself. 368c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 369c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device - a string, file name of a storage device or a device partition 370c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (as in /dev/sda[0-9] or /dev/mmcblk0p[0-9]). 371c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 372c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Return internal kernel disk. 373c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 374c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.is_removable_device(device): 375c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if os.path.exists('/dev/mmcblk1'): 376c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return '/dev/mmcblk1' 377c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 378c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return '/dev/sda' 379c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 380c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.strip_part(device) 381c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 382c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_root_part(self): 383c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Return a string, the name of root device with partition number''' 384c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.run_shell_command_get_output('rootdev -s')[0] 385c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 386c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_root_dev(self): 387c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Return a string, the name of root device without partition number''' 388c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.strip_part(self.get_root_part()) 389c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 390c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def join_part(self, dev, part): 391c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Return a concatenated string of device and partition number''' 392c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if 'mmcblk' in dev: 393c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return dev + 'p' + part 394c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 395c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return dev + part 396c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 397c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def strip_part(self, dev_with_part): 398c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Return a stripped string without partition number''' 399c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam dev_name_stripper = re.compile('p?[0-9]+$') 400c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return dev_name_stripper.sub('', dev_with_part) 401c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 402c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def run_shell_command_get_output(self, cmd): 403c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Run shell command and return its console output to the caller. 404c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 405c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The output is returned as a list of strings stripped of the newline 406c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam characters.''' 407c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 408c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam process = self.run_shell_command(cmd) 409c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return [x.rstrip() for x in process.stdout.readlines()] 410c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 411c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def boot_state_vector(self): 412c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Read and return to caller a string describing the system state. 413c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 414c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The string has a form of x0:x1:x2:<removable>:<partition_number>, 415c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam where the field meanings of X# are described in the 416c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Crossystem.get_boot_vector_base() docstring above. 417c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 418c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam <removable> is set to 1 or 0 depending if the root device is removable 419c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam or not, and <partition number> is the last element of the root device 420c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam name, designating the partition where the root fs is mounted. 421c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 422c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam This vector fully describes the way the system came up. 423c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 424c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 425c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state = self.cs.get_boot_vector_base() 426c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 427c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(state) != 3: 428c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise ChromeOSInterfaceError(self.cs.dump()) 429c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 430c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam root_part = self.get_root_part() 431c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state.append('%d' % int(self.is_removable_device(root_part))) 432c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state.append('%s' % root_part[-1]) 433c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam state_str = ':'.join(state) 434c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return state_str 435c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 436c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def cmp_boot_vector(self, vector1, vector2): 437c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Compare if the two boot vectors are the same 438c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 439c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Note: a wildcard (*) will match any value. 440c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 441c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam list1 = vector1.split(':') 442c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam list2 = vector2.split(':') 443c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(list1) != len(list2): 444c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise ChromeOSInterfaceError( 445c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'Boot vectors (%s %s) should be of the same length' 446c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam % (vecotr1, vector2)) 447c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for i in range(len(list1)): 448c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if list1[i] != list2[i] and list1[i] != '*' and list2[i] != '*': 449c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return False 450c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return True 451c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 452c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_writeable_mount_point(self, dev, tmp_dir): 453c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Get mountpoint of the passed in device mounted in read/write mode. 454c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 455c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam If the device is already mounted and is writeable - return its mount 456c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam point. If the device is mounted but read-only - remount it read/write 457c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam and return its mount point. If the device is not mounted - mount it read 458c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam write on the passsed in path and return this path. 459c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 460c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 461c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # The device root file system is mounted on is represented as /dev/root 462c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # otherwise. 463c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam options_filter = re.compile('.*\((.+)\).*') 464c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam root_part = self.get_root_part() 465c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if dev == root_part: 466c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam dev = '/dev/root' 467c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 468c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for line in self.run_shell_command_get_output('mount'): 469c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not line.startswith('%s ' % dev): 470c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 471c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam mount_options = options_filter.match(line).groups(0)[0] 472c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # found mounted 473c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if 'ro' in mount_options.split(','): 474c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # mounted read only 475c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.run_shell_command('mount -o remount,rw %s' % dev) 476c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return line.split()[2] # Mountpoint is the third element. 477c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Not found, needs to be mounted 478c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.run_shell_command('mount %s %s' % (dev, tmp_dir)) 479c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return tmp_dir 480c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 481c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def retrieve_body_version(self, blob): 482c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Given a blob, retrieve body version. 483c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 484c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Currently works for both, firmware and kernel blobs. Returns '-1' in 485c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam case the version can not be retrieved reliably. 486c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 487c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam header_format = '<8s8sQ' 488c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam preamble_format = '<40sQ' 489c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam magic, _, kb_size = struct.unpack_from(header_format, blob) 490c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 491c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if magic != 'CHROMEOS': 492c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return -1 # This could be a corrupted version case. 493c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 494c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam _, version = struct.unpack_from(preamble_format, blob, kb_size) 495c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return version 496c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 497c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def retrieve_datakey_version(self, blob): 498c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Given a blob, retrieve firmware data key version. 499c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 500c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Currently works for both, firmware and kernel blobs. Returns '-1' in 501c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam case the version can not be retrieved reliably. 502c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 503c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam header_format = '<8s96sQ' 504c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam magic, _, version = struct.unpack_from(header_format, blob) 505c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if magic != 'CHROMEOS': 506c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return -1 # This could be a corrupted version case. 507c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return version 508c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 509c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def retrieve_kernel_subkey_version(self, blob): 510c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Given a blob, retrieve kernel subkey version. 511c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 512c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam It is in firmware vblock's preamble. 513c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 514c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 515c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam header_format = '<8s8sQ' 516c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam preamble_format = '<72sQ' 517c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam magic, _, kb_size = struct.unpack_from(header_format, blob) 518c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 519c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if magic != 'CHROMEOS': 520c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return -1 521c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 522c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam _, version = struct.unpack_from(preamble_format, blob, kb_size) 523c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return version 524c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 525c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def retrieve_preamble_flags(self, blob): 526c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Given a blob, retrieve preamble flags if available. 527c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 528c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam It only works for firmware. If the version of preamble header is less 529c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam than 2.1, no preamble flags supported, just returns 0. 530c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ''' 531c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam header_format = '<8s8sQ' 532c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam preamble_format = '<32sII64sI' 533c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam magic, _, kb_size = struct.unpack_from(header_format, blob) 534c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 535c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if magic != 'CHROMEOS': 536c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return -1 # This could be a corrupted version case. 537c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 538c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam _, ver, subver, _, flags = struct.unpack_from(preamble_format, blob, 539c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam kb_size) 540c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 541c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if ver > 2 or (ver == 2 and subver >= 1): 542c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return flags 543c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 544c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 0 # Returns 0 if preamble flags not available. 545c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 546c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def read_partition(self, partition, size): 547c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam '''Read the requested partition, up to size bytes.''' 548c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tmp_file = self.state_dir_file('part.tmp') 549c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.run_shell_command('dd if=%s of=%s bs=1 count=%d' % ( 550c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam partition, tmp_file, size)) 551c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam fileh = open(tmp_file, 'r') 552c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam data = fileh.read() 553c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam fileh.close() 554c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam os.remove(tmp_file) 555c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return data 556