def testLookupPhandle(self): """Test looking up a single phandle""" dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts') node = dtb.GetNode('/phandle-source2') prop = node.props['clocks'] target = dtb.GetNode('/phandle-target') self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
def GetNode(self): binman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) tools.PrepareOutputDir(None) fname = fdt_util.EnsureCompiled( os.path.join(binman_dir,('test/05_simple.dts'))) dtb = fdt.FdtScan(fname) return dtb.GetNode('/binman/u-boot')
def _RunMicrocodeTest(self, dts_fname, nodtb_data): data = self._DoReadFile(dts_fname, True) # Now check the device tree has no microcode second = data[len(nodtb_data):] fname = tools.GetOutputFilename('test.dtb') with open(fname, 'wb') as fd: fd.write(second) dtb = fdt.FdtScan(fname) ucode = dtb.GetNode('/microcode') self.assertTrue(ucode) for node in ucode.subnodes: self.assertFalse(node.props.get('data')) fdt_len = self.GetFdtLen(second) third = second[fdt_len:] # Check that the microcode appears immediately after the Fdt # This matches the concatenation of the data properties in # the /microcode/update@xxx nodes in 34_x86_ucode.dts. ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000, 0x78235609) self.assertEqual(ucode_data, third[:len(ucode_data)]) ucode_pos = len(nodtb_data) + fdt_len # Check that the microcode pointer was inserted. It should match the # expected position and size pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, len(ucode_data)) first = data[:len(nodtb_data)] return first, pos_and_size
def scan_dtb(self): """Scan the device tree to obtain a tree of nodes and properties Once this is done, self._fdt.GetRoot() can be called to obtain the device tree root node, and progress from there. """ self._fdt = fdt.FdtScan(self._dtb_fname)
def testGetPhandleList(self): dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts') node = dtb.GetNode('/phandle-source2') self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks')) node = dtb.GetNode('/phandle-source') self.assertEqual([1, 2, 11, 3, 12, 13, 1], fdt_util.GetPhandleList(node, 'clocks')) self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
def testFdtCellsToCpu(self): val = self.node.props['intarray'].value self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0)) self.assertEqual(2, fdt_util.fdt_cells_to_cpu(val, 1)) dtb2 = fdt.FdtScan('tools/dtoc/dtoc_test_addr64.dts') node2 = dtb2.GetNode('/test1') val = node2.props['reg'].value self.assertEqual(0x1234, fdt_util.fdt_cells_to_cpu(val, 2))
def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False): """Handle running a test for insertion of microcode Args: dts_fname: Name of test .dts file nodtb_data: Data that we expect in the first section ucode_second: True if the microsecond entry is second instead of third Returns: Tuple: Contents of first region (U-Boot or SPL) Position and size components of microcode pointer, as inserted in the above (two 4-byte words) """ data = self._DoReadFile(dts_fname, True) # Now check the device tree has no microcode if ucode_second: ucode_content = data[len(nodtb_data):] ucode_pos = len(nodtb_data) dtb_with_ucode = ucode_content[16:] fdt_len = self.GetFdtLen(dtb_with_ucode) else: dtb_with_ucode = data[len(nodtb_data):] fdt_len = self.GetFdtLen(dtb_with_ucode) ucode_content = dtb_with_ucode[fdt_len:] ucode_pos = len(nodtb_data) + fdt_len fname = tools.GetOutputFilename('test.dtb') with open(fname, 'wb') as fd: fd.write(dtb_with_ucode) dtb = fdt.FdtScan(fname) ucode = dtb.GetNode('/microcode') self.assertTrue(ucode) for node in ucode.subnodes: self.assertFalse(node.props.get('data')) # Check that the microcode appears immediately after the Fdt # This matches the concatenation of the data properties in # the /microcode/update@xxx nodes in 34_x86_ucode.dts. ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000, 0x78235609) self.assertEqual(ucode_data, ucode_content[:len(ucode_data)]) # Check that the microcode pointer was inserted. It should match the # expected position and size pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, len(ucode_data)) u_boot = data[:len(nodtb_data)] return u_boot, pos_and_size
def UpdateFdtContents(etype, data): """Update the contents of a particular device tree The device tree is updated and written back to its file. This affects what is returned from future called to GetFdtContents(), etc. Args: etype: Entry type (e.g. 'u-boot-dtb') data: Data to replace the DTB with """ dtb, fname, entry = output_fdt_info[etype] dtb_fname = dtb.GetFilename() tools.WriteFile(dtb_fname, data) dtb = fdt.FdtScan(dtb_fname) output_fdt_info[etype] = [dtb, fname, entry]
def ObtainContents(self): Entry_blob.ObtainContents(self) # If the image does not need microcode, there is nothing to do ucode_dest_entry = self.image.FindEntryType( 'u-boot-spl-with-ucode-ptr') if not ucode_dest_entry or not ucode_dest_entry.target_pos: ucode_dest_entry = self.image.FindEntryType( 'u-boot-with-ucode-ptr') if not ucode_dest_entry or not ucode_dest_entry.target_pos: return True # Create a new file to hold the copied device tree dtb_name = 'u-boot-dtb-with-ucode.dtb' fname = tools.GetOutputFilename(dtb_name) with open(fname, 'wb') as fd: fd.write(self.data) # Remove the microcode dtb = fdt.FdtScan(fname) ucode = dtb.GetNode('/microcode') if not ucode: raise self.Raise("No /microcode node found in '%s'" % fname) # There's no need to collate it (move all microcode into one place) # if we only have one chunk of microcode. self.collate = len(ucode.subnodes) > 1 for node in ucode.subnodes: data_prop = node.props.get('data') if data_prop: self.ucode_data += ''.join(data_prop.bytes) if self.collate: prop = node.DeleteProp('data') else: # Find the offset in the device tree of the ucode data self.ucode_offset = data_prop.GetOffset() + 12 self.ucode_size = len(data_prop.bytes) if self.collate: dtb.Pack() dtb.Flush() # Make this file the contents of this entry self._pathname = fname self.ReadContents() return True
def testPackUbootMicrocode(self): """Test that x86 microcode can be handled correctly We expect to see the following in the image, in order: u-boot-nodtb.bin with a microcode pointer inserted at the correct place u-boot.dtb with the microcode removed the microcode """ data = self._DoReadFile('34_x86_ucode.dts', True) # Now check the device tree has no microcode second = data[len(U_BOOT_NODTB_DATA):] fname = tools.GetOutputFilename('test.dtb') with open(fname, 'wb') as fd: fd.write(second) dtb = fdt.FdtScan(fname) ucode = dtb.GetNode('/microcode') self.assertTrue(ucode) for node in ucode.subnodes: self.assertFalse(node.props.get('data')) fdt_len = self.GetFdtLen(second) third = second[fdt_len:] # Check that the microcode appears immediately after the Fdt # This matches the concatenation of the data properties in # the /microcode/update@xxx nodes in x86_ucode.dts. ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000, 0x78235609) self.assertEqual(ucode_data, third[:len(ucode_data)]) ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len # Check that the microcode pointer was inserted. It should match the # expected position and size pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, len(ucode_data)) first = data[:len(U_BOOT_NODTB_DATA)] self.assertEqual( 'nodtb with microcode' + pos_and_size + ' somewhere in here', first)
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 testPhandle(self): dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts') node = dtb.GetNode('/phandle-source2') prop = node.props['clocks'] self.assertTrue(fdt32_to_cpu(prop.value) > 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
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 try: tools.SetInputDirs(options.indir) tools.PrepareOutputDir(options.outdir, options.preserve) 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-out.dtb') with open(dtb_fname) as infd: with open(fname, 'wb') as outfd: outfd.write(infd.read()) dtb = fdt.FdtScan(fname) # Note the file so that GetFdt() can find it fdt_files['u-boot.dtb'] = dtb node = _FindBinmanNode(dtb) if not node: raise ValueError("Device tree '%s' does not have a 'binman' " "node" % dtb_fname) images = _ReadImageDesc(node) # 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(): if options.update_fdt: image.AddMissingProperties() image.ProcessFdt(dtb) dtb.Pack() dtb.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() image.PackEntries() image.CheckSize() image.CheckEntries() image.SetImagePos() if options.update_fdt: image.SetCalculatedProperties() image.ProcessEntryContents() image.WriteSymbols() image.BuildImage() if options.map: image.WriteMap() with open(fname, 'wb') as outfd: outfd.write(dtb.GetContents()) finally: tools.FinaliseOutputDir() finally: tout.Uninit() return 0
def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts')
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
def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') self.node = self.dtb.GetNode('/spl-test')
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: tout.Init(options.verbosity) elf.debug = options.debug try: tools.SetInputDirs(options.indir) tools.PrepareOutputDir(options.outdir, options.preserve) dtb = fdt.FdtScan(dtb_fname) node = _FindBinmanNode(dtb) if not node: raise ValueError("Device tree '%s' does not have a 'binman' " "node" % dtb_fname) images = _ReadImageDesc(node) 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.GetEntryPositions() image.PackEntries() image.CheckSize() image.CheckEntries() image.ProcessEntryContents() image.WriteSymbols() image.BuildImage() if options.map: image.WriteMap() finally: tools.FinaliseOutputDir() finally: tout.Uninit() return 0