1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (c) 2016 Google, Inc 3*4882a593Smuzhiyun# Written by Simon Glass <sjg@chromium.org> 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0+ 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# To run a single test, change to this directory, and: 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# python -m unittest func_test.TestFunctional.testHelp 10*4882a593Smuzhiyun 11*4882a593Smuzhiyunfrom optparse import OptionParser 12*4882a593Smuzhiyunimport os 13*4882a593Smuzhiyunimport shutil 14*4882a593Smuzhiyunimport struct 15*4882a593Smuzhiyunimport sys 16*4882a593Smuzhiyunimport tempfile 17*4882a593Smuzhiyunimport unittest 18*4882a593Smuzhiyun 19*4882a593Smuzhiyunimport binman 20*4882a593Smuzhiyunimport cmdline 21*4882a593Smuzhiyunimport command 22*4882a593Smuzhiyunimport control 23*4882a593Smuzhiyunimport entry 24*4882a593Smuzhiyunimport fdt 25*4882a593Smuzhiyunimport fdt_util 26*4882a593Smuzhiyunimport tools 27*4882a593Smuzhiyunimport tout 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun# Contents of test files, corresponding to different entry types 30*4882a593SmuzhiyunU_BOOT_DATA = '1234' 31*4882a593SmuzhiyunU_BOOT_IMG_DATA = 'img' 32*4882a593SmuzhiyunU_BOOT_SPL_DATA = '567' 33*4882a593SmuzhiyunBLOB_DATA = '89' 34*4882a593SmuzhiyunME_DATA = '0abcd' 35*4882a593SmuzhiyunVGA_DATA = 'vga' 36*4882a593SmuzhiyunU_BOOT_DTB_DATA = 'udtb' 37*4882a593SmuzhiyunX86_START16_DATA = 'start16' 38*4882a593SmuzhiyunU_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here' 39*4882a593SmuzhiyunFSP_DATA = 'fsp' 40*4882a593SmuzhiyunCMC_DATA = 'cmc' 41*4882a593Smuzhiyun 42*4882a593Smuzhiyunclass TestFunctional(unittest.TestCase): 43*4882a593Smuzhiyun """Functional tests for binman 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun Most of these use a sample .dts file to build an image and then check 46*4882a593Smuzhiyun that it looks correct. The sample files are in the test/ subdirectory 47*4882a593Smuzhiyun and are numbered. 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun For each entry type a very small test file is created using fixed 50*4882a593Smuzhiyun string contents. This makes it easy to test that things look right, and 51*4882a593Smuzhiyun debug problems. 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun In some cases a 'real' file must be used - these are also supplied in 54*4882a593Smuzhiyun the test/ diurectory. 55*4882a593Smuzhiyun """ 56*4882a593Smuzhiyun @classmethod 57*4882a593Smuzhiyun def setUpClass(self): 58*4882a593Smuzhiyun # Handle the case where argv[0] is 'python' 59*4882a593Smuzhiyun self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) 60*4882a593Smuzhiyun self._binman_pathname = os.path.join(self._binman_dir, 'binman') 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun # Create a temporary directory for input files 63*4882a593Smuzhiyun self._indir = tempfile.mkdtemp(prefix='binmant.') 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun # Create some test files 66*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA) 67*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA) 68*4882a593Smuzhiyun TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA) 69*4882a593Smuzhiyun TestFunctional._MakeInputFile('blobfile', BLOB_DATA) 70*4882a593Smuzhiyun TestFunctional._MakeInputFile('me.bin', ME_DATA) 71*4882a593Smuzhiyun TestFunctional._MakeInputFile('vga.bin', VGA_DATA) 72*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA) 73*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA) 74*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA) 75*4882a593Smuzhiyun TestFunctional._MakeInputFile('fsp.bin', FSP_DATA) 76*4882a593Smuzhiyun TestFunctional._MakeInputFile('cmc.bin', CMC_DATA) 77*4882a593Smuzhiyun self._output_setup = False 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun # ELF file with a '_dt_ucode_base_size' symbol 80*4882a593Smuzhiyun with open(self.TestFile('u_boot_ucode_ptr')) as fd: 81*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot', fd.read()) 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun # Intel flash descriptor file 84*4882a593Smuzhiyun with open(self.TestFile('descriptor.bin')) as fd: 85*4882a593Smuzhiyun TestFunctional._MakeInputFile('descriptor.bin', fd.read()) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun @classmethod 88*4882a593Smuzhiyun def tearDownClass(self): 89*4882a593Smuzhiyun """Remove the temporary input directory and its contents""" 90*4882a593Smuzhiyun if self._indir: 91*4882a593Smuzhiyun shutil.rmtree(self._indir) 92*4882a593Smuzhiyun self._indir = None 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun def setUp(self): 95*4882a593Smuzhiyun # Enable this to turn on debugging output 96*4882a593Smuzhiyun # tout.Init(tout.DEBUG) 97*4882a593Smuzhiyun command.test_result = None 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun def tearDown(self): 100*4882a593Smuzhiyun """Remove the temporary output directory""" 101*4882a593Smuzhiyun tools._FinaliseForTest() 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun def _RunBinman(self, *args, **kwargs): 104*4882a593Smuzhiyun """Run binman using the command line 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun Args: 107*4882a593Smuzhiyun Arguments to pass, as a list of strings 108*4882a593Smuzhiyun kwargs: Arguments to pass to Command.RunPipe() 109*4882a593Smuzhiyun """ 110*4882a593Smuzhiyun result = command.RunPipe([[self._binman_pathname] + list(args)], 111*4882a593Smuzhiyun capture=True, capture_stderr=True, raise_on_error=False) 112*4882a593Smuzhiyun if result.return_code and kwargs.get('raise_on_error', True): 113*4882a593Smuzhiyun raise Exception("Error running '%s': %s" % (' '.join(args), 114*4882a593Smuzhiyun result.stdout + result.stderr)) 115*4882a593Smuzhiyun return result 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun def _DoBinman(self, *args): 118*4882a593Smuzhiyun """Run binman using directly (in the same process) 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun Args: 121*4882a593Smuzhiyun Arguments to pass, as a list of strings 122*4882a593Smuzhiyun Returns: 123*4882a593Smuzhiyun Return value (0 for success) 124*4882a593Smuzhiyun """ 125*4882a593Smuzhiyun (options, args) = cmdline.ParseArgs(list(args)) 126*4882a593Smuzhiyun options.pager = 'binman-invalid-pager' 127*4882a593Smuzhiyun options.build_dir = self._indir 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun # For testing, you can force an increase in verbosity here 130*4882a593Smuzhiyun # options.verbosity = tout.DEBUG 131*4882a593Smuzhiyun return control.Binman(options, args) 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun def _DoTestFile(self, fname): 134*4882a593Smuzhiyun """Run binman with a given test file 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun Args: 137*4882a593Smuzhiyun fname: Device tree source filename to use (e.g. 05_simple.dts) 138*4882a593Smuzhiyun """ 139*4882a593Smuzhiyun return self._DoBinman('-p', '-I', self._indir, 140*4882a593Smuzhiyun '-d', self.TestFile(fname)) 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun def _SetupDtb(self, fname, outfile='u-boot.dtb'): 143*4882a593Smuzhiyun """Set up a new test device-tree file 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun The given file is compiled and set up as the device tree to be used 146*4882a593Smuzhiyun for ths test. 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun Args: 149*4882a593Smuzhiyun fname: Filename of .dts file to read 150*4882a593Smuzhiyun outfile: Output filename for compiled device tree binary 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun Returns: 153*4882a593Smuzhiyun Contents of device tree binary 154*4882a593Smuzhiyun """ 155*4882a593Smuzhiyun if not self._output_setup: 156*4882a593Smuzhiyun tools.PrepareOutputDir(self._indir, True) 157*4882a593Smuzhiyun self._output_setup = True 158*4882a593Smuzhiyun dtb = fdt_util.EnsureCompiled(self.TestFile(fname)) 159*4882a593Smuzhiyun with open(dtb) as fd: 160*4882a593Smuzhiyun data = fd.read() 161*4882a593Smuzhiyun TestFunctional._MakeInputFile(outfile, data) 162*4882a593Smuzhiyun return data 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun def _DoReadFileDtb(self, fname, use_real_dtb=False): 165*4882a593Smuzhiyun """Run binman and return the resulting image 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun This runs binman with a given test file and then reads the resulting 168*4882a593Smuzhiyun output file. It is a shortcut function since most tests need to do 169*4882a593Smuzhiyun these steps. 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun Raises an assertion failure if binman returns a non-zero exit code. 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun Args: 174*4882a593Smuzhiyun fname: Device tree source filename to use (e.g. 05_simple.dts) 175*4882a593Smuzhiyun use_real_dtb: True to use the test file as the contents of 176*4882a593Smuzhiyun the u-boot-dtb entry. Normally this is not needed and the 177*4882a593Smuzhiyun test contents (the U_BOOT_DTB_DATA string) can be used. 178*4882a593Smuzhiyun But in some test we need the real contents. 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun Returns: 181*4882a593Smuzhiyun Tuple: 182*4882a593Smuzhiyun Resulting image contents 183*4882a593Smuzhiyun Device tree contents 184*4882a593Smuzhiyun """ 185*4882a593Smuzhiyun dtb_data = None 186*4882a593Smuzhiyun # Use the compiled test file as the u-boot-dtb input 187*4882a593Smuzhiyun if use_real_dtb: 188*4882a593Smuzhiyun dtb_data = self._SetupDtb(fname) 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun try: 191*4882a593Smuzhiyun retcode = self._DoTestFile(fname) 192*4882a593Smuzhiyun self.assertEqual(0, retcode) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun # Find the (only) image, read it and return its contents 195*4882a593Smuzhiyun image = control.images['image'] 196*4882a593Smuzhiyun fname = tools.GetOutputFilename('image.bin') 197*4882a593Smuzhiyun self.assertTrue(os.path.exists(fname)) 198*4882a593Smuzhiyun with open(fname) as fd: 199*4882a593Smuzhiyun return fd.read(), dtb_data 200*4882a593Smuzhiyun finally: 201*4882a593Smuzhiyun # Put the test file back 202*4882a593Smuzhiyun if use_real_dtb: 203*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA) 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun def _DoReadFile(self, fname, use_real_dtb=False): 206*4882a593Smuzhiyun """Helper function which discards the device-tree binary""" 207*4882a593Smuzhiyun return self._DoReadFileDtb(fname, use_real_dtb)[0] 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun @classmethod 210*4882a593Smuzhiyun def _MakeInputFile(self, fname, contents): 211*4882a593Smuzhiyun """Create a new test input file, creating directories as needed 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun Args: 214*4882a593Smuzhiyun fname: Filenaem to create 215*4882a593Smuzhiyun contents: File contents to write in to the file 216*4882a593Smuzhiyun Returns: 217*4882a593Smuzhiyun Full pathname of file created 218*4882a593Smuzhiyun """ 219*4882a593Smuzhiyun pathname = os.path.join(self._indir, fname) 220*4882a593Smuzhiyun dirname = os.path.dirname(pathname) 221*4882a593Smuzhiyun if dirname and not os.path.exists(dirname): 222*4882a593Smuzhiyun os.makedirs(dirname) 223*4882a593Smuzhiyun with open(pathname, 'wb') as fd: 224*4882a593Smuzhiyun fd.write(contents) 225*4882a593Smuzhiyun return pathname 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun @classmethod 228*4882a593Smuzhiyun def TestFile(self, fname): 229*4882a593Smuzhiyun return os.path.join(self._binman_dir, 'test', fname) 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun def AssertInList(self, grep_list, target): 232*4882a593Smuzhiyun """Assert that at least one of a list of things is in a target 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun Args: 235*4882a593Smuzhiyun grep_list: List of strings to check 236*4882a593Smuzhiyun target: Target string 237*4882a593Smuzhiyun """ 238*4882a593Smuzhiyun for grep in grep_list: 239*4882a593Smuzhiyun if grep in target: 240*4882a593Smuzhiyun return 241*4882a593Smuzhiyun self.fail("Error: '%' not found in '%s'" % (grep_list, target)) 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun def CheckNoGaps(self, entries): 244*4882a593Smuzhiyun """Check that all entries fit together without gaps 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun Args: 247*4882a593Smuzhiyun entries: List of entries to check 248*4882a593Smuzhiyun """ 249*4882a593Smuzhiyun pos = 0 250*4882a593Smuzhiyun for entry in entries.values(): 251*4882a593Smuzhiyun self.assertEqual(pos, entry.pos) 252*4882a593Smuzhiyun pos += entry.size 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun def GetFdtLen(self, dtb): 255*4882a593Smuzhiyun """Get the totalsize field from a device tree binary 256*4882a593Smuzhiyun 257*4882a593Smuzhiyun Args: 258*4882a593Smuzhiyun dtb: Device tree binary contents 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun Returns: 261*4882a593Smuzhiyun Total size of device tree binary, from the header 262*4882a593Smuzhiyun """ 263*4882a593Smuzhiyun return struct.unpack('>L', dtb[4:8])[0] 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun def testRun(self): 266*4882a593Smuzhiyun """Test a basic run with valid args""" 267*4882a593Smuzhiyun result = self._RunBinman('-h') 268*4882a593Smuzhiyun 269*4882a593Smuzhiyun def testFullHelp(self): 270*4882a593Smuzhiyun """Test that the full help is displayed with -H""" 271*4882a593Smuzhiyun result = self._RunBinman('-H') 272*4882a593Smuzhiyun help_file = os.path.join(self._binman_dir, 'README') 273*4882a593Smuzhiyun self.assertEqual(len(result.stdout), os.path.getsize(help_file)) 274*4882a593Smuzhiyun self.assertEqual(0, len(result.stderr)) 275*4882a593Smuzhiyun self.assertEqual(0, result.return_code) 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun def testFullHelpInternal(self): 278*4882a593Smuzhiyun """Test that the full help is displayed with -H""" 279*4882a593Smuzhiyun try: 280*4882a593Smuzhiyun command.test_result = command.CommandResult() 281*4882a593Smuzhiyun result = self._DoBinman('-H') 282*4882a593Smuzhiyun help_file = os.path.join(self._binman_dir, 'README') 283*4882a593Smuzhiyun finally: 284*4882a593Smuzhiyun command.test_result = None 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun def testHelp(self): 287*4882a593Smuzhiyun """Test that the basic help is displayed with -h""" 288*4882a593Smuzhiyun result = self._RunBinman('-h') 289*4882a593Smuzhiyun self.assertTrue(len(result.stdout) > 200) 290*4882a593Smuzhiyun self.assertEqual(0, len(result.stderr)) 291*4882a593Smuzhiyun self.assertEqual(0, result.return_code) 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun # Not yet available. 294*4882a593Smuzhiyun def testBoard(self): 295*4882a593Smuzhiyun """Test that we can run it with a specific board""" 296*4882a593Smuzhiyun self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb') 297*4882a593Smuzhiyun TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA) 298*4882a593Smuzhiyun result = self._DoBinman('-b', 'sandbox') 299*4882a593Smuzhiyun self.assertEqual(0, result) 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun def testNeedBoard(self): 302*4882a593Smuzhiyun """Test that we get an error when no board ius supplied""" 303*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 304*4882a593Smuzhiyun result = self._DoBinman() 305*4882a593Smuzhiyun self.assertIn("Must provide a board to process (use -b <board>)", 306*4882a593Smuzhiyun str(e.exception)) 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun def testMissingDt(self): 309*4882a593Smuzhiyun """Test that an invalid device tree file generates an error""" 310*4882a593Smuzhiyun with self.assertRaises(Exception) as e: 311*4882a593Smuzhiyun self._RunBinman('-d', 'missing_file') 312*4882a593Smuzhiyun # We get one error from libfdt, and a different one from fdtget. 313*4882a593Smuzhiyun self.AssertInList(["Couldn't open blob from 'missing_file'", 314*4882a593Smuzhiyun 'No such file or directory'], str(e.exception)) 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun def testBrokenDt(self): 317*4882a593Smuzhiyun """Test that an invalid device tree source file generates an error 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun Since this is a source file it should be compiled and the error 320*4882a593Smuzhiyun will come from the device-tree compiler (dtc). 321*4882a593Smuzhiyun """ 322*4882a593Smuzhiyun with self.assertRaises(Exception) as e: 323*4882a593Smuzhiyun self._RunBinman('-d', self.TestFile('01_invalid.dts')) 324*4882a593Smuzhiyun self.assertIn("FATAL ERROR: Unable to parse input tree", 325*4882a593Smuzhiyun str(e.exception)) 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun def testMissingNode(self): 328*4882a593Smuzhiyun """Test that a device tree without a 'binman' node generates an error""" 329*4882a593Smuzhiyun with self.assertRaises(Exception) as e: 330*4882a593Smuzhiyun self._DoBinman('-d', self.TestFile('02_missing_node.dts')) 331*4882a593Smuzhiyun self.assertIn("does not have a 'binman' node", str(e.exception)) 332*4882a593Smuzhiyun 333*4882a593Smuzhiyun def testEmpty(self): 334*4882a593Smuzhiyun """Test that an empty binman node works OK (i.e. does nothing)""" 335*4882a593Smuzhiyun result = self._RunBinman('-d', self.TestFile('03_empty.dts')) 336*4882a593Smuzhiyun self.assertEqual(0, len(result.stderr)) 337*4882a593Smuzhiyun self.assertEqual(0, result.return_code) 338*4882a593Smuzhiyun 339*4882a593Smuzhiyun def testInvalidEntry(self): 340*4882a593Smuzhiyun """Test that an invalid entry is flagged""" 341*4882a593Smuzhiyun with self.assertRaises(Exception) as e: 342*4882a593Smuzhiyun result = self._RunBinman('-d', 343*4882a593Smuzhiyun self.TestFile('04_invalid_entry.dts')) 344*4882a593Smuzhiyun #print e.exception 345*4882a593Smuzhiyun self.assertIn("Unknown entry type 'not-a-valid-type' in node " 346*4882a593Smuzhiyun "'/binman/not-a-valid-type'", str(e.exception)) 347*4882a593Smuzhiyun 348*4882a593Smuzhiyun def testSimple(self): 349*4882a593Smuzhiyun """Test a simple binman with a single file""" 350*4882a593Smuzhiyun data = self._DoReadFile('05_simple.dts') 351*4882a593Smuzhiyun self.assertEqual(U_BOOT_DATA, data) 352*4882a593Smuzhiyun 353*4882a593Smuzhiyun def testDual(self): 354*4882a593Smuzhiyun """Test that we can handle creating two images 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun This also tests image padding. 357*4882a593Smuzhiyun """ 358*4882a593Smuzhiyun retcode = self._DoTestFile('06_dual_image.dts') 359*4882a593Smuzhiyun self.assertEqual(0, retcode) 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun image = control.images['image1'] 362*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), image._size) 363*4882a593Smuzhiyun fname = tools.GetOutputFilename('image1.bin') 364*4882a593Smuzhiyun self.assertTrue(os.path.exists(fname)) 365*4882a593Smuzhiyun with open(fname) as fd: 366*4882a593Smuzhiyun data = fd.read() 367*4882a593Smuzhiyun self.assertEqual(U_BOOT_DATA, data) 368*4882a593Smuzhiyun 369*4882a593Smuzhiyun image = control.images['image2'] 370*4882a593Smuzhiyun self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size) 371*4882a593Smuzhiyun fname = tools.GetOutputFilename('image2.bin') 372*4882a593Smuzhiyun self.assertTrue(os.path.exists(fname)) 373*4882a593Smuzhiyun with open(fname) as fd: 374*4882a593Smuzhiyun data = fd.read() 375*4882a593Smuzhiyun self.assertEqual(U_BOOT_DATA, data[3:7]) 376*4882a593Smuzhiyun self.assertEqual(chr(0) * 3, data[:3]) 377*4882a593Smuzhiyun self.assertEqual(chr(0) * 5, data[7:]) 378*4882a593Smuzhiyun 379*4882a593Smuzhiyun def testBadAlign(self): 380*4882a593Smuzhiyun """Test that an invalid alignment value is detected""" 381*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 382*4882a593Smuzhiyun self._DoTestFile('07_bad_align.dts') 383*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power " 384*4882a593Smuzhiyun "of two", str(e.exception)) 385*4882a593Smuzhiyun 386*4882a593Smuzhiyun def testPackSimple(self): 387*4882a593Smuzhiyun """Test that packing works as expected""" 388*4882a593Smuzhiyun retcode = self._DoTestFile('08_pack.dts') 389*4882a593Smuzhiyun self.assertEqual(0, retcode) 390*4882a593Smuzhiyun self.assertIn('image', control.images) 391*4882a593Smuzhiyun image = control.images['image'] 392*4882a593Smuzhiyun entries = image._entries 393*4882a593Smuzhiyun self.assertEqual(5, len(entries)) 394*4882a593Smuzhiyun 395*4882a593Smuzhiyun # First u-boot 396*4882a593Smuzhiyun self.assertIn('u-boot', entries) 397*4882a593Smuzhiyun entry = entries['u-boot'] 398*4882a593Smuzhiyun self.assertEqual(0, entry.pos) 399*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), entry.size) 400*4882a593Smuzhiyun 401*4882a593Smuzhiyun # Second u-boot, aligned to 16-byte boundary 402*4882a593Smuzhiyun self.assertIn('u-boot-align', entries) 403*4882a593Smuzhiyun entry = entries['u-boot-align'] 404*4882a593Smuzhiyun self.assertEqual(16, entry.pos) 405*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), entry.size) 406*4882a593Smuzhiyun 407*4882a593Smuzhiyun # Third u-boot, size 23 bytes 408*4882a593Smuzhiyun self.assertIn('u-boot-size', entries) 409*4882a593Smuzhiyun entry = entries['u-boot-size'] 410*4882a593Smuzhiyun self.assertEqual(20, entry.pos) 411*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), entry.contents_size) 412*4882a593Smuzhiyun self.assertEqual(23, entry.size) 413*4882a593Smuzhiyun 414*4882a593Smuzhiyun # Fourth u-boot, placed immediate after the above 415*4882a593Smuzhiyun self.assertIn('u-boot-next', entries) 416*4882a593Smuzhiyun entry = entries['u-boot-next'] 417*4882a593Smuzhiyun self.assertEqual(43, entry.pos) 418*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), entry.size) 419*4882a593Smuzhiyun 420*4882a593Smuzhiyun # Fifth u-boot, placed at a fixed position 421*4882a593Smuzhiyun self.assertIn('u-boot-fixed', entries) 422*4882a593Smuzhiyun entry = entries['u-boot-fixed'] 423*4882a593Smuzhiyun self.assertEqual(61, entry.pos) 424*4882a593Smuzhiyun self.assertEqual(len(U_BOOT_DATA), entry.size) 425*4882a593Smuzhiyun 426*4882a593Smuzhiyun self.assertEqual(65, image._size) 427*4882a593Smuzhiyun 428*4882a593Smuzhiyun def testPackExtra(self): 429*4882a593Smuzhiyun """Test that extra packing feature works as expected""" 430*4882a593Smuzhiyun retcode = self._DoTestFile('09_pack_extra.dts') 431*4882a593Smuzhiyun 432*4882a593Smuzhiyun self.assertEqual(0, retcode) 433*4882a593Smuzhiyun self.assertIn('image', control.images) 434*4882a593Smuzhiyun image = control.images['image'] 435*4882a593Smuzhiyun entries = image._entries 436*4882a593Smuzhiyun self.assertEqual(5, len(entries)) 437*4882a593Smuzhiyun 438*4882a593Smuzhiyun # First u-boot with padding before and after 439*4882a593Smuzhiyun self.assertIn('u-boot', entries) 440*4882a593Smuzhiyun entry = entries['u-boot'] 441*4882a593Smuzhiyun self.assertEqual(0, entry.pos) 442*4882a593Smuzhiyun self.assertEqual(3, entry.pad_before) 443*4882a593Smuzhiyun self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size) 444*4882a593Smuzhiyun 445*4882a593Smuzhiyun # Second u-boot has an aligned size, but it has no effect 446*4882a593Smuzhiyun self.assertIn('u-boot-align-size-nop', entries) 447*4882a593Smuzhiyun entry = entries['u-boot-align-size-nop'] 448*4882a593Smuzhiyun self.assertEqual(12, entry.pos) 449*4882a593Smuzhiyun self.assertEqual(4, entry.size) 450*4882a593Smuzhiyun 451*4882a593Smuzhiyun # Third u-boot has an aligned size too 452*4882a593Smuzhiyun self.assertIn('u-boot-align-size', entries) 453*4882a593Smuzhiyun entry = entries['u-boot-align-size'] 454*4882a593Smuzhiyun self.assertEqual(16, entry.pos) 455*4882a593Smuzhiyun self.assertEqual(32, entry.size) 456*4882a593Smuzhiyun 457*4882a593Smuzhiyun # Fourth u-boot has an aligned end 458*4882a593Smuzhiyun self.assertIn('u-boot-align-end', entries) 459*4882a593Smuzhiyun entry = entries['u-boot-align-end'] 460*4882a593Smuzhiyun self.assertEqual(48, entry.pos) 461*4882a593Smuzhiyun self.assertEqual(16, entry.size) 462*4882a593Smuzhiyun 463*4882a593Smuzhiyun # Fifth u-boot immediately afterwards 464*4882a593Smuzhiyun self.assertIn('u-boot-align-both', entries) 465*4882a593Smuzhiyun entry = entries['u-boot-align-both'] 466*4882a593Smuzhiyun self.assertEqual(64, entry.pos) 467*4882a593Smuzhiyun self.assertEqual(64, entry.size) 468*4882a593Smuzhiyun 469*4882a593Smuzhiyun self.CheckNoGaps(entries) 470*4882a593Smuzhiyun self.assertEqual(128, image._size) 471*4882a593Smuzhiyun 472*4882a593Smuzhiyun def testPackAlignPowerOf2(self): 473*4882a593Smuzhiyun """Test that invalid entry alignment is detected""" 474*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 475*4882a593Smuzhiyun self._DoTestFile('10_pack_align_power2.dts') 476*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power " 477*4882a593Smuzhiyun "of two", str(e.exception)) 478*4882a593Smuzhiyun 479*4882a593Smuzhiyun def testPackAlignSizePowerOf2(self): 480*4882a593Smuzhiyun """Test that invalid entry size alignment is detected""" 481*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 482*4882a593Smuzhiyun self._DoTestFile('11_pack_align_size_power2.dts') 483*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a " 484*4882a593Smuzhiyun "power of two", str(e.exception)) 485*4882a593Smuzhiyun 486*4882a593Smuzhiyun def testPackInvalidAlign(self): 487*4882a593Smuzhiyun """Test detection of an position that does not match its alignment""" 488*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 489*4882a593Smuzhiyun self._DoTestFile('12_pack_inv_align.dts') 490*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Position 0x5 (5) does not match " 491*4882a593Smuzhiyun "align 0x4 (4)", str(e.exception)) 492*4882a593Smuzhiyun 493*4882a593Smuzhiyun def testPackInvalidSizeAlign(self): 494*4882a593Smuzhiyun """Test that invalid entry size alignment is detected""" 495*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 496*4882a593Smuzhiyun self._DoTestFile('13_pack_inv_size_align.dts') 497*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match " 498*4882a593Smuzhiyun "align-size 0x4 (4)", str(e.exception)) 499*4882a593Smuzhiyun 500*4882a593Smuzhiyun def testPackOverlap(self): 501*4882a593Smuzhiyun """Test that overlapping regions are detected""" 502*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 503*4882a593Smuzhiyun self._DoTestFile('14_pack_overlap.dts') 504*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-align': Position 0x3 (3) overlaps " 505*4882a593Smuzhiyun "with previous entry '/binman/u-boot' ending at 0x4 (4)", 506*4882a593Smuzhiyun str(e.exception)) 507*4882a593Smuzhiyun 508*4882a593Smuzhiyun def testPackEntryOverflow(self): 509*4882a593Smuzhiyun """Test that entries that overflow their size are detected""" 510*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 511*4882a593Smuzhiyun self._DoTestFile('15_pack_overflow.dts') 512*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) " 513*4882a593Smuzhiyun "but entry size is 0x3 (3)", str(e.exception)) 514*4882a593Smuzhiyun 515*4882a593Smuzhiyun def testPackImageOverflow(self): 516*4882a593Smuzhiyun """Test that entries which overflow the image size are detected""" 517*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 518*4882a593Smuzhiyun self._DoTestFile('16_pack_image_overflow.dts') 519*4882a593Smuzhiyun self.assertIn("Image '/binman': contents size 0x4 (4) exceeds image " 520*4882a593Smuzhiyun "size 0x3 (3)", str(e.exception)) 521*4882a593Smuzhiyun 522*4882a593Smuzhiyun def testPackImageSize(self): 523*4882a593Smuzhiyun """Test that the image size can be set""" 524*4882a593Smuzhiyun retcode = self._DoTestFile('17_pack_image_size.dts') 525*4882a593Smuzhiyun self.assertEqual(0, retcode) 526*4882a593Smuzhiyun self.assertIn('image', control.images) 527*4882a593Smuzhiyun image = control.images['image'] 528*4882a593Smuzhiyun self.assertEqual(7, image._size) 529*4882a593Smuzhiyun 530*4882a593Smuzhiyun def testPackImageSizeAlign(self): 531*4882a593Smuzhiyun """Test that image size alignemnt works as expected""" 532*4882a593Smuzhiyun retcode = self._DoTestFile('18_pack_image_align.dts') 533*4882a593Smuzhiyun self.assertEqual(0, retcode) 534*4882a593Smuzhiyun self.assertIn('image', control.images) 535*4882a593Smuzhiyun image = control.images['image'] 536*4882a593Smuzhiyun self.assertEqual(16, image._size) 537*4882a593Smuzhiyun 538*4882a593Smuzhiyun def testPackInvalidImageAlign(self): 539*4882a593Smuzhiyun """Test that invalid image alignment is detected""" 540*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 541*4882a593Smuzhiyun self._DoTestFile('19_pack_inv_image_align.dts') 542*4882a593Smuzhiyun self.assertIn("Image '/binman': Size 0x7 (7) does not match " 543*4882a593Smuzhiyun "align-size 0x8 (8)", str(e.exception)) 544*4882a593Smuzhiyun 545*4882a593Smuzhiyun def testPackAlignPowerOf2(self): 546*4882a593Smuzhiyun """Test that invalid image alignment is detected""" 547*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 548*4882a593Smuzhiyun self._DoTestFile('20_pack_inv_image_align_power2.dts') 549*4882a593Smuzhiyun self.assertIn("Image '/binman': Alignment size 131 must be a power of " 550*4882a593Smuzhiyun "two", str(e.exception)) 551*4882a593Smuzhiyun 552*4882a593Smuzhiyun def testImagePadByte(self): 553*4882a593Smuzhiyun """Test that the image pad byte can be specified""" 554*4882a593Smuzhiyun data = self._DoReadFile('21_image_pad.dts') 555*4882a593Smuzhiyun self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 9) + U_BOOT_DATA, data) 556*4882a593Smuzhiyun 557*4882a593Smuzhiyun def testImageName(self): 558*4882a593Smuzhiyun """Test that image files can be named""" 559*4882a593Smuzhiyun retcode = self._DoTestFile('22_image_name.dts') 560*4882a593Smuzhiyun self.assertEqual(0, retcode) 561*4882a593Smuzhiyun image = control.images['image1'] 562*4882a593Smuzhiyun fname = tools.GetOutputFilename('test-name') 563*4882a593Smuzhiyun self.assertTrue(os.path.exists(fname)) 564*4882a593Smuzhiyun 565*4882a593Smuzhiyun image = control.images['image2'] 566*4882a593Smuzhiyun fname = tools.GetOutputFilename('test-name.xx') 567*4882a593Smuzhiyun self.assertTrue(os.path.exists(fname)) 568*4882a593Smuzhiyun 569*4882a593Smuzhiyun def testBlobFilename(self): 570*4882a593Smuzhiyun """Test that generic blobs can be provided by filename""" 571*4882a593Smuzhiyun data = self._DoReadFile('23_blob.dts') 572*4882a593Smuzhiyun self.assertEqual(BLOB_DATA, data) 573*4882a593Smuzhiyun 574*4882a593Smuzhiyun def testPackSorted(self): 575*4882a593Smuzhiyun """Test that entries can be sorted""" 576*4882a593Smuzhiyun data = self._DoReadFile('24_sorted.dts') 577*4882a593Smuzhiyun self.assertEqual(chr(0) * 5 + U_BOOT_SPL_DATA + chr(0) * 2 + 578*4882a593Smuzhiyun U_BOOT_DATA, data) 579*4882a593Smuzhiyun 580*4882a593Smuzhiyun def testPackZeroPosition(self): 581*4882a593Smuzhiyun """Test that an entry at position 0 is not given a new position""" 582*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 583*4882a593Smuzhiyun self._DoTestFile('25_pack_zero_size.dts') 584*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-spl': Position 0x0 (0) overlaps " 585*4882a593Smuzhiyun "with previous entry '/binman/u-boot' ending at 0x4 (4)", 586*4882a593Smuzhiyun str(e.exception)) 587*4882a593Smuzhiyun 588*4882a593Smuzhiyun def testPackUbootDtb(self): 589*4882a593Smuzhiyun """Test that a device tree can be added to U-Boot""" 590*4882a593Smuzhiyun data = self._DoReadFile('26_pack_u_boot_dtb.dts') 591*4882a593Smuzhiyun self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data) 592*4882a593Smuzhiyun 593*4882a593Smuzhiyun def testPackX86RomNoSize(self): 594*4882a593Smuzhiyun """Test that the end-at-4gb property requires a size property""" 595*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 596*4882a593Smuzhiyun self._DoTestFile('27_pack_4gb_no_size.dts') 597*4882a593Smuzhiyun self.assertIn("Image '/binman': Image size must be provided when " 598*4882a593Smuzhiyun "using end-at-4gb", str(e.exception)) 599*4882a593Smuzhiyun 600*4882a593Smuzhiyun def testPackX86RomOutside(self): 601*4882a593Smuzhiyun """Test that the end-at-4gb property checks for position boundaries""" 602*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 603*4882a593Smuzhiyun self._DoTestFile('28_pack_4gb_outside.dts') 604*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside " 605*4882a593Smuzhiyun "the image starting at 0xfffffff0 (4294967280)", 606*4882a593Smuzhiyun str(e.exception)) 607*4882a593Smuzhiyun 608*4882a593Smuzhiyun def testPackX86Rom(self): 609*4882a593Smuzhiyun """Test that a basic x86 ROM can be created""" 610*4882a593Smuzhiyun data = self._DoReadFile('29_x86-rom.dts') 611*4882a593Smuzhiyun self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA + 612*4882a593Smuzhiyun chr(0) * 6, data) 613*4882a593Smuzhiyun 614*4882a593Smuzhiyun def testPackX86RomMeNoDesc(self): 615*4882a593Smuzhiyun """Test that an invalid Intel descriptor entry is detected""" 616*4882a593Smuzhiyun TestFunctional._MakeInputFile('descriptor.bin', '') 617*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 618*4882a593Smuzhiyun self._DoTestFile('31_x86-rom-me.dts') 619*4882a593Smuzhiyun self.assertIn("Node '/binman/intel-descriptor': Cannot find FD " 620*4882a593Smuzhiyun "signature", str(e.exception)) 621*4882a593Smuzhiyun 622*4882a593Smuzhiyun def testPackX86RomBadDesc(self): 623*4882a593Smuzhiyun """Test that the Intel requires a descriptor entry""" 624*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 625*4882a593Smuzhiyun self._DoTestFile('30_x86-rom-me-no-desc.dts') 626*4882a593Smuzhiyun self.assertIn("Node '/binman/intel-me': No position set with " 627*4882a593Smuzhiyun "pos-unset: should another entry provide this correct " 628*4882a593Smuzhiyun "position?", str(e.exception)) 629*4882a593Smuzhiyun 630*4882a593Smuzhiyun def testPackX86RomMe(self): 631*4882a593Smuzhiyun """Test that an x86 ROM with an ME region can be created""" 632*4882a593Smuzhiyun data = self._DoReadFile('31_x86-rom-me.dts') 633*4882a593Smuzhiyun self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)]) 634*4882a593Smuzhiyun 635*4882a593Smuzhiyun def testPackVga(self): 636*4882a593Smuzhiyun """Test that an image with a VGA binary can be created""" 637*4882a593Smuzhiyun data = self._DoReadFile('32_intel-vga.dts') 638*4882a593Smuzhiyun self.assertEqual(VGA_DATA, data[:len(VGA_DATA)]) 639*4882a593Smuzhiyun 640*4882a593Smuzhiyun def testPackStart16(self): 641*4882a593Smuzhiyun """Test that an image with an x86 start16 region can be created""" 642*4882a593Smuzhiyun data = self._DoReadFile('33_x86-start16.dts') 643*4882a593Smuzhiyun self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)]) 644*4882a593Smuzhiyun 645*4882a593Smuzhiyun def testPackUbootMicrocode(self): 646*4882a593Smuzhiyun """Test that x86 microcode can be handled correctly 647*4882a593Smuzhiyun 648*4882a593Smuzhiyun We expect to see the following in the image, in order: 649*4882a593Smuzhiyun u-boot-nodtb.bin with a microcode pointer inserted at the correct 650*4882a593Smuzhiyun place 651*4882a593Smuzhiyun u-boot.dtb with the microcode removed 652*4882a593Smuzhiyun the microcode 653*4882a593Smuzhiyun """ 654*4882a593Smuzhiyun data = self._DoReadFile('34_x86_ucode.dts', True) 655*4882a593Smuzhiyun 656*4882a593Smuzhiyun # Now check the device tree has no microcode 657*4882a593Smuzhiyun second = data[len(U_BOOT_NODTB_DATA):] 658*4882a593Smuzhiyun fname = tools.GetOutputFilename('test.dtb') 659*4882a593Smuzhiyun with open(fname, 'wb') as fd: 660*4882a593Smuzhiyun fd.write(second) 661*4882a593Smuzhiyun dtb = fdt.FdtScan(fname) 662*4882a593Smuzhiyun ucode = dtb.GetNode('/microcode') 663*4882a593Smuzhiyun self.assertTrue(ucode) 664*4882a593Smuzhiyun for node in ucode.subnodes: 665*4882a593Smuzhiyun self.assertFalse(node.props.get('data')) 666*4882a593Smuzhiyun 667*4882a593Smuzhiyun fdt_len = self.GetFdtLen(second) 668*4882a593Smuzhiyun third = second[fdt_len:] 669*4882a593Smuzhiyun 670*4882a593Smuzhiyun # Check that the microcode appears immediately after the Fdt 671*4882a593Smuzhiyun # This matches the concatenation of the data properties in 672*4882a593Smuzhiyun # the /microcode/update@xxx nodes in x86_ucode.dts. 673*4882a593Smuzhiyun ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000, 674*4882a593Smuzhiyun 0x78235609) 675*4882a593Smuzhiyun self.assertEqual(ucode_data, third[:len(ucode_data)]) 676*4882a593Smuzhiyun ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len 677*4882a593Smuzhiyun 678*4882a593Smuzhiyun # Check that the microcode pointer was inserted. It should match the 679*4882a593Smuzhiyun # expected position and size 680*4882a593Smuzhiyun pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, 681*4882a593Smuzhiyun len(ucode_data)) 682*4882a593Smuzhiyun first = data[:len(U_BOOT_NODTB_DATA)] 683*4882a593Smuzhiyun self.assertEqual('nodtb with microcode' + pos_and_size + 684*4882a593Smuzhiyun ' somewhere in here', first) 685*4882a593Smuzhiyun 686*4882a593Smuzhiyun def _RunPackUbootSingleMicrocode(self): 687*4882a593Smuzhiyun """Test that x86 microcode can be handled correctly 688*4882a593Smuzhiyun 689*4882a593Smuzhiyun We expect to see the following in the image, in order: 690*4882a593Smuzhiyun u-boot-nodtb.bin with a microcode pointer inserted at the correct 691*4882a593Smuzhiyun place 692*4882a593Smuzhiyun u-boot.dtb with the microcode 693*4882a593Smuzhiyun an empty microcode region 694*4882a593Smuzhiyun """ 695*4882a593Smuzhiyun # We need the libfdt library to run this test since only that allows 696*4882a593Smuzhiyun # finding the offset of a property. This is required by 697*4882a593Smuzhiyun # Entry_u_boot_dtb_with_ucode.ObtainContents(). 698*4882a593Smuzhiyun data = self._DoReadFile('35_x86_single_ucode.dts', True) 699*4882a593Smuzhiyun 700*4882a593Smuzhiyun second = data[len(U_BOOT_NODTB_DATA):] 701*4882a593Smuzhiyun 702*4882a593Smuzhiyun fdt_len = self.GetFdtLen(second) 703*4882a593Smuzhiyun third = second[fdt_len:] 704*4882a593Smuzhiyun second = second[:fdt_len] 705*4882a593Smuzhiyun 706*4882a593Smuzhiyun ucode_data = struct.pack('>2L', 0x12345678, 0x12345679) 707*4882a593Smuzhiyun self.assertIn(ucode_data, second) 708*4882a593Smuzhiyun ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA) 709*4882a593Smuzhiyun 710*4882a593Smuzhiyun # Check that the microcode pointer was inserted. It should match the 711*4882a593Smuzhiyun # expected position and size 712*4882a593Smuzhiyun pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, 713*4882a593Smuzhiyun len(ucode_data)) 714*4882a593Smuzhiyun first = data[:len(U_BOOT_NODTB_DATA)] 715*4882a593Smuzhiyun self.assertEqual('nodtb with microcode' + pos_and_size + 716*4882a593Smuzhiyun ' somewhere in here', first) 717*4882a593Smuzhiyun 718*4882a593Smuzhiyun def testPackUbootSingleMicrocode(self): 719*4882a593Smuzhiyun """Test that x86 microcode can be handled correctly with fdt_normal. 720*4882a593Smuzhiyun """ 721*4882a593Smuzhiyun self._RunPackUbootSingleMicrocode() 722*4882a593Smuzhiyun 723*4882a593Smuzhiyun def testUBootImg(self): 724*4882a593Smuzhiyun """Test that u-boot.img can be put in a file""" 725*4882a593Smuzhiyun data = self._DoReadFile('36_u_boot_img.dts') 726*4882a593Smuzhiyun self.assertEqual(U_BOOT_IMG_DATA, data) 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun def testNoMicrocode(self): 729*4882a593Smuzhiyun """Test that a missing microcode region is detected""" 730*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 731*4882a593Smuzhiyun self._DoReadFile('37_x86_no_ucode.dts', True) 732*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode " 733*4882a593Smuzhiyun "node found in ", str(e.exception)) 734*4882a593Smuzhiyun 735*4882a593Smuzhiyun def testMicrocodeWithoutNode(self): 736*4882a593Smuzhiyun """Test that a missing u-boot-dtb-with-ucode node is detected""" 737*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 738*4882a593Smuzhiyun self._DoReadFile('38_x86_ucode_missing_node.dts', True) 739*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " 740*4882a593Smuzhiyun "microcode region u-boot-dtb-with-ucode", str(e.exception)) 741*4882a593Smuzhiyun 742*4882a593Smuzhiyun def testMicrocodeWithoutNode2(self): 743*4882a593Smuzhiyun """Test that a missing u-boot-ucode node is detected""" 744*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 745*4882a593Smuzhiyun self._DoReadFile('39_x86_ucode_missing_node2.dts', True) 746*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " 747*4882a593Smuzhiyun "microcode region u-boot-ucode", str(e.exception)) 748*4882a593Smuzhiyun 749*4882a593Smuzhiyun def testMicrocodeWithoutPtrInElf(self): 750*4882a593Smuzhiyun """Test that a U-Boot binary without the microcode symbol is detected""" 751*4882a593Smuzhiyun # ELF file without a '_dt_ucode_base_size' symbol 752*4882a593Smuzhiyun try: 753*4882a593Smuzhiyun with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: 754*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot', fd.read()) 755*4882a593Smuzhiyun 756*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 757*4882a593Smuzhiyun self._RunPackUbootSingleMicrocode() 758*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate " 759*4882a593Smuzhiyun "_dt_ucode_base_size symbol in u-boot", str(e.exception)) 760*4882a593Smuzhiyun 761*4882a593Smuzhiyun finally: 762*4882a593Smuzhiyun # Put the original file back 763*4882a593Smuzhiyun with open(self.TestFile('u_boot_ucode_ptr')) as fd: 764*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot', fd.read()) 765*4882a593Smuzhiyun 766*4882a593Smuzhiyun def testMicrocodeNotInImage(self): 767*4882a593Smuzhiyun """Test that microcode must be placed within the image""" 768*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 769*4882a593Smuzhiyun self._DoReadFile('40_x86_ucode_not_in_image.dts', True) 770*4882a593Smuzhiyun self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode " 771*4882a593Smuzhiyun "pointer _dt_ucode_base_size at fffffe14 is outside the " 772*4882a593Smuzhiyun "image ranging from 00000000 to 0000002e", str(e.exception)) 773*4882a593Smuzhiyun 774*4882a593Smuzhiyun def testWithoutMicrocode(self): 775*4882a593Smuzhiyun """Test that we can cope with an image without microcode (e.g. qemu)""" 776*4882a593Smuzhiyun with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: 777*4882a593Smuzhiyun TestFunctional._MakeInputFile('u-boot', fd.read()) 778*4882a593Smuzhiyun data, dtb = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) 779*4882a593Smuzhiyun 780*4882a593Smuzhiyun # Now check the device tree has no microcode 781*4882a593Smuzhiyun self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)]) 782*4882a593Smuzhiyun second = data[len(U_BOOT_NODTB_DATA):] 783*4882a593Smuzhiyun 784*4882a593Smuzhiyun fdt_len = self.GetFdtLen(second) 785*4882a593Smuzhiyun self.assertEqual(dtb, second[:fdt_len]) 786*4882a593Smuzhiyun 787*4882a593Smuzhiyun used_len = len(U_BOOT_NODTB_DATA) + fdt_len 788*4882a593Smuzhiyun third = data[used_len:] 789*4882a593Smuzhiyun self.assertEqual(chr(0) * (0x200 - used_len), third) 790*4882a593Smuzhiyun 791*4882a593Smuzhiyun def testUnknownPosSize(self): 792*4882a593Smuzhiyun """Test that microcode must be placed within the image""" 793*4882a593Smuzhiyun with self.assertRaises(ValueError) as e: 794*4882a593Smuzhiyun self._DoReadFile('41_unknown_pos_size.dts', True) 795*4882a593Smuzhiyun self.assertIn("Image '/binman': Unable to set pos/size for unknown " 796*4882a593Smuzhiyun "entry 'invalid-entry'", str(e.exception)) 797*4882a593Smuzhiyun 798*4882a593Smuzhiyun def testPackFsp(self): 799*4882a593Smuzhiyun """Test that an image with a FSP binary can be created""" 800*4882a593Smuzhiyun data = self._DoReadFile('42_intel-fsp.dts') 801*4882a593Smuzhiyun self.assertEqual(FSP_DATA, data[:len(FSP_DATA)]) 802*4882a593Smuzhiyun 803*4882a593Smuzhiyun def testPackCmc(self): 804*4882a593Smuzhiyun """Test that an image with a FSP binary can be created""" 805*4882a593Smuzhiyun data = self._DoReadFile('43_intel-cmc.dts') 806*4882a593Smuzhiyun self.assertEqual(CMC_DATA, data[:len(CMC_DATA)]) 807