1#!/usr/bin/env python 2# SPDX-License-Identifier: GPL-2.0+ 3# Copyright 2019 Google LLC 4# Written by Simon Glass <sjg@chromium.org> 5 6"""Tests for cbfs_util 7 8These create and read various CBFSs and compare the results with expected 9values and with cbfstool 10""" 11 12import io 13import os 14import shutil 15import struct 16import tempfile 17import unittest 18 19from binman import bintool 20from binman import cbfs_util 21from binman.cbfs_util import CbfsWriter 22from binman import elf 23from u_boot_pylib import test_util 24from u_boot_pylib import tools 25 26U_BOOT_DATA = b'1234' 27U_BOOT_DTB_DATA = b'udtb' 28COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data' 29 30 31class TestCbfs(unittest.TestCase): 32 """Test of cbfs_util classes""" 33 #pylint: disable=W0212 34 @classmethod 35 def setUpClass(cls): 36 # Create a temporary directory for test files 37 cls._indir = tempfile.mkdtemp(prefix='cbfs_util.') 38 tools.set_input_dirs([cls._indir]) 39 40 # Set up some useful data files 41 TestCbfs._make_input_file('u-boot.bin', U_BOOT_DATA) 42 TestCbfs._make_input_file('u-boot.dtb', U_BOOT_DTB_DATA) 43 TestCbfs._make_input_file('compress', COMPRESS_DATA) 44 45 # Set up a temporary output directory, used by the tools library when 46 # compressing files 47 tools.prepare_output_dir(None) 48 49 cls.cbfstool = bintool.Bintool.create('cbfstool') 50 cls.have_cbfstool = cls.cbfstool.is_present() 51 52 lz4 = bintool.Bintool.create('lz4') 53 cls.have_lz4 = lz4.is_present() 54 55 @classmethod 56 def tearDownClass(cls): 57 """Remove the temporary input directory and its contents""" 58 if cls._indir: 59 shutil.rmtree(cls._indir) 60 cls._indir = None 61 tools.finalise_output_dir() 62 63 @classmethod 64 def _make_input_file(cls, fname, contents): 65 """Create a new test input file, creating directories as needed 66 67 Args: 68 fname: Filename to create 69 contents: File contents to write in to the file 70 Returns: 71 Full pathname of file created 72 """ 73 pathname = os.path.join(cls._indir, fname) 74 tools.write_file(pathname, contents) 75 return pathname 76 77 def _check_hdr(self, data, size, offset=0, arch=cbfs_util.ARCHITECTURE_X86): 78 """Check that the CBFS has the expected header 79 80 Args: 81 data: Data to check 82 size: Expected ROM size 83 offset: Expected offset to first CBFS file 84 arch: Expected architecture 85 86 Returns: 87 CbfsReader object containing the CBFS 88 """ 89 cbfs = cbfs_util.CbfsReader(data) 90 self.assertEqual(cbfs_util.HEADER_MAGIC, cbfs.magic) 91 self.assertEqual(cbfs_util.HEADER_VERSION2, cbfs.version) 92 self.assertEqual(size, cbfs.rom_size) 93 self.assertEqual(0, cbfs.boot_block_size) 94 self.assertEqual(cbfs_util.ENTRY_ALIGN, cbfs.align) 95 self.assertEqual(offset, cbfs.cbfs_offset) 96 self.assertEqual(arch, cbfs.arch) 97 return cbfs 98 99 def _check_uboot(self, cbfs, ftype=cbfs_util.TYPE_RAW, offset=0x20, 100 data=U_BOOT_DATA, cbfs_offset=None): 101 """Check that the U-Boot file is as expected 102 103 Args: 104 cbfs: CbfsReader object to check 105 ftype: Expected file type 106 offset: Expected offset of file 107 data: Expected data in file 108 cbfs_offset: Expected CBFS offset for file's data 109 110 Returns: 111 CbfsFile object containing the file 112 """ 113 self.assertIn('u-boot', cbfs.files) 114 cfile = cbfs.files['u-boot'] 115 self.assertEqual('u-boot', cfile.name) 116 self.assertEqual(offset, cfile.offset) 117 if cbfs_offset is not None: 118 self.assertEqual(cbfs_offset, cfile.cbfs_offset) 119 self.assertEqual(data, cfile.data) 120 self.assertEqual(ftype, cfile.ftype) 121 self.assertEqual(cbfs_util.COMPRESS_NONE, cfile.compress) 122 self.assertEqual(len(data), cfile.memlen) 123 return cfile 124 125 def _check_dtb(self, cbfs, offset=0x24, data=U_BOOT_DTB_DATA, 126 cbfs_offset=None): 127 """Check that the U-Boot dtb file is as expected 128 129 Args: 130 cbfs: CbfsReader object to check 131 offset: Expected offset of file 132 data: Expected data in file 133 cbfs_offset: Expected CBFS offset for file's data 134 """ 135 self.assertIn('u-boot-dtb', cbfs.files) 136 cfile = cbfs.files['u-boot-dtb'] 137 self.assertEqual('u-boot-dtb', cfile.name) 138 self.assertEqual(offset, cfile.offset) 139 if cbfs_offset is not None: 140 self.assertEqual(cbfs_offset, cfile.cbfs_offset) 141 self.assertEqual(U_BOOT_DTB_DATA, cfile.data) 142 self.assertEqual(cbfs_util.TYPE_RAW, cfile.ftype) 143 self.assertEqual(cbfs_util.COMPRESS_NONE, cfile.compress) 144 self.assertEqual(len(U_BOOT_DTB_DATA), cfile.memlen) 145 146 def _check_raw(self, data, size, offset=0, arch=cbfs_util.ARCHITECTURE_X86): 147 """Check that two raw files are added as expected 148 149 Args: 150 data: Data to check 151 size: Expected ROM size 152 offset: Expected offset to first CBFS file 153 arch: Expected architecture 154 """ 155 cbfs = self._check_hdr(data, size, offset=offset, arch=arch) 156 self._check_uboot(cbfs) 157 self._check_dtb(cbfs) 158 159 def _get_expected_cbfs(self, size, arch='x86', compress=None, base=None): 160 """Get the file created by cbfstool for a particular scenario 161 162 Args: 163 size: Size of the CBFS in bytes 164 arch: Architecture of the CBFS, as a string 165 compress: Compression to use, e.g. cbfs_util.COMPRESS_LZMA 166 base: Base address of file, or None to put it anywhere 167 168 Returns: 169 Resulting CBFS file, or None if cbfstool is not available 170 """ 171 if not self.have_cbfstool or not self.have_lz4: 172 return None 173 cbfs_fname = os.path.join(self._indir, 'test.cbfs') 174 self.cbfstool.create_new(cbfs_fname, size, arch) 175 if base: 176 base = [(1 << 32) - size + b for b in base] 177 self.cbfstool.add_raw( 178 cbfs_fname, 'u-boot', 179 tools.get_input_filename(compress and 'compress' or 'u-boot.bin'), 180 compress[0] if compress else None, 181 base[0] if base else None) 182 self.cbfstool.add_raw( 183 cbfs_fname, 'u-boot-dtb', 184 tools.get_input_filename(compress and 'compress' or 'u-boot.dtb'), 185 compress[1] if compress else None, 186 base[1] if base else None) 187 return cbfs_fname 188 189 def _compare_expected_cbfs(self, data, cbfstool_fname): 190 """Compare against what cbfstool creates 191 192 This compares what binman creates with what cbfstool creates for what 193 is proportedly the same thing. 194 195 Args: 196 data: CBFS created by binman 197 cbfstool_fname: CBFS created by cbfstool 198 """ 199 if not self.have_cbfstool or not self.have_lz4: 200 return 201 expect = tools.read_file(cbfstool_fname) 202 if expect != data: 203 tools.write_file('/tmp/expect', expect) 204 tools.write_file('/tmp/actual', data) 205 print('diff -y <(xxd -g1 /tmp/expect) <(xxd -g1 /tmp/actual) | colordiff') 206 self.fail('cbfstool produced a different result') 207 208 def test_cbfs_functions(self): 209 """Test global functions of cbfs_util""" 210 self.assertEqual(cbfs_util.ARCHITECTURE_X86, cbfs_util.find_arch('x86')) 211 self.assertIsNone(cbfs_util.find_arch('bad-arch')) 212 213 self.assertEqual(cbfs_util.COMPRESS_LZMA, cbfs_util.find_compress('lzma')) 214 self.assertIsNone(cbfs_util.find_compress('bad-comp')) 215 216 def test_cbfstool_failure(self): 217 """Test failure to run cbfstool""" 218 if not self.have_cbfstool: 219 self.skipTest('No cbfstool available') 220 with self.assertRaises(ValueError) as exc: 221 out = self.cbfstool.fail() 222 self.assertIn('cbfstool missing-file bad-command', str(exc.exception)) 223 224 def test_cbfs_raw(self): 225 """Test base handling of a Coreboot Filesystem (CBFS)""" 226 size = 0xb0 227 cbw = CbfsWriter(size) 228 cbw.add_file_raw('u-boot', U_BOOT_DATA) 229 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 230 data = cbw.get_data() 231 self._check_raw(data, size) 232 cbfs_fname = self._get_expected_cbfs(size=size) 233 self._compare_expected_cbfs(data, cbfs_fname) 234 235 def test_cbfs_invalid_file_type(self): 236 """Check handling of an invalid file type when outputiing a CBFS""" 237 size = 0xb0 238 cbw = CbfsWriter(size) 239 cfile = cbw.add_file_raw('u-boot', U_BOOT_DATA) 240 241 # Change the type manually before generating the CBFS, and make sure 242 # that the generator complains 243 cfile.ftype = 0xff 244 with self.assertRaises(ValueError) as e: 245 cbw.get_data() 246 self.assertIn('Unknown type 0xff when writing', str(e.exception)) 247 248 def test_cbfs_invalid_file_type_on_read(self): 249 """Check handling of an invalid file type when reading the CBFS""" 250 size = 0xb0 251 cbw = CbfsWriter(size) 252 cbw.add_file_raw('u-boot', U_BOOT_DATA) 253 254 data = cbw.get_data() 255 256 # Read in the first file header 257 cbr = cbfs_util.CbfsReader(data, read=False) 258 with io.BytesIO(data) as fd: 259 self.assertTrue(cbr._find_and_read_header(fd, len(data))) 260 pos = fd.tell() 261 hdr_data = fd.read(cbfs_util.FILE_HEADER_LEN) 262 magic, size, ftype, attr, offset = struct.unpack( 263 cbfs_util.FILE_HEADER_FORMAT, hdr_data) 264 265 # Create a new CBFS with a change to the file type 266 ftype = 0xff 267 newdata = data[:pos] 268 newdata += struct.pack(cbfs_util.FILE_HEADER_FORMAT, magic, size, ftype, 269 attr, offset) 270 newdata += data[pos + cbfs_util.FILE_HEADER_LEN:] 271 272 # Read in this CBFS and make sure that the reader complains 273 with self.assertRaises(ValueError) as e: 274 cbfs_util.CbfsReader(newdata) 275 self.assertIn('Unknown type 0xff when reading', str(e.exception)) 276 277 def test_cbfs_no_space(self): 278 """Check handling of running out of space in the CBFS""" 279 size = 0x60 280 cbw = CbfsWriter(size) 281 cbw.add_file_raw('u-boot', U_BOOT_DATA) 282 with self.assertRaises(ValueError) as e: 283 cbw.get_data() 284 self.assertIn('No space for header', str(e.exception)) 285 286 def test_cbfs_no_space_skip(self): 287 """Check handling of running out of space in CBFS with file header""" 288 size = 0x5c 289 cbw = CbfsWriter(size, arch=cbfs_util.ARCHITECTURE_PPC64) 290 cbw._add_fileheader = True 291 cbw.add_file_raw('u-boot', U_BOOT_DATA) 292 with self.assertRaises(ValueError) as e: 293 cbw.get_data() 294 self.assertIn('No space for data before offset', str(e.exception)) 295 296 def test_cbfs_no_space_pad(self): 297 """Check handling of running out of space in CBFS with file header""" 298 size = 0x70 299 cbw = CbfsWriter(size) 300 cbw._add_fileheader = True 301 cbw.add_file_raw('u-boot', U_BOOT_DATA) 302 with self.assertRaises(ValueError) as e: 303 cbw.get_data() 304 self.assertIn('No space for data before pad offset', str(e.exception)) 305 306 def test_cbfs_bad_header_ptr(self): 307 """Check handling of a bad master-header pointer""" 308 size = 0x70 309 cbw = CbfsWriter(size) 310 cbw.add_file_raw('u-boot', U_BOOT_DATA) 311 data = cbw.get_data() 312 313 # Add one to the pointer to make it invalid 314 newdata = data[:-4] + struct.pack('<I', cbw._header_offset + 1) 315 316 # We should still be able to find the master header by searching 317 with test_util.capture_sys_output() as (stdout, _stderr): 318 cbfs = cbfs_util.CbfsReader(newdata) 319 self.assertIn('Relative offset seems wrong', stdout.getvalue()) 320 self.assertIn('u-boot', cbfs.files) 321 self.assertEqual(size, cbfs.rom_size) 322 323 def test_cbfs_bad_header(self): 324 """Check handling of a bad master header""" 325 size = 0x70 326 cbw = CbfsWriter(size) 327 cbw.add_file_raw('u-boot', U_BOOT_DATA) 328 data = cbw.get_data() 329 330 # Drop most of the header and try reading the modified CBFS 331 newdata = data[:cbw._header_offset + 4] 332 333 with test_util.capture_sys_output() as (stdout, _stderr): 334 with self.assertRaises(ValueError) as e: 335 cbfs_util.CbfsReader(newdata) 336 self.assertIn('Relative offset seems wrong', stdout.getvalue()) 337 self.assertIn('Cannot find master header', str(e.exception)) 338 339 def test_cbfs_bad_file_header(self): 340 """Check handling of a bad file header""" 341 size = 0x70 342 cbw = CbfsWriter(size) 343 cbw.add_file_raw('u-boot', U_BOOT_DATA) 344 data = cbw.get_data() 345 346 # Read in the CBFS master header (only), then stop 347 cbr = cbfs_util.CbfsReader(data, read=False) 348 with io.BytesIO(data) as fd: 349 self.assertTrue(cbr._find_and_read_header(fd, len(data))) 350 pos = fd.tell() 351 352 # Remove all but 4 bytes of the file headerm and try to read the file 353 newdata = data[:pos + 4] 354 with test_util.capture_sys_output() as (stdout, _stderr): 355 with io.BytesIO(newdata) as fd: 356 fd.seek(pos) 357 self.assertEqual(False, cbr._read_next_file(fd)) 358 self.assertIn('File header at 0x0 ran out of data', stdout.getvalue()) 359 360 def test_cbfs_bad_file_string(self): 361 """Check handling of an incomplete filename string""" 362 size = 0x70 363 cbw = CbfsWriter(size) 364 cbw.add_file_raw('16-characters xx', U_BOOT_DATA) 365 data = cbw.get_data() 366 367 # Read in the CBFS master header (only), then stop 368 cbr = cbfs_util.CbfsReader(data, read=False) 369 with io.BytesIO(data) as fd: 370 self.assertTrue(cbr._find_and_read_header(fd, len(data))) 371 pos = fd.tell() 372 373 # Create a new CBFS with only the first 16 bytes of the file name, then 374 # try to read the file 375 newdata = data[:pos + cbfs_util.FILE_HEADER_LEN + 16] 376 with test_util.capture_sys_output() as (stdout, _stderr): 377 with io.BytesIO(newdata) as fd: 378 fd.seek(pos) 379 self.assertEqual(False, cbr._read_next_file(fd)) 380 self.assertIn('String at %#x ran out of data' % 381 cbfs_util.FILE_HEADER_LEN, stdout.getvalue()) 382 383 def test_cbfs_debug(self): 384 """Check debug output""" 385 size = 0x70 386 cbw = CbfsWriter(size) 387 cbw.add_file_raw('u-boot', U_BOOT_DATA) 388 data = cbw.get_data() 389 390 try: 391 cbfs_util.DEBUG = True 392 with test_util.capture_sys_output() as (stdout, _stderr): 393 cbfs_util.CbfsReader(data) 394 self.assertEqual('name u-boot\nftype 50\ndata %s\n' % U_BOOT_DATA, 395 stdout.getvalue()) 396 finally: 397 cbfs_util.DEBUG = False 398 399 def test_cbfs_bad_attribute(self): 400 """Check handling of bad attribute tag""" 401 if not self.have_lz4: 402 self.skipTest('lz4 --no-frame-crc not available') 403 size = 0x140 404 cbw = CbfsWriter(size) 405 cbw.add_file_raw('u-boot', COMPRESS_DATA, None, 406 compress=cbfs_util.COMPRESS_LZ4) 407 data = cbw.get_data() 408 409 # Search the CBFS for the expected compression tag 410 with io.BytesIO(data) as fd: 411 while True: 412 pos = fd.tell() 413 tag, = struct.unpack('>I', fd.read(4)) 414 if tag == cbfs_util.FILE_ATTR_TAG_COMPRESSION: 415 break 416 417 # Create a new CBFS with the tag changed to something invalid 418 newdata = data[:pos] + struct.pack('>I', 0x123) + data[pos + 4:] 419 with test_util.capture_sys_output() as (stdout, _stderr): 420 cbfs_util.CbfsReader(newdata) 421 self.assertEqual('Unknown attribute tag 123\n', stdout.getvalue()) 422 423 def test_cbfs_missing_attribute(self): 424 """Check handling of an incomplete attribute tag""" 425 if not self.have_lz4: 426 self.skipTest('lz4 --no-frame-crc not available') 427 size = 0x140 428 cbw = CbfsWriter(size) 429 cbw.add_file_raw('u-boot', COMPRESS_DATA, None, 430 compress=cbfs_util.COMPRESS_LZ4) 431 data = cbw.get_data() 432 433 # Read in the CBFS master header (only), then stop 434 cbr = cbfs_util.CbfsReader(data, read=False) 435 with io.BytesIO(data) as fd: 436 self.assertTrue(cbr._find_and_read_header(fd, len(data))) 437 pos = fd.tell() 438 439 # Create a new CBFS with only the first 4 bytes of the compression tag, 440 # then try to read the file. Note that the tag gets pushed out 4 bytes 441 tag_pos = (4 + pos + cbfs_util.FILE_HEADER_LEN + 442 cbfs_util.ATTRIBUTE_ALIGN) 443 newdata = data[:tag_pos + 4] 444 with test_util.capture_sys_output() as (stdout, _stderr): 445 with io.BytesIO(newdata) as fd: 446 fd.seek(pos) 447 self.assertEqual(False, cbr._read_next_file(fd)) 448 self.assertIn('Attribute tag at %x ran out of data' % tag_pos, 449 stdout.getvalue()) 450 451 def test_cbfs_file_master_header(self): 452 """Check handling of a file containing a master header""" 453 size = 0x100 454 cbw = CbfsWriter(size) 455 cbw._add_fileheader = True 456 cbw.add_file_raw('u-boot', U_BOOT_DATA) 457 data = cbw.get_data() 458 459 cbr = cbfs_util.CbfsReader(data) 460 self.assertIn('u-boot', cbr.files) 461 self.assertEqual(size, cbr.rom_size) 462 463 def test_cbfs_arch(self): 464 """Test on non-x86 architecture""" 465 size = 0x100 466 cbw = CbfsWriter(size, arch=cbfs_util.ARCHITECTURE_PPC64) 467 cbw.add_file_raw('u-boot', U_BOOT_DATA) 468 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 469 data = cbw.get_data() 470 self._check_raw(data, size, offset=0x40, 471 arch=cbfs_util.ARCHITECTURE_PPC64) 472 473 # Compare against what cbfstool creates 474 cbfs_fname = self._get_expected_cbfs(size=size, arch='ppc64') 475 self._compare_expected_cbfs(data, cbfs_fname) 476 477 def test_cbfs_stage(self): 478 """Tests handling of a CBFS stage""" 479 if not elf.ELF_TOOLS: 480 self.skipTest('Python elftools not available') 481 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf') 482 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA) 483 484 size = 0xb0 485 cbw = CbfsWriter(size) 486 cbw.add_file_stage('u-boot', tools.read_file(elf_fname)) 487 488 data = cbw.get_data() 489 cbfs = self._check_hdr(data, size) 490 load = 0xfef20000 491 entry = load + 2 492 493 cfile = self._check_uboot(cbfs, cbfs_util.TYPE_STAGE, offset=0x38, 494 data=U_BOOT_DATA + U_BOOT_DTB_DATA) 495 496 self.assertEqual(entry, cfile.entry) 497 self.assertEqual(load, cfile.load) 498 self.assertEqual(len(U_BOOT_DATA) + len(U_BOOT_DTB_DATA), 499 cfile.data_len) 500 501 # Compare against what cbfstool creates 502 if self.have_cbfstool: 503 cbfs_fname = os.path.join(self._indir, 'test.cbfs') 504 self.cbfstool.create_new(cbfs_fname, size) 505 self.cbfstool.add_stage(cbfs_fname, 'u-boot', elf_fname) 506 self._compare_expected_cbfs(data, cbfs_fname) 507 508 def test_cbfs_raw_compress(self): 509 """Test base handling of compressing raw files""" 510 if not self.have_lz4: 511 self.skipTest('lz4 --no-frame-crc not available') 512 size = 0x140 513 cbw = CbfsWriter(size) 514 cbw.add_file_raw('u-boot', COMPRESS_DATA, None, 515 compress=cbfs_util.COMPRESS_LZ4) 516 cbw.add_file_raw('u-boot-dtb', COMPRESS_DATA, None, 517 compress=cbfs_util.COMPRESS_LZMA) 518 data = cbw.get_data() 519 520 cbfs = self._check_hdr(data, size) 521 self.assertIn('u-boot', cbfs.files) 522 cfile = cbfs.files['u-boot'] 523 self.assertEqual(cfile.name, 'u-boot') 524 self.assertEqual(cfile.offset, 0x30) 525 self.assertEqual(cfile.data, COMPRESS_DATA) 526 self.assertEqual(cfile.ftype, cbfs_util.TYPE_RAW) 527 self.assertEqual(cfile.compress, cbfs_util.COMPRESS_LZ4) 528 self.assertEqual(cfile.memlen, len(COMPRESS_DATA)) 529 530 self.assertIn('u-boot-dtb', cbfs.files) 531 cfile = cbfs.files['u-boot-dtb'] 532 self.assertEqual(cfile.name, 'u-boot-dtb') 533 self.assertEqual(cfile.offset, 0x34) 534 self.assertEqual(cfile.data, COMPRESS_DATA) 535 self.assertEqual(cfile.ftype, cbfs_util.TYPE_RAW) 536 self.assertEqual(cfile.compress, cbfs_util.COMPRESS_LZMA) 537 self.assertEqual(cfile.memlen, len(COMPRESS_DATA)) 538 539 cbfs_fname = self._get_expected_cbfs(size=size, compress=['lz4', 'lzma']) 540 self._compare_expected_cbfs(data, cbfs_fname) 541 542 def test_cbfs_raw_space(self): 543 """Test files with unused space in the CBFS""" 544 size = 0xf0 545 cbw = CbfsWriter(size) 546 cbw.add_file_raw('u-boot', U_BOOT_DATA) 547 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 548 data = cbw.get_data() 549 self._check_raw(data, size) 550 cbfs_fname = self._get_expected_cbfs(size=size) 551 self._compare_expected_cbfs(data, cbfs_fname) 552 553 def test_cbfs_offset(self): 554 """Test a CBFS with files at particular offsets""" 555 size = 0x200 556 cbw = CbfsWriter(size) 557 cbw.add_file_raw('u-boot', U_BOOT_DATA, 0x40) 558 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA, 0x140) 559 560 data = cbw.get_data() 561 cbfs = self._check_hdr(data, size) 562 self._check_uboot(cbfs, ftype=cbfs_util.TYPE_RAW, offset=0x40, 563 cbfs_offset=0x40) 564 self._check_dtb(cbfs, offset=0x40, cbfs_offset=0x140) 565 566 cbfs_fname = self._get_expected_cbfs(size=size, base=(0x40, 0x140)) 567 self._compare_expected_cbfs(data, cbfs_fname) 568 569 def test_cbfs_invalid_file_type_header(self): 570 """Check handling of an invalid file type when outputting a header""" 571 size = 0xb0 572 cbw = CbfsWriter(size) 573 cfile = cbw.add_file_raw('u-boot', U_BOOT_DATA, 0) 574 575 # Change the type manually before generating the CBFS, and make sure 576 # that the generator complains 577 cfile.ftype = 0xff 578 with self.assertRaises(ValueError) as e: 579 cbw.get_data() 580 self.assertIn('Unknown file type 0xff', str(e.exception)) 581 582 def test_cbfs_offset_conflict(self): 583 """Test a CBFS with files that want to overlap""" 584 size = 0x200 585 cbw = CbfsWriter(size) 586 cbw.add_file_raw('u-boot', U_BOOT_DATA, 0x40) 587 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA, 0x80) 588 589 with self.assertRaises(ValueError) as e: 590 cbw.get_data() 591 self.assertIn('No space for data before pad offset', str(e.exception)) 592 593 def test_cbfs_check_offset(self): 594 """Test that we can discover the offset of a file after writing it""" 595 size = 0xb0 596 cbw = CbfsWriter(size) 597 cbw.add_file_raw('u-boot', U_BOOT_DATA) 598 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 599 data = cbw.get_data() 600 601 cbfs = cbfs_util.CbfsReader(data) 602 self.assertEqual(0x20, cbfs.files['u-boot'].cbfs_offset) 603 self.assertEqual(0x64, cbfs.files['u-boot-dtb'].cbfs_offset) 604 605 606if __name__ == '__main__': 607 unittest.main() 608