Exemple #1
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
Exemple #2
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)')
        keydir = tools.GetInputFilename(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.GetInputFilename(self.bmpblk))

        if stdout is not None:
            self.SetContents(tools.ReadFile(fname))
        else:
            # Bintool is missing; just use the required amount of zero data
            self.record_missing_bintool(self.futility)
            self.SetContents(tools.GetBytes(0, gbb_size))

        return True
Exemple #3
0
    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.GetInputFilename(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.GetInputFilename(compress and 'compress' or 'u-boot.dtb'),
            compress[1] if compress else None, base[1] if base else None)
        return cbfs_fname
Exemple #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
Exemple #5
0
 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
Exemple #6
0
    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.GetInputFilename(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()
Exemple #7
0
    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
Exemple #8
0
 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
Exemple #9
0
 def ObtainContents(self):
     self._filename = self.GetDefaultFilename()
     self._pathname = tools.GetInputFilename(self._filename,
                                             self.section.GetAllowMissing())
     # Allow the file to be missing
     if not self._pathname:
         self.SetContents(b'')
         self.missing = True
         return True
     return super().ObtainContents()
Exemple #10
0
    def ObtainContents(self):
        self._filename = self.GetDefaultFilename()
        self._pathname = tools.GetInputFilename(
            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
Exemple #11
0
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.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.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))

            # 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:])
Exemple #12
0
    def ObtainContents(self):
        if self.allow_fake and not pathlib.Path(self._filename).is_file():
            with open(self._filename, "wb") as out:
                out.truncate(1024)
            self.faked = True

        self._filename = self.GetDefaultFilename()
        self._pathname = tools.GetInputFilename(
            self._filename, self.external and self.section.GetAllowMissing())
        # Allow the file to be missing
        if not self._pathname:
            self.SetContents(b'')
            self.missing = True
            return True

        self.ReadBlobContents()
        return True
Exemple #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.
    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', 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]
Exemple #14
0
    def ObtainContents(self):
        missing = False
        pathnames = []
        for fname in self._filenames:
            pathname = tools.GetInputFilename(
                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
Exemple #15
0
 def ObtainContents(self):
     self._filename = self.GetDefaultFilename()
     self._pathname = tools.GetInputFilename(self._filename)
     self.ReadBlobContents()
     return True
Exemple #16
0
        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._fit_sections[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 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.GetInputFilename(fdt_fname + '.dtb')
                            with fsw.add_node(node_name):
                                for pname, prop in subnode.props.items():
                                    val = prop.bytes.replace(
                                        b'NAME', tools.ToBytes(fdt_fname))
                                    val = val.replace(
                                        b'SEQ', tools.ToBytes(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.ReadFile(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)