blob: d543de9f759beab5278836f32485457c00340cdd [file] [log] [blame]
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2018 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# Entry-type module for U-Boot device tree files
#
from binman.entry import Entry
from binman.etype.blob import Entry_blob
from dtoc import fdt_util
import struct
# This is imported if needed
state = None
class Entry_blob_dtb(Entry_blob):
"""A blob that holds a device tree
This is a blob containing a device tree. The contents of the blob are
obtained from the list of available device-tree files, managed by the
'state' module.
Additional attributes:
prepend: Header used (e.g. 'length')
"""
def __init__(self, section, etype, node):
# Put this here to allow entry-docs and help to work without libfdt
global state
from binman import state
super().__init__(section, etype, node)
self.prepend = None
def ReadNode(self):
super().ReadNode()
self.prepend = fdt_util.GetString(self._node, 'prepend')
if self.prepend and self.prepend not in ['length']:
self.Raise("Invalid prepend in '%s': '%s'" %
(self._node.name, self.prepend))
def ObtainContents(self, fake_size=0):
"""Get the device-tree from the list held by the 'state' module"""
self._filename = self.GetDefaultFilename()
self._pathname, _ = state.GetFdtContents(self.GetFdtEtype())
return super().ReadBlobContents()
def ProcessContents(self):
"""Re-read the DTB contents so that we get any calculated properties"""
_, indata = state.GetFdtContents(self.GetFdtEtype())
if self.compress == 'zstd' and self.prepend != 'length':
self.Raise('The zstd compression requires a length header')
data = self.CompressData(indata)
return self.ProcessContentsUpdate(data)
def GetFdtEtype(self):
"""Get the entry type of this device tree
This can be 'u-boot-dtb', 'u-boot-spl-dtb' or 'u-boot-tpl-dtb'
Returns:
Entry type if any, e.g. 'u-boot-dtb'
"""
return None
def GetFdts(self):
fname = self.GetDefaultFilename()
return {self.GetFdtEtype(): [self, fname]}
def WriteData(self, data, decomp=True):
ok = super().WriteData(data, decomp)
# Update the state module, since it has the authoritative record of the
# device trees used. If we don't do this, then state.GetFdtContents()
# will still return the old contents
state.UpdateFdtContents(self.GetFdtEtype(), data)
return ok
def CompressData(self, indata):
data = super().CompressData(indata)
if self.prepend == 'length':
hdr = struct.pack('<I', len(data))
data = hdr + data
return data
def DecompressData(self, indata):
if self.prepend == 'length':
data_len = struct.unpack('<I', indata[:4])[0]
indata = indata[4:4 + data_len]
data = super().DecompressData(indata)
return data