1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright (c) 2018 Google, Inc 3# Written by Simon Glass <sjg@chromium.org> 4# 5# Entry-type module for U-Boot device tree files 6# 7 8from binman.entry import Entry 9from binman.etype.blob import Entry_blob 10from dtoc import fdt_util 11import struct 12 13# This is imported if needed 14state = None 15 16class Entry_blob_dtb(Entry_blob): 17 """A blob that holds a device tree 18 19 This is a blob containing a device tree. The contents of the blob are 20 obtained from the list of available device-tree files, managed by the 21 'state' module. 22 23 Additional attributes: 24 prepend: Header used (e.g. 'length') 25 """ 26 def __init__(self, section, etype, node): 27 # Put this here to allow entry-docs and help to work without libfdt 28 global state 29 from binman import state 30 31 super().__init__(section, etype, node) 32 self.prepend = None 33 34 def ReadNode(self): 35 super().ReadNode() 36 self.prepend = fdt_util.GetString(self._node, 'prepend') 37 if self.prepend and self.prepend not in ['length']: 38 self.Raise("Invalid prepend in '%s': '%s'" % 39 (self._node.name, self.prepend)) 40 41 def ObtainContents(self, fake_size=0): 42 """Get the device-tree from the list held by the 'state' module""" 43 self._filename = self.GetDefaultFilename() 44 self._pathname, _ = self.FdtContents(self.GetFdtEtype()) 45 return super().ReadBlobContents() 46 47 def ProcessContents(self): 48 """Re-read the DTB contents so that we get any calculated properties""" 49 _, indata = self.FdtContents(self.GetFdtEtype()) 50 51 if self.compress == 'zstd' and self.prepend != 'length': 52 self.Raise('The zstd compression requires a length header') 53 54 data = self.CompressData(indata) 55 return self.ProcessContentsUpdate(data) 56 57 def GetFdtEtype(self): 58 """Get the entry type of this device tree 59 60 This can be 'u-boot-dtb', 'u-boot-spl-dtb', 'u-boot-tpl-dtb' or 61 'u-boot-vpl-dtb' 62 63 Returns: 64 Entry type if any, e.g. 'u-boot-dtb' 65 """ 66 return None 67 68 def GetFdts(self): 69 fname = self.GetDefaultFilename() 70 return {self.GetFdtEtype(): [self, fname]} 71 72 def WriteData(self, data, decomp=True): 73 ok = super().WriteData(data, decomp) 74 75 # Update the state module, since it has the authoritative record of the 76 # device trees used. If we don't do this, then state.GetFdtContents() 77 # will still return the old contents 78 state.UpdateFdtContents(self.GetFdtEtype(), data) 79 return ok 80 81 def CompressData(self, indata): 82 data = super().CompressData(indata) 83 if self.prepend == 'length': 84 hdr = struct.pack('<I', len(data)) 85 data = hdr + data 86 return data 87 88 def DecompressData(self, indata): 89 if self.prepend == 'length': 90 data_len = struct.unpack('<I', indata[:4])[0] 91 indata = indata[4:4 + data_len] 92 data = super().DecompressData(indata) 93 return data 94