Beispiel #1
0
    def test_cbfs_stage(self):
        """Tests handling of a Coreboot Filesystem (CBFS)"""
        if not elf.ELF_TOOLS:
            self.skipTest('Python elftools not available')
        elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
        elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)

        size = 0xb0
        cbw = CbfsWriter(size)
        cbw.add_file_stage('u-boot', tools.ReadFile(elf_fname))

        data = cbw.get_data()
        cbfs = self._check_hdr(data, size)
        load = 0xfef20000
        entry = load + 2

        cfile = self._check_uboot(cbfs,
                                  cbfs_util.TYPE_STAGE,
                                  offset=0x28,
                                  data=U_BOOT_DATA + U_BOOT_DTB_DATA)

        self.assertEqual(entry, cfile.entry)
        self.assertEqual(load, cfile.load)
        self.assertEqual(
            len(U_BOOT_DATA) + len(U_BOOT_DTB_DATA), cfile.data_len)

        # Compare against what cbfstool creates
        if self.have_cbfstool:
            cbfs_fname = os.path.join(self._indir, 'test.cbfs')
            cbfs_util.cbfstool(cbfs_fname, 'create', '-m', 'x86', '-s',
                               '%#x' % size)
            cbfs_util.cbfstool(cbfs_fname, 'add-stage', '-n', 'u-boot', '-f',
                               elf_fname)
            self._compare_expected_cbfs(data, cbfs_fname)
Beispiel #2
0
    def ObtainContents(self):
        # Join up the data files to be signed
        input_data = ''
        for entry_phandle in self.content:
            data = self.section.GetContentsByPhandle(entry_phandle, self)
            if data is None:
                # Data not available yet
                return False
            input_data += data

        uniq = self.GetUniqueName()
        output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
        input_fname = tools.GetOutputFilename('input.%s' % uniq)
        tools.WriteFile(input_fname, input_data)
        prefix = self.keydir + '/'
        args = [
            'vbutil_firmware',
            '--vblock', output_fname,
            '--keyblock', prefix + self.keyblock,
            '--signprivate', prefix + self.signprivate,
            '--version', '%d' % self.version,
            '--fv', input_fname,
            '--kernelkey', prefix + self.kernelkey,
            '--flags', '%d' % self.preamble_flags,
        ]
        #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
        stdout = tools.Run('futility', *args)
        self.SetContents(tools.ReadFile(output_fname))
        return True
  def ProduceFinalImage(self, tools, out, tmpdir, image_fname):
    """Produce the final image for an Intel ME system

    Some Intel systems require that an image contains the Management Engine
    firmware, and also a firmware descriptor.

    This function takes the existing image, removes the front part of it,
    and replaces it with these required pieces using ifdtool.

    Args:
      tools: Tools object to use to run tools.
      out: Output object to send output to
      tmpdir: Temporary directory to use to create required files.
      image_fname: Output image filename
    """
    out.Progress('Setting up Intel ME')
    data = tools.ReadFile(image_fname)

    # We can assume that the ifd section is at the start of the image.
    if self.offset != 0:
      raise ConfigError('IFD section must be at offset 0 in the image')
    data = data[self.size:]
    input_fname = os.path.join(tmpdir, 'ifd-input.bin')
    tools.WriteFile(input_fname, data)
    ifd_output = os.path.join(tmpdir, 'image.ifd')

    # This works by modifying a skeleton file.
    shutil.copyfile(tools.Filename(self.pack.props['skeleton']), ifd_output)
    args = ['-i', 'BIOS:%s' % input_fname, ifd_output]
    tools.Run('ifdtool', args)

    # ifdtool puts the output in a file with '.new' tacked on the end.
    shutil.move(ifd_output + '.new', image_fname)
    tools.OutputSize('IFD image', image_fname)
Beispiel #4
0
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
Beispiel #5
0
    def FromFile(cls, fname):
        """Convert an image file into an Image for use in binman

        Args:
            fname: Filename of image file to read

        Returns:
            Image object on success

        Raises:
            ValueError if something goes wrong
        """
        data = tools.ReadFile(fname)
        size = len(data)

        # First look for an image header
        pos = image_header.LocateHeaderOffset(data)
        if pos is None:
            # Look for the FDT map
            pos = fdtmap.LocateFdtmap(data)
        if pos is None:
            raise ValueError('Cannot find FDT map in image')

        # We don't know the FDT size, so check its header first
        probe_dtb = fdt.Fdt.FromData(data[pos + fdtmap.FDTMAP_HDR_LEN:pos +
                                          256])
        dtb_size = probe_dtb.GetFdtObj().totalsize()
        fdtmap_data = data[pos:pos + dtb_size + fdtmap.FDTMAP_HDR_LEN]
        dtb = fdt.Fdt.FromData(fdtmap_data[fdtmap.FDTMAP_HDR_LEN:])
        dtb.Scan()

        # Return an Image with the associated nodes
        image = Image('image', dtb.GetRoot())
        image._data = data
        return image
Beispiel #6
0
    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
Beispiel #7
0
 def ReadBlobContents(self):
     if self._strip:
         uniq = self.GetUniqueName()
         out_fname = tools.GetOutputFilename('%s.stripped' % uniq)
         tools.WriteFile(out_fname, tools.ReadFile(self._pathname))
         tools.Run('strip', out_fname)
         self._pathname = out_fname
     Entry_blob.ReadBlobContents(self)
     return True
Beispiel #8
0
    def ReadBlobContents(self):
        """Read blob contents into memory

        This function compresses the data before storing if needed.

        We assume the data is small enough to fit into memory. If this
        is used for large filesystem image that might not be true.
        In that case, Image.BuildImage() could be adjusted to use a
        new Entry method which can read in chunks. Then we could copy
        the data in chunks and avoid reading it all at once. For now
        this seems like an unnecessary complication.
        """
        indata = tools.ReadFile(self._pathname)
        data = self.CompressData(indata)
        self.SetContents(data)
        return True
Beispiel #9
0
    def FromFile(cls, fname):
        """Convert an image file into an Image for use in binman

        Args:
            fname: Filename of image file to read

        Returns:
            Image object on success

        Raises:
            ValueError if something goes wrong
        """
        data = tools.ReadFile(fname)
        size = len(data)

        # First look for an image header
        pos = image_header.LocateHeaderOffset(data)
        if pos is None:
            # Look for the FDT map
            pos = fdtmap.LocateFdtmap(data)
        if pos is None:
            raise ValueError('Cannot find FDT map in image')

        # We don't know the FDT size, so check its header first
        probe_dtb = fdt.Fdt.FromData(
            data[pos + fdtmap.FDTMAP_HDR_LEN:pos + 256])
        dtb_size = probe_dtb.GetFdtObj().totalsize()
        fdtmap_data = data[pos:pos + dtb_size + fdtmap.FDTMAP_HDR_LEN]
        fdt_data = fdtmap_data[fdtmap.FDTMAP_HDR_LEN:]
        out_fname = tools.GetOutputFilename('fdtmap.in.dtb')
        tools.WriteFile(out_fname, fdt_data)
        dtb = fdt.Fdt(out_fname)
        dtb.Scan()

        # Return an Image with the associated nodes
        root = dtb.GetRoot()
        image = Image('image', root, copy_to_orig=False)

        image.image_node = fdt_util.GetString(root, 'image-node', 'image')
        image.fdtmap_dtb = dtb
        image.fdtmap_data = fdtmap_data
        image._data = data
        image._filename = fname
        image.image_name, _ = os.path.splitext(fname)
        return image
Beispiel #10
0
    def _compare_expected_cbfs(self, data, cbfstool_fname):
        """Compare against what cbfstool creates

        This compares what binman creates with what cbfstool creates for what
        is proportedly the same thing.

        Args:
            data: CBFS created by binman
            cbfstool_fname: CBFS created by cbfstool
        """
        if not self.have_cbfstool or not self.have_lz4:
            return
        expect = tools.ReadFile(cbfstool_fname)
        if expect != data:
            tools.WriteFile('/tmp/expect', expect)
            tools.WriteFile('/tmp/actual', data)
            print('diff -y <(xxd -g1 /tmp/expect) <(xxd -g1 /tmp/actual) | colordiff')
            self.fail('cbfstool produced a different result')
Beispiel #11
0
    def testDecodeElf(self):
        """Test for the MakeElf function"""
        if not elf.ELF_TOOLS:
            self.skipTest('Python elftools not available')
        outdir = tempfile.mkdtemp(prefix='elf.')
        expected_text = b'1234'
        expected_data = b'wxyz'
        elf_fname = os.path.join(outdir, 'elf')
        elf.MakeElf(elf_fname, expected_text, expected_data)
        data = tools.ReadFile(elf_fname)

        load = 0xfef20000
        entry = load + 2
        expected = expected_text + expected_data
        self.assertEqual(elf.ElfInfo(expected, load, entry, len(expected)),
                         elf.DecodeElf(data, 0))
        self.assertEqual(
            elf.ElfInfo(b'\0\0' + expected[2:], load, entry, len(expected)),
            elf.DecodeElf(data, load + 2))
Beispiel #12
0
    def ReadBlobContents(self):
        # We assume the data is small enough to fit into memory. If this
        # is used for large filesystem image that might not be true.
        # In that case, Image.BuildImage() could be adjusted to use a
        # new Entry method which can read in chunks. Then we could copy
        # the data in chunks and avoid reading it all at once. For now
        # this seems like an unnecessary complication.
        data = tools.ReadFile(self._pathname)
        if self._compress == 'lz4':
            self._uncompressed_size = len(data)
            '''
            import lz4  # Import this only if needed (python-lz4 dependency)

            try:
                data = lz4.frame.compress(data)
            except AttributeError:
                data = lz4.compress(data)
            '''
            data = tools.Run('lz4', '-c', self._pathname, binary=True)
        self.SetContents(data)
        return True
Beispiel #13
0
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]
Beispiel #14
0
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
Beispiel #15
0
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
Beispiel #16
0
def Binman(options, args):
    """The main control code for binman

    This assumes that help and test options have already been dealt with. It
    deals with the core task of building images.

    Args:
        options: Command line options object
        args: Command line arguments (list of strings)
    """
    global images

    if options.full_help:
        pager = os.getenv('PAGER')
        if not pager:
            pager = 'more'
        fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
                             'README')
        command.Run(pager, fname)
        return 0

    # Try to figure out which device tree contains our image description
    if options.dt:
        dtb_fname = options.dt
    else:
        board = options.board
        if not board:
            raise ValueError(
                'Must provide a board to process (use -b <board>)')
        board_pathname = os.path.join(options.build_dir, board)
        dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
        if not options.indir:
            options.indir = ['.']
        options.indir.append(board_pathname)

    try:
        # Import these here in case libfdt.py is not available, in which case
        # the above help option still works.
        import fdt
        import fdt_util

        tout.Init(options.verbosity)
        elf.debug = options.debug
        state.use_fake_dtb = options.fake_dtb
        try:
            tools.SetInputDirs(options.indir)
            tools.PrepareOutputDir(options.outdir, options.preserve)
            state.SetEntryArgs(options.entry_arg)

            # Get the device tree ready by compiling it and copying the compiled
            # output into a file in our output directly. Then scan it for use
            # in binman.
            dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
            fname = tools.GetOutputFilename('u-boot.dtb.out')
            tools.WriteFile(fname, tools.ReadFile(dtb_fname))
            dtb = fdt.FdtScan(fname)

            node = _FindBinmanNode(dtb)
            if not node:
                raise ValueError("Device tree '%s' does not have a 'binman' "
                                 "node" % dtb_fname)

            images = _ReadImageDesc(node)

            if options.image:
                skip = []
                new_images = OrderedDict()
                for name, image in images.items():
                    if name in options.image:
                        new_images[name] = image
                    else:
                        skip.append(name)
                images = new_images
                if skip and options.verbosity >= 2:
                    print('Skipping images: %s' % ', '.join(skip))

            state.Prepare(images, dtb)

            # Prepare the device tree by making sure that any missing
            # properties are added (e.g. 'pos' and 'size'). The values of these
            # may not be correct yet, but we add placeholders so that the
            # size of the device tree is correct. Later, in
            # SetCalculatedProperties() we will insert the correct values
            # without changing the device-tree size, thus ensuring that our
            # entry offsets remain the same.
            for image in images.values():
                image.ExpandEntries()
                if options.update_fdt:
                    image.AddMissingProperties()
                image.ProcessFdt(dtb)

            for dtb_item in state.GetFdts():
                dtb_item.Sync(auto_resize=True)
                dtb_item.Pack()
                dtb_item.Flush()

            for image in images.values():
                # Perform all steps for this image, including checking and
                # writing it. This means that errors found with a later
                # image will be reported after earlier images are already
                # completed and written, but that does not seem important.
                image.GetEntryContents()
                image.GetEntryOffsets()
                try:
                    image.PackEntries()
                    image.CheckSize()
                    image.CheckEntries()
                except Exception as e:
                    if options.map:
                        fname = image.WriteMap()
                        print("Wrote map file '%s' to show errors" % fname)
                    raise
                image.SetImagePos()
                if options.update_fdt:
                    image.SetCalculatedProperties()
                    for dtb_item in state.GetFdts():
                        dtb_item.Sync()
                image.ProcessEntryContents()
                image.WriteSymbols()
                image.BuildImage()
                if options.map:
                    image.WriteMap()

            # Write the updated FDTs to our output files
            for dtb_item in state.GetFdts():
                tools.WriteFile(dtb_item._fname, dtb_item.GetContents())

        finally:
            tools.FinaliseOutputDir()
    finally:
        tout.Uninit()

    return 0
Beispiel #17
0
def Binman(args):
    """The main control code for binman

    This assumes that help and test options have already been dealt with. It
    deals with the core task of building images.

    Args:
        args: Command line arguments Namespace object
    """
    global images

    if args.full_help:
        pager = os.getenv('PAGER')
        if not pager:
            pager = 'more'
        fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
                             'README')
        command.Run(pager, fname)
        return 0

    if args.cmd == 'ls':
        ListEntries(args.image, args.paths)
        return 0

    if args.cmd == 'extract':
        try:
            tools.PrepareOutputDir(None)
            ExtractEntries(args.image, args.filename, args.outdir, args.paths,
                           not args.uncompressed)
        finally:
            tools.FinaliseOutputDir()
        return 0

    # Try to figure out which device tree contains our image description
    if args.dt:
        dtb_fname = args.dt
    else:
        board = args.board
        if not board:
            raise ValueError(
                'Must provide a board to process (use -b <board>)')
        board_pathname = os.path.join(args.build_dir, board)
        dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
        if not args.indir:
            args.indir = ['.']
        args.indir.append(board_pathname)

    try:
        # Import these here in case libfdt.py is not available, in which case
        # the above help option still works.
        import fdt
        import fdt_util

        tout.Init(args.verbosity)
        elf.debug = args.debug
        cbfs_util.VERBOSE = args.verbosity > 2
        state.use_fake_dtb = args.fake_dtb
        try:
            tools.SetInputDirs(args.indir)
            tools.PrepareOutputDir(args.outdir, args.preserve)
            tools.SetToolPaths(args.toolpath)
            state.SetEntryArgs(args.entry_arg)

            # Get the device tree ready by compiling it and copying the compiled
            # output into a file in our output directly. Then scan it for use
            # in binman.
            dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
            fname = tools.GetOutputFilename('u-boot.dtb.out')
            tools.WriteFile(fname, tools.ReadFile(dtb_fname))
            dtb = fdt.FdtScan(fname)

            node = _FindBinmanNode(dtb)
            if not node:
                raise ValueError("Device tree '%s' does not have a 'binman' "
                                 "node" % dtb_fname)

            images = _ReadImageDesc(node)

            if args.image:
                skip = []
                new_images = OrderedDict()
                for name, image in images.items():
                    if name in args.image:
                        new_images[name] = image
                    else:
                        skip.append(name)
                images = new_images
                if skip and args.verbosity >= 2:
                    print('Skipping images: %s' % ', '.join(skip))

            state.Prepare(images, dtb)

            # Prepare the device tree by making sure that any missing
            # properties are added (e.g. 'pos' and 'size'). The values of these
            # may not be correct yet, but we add placeholders so that the
            # size of the device tree is correct. Later, in
            # SetCalculatedProperties() we will insert the correct values
            # without changing the device-tree size, thus ensuring that our
            # entry offsets remain the same.
            for image in images.values():
                image.ExpandEntries()
                if args.update_fdt:
                    image.AddMissingProperties()
                image.ProcessFdt(dtb)

            for dtb_item in state.GetFdts():
                dtb_item.Sync(auto_resize=True)
                dtb_item.Pack()
                dtb_item.Flush()

            for image in images.values():
                # Perform all steps for this image, including checking and
                # writing it. This means that errors found with a later
                # image will be reported after earlier images are already
                # completed and written, but that does not seem important.
                image.GetEntryContents()
                image.GetEntryOffsets()

                # We need to pack the entries to figure out where everything
                # should be placed. This sets the offset/size of each entry.
                # However, after packing we call ProcessEntryContents() which
                # may result in an entry changing size. In that case we need to
                # do another pass. Since the device tree often contains the
                # final offset/size information we try to make space for this in
                # AddMissingProperties() above. However, if the device is
                # compressed we cannot know this compressed size in advance,
                # since changing an offset from 0x100 to 0x104 (for example) can
                # alter the compressed size of the device tree. So we need a
                # third pass for this.
                passes = 3
                for pack_pass in range(passes):
                    try:
                        image.PackEntries()
                        image.CheckSize()
                        image.CheckEntries()
                    except Exception as e:
                        if args.map:
                            fname = image.WriteMap()
                            print("Wrote map file '%s' to show errors" % fname)
                        raise
                    image.SetImagePos()
                    if args.update_fdt:
                        image.SetCalculatedProperties()
                        for dtb_item in state.GetFdts():
                            dtb_item.Sync()
                    sizes_ok = image.ProcessEntryContents()
                    if sizes_ok:
                        break
                    image.ResetForPack()
                if not sizes_ok:
                    image.Raise(
                        'Entries expanded after packing (tried %s passes)' %
                        passes)

                image.WriteSymbols()
                image.BuildImage()
                if args.map:
                    image.WriteMap()

            # Write the updated FDTs to our output files
            for dtb_item in state.GetFdts():
                tools.WriteFile(dtb_item._fname, dtb_item.GetContents())

        finally:
            tools.FinaliseOutputDir()
    finally:
        tout.Uninit()

    return 0
Beispiel #18
0
def ReplaceEntries(image_fname,
                   input_fname,
                   indir,
                   entry_paths,
                   do_compress=True,
                   allow_resize=True,
                   write_map=False):
    """Replace the data from one or more entries from input files

    Args:
        image_fname: Image filename to process
        input_fname: Single input ilename to use if replacing one file, None
            otherwise
        indir: Input directory to use (for any number of files), else None
        entry_paths: List of entry paths to extract
        do_compress: True if the input data is uncompressed and may need to be
            compressed if the entry requires it, False if the data is already
            compressed.
        write_map: True to write a map file

    Returns:
        List of EntryInfo records that were written
    """
    image = Image.FromFile(image_fname)

    # Replace an entry from a single file, as a special case
    if input_fname:
        if not entry_paths:
            raise ValueError('Must specify an entry path to read with -f')
        if len(entry_paths) != 1:
            raise ValueError(
                'Must specify exactly one entry path to write with -f')
        entry = image.FindEntryPath(entry_paths[0])
        data = tools.ReadFile(input_fname)
        tout.Notice("Read %#x bytes from file '%s'" % (len(data), input_fname))
        WriteEntryToImage(image,
                          entry,
                          data,
                          do_compress=do_compress,
                          allow_resize=allow_resize,
                          write_map=write_map)
        return

    # Otherwise we will input from a path given by the entry path of each entry.
    # This means that files must appear in subdirectories if they are part of
    # a sub-section.
    einfos = image.GetListEntries(entry_paths)[0]
    tout.Notice("Replacing %d matching entries in image '%s'" %
                (len(einfos), image_fname))

    BeforeReplace(image, allow_resize)

    for einfo in einfos:
        entry = einfo.entry
        if entry.GetEntries():
            tout.Info("Skipping section entry '%s'" % entry.GetPath())
            continue

        path = entry.GetPath()[1:]
        fname = os.path.join(indir, path)

        if os.path.exists(fname):
            tout.Notice("Write entry '%s' from file '%s'" %
                        (entry.GetPath(), fname))
            data = tools.ReadFile(fname)
            ReplaceOneEntry(image, entry, data, do_compress, allow_resize)
        else:
            tout.Warning("Skipping entry '%s' from missing file '%s'" %
                         (entry.GetPath(), fname))

    AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
    return image
Beispiel #19
0
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
    """Prepare the images to be processed and select the device tree

    This function:
    - reads in the device tree
    - finds and scans the binman node to create all entries
    - selects which images to build
    - Updates the device tress with placeholder properties for offset,
        image-pos, etc.

    Args:
        dtb_fname: Filename of the device tree file to use (.dts or .dtb)
        selected_images: List of images to output, or None for all
        update_fdt: True to update the FDT wth entry offsets, etc.
    """
    # Import these here in case libfdt.py is not available, in which case
    # the above help option still works.
    import fdt
    import fdt_util
    global images

    # Get the device tree ready by compiling it and copying the compiled
    # output into a file in our output directly. Then scan it for use
    # in binman.
    dtb_fname = fdt_util.EnsureCompiled(dtb_fname)
    fname = tools.GetOutputFilename('u-boot.dtb.out')
    tools.WriteFile(fname, tools.ReadFile(dtb_fname))
    dtb = fdt.FdtScan(fname)

    node = _FindBinmanNode(dtb)
    if not node:
        raise ValueError("Device tree '%s' does not have a 'binman' "
                         "node" % dtb_fname)

    images = _ReadImageDesc(node)

    if select_images:
        skip = []
        new_images = OrderedDict()
        for name, image in images.items():
            if name in select_images:
                new_images[name] = image
            else:
                skip.append(name)
        images = new_images
        tout.Notice('Skipping images: %s' % ', '.join(skip))

    state.Prepare(images, dtb)

    # Prepare the device tree by making sure that any missing
    # properties are added (e.g. 'pos' and 'size'). The values of these
    # may not be correct yet, but we add placeholders so that the
    # size of the device tree is correct. Later, in
    # SetCalculatedProperties() we will insert the correct values
    # without changing the device-tree size, thus ensuring that our
    # entry offsets remain the same.
    for image in images.values():
        image.ExpandEntries()
        if update_fdt:
            image.AddMissingProperties()
        image.ProcessFdt(dtb)

    for dtb_item in state.GetAllFdts():
        dtb_item.Sync(auto_resize=True)
        dtb_item.Pack()
        dtb_item.Flush()
    return images