saft_flashrom_util.py revision 8086f96b61050d813db785f8a416d884bd0b2225
1c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Use of this source code is governed by a BSD-style license that can be 3c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# found in the LICENSE file. 4c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 5c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam""" This module provides convenience routines to access Flash ROM (EEPROM) 6c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 7c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamsaft_flashrom_util is based on utility 'flashrom'. 8c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 9c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamOriginal tool syntax: 10c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (read ) flashrom -r <file> 11c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (write) flashrom -l <layout_fn> [-i <image_name> ...] -w <file> 12c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 13c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamThe layout_fn is in format of 14c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam address_begin:address_end image_name 15c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam which defines a region between (address_begin, address_end) and can 16c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam be accessed by the name image_name. 17c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 18c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamCurrently the tool supports multiple partial write but not partial read. 19c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 20c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamIn the saft_flashrom_util, we provide read and partial write abilities. 21c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamFor more information, see help(saft_flashrom_util.flashrom_util). 22c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam""" 23c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 24c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport os 25c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport re 26c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport stat 27c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport subprocess 28c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport sys 29c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport tempfile 30c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport types 31c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 32c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamimport chromeos_interface 33c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 34c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass TestError(Exception): 35c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pass 36c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 37c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 38c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass LayoutScraper(object): 39be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Object of this class is used to retrieve layout from a BIOS file.""" 40c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 41c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # The default conversion table for mosys. 42c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam DEFAULT_CHROMEOS_FMAP_CONVERSION = { 43c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Boot Stub": "FV_BSTUB", 44c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "GBB Area": "FV_GBB", 45c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Recovery Firmware": "FVDEV", 46c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "RO VPD": "RO_VPD", 47c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware A Key": "VBOOTA", 48c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware A Data": "FVMAIN", 49c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware B Key": "VBOOTB", 50c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware B Data": "FVMAINB", 51c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Log Volume": "FV_LOG", 52c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # New layout in Chrome OS Main Processor Firmware Specification, 53c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # used by all newer (>2011) platforms except Mario. 54c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "BOOT_STUB": "FV_BSTUB", 55c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "GBB": "FV_GBB", 56c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "RECOVERY": "FVDEV", 57c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "VBLOCK_A": "VBOOTA", 58c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "VBLOCK_B": "VBOOTB", 59c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "FW_MAIN_A": "FVMAIN", 60c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "FW_MAIN_B": "FVMAINB", 618086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam # New sections in Depthcharge. 628086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam "EC_MAIN_A": "ECMAINA", 638086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam "EC_MAIN_B": "ECMAINB", 64c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # EC firmware layout 65c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "EC_RW": "EC_RW", 66c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 67c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 68c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __init__(self, os_if): 69c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.image = None 70c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if = os_if 71c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 72c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _get_text_layout(self, file_name): 73be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Retrieve text layout from a firmware image file. 74c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 75c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam This function uses the 'mosys' utility to scan the firmware image and 76c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam retrieve the section layout information. 77c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 78c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The layout is reported as a set of lines with multiple 79c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "<name>"="value" pairs, all this output is passed to the caller. 80be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 81c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 82c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam mosys_cmd = 'mosys -f -k eeprom map %s' % file_name 83c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.os_if.run_shell_command_get_output(mosys_cmd) 84c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 85c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _line_to_dictionary(self, line): 86be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Convert a text layout line into a dictionary. 87c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 88c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Get a string consisting of single space separated "<name>"="value>" 89c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pairs and convert it into a dictionary where keys are the <name> 90c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam fields, and values are the corresponding <value> fields. 91c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 92c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Return the dictionary to the caller. 93be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 94c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 95c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam rv = {} 96c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 97c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam items = line.replace('" ', '"^').split('^') 98c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for item in items: 99c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pieces = item.split('=') 100c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(pieces) != 2: 101c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 102c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam rv[pieces[0]] = pieces[1].strip('"') 103c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return rv 104c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 105c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def check_layout(self, layout, file_size): 106be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Verify the layout to be consistent. 107c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 108c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The layout is consistent if there is no overlapping sections and the 109c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section boundaries do not exceed the file size. 110c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 111c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Inputs: 112c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout: a dictionary keyed by a string (the section name) with 113c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam values being two integers tuples, the first and the last 114c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam bites' offset in the file. 115c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam file_size: and integer, the size of the file the layout describes 116c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam the sections in. 117c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 118c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises: 119c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam TestError in case the layout is not consistent. 120be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 121c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 122c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Generate a list of section range tuples. 123c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ost = sorted([layout[section] for section in layout]) 124c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base = -1 125c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for section_base, section_end in ost: 126c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if section_base <= base or section_end + 1 < section_base: 127c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('bad section at 0x%x..0x%x' % ( 128c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section_base, section_end)) 129c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base = section_end 130c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if base > file_size: 131c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('Section end 0x%x exceeds file size %x' % ( 132c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base, file_size)) 133c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 134c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_layout(self, file_name): 135be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Generate layout for a firmware file. 136c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 137c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam First retrieve the text layout as reported by 'mosys' and then convert 138c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam it into a dictionary, replacing section names reported by mosys into 139c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam matching names from DEFAULT_CHROMEOS_FMAP_CONVERSION dictionary above, 140c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam using the names as keys in the layout dictionary. The elements of the 141c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout dictionary are the offsets of the first ans last bytes of the 142c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section in the firmware file. 143c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 144c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Then verify the generated layout's consistency and return it to the 145c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam caller. 146be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 147c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 148c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_data = {} # keyed by the section name, elements - tuples of 149c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # (<section start addr>, <section end addr>) 150c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 151c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for line in self._get_text_layout(file_name): 152c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam d = self._line_to_dictionary(line) 153c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam try: 154c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam name = self.DEFAULT_CHROMEOS_FMAP_CONVERSION[d['area_name']] 155c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam except KeyError: 156c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue # This line does not contain an area of interest. 157c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 158c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if name in layout_data: 159c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('%s duplicated in the layout' % area_name) 160c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 161c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam offset = int(d['area_offset'], 0) 162c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam size = int(d['area_size'], 0) 163c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_data[name] = (offset, offset + size - 1) 164c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 165c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.check_layout(layout_data, os.stat(file_name)[stat.ST_SIZE]) 166c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return layout_data 167c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 168c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# flashrom utility wrapper 169c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass flashrom_util(object): 170c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ a wrapper for "flashrom" utility. 171c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 172c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam You can read, write, or query flash ROM size with this utility. 173c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Although you can do "partial-write", the tools always takes a 174c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam full ROM image as input parameter. 175c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 176c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam NOTE before accessing flash ROM, you may need to first "select" 177c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam your target - usually BIOS or EC. That part is not handled by 178c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam this utility. Please find other external script to do it. 179c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 180c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam To perform a read, you need to: 181c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1. Prepare a flashrom_util object 182c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: flashrom = flashrom_util.flashrom_util() 183c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2. Perform read operation 184c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: image = flashrom.read_whole() 185c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 186c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam When the contents of the flashrom is read off the target, it's map 187c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam gets created automatically (read from the flashrom image using 188c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mosys'). If the user wants this object to operate on some other file, 189c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam he could either have the map for the file created explicitly by 190c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam invoking flashrom.set_firmware_layout(filename), or supply his own map 191c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (which is a dictionary where keys are section names, and values are 192c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tuples of integers, base address of the section and the last address 193c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam of the section). 194c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 195c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam By default this object operates on the map retrieved from the image and 196c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam stored locally, this map can be overwritten by an explicitly passed user 197c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam map. 198c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 199c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam To perform a (partial) write: 200c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 201c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1. Prepare a buffer storing an image to be written into the flashrom. 202c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2. Have the map generated automatically or prepare your own, for instance: 203c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: layout_map_all = { 'all': (0, rom_size - 1) } 204c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: layout_map = { 'ro': (0, 0xFFF), 'rw': (0x1000, rom_size-1) } 205c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 4. Perform write operation 206c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 207c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex using default map: 208c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam flashrom.write_partial(new_image, (<section_name>, ...)) 209c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex using explicitly provided map: 210c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam flashrom.write_partial(new_image, layout_map_all, ('all',)) 211c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 212c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attributes: 213c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam verbose: print debug and helpful messages 214c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam keep_temp_files: boolean flag to control cleaning of temporary files 215c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ 216c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 217be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam def __init__(self, verbose=False, keep_temp_files=False, 218be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam target_is_ec=False): 219c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ constructor of flashrom_util. help(flashrom_util) for more info """ 220c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.verbose = verbose 221c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.keep_temp_files = keep_temp_files 222c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.firmware_layout = {} 223c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if = chromeos_interface.ChromeOSInterface(True) 224c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if.init(tempfile.gettempdir()) 225c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command = '' 226c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if target_is_ec: 227c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._enable_ec_access() 228c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 229c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._enable_bios_access() 230c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 231c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _enable_bios_access(self): 232c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.os_if.target_hosted(): 233c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 234c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command = '-p internal:bus=spi' 235c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 236c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _enable_ec_access(self): 237c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.os_if.target_hosted(): 238c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 239c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command = '-p internal:bus=lpc' 240c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 241c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_temp_filename(self, prefix): 242be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ (internal) Returns name of a temporary file in self.tmp_root """ 243c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (fd, name) = tempfile.mkstemp(prefix=prefix) 244c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam os.close(fd) 245c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return name 246c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 247c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def remove_temp_file(self, filename): 248c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ (internal) Removes a temp file if self.keep_temp_files is false. """ 249c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.keep_temp_files: 250c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 251c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if os.path.exists(filename): 252c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam os.remove(filename) 253c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 254c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def create_layout_file(self, layout_map): 255be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 256c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (internal) Creates a layout file based on layout_map. 257c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the file name containing layout information. 258be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 259c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_text = ['0x%08lX:0x%08lX %s' % (v[0], v[1], k) 260c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for k, v in layout_map.items()] 261c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_text.sort() # XXX unstable if range exceeds 2^32 262c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tmpfn = self.get_temp_filename('lay') 263c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam open(tmpfn, 'wb').write('\n'.join(layout_text) + '\n') 264c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return tmpfn 265c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 266c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_section(self, base_image, section_name): 267be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 268c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Retrieves a section of data based on section_name in layout_map. 269c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises error if unknown section or invalid layout_map. 270be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 2718086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if section_name not in self.firmware_layout: 2728086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam return [] 273c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pos = self.firmware_layout[section_name] 274c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if pos[0] >= pos[1] or pos[1] >= len(base_image): 275c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('INTERNAL ERROR: invalid layout map: %s.' % 276c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section_name) 277eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = base_image[pos[0] : pos[1] + 1] 278eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # Trim down the main firmware body to its actual size since the 279eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # signing utility uses the size of the input file as the size of 280eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # the data to sign. Make it the same way as firmware creation. 2818086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if section_name in ('FVMAIN', 'FVMAINB', 'ECMAINA', 'ECMAINB'): 282eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam align = 4 283eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam pad = blob[-1] 284eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = blob.rstrip(pad) 285eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = blob + ((align - 1) - (len(blob) - 1) % align) * pad 286eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam return blob 287c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 288c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def put_section(self, base_image, section_name, data): 289be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 290c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Updates a section of data based on section_name in firmware_layout. 291c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises error if unknown section. 292c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the full updated image data. 293be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 294c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pos = self.firmware_layout[section_name] 295c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if pos[0] >= pos[1] or pos[1] >= len(base_image): 296c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('INTERNAL ERROR: invalid layout map.') 297c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(data) != pos[1] - pos[0] + 1: 298eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # Pad the main firmware body since we trimed it down before. 2998086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if (len(data) < pos[1] - pos[0] + 1 and section_name in 3008086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam ('FVMAIN', 'FVMAINB', 'ECMAINA', 'ECMAINB')): 301eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam pad = base_image[pos[1]] 302eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam data = data + pad * (pos[1] - pos[0] + 1 - len(data)) 303eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam else: 304eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam raise TestError('INTERNAL ERROR: unmatched data size.') 305c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return base_image[0 : pos[0]] + data + base_image[pos[1] + 1 :] 306c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 307c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_size(self): 308c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ Gets size of current flash ROM """ 309c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # TODO(hungte) Newer version of tool (flashrom) may support --get-size 310c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # command which is faster in future. Right now we use back-compatible 311c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # method: read whole and then get length. 312c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam image = self.read_whole() 313c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return len(image) 314c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 315c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def set_firmware_layout(self, file_name): 316c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """get layout read from the BIOS """ 317c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 318c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam scraper = LayoutScraper(self.os_if) 319c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.firmware_layout = scraper.get_layout(file_name) 320c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 32144204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam def enable_write_protect(self): 32244204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam """Enable the write pretection of the flash chip.""" 32344204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam cmd = 'flashrom %s --wp-enable' % self._target_command 32444204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 32544204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam 32644204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam def disable_write_protect(self): 32744204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam """Disable the write pretection of the flash chip.""" 32844204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam cmd = 'flashrom %s --wp-disable' % self._target_command 32944204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 33044204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam 331c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def read_whole(self): 332be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 333c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Reads whole flash ROM data. 334c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the data read from flash ROM, or empty string for other error. 335be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 336c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tmpfn = self.get_temp_filename('rd_') 337c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam cmd = 'flashrom %s -r "%s"' % (self._target_command, tmpfn) 338c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.verbose: 339c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam print 'flashrom_util.read_whole(): ', cmd 340c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 341c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 342c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam result = open(tmpfn, 'rb').read() 343c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.set_firmware_layout(tmpfn) 344c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 345c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # clean temporary resources 346c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.remove_temp_file(tmpfn) 347c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return result 348c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 349c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def write_partial(self, base_image, write_list, write_layout_map=None): 350be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 351c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Writes data in sections of write_list to flash ROM. 352c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam An exception is raised if write operation fails. 353be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 354c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 355c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if write_layout_map: 356c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = write_layout_map 357c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 358c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = self.firmware_layout 359c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 360c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tmpfn = self.get_temp_filename('wr_') 361c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam open(tmpfn, 'wb').write(base_image) 362c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_fn = self.create_layout_file(layout_map) 363c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 364c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam cmd = 'flashrom %s -l "%s" -i %s -w "%s"' % ( 365c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command, layout_fn, ' -i '.join(write_list), tmpfn) 366c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.verbose: 367c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam print 'flashrom.write_partial(): ', cmd 368c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 369c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 370c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 371c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # clean temporary resources 372c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.remove_temp_file(tmpfn) 373c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.remove_temp_file(layout_fn) 374c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 375c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def write_whole(self, base_image): 376be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Write the whole base image. """ 377c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = { 'all': (0, len(base_image) - 1) } 378c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.write_partial(base_image, ('all',), layout_map) 379