| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 '''A module to support automated testing of ChromeOS formware. | 6 '''A module to support automated testing of ChromeOS formware. |
| 7 | 7 |
| 8 Utilizes services provided by <board arch>/flashrom_util.py read/write the | 8 Utilizes services provided by <board arch>/flashrom_util.py read/write the |
| 9 flashrom chip and to parse the flash rom image. | 9 flashrom chip and to parse the flash rom image. |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 '''An object to provide logical services for automated flashrom testing.''' | 32 '''An object to provide logical services for automated flashrom testing.''' |
| 33 | 33 |
| 34 DELTA = 1 # value to add to a byte to corrupt a section contents | 34 DELTA = 1 # value to add to a byte to corrupt a section contents |
| 35 | 35 |
| 36 # File in the state directory to store public root key. | 36 # File in the state directory to store public root key. |
| 37 PUB_KEY_FILE_NAME = 'root.pubkey' | 37 PUB_KEY_FILE_NAME = 'root.pubkey' |
| 38 | 38 |
| 39 def __init__(self): | 39 def __init__(self): |
| 40 # make sure it does not accidentally overwrite the image. | 40 # make sure it does not accidentally overwrite the image. |
| 41 self.fum = None | 41 self.fum = None |
| 42 self.bios_layout = None | |
| 43 self.chros_if = None | 42 self.chros_if = None |
| 44 self.image = '' | 43 self.image = '' |
| 45 self.pub_key_file = '' | 44 self.pub_key_file = '' |
| 46 self.fv_sections = { | 45 self.fv_sections = { |
| 47 'a': FvImage('VBOOTA', 'FVMAIN'), | 46 'a': FvImage('VBOOTA', 'FVMAIN'), |
| 48 'b': FvImage('VBOOTB', 'FVMAINB'), | 47 'b': FvImage('VBOOTB', 'FVMAINB'), |
| 49 } | 48 } |
| 50 | 49 |
| 51 def init(self, flashrom_util_module, chros_if, pub_key_file=None): | 50 def init(self, flashrom_util_module, chros_if, pub_key_file=None): |
| 52 '''Flashrom handler initializer. | 51 '''Flashrom handler initializer. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 70 flashrom is read and its contents are saved into a | 69 flashrom is read and its contents are saved into a |
| 71 temporary file which is used instead. | 70 temporary file which is used instead. |
| 72 | 71 |
| 73 The input file is parsed and the sections of importance (as defined in | 72 The input file is parsed and the sections of importance (as defined in |
| 74 self.fv_sections) are saved in separate files in the state directory | 73 self.fv_sections) are saved in separate files in the state directory |
| 75 as defined in the chros_if object. | 74 as defined in the chros_if object. |
| 76 ''' | 75 ''' |
| 77 | 76 |
| 78 if image_file: | 77 if image_file: |
| 79 self.image = open(image_file, 'rb').read() | 78 self.image = open(image_file, 'rb').read() |
| 79 self.fum.set_bios_layout(image_file) |
| 80 else: | 80 else: |
| 81 self.image = self.fum.read_whole() | 81 self.image = self.fum.read_whole() |
| 82 self.bios_layout = self.fum.detect_chromeos_layout('bios', | |
| 83 len(self.image)) | |
| 84 self.whole_flash_layout = self.fum.detect_layout('all', | |
| 85 len(self.image)) | |
| 86 | 82 |
| 87 for section in self.fv_sections.itervalues(): | 83 for section in self.fv_sections.itervalues(): |
| 88 for subsection_name in section.names(): | 84 for subsection_name in section.names(): |
| 89 f = open(self.chros_if.state_dir_file(subsection_name), 'wb') | 85 f = open(self.chros_if.state_dir_file(subsection_name), 'wb') |
| 90 f.write(self.fum.get_section(self.image, | 86 f.write(self.fum.get_section(self.image, subsection_name)) |
| 91 self.bios_layout, subsection_name)) | |
| 92 f.close() | 87 f.close() |
| 93 | 88 |
| 94 if not self.pub_key_file: | 89 if not self.pub_key_file: |
| 95 self._retrieve_pub_key() | 90 self._retrieve_pub_key() |
| 96 | 91 |
| 97 def _retrieve_pub_key(self): | 92 def _retrieve_pub_key(self): |
| 98 '''Retrieve root public key from the firmware GBB section.''' | 93 '''Retrieve root public key from the firmware GBB section.''' |
| 99 | 94 |
| 100 gbb_header_format = '<4s20s2I' | 95 gbb_header_format = '<4s20s2I' |
| 101 pubk_header_format = '<2Q' | 96 pubk_header_format = '<2Q' |
| 102 | 97 |
| 103 gbb_section = self.fum.get_section( | 98 gbb_section = self.fum.get_section(self.image, 'FV_GBB') |
| 104 self.image, self.bios_layout, 'FV_GBB') | |
| 105 | 99 |
| 106 # do some sanity checks | 100 # do some sanity checks |
| 107 try: | 101 try: |
| 108 sig, _, rootk_offs, rootk_size = struct.unpack_from( | 102 sig, _, rootk_offs, rootk_size = struct.unpack_from( |
| 109 gbb_header_format, gbb_section) | 103 gbb_header_format, gbb_section) |
| 110 except struct.error, e: | 104 except struct.error, e: |
| 111 raise FlashromHandlerError(e) | 105 raise FlashromHandlerError(e) |
| 112 | 106 |
| 113 if sig != '$GBB' or (rootk_offs + rootk_size) > len(gbb_section): | 107 if sig != '$GBB' or (rootk_offs + rootk_size) > len(gbb_section): |
| 114 raise FlashromHandlerError('Bad gbb header') | 108 raise FlashromHandlerError('Bad gbb header') |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 158 |
| 165 if not self.image: | 159 if not self.image: |
| 166 raise FlashromHandlerError( | 160 raise FlashromHandlerError( |
| 167 'Attempt at using an uninitialized object') | 161 'Attempt at using an uninitialized object') |
| 168 if section not in self.fv_sections: | 162 if section not in self.fv_sections: |
| 169 raise FlashromHandlerError('Unknown FW section %s' | 163 raise FlashromHandlerError('Unknown FW section %s' |
| 170 % section) | 164 % section) |
| 171 | 165 |
| 172 # Get the appropriate section of the image. | 166 # Get the appropriate section of the image. |
| 173 subsection_name = self.fv_sections[section].body_name | 167 subsection_name = self.fv_sections[section].body_name |
| 174 body = self.fum.get_section(self.image, self.bios_layout, | 168 body = self.fum.get_section(self.image, subsection_name) |
| 175 subsection_name) | |
| 176 | 169 |
| 177 # Modify the byte in it within 5% of the section body. | 170 # Modify the byte in it within 5% of the section body. |
| 178 index = len(body) / 20 | 171 index = len(body) / 20 |
| 179 body_list = list(body) | 172 body_list = list(body) |
| 180 body_list[index] = '%c' % ((ord(body[index]) + delta) % 0x100) | 173 body_list[index] = '%c' % ((ord(body[index]) + delta) % 0x100) |
| 181 self.image = self.fum.put_section(self.image, self.bios_layout, | 174 self.image = self.fum.put_section(self.image, |
| 182 subsection_name, ''.join(body_list)) | 175 subsection_name, ''.join(body_list)) |
| 183 return subsection_name | 176 return subsection_name |
| 184 | 177 |
| 185 def corrupt_section(self, section): | 178 def corrupt_section(self, section): |
| 186 '''Corrupt a section of the image''' | 179 '''Corrupt a section of the image''' |
| 187 | 180 |
| 188 return self._modify_section(section, self.DELTA) | 181 return self._modify_section(section, self.DELTA) |
| 189 | 182 |
| 190 def restore_section(self, section): | 183 def restore_section(self, section): |
| 191 '''Restore a previously corrupted section of the image.''' | 184 '''Restore a previously corrupted section of the image.''' |
| 192 | 185 |
| 193 return self._modify_section(section, -self.DELTA) | 186 return self._modify_section(section, -self.DELTA) |
| 194 | 187 |
| 195 def corrupt_firmware(self, section): | 188 def corrupt_firmware(self, section): |
| 196 '''Corrupt a section in the FLASHROM!!!''' | 189 '''Corrupt a section in the FLASHROM!!!''' |
| 197 | 190 |
| 198 subsection_name = self.corrupt_section(section) | 191 subsection_name = self.corrupt_section(section) |
| 199 self.fum.write_partial(self.image, self.bios_layout, | 192 self.fum.write_partial(self.image, (subsection_name, )) |
| 200 (subsection_name, )) | |
| 201 | 193 |
| 202 def restore_firmware(self, section): | 194 def restore_firmware(self, section): |
| 203 '''Restore the previously corrupted section in the FLASHROM!!!''' | 195 '''Restore the previously corrupted section in the FLASHROM!!!''' |
| 204 | 196 |
| 205 subsection_name = self.restore_section(section) | 197 subsection_name = self.restore_section(section) |
| 206 self.fum.write_partial(self.image, self.bios_layout, | 198 self.fum.write_partial(self.image, (subsection_name, )) |
| 207 (subsection_name, )) | |
| 208 | 199 |
| 209 def write_whole(self): | 200 def write_whole(self): |
| 210 '''Write the whole image into the flashrom.''' | 201 '''Write the whole image into the flashrom.''' |
| 211 | 202 |
| 212 if not self.image: | 203 if not self.image: |
| 213 raise FlashromHandlerError( | 204 raise FlashromHandlerError( |
| 214 'Attempt at using an uninitialized object') | 205 'Attempt at using an uninitialized object') |
| 215 self.fum.write_partial(self.image, self.whole_flash_layout, ('all', )) | 206 self.fum.write_whole(self.image) |
| 216 | 207 |
| 217 def dump_whole(self, filename): | 208 def dump_whole(self, filename): |
| 218 '''Write the whole image into a file.''' | 209 '''Write the whole image into a file.''' |
| 219 | 210 |
| 220 if not self.image: | 211 if not self.image: |
| 221 raise FlashromHandlerError( | 212 raise FlashromHandlerError( |
| 222 'Attempt at using an uninitialized object') | 213 'Attempt at using an uninitialized object') |
| 223 open(filename, 'w').write(self.image) | 214 open(filename, 'w').write(self.image) |
| OLD | NEW |