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') cbfs_util.cbfstool(cbfs_fname, 'create', '-m', arch, '-s', '%#x' % size) if base: base = [(1 << 32) - size + b for b in base] cbfs_util.cbfstool(cbfs_fname, 'add', '-n', 'u-boot', '-t', 'raw', '-c', compress and compress[0] or 'none', '-f', tools.GetInputFilename( compress and 'compress' or 'u-boot.bin'), base=base[0] if base else None) cbfs_util.cbfstool(cbfs_fname, 'add', '-n', 'u-boot-dtb', '-t', 'raw', '-c', compress and compress[1] or 'none', '-f', tools.GetInputFilename( compress and 'compress' or 'u-boot.dtb'), base=base[1] if base else None) return cbfs_fname
def ObtainContents(self): gbb = 'gbb.bin' fname = tools.GetOutputFilename(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)') sizes = [0x100, 0x1000, bmpfv_size, 0x1000] sizes = ['%#x' % size for size in sizes] keydir = tools.GetInputFilename(self.keydir) gbb_set_command = [ 'gbb_utility', '-s', '--hwid=%s' % self.hardware_id, '--rootkey=%s/root_key.vbpubk' % keydir, '--recoverykey=%s/recovery_key.vbpubk' % keydir, '--flags=%d' % self.gbb_flags, '--bmpfv=%s' % tools.GetInputFilename(self.bmpblk), fname ] tools.Run('futility', 'gbb_utility', '-c', ','.join(sizes), fname) tools.Run('futility', *gbb_set_command) self.SetContents(tools.ReadFile(fname)) return True
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.GetInputFilename(fname) data = tools.ReadFile(pathname) return pathname, data
def setUpClass(cls): # Create a temporary directory for test files cls._indir = tempfile.mkdtemp(prefix='cbfs_util.') tools.SetInputDirs([cls._indir]) # Set up some useful data files TestCbfs._make_input_file('u-boot.bin', U_BOOT_DATA) TestCbfs._make_input_file('u-boot.dtb', U_BOOT_DTB_DATA) TestCbfs._make_input_file('compress', COMPRESS_DATA) # Set up a temporary output directory, used by the tools library when # compressing files tools.PrepareOutputDir(None) cls.have_cbfstool = True try: tools.Run('which', 'cbfstool') except: cls.have_cbfstool = False cls.have_lz4 = True try: tools.Run('lz4', '--no-frame-crc', '-c', tools.GetInputFilename('u-boot.bin'), binary=True) except: cls.have_lz4 = False
def ObtainContents(self): fname = tools.GetInputFilename('spl/u-boot-spl') args = [['nm', fname], ['grep', '__bss_size']] out = command.RunPipe(args, capture=True).stdout.splitlines() bss_size = int(out[0].split()[0], 16) self.data = chr(0) * bss_size self.contents_size = bss_size
def ObtainContents(self): fname = tools.GetInputFilename('spl/u-boot-spl') bss_size = elf.GetSymbolAddress(fname, '__bss_size') if not bss_size: self.Raise('Expected __bss_size symbol in spl/u-boot-spl') self.SetContents(tools.GetBytes(0, bss_size)) return True
def ObtainContents(self): fname = tools.GetInputFilename('spl/u-boot-spl') bss_size = elf.GetSymbolAddress(fname, '__bss_size') if not bss_size: self.Raise('Expected __bss_size symbol in spl/u-boot-spl') self.data = chr(0) * bss_size self.contents_size = bss_size
def ProcessFdt(self, fdt): # Figure out where to put the microcode pointer fname = tools.GetInputFilename(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 ObtainContents(self): # Figure out where to put the microcode pointer fname = tools.GetInputFilename(self.elf_fname) sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size') if sym: self.target_pos = sym elif not fdt_util.GetBool(self._node, 'optional-ucode'): self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') return Entry_blob.ObtainContents(self)
def ObtainContents(self): # Figure out where to put the microcode pointer fname = tools.GetInputFilename(self.elf_fname) args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']] out = (command.RunPipe(args, capture=True, raise_on_error=False).stdout.splitlines()) if len(out) == 1: self.target_pos = int(out[0].split()[0], 16) elif not fdt_util.GetBool(self._node, 'optional-ucode'): self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') return Entry_blob.ObtainContents(self)
def LookupAndWriteSymbols(elf_fname, entry, image): """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 positions 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 image: Image which can be used to lookup symbol values """ fname = tools.GetInputFilename(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.iteritems(): if name.startswith('_binman'): msg = ("Image '%s': Symbol '%s'\n in entry '%s'" % (image.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)) # Look up the symbol in our entry tables. value = image.LookupSymbol(name, sym.weak, msg) if value is not None: value += base.address else: value = -1 pack_string = pack_string.lower() value_bytes = struct.pack(pack_string, value) if debug: print('%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): """Get the contects 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.GetInputFilename(self._filename) # Create the IFWI file if needed if self._convert_fit: inname = self._pathname outname = tools.GetOutputFilename('ifwi.bin') tools.RunIfwiTool(inname, tools.CMD_CREATE, outname) self._filename = 'ifwi.bin' self._pathname = outname else: # Provide a different code path here to ensure we have test coverage inname = self._pathname # Delete OBBP if it is there, then add the required new items. tools.RunIfwiTool(inname, tools.CMD_DELETE, subpart='OBBP') for entry in self._ifwi_entries.values(): # First get the input data and put it in a file if not entry.ObtainContents(): return False data = entry.GetData() uniq = self.GetUniqueName() input_fname = tools.GetOutputFilename('input.%s' % uniq) tools.WriteFile(input_fname, data) tools.RunIfwiTool( inname, tools.CMD_REPLACE if entry._ifwi_replace else tools.CMD_ADD, input_fname, entry._ifwi_subpart, entry._ifwi_entry_name) self.ReadBlobContents() return True
def ObtainContents(self): """Get the contects 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.GetInputFilename(self._filename) for entry in self._ifwi_entries.values(): if not entry.ObtainContents(): return False return self._BuildIfwi()
def GetFdtContents(fname='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: fname: Filename to look up (e.g. 'u-boot.dtb'). Returns: tuple: pathname to Fdt Fdt data (as bytes) """ if fname in fdt_files and not use_fake_dtb: pathname = GetFdtPath(fname) data = GetFdt(fname).GetContents() else: pathname = tools.GetInputFilename(fname) data = tools.ReadFile(pathname) return pathname, data
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. import fdt 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', None] output_fdt_info['u-boot-spl-dtb'] = [dtb, 'spl/u-boot-spl.dtb', None] output_fdt_info['u-boot-tpl-dtb'] = [dtb, 'tpl/u-boot-tpl.dtb', None] if not use_fake_dtb: fdt_set = {} for image in images.values(): fdt_set.update(image.GetFdts()) for etype, other in fdt_set.items(): entry, other_fname = other infile = tools.GetInputFilename(other_fname) other_fname_dtb = fdt_util.EnsureCompiled(infile) out_fname = tools.GetOutputFilename('%s.out' % os.path.split(other_fname)[1]) tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) other_dtb = fdt.FdtScan(out_fname) output_fdt_info[etype] = [other_dtb, out_fname, entry]
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 GetFdts(). At present there is only one, that for U-Boot proper. Args: images: List of images being used dtb: Main dtb """ global fdt_set, fdt_subset, fdt_files, main_dtb # Import these here in case libfdt.py is not available, in which case # the above help option still works. import fdt 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 fdt_files.clear() fdt_files['u-boot.dtb'] = dtb fdt_subset = set() if not use_fake_dtb: for image in images.values(): fdt_subset.update(image.GetFdtSet()) fdt_subset.discard('u-boot.dtb') for other_fname in fdt_subset: infile = tools.GetInputFilename(other_fname) other_fname_dtb = fdt_util.EnsureCompiled(infile) out_fname = tools.GetOutputFilename('%s.out' % os.path.split(other_fname)[1]) tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) other_dtb = fdt.FdtScan(out_fname) fdt_files[other_fname] = other_dtb
def ObtainContents(self): self._filename = self.GetDefaultFilename() self._pathname = tools.GetInputFilename(self._filename) self.ReadContents() return True