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=0x38, 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=0x38, 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\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 441 tag_pos = pos + cbfs_util.FILE_HEADER_LEN + cbfs_util.FILENAME_ALIGN 442 newdata = data[:tag_pos + 4] 443 with test_util.capture_sys_output() as (stdout, _stderr): 444 with io.BytesIO(newdata) as fd: 445 fd.seek(pos) 446 self.assertEqual(False, cbr._read_next_file(fd)) 447 self.assertIn('Attribute tag at %x ran out of data' % tag_pos, 448 stdout.getvalue()) 449 450 def test_cbfs_file_master_header(self): 451 """Check handling of a file containing a master header""" 452 size = 0x100 453 cbw = CbfsWriter(size) 454 cbw._add_fileheader = True 455 cbw.add_file_raw('u-boot', U_BOOT_DATA) 456 data = cbw.get_data() 457 458 cbr = cbfs_util.CbfsReader(data) 459 self.assertIn('u-boot', cbr.files) 460 self.assertEqual(size, cbr.rom_size) 461 462 def test_cbfs_arch(self): 463 """Test on non-x86 architecture""" 464 size = 0x100 465 cbw = CbfsWriter(size, arch=cbfs_util.ARCHITECTURE_PPC64) 466 cbw.add_file_raw('u-boot', U_BOOT_DATA) 467 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 468 data = cbw.get_data() 469 self._check_raw(data, size, offset=0x40, 470 arch=cbfs_util.ARCHITECTURE_PPC64) 471 472 # Compare against what cbfstool creates 473 cbfs_fname = self._get_expected_cbfs(size=size, arch='ppc64') 474 self._compare_expected_cbfs(data, cbfs_fname) 475 476 def test_cbfs_stage(self): 477 """Tests handling of a Coreboot Filesystem (CBFS)""" 478 if not elf.ELF_TOOLS: 479 self.skipTest('Python elftools not available') 480 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf') 481 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA) 482 483 size = 0xb0 484 cbw = CbfsWriter(size) 485 cbw.add_file_stage('u-boot', tools.read_file(elf_fname)) 486 487 data = cbw.get_data() 488 cbfs = self._check_hdr(data, size) 489 load = 0xfef20000 490 entry = load + 2 491 492 cfile = self._check_uboot(cbfs, cbfs_util.TYPE_STAGE, offset=0x28, 493 data=U_BOOT_DATA + U_BOOT_DTB_DATA) 494 495 self.assertEqual(entry, cfile.entry) 496 self.assertEqual(load, cfile.load) 497 self.assertEqual(len(U_BOOT_DATA) + len(U_BOOT_DTB_DATA), 498 cfile.data_len) 499 500 # Compare against what cbfstool creates 501 if self.have_cbfstool: 502 cbfs_fname = os.path.join(self._indir, 'test.cbfs') 503 self.cbfstool.create_new(cbfs_fname, size) 504 self.cbfstool.add_stage(cbfs_fname, 'u-boot', elf_fname) 505 self._compare_expected_cbfs(data, cbfs_fname) 506 507 def test_cbfs_raw_compress(self): 508 """Test base handling of compressing raw files""" 509 if not self.have_lz4: 510 self.skipTest('lz4 --no-frame-crc not available') 511 size = 0x140 512 cbw = CbfsWriter(size) 513 cbw.add_file_raw('u-boot', COMPRESS_DATA, None, 514 compress=cbfs_util.COMPRESS_LZ4) 515 cbw.add_file_raw('u-boot-dtb', COMPRESS_DATA, None, 516 compress=cbfs_util.COMPRESS_LZMA) 517 data = cbw.get_data() 518 519 cbfs = self._check_hdr(data, size) 520 self.assertIn('u-boot', cbfs.files) 521 cfile = cbfs.files['u-boot'] 522 self.assertEqual(cfile.name, 'u-boot') 523 self.assertEqual(cfile.offset, 56) 524 self.assertEqual(cfile.data, COMPRESS_DATA) 525 self.assertEqual(cfile.ftype, cbfs_util.TYPE_RAW) 526 self.assertEqual(cfile.compress, cbfs_util.COMPRESS_LZ4) 527 self.assertEqual(cfile.memlen, len(COMPRESS_DATA)) 528 529 self.assertIn('u-boot-dtb', cbfs.files) 530 cfile = cbfs.files['u-boot-dtb'] 531 self.assertEqual(cfile.name, 'u-boot-dtb') 532 self.assertEqual(cfile.offset, 56) 533 self.assertEqual(cfile.data, COMPRESS_DATA) 534 self.assertEqual(cfile.ftype, cbfs_util.TYPE_RAW) 535 self.assertEqual(cfile.compress, cbfs_util.COMPRESS_LZMA) 536 self.assertEqual(cfile.memlen, len(COMPRESS_DATA)) 537 538 cbfs_fname = self._get_expected_cbfs(size=size, compress=['lz4', 'lzma']) 539 self._compare_expected_cbfs(data, cbfs_fname) 540 541 def test_cbfs_raw_space(self): 542 """Test files with unused space in the CBFS""" 543 size = 0xf0 544 cbw = CbfsWriter(size) 545 cbw.add_file_raw('u-boot', U_BOOT_DATA) 546 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 547 data = cbw.get_data() 548 self._check_raw(data, size) 549 cbfs_fname = self._get_expected_cbfs(size=size) 550 self._compare_expected_cbfs(data, cbfs_fname) 551 552 def test_cbfs_offset(self): 553 """Test a CBFS with files at particular offsets""" 554 size = 0x200 555 cbw = CbfsWriter(size) 556 cbw.add_file_raw('u-boot', U_BOOT_DATA, 0x40) 557 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA, 0x140) 558 559 data = cbw.get_data() 560 cbfs = self._check_hdr(data, size) 561 self._check_uboot(cbfs, ftype=cbfs_util.TYPE_RAW, offset=0x40, 562 cbfs_offset=0x40) 563 self._check_dtb(cbfs, offset=0x40, cbfs_offset=0x140) 564 565 cbfs_fname = self._get_expected_cbfs(size=size, base=(0x40, 0x140)) 566 self._compare_expected_cbfs(data, cbfs_fname) 567 568 def test_cbfs_invalid_file_type_header(self): 569 """Check handling of an invalid file type when outputting a header""" 570 size = 0xb0 571 cbw = CbfsWriter(size) 572 cfile = cbw.add_file_raw('u-boot', U_BOOT_DATA, 0) 573 574 # Change the type manually before generating the CBFS, and make sure 575 # that the generator complains 576 cfile.ftype = 0xff 577 with self.assertRaises(ValueError) as e: 578 cbw.get_data() 579 self.assertIn('Unknown file type 0xff', str(e.exception)) 580 581 def test_cbfs_offset_conflict(self): 582 """Test a CBFS with files that want to overlap""" 583 size = 0x200 584 cbw = CbfsWriter(size) 585 cbw.add_file_raw('u-boot', U_BOOT_DATA, 0x40) 586 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA, 0x80) 587 588 with self.assertRaises(ValueError) as e: 589 cbw.get_data() 590 self.assertIn('No space for data before pad offset', str(e.exception)) 591 592 def test_cbfs_check_offset(self): 593 """Test that we can discover the offset of a file after writing it""" 594 size = 0xb0 595 cbw = CbfsWriter(size) 596 cbw.add_file_raw('u-boot', U_BOOT_DATA) 597 cbw.add_file_raw('u-boot-dtb', U_BOOT_DTB_DATA) 598 data = cbw.get_data() 599 600 cbfs = cbfs_util.CbfsReader(data) 601 self.assertEqual(0x38, cbfs.files['u-boot'].cbfs_offset) 602 self.assertEqual(0x78, cbfs.files['u-boot-dtb'].cbfs_offset) 603 604 605if __name__ == '__main__': 606 unittest.main() 607