mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-27 16:01:27 +00:00
binman: Move stage header into a CBFS attribute
cbfsutil completely changed the way that stages are formatted in CBFS. Adjust the binman implementation to do the same. This mirrors commit 81dc20e744 in coreboot. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
fe35c2f011
commit
ce0e9e3990
2 changed files with 42 additions and 29 deletions
|
@ -44,10 +44,10 @@ FILE_HEADER_LEN = 0x18
|
||||||
FILE_MAGIC = b'LARCHIVE'
|
FILE_MAGIC = b'LARCHIVE'
|
||||||
ATTRIBUTE_ALIGN = 4 # All attribute sizes must be divisible by this
|
ATTRIBUTE_ALIGN = 4 # All attribute sizes must be divisible by this
|
||||||
|
|
||||||
# A stage header containing information about 'stage' files
|
# A stage-header attribute containing information about 'stage' files
|
||||||
# Yes this is correct: this header is in litte-endian format
|
# Yes this is correct: this header is in litte-endian format
|
||||||
STAGE_FORMAT = '<IQQII'
|
ATTR_STAGE_FORMAT = '>IIQII'
|
||||||
STAGE_LEN = 0x1c
|
ATTR_STAGE_LEN = 0x18
|
||||||
|
|
||||||
# An attribute describring the compression used in a file
|
# An attribute describring the compression used in a file
|
||||||
ATTR_COMPRESSION_FORMAT = '>IIII'
|
ATTR_COMPRESSION_FORMAT = '>IIII'
|
||||||
|
@ -59,6 +59,7 @@ FILE_ATTR_TAG_HASH = 0x68736148
|
||||||
FILE_ATTR_TAG_POSITION = 0x42435350 # PSCB
|
FILE_ATTR_TAG_POSITION = 0x42435350 # PSCB
|
||||||
FILE_ATTR_TAG_ALIGNMENT = 0x42434c41 # ALCB
|
FILE_ATTR_TAG_ALIGNMENT = 0x42434c41 # ALCB
|
||||||
FILE_ATTR_TAG_PADDING = 0x47444150 # PDNG
|
FILE_ATTR_TAG_PADDING = 0x47444150 # PDNG
|
||||||
|
FILE_ATTR_TAG_STAGEHEADER = 0x53746748 # StgH
|
||||||
|
|
||||||
# This is 'the size of bootblock reserved in firmware image (cbfs.txt)'
|
# This is 'the size of bootblock reserved in firmware image (cbfs.txt)'
|
||||||
# Not much more info is available, but we set it to 4, due to this comment in
|
# Not much more info is available, but we set it to 4, due to this comment in
|
||||||
|
@ -97,6 +98,7 @@ ARCH_NAMES = {
|
||||||
# File types. Only supported ones are included here
|
# File types. Only supported ones are included here
|
||||||
TYPE_CBFSHEADER = 0x02 # Master header, HEADER_FORMAT
|
TYPE_CBFSHEADER = 0x02 # Master header, HEADER_FORMAT
|
||||||
TYPE_LEGACY_STAGE = 0x10 # Stage, holding an executable
|
TYPE_LEGACY_STAGE = 0x10 # Stage, holding an executable
|
||||||
|
TYPE_STAGE = 0x11 # New-type stage with ATTR_STAGE_FORMAT
|
||||||
TYPE_RAW = 0x50 # Raw file, possibly compressed
|
TYPE_RAW = 0x50 # Raw file, possibly compressed
|
||||||
TYPE_EMPTY = 0xffffffff # Empty data
|
TYPE_EMPTY = 0xffffffff # Empty data
|
||||||
|
|
||||||
|
@ -265,7 +267,7 @@ class CbfsFile(object):
|
||||||
Returns:
|
Returns:
|
||||||
CbfsFile object containing the file information
|
CbfsFile object containing the file information
|
||||||
"""
|
"""
|
||||||
cfile = CbfsFile(name, TYPE_LEGACY_STAGE, data, cbfs_offset)
|
cfile = CbfsFile(name, TYPE_STAGE, data, cbfs_offset)
|
||||||
cfile.base_address = base_address
|
cfile.base_address = base_address
|
||||||
return cfile
|
return cfile
|
||||||
|
|
||||||
|
@ -326,8 +328,8 @@ class CbfsFile(object):
|
||||||
"""
|
"""
|
||||||
name = _pack_string(self.name)
|
name = _pack_string(self.name)
|
||||||
hdr_len = len(name) + FILE_HEADER_LEN
|
hdr_len = len(name) + FILE_HEADER_LEN
|
||||||
if self.ftype == TYPE_LEGACY_STAGE:
|
if self.ftype == TYPE_STAGE:
|
||||||
pass
|
hdr_len += ATTR_STAGE_LEN
|
||||||
elif self.ftype == TYPE_RAW:
|
elif self.ftype == TYPE_RAW:
|
||||||
if self.compress:
|
if self.compress:
|
||||||
hdr_len += ATTR_COMPRESSION_LEN
|
hdr_len += ATTR_COMPRESSION_LEN
|
||||||
|
@ -354,11 +356,11 @@ class CbfsFile(object):
|
||||||
attr = b''
|
attr = b''
|
||||||
pad = b''
|
pad = b''
|
||||||
data = self.data
|
data = self.data
|
||||||
if self.ftype == TYPE_LEGACY_STAGE:
|
if self.ftype == TYPE_STAGE:
|
||||||
elf_data = elf.DecodeElf(data, self.base_address)
|
elf_data = elf.DecodeElf(data, self.base_address)
|
||||||
content = struct.pack(STAGE_FORMAT, self.compress,
|
attr = struct.pack(ATTR_STAGE_FORMAT, FILE_ATTR_TAG_STAGEHEADER,
|
||||||
elf_data.entry, elf_data.load,
|
ATTR_STAGE_LEN, elf_data.load,
|
||||||
len(elf_data.data), elf_data.memsize)
|
elf_data.entry - elf_data.load, elf_data.memsize)
|
||||||
data = elf_data.data
|
data = elf_data.data
|
||||||
elif self.ftype == TYPE_RAW:
|
elif self.ftype == TYPE_RAW:
|
||||||
orig_data = data
|
orig_data = data
|
||||||
|
@ -639,7 +641,7 @@ class CbfsReader(object):
|
||||||
files: Ordered list of CbfsFile objects
|
files: Ordered list of CbfsFile objects
|
||||||
align: Alignment to use for files, typically ENTRT_ALIGN
|
align: Alignment to use for files, typically ENTRT_ALIGN
|
||||||
stage_base_address: Base address to use when mapping ELF files into the
|
stage_base_address: Base address to use when mapping ELF files into the
|
||||||
CBFS for TYPE_LEGACY_STAGE files. If this is larger than the code address
|
CBFS for TYPE_STAGE files. If this is larger than the code address
|
||||||
of the ELF file, then data at the start of the ELF file will not
|
of the ELF file, then data at the start of the ELF file will not
|
||||||
appear in the CBFS. Currently there are no tests for behaviour as
|
appear in the CBFS. Currently there are no tests for behaviour as
|
||||||
documentation is sparse
|
documentation is sparse
|
||||||
|
@ -740,26 +742,28 @@ class CbfsReader(object):
|
||||||
print('name', name)
|
print('name', name)
|
||||||
|
|
||||||
# If there are attribute headers present, read those
|
# If there are attribute headers present, read those
|
||||||
compress = self._read_attr(fd, file_pos, attr, offset)
|
attrs = self._read_attr(fd, file_pos, attr, offset)
|
||||||
if compress is None:
|
if attrs is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Create the correct CbfsFile object depending on the type
|
# Create the correct CbfsFile object depending on the type
|
||||||
cfile = None
|
cfile = None
|
||||||
cbfs_offset = file_pos + offset
|
cbfs_offset = file_pos + offset
|
||||||
fd.seek(cbfs_offset, io.SEEK_SET)
|
fd.seek(cbfs_offset, io.SEEK_SET)
|
||||||
|
if DEBUG:
|
||||||
|
print(f'ftype {ftype:x}')
|
||||||
if ftype == TYPE_CBFSHEADER:
|
if ftype == TYPE_CBFSHEADER:
|
||||||
self._read_header(fd)
|
self._read_header(fd)
|
||||||
elif ftype == TYPE_LEGACY_STAGE:
|
elif ftype == TYPE_STAGE:
|
||||||
data = fd.read(STAGE_LEN)
|
|
||||||
cfile = CbfsFile.stage(self.stage_base_address, name, b'',
|
cfile = CbfsFile.stage(self.stage_base_address, name, b'',
|
||||||
cbfs_offset)
|
cbfs_offset)
|
||||||
(cfile.compress, cfile.entry, cfile.load, cfile.data_len,
|
cfile.load, entry_offset, cfile.memlen = attrs
|
||||||
cfile.memlen) = struct.unpack(STAGE_FORMAT, data)
|
cfile.entry = cfile.load + entry_offset
|
||||||
cfile.data = fd.read(cfile.data_len)
|
cfile.data = fd.read(cfile.memlen)
|
||||||
|
cfile.data_len = cfile.memlen
|
||||||
elif ftype == TYPE_RAW:
|
elif ftype == TYPE_RAW:
|
||||||
data = fd.read(size)
|
data = fd.read(size)
|
||||||
cfile = CbfsFile.raw(name, data, cbfs_offset, compress)
|
cfile = CbfsFile.raw(name, data, cbfs_offset, attrs)
|
||||||
cfile.decompress()
|
cfile.decompress()
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print('data', data)
|
print('data', data)
|
||||||
|
@ -783,8 +787,8 @@ class CbfsReader(object):
|
||||||
"""Read attributes from the file
|
"""Read attributes from the file
|
||||||
|
|
||||||
CBFS files can have attributes which are things that cannot fit into the
|
CBFS files can have attributes which are things that cannot fit into the
|
||||||
header. The only attributes currently supported are compression and the
|
header. The only attributes currently supported are compression, stage
|
||||||
unused tag.
|
header and the unused tag
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fd: File to read from
|
fd: File to read from
|
||||||
|
@ -794,11 +798,16 @@ class CbfsReader(object):
|
||||||
attributes)
|
attributes)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
Either:
|
||||||
Compression to use for the file (COMPRESS_...)
|
Compression to use for the file (COMPRESS_...)
|
||||||
|
tuple containing stage info:
|
||||||
|
load address
|
||||||
|
entry offset
|
||||||
|
memory size
|
||||||
"""
|
"""
|
||||||
compress = COMPRESS_NONE
|
attrs = None
|
||||||
if not attr:
|
if not attr:
|
||||||
return compress
|
return COMPRESS_NONE
|
||||||
attr_size = offset - attr
|
attr_size = offset - attr
|
||||||
fd.seek(file_pos + attr, io.SEEK_SET)
|
fd.seek(file_pos + attr, io.SEEK_SET)
|
||||||
while attr_size:
|
while attr_size:
|
||||||
|
@ -813,10 +822,15 @@ class CbfsReader(object):
|
||||||
# We don't currently use this information
|
# We don't currently use this information
|
||||||
atag, alen, compress, _decomp_size = struct.unpack(
|
atag, alen, compress, _decomp_size = struct.unpack(
|
||||||
ATTR_COMPRESSION_FORMAT, data)
|
ATTR_COMPRESSION_FORMAT, data)
|
||||||
|
attrs = compress
|
||||||
|
elif atag == FILE_ATTR_TAG_STAGEHEADER:
|
||||||
|
atag, alen, load, entry_offset, memsize = struct.unpack(
|
||||||
|
ATTR_STAGE_FORMAT, data)
|
||||||
|
attrs = (load, entry_offset, memsize)
|
||||||
else:
|
else:
|
||||||
print('Unknown attribute tag %x' % atag)
|
print('Unknown attribute tag %x' % atag)
|
||||||
attr_size -= len(data)
|
attr_size -= len(data)
|
||||||
return compress
|
return attrs
|
||||||
|
|
||||||
def _read_header(self, fd):
|
def _read_header(self, fd):
|
||||||
"""Read the master header
|
"""Read the master header
|
||||||
|
|
|
@ -391,7 +391,7 @@ class TestCbfs(unittest.TestCase):
|
||||||
cbfs_util.DEBUG = True
|
cbfs_util.DEBUG = True
|
||||||
with test_util.capture_sys_output() as (stdout, _stderr):
|
with test_util.capture_sys_output() as (stdout, _stderr):
|
||||||
cbfs_util.CbfsReader(data)
|
cbfs_util.CbfsReader(data)
|
||||||
self.assertEqual('name u-boot\ndata %s\n' % U_BOOT_DATA,
|
self.assertEqual('name u-boot\nftype 50\ndata %s\n' % U_BOOT_DATA,
|
||||||
stdout.getvalue())
|
stdout.getvalue())
|
||||||
finally:
|
finally:
|
||||||
cbfs_util.DEBUG = False
|
cbfs_util.DEBUG = False
|
||||||
|
@ -475,7 +475,7 @@ class TestCbfs(unittest.TestCase):
|
||||||
self._compare_expected_cbfs(data, cbfs_fname)
|
self._compare_expected_cbfs(data, cbfs_fname)
|
||||||
|
|
||||||
def test_cbfs_stage(self):
|
def test_cbfs_stage(self):
|
||||||
"""Tests handling of a Coreboot Filesystem (CBFS)"""
|
"""Tests handling of a CBFS stage"""
|
||||||
if not elf.ELF_TOOLS:
|
if not elf.ELF_TOOLS:
|
||||||
self.skipTest('Python elftools not available')
|
self.skipTest('Python elftools not available')
|
||||||
elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
|
elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
|
||||||
|
@ -490,8 +490,7 @@ class TestCbfs(unittest.TestCase):
|
||||||
load = 0xfef20000
|
load = 0xfef20000
|
||||||
entry = load + 2
|
entry = load + 2
|
||||||
|
|
||||||
cfile = self._check_uboot(cbfs, cbfs_util.TYPE_LEGACY_STAGE,
|
cfile = self._check_uboot(cbfs, cbfs_util.TYPE_STAGE, offset=0x38,
|
||||||
offset=0x20,
|
|
||||||
data=U_BOOT_DATA + U_BOOT_DTB_DATA)
|
data=U_BOOT_DATA + U_BOOT_DTB_DATA)
|
||||||
|
|
||||||
self.assertEqual(entry, cfile.entry)
|
self.assertEqual(entry, cfile.entry)
|
||||||
|
|
Loading…
Add table
Reference in a new issue