Example #1
0
def main():
    # noinspection PyTypeChecker
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--bitfile", help="The bitfile to load", type=abspath_arg)
    parser.add_argument("--ltxfile", help="The LTX file to use", type=abspath_arg)
    parser.add_argument("--bios", help="The machine-mode program to load", type=abspath_arg)
    parser.add_argument("--kernel", help="The supervisor-mode program to load", type=abspath_arg)
    parser.add_argument("--kernel-debug-file", help="Debug info file for the kernel", type=abspath_arg)
    parser.add_argument("--gdb", default=shutil.which("gdb") or "gdb", help="Path to GDB binary", type=Path)
    parser.add_argument("--openocd", default=shutil.which("openocd") or "openocd", help="Path to openocd binary",
                        type=abspath_arg)
    parser.add_argument("--num-cores", type=int, default=1, help="Number of harts on bitstream")
    parser.add_argument("--test-command", action='append',
                        help="Run a command non-interactively before possibly opening a console")
    parser.add_argument("--test-timeout", type=int, default=60 * 60, help="Timeout for the test command")
    parser.add_argument("--pretend", help="Don't actually run the commands just show what would happen",
                        action="store_true")
    parser.add_argument("action", choices=["all", "bitfile", "boot", "console"],
                        default="all", nargs=argparse.OPTIONAL)
    try:
        # noinspection PyUnresolvedReferences
        import argcomplete
        argcomplete.autocomplete(parser)
    except ImportError:
        pass
    args = parser.parse_args()
    print(args)
    init_global_config(ConfigBase(pretend=args.pretend, verbose=True, quiet=False))
    if (args.action == "all" and args.bitfile is not None) or args.action == "bitfile":
        if args.ltxfile is None:
            args.ltxfile = Path(args.bitfile).with_suffix(".ltx")
        load_bitfile(args.bitfile, args.ltxfile, FileSystemUtils(get_global_config()))
        if args.action == "bitfile":
            sys.exit(0)

    tty_info = find_vcu118_tty(args.pretend)
    success("Found TTY:", tty_info)
    info(tty_info.usb_info())
    if args.action == "console":
        console = get_console(tty_info)
        console.interact()
        return
    else:
        conn = load_and_start_kernel(gdb_cmd=args.gdb, openocd_cmd=args.openocd, bios_image=args.bios,
                                     kernel_image=args.kernel, kernel_debug_file=args.kernel_debug_file,
                                     tty_info=tty_info, num_cores=args.num_cores)
        console = conn.serial
        if args.action == "boot":
            sys.exit(0)

    if args.test_command is not None:
        success("Running test commands")
        for test_command in args.test_command:
            console.cheribsd.checked_run(test_command, timeout=args.test_timeout)
    # Finally interact with the console (if possible)
    if not sys.__stdin__.isatty():
        success("Not interating with console since stdin is not a TTY. Exiting now.")
    else:
        console.interact()
Example #2
0
 def __init__(self, executable, args):
     if get_global_config().pretend:
         self.cheribsd = FakeSerialSpawn(executable, args)
     else:
         print_command([executable, *args])
         self.cheribsd = CheriBSDInstance(CompilationTargets.CHERIBSD_RISCV_HYBRID, executable, args,
                                          logfile=sys.stdout, encoding="utf-8", timeout=60)
     assert isinstance(self.cheribsd, CheriBSDSpawnMixin)
Example #3
0
def load_bitfile(bitfile: Path, ltxfile: Path, fu: FileSystemUtils):
    if shutil.which("vivado") is None:
        fatal_error("vivado not in $PATH, cannot continue")
    if bitfile is None or not bitfile.exists():
        fatal_error("Missing bitfile:", bitfile)
    if ltxfile is None or not ltxfile.exists():
        fatal_error("Missing ltx file:", ltxfile)
    with tempfile.NamedTemporaryFile() as t:
        t.write(VIVADO_SCRIPT)
        t.flush()
        args = [
            "vivado", "-nojournal", "-notrace", "-nolog", "-source", t.name,
            "-mode", "batch", "-tclargs",
            str(bitfile),
            str(ltxfile)
        ]
        print_command(args, config=get_global_config())
        if get_global_config().pretend:
            vivado = PretendSpawn(args[0], args[1:])
        else:
            vivado = pexpect.spawn(args[0],
                                   args[1:],
                                   logfile=sys.stdout,
                                   encoding="utf-8")
        vivado_exit_str = "Exiting Vivado at"
        if vivado.expect_exact(["****** Vivado", vivado_exit_str]) != 0:
            failure("Vivado failed to start", exit=True)
        success("Vivado started")
        if vivado.expect_exact(["Programming...", vivado_exit_str]) != 0:
            failure("Vivado failed to start programming", exit=True)
        success("Vivado started programming FPGA")
        # 5 minutes should be enough time to programt the FPGA
        if vivado.expect_exact(["Done!", vivado_exit_str],
                               timeout=5 * 60) != 0:
            failure("Vivado failed to program FPGA", exit=True)
        success("Vivado finished programming FPGA")
        vivado.expect_exact([vivado_exit_str])
        vivado.wait()
        fu.delete_file(Path("webtalk.log"), print_verbose_only=True)
        fu.delete_file(Path("webtalk.jou"), print_verbose_only=True)
        if not get_global_config().pretend:
            # wait for 3 seconds to avoid 'Error: libusb_claim_interface() failed with LIBUSB_ERROR_BUSY'
            time.sleep(3)
Example #4
0
def start_openocd(openocd_cmd: Path, num_cores: int) -> typing.Tuple[pexpect.spawn, int]:
    with tempfile.NamedTemporaryFile() as t:
        t.write(generate_openocd_script(num_cores))
        t.flush()
        cmdline = [str(openocd_cmd), "-f", t.name]
        print_command(cmdline, config=get_global_config())
        if get_global_config().pretend:
            openocd = PretendSpawn(cmdline[0], cmdline[1:])
        else:
            openocd = pexpect.spawn(cmdline[0], cmdline[1:], logfile=sys.stdout, encoding="utf-8")
        openocd.expect_exact(["Open On-Chip Debugger"])
        success("openocd started")
        gdb_port = 3333
        openocd.expect(["Info : Listening on port (\\d+) for gdb connections"])
        if openocd.match is not None:
            gdb_port = int(openocd.match.group(1))
        openocd.expect_exact(["Info : Listening on port 4444 for telnet connections"])
        success("openocd waiting for GDB connection")
        return openocd, gdb_port
Example #5
0
def load_and_start_kernel(*,
                          gdb_cmd: Path,
                          openocd_cmd: Path,
                          bios_image: Path,
                          kernel_image: Path = None,
                          kernel_debug_file: Path = None,
                          tty_info: ListPortInfo,
                          num_cores: int) -> FpgaConnection:
    # Open the serial connection first to check that it's available:
    serial_conn = get_console(tty_info)
    success("Connected to TTY")
    if bios_image is None or not bios_image.exists():
        failure("Missing bios image: ", bios_image)
    # First start openocd
    gdb_start_time = datetime.datetime.utcnow()
    openocd, openocd_gdb_port = start_openocd(openocd_cmd, num_cores)
    # openocd is running, now start GDB
    args = [
        str(Path(bios_image).absolute()), "-ex",
        "target extended-remote :" + str(openocd_gdb_port)
    ]
    args += ["-ex", "set confirm off"]  # avoid interactive prompts
    args += ["-ex",
             "set pagination off"]  # avoid paginating output, requiring input
    args += ["-ex", "set style enabled off"
             ]  # disable colours since they break the matcher strings
    args += ["-ex", "monitor reset init"]  # reset and go back to boot room
    args += ["-ex", "si 5"
             ]  # we need to run the first few instructions to get a valid DTB
    args += ["-ex", "set disassemble-next-line on"]
    # Load the kernel image first since load changes the next PC to the entry point
    if kernel_image is not None:
        kernel_image = kernel_image.absolute()
        if kernel_debug_file is None:
            # If there is a .full image use that to get debug symbols:
            full_file = kernel_image.with_name(kernel_image.name + ".full")
            if full_file.exists():
                kernel_debug_file = full_file
            else:
                # Fall back to the kernel image without debug info.
                kernel_debug_file = kernel_image
        args += [
            "-ex",
            "symbol-file " + shlex.quote(str(kernel_debug_file.absolute()))
        ]
        args += ["-ex", "load " + shlex.quote(str(kernel_image.absolute()))]
    args += ["-ex", "load " + shlex.quote(str(Path(bios_image).absolute()))]
    if num_cores > 1:
        args += ["-ex", "set $entry_point = $pc"
                 ]  # Record the entry point to the bios
        for core in range(1, num_cores):
            args += ["-ex", "thread {:d}".format(core + 1)
                     ]  # switch to thread (core + 1) (GDB counts from 1)
            args += ["-ex", "si 5"]  # execute bootrom on every other core
            args += ["-ex", "set $pc=$entry_point"
                     ]  # set every other core to the start of the bios
        args += ["-ex", "thread 1"]  # switch back to core 0
    print_command(str(gdb_cmd), *args, config=get_global_config())
    if get_global_config().pretend:
        gdb = PretendSpawn(str(gdb_cmd), args, timeout=60)
    else:
        gdb = pexpect.spawn(str(gdb_cmd),
                            args,
                            timeout=60,
                            logfile=sys.stdout,
                            encoding="utf-8")
    gdb.expect_exact(["Reading symbols from"])
    # openOCD should acknowledge the GDB connection:
    openocd.expect_exact([
        "Info : accepting 'gdb' connection on tcp/{}".format(openocd_gdb_port)
    ])
    success("openocd accepted GDB connection")
    gdb.expect_exact(["Remote debugging using :" + str(openocd_gdb_port)])
    success("GDB connected to openocd")
    # XXX: doesn't match with recent GDB:  gdb.expect_exact(["0x0000000070000000 in ??"])
    gdb.expect_exact(["0x0000000070000000"])
    success("PC set to bootrom")
    # XXX: doesn't match with recent GDB: gdb.expect_exact(["0x0000000044000000 in ??"])
    gdb.expect_exact(["0x0000000044000000"])
    success("Done executing bootrom")
    if kernel_image is not None:
        gdb.expect_exact(["Loading section .text"])
        load_start_time = datetime.datetime.utcnow()
        success("Started loading kernel image (this may take a long time)")
        gdb.expect_exact(["Transfer rate:"], timeout=120 *
                         60)  # XXX: is 2 hours a sensible timeout?
        load_end_time = datetime.datetime.utcnow()
        success("Finished loading kernel image in ",
                load_end_time - load_start_time)
    # Now load the bootloader
    gdb.expect_exact(["Loading section .text"])
    load_start_time = datetime.datetime.utcnow()
    success("Started loading bootloader image")
    gdb.expect_exact(["Transfer rate:"],
                     timeout=10 * 60)  # XXX: is 10 minutes a sensible timeout?
    load_end_time = datetime.datetime.utcnow()
    success("Finished loading bootloader image in ",
            load_end_time - load_start_time)
    gdb_finish_time = load_end_time
    if num_cores > 1:
        for core in range(1, num_cores):
            gdb.expect_exact(["0x0000000044000000"])
        success("Done executing bootrom on all other cores")
    gdb.sendline("continue")
    success("Starting CheriBSD after ",
            datetime.datetime.utcnow() - gdb_start_time)
    i = serial_conn.cheribsd.expect_exact(
        ["bbl loader", "---<<BOOT>>---", pexpect.TIMEOUT], timeout=30)
    if i == 0:
        success("bbl loader started")
    elif i == 1:
        success("FreeBSD boot started")
    else:
        failure("Did not get expected boot output", exit=True)
    # TODO: network_iface="xae0", but DHCP doesn't work
    boot_and_login(serial_conn.cheribsd,
                   starttime=gdb_finish_time,
                   network_iface=None)
    return FpgaConnection(gdb, openocd, serial_conn)
Example #6
0
def main():
    # noinspection PyTypeChecker
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--bitfile",
                        help="The bitfile to load",
                        type=abspath_arg)
    parser.add_argument("--ltxfile",
                        help="The LTX file to use",
                        type=abspath_arg)
    parser.add_argument("--bios",
                        default="openocd",
                        help="The machine-mode program to load",
                        type=abspath_arg)
    parser.add_argument("--kernel",
                        help="The supervisor-mode program to load",
                        type=abspath_arg)
    parser.add_argument("--kernel-debug-file",
                        help="Debug info file for the kernel",
                        type=abspath_arg)
    parser.add_argument("--gdb",
                        default=shutil.which("gdb") or "gdb",
                        help="Path to GDB binary",
                        type=Path)
    parser.add_argument("--openocd",
                        default=shutil.which("openocd") or "openocd",
                        help="Path to openocd binary",
                        type=abspath_arg)
    parser.add_argument(
        "--pretend",
        help="Don't actually run the commands just show what would happen",
        action="store_true")
    parser.add_argument("action",
                        choices=["all", "bitfile", "boot", "console"],
                        default="all",
                        nargs=argparse.OPTIONAL)
    try:
        # noinspection PyUnresolvedReferences
        import argcomplete
        argcomplete.autocomplete(parser)
    except ImportError:
        pass
    args = parser.parse_args()
    print(args)
    init_global_config(
        ConfigBase(pretend=args.pretend, verbose=True, quiet=False))
    if (args.action == "all"
            and args.bitfile is not None) or args.action == "bitfile":
        if args.ltxfile is None:
            args.ltxfile = Path(args.bitfile).with_suffix(".ltx")
        load_bitfile(args.bitfile, args.ltxfile,
                     FileSystemUtils(get_global_config()))
        if args.action == "bitfile":
            sys.exit(0)

    tty_info = find_vcu118_tty()
    success("Found TTY:", tty_info)
    info(tty_info.usb_info())
    if args.action == "console":
        console = get_console(tty_info)
    else:
        conn = load_and_start_kernel(gdb_cmd=args.gdb,
                                     openocd_cmd=args.openocd,
                                     bios_image=args.bios,
                                     kernel_image=args.kernel,
                                     kernel_debug_file=args.kernel_debug_file,
                                     tty_info=tty_info)
        console = conn.serial
        if args.action == "boot":
            sys.exit(0)
    # interact() prints all input+output -> disable logfile
    console.cheribsd.logfile = None
    console.cheribsd.logfile_read = None
    console.cheribsd.logfile_send = None
    console.show_help_message()
    if args.action == "console":
        pass
        # TODO? console.sendintr()  # Send CTRL+C to get a clean prompt
    console.cheribsd.interact()