u-boot/tools/binman/fmap_util.py
Simon Glass bf776679a7 patman: Move to absolute imports
At present patman sets the python path on startup so that it can access
the libraries it needs. If we convert to use absolute imports this is not
necessary.

Move patman to use absolute imports. This requires changes in tools which
use the patman libraries (which is most of them).

Signed-off-by: Simon Glass <sjg@chromium.org>
2020-04-26 14:25:21 -06:00

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
from patman 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