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 Tamclass TestError(Exception): 25c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pass 26c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 27c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 28c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass LayoutScraper(object): 29be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Object of this class is used to retrieve layout from a BIOS file.""" 30c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 31c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # The default conversion table for mosys. 32c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam DEFAULT_CHROMEOS_FMAP_CONVERSION = { 33c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Boot Stub": "FV_BSTUB", 34c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "GBB Area": "FV_GBB", 35c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Recovery Firmware": "FVDEV", 36c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "RO VPD": "RO_VPD", 37c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware A Key": "VBOOTA", 38c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware A Data": "FVMAIN", 39c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware B Key": "VBOOTB", 40c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Firmware B Data": "FVMAINB", 41c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "Log Volume": "FV_LOG", 42c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # New layout in Chrome OS Main Processor Firmware Specification, 43c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # used by all newer (>2011) platforms except Mario. 44c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "BOOT_STUB": "FV_BSTUB", 45c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "GBB": "FV_GBB", 46c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "RECOVERY": "FVDEV", 47c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "VBLOCK_A": "VBOOTA", 48c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "VBLOCK_B": "VBOOTB", 49c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "FW_MAIN_A": "FVMAIN", 50c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "FW_MAIN_B": "FVMAINB", 51dcff84266ccf29d474e902b597225a1e07cb765dTyler Reid # Memory Training data cache for recovery boots 52dcff84266ccf29d474e902b597225a1e07cb765dTyler Reid # Added on Nov 09, 2016 53dcff84266ccf29d474e902b597225a1e07cb765dTyler Reid "RECOVERY_MRC_CACHE": "RECOVERY_MRC_CACHE", 548086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam # New sections in Depthcharge. 558086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam "EC_MAIN_A": "ECMAINA", 568086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam "EC_MAIN_B": "ECMAINB", 57c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # EC firmware layout 58c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "EC_RW": "EC_RW", 59c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 60c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 61c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __init__(self, os_if): 62c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.image = None 63c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if = os_if 64c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 65c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _get_text_layout(self, file_name): 66be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Retrieve text layout from a firmware image file. 67c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 68c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam This function uses the 'mosys' utility to scan the firmware image and 69c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam retrieve the section layout information. 70c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 71c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The layout is reported as a set of lines with multiple 72c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam "<name>"="value" pairs, all this output is passed to the caller. 73be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 74c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 7564161b4d52c8d313ade6427cd290b90ff1e26581David Hendricks mosys_cmd = 'mosys -k eeprom map %s' % file_name 76c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.os_if.run_shell_command_get_output(mosys_cmd) 77c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 78c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _line_to_dictionary(self, line): 79be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Convert a text layout line into a dictionary. 80c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 81c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Get a string consisting of single space separated "<name>"="value>" 82c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pairs and convert it into a dictionary where keys are the <name> 83c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam fields, and values are the corresponding <value> fields. 84c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 85c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Return the dictionary to the caller. 86be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 87c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 88c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam rv = {} 89c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 90c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam items = line.replace('" ', '"^').split('^') 91c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for item in items: 92c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pieces = item.split('=') 93c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(pieces) != 2: 94c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 95c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam rv[pieces[0]] = pieces[1].strip('"') 96c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return rv 97c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 98c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def check_layout(self, layout, file_size): 99be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Verify the layout to be consistent. 100c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 101c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam The layout is consistent if there is no overlapping sections and the 102c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section boundaries do not exceed the file size. 103c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 104c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Inputs: 105c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout: a dictionary keyed by a string (the section name) with 106c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam values being two integers tuples, the first and the last 107c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam bites' offset in the file. 108c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam file_size: and integer, the size of the file the layout describes 109c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam the sections in. 110c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 111c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises: 112c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam TestError in case the layout is not consistent. 113be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 114c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 115c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Generate a list of section range tuples. 116c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ost = sorted([layout[section] for section in layout]) 117c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base = -1 118c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for section_base, section_end in ost: 119c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if section_base <= base or section_end + 1 < section_base: 120c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('bad section at 0x%x..0x%x' % ( 121c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section_base, section_end)) 122c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base = section_end 123c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if base > file_size: 124c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('Section end 0x%x exceeds file size %x' % ( 125c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam base, file_size)) 126c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 127c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_layout(self, file_name): 128be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Generate layout for a firmware file. 129c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 130c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam First retrieve the text layout as reported by 'mosys' and then convert 131c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam it into a dictionary, replacing section names reported by mosys into 132c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam matching names from DEFAULT_CHROMEOS_FMAP_CONVERSION dictionary above, 133c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam using the names as keys in the layout dictionary. The elements of the 134c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout dictionary are the offsets of the first ans last bytes of the 135c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section in the firmware file. 136c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 137c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Then verify the generated layout's consistency and return it to the 138c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam caller. 139be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 140c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 141c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_data = {} # keyed by the section name, elements - tuples of 142c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # (<section start addr>, <section end addr>) 143c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 144c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for line in self._get_text_layout(file_name): 145c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam d = self._line_to_dictionary(line) 146c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam try: 147c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam name = self.DEFAULT_CHROMEOS_FMAP_CONVERSION[d['area_name']] 148c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam except KeyError: 149c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue # This line does not contain an area of interest. 150c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 151c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if name in layout_data: 1529999730bc117c6a6363b616d3da5dbf0eb6b4d50Tom Wai-Hong Tam raise TestError('%s duplicated in the layout' % name) 153c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 154c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam offset = int(d['area_offset'], 0) 155c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam size = int(d['area_size'], 0) 156c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_data[name] = (offset, offset + size - 1) 157c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 15838aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self.check_layout(layout_data, self.os_if.get_file_size(file_name)) 159c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return layout_data 160c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 161c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# flashrom utility wrapper 162c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass flashrom_util(object): 163c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ a wrapper for "flashrom" utility. 164c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 165c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam You can read, write, or query flash ROM size with this utility. 166c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Although you can do "partial-write", the tools always takes a 167c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam full ROM image as input parameter. 168c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 169c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam NOTE before accessing flash ROM, you may need to first "select" 170c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam your target - usually BIOS or EC. That part is not handled by 171c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam this utility. Please find other external script to do it. 172c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 173c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam To perform a read, you need to: 174c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1. Prepare a flashrom_util object 175c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: flashrom = flashrom_util.flashrom_util() 176c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2. Perform read operation 177c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: image = flashrom.read_whole() 178c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 179c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam When the contents of the flashrom is read off the target, it's map 180c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam gets created automatically (read from the flashrom image using 181c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'mosys'). If the user wants this object to operate on some other file, 182c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam he could either have the map for the file created explicitly by 183c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam invoking flashrom.set_firmware_layout(filename), or supply his own map 184c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (which is a dictionary where keys are section names, and values are 185c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam tuples of integers, base address of the section and the last address 186c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam of the section). 187c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 188c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam By default this object operates on the map retrieved from the image and 189c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam stored locally, this map can be overwritten by an explicitly passed user 190c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam map. 191c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 192c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam To perform a (partial) write: 193c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 194c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1. Prepare a buffer storing an image to be written into the flashrom. 195c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 2. Have the map generated automatically or prepare your own, for instance: 196c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: layout_map_all = { 'all': (0, rom_size - 1) } 197c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex: layout_map = { 'ro': (0, 0xFFF), 'rw': (0x1000, rom_size-1) } 198c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 4. Perform write operation 199c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 200c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex using default map: 201c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam flashrom.write_partial(new_image, (<section_name>, ...)) 202c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ex using explicitly provided map: 203c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam flashrom.write_partial(new_image, layout_map_all, ('all',)) 204c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 205c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attributes: 206c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam keep_temp_files: boolean flag to control cleaning of temporary files 207c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ 208c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 209ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam def __init__(self, os_if, keep_temp_files=False, 210be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam target_is_ec=False): 211c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ constructor of flashrom_util. help(flashrom_util) for more info """ 212ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam self.os_if = os_if 213c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.keep_temp_files = keep_temp_files 214c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.firmware_layout = {} 215c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command = '' 216c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if target_is_ec: 217c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._enable_ec_access() 218c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 219c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._enable_bios_access() 220c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 221c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _enable_bios_access(self): 222c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.os_if.target_hosted(): 223c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 22437bcc951d328d064255426a10ec6fd855c0eaeb4David Hendricks self._target_command = '-p host' 225c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 226c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def _enable_ec_access(self): 227c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not self.os_if.target_hosted(): 228c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 22937bcc951d328d064255426a10ec6fd855c0eaeb4David Hendricks self._target_command = '-p ec' 230c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 23138aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam def _get_temp_filename(self, prefix): 23238aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam """Returns name of a temporary file in /tmp.""" 23338aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam return self.os_if.create_temp_file(prefix) 234c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 23538aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam def _remove_temp_file(self, filename): 23638aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam """Removes a temp file if self.keep_temp_files is false.""" 237c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.keep_temp_files: 238c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 23938aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam if self.os_if.path_exists(filename): 24038aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self.os_if.remove_file(filename) 24138aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam 24238aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam def _create_layout_file(self, layout_map): 24338aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam """Creates a layout file based on layout_map. 244c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 245c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the file name containing layout information. 246be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 247c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_text = ['0x%08lX:0x%08lX %s' % (v[0], v[1], k) 248c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for k, v in layout_map.items()] 249c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_text.sort() # XXX unstable if range exceeds 2^32 25038aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam tmpfn = self._get_temp_filename('lay_') 25138aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self.os_if.write_file(tmpfn, '\n'.join(layout_text) + '\n') 252c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return tmpfn 253c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 254c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_section(self, base_image, section_name): 255be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 256c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Retrieves a section of data based on section_name in layout_map. 257c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises error if unknown section or invalid layout_map. 258be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 2598086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if section_name not in self.firmware_layout: 2608086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam return [] 261c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pos = self.firmware_layout[section_name] 262c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if pos[0] >= pos[1] or pos[1] >= len(base_image): 263c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('INTERNAL ERROR: invalid layout map: %s.' % 264c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam section_name) 265eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = base_image[pos[0] : pos[1] + 1] 266eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # Trim down the main firmware body to its actual size since the 267eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # signing utility uses the size of the input file as the size of 268eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # the data to sign. Make it the same way as firmware creation. 2698086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if section_name in ('FVMAIN', 'FVMAINB', 'ECMAINA', 'ECMAINB'): 270eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam align = 4 271eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam pad = blob[-1] 272eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = blob.rstrip(pad) 273eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam blob = blob + ((align - 1) - (len(blob) - 1) % align) * pad 274eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam return blob 275c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 276c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def put_section(self, base_image, section_name, data): 277be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 278c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Updates a section of data based on section_name in firmware_layout. 279c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises error if unknown section. 280c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the full updated image data. 281be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 282c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pos = self.firmware_layout[section_name] 283c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if pos[0] >= pos[1] or pos[1] >= len(base_image): 284c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TestError('INTERNAL ERROR: invalid layout map.') 285c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if len(data) != pos[1] - pos[0] + 1: 286eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam # Pad the main firmware body since we trimed it down before. 2878086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam if (len(data) < pos[1] - pos[0] + 1 and section_name in 2888086f96b61050d813db785f8a416d884bd0b2225Tom Wai-Hong Tam ('FVMAIN', 'FVMAINB', 'ECMAINA', 'ECMAINB')): 289eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam pad = base_image[pos[1]] 290eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam data = data + pad * (pos[1] - pos[0] + 1 - len(data)) 291eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam else: 292eac7acffc449b41455a2ae57ed5df9a6fa83f352Tom Wai-Hong Tam raise TestError('INTERNAL ERROR: unmatched data size.') 293c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return base_image[0 : pos[0]] + data + base_image[pos[1] + 1 :] 294c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 295c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_size(self): 296c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """ Gets size of current flash ROM """ 297c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # TODO(hungte) Newer version of tool (flashrom) may support --get-size 298c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # command which is faster in future. Right now we use back-compatible 299c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # method: read whole and then get length. 300c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam image = self.read_whole() 301c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return len(image) 302c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 303c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def set_firmware_layout(self, file_name): 304c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam """get layout read from the BIOS """ 305c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 306c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam scraper = LayoutScraper(self.os_if) 307c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.firmware_layout = scraper.get_layout(file_name) 308c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 30944204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam def enable_write_protect(self): 31044204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam """Enable the write pretection of the flash chip.""" 31144204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam cmd = 'flashrom %s --wp-enable' % self._target_command 31244204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 31344204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam 31444204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam def disable_write_protect(self): 31544204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam """Disable the write pretection of the flash chip.""" 31644204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam cmd = 'flashrom %s --wp-disable' % self._target_command 31744204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 31844204b3e74e1ee85a19e330894e731ef554c0a6dTom Wai-Hong Tam 319c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def read_whole(self): 320be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 321c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Reads whole flash ROM data. 322c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Returns the data read from flash ROM, or empty string for other error. 323be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 32438aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam tmpfn = self._get_temp_filename('rd_') 325c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam cmd = 'flashrom %s -r "%s"' % (self._target_command, tmpfn) 32622331b87b470527c17309695a07560d67cb9ddd1Tom Wai-Hong Tam self.os_if.log('flashrom_util.read_whole(): %s' % cmd) 327c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 32838aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam result = self.os_if.read_file(tmpfn) 329c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.set_firmware_layout(tmpfn) 330c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 331c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # clean temporary resources 33238aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self._remove_temp_file(tmpfn) 333c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return result 334c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 335c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def write_partial(self, base_image, write_list, write_layout_map=None): 336be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 337c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Writes data in sections of write_list to flash ROM. 338c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam An exception is raised if write operation fails. 339be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 340c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 341c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if write_layout_map: 342c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = write_layout_map 343c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam else: 344c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = self.firmware_layout 345c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 34638aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam tmpfn = self._get_temp_filename('wr_') 34738aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self.os_if.write_file(tmpfn, base_image) 34838aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam layout_fn = self._create_layout_file(layout_map) 349c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 350c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam cmd = 'flashrom %s -l "%s" -i %s -w "%s"' % ( 351c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self._target_command, layout_fn, ' -i '.join(write_list), tmpfn) 35222331b87b470527c17309695a07560d67cb9ddd1Tom Wai-Hong Tam self.os_if.log('flashrom.write_partial(): %s' % cmd) 353c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if.run_shell_command(cmd) 354c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 3556dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen # flashrom write will reboot the ec after corruption 3566dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen # For Android, need to make sure ec is back online 3576dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen # before continuing, or adb command will cause test failure 3586dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen if self.os_if.is_android: 3596dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen self.os_if.wait_for_device(60) 3606dd5843d5526bd472d61bc4a3dd38d1a8e5fe24bShelley Chen 361c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # clean temporary resources 36238aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self._remove_temp_file(tmpfn) 36338aa548ceb0f1fdb081deb9389b4c8e99aee485bTom Wai-Hong Tam self._remove_temp_file(layout_fn) 364c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 365c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def write_whole(self, base_image): 366be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Write the whole base image. """ 367c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam layout_map = { 'all': (0, len(base_image) - 1) } 368c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.write_partial(base_image, ('all',), layout_map) 369