def boot_linux(self, rootfs=None, bootargs=""): """Boots the RPi's OS. :param rootfs: Indicates the rootsfs image path if needs to be loaded (parameter to be used at later point), defaults to None. :type rootfs: NA :param bootargs: Indicates the boot parameters to be specified if any (parameter to be used at later point), defaults to empty string "". :type bootargs: string """ common.print_bold("\n===== Booting linux for %s =====" % self.model) self.sendline("fdt addr $fdt_addr") self.expect(self.uprompt) self.sendline("fdt get value bcm_bootargs /chosen bootargs") self.expect(self.uprompt) self.sendline('setenv bootargs "$bcm_bootargs %s"' % bootargs) self.expect(self.uprompt) self.sendline( "setenv bootcmd 'fatload mmc 0 ${kernel_addr_r} %s; bootm ${kernel_addr_r} - ${fdt_addr}; booti ${kernel_addr_r} - ${fdt_addr}'" % getattr(self, "kernel_file", "uImage")) self.expect(self.uprompt) self.sendline("saveenv") self.expect(self.uprompt) self.sendline("boot") # Linux handles serial better ? self.delaybetweenchar = None
def flash_uboot(self, uboot): """Flash the Raspberry pi board with the Universal Bootloader image. In this case it's flashing the vfat partition of the bootload. Need to have that image u-boot and serial turned on via dtoverlay for things to work after flashing. :param uboot: Indicates the absolute location of the file to be used to flash. :type uboot: string """ common.print_bold("\n===== Flashing bootloader (and u-boot) =====\n") filename = self.prepare_file(uboot) size = self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.sendline("mmc part") # get offset of ext (83) partition after a fat (0c) partition self.expect(r"\r\n\s+\d+\s+(\d+)\s+(\d+).*0c( Boot)?\r\n") start = hex(int(self.match.groups()[0])) if int(size) != int(self.match.groups()[1]) * 512: raise Exception("Partition size does not match, refusing to flash") self.expect(self.uprompt) count = hex(int(size / 512)) self.sendline("mmc erase %s %s" % (start, count)) self.expect(self.uprompt) self.sendline("mmc write %s %s %s" % (self.uboot_ddr_addr, start, count)) self.expect(self.uprompt, timeout=120) self.reset() self.wait_for_boot() self.setup_uboot_network()
def boot_linux(self, rootfs=None, bootargs=""): """This method boots Qcom Akronite board. :param rootfs: Indicates the rootsfs image path if needs to be loaded (parameter to be used at later point), defaults to None. :type rootfs: NA :param bootargs: Indicates the boot parameters to be specified if any (parameter to be used at later point), defaults to empty string "". :type bootargs: string """ common.print_bold("\n===== Booting linux for %s =====" % self.model) self.reset() self.wait_for_boot() self.sendline("setenv bootcmd bootipq") self.expect(self.uprompt) self.sendline("saveenv") self.expect(self.uprompt) self.sendline("print") self.expect(self.uprompt) self.sendline('run bootcmd') # if run isn't support, we just reset u-boot and # let the bootcmd run that way try: self.expect('Unknown command', timeout=5) except: pass else: self.sendline('reset')
def flash_meta(self, META_BUILD, wan, lan): ''' A meta image contains several components wrapped up into one file. Here we flash a meta image onto the board. ''' common.print_bold("\n===== Flashing meta =====\n") filename = self.prepare_file(META_BUILD) self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) # probe SPI flash incase this is a NOR boot meta if self.model not in ("dk01", "dk04"): self.sendline('sf probe') self.expect('sf probe') self.expect(self.uprompt) self.sendline( 'machid=%s && imgaddr=%s && source $imgaddr:script && echo DONE' % (self.machid, self.uboot_ddr_addr)) self.expect('DONE') try: self.expect("Can't find 'script' FIT subimage", timeout=5) except: pass else: self.sendline( 'machid=%s && imgaddr=%s && source $imgaddr:SCRIPT && echo DONE' % (self.machid, self.uboot_ddr_addr)) self.expect('DONE') self.expect('DONE', timeout=400) self.expect(self.uprompt) # reboot incase partitions changed self.reset() self.wait_for_boot() self.setup_uboot_network()
def filter_station_config(boardfarm_config, board_type=None, board_names=[], board_features=[], board_filter=None): ''' From the boardfarm config, return a list of board names that match filter criteria. ''' result = [] if board_type: print_bold("Selecting board from board type = %s" % board_type) possible_names = boardfarm_config if board_names: print("Board names = %s" % board_names) # Allow selection only from given set of board names possible_names = set(boardfarm_config) & set(board_names) for b in possible_names: if len(board_names) != 1 and \ 'available_for_autotests' in boardfarm_config[b] and \ boardfarm_config[b]['available_for_autotests'] == False: # Skip this board continue if board_features != []: if 'feature' not in boardfarm_config[b]: continue features = boardfarm_config[b]['feature'] if 'devices' in boardfarm_config[b]: seen_names = [] for d in boardfarm_config[b]['devices']: if 'feature' in d: # since we only connect to one type of device # we need to ignore the features on the other ones # even though they should be the same if d['name'] in seen_names: continue seen_names.append(d['name']) if type(d['feature']) in (str, six.text_type): d['feature'] = [d['feature']] features.extend(x for x in d['feature'] if x not in features) if type(features) in (str, six.text_type): features = [features] if set(board_features) != set(board_features) & set(features): continue for t in board_type: if boardfarm_config[b]['board_type'].lower() == t.lower(): if board_filter: if filter_boards(boardfarm_config[b], board_filter, b): result.append(b) else: result.append(b) else: if board_names: result = board_names return result
def parse_and_add_results(cls, prefix=""): name = prefix + getattr(cls, "name", cls.__class__.__name__) grade = getattr(cls, "result_grade", None) try: if hasattr(cls, "elapsed_time"): elapsed_time = getattr(cls, "elapsed_time") else: start_time = getattr(cls, "start_time") stop_time = getattr(cls, "stop_time") elapsed_time = stop_time - start_time except Exception as error: print(error) elapsed_time = 0 unexpected = None if "_source" in golden: if name + "-result" in golden["_source"]: if golden["_source"][name + "-result"] != grade: unexpected = True else: unexpected = False if grade == "Unexp OK" or (grade == "OK" and unexpected is True): grade = "Unexp OK" full_results["unexpected_pass"] += 1 elif grade == "Exp FAIL" or (grade == "FAIL" and unexpected is False): grade = "Exp FAIL" full_results["unexpected_fail"] += 1 elif grade == "OK": full_results["tests_pass"] += 1 elif grade == "FAIL": full_results["tests_fail"] += 1 elif grade == "TD FAIL": full_results["tests_teardown_fail"] += 1 elif grade == "CC FAIL": full_results["tests_contingency_fail"] += 1 elif grade == "SKIP" or grade is None: full_results["tests_skip"] += 1 message = getattr(cls, "result_message", None) if message is None: try: message = cls.__doc__.split("\n")[0] except Exception as error: print(error) message = "Missing description of class (no docstring)" print_bold("WARN: Please add docstring to %s." % cls) long_message = getattr(cls, "long_result_message", "") full_results["test_results"].append({ "name": name, "message": message, "long_message": long_message, "grade": grade, "elapsed_time": elapsed_time, })
def parse_and_add_results(cls, prefix=""): name = prefix + getattr(cls, 'name', cls.__class__.__name__) grade = getattr(cls, 'result_grade', None) try: if hasattr(cls, 'elapsed_time'): elapsed_time = getattr(cls, 'elapsed_time') else: start_time = getattr(cls, 'start_time') stop_time = getattr(cls, 'stop_time') elapsed_time = stop_time - start_time except: elapsed_time = 0 unexpected = None if '_source' in golden: if name + "-result" in golden['_source']: if golden['_source'][name + "-result"] != grade: unexpected = True else: unexpected = False if grade == "Unexp OK" or (grade == "OK" and unexpected == True): grade = "Unexp OK" full_results['unexpected_pass'] += 1 elif grade == "Exp FAIL" or (grade == "FAIL" and unexpected == False): grade = "Exp FAIL" full_results['unexpected_fail'] += 1 elif grade == "OK": full_results['tests_pass'] += 1 elif grade == "FAIL": full_results['tests_fail'] += 1 elif grade == "TD FAIL": full_results['tests_teardown_fail'] += 1 elif grade == "CC FAIL": full_results['tests_contingency_fail'] += 1 elif grade == "SKIP" or grade is None: full_results['tests_skip'] += 1 message = getattr(cls, 'result_message', None) if message is None: try: message = cls.__doc__.split('\n')[0] except: message = "Missing description of class (no docstring)" print_bold("WARN: Please add docstring to %s." % cls) long_message = getattr(cls, 'long_result_message', "") full_results['test_results'].append({ "name": name, "message": message, "long_message": long_message, "grade": grade, "elapsed_time": elapsed_time })
def flash_linux(self, KERNEL): """Flash the Qcom Akronite board by copying file to the board using TFTP protocol. :param KERNEL: Indicates the absoulte location of the file to be used to flash. :type KERNEL: string """ common.print_bold("\n===== Flashing linux =====\n") self.prepare_file(KERNEL) raise Exception("Kernel is in UBI rootfs, not separate")
def runTest(self): """Perform concurrent iperf connections.""" board = self.dev.board wan = self.dev.wan lan = self.dev.lan wan_ip = wan.get_interface_ipaddr(wan.iface_dut) wan.sendline("iperf -s -l 1M -w 1M") wan.expect("Server listening on ") board.collect_stats(stats=["mpstat"]) time = 10 cmd = "iperf -R -c %s -P %s -t 10 -N -w 1M -l 1M | grep SUM" # prime the pipes... lan.sendline(cmd % (wan_ip, 4)) lan.expect(prompt) prev_failed = 0 for con_conn in range(32, 513, 16): try: tstart = datetime.now() lan.sendline(cmd % (wan_ip, con_conn)) failed_cons = 0 while (datetime.now() - tstart).seconds < (time * 2): timeout = (time * 2) - (datetime.now() - tstart).seconds if 0 == lan.expect( ["write failed: Connection reset by peer"] + prompt, timeout=timeout, ): failed_cons += 1 else: break print_bold("For iperf with %s connections, %s failed...." % (con_conn, failed_cons)) lan.expect(".*") wan.expect(".*") board.touch() prev_conn = con_conn prev_failed = failed_cons if con_conn == 512: self.result_message = ( "iPerf Concurrent passed 512 connections (failed conns = %s)" % failed_cons) except Exception: self.result_message = ( "iPerf Concurrent Connections failed entirely at %s (failed conns = %s)" % (prev_conn, prev_failed)) break print(self.result_message) self.recover()
def flash_linux(self, KERNEL): """Flash the Qcom Akronite board by copying file to the board. :param KERNEL: Indicates the absolute location of the file to be used to flash. :type KERNEL: string """ common.print_bold("\n===== Flashing linux =====\n") filename = self.prepare_file(KERNEL) size = self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.spi_flash_bin("0x0062b0000", size, self.uboot_ddr_addr, "0x400000")
def flash_rootfs(self, ROOTFS): """Flash the Qcom Akronite board with the ROOTFS (which in general is a patch update on the firmware). :param ROOTFS: Indicates the absolute location of the file to be used to flash. :type ROOTFS: string """ common.print_bold("\n===== Flashing rootfs =====\n") filename = self.prepare_file(ROOTFS) self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.nand_flash_bin(self.rootfs_addr, self.rootfs_size, self.uboot_ddr_addr)
def flash_linux(self, KERNEL): """This method flashes the marvell board by copying file to the board. :param KERNEL: Indicates the absoulte location of the file to be used to flash. :type KERNEL: string """ common.print_bold("\n===== Flashing linux =====\n") filename = self.prepare_file(KERNEL) self.sendline('setenv firmwareName %s' % filename) self.expect(self.uprompt) self.sendline('run update_both_images') self.expect(self.uprompt, timeout=90)
def flash_linux(self, KERNEL): """This method flashes the Qcom Dakota board by copying file to the board. :param KERNEL: Indicates the absoulte location of the file to be used to flash. :type KERNEL: string """ common.print_bold("\n===== Flashing linux =====\n") filename = self.prepare_file(KERNEL) size = self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.spi_flash_bin(self.kernel_addr, size, self.uboot_ddr_addr, self.kernel_size)
def boot_linux(self, rootfs=None, bootargs=""): common.print_bold("\n===== Booting linux for %s =====" % self.model) if self.model == "ap135-nand": self.sendline('setenv bootcmd nboot 0x81000000 0 0x100000') self.expect(self.uprompt) else: self.sendline("setenv bootcmd 'bootm %s'" % self.kernel_addr) self.expect(self.uprompt) if self.saveenv_safe: self.sendline("saveenv") self.expect(self.uprompt) self.sendline("print") self.expect(self.uprompt) self.sendline("boot")
def flash_rootfs(self, ROOTFS): """This method flashes the Raspberry pi board with the ROOTFS (which in general is a patch update on the firmware). :param ROOTFS: Indicates the absolute location of the file to be used to flash. :type ROOTFS: string """ common.print_bold("\n===== Flashing rootfs =====\n") filename = self.prepare_file(ROOTFS) size = self.tftp_get_file_uboot(self.uboot_ddr_addr, filename, timeout=220) self.sendline('mmc part') # get offset of ext (83) partition after a fat (0c) partition self.expect(r'0c( Boot)?\r\n\s+\d+\s+(\d+)\s+(\d+).*83\r\n') start = hex(int(self.match.groups()[-2])) sectors = int(self.match.groups()[-1]) self.expect(self.uprompt) # increase partition size if required if (int(size) > (sectors * 512)): self.sendline("mmc read %s 0 1" % self.uboot_ddr_addr) self.expect(self.uprompt) gp2_sz = int(self.uboot_ddr_addr, 16) + int("0x1da", 16) self.sendline("mm 0x%08x" % gp2_sz) self.expect("%08x: %08x ?" % (gp2_sz, sectors)) # pad 100M self.sendline('0x%08x' % int((int(size) + 104857600) / 512)) self.sendcontrol('c') self.sendcontrol('c') self.expect(self.uprompt) self.sendline('echo FOO') self.expect_exact('echo FOO') self.expect_exact('FOO') self.expect(self.uprompt) self.sendline("mmc write %s 0 1" % self.uboot_ddr_addr) self.expect(self.uprompt) self.sendline('mmc rescan') self.expect(self.uprompt) self.sendline('mmc part') self.expect(self.uprompt) count = hex(int(size / 512)) self.sendline('mmc erase %s %s' % (start, count)) self.expect(self.uprompt) self.sendline('mmc write %s %s %s' % (self.uboot_ddr_addr, start, count)) self.expect_exact('mmc write %s %s %s' % (self.uboot_ddr_addr, start, count)) self.expect(self.uprompt, timeout=480)
def flash_linux(self, KERNEL): """This method flashes the Raspberry pi board with a file downloaded using TFTP protocol. :param KERNEL: Indicates the absoulte location of the file to be used to flash. :type KERNEL: string """ common.print_bold("\n===== Flashing linux =====\n") filename = self.prepare_file(KERNEL) self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.kernel_file = os.path.basename(KERNEL) self.sendline('fatwrite mmc 0 %s %s $filesize' % (self.kernel_file, self.uboot_ddr_addr)) self.expect(self.uprompt)
def flash_uboot(self, uboot): """Flash the Qcom Akronite board with the Universal Bootloader image. :param uboot: Indicates the absolute location of the file to be used to flash. :type uboot: string """ common.print_bold("\n===== Flashing u-boot =====\n") filename = self.prepare_file(uboot) self.tftp_get_file_uboot(self.uboot_ddr_addr, filename) self.sendline('ipq_nand sbl') self.expect(self.uprompt) self.nand_flash_bin(self.uboot_addr, self.uboot_size, self.uboot_ddr_addr) self.reset() self.wait_for_boot() self.setup_uboot_network()
def boot_linux_ramboot(self): """This method flashes the linux from initramfs. initramfs is a complete set of directories that you would find on a normal root filesystem. """ common.print_bold("\n===== Booting linux (ramboot) for %s =====" % self.model) bootargs = 'console=ttyMSM0,115200 clk_ignore_unused norootfssplit mem=256M %s' % self.get_safe_mtdparts( ) if self.boot_dbg: bootargs += " dyndbg=\"module %s +p\"" % self.boot_dbg self.sendline("setenv bootargs '%s'" % bootargs) self.expect(self.uprompt) self.sendline('set fdt_high 0x85000000') self.expect(self.uprompt) self.sendline("bootm %s" % self.uboot_ddr_addr) self.expect("Loading Device Tree to") self.rambooted = True
def flash_linux(self, KERNEL): common.print_bold("\n===== Flashing linux =====\n") filename = self.prepare_file(KERNEL) self.tftp_get_file_uboot("0x82060000", filename) if self.model == "ap135-nand": self.sendline('nand erase 0x100000 $filesize') self.expect('OK') self.expect(self.uprompt) self.sendline('nand write.jffs2 0x82060000 0x100000 $filesize') self.expect('OK') self.expect(self.uprompt) return self.sendline('erase %s +$filesize' % self.kernel_addr) self.expect('Erased .* sectors', timeout=120) self.expect(self.uprompt) self.sendline('protect off all') self.expect(self.uprompt) self.sendline('cp.b $fileaddr %s $filesize' % self.kernel_addr) self.expect('done', timeout=60) self.sendline('cmp.b $fileaddr %s $filesize' % self.kernel_addr) self.expect('Total of .* bytes were the same') self.expect(self.uprompt)
def collect_stats(self, stats=None): if stats is None: stats = [] pp = self.get_pp_dev() self.stats = [] self.failed_stats = {} for stat in stats: if "mpstat" in stat: for i in range(5): try: pp.sendcontrol("c") pp.sendline( "kill `ps | grep mpstat | grep -v grep | awk '{print $1}'`" ) pp.expect_exact( "kill `ps | grep mpstat | grep -v grep | awk '{print $1}'`" ) pp.expect(pp.prompt) break except Exception: pp.sendcontrol("d") pp = self.get_pp_dev() if i == 4: print_bold("FAILED TO KILL MPSTAT!") pp.sendcontrol("c") pp.sendline("mpstat -P ALL 5 > %s/mpstat &" % self.tmpdir) if 0 == pp.expect(["mpstat: not found"] + pp.prompt): self.failed_stats["mpstat"] = float("nan") continue elif 0 == pp.expect(["mpstat: not found", pexpect.TIMEOUT], timeout=4): self.failed_stats["mpstat"] = float("nan") continue pp.sendline("ps | grep mpstat") self.stats.append(stat)
def boot_linux(self, rootfs=None, bootargs=""): """Boot Qcom Akronite board. :param rootfs: Indicates the rootsfs image path if needs to be loaded (parameter to be used at later point), defaults to None. :type rootfs: NA :param bootargs: Indicates the boot parameters to be specified if any (parameter to be used at later point), defaults to empty string "". :type bootargs: string """ common.print_bold("\n===== Booting linux for %s =====" % self.model) self.reset() self.wait_for_boot() self.sendline("set bootargs 'console=ttyMSM0,115200'") self.expect(self.uprompt) self.sendline("set fsbootargs 'rootfstype=squashfs,jffs2'") self.expect(self.uprompt) self.sendline('set bootcmd bootipq') self.expect(self.uprompt) self.sendline("saveenv") self.expect(self.uprompt) self.sendline("print") self.expect(self.uprompt) self.sendline('run bootcmd')
def collect_stats(self, stats=[]): pp = self.get_pp_dev() self.stats = [] self.failed_stats = {} for stat in stats: if 'mpstat' in stat: for i in range(5): try: pp.sendcontrol('c') pp.sendline( "kill `ps | grep mpstat | grep -v grep | awk '{print $1}'`" ) pp.expect_exact( "kill `ps | grep mpstat | grep -v grep | awk '{print $1}'`" ) pp.expect(pp.prompt) break except: pp.sendcontrol('d') pp = self.get_pp_dev() if i == 4: print_bold("FAILED TO KILL MPSTAT!") pp.sendcontrol('c') pass pp.sendline('mpstat -P ALL 5 > %s/mpstat &' % self.tmpdir) if 0 == pp.expect(['mpstat: not found'] + pp.prompt): self.failed_stats['mpstat'] = float('nan') continue elif 0 == pp.expect(['mpstat: not found', pexpect.TIMEOUT], timeout=4): self.failed_stats['mpstat'] = float('nan') continue pp.sendline('ps | grep mpstat') self.stats.append(stat)
def filter_station_config( boardfarm_config, board_type=None, board_names=[], board_features=[], board_filter=None, ): """ From the boardfarm config, return a list of board names that match filter criteria. """ result = [] if board_type: print_bold("Selecting board from board type = %s" % board_type) possible_names = boardfarm_config if board_names: logger.info("Board names = %s" % board_names) # Allow selection only from given set of board names possible_names = set(boardfarm_config) & set(board_names) for b in possible_names: if b == "_redirect": continue if (len(board_names) != 1 and "available_for_autotests" in boardfarm_config[b] and boardfarm_config[b]["available_for_autotests"] == False): # Skip this board continue if board_features != []: if "feature" not in boardfarm_config[b]: continue features = boardfarm_config[b]["feature"] if "devices" in boardfarm_config[b]: seen_names = [] for d in boardfarm_config[b]["devices"]: if "feature" in d: # since we only connect to one type of device # we need to ignore the features on the other ones # even though they should be the same if d["name"] in seen_names: continue seen_names.append(d["name"]) if type(d["feature"]) in (str, six.text_type): d["feature"] = [d["feature"]] features.extend(x for x in d["feature"] if x not in features) if type(features) in (str, six.text_type): features = [features] if set(board_features) != set(board_features) & set(features): continue for t in board_type: if boardfarm_config[b]["board_type"].lower() == t.lower(): if board_filter: if filter_boards(boardfarm_config[b], board_filter, b): result.append(b) else: result.append(b) else: if board_names: result = board_names return result
def boot_linux(self, rootfs=None, bootargs=None): common.print_bold("\n===== Booting linux for %s =====" % self.model) self.switch_to_mode(MODE_DISABLED) self.sendline('npcpu start') self.sendline('bootkernel -c %kernel_cmd_line%') self.delaybetweenchar = None