binman: Add an entry filled with a repeating byte

It is sometimes useful to have an area of the image which is all zeroes,
or all 0xff. This can often be achieved by padding the size of an an
existing entry and setting the pad byte for an entry or image.

But it is useful to have an explicit means of adding blocks of repeating
data to the image. Add a 'fill' entry type to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
lime2-spi
Simon Glass 6 years ago
parent ec127af042
commit 3af8e49cef
  1. 16
      tools/binman/README.entries
  2. 32
      tools/binman/etype/fill.py
  3. 13
      tools/binman/ftest.py
  4. 15
      tools/binman/test/69_fill.dts
  5. 14
      tools/binman/test/70_fill_no_size.dts
  6. 23
      tools/dtoc/fdt_util.py
  7. 15
      tools/dtoc/test_fdt.py

@ -55,6 +55,22 @@ updating the EC on startup via software sync.
Entry: fill: An entry which is filled to a particular byte value
----------------------------------------------------------------
Properties / Entry arguments:
- fill-byte: Byte to use to fill the entry
Note that the size property must be set since otherwise this entry does not
know how large it should be.
You can often achieve the same effect using the pad-byte property of the
overall image, in that the space between entries will then be padded with
that byte. But this entry is sometimes useful for explicitly setting the
byte value of a region.
Entry: fmap: An entry which contains an Fmap section
----------------------------------------------------

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2018 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
from entry import Entry
import fdt_util
class Entry_fill(Entry):
"""An entry which is filled to a particular byte value
Properties / Entry arguments:
- fill-byte: Byte to use to fill the entry
Note that the size property must be set since otherwise this entry does not
know how large it should be.
You can often achieve the same effect using the pad-byte property of the
overall image, in that the space between entries will then be padded with
that byte. But this entry is sometimes useful for explicitly setting the
byte value of a region.
"""
def __init__(self, section, etype, node):
Entry.__init__(self, section, etype, node)
if not self.size:
self.Raise("'fill' entry must have a size property")
self.fill_value = fdt_util.GetByte(self._node, 'fill-byte', 0)
def ObtainContents(self):
self.SetContents(chr(self.fill_value) * self.size)
return True

@ -1235,6 +1235,19 @@ class TestFunctional(unittest.TestCase):
data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
entry_args=entry_args)
def testFill(self):
"""Test for an fill entry type"""
data = self._DoReadFile('69_fill.dts')
expected = 8 * chr(0xff) + 8 * chr(0)
self.assertEqual(expected, data)
def testFillNoSize(self):
"""Test for an fill entry type with no size"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('70_fill_no_size.dts')
self.assertIn("'fill' entry must have a size property",
str(e.exception))
if __name__ == "__main__":
unittest.main()

@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
size = <16>;
fill {
size = <8>;
fill-byte = [ff];
};
};
};

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
size = <16>;
fill {
fill-byte = [ff];
};
};
};

@ -148,6 +148,29 @@ def GetBool(node, propname, default=False):
return True
return default
def GetByte(node, propname, default=None):
"""Get an byte from a property
Args:
node: Node object to read from
propname: property name to read
default: Default value to use if the node/property do not exist
Returns:
Byte value read, or default if none
"""
prop = node.props.get(propname)
if not prop:
return default
value = prop.value
if isinstance(value, list):
raise ValueError("Node '%s' property '%s' has list value: expecting "
"a single byte" % (node.name, propname))
if len(value) != 1:
raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
(node.name, propname, len(value), 1))
return ord(value[0])
def GetDatatype(node, propname, datatype):
"""Get a value of a given type from a property

@ -380,6 +380,20 @@ class TestFdtUtil(unittest.TestCase):
self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
def testGetByte(self):
self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
with self.assertRaises(ValueError) as e:
fdt_util.GetByte(self.node, 'longbytearray')
self.assertIn("property 'longbytearray' has list value: expecting a "
'single byte', str(e.exception))
with self.assertRaises(ValueError) as e:
fdt_util.GetByte(self.node, 'intval')
self.assertIn("property 'intval' has length 4, expecting 1",
str(e.exception))
def testGetDataType(self):
self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
@ -387,7 +401,6 @@ class TestFdtUtil(unittest.TestCase):
with self.assertRaises(ValueError) as e:
self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
bool))
def testFdtCellsToCpu(self):
val = self.node.props['intarray'].value
self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))

Loading…
Cancel
Save