def ObtainContents(self): gbb = 'gbb.bin' fname = tools.get_output_filename(gbb) if not self.size: self.Raise('GBB must have a fixed size') gbb_size = self.size bmpfv_size = gbb_size - 0x2180 if bmpfv_size < 0: self.Raise('GBB is too small (minimum 0x2180 bytes)') keydir = tools.get_input_filename(self.keydir) stdout = self.futility.gbb_create(fname, [0x100, 0x1000, bmpfv_size, 0x1000]) if stdout is not None: stdout = self.futility.gbb_set( fname, hwid=self.hardware_id, rootkey='%s/root_key.vbpubk' % keydir, recoverykey='%s/recovery_key.vbpubk' % keydir, flags=self.gbb_flags, bmpfv=tools.get_input_filename(self.bmpblk)) if stdout is not None: self.SetContents(tools.read_file(fname)) else: # Bintool is missing; just use the required amount of zero data self.record_missing_bintool(self.futility) self.SetContents(tools.get_bytes(0, gbb_size)) return True
def _get_expected_cbfs(self, size, arch='x86', compress=None, base=None): """Get the file created by cbfstool for a particular scenario Args: size: Size of the CBFS in bytes arch: Architecture of the CBFS, as a string compress: Compression to use, e.g. cbfs_util.COMPRESS_LZMA base: Base address of file, or None to put it anywhere Returns: Resulting CBFS file, or None if cbfstool is not available """ if not self.have_cbfstool or not self.have_lz4: return None cbfs_fname = os.path.join(self._indir, 'test.cbfs') self.cbfstool.create_new(cbfs_fname, size, arch) if base: base = [(1 << 32) - size + b for b in base] self.cbfstool.add_raw( cbfs_fname, 'u-boot', tools.get_input_filename(compress and 'compress' or 'u-boot.bin'), compress[0] if compress else None, base[0] if base else None) self.cbfstool.add_raw( cbfs_fname, 'u-boot-dtb', tools.get_input_filename(compress and 'compress' or 'u-boot.dtb'), compress[1] if compress else None, base[1] if base else None) return cbfs_fname
def ObtainContents(self): """Get the contents for the IFWI Unfortunately we cannot create anything from scratch here, as Intel has tools which create precursor binaries with lots of data and settings, and these are not incorporated into binman. The first step is to get a file in the IFWI format. This is either supplied directly or is extracted from a fitimage using the 'create' subcommand. After that we delete the OBBP sub-partition and add each of the files that we want in the IFWI file, one for each sub-entry of the IWFI node. """ self._pathname = tools.get_input_filename( self._filename, self.section.GetAllowMissing()) # Allow the file to be missing if not self._pathname: self.SetContents(b'') self.missing = True return True for entry in self._ifwi_entries.values(): if not entry.ObtainContents(): return False return self._BuildIfwi()
def GetFdtContents(etype='u-boot-dtb'): """Looks up the FDT pathname and contents This is used to obtain the Fdt pathname and contents when needed by an entry. It supports a 'fake' dtb, allowing tests to substitute test data for the real dtb. Args: etype: Entry type to look up (e.g. 'u-boot.dtb'). Returns: tuple: pathname to Fdt Fdt data (as bytes) """ if etype not in output_fdt_info: return None, None if not use_fake_dtb: pathname = GetFdtPath(etype) data = GetFdtForEtype(etype).GetContents() else: fname = output_fdt_info[etype][1] pathname = tools.get_input_filename(fname) data = tools.read_file(pathname) return pathname, data
def ObtainContents(self): fname = tools.get_input_filename('tpl/u-boot-tpl') bss_size = elf.GetSymbolAddress(fname, '__bss_size') if not bss_size: self.Raise('Expected __bss_size symbol in tpl/u-boot-tpl') self.SetContents(tools.get_bytes(0, bss_size)) return True
def ProcessFdt(self, fdt): # Figure out where to put the microcode pointer fname = tools.get_input_filename(self.elf_fname) sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size') if sym: self.target_offset = sym elif not fdt_util.GetBool(self._node, 'optional-ucode'): self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') return True
def _gen_fdt_nodes(base_node, node, depth, in_images): """Generate FDT nodes This creates one node for each member of self._fdts using the provided template. If a property value contains 'NAME' it is replaced with the filename of the FDT. If a property value contains SEQ it is replaced with the node sequence number, where 1 is the first. Args: node (None): Generator node to process depth: Current node depth (0 is the base 'fit' node) in_images: True if this is inside the 'images' node, so that 'data' properties should be generated """ if self._fdts: # Generate nodes for each FDT for seq, fdt_fname in enumerate(self._fdts): node_name = node.name[1:].replace('SEQ', str(seq + 1)) fname = tools.get_input_filename(fdt_fname + '.dtb') with fsw.add_node(node_name): for pname, prop in node.props.items(): if pname == 'fit,loadables': val = '\0'.join(self._loadables) + '\0' fsw.property('loadables', val.encode('utf-8')) elif pname == 'fit,operation': pass elif pname.startswith('fit,'): self._raise_subnode( node, f"Unknown directive '{pname}'") else: val = prop.bytes.replace( b'NAME', tools.to_bytes(fdt_fname)) val = val.replace(b'SEQ', tools.to_bytes(str(seq + 1))) fsw.property(pname, val) # Add data for 'images' nodes (but not 'config') if depth == 1 and in_images: fsw.property('data', tools.read_file(fname)) for subnode in node.subnodes: with fsw.add_node(subnode.name): _add_node(node, depth + 1, subnode) else: if self._fdts is None: if self._fit_list_prop: self.Raise( 'Generator node requires ' f"'{self._fit_list_prop.value}' entry argument") else: self.Raise( "Generator node requires 'fit,fdt-list' property")
def LookupAndWriteSymbols(elf_fname, entry, section): """Replace all symbols in an entry with their correct values The entry contents is updated so that values for referenced symbols will be visible at run time. This is done by finding out the symbols offsets in the entry (using the ELF file) and replacing them with values from binman's data structures. Args: elf_fname: Filename of ELF image containing the symbol information for entry entry: Entry to process section: Section which can be used to lookup symbol values """ fname = tools.get_input_filename(elf_fname) syms = GetSymbols(fname, ['image', 'binman']) if not syms: return base = syms.get('__image_copy_start') if not base: return for name, sym in syms.items(): if name.startswith('_binman'): msg = ("Section '%s': Symbol '%s'\n in entry '%s'" % (section.GetPath(), name, entry.GetPath())) offset = sym.address - base.address if offset < 0 or offset + sym.size > entry.contents_size: raise ValueError('%s has offset %x (size %x) but the contents ' 'size is %x' % (entry.GetPath(), offset, sym.size, entry.contents_size)) if sym.size == 4: pack_string = '<I' elif sym.size == 8: pack_string = '<Q' else: raise ValueError('%s has size %d: only 4 and 8 are supported' % (msg, sym.size)) if name == '_binman_sym_magic': value = BINMAN_SYM_MAGIC_VALUE else: # Look up the symbol in our entry tables. value = section.GetImage().LookupImageSymbol(name, sym.weak, msg, base.address) if value is None: value = -1 pack_string = pack_string.lower() value_bytes = struct.pack(pack_string, value) tout.debug('%s:\n insert %s, offset %x, value %x, length %d' % (msg, name, offset, value, len(value_bytes))) entry.data = (entry.data[:offset] + value_bytes + entry.data[offset + sym.size:])
def ObtainContents(self): self._filename = self.GetDefaultFilename() self._pathname = tools.get_input_filename( self._filename, self.external and self.section.GetAllowMissing()) # Allow the file to be missing if not self._pathname: self._pathname = self.check_fake_fname(self._filename) self.SetContents(b'') self.missing = True return True self.ReadBlobContents() return True
def _scan_gen_fdt_nodes(subnode, depth, in_images): """Generate FDT nodes This creates one node for each member of self._fdts using the provided template. If a property value contains 'NAME' it is replaced with the filename of the FDT. If a property value contains SEQ it is replaced with the node sequence number, where 1 is the first. Args: subnode (None): Generator node to process depth: Current node depth (0 is the base 'fit' node) in_images: True if this is inside the 'images' node, so that 'data' properties should be generated """ if self._fdts: # Generate nodes for each FDT for seq, fdt_fname in enumerate(self._fdts): node_name = subnode.name[1:].replace('SEQ', str(seq + 1)) fname = tools.get_input_filename(fdt_fname + '.dtb') with fsw.add_node(node_name): for pname, prop in subnode.props.items(): val = prop.bytes.replace(b'NAME', tools.to_bytes(fdt_fname)) val = val.replace(b'SEQ', tools.to_bytes(str(seq + 1))) fsw.property(pname, val) # Add data for 'images' nodes (but not 'config') if depth == 1 and in_images: fsw.property('data', tools.read_file(fname)) else: if self._fdts is None: if self._fit_list_prop: self.Raise( "Generator node requires '%s' entry argument" % self._fit_list_prop.value) else: self.Raise( "Generator node requires 'fit,fdt-list' property")
def Prepare(images, dtb): """Get device tree files ready for use This sets up a set of device tree files that can be retrieved by GetAllFdts(). This includes U-Boot proper and any SPL device trees. Args: images: List of images being used dtb: Main dtb """ global output_fdt_info, main_dtb, fdt_path_prefix # Import these here in case libfdt.py is not available, in which case # the above help option still works. from dtoc import fdt from dtoc import fdt_util # If we are updating the DTBs we need to put these updated versions # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb' # since it is assumed to be the one passed in with options.dt, and # was handled just above. main_dtb = dtb output_fdt_info.clear() fdt_path_prefix = '' output_fdt_info['u-boot-dtb'] = [dtb, 'u-boot.dtb'] if use_fake_dtb: for etype, fname in DTB_TYPE_FNAME.items(): output_fdt_info[etype] = [dtb, fname] else: fdt_set = {} for etype, fname in DTB_TYPE_FNAME.items(): infile = tools.get_input_filename(fname, allow_missing=True) if infile and os.path.exists(infile): fname_dtb = fdt_util.EnsureCompiled(infile) out_fname = tools.get_output_filename('%s.out' % os.path.split(fname)[1]) tools.write_file(out_fname, tools.read_file(fname_dtb)) other_dtb = fdt.FdtScan(out_fname) output_fdt_info[etype] = [other_dtb, out_fname]
def ObtainContents(self): missing = False pathnames = [] for fname in self._filenames: fname, _ = self.check_fake_fname(fname) pathname = tools.get_input_filename( fname, self.external and self.section.GetAllowMissing()) # Allow the file to be missing if not pathname: missing = True pathnames.append(pathname) self._pathnames = pathnames if missing: self.SetContents(b'') self.missing = True return True data = bytearray() for pathname in pathnames: data += self.ReadFileContents(pathname) self.SetContents(data) return True
def _AddNode(base_node, depth, node): """Add a node to the FIT Args: base_node: Base Node of the FIT (with 'description' property) depth: Current node depth (0 is the base node) node: Current node to process There are two cases to deal with: - hash and signature nodes which become part of the FIT - binman entries which are used to define the 'data' for each image """ for pname, prop in node.props.items(): if not pname.startswith('fit,'): if pname == 'default': val = prop.value # Handle the 'default' property if val.startswith('@'): if not self._fdts: continue if not self._fit_default_dt: self.Raise("Generated 'default' node requires default-dt entry argument") if self._fit_default_dt not in self._fdts: self.Raise("default-dt entry argument '%s' not found in fdt list: %s" % (self._fit_default_dt, ', '.join(self._fdts))) seq = self._fdts.index(self._fit_default_dt) val = val[1:].replace('DEFAULT-SEQ', str(seq + 1)) fsw.property_string(pname, val) continue fsw.property(pname, prop.bytes) rel_path = node.path[len(base_node.path):] in_images = rel_path.startswith('/images') has_images = depth == 2 and in_images if has_images: # This node is a FIT subimage node (e.g. "/images/kernel") # containing content nodes. We collect the subimage nodes and # section entries for them here to merge the content subnodes # together and put the merged contents in the subimage node's # 'data' property later. entry = Entry.Create(self.section, node, etype='section') entry.ReadNode() self._entries[rel_path] = entry for subnode in node.subnodes: if has_images and not (subnode.name.startswith('hash') or subnode.name.startswith('signature')): # This subnode is a content node not meant to appear in # the FIT (e.g. "/images/kernel/u-boot"), so don't call # fsw.add_node() or _AddNode() for it. pass elif self.GetImage().generate and subnode.name.startswith('@'): if self._fdts: # Generate notes for each FDT for seq, fdt_fname in enumerate(self._fdts): node_name = subnode.name[1:].replace('SEQ', str(seq + 1)) fname = tools.get_input_filename(fdt_fname + '.dtb') with fsw.add_node(node_name): for pname, prop in subnode.props.items(): val = prop.bytes.replace( b'NAME', tools.to_bytes(fdt_fname)) val = val.replace( b'SEQ', tools.to_bytes(str(seq + 1))) fsw.property(pname, val) # Add data for 'fdt' nodes (but not 'config') if depth == 1 and in_images: fsw.property('data', tools.read_file(fname)) else: if self._fdts is None: if self._fit_list_prop: self.Raise("Generator node requires '%s' entry argument" % self._fit_list_prop.value) else: self.Raise("Generator node requires 'fit,fdt-list' property") else: with fsw.add_node(subnode.name): _AddNode(base_node, depth + 1, subnode)