pub fn new_hle(mut fw_file: impl Read) -> std::io::Result<Ts7200> {
        // TODO?: use seek instead of reading entire elf file into memory.

        // load kernel ELF
        let mut elf_data = Vec::new();
        fw_file.read_to_end(&mut elf_data)?;
        let elf_header = goblin::elf::Elf::parse(&elf_data).map_err(|_e| {
            std::io::Error::new(std::io::ErrorKind::InvalidData, "could not parse elf file")
        })?;

        // load directly into the kernel
        debug!("Setting PC to {:#010x?}", elf_header.entry);
        let mut cpu = Cpu::new();
        cpu.reg_set(ArmMode::User, reg::PC, elf_header.entry as u32);
        cpu.reg_set(ArmMode::User, reg::CPSR, 0xd3); // supervisor mode
        cpu.reg_set(ArmMode::Supervisor, reg::LR, HLE_BOOTLOADER_LR);
        cpu.reg_set(ArmMode::Supervisor, reg::SP, HLE_BOOTLOADER_SP);

        // create the interrupt bus
        let (interrupt_bus_tx, interrupt_bus_rx) = chan::unbounded();

        // initialize system devices (in HLE state)
        let mut bus = Ts7200Bus::new_hle(interrupt_bus_tx);

        // copy all in-memory sections from the ELF file into system RAM
        let sections = elf_header
            .section_headers
            .iter()
            .filter(|h| h.is_alloc() && h.sh_type != goblin::elf::section_header::SHT_NOBITS);
        for h in sections {
            debug!(
                "loading section {:?} into memory from [{:#010x?}..{:#010x?}]",
                elf_header.shdr_strtab.get(h.sh_name).unwrap().unwrap(),
                h.sh_addr,
                h.sh_addr + h.sh_size,
            );

            bus.sdram
                .bulk_write(h.sh_addr as usize, &elf_data[h.file_range()]);
        }

        // Redboot pre-populates up the interrupt vector table with a bunch of
        // `ldr pc, [pc, #0x20]` instructions. This enables easy interrupt service
        // routine registration, simply by writing function pointers at an offset
        // of +0x20 from the corresponding IVT entry.
        // e.g: SWI correspond to IVT entry 0x08, so to register a SWI handler,
        // write a function pointer to 0x28
        for addr in (0..0x20).step_by(0x04) {
            bus.sdram.w32(addr, 0xe59f_f018).unwrap();
        }

        Ok(Ts7200 {
            hle: true,
            frozen: false,

            cpu,
            devices: bus,
            interrupt_bus: interrupt_bus_rx,

            watchpoints: Vec::new(),
            breakpoints: Vec::new(),
        })
    }
/// Returns a new Ts7200 using High Level Emulation (HLE) of the bootloader.
/// Execution begins from OS code (as specified in the elf file), and the
/// system's peripherals are pre-initialized.
Returns a new Ts7200 using High Level Emulation (HLE) of the bootloader.
Execution begins from OS code (as specified in the elf file), and the
system's peripherals are pre-initialized.
Returns a new Ts7200 using High Level Emulation ( HLE ) of the bootloader . Execution begins from OS code ( as specified in the elf file ) and the system ' s peripherals are pre - initialized .
pub fn new_hle(mut fw_file: impl Read) -> std::io::Result<Ts7200> {
        // TODO?: use seek instead of reading entire elf file into memory.
        // load kernel ELF
        let mut elf_data = Vec::new();
        fw_file.read_to_end(&mut elf_data)?;
        let elf_header = goblin::elf::Elf::parse(&elf_data).map_err(|_e| {
            std::io::Error::new(std::io::ErrorKind::InvalidData, "could not parse elf file")
        })?;
        // load directly into the kernel
        debug!("Setting PC to {:#010x?}", elf_header.entry);
        let mut cpu = Cpu::new();
        cpu.reg_set(ArmMode::User, reg::PC, elf_header.entry as u32);
        cpu.reg_set(ArmMode::User, reg::CPSR, 0xd3); // supervisor mode
        cpu.reg_set(ArmMode::Supervisor, reg::LR, HLE_BOOTLOADER_LR);
        cpu.reg_set(ArmMode::Supervisor, reg::SP, HLE_BOOTLOADER_SP);
        // create the interrupt bus
        let (interrupt_bus_tx, interrupt_bus_rx) = chan::unbounded();
        // initialize system devices (in HLE state)
        let mut bus = Ts7200Bus::new_hle(interrupt_bus_tx);
        // copy all in-memory sections from the ELF file into system RAM
        let sections = elf_header
            .section_headers
            .iter()
            .filter(|h| h.is_alloc() && h.sh_type != goblin::elf::section_header::SHT_NOBITS);
        for h in sections {
            debug!(
                "loading section {:?} into memory from [{:#010x?}..{:#010x?}]",
                elf_header.shdr_strtab.get(h.sh_name).unwrap().unwrap(),
                h.sh_addr,
                h.sh_addr + h.sh_size,
            );
            bus.sdram
                .bulk_write(h.sh_addr as usize, &elf_data[h.file_range()]);
        }
        // Redboot pre-populates up the interrupt vector table with a bunch of
        // `ldr pc, [pc, #0x20]` instructions. This enables easy interrupt service
        // routine registration, simply by writing function pointers at an offset
        // of +0x20 from the corresponding IVT entry.
        // e.g: SWI correspond to IVT entry 0x08, so to register a SWI handler,
        // write a function pointer to 0x28
        for addr in (0..0x20).step_by(0x04) {
            bus.sdram.w32(addr, 0xe59f_f018).unwrap();
        }
        Ok(Ts7200 {
            hle: true,
            frozen: false,
            cpu,
            devices: bus,
            interrupt_bus: interrupt_bus_rx,
            watchpoints: Vec::new(),
            breakpoints: Vec::new(),
        })
    }
pub fn new_hle ( mut fw_file : impl Read ) -> std :: io :: Result < Ts7200 > { // TODO?: use seek instead of reading entire elf file into memory. // load kernel ELF let mut elf_data = Vec :: new ( ) ; fw_file . read_to_end ( & mut elf_data ) ? ; let elf_header = goblin :: elf :: Elf :: parse ( & elf_data ) . map_err ( | _e | { std :: io :: Error :: new ( std :: io :: ErrorKind :: InvalidData , " " ) } ) ? ; // load directly into the kernel debug ! ( " " elf_header entry ) ; let mut cpu = Cpu :: new ( ) ; cpu . reg_set ( ArmMode :: User , reg :: PC , elf_header . entry as u32 ) ; cpu . reg_set ( ArmMode :: User , reg :: CPSR , 0xd3 ) ; // supervisor mode cpu . reg_set ( ArmMode :: Supervisor , reg :: LR , HLE_BOOTLOADER_LR ) ; cpu . reg_set ( ArmMode :: Supervisor , reg :: SP , HLE_BOOTLOADER_SP ) ; // create the interrupt bus let ( interrupt_bus_tx , interrupt_bus_rx ) = chan :: unbounded ( ) ; // initialize system devices (in HLE state) let mut bus = Ts7200Bus :: new_hle ( interrupt_bus_tx ) ; // copy all in-memory sections from the ELF file into system RAM let sections = elf_header . section_headers . iter ( ) . filter ( | h | h . is_alloc ( ) && h . sh_type != goblin :: elf :: section_header :: SHT_NOBITS ) ; for h in sections { debug ! ( " " elf_header shdr_strtab get ( h sh_name ) unwrap ( ) unwrap ( ) h sh_addr h sh_addr h sh_size ) ; bus . sdram . bulk_write ( h . sh_addr as usize , & elf_data [ h . file_range ( ) ] ) ; } // Redboot pre-populates up the interrupt vector table with a bunch of // `ldr pc, [pc, #0x20]` instructions. This enables easy interrupt service // routine registration, simply by writing function pointers at an offset // of +0x20 from the corresponding IVT entry. // e.g: SWI correspond to IVT entry 0x08, so to register a SWI handler, // write a function pointer to 0x28 for addr in ( 0 .. 0x20 ) . step_by ( 0x04 ) { bus . sdram . w32 ( addr , 0xe59f_f018 ) . unwrap ( ) ; } Ok ( Ts7200 { hle : true , frozen : false , cpu , devices : bus , interrupt_bus : interrupt_bus_rx , watchpoints : Vec :: new ( ) , breakpoints : Vec :: new ( ) , } ) }
Returns a new Ts7200 using High Level Emulation (HLE) of the bootloader.
Returns a new Ts7200 using High Level Emulation ( HLE ) of the bootloader .
fw_file
impl Read
fw_file
impl Read