mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 07:31:15 +00:00
4583c00236
The patman directory has a number of modules which are used by other tools in U-Boot. This makes it hard to package the tools using pypi since the common files must be copied along with the tool that uses them. To address this, move these files into a new u_boot_pylib library. This can be packaged separately and listed as a dependency of each tool. Signed-off-by: Simon Glass <sjg@chromium.org>
121 lines
3.4 KiB
Python
121 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 u_boot_pylib 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',
|
|
)
|
|
|
|
# Flags supported by areas (bits 2:0 are unused so not included here)
|
|
FMAP_AREA_PRESERVE = 1 << 3 # Preserved by any firmware updates
|
|
|
|
# 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:
|
|
name = name.decode('utf-8')
|
|
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.to_bytes(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, 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
|