mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	This needs special care to ensure that the bytes type is used for binary data. Add conversion code to deal with strings and bytes correctly. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			120 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # SPDX-License-Identifier: GPL-2.0+
 | |
| # Copyright (c) 2018 Google, Inc
 | |
| # Written by Simon Glass <sjg@chromium.org>
 | |
| #
 | |
| # Support for flashrom's FMAP format. This supports a header followed by a
 | |
| # number of 'areas', describing regions of a firmware storage device,
 | |
| # generally SPI flash.
 | |
| 
 | |
| import collections
 | |
| import struct
 | |
| import sys
 | |
| 
 | |
| import tools
 | |
| 
 | |
| # constants imported from lib/fmap.h
 | |
| FMAP_SIGNATURE = b'__FMAP__'
 | |
| FMAP_VER_MAJOR = 1
 | |
| FMAP_VER_MINOR = 0
 | |
| FMAP_STRLEN = 32
 | |
| 
 | |
| FMAP_AREA_STATIC = 1 << 0
 | |
| FMAP_AREA_COMPRESSED = 1 << 1
 | |
| FMAP_AREA_RO = 1 << 2
 | |
| 
 | |
| FMAP_HEADER_LEN = 56
 | |
| FMAP_AREA_LEN = 42
 | |
| 
 | |
| FMAP_HEADER_FORMAT = '<8sBBQI%dsH'% (FMAP_STRLEN)
 | |
| FMAP_AREA_FORMAT = '<II%dsH' % (FMAP_STRLEN)
 | |
| 
 | |
| FMAP_HEADER_NAMES = (
 | |
|     'signature',
 | |
|     'ver_major',
 | |
|     'ver_minor',
 | |
|     'base',
 | |
|     'image_size',
 | |
|     'name',
 | |
|     'nareas',
 | |
| )
 | |
| 
 | |
| FMAP_AREA_NAMES = (
 | |
|     'offset',
 | |
|     'size',
 | |
|     'name',
 | |
|     'flags',
 | |
| )
 | |
| 
 | |
| # These are the two data structures supported by flashrom, a header (which
 | |
| # appears once at the start) and an area (which is repeated until the end of
 | |
| # the list of areas)
 | |
| FmapHeader = collections.namedtuple('FmapHeader', FMAP_HEADER_NAMES)
 | |
| FmapArea = collections.namedtuple('FmapArea', FMAP_AREA_NAMES)
 | |
| 
 | |
| 
 | |
| def NameToFmap(name):
 | |
|     if type(name) == bytes and sys.version_info[0] >= 3:
 | |
|         name = name.decode('utf-8')  # pragma: no cover (for Python 2)
 | |
|     return name.replace('\0', '').replace('-', '_').upper()
 | |
| 
 | |
| def ConvertName(field_names, fields):
 | |
|     """Convert a name to something flashrom likes
 | |
| 
 | |
|     Flashrom requires upper case, underscores instead of hyphens. We remove any
 | |
|     null characters as well. This updates the 'name' value in fields.
 | |
| 
 | |
|     Args:
 | |
|         field_names: List of field names for this struct
 | |
|         fields: Dict:
 | |
|             key: Field name
 | |
|             value: value of that field (string for the ones we support)
 | |
|     """
 | |
|     name_index = field_names.index('name')
 | |
|     fields[name_index] = tools.ToBytes(NameToFmap(fields[name_index]))
 | |
| 
 | |
| def DecodeFmap(data):
 | |
|     """Decode a flashmap into a header and list of areas
 | |
| 
 | |
|     Args:
 | |
|         data: Data block containing the FMAP
 | |
| 
 | |
|     Returns:
 | |
|         Tuple:
 | |
|             header: FmapHeader object
 | |
|             List of FmapArea objects
 | |
|     """
 | |
|     fields = list(struct.unpack(FMAP_HEADER_FORMAT, data[:FMAP_HEADER_LEN]))
 | |
|     ConvertName(FMAP_HEADER_NAMES, fields)
 | |
|     header = FmapHeader(*fields)
 | |
|     areas = []
 | |
|     data = data[FMAP_HEADER_LEN:]
 | |
|     for area in range(header.nareas):
 | |
|         fields = list(struct.unpack(FMAP_AREA_FORMAT, data[:FMAP_AREA_LEN]))
 | |
|         ConvertName(FMAP_AREA_NAMES, fields)
 | |
|         areas.append(FmapArea(*fields))
 | |
|         data = data[FMAP_AREA_LEN:]
 | |
|     return header, areas
 | |
| 
 | |
| def EncodeFmap(image_size, name, areas):
 | |
|     """Create a new FMAP from a list of areas
 | |
| 
 | |
|     Args:
 | |
|         image_size: Size of image, to put in the header
 | |
|         name: Name of image, to put in the header
 | |
|         areas: List of FmapArea objects
 | |
| 
 | |
|     Returns:
 | |
|         String containing the FMAP created
 | |
|     """
 | |
|     def _FormatBlob(fmt, names, obj):
 | |
|         params = [getattr(obj, name) for name in names]
 | |
|         ConvertName(names, params)
 | |
|         return struct.pack(fmt, *params)
 | |
| 
 | |
|     values = FmapHeader(FMAP_SIGNATURE, 1, 0, 0, image_size,
 | |
|                         tools.FromUnicode(name), len(areas))
 | |
|     blob = _FormatBlob(FMAP_HEADER_FORMAT, FMAP_HEADER_NAMES, values)
 | |
|     for area in areas:
 | |
|         blob += _FormatBlob(FMAP_AREA_FORMAT, FMAP_AREA_NAMES, area)
 | |
|     return blob
 |