Example #1
0
void trap_put_bytes(TrapContext *ctx, const void *haddrp, uaecptr addr, int cnt)
{
	if (cnt <= 0)
		return;
	uae_u8 *haddr = (uae_u8*)haddrp;
	if (trap_is_indirect_null(ctx)) {
		while (cnt > 0) {
			int max = cnt > RTAREA_TRAP_DATA_EXTRA_SIZE ? RTAREA_TRAP_DATA_EXTRA_SIZE : cnt;
			memcpy(ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA, haddr, max);
			call_hardware_trap_back(ctx, TRAPCMD_PUT_BYTES, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, addr, max, 0);
			haddr += max;
			addr += max;
			cnt -= max;
		}
	} else {
		if (real_address_allowed() && valid_address(addr, cnt)) {
			memcpy(get_real_address(addr), haddr, cnt);
		} else {
			for (int i = 0; i < cnt; i++) {
				put_byte(addr, *haddr++);
				addr++;
			}
		}
	}
}
Example #2
0
static void uade_put_long(int addr, int val)
{
  uae_u32 *p;
  if (!valid_address(addr, 4)) {
    fprintf(stderr, "uadecore: Invalid uade_put_long (0x%x).\n", addr);
    return;
  }
  p = (uae_u32 *) get_real_address(addr);
  *p = htonl(val);
}
Example #3
0
/* check if string is on a safe zone */
static int uade_valid_string(uae_u32 address)
{
  while (valid_address(address, 1)) {
    if (* ((uae_u8 *) get_real_address(address)) == 0)
      return 1;
    address++;
  }
  fprintf(stderr, "uadecore: Invalid string at 0x%x.\n", address);
  return 0;
}
Example #4
0
static int uade_get_u32(int addr)
{
  uae_u32 *ptr;
  int x;
  if (!valid_address(addr, 4)) {
    fprintf(stderr, "uadecore: Invalid uade_get_u32 (0x%x).\n", addr);
    return 0;
  }
  ptr = (uae_u32 *) get_real_address(addr);
  return ntohl(*ptr);
}
Example #5
0
bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size)
{
	bool locked = false;

	while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state);

#if PPC_ACCESS_LOG > 0 && PPC_ACCESS_LOG < 2
	if (!valid_address(addr, size)) {
		if (addr >= PPC_DEBUG_ADDR_FROM && addr < PPC_DEBUG_ADDR_TO)
			write_log(_T("PPC io write %08x = %08x %d\n"), addr, data, size);
	}
#endif

	locked = spinlock_pre(addr);
	switch (size)
	{
	case 4:
		put_long(addr, data);
		break;
	case 2:
		put_word(addr, data);
		break;
	case 1:
		put_byte(addr, data);
		break;
	}

	if (addr >= 0xdff000 && addr < 0xe00000) {
		int reg = addr & 0x1fe;
		switch (reg) {
			case 0x09c: // INTREQ
			case 0x09a: // INTENA
			if (data & 0x8000) {
				// possible interrupt change:
				// make sure M68K thread reacts to it ASAP.
				uae_int_requested |= 0x010000;
			}
			break;
		}
	}

	spinlock_post(locked);

#if PPC_ACCESS_LOG >= 2
	write_log(_T("PPC write %08x = %08x %d\n"), addr, data, size);
#endif

	return true;
}
Example #6
0
/* Return a pt_regs pointer for a valid signal handler frame */
static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
{
	BacktraceIterator *b = &kbt->it;

	if (b->pc == VDSO_BASE) {
		struct rt_sigframe *frame;
		unsigned long sigframe_top =
			b->sp + sizeof(struct rt_sigframe) - 1;
		if (!valid_address(kbt, b->sp) ||
		    !valid_address(kbt, sigframe_top)) {
			if (kbt->verbose)
				pr_err("  (odd signal: sp %#lx?)\n",
				       (unsigned long)(b->sp));
			return NULL;
		}
		frame = (struct rt_sigframe *)b->sp;
		if (kbt->verbose) {
			pr_err("  <received signal %d>\n",
			       frame->info.si_signo);
		}
		return (struct pt_regs *)&frame->uc.uc_mcontext;
	}
	return NULL;
}
Example #7
0
bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size)
{
	uint32_t v;
	bool locked = false;

	while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state);

	if (addr >= 0xdff000 && addr < 0xe00000) {
		int reg = addr & 0x1fe;
		// shortcuts for common registers
		switch (reg) {
			case 0x01c: // INTENAR
			*data = intena;
			return true;
			case 0x01e: // INTREQR
			*data = intreq;
			return true;
		}
	}

	locked = spinlock_pre(addr);
	switch (size)
	{
	case 4:
		v = get_long(addr);
		break;
	case 2:
		v = get_word(addr);
		break;
	case 1:
		v = get_byte(addr);
		break;
	}
	*data = v;
	spinlock_post(locked);

#if PPC_ACCESS_LOG > 0 && PPC_ACCESS_LOG < 2
	if (!valid_address(addr, size)) {
		if (addr >= PPC_DEBUG_ADDR_FROM && addr < PPC_DEBUG_ADDR_TO && addr != 0xdff006)
			write_log(_T("PPC io read %08x=%08x %d\n"), addr, v, size);
	}
#endif
#if PPC_ACCESS_LOG >= 2
	if (addr < 0xb00000 || addr > 0xc00000)
		write_log(_T("PPC read %08x=%08x %d\n"), addr, v, size);
#endif
	return true;
}
Example #8
0
/* Callback for backtracer; basically a glorified memcpy */
static bool read_memory_func(void *result, unsigned long address,
			     unsigned int size, void *vkbt)
{
	int retval;
	struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt;
	if (__kernel_text_address(address)) {
		/* OK to read kernel code. */
	} else if (address >= PAGE_OFFSET) {
		/* We only tolerate kernel-space reads of this task's stack */
		if (!in_kernel_stack(kbt, address))
			return 0;
	} else if (!valid_address(kbt, address)) {
		return 0;	/* invalid user-space address */
	}
	pagefault_disable();
	retval = __copy_from_user_inatomic(result,
					   (void __user __force *)address,
					   size);
	pagefault_enable();
	return (retval == 0);
}
Example #9
0
static int uade_safe_load(int dst, FILE *file, int maxlen)
{

#define UADE_SAFE_BUFSIZE 4096

  char buf[UADE_SAFE_BUFSIZE];
  int nbytes, len, off;

  len = UADE_SAFE_BUFSIZE;
  off = 0;

  if (maxlen <= 0)
    return 0;

  while (maxlen > 0) {

    if (maxlen < UADE_SAFE_BUFSIZE)
      len = maxlen;

    nbytes = fread(buf, 1, len, file);
    if (!nbytes)
      break;

    if (!valid_address(dst + off, nbytes)) {
      fprintf(stderr, "uadecore: Invalid load range [%x,%x).\n", dst + off, dst + off + nbytes);
      break;
    }

    memcpy(get_real_address(dst + off), buf, nbytes);
    off += nbytes;
    maxlen -= nbytes;
  }

  /* find out how much would have been read even if maxlen was violated */
  while ((nbytes = fread(buf, 1, UADE_SAFE_BUFSIZE, file)))
    off += nbytes;

  return off;
}
Example #10
0
static void uade_safe_get_string(char *dst, int src, int maxlen)
{
  int i = 0;
  while (1) {
    if (i >= maxlen)
      break;
    if (!valid_address(src + i, 1)) {
      fprintf(stderr, "uadecore: Invalid memory range in safe_get_string.\n");
      break;
    }
    dst[i] = * (char *) get_real_address(src + i);
    i++;
  }
  if (maxlen > 0) {
    if (i < maxlen) {
      dst[i] = 0;
    } else { 
      fprintf(stderr, "uadecore: Warning: string truncated.\n");
      dst[maxlen - 1] = 0;
    }
  }
}
Example #11
0
//
// Process a set of S-records, loading the contents into memory.  
// Note: if a "base" value is provided, the data will be relocated
// relative to that location.  Of course, this can only work for
// the first section of the data, so if there are non-contiguous
// pieces of data, they will end up relocated in the same fashion.
// Because of this, "base" probably only makes sense for a set of
// data which has only one section, e.g. a ROM image.
//
static unsigned long
load_srec_image(getc_t getc, unsigned long base)
{
    int  c;
    long offset = 0, count, sum, val, cksum;
    unsigned char *addr, *base_addr;
    char type;
    bool first_addr = true;
    unsigned long addr_offset = 0;
    unsigned long highest_address = 0;
    unsigned long lowest_address = 0xFFFFFFFF;

    while ((c = (*getc)()) > 0) {
        // Start of line
        if (c != 'S') {
            redboot_getc_terminate(true);
            err_printf("Invalid S-record at offset %p, input: %c\n", 
                   (void *)offset, c);
            return 0;
        }
        type = (*getc)();
        offset += 2;
        sum = 0;
        if ((count = _hex2(getc, 1, &sum)) < 0) {
            redboot_getc_terminate(true);
            err_printf("Bad S-record count at offset %p\n", (void *)offset);
            return 0;
        }
        offset += 1;
        switch (type) {
        case '0':
            break;
        case '1':
        case '2':
        case '3':
            base_addr = addr = (unsigned char *)_hex2(getc, (type-'1'+2), &sum);
            offset += (type-'1'+2);
            if (first_addr) {
                if (base) {
                    addr_offset = (unsigned long)base - (unsigned long)addr;
                } else {
                    addr_offset = 0;                    
                }
                first_addr = false;
            }
            addr += addr_offset;
            if ((unsigned long)(addr-addr_offset) < lowest_address) {
                lowest_address = (unsigned long)(addr - addr_offset);
            }
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (!(valid_address(addr)
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
                  || (flash_verify_addr(addr) == FLASH_ERR_OK)
#endif
                  )) {
	      // Only if there is no need to stop the download before printing
	      // output can we ask confirmation questions.
                redboot_getc_terminate(true);
		err_printf("*** Abort! Attempt to load S-record to address: %p, which is not valid\n",(void*)addr);
                return 0;
            }
#endif
            count -= ((type-'1'+2)+1);
            offset += count;
            while (count-- > 0) {
                val = _hex2(getc, 1, &sum);
                if (valid_address(addr)) {
                  *addr++ = val;
                }
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
                else {
                  flash_load_write(addr, val);
                  addr++;
                }
#endif
            }
            cksum = _hex2(getc, 1, 0);
            offset += 1;
            sum = sum & 0xFF;
            cksum = (~cksum & 0xFF);
            if (cksum != sum) {
                redboot_getc_terminate(true);
                err_printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n", 
                       (unsigned long)base_addr, sum, cksum);
                return 0;
            }
            if ((unsigned long)(addr-addr_offset) > highest_address) {
                highest_address = (unsigned long)(addr - addr_offset);
            }
            break;
        case '7':
        case '8':
        case '9':
            addr = (unsigned char *)_hex2(getc, ('9'-type+2), &sum);
            offset += ('9'-type+2);
            // Save load base/top, entry address
            if (base) {
                load_address = base;
                load_address_end = base + (highest_address - lowest_address);
                entry_address = (unsigned long)(base + (addr - lowest_address));
            } else {
                load_address = lowest_address;
                load_address_end = highest_address;
                entry_address = (unsigned long)addr;
            }
            redboot_getc_terminate(false);
            if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
            diag_printf("Entry point: %p, address range: %p-%p\n", 
                   (void*)entry_address, (void *)load_address, (void *)load_address_end);

            return load_address_end;
        default:
            redboot_getc_terminate(true);
            err_printf("Invalid S-record at offset 0x%lx, type: %x\n", 
                   (unsigned long)offset, type);
            return 0;
        }
        while ((c = (*getc)()) != '\n') offset++;
    }
    return 0;
}
Example #12
0
//
// Load an ELF [binary] image 
//
static unsigned long
load_elf_image(getc_t getc, unsigned long base)
{
#ifdef CYGSEM_REDBOOT_ELF
    Elf32_Ehdr ehdr;
#define MAX_PHDR 8
    Elf32_Phdr phdr[MAX_PHDR];
    unsigned long offset = 0;
    int phx, len, ch;
    unsigned char *addr;
    unsigned long addr_offset = 0;
    unsigned long highest_address = 0;
    unsigned long lowest_address = 0xFFFFFFFF;
    unsigned char *SHORT_DATA = "Short data reading ELF file\n";

    // Read the header
    if (_read(getc, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
        err_printf("Can't read ELF header\n");
        redboot_getc_terminate(true);
        return 0;
    }
    offset += sizeof(ehdr);    
#if 0 // DEBUG
    diag_printf("Type: %d, Machine: %d, Version: %d, Entry: %p, PHoff: %p/%d/%d, SHoff: %p/%d/%d\n",
                ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_entry, 
                ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,
                ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
#endif
    if (ehdr.e_type != ET_EXEC) {
        err_printf("Only absolute ELF images supported\n");
        redboot_getc_terminate(true);
        return 0;
    }
    if (ehdr.e_phnum > MAX_PHDR) {
        err_printf("Too many program headers\n");
        redboot_getc_terminate(true);
        return 0;
    }
    while (offset < ehdr.e_phoff) {
        if ((*getc)() < 0) {
            err_printf(SHORT_DATA);
            redboot_getc_terminate(true);
            return 0;
        }
        offset++;
    }
    for (phx = 0;  phx < ehdr.e_phnum;  phx++) {
        if (_read(getc, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {
            err_printf("Can't read ELF program header\n");
            redboot_getc_terminate(true);
            return 0;
        }
#if 0 // DEBUG
        diag_printf("Program header: type: %d, off: %p, va: %p, pa: %p, len: %d/%d, flags: %d\n",
                    phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
                    phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);
#endif
        offset += sizeof(phdr[0]);
    }
    if (base) {
        // Set address offset based on lowest address in file.
        addr_offset = 0xFFFFFFFF;
        for (phx = 0;  phx < ehdr.e_phnum;  phx++) {
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS     
            if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_vaddr < addr_offset)) {
                addr_offset = phdr[phx].p_vaddr;
#else
            if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_paddr < addr_offset)) {
                addr_offset = phdr[phx].p_paddr;
#endif
            }
        }
        addr_offset = (unsigned long)base - addr_offset;
    } else {
        addr_offset = 0;
    }
    for (phx = 0;  phx < ehdr.e_phnum;  phx++) {
        if (phdr[phx].p_type == PT_LOAD) {
            // Loadable segment
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
            addr = (unsigned char *)phdr[phx].p_vaddr;
#else     
            addr = (unsigned char *)phdr[phx].p_paddr;
#endif
            len = phdr[phx].p_filesz;
            if ((unsigned long)addr < lowest_address) {
                lowest_address = (unsigned long)addr;
            }
            addr += addr_offset;
            if (offset > phdr[phx].p_offset) {
                if ((phdr[phx].p_offset + len) < offset) {
                    err_printf("Can't load ELF file - program headers out of order\n");
                    redboot_getc_terminate(true);
                    return 0;
                }
                addr += offset - phdr[phx].p_offset;
            } else {
                while (offset < phdr[phx].p_offset) {
                    if ((*getc)() < 0) {
                        err_printf(SHORT_DATA);
                        redboot_getc_terminate(true);
                        return 0;
                    }
                    offset++;
                }
            }

            // Copy data into memory
            while (len-- > 0) {
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
                if (!(valid_address(addr) 
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
                    || (flash_verify_addr(addr) == FLASH_ERR_OK)
#endif
                    )) {
                    redboot_getc_terminate(true);
                    err_printf("*** Abort! Attempt to load ELF data to address: %p which is not valid\n", (void*)addr);
                    return 0;
                }
#endif
                if ((ch = (*getc)()) < 0) {
                    err_printf(SHORT_DATA);
                    redboot_getc_terminate(true);
                    return 0;
                }
                if (valid_address(addr)) {
                  *addr++ = ch;
                }
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
                else {
                  flash_load_write(addr, ch);
                  addr++;
                }
#endif
                offset++;
                if ((unsigned long)(addr-addr_offset) > highest_address) {
                    highest_address = (unsigned long)(addr - addr_offset);
                }
            }
        }
    }

    // Save load base/top and entry
    if (base) {
        load_address = base;
        load_address_end = base + (highest_address - lowest_address);
        entry_address = base + (ehdr.e_entry - lowest_address);
    } else {
        load_address = lowest_address;
        load_address_end = highest_address;
        entry_address = ehdr.e_entry;
    }

    // nak everything to stop the transfer, since redboot
    // usually doesn't read all the way to the end of the
    // elf files.
    redboot_getc_terminate(true);
    if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
    diag_printf("Entry point: %p, address range: %p-%p\n", 
                (void*)entry_address, (void *)load_address, (void *)load_address_end);
    return 1;
#else // CYGSEM_REDBOOT_ELF
    err_printf("Loading ELF images not supported\n");
    return 0;
#endif // CYGSEM_REDBOOT_ELF
}
Example #13
0
//
// Process a set of S-records, loading the contents into memory.  
// Note: if a "base" value is provided, the data will be relocated
// relative to that location.  Of course, this can only work for
// the first section of the data, so if there are non-contiguous
// pieces of data, they will end up relocated in the same fashion.
// Because of this, "base" probably only makes sense for a set of
// data which has only one section, e.g. a ROM image.
//
// Note that in case of multicore and the core we wanna load the 
// image for is not in the same endianness that the core we run 
// redboot from, have to invert bytes on 16-bit boundary 
// (16-bit memory)
//
static unsigned long
load_srec_image(getc_t getc, unsigned long base, bool swap16bit)
{
    int  c;
    long offset = 0, count, sum, val, cksum;
    unsigned char *addr, *base_addr, *addr_swap;
    char type;
    bool first_addr = true;
    unsigned long addr_offset = 0;
    unsigned long highest_address = 0;
    unsigned long lowest_address = 0xFFFFFFFF;

    while ((c = (*getc)()) > 0) {
        // Start of line
        if (c != 'S') {
            redboot_getc_terminate(true);
            diag_printf("Invalid S-record at offset %p, input: %c\n", 
                   (void *)offset, c);
            return 0;
        }
        type = (*getc)();
        offset += 2;
        sum = 0;
        if ((count = _hex2(getc, 1, &sum)) < 0) {
            redboot_getc_terminate(true);
            diag_printf("Bad S-record count at offset %p\n", (void *)offset);
            return 0;
        }
        offset += 1;
        switch (type) {
        case '0':
            break;
        case '1':
        case '2':
        case '3':
            base_addr = addr = (unsigned char *)_hex2(getc, (type-'1'+2), &sum);
            offset += (type-'1'+2);
            if (first_addr) {
                if (base) {
                    addr_offset = (unsigned long)base - (unsigned long)addr;
                } else {
                    addr_offset = 0;                    
                }
                first_addr = false;
            }
            addr += addr_offset;
            if ((unsigned long)(addr-addr_offset) < lowest_address) {
                lowest_address = (unsigned long)(addr - addr_offset);
            }
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (!valid_address(addr)) {
	      // Only if there is no need to stop the download before printing
	      // output can we ask confirmation questions.
                redboot_getc_terminate(true);
		diag_printf("*** Abort! Attempt to load S-record to address: %p, which is not in RAM\n",(void*)addr);
                return 0;
            }
#endif
            count -= ((type-'1'+2)+1);
            offset += count;
            while (count-- > 0) {
                val = _hex2(getc, 1, &sum);
                /* In case of multicore and the core we wanna load the image for is not in the same endianness
	    	that the core we run redboot from, have to invert bytes on 16-bit boundary (16-bit memory)*/
                if(swap16bit){
                    // addr is even, have to write char data to the last address
                    if(((unsigned long)addr)%2){
                        addr_swap=addr-1;
                        *addr_swap = val;
                    }
                    // addr is odd, have to write char data to the next address
                    else{
                        addr_swap=addr+1;
                        *addr_swap = val;
                    }
                    addr++;
                }
                else {
                *addr++ = val;
                }
            }
            cksum = _hex2(getc, 1, 0);
            offset += 1;
            sum = sum & 0xFF;
            cksum = (~cksum & 0xFF);
            if (cksum != sum) {
                redboot_getc_terminate(true);
                diag_printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n", 
                       (unsigned long)base_addr, sum, cksum);
                return 0;
            }
            if ((unsigned long)(addr-addr_offset) > highest_address) {
                highest_address = (unsigned long)(addr - addr_offset);
            }
            break;
        case '7':
        case '8':
        case '9':
            addr = (unsigned char *)_hex2(getc, ('9'-type+2), &sum);
            offset += ('9'-type+2);
            // Save load base/top, entry address
            if (base) {
                load_address = base;
                load_address_end = base + (highest_address - lowest_address);
                entry_address = (unsigned long)(base + (addr - lowest_address));
            } else {
                load_address = lowest_address;
                load_address_end = highest_address;
                entry_address = (unsigned long)addr;
            }
            redboot_getc_terminate(false);
            if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
            diag_printf("Entry point: %p, address range: %p-%p\n", 
                   (void*)entry_address, (void *)load_address, (void *)load_address_end);

            return load_address_end;
        default:
            redboot_getc_terminate(true);
            diag_printf("Invalid S-record at offset 0x%lx, type: %x\n", 
                   (unsigned long)offset, type);
            return 0;
        }
        while ((c = (*getc)()) != '\n') offset++;
    }
    return 0;
}
Example #14
0
/* this is called for each played song from newcpu.c/m68k_reset() */
void uade_reset(void)
{
  /* don't load anything under 0x1000 (execbase top at $1000) */
  const int modnameaddr = 0x00400;
  const int scoreaddr   = 0x01000;
  const int userstack   = 0x08500;
  const int superstack  = 0x08f00;
  const int playeraddr  = 0x09000;
  int relocaddr;
  int modaddr;
  int len;
  FILE *file;
  int bytesread;

  uint8_t command[UADE_MAX_MESSAGE_SIZE];
  struct uade_msg *um = (struct uade_msg *) command;

  int ret;

 nextsong:

  /* IMPORTANT:
     It seems that certain players don't work totally reliably if memory
     contains trash from previous songs. To be certain that each song is
     played from the same initial state of emulator we clear the memory
     from 0x400 to 'uade_highmem' each time a new song is played */
  uade_highmem = 0;
  while (uade_highmem < 0x800000) {
    if (!valid_address(0, uade_highmem + 0x10000))
      break;
    uade_highmem += 0x10000;
  }
  if (uade_highmem < 0x80000) {
    fprintf(stderr, "uadecore: There must be at least 512 KiB of amiga memory (%d bytes found).\n", uade_highmem);
    exit(-1);
  }
  if (uade_highmem < 0x200000) {
    fprintf(stderr, "uadecore: Warning: highmem == 0x%x (< 0x200000)!\n", uade_highmem);
  }
  memset(get_real_address(0), 0, uade_highmem);

  song.cur_subsong = song.min_subsong = song.max_subsong = 0;

  ret = uade_receive_string(song.scorename, UADE_COMMAND_SCORE, sizeof(song.scorename), &uadeipc);
  if (ret == 0) {
    fprintf(stderr, "uadecore: No more songs to play.\n");
    exit(0);
  } else if (ret < 0) {
    fprintf(stderr, "uadecore: Invalid input. Expected score name.\n");
    exit(-1);
  }
//	printf("got scorename %s\n",song.scorename);

  ret = uade_receive_string(song.playername, UADE_COMMAND_PLAYER, sizeof(song.playername), &uadeipc);
  if (ret == 0) {
    printf("uadecore: Expected player name. Got nothing.\n");
    exit(-1);
  } else if (ret < 0) {
    printf( "uadecore: Invalid input. Expected player name.\n");
    exit(-1);
  }
//	printf("got playername %s\n",song.playername);

  if (uade_dirname(uade_player_dir, song.playername, sizeof(uade_player_dir)) == NULL) {
    printf( "uadecore: Invalid dirname with player: %s\n", song.playername);
    exit(-1);
  }

  ret = uade_receive_message(um, sizeof command, &uadeipc);
  if (ret == 0) {
    printf("uadecore: Expected module name. Got nothing.\n");
    exit(-1);
  } else if (ret < 0) {
    printf( "uadecore: Invalid input. Expected module name.\n");
    exit(-1);
  }
  assert(um->msgtype == UADE_COMMAND_MODULE);
  if (um->size == 0) {
    song.modulename[0] = 0;
  } else {
    assert(um->size == (strlen((char *) um->data) + 1));
    strlcpy(song.modulename, (char *) um->data, sizeof(song.modulename));
  }
//	printf("got modulename %s\n",song.modulename);

  uade_set_automatic_song_end(1);

  uade_put_long(SCORE_EXEC_DEBUG, uade_execdebugboolean ? 0x12345678 : 0);
  uade_put_long(SCORE_VOLUME_TEST, voltestboolean);
  uade_put_long(SCORE_DMA_WAIT, uade_dmawait);
  uade_put_long(SCORE_MODULECHANGE, disable_modulechange);

  bytesread = uade_safe_load_name(playeraddr, song.playername, "player", uade_highmem - playeraddr);

  if (bytesread > (uade_highmem - playeraddr)) {
    fprintf (stderr, "uadecore: Player %s too big a file (%d bytes).\n", song.playername, bytesread);
    goto skiptonextsong;
  }
  if (bytesread == 0) {
    goto skiptonextsong;
  }

  /* fprintf(stderr, "uadecore: player '%s' (%d bytes)\n", song.playername, bytesread); */

  /* set player executable address for relocator */
  uade_put_long(SCORE_PLAYER_ADDR, playeraddr);
  len = uade_calc_reloc_size((uae_u32 *) get_real_address(playeraddr),
			     (uae_u32 *) get_real_address(playeraddr + bytesread));
  if (!len) {
    fprintf(stderr, "uadecore: Problem with reloc calculation.\n");
    goto skiptonextsong;
  }
  relocaddr  = ((playeraddr + bytesread) & 0x7FFFF000) + 0x4000;
  /* + 0x4000 for hippel coso (wasseremu) */
  modaddr = ((relocaddr + len) & 0x7FFFF000) + 0x2000;

  if (modaddr <= relocaddr) {
    /* this is very bad because sound core memory allocation will fail */
    fprintf(stderr, "uadecore: Warning: modaddr <= relocaddr: 0x%x <= 0x%x\n", modaddr, relocaddr);
  }

  uade_put_long(SCORE_RELOC_ADDR, relocaddr);  /*address for relocated player*/
  uade_put_long(SCORE_MODULE_ADDR, modaddr);   /* set module address */
  uade_put_long(SCORE_MODULE_LEN, 0);          /* set module size to zero */
  uade_put_long(SCORE_MODULE_NAME_ADDR, 0);    /* mod name address pointer */

  /* load the module if available */
  if (song.modulename[0]) {
    bytesread = uade_safe_load_name(modaddr, song.modulename, "module", uade_highmem - modaddr);
    if (bytesread > (uade_highmem - playeraddr)) {
      fprintf (stderr, "uadecore: Module %s too big a file (%d bytes).\n", song.modulename, bytesread);
      goto skiptonextsong;
    }
    if (bytesread == 0) {
      goto skiptonextsong;
    }

    uade_put_long(SCORE_MODULE_LEN, bytesread);

    if (!valid_address(modnameaddr, strlen(song.modulename) + 1)) {
      fprintf(stderr, "uadecore: Invalid address for modulename.\n");
      goto skiptonextsong;
    }

    strlcpy((char *) get_real_address(modnameaddr), song.modulename, 1024);
    uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr);

  } else {

    if (!valid_address(modnameaddr, strlen(song.playername) + 1)) {
      fprintf(stderr, "uadecore: Invalid address for playername.\n");
      goto skiptonextsong;
    }

    strlcpy((char *) get_real_address(modnameaddr), song.playername, 1024);
    uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr);

    bytesread = 0;
  }

  /* load sound core (score) */
  if ((file = fopen(song.scorename, "rb"))) {
    bytesread = uade_safe_load(scoreaddr, file, uade_highmem - scoreaddr);
    fclose(file);
  } else {
    fprintf (stderr, "uadecore: Can not load score (%s).\n", song.scorename);
    goto skiptonextsong;
  }

  m68k_areg(regs,7) = scoreaddr;
  m68k_setpc(scoreaddr);

  /* obey player format checking */
  uade_put_long(SCORE_FORCE, 0);
  /* set default subsong */
  uade_put_long(SCORE_SET_SUBSONG, 0);
  uade_put_long(SCORE_SUBSONG, 0);
  /* set PAL mode */
  uade_set_ntsc(0);

  /* pause bits (don't care!), for debugging purposes only */
  uade_put_long(SCORE_PREPAUSE, 0);
  uade_put_long(SCORE_POSTPAUSE, 0);
  /* set user and supervisor stack pointers */
  uade_put_long(SCORE_USER_STACK, userstack);
  uade_put_long(SCORE_SUPER_STACK, superstack);
  /* no message for score */
  uade_put_long(SCORE_OUTPUT_MSG, 0);
  if ((userstack - (scoreaddr + bytesread)) < 0x1000)
    fprintf(stderr, "uadecore: Amiga stack overrun warning.\n");

  flush_sound();

  /* note that uade_speed_hack can be negative (meaning that uade never uses
     speed hack, even if it's requested by the amiga player)! */
  uade_time_critical = 0;
  if (uade_speed_hack > 0) {
    uade_time_critical = 1;
  }

  uade_reboot = 0;

  uade_audio_output = 0;
  uade_audio_skip = 0;

  old_ledstate = gui_ledstate;

  if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n");
    exit(-1);
  }

  if (uade_send_short_message(UADE_REPLY_CAN_PLAY, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send 'CAN_PLAY' reply.\n");
    exit(-1);
  }
  if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send token from uade_reset().\n");
    exit(-1);
  }

  set_sound_freq(UADE_DEFAULT_FREQUENCY);
  epoptionsize = 0;

  return;

 skiptonextsong:
  fprintf(stderr, "uadecore: Can not play. Reboot.\n");

  if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n");
    exit(-1);
  }

  if (uade_send_short_message(UADE_REPLY_CANT_PLAY, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send 'CANT_PLAY' reply.\n");
    exit(-1);
  }
  if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send token from uade_reset().\n");
    exit(-1);
  }
  goto nextsong;
}
Example #15
0
void uade_get_amiga_message(void)
{
  uae_u8 *ptr;
  uae_u8 *nameptr;
  FILE *file;
  int x;
  unsigned int mins, maxs, curs;
  int status;
  int src, dst, off, len;
  char tmpstr[256];
  char *srcstr, *dststr;

  uint32_t *u32ptr;
  uint8_t space[256];
  struct uade_msg *um = (struct uade_msg *) space;

  x = uade_get_u32(SCORE_INPUT_MSG);  /* message type from amiga */

  switch (x) {

  case AMIGAMSG_SONG_END:
    uade_song_end("player", 0);
    break;

  case AMIGAMSG_SUBSINFO:
    mins = uade_get_u32(SCORE_MIN_SUBSONG);
    maxs = uade_get_u32(SCORE_MAX_SUBSONG);
    curs = uade_get_u32(SCORE_CUR_SUBSONG);
    /* Brain damage in TFMX BC Kid Despair */
    if (maxs < mins) {
      uade_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs);
      maxs = mins;
    }
    /* Brain damage in Bubble bobble custom */
    if (curs > maxs) {
      uade_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs);
      maxs = curs;
    }
    um->msgtype = UADE_REPLY_SUBSONG_INFO;
    um->size = 12;
    u32ptr = (uint32_t *) um->data;
    u32ptr[0] = htonl(mins);
    u32ptr[1] = htonl(maxs);
    u32ptr[2] = htonl(curs);
    if (uade_send_message(um, &uadeipc)) {
      fprintf(stderr, "uadecore: Could not send subsong info message.\n");
      exit(-1);
    }
    break;

  case AMIGAMSG_PLAYERNAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_PLAYERNAME, tmpstr, &uadeipc);
    break;

  case AMIGAMSG_MODULENAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_MODULENAME, tmpstr, &uadeipc);
    break;

  case AMIGAMSG_FORMATNAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_FORMATNAME, tmpstr, &uadeipc);
    break;

  case AMIGAMSG_GENERALMSG:
    uade_send_debug((char *) get_real_address(0x204));
    break;

  case AMIGAMSG_CHECKERROR:
    uade_song_end("module check failed", 1);
    break;

  case AMIGAMSG_SCORECRASH:
    if (uade_debug) {
      fprintf(stderr, "uadecore: Score crashed.\n");
      activate_debugger();
      break;
    }
    uade_song_end("score crashed", 1);
    break;

  case AMIGAMSG_SCOREDEAD:
     if (uade_debug) {
      fprintf(stderr, "uadecore: Score is dead.\n"); 
      activate_debugger();
      break;
    }
     uade_song_end("score died", 1);
    break;

  case AMIGAMSG_LOADFILE:
    /* load a file named at 0x204 (name pointer) to address pointed by
       0x208 and insert the length to 0x20C */
    src = uade_get_u32(0x204);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: Load name in invalid address range.\n");
      break;
    }
    nameptr = get_real_address(src);
    if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) {
      dst = uade_get_u32(0x208);
      len = uade_safe_load(dst, file, uade_highmem - dst);
      fclose(file); file = NULL;
      uade_put_long(0x20C, len);
      uade_send_debug("load success: %s ptr 0x%x size 0x%x", nameptr, dst, len);
    } else {
      uade_send_debug("load: file not found: %s", nameptr);
    }
    break;

  case AMIGAMSG_READ:
    src = uade_get_u32(0x204);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: Read name in invalid address range.\n");
      break;
    }
    nameptr = get_real_address(src);
    dst = uade_get_u32(0x208);
    off = uade_get_u32(0x20C);
    len = uade_get_u32(0x210);
    if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) {
      if (fseek(file, off, SEEK_SET)) {
	perror("can not fseek to position");
	x = 0;
      } else {
	x = uade_safe_load(dst, file, len);
	if (x > len)
	  x = len;
      }
      fclose(file);
      uade_send_debug("read %s dst 0x%x off 0x%x len 0x%x res 0x%x", nameptr, dst, off, len, x);
      uade_put_long(0x214, x);
    } else {
      uade_send_debug("read: file not found: %s", nameptr);
      uade_put_long(0x214, 0);
    }
    break;

  case AMIGAMSG_FILESIZE:
    src = uade_get_u32(0x204);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: Filesize name in invalid address range.\n");
      break;
    }
    nameptr = get_real_address(src);
    if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) {
      fseek(file, 0, SEEK_END);
      len = ftell(file);
      fclose(file);
      uade_put_long(0x208, len);
      uade_put_long(0x20C, -1);
      uade_send_debug("filesize: file %s res 0x%x", nameptr, len);
    } else {
      uade_put_long(0x208, 0);
      uade_put_long(0x20C, 0);
      uade_send_debug("filesize: file not found: %s", nameptr);
    }
    break;

  case AMIGAMSG_TIME_CRITICAL:
    uade_time_critical = uade_get_u32(0x204) ? 1 : 0;
    if (uade_speed_hack < 0) {
      /* a negative value forbids use of speed hack */
      uade_time_critical = 0;
    }
    break;

  case AMIGAMSG_GET_INFO:
    src = uade_get_u32(0x204);
    dst = uade_get_u32(0x208);
    len = uade_get_u32(0x20C);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: get info: Invalid src: 0x%x\n", src);
      break;
    }
    if (len <= 0) {
      fprintf(stderr, "uadecore: get info: len = %d\n", len);
      break;
    }
    if (!valid_address(dst, len)) {
      fprintf(stderr, "uadecore: get info: Invalid dst: 0x%x\n", dst);
      break;
    }
    srcstr = (char *) get_real_address(src);
    dststr = (char *) get_real_address(dst);
    uade_send_debug("score issued an info request: %s (maxlen %d)\n", srcstr, len);
    len = get_info_for_ep(dststr, srcstr, len);
    /* Send printable debug */
    do {
      size_t i;
      size_t maxspace = sizeof space;
      if (len <= 0) {
	maxspace = 1;
      } else {
	if (len < maxspace)
	  maxspace = len;
      }
      for (i = 0; i < maxspace; i++) {
	space[i] = dststr[i];
	if (space[i] == 0)
	  space[i] = ' ';
      }
      if (i < maxspace) {
	space[i] = 0;
      } else {
	space[maxspace - 1] = 0;
      }
      uade_send_debug("reply to score: %s (total len %d)\n", space, len);
    } while (0);
    uade_put_long(0x20C, len);
    break;

  case AMIGAMSG_START_OUTPUT:
    uade_audio_output = 1;
    uade_send_debug("Starting audio output at %d", uade_audio_skip);
    break;

  default:
    fprintf(stderr,"uadecore: Unknown message from score (%d)\n", x);
    break;
  }
}
/*--------------------------------------------
| Name:        _tiny_elfloader
| Description:
| Parameters:  none
| Return Type: none
| Comments:
| See:
----------------------------------------------*/
unsigned long _tiny_elfloader(unsigned long flash_base, unsigned long base)
{
   Elf32_Ehdr ehdr;

   Elf32_Phdr phdr[MAX_PHDR];
   unsigned long offset = 0;
   int phx=0;
   int len=0;
   unsigned char ch;
   unsigned char *addr;
   unsigned long addr_offset = 0;
   unsigned long highest_address = 0;
   unsigned long lowest_address = 0xFFFFFFFF;
   unsigned char *SHORT_DATA = "error: short data reading elf file\r\n";

   //
   int cb=0;
   boot_handler_t boot_handler = (boot_handler_t)0x00000000;

#ifdef DEBUG
   _elf_printf("read elf file at 0x%x\r\n", (unsigned int)flash_base);
#endif
   //ALREADY DONE
   //_at91sam9261_remap_internal_ram();

   // Read the header
   _elf_printf("read elf header informations:\r\n" );
   if (_elf_read(flash_base, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
#ifdef DEBUG
      _elf_printf("error: can't read elf header\r\n");
#endif
      return 0;
   }
   offset += sizeof(ehdr);
   //
#ifdef DEBUG
   _elf_printf(
      "type: %d, machine: %d, version: %d\r\nentry: 0x%x, PHoff: 0x%x/%d/%d, SHoff: 0x%x/%d/%d\r\n\r\n",
      ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_entry,
      ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,
      ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
#endif
   //
   if (ehdr.e_type != ET_EXEC) {
#ifdef DEBUG
      _elf_printf("error: only absolute elf images supported\r\n");
#endif
      return 0;
   }
   //
   if (ehdr.e_phnum > MAX_PHDR) {
#ifdef DEBUG
      _elf_printf("error: too many firmware headers\r\n");
#endif
      return 0;
   }
#ifdef DEBUG
   _elf_printf("jump to offset 0x%x wait some seconds... ",ehdr.e_phoff);
#endif
   //jump to offset
#ifdef USE_OPTIMIZED_READELF
   //optimized code
   #if !defined(__GNUC__)
   _elf_lseek(flash_base,ehdr.e_phoff,0);
   offset+=ehdr.e_phoff;
   #endif
#else
   //not optimized original code from reboot
   while (offset < ehdr.e_phoff) {
      if (_elf_getc(flash_base) < 0) {
   #ifdef DEBUG
         printf(SHORT_DATA);
   #endif
         return 0;
      }
      offset++;
   }
#endif

   //
#ifdef DEBUG
   _elf_printf("done\r\n");
#endif

#ifdef DEBUG
   _elf_printf("read elf section header\r\n");
#endif
   //
   for (phx = 0; phx < ehdr.e_phnum; phx++) {
      if (_elf_read(flash_base, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {
#ifdef DEBUG
         _elf_printf("error: can't read ELF program header\r\n");
#endif
         return 0;
      }
#ifdef DEBUG
      _elf_printf(
         "section header: type: %d, off: 0x%x\r\nva: 0x%x, pa: 0x%x, len: %d/%d, flags: %d\r\n",
         phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
         phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);
#endif
      offset += sizeof(phdr[0]);
   }

   if (base) {
      // Set address offset based on lowest address in file.
      addr_offset = 0xFFFFFFFF;
      for (phx = 0; phx < ehdr.e_phnum; phx++) {
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
         if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_vaddr < addr_offset)) {
            addr_offset = phdr[phx].p_vaddr;
#else
         if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_paddr < addr_offset)) {
            addr_offset = phdr[phx].p_paddr;
#endif
         }
      }
      addr_offset = (unsigned long)base - addr_offset;
   }else{
      addr_offset = 0;
   }
   //phlb modif
#if !defined(__GNUC__)
   _elf_lseek(flash_base,sizeof(ehdr),0);
#endif

#ifdef DEBUG
   _elf_printf("copy firmware in ram started:\r\n");
#endif

   for (phx = 0; phx < ehdr.e_phnum; phx++) {

      //
      if (phdr[phx].p_type == PT_LOAD) {
         // Loadable segment
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
         addr = (unsigned char *)phdr[phx].p_vaddr;
#else
         addr = (unsigned char *)phdr[phx].p_paddr;
#endif

         //
         len = phdr[phx].p_filesz;
         if ((unsigned long)addr < lowest_address) {
            lowest_address = (unsigned long)addr;
         }
         //
         addr += addr_offset;
         if (offset > phdr[phx].p_offset) {
            /*
             if ((phdr[phx].p_offset + len) < offset) {
                 printf("Can't load ELF file - program headers out of order\r\n");
                 return 0;
             }
             */
            /*addr += offset - phdr[phx].p_offset;*/
         } else {
            while (offset < phdr[phx].p_offset) {
               if (_elf_getc(flash_base) < 0) {
#ifdef DEBUG
                  printf(SHORT_DATA);
#endif
                  return 0;
               }
               offset++;
            }
         }

#ifdef DEBUG
         _elf_printf(
            "program header: type: %d, off: 0x%x, va: 0x%x, pa:0x%x, len: %d/%d, flags: %d\r\n",
            phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
            phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);

#endif

         // Copy data into memory
#ifndef USE_OPTIMIZED_READELF
         while (len-- > 0) {

            if ((ch = _elf_getc(flash_base)) < 0) {
   #ifdef DEBUG
               printf(SHORT_DATA);
   #endif
               return 0;
            }
   #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (valid_address(addr))
   #endif
            *addr = ch;      //original code
   #ifdef DEBUG
            if(!(((unsigned long)offset)%(80*1*1024)))
               _elf_printf(".");
   #endif

            addr++;
            offset++;
            if ((unsigned long)(addr-addr_offset) > highest_address) {
               highest_address = (unsigned long)(addr - addr_offset);
            }
         }
#endif

#ifdef USE_OPTIMIZED_READELF
         //
   #if defined(__GNUC__)
         _elf_lseek(flash_base,phdr[phx].p_offset,0);
         _elf_printf("offset:%d addr:0x%x fl_offset:%d\r\n", offset, addr, elf_flash_offset);
   #endif

         cb=0;
         while((len-cb)) {
            unsigned char elf_buffer[4096]={0};
            int sz=0;

            if((len-cb)>=sizeof(elf_buffer))
               sz=sizeof(elf_buffer);
            else
               sz=(len-cb);

            //cb += read(fd,elf_buffer,sz);
            cb+=_elf_read(flash_base, addr, sz);
            /*
            #ifdef DEBUG
            lseek(fd_bin,(unsigned long)addr,SEEK_SET);
            write(fd_bin,elf_buffer,sz);
            #endif
            */
   #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (valid_address(addr))
   #endif
            //memcpy(addr,elf_buffer,sz);

            //
            addr+=sz;
            offset+=sz;
            if ((unsigned long)(addr-addr_offset) > highest_address) {
               highest_address = (unsigned long)(addr - addr_offset);
            }
         }
#endif
      }
   }

   // Save load base/top and entry
   if (base) {
      load_address = base;
      load_address_end = base + (highest_address - lowest_address);
      entry_address = base + (ehdr.e_entry - lowest_address);
   } else {
      load_address = lowest_address;
      load_address_end = highest_address;
      entry_address = ehdr.e_entry;
   }

   // nak everything to stop the transfer, since redboot
   // usually doesn't read all the way to the end of the
   // elf files.
#ifdef DEBUG
   _elf_printf("\r\ncopy firmware in ram done\r\n");
   if (addr_offset)
      _elf_printf("address offset = 0x%x\n", addr_offset);
   _elf_printf("firmware entry point: 0x%x, address range: 0x%x-0x%x\r\n",entry_address,
               load_address,
               load_address_end);
   _elf_printf("ready to rumble? ;)\r\nboot on firmware\r\n");
#endif

   boot_handler = (boot_handler_t)entry_address;

   //boot!!!!
   boot_handler();
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   for(;; ) ;

   return 1;
}
Example #17
0
int main (int argc, char ** argv)
{
	std::string filename;
	std::ifstream trace_file;

	uint64_t memory_size = 8*1024*1024; // default is 8GB
	// Check if all arguments are given in command line
	if (argc != 3)
	{
		std::cout << "Please supply two arguements: <trace file> <physical memory size (B)>." << std::endl;
		return -1;
	}

	// Get the filename
	filename.assign(argv[1]);
	// Assign the memory size
	memory_size = std::stol(argv[2], nullptr, 10);

	// allocate array
	uint64_t array_size = memory_size / page_size;
	array_size--; // assume 1st level page table ALWAYS in memory
	MEME * in_memory = new MEME[array_size];
//	in_memory [array_size];
	uint64_t array_index = 0;

	//std::cout << argv[2] << " " << memory_size << " " << array_size << std::endl;


	// Open the file
	trace_file.open(filename);
	char operation;
	std::string virtual_address;
	std::string this_key;
	int byte_size;
	std::string file_line;
	std::vector<std::string> line_input;
	std::string token;

	while (std::getline(trace_file, file_line))
	{
		// tokenize string
		std::istringstream ss(file_line);
		while(std::getline(ss, token, ' '))
		{
			line_input.push_back(token);
			//std::cout << token << std::endl;
		}

		if (line_input.size() != 3)
		{
			line_input.clear();
			continue;
		}
		
		operation = line_input[0].at(0);
		if (operation != 'R' && operation != 'W')
		{
			line_input.clear();
			continue;
		}

		line_input[1] = line_input[1].substr(0, line_input[1].size() - 3);
		if (!valid_address(line_input[1]))
		{
			line_input.clear();
			continue;
		}
		virtual_address = line_input[1];
		this_key = line_input[1];//virtual_address;//get_VPN(virtual_address);

		if (!valid_size(line_input[2]))
		{
			line_input.clear();
			continue;
		}
		byte_size = std::stoi(line_input[2]);

		if (operation == 'R')
			total_bytes_read += byte_size;
		else
			total_bytes_write += byte_size;

		auto search = vpn_tracker.find(this_key);
		if (search != vpn_tracker.end())
		{
			// check if 2nd level not in memory
			if (!vpn_tracker[this_key].lvl_2_mem)
			{
				// find page to eject
				array_index = get_next_index(in_memory, array_size, array_index);
				eject_from_memory (in_memory[array_index].vpn, in_memory[array_index].level);

				// insert new page
				insert_into_memory (in_memory, array_index, this_key, 2);
			}
			else if (vpn_tracker[this_key].lvl_2_mem)
			{
				total_accessed++;
				vpn_tracker[this_key].lvl_2_clock = 1;
			}

			// check if 3rd level not in memory
			if (!vpn_tracker[this_key].lvl_3_mem)
			{
				// find page to eject
				array_index = get_next_index(in_memory, array_size, array_index);
				eject_from_memory (in_memory[array_index].vpn, in_memory[array_index].level);

				// insert new page
				insert_into_memory (in_memory, array_index, this_key, 3);
			}
			else if (vpn_tracker[this_key].lvl_3_mem)
			{
				total_accessed++;
				vpn_tracker[this_key].lvl_3_clock = 1;
			}

			// check if 4th level not in memory
			if (!vpn_tracker[this_key].lvl_4_mem)
			{
				// find page to eject
				array_index = get_next_index(in_memory, array_size, array_index);
				eject_from_memory (in_memory[array_index].vpn, in_memory[array_index].level);

				// insert new page
				insert_into_memory (in_memory, array_index, this_key, 4);
			}
			else if (vpn_tracker[this_key].lvl_4_mem)
			{
				total_accessed++;
				vpn_tracker[this_key].lvl_4_clock = 1;
			}

			vpn_tracker[this_key].num_accessed += 1;
		}
		else
		{
			PTE new_elem = {this_key, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
			vpn_tracker.insert(std::pair<std::string, PTE>(this_key, new_elem));
			for (int i = 2; i < 5; ++i)
			{
				array_index = get_next_index(in_memory, array_size, array_index);
				eject_from_memory (in_memory[array_index].vpn, in_memory[array_index].level);
				insert_into_memory (in_memory, array_index, this_key, i);
			}
		}
		// std::cout << "num tokens: " << line_input.size() << std::endl;
		// {
		// 	virtual_address 
		// }
		//std::cout << operation << " " << std::hex << virtual_address << " " << std::hex << get_VPN(virtual_address) << std::endl;

		line_input.clear();
	}

	std::string most_accessed_vpn = "";
	uint64_t num_access_vpn = 0;
	for (auto& x: vpn_tracker)
	{
		if (x.second.num_accessed > num_access_vpn)
		{
			num_access_vpn = x.second.num_accessed;
			most_accessed_vpn = x.first;
		}
	}

	long double page_fault_rate = (long double) total_faults / (long double) total_accessed;

	std::cout << "Number of pages accessed: " << vpn_tracker.size() << std::endl;
	//std::cout << "faults " << total_faults << " accessed " << total_accessed << std::endl;
	std::cout << "Page fault rate: " << page_fault_rate << std::endl;
	std::cout << "Most accessed VPN: " << most_accessed_vpn << std::endl;
	std::cout << "Number of bytes read: " << total_bytes_read << std::endl;
	std::cout << "Number of bytes written: " << total_bytes_write << std::endl;
	std::cout << "Memory footprint: " << (page_size * (1 + vpn_tracker.size())) << std::endl;

	delete [] in_memory;

	// uint64_t hex_value = 0;
	// std::cin >> std::hex >> hex_value;

	// std::cout << std::hex << get_VPN(hex_value) << std::endl;

	return 0;
}
Example #18
0
static void
fis_load(int argc, char *argv[])
{
    char *name;
    struct fis_image_desc *img;
    CYG_ADDRESS mem_addr;
    bool mem_addr_set = false;
    bool show_cksum = false;
    struct option_info opts[3];
#if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
    unsigned long cksum;
#endif
    int num_options;
#if defined(CYGPRI_REDBOOT_ZLIB_FLASH) ||  defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
    bool decompress = false;
#endif
    void *err_addr;

    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
              (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 
              (void *)&show_cksum, (bool *)0, "display checksum");
    num_options = 2;
#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
    init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG, 
              (void *)&decompress, 0, "decompress");
    num_options++;
#endif

    CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");

    if (!scan_opts(argc, argv, 2, opts, num_options, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
    {
        fis_usage("invalid arguments");
        return;
    }
    if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
        diag_printf("No image '%s' found\n", name);
        return;
    }
    if (!mem_addr_set) {
        mem_addr = img->mem_base;
    }
    // Load image from FLASH into RAM
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
    if (!valid_address((void *)mem_addr)) {
        diag_printf("Not a loadable image - try using -b ADDRESS option\n");
        return;
    }
#endif
#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
    if (decompress) {
        int err;
        _pipe_t fis_load_pipe;
        _pipe_t* p = &fis_load_pipe;
        p->out_buf = (unsigned char*) mem_addr;
        p->out_max = p->out_size = -1;
        p->in_buf = (unsigned char*) img->flash_base;
        p->in_avail = img->data_length;

        err = (*_dc_init)(p);

        if (0 == err)
            err = (*_dc_inflate)(p);

        // Free used resources, do final translation of
        // error value.
        err = (*_dc_close)(p, err);

        if (0 != err && p->msg) {
            diag_printf("decompression error: %s\n", p->msg);
        } else {
            diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
        }

        // Set load address/top
        load_address = mem_addr;
        load_address_end = (unsigned long)p->out_buf;

        // Reload fis directory
        fis_read_directory();
    } else // dangling block
#endif
    {
        flash_read((void *)img->flash_base, (void *)mem_addr, img->size, (void **)&err_addr);

        // Set load address/top
        load_address = mem_addr;
        load_address_end = mem_addr + img->size;
        diag_printf("load address 0x%08lx end 0x%08lx, image length 0x%08lx\n",load_address,load_address_end,img->data_length);
    }
    entry_address = (unsigned long)img->entry_point;

#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
    cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);
    if (show_cksum) {
        diag_printf("Checksum: 0x%08lx\n", cksum);
    }
    // When decompressing, leave CRC checking to decompressor
    if (!decompress && img->file_cksum) {
        if (cksum != img->file_cksum) {
            diag_printf("** Warning - checksum failure.  stored: 0x%08lx, computed: 0x%08lx\n",
                        img->file_cksum, cksum);
            entry_address = (unsigned long)NO_MEMORY;
        }
    }
#endif
}
Example #19
0
void 
do_load(int argc, char *argv[])
{
    int res, num_options;
    int i, err;
    bool verbose, raw;
    bool base_addr_set, mode_str_set;
    char *mode_str;
#ifdef CYGPKG_REDBOOT_NETWORKING
    struct sockaddr_in host;
    bool hostname_set, port_set;
    unsigned int port;	// int because it's an OPTION_ARG_TYPE_NUM, 
                        // but will be cast to short
    char *hostname;
#endif
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
    bool flash_addr_set = false;
#endif
    bool decompress = false;
    int chan = -1;
#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
    bool chan_set;
#endif
    unsigned long base = 0;
    unsigned long end = 0;
    char type[4];
    char *filename = 0;
    struct option_info opts[9];
    connection_info_t info;
    getc_io_funcs_t *io = NULL;
    struct load_io_entry *io_tab;
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
    bool spillover_ok = false;
#endif

#ifdef CYGPKG_REDBOOT_NETWORKING
    memset((char *)&host, 0, sizeof(host));
    host.sin_len = sizeof(host);
    host.sin_family = AF_INET;
    host.sin_addr = my_bootp_info.bp_siaddr;
    host.sin_port = 0;
#endif

    init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG, 
              (void *)&verbose, 0, "verbose");
    init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG, 
              (void *)&raw, 0, "load raw data");
    init_opts(&opts[2], 'b', true, OPTION_ARG_TYPE_NUM, 
              (void *)&base, (bool *)&base_addr_set, "load address");
    init_opts(&opts[3], 'm', true, OPTION_ARG_TYPE_STR, 
              (void *)&mode_str, (bool *)&mode_str_set, "download mode (TFTP, xyzMODEM, or disk)");
    num_options = 4;
#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
    init_opts(&opts[num_options], 'c', true, OPTION_ARG_TYPE_NUM, 
              (void *)&chan, (bool *)&chan_set, "I/O channel");
    num_options++;
#endif
#ifdef CYGPKG_REDBOOT_NETWORKING
    init_opts(&opts[num_options], 'h', true, OPTION_ARG_TYPE_STR, 
              (void *)&hostname, (bool *)&hostname_set, "host name or IP address");
    num_options++;
    init_opts(&opts[num_options], 'p', true, OPTION_ARG_TYPE_NUM, 
              (void *)&port, (bool *)&port_set, "TCP port");
    num_options++;
#endif
#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
    init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG, 
              (void *)&decompress, 0, "decompress");
    num_options++;
#endif
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
    init_opts(&opts[num_options], 'f', true, OPTION_ARG_TYPE_NUM,
              (void *)&base, (bool *)&flash_addr_set, "flash address");
    num_options++;
#endif
    CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
    
    if (!scan_opts(argc, argv, 1, opts, num_options, 
                   (void *)&filename, OPTION_ARG_TYPE_STR, "file name")) {
        return;
    }
#ifdef CYGPKG_REDBOOT_NETWORKING
    if (hostname_set) {
        ip_route_t rt;
        if (!_gethostbyname(hostname, (in_addr_t *)&host)) {
            err_printf("Invalid host: %s\n", hostname);
            return;
        }
        /* check that the host can be accessed */
        if (__arp_lookup((ip_addr_t *)&host.sin_addr, &rt) < 0) {
            err_printf("Unable to reach host %s (%s)\n",
                        hostname, inet_ntoa((in_addr_t *)&host));
            return;
        }
    }
    if (port_set) 
	    host.sin_port = port;
#endif
    if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
        err_printf("Invalid I/O channel: %d\n", chan);
        return;
    }
    if (mode_str_set) {
        for (io_tab = __RedBoot_LOAD_TAB__; 
             io_tab != &__RedBoot_LOAD_TAB_END__;  io_tab++) {
            if (strncasecmp(&mode_str[0], io_tab->name, strlen(&mode_str[0])) == 0) {
                io = io_tab->funcs;
                break;
            }
        }
        if (!io) {
            diag_printf("Invalid 'mode': %s.  Valid modes are:", mode_str);
            for (io_tab = __RedBoot_LOAD_TAB__; 
                 io_tab != &__RedBoot_LOAD_TAB_END__;  io_tab++) {
                diag_printf(" %s", io_tab->name);
            }
            err_printf("\n");
        }
        if (!io) {
            return;
        }
        verbose &= io_tab->can_verbose;
        if (io_tab->need_filename && !filename) {
            diag_printf("File name required\n");
            err_printf("usage: load %s\n", usage);
            return;
        }
    } else {
        char *which = "";
        io_tab = (struct load_io_entry *)NULL;  // Default
#ifdef CYGPKG_REDBOOT_NETWORKING
#ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD        
        which = "TFTP";
        io = &tftp_io;
#elif defined(CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD)
        which = "HTTP";
        io = &http_io;
#endif
#endif
#if 0 //def CYGPKG_REDBOOT_FILEIO
        // Make file I/O default if mounted
	if (fileio_mounted) {
	    which = "file";
	    io = &fileio_io;
	}
#endif
        if (!io) {
#ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM
            which = "Xmodem";
            io = &xyzModem_io;
            verbose = false;
#else
            err_printf("No default protocol!\n");
            return;
#endif
        }
        diag_printf("Using default protocol (%s)\n", which);
    }
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
#ifdef  CYGBLD_REDBOOT_LOAD_INTO_FLASH
    if (flash_addr_set && flash_verify_addr((unsigned char *)base)) {
        if (!verify_action("Specified address (%p) is not believed to be in FLASH", (void*)base))
          return;
        spillover_ok = true;
    }
#endif
    if (base_addr_set && !valid_address((unsigned char *)base)) {
        if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))
            return;
        spillover_ok = true;
    }
#endif
    if (raw && !(base_addr_set 
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
                || flash_addr_set
#endif
        )) {
        err_printf("Raw load requires a memory address\n");
        return;
    }
    info.filename = filename;
    info.chan = chan;
    info.mode = io_tab ? io_tab->mode : 0;
#ifdef CYGPKG_REDBOOT_NETWORKING
    info.server = &host;
#endif
    res = redboot_getc_init(&info, io, verbose, decompress);
    if (res < 0) {
        return;
    }
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
    flash_load_start();
#endif
    // Stream open, process the data
    if (raw) {
        unsigned char *mp = (unsigned char *)base;
        err = 0;
        while ((res = redboot_getc()) >= 0) {
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
            if (flash_addr_set && flash_verify_addr(mp) && !spillover_ok) {
                // Only if there is no need to stop the download
                // before printing output can we ask confirmation
                // questions.
                redboot_getc_terminate(true);
                err_printf("*** Abort! RAW data spills over limit of FLASH at %p\n",(void*)mp);
                err = -1;
                break;
            }
#endif
            if (base_addr_set && !valid_address(mp) && !spillover_ok) {
                // Only if there is no need to stop the download
                // before printing output can we ask confirmation
                // questions.
                redboot_getc_terminate(true);
                err_printf("*** Abort! RAW data spills over limit of user RAM at %p\n",(void*)mp);
                err = -1;
                break;
            }
#endif
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
            if (flash_addr_set) {
              flash_load_write(mp, res);
              mp++;
              res++;
            } else
#endif
            *mp++ = res;
        }
        end = (unsigned long) mp;

        // Save load base/top
        load_address = base;
        load_address_end = end;
        entry_address = base;           // best guess

        redboot_getc_terminate(false);
        if (0 == err)
            diag_printf("Raw file loaded %p-%p, assumed entry at %p\n", 
                        (void *)base, (void *)(end - 1), (void*)base);
    } else {
        // Read initial header - to determine file [image] type
        for (i = 0;  i < sizeof(type);  i++) {
            if ((res = redboot_getc()) < 0) {
                err = getc_info.err;
                break;
            } 
            type[i] = res;
        }
        if (res >= 0) {
            redboot_getc_rewind();  // Restore header to stream
            // Treat data as some sort of executable image
            if (strncmp(&type[1], "ELF", 3) == 0) {
                end = load_elf_image(redboot_getc, base);
            } else if ((type[0] == 'S') &&
                       ((type[1] >= '0') && (type[1] <= '9'))) {
		end = load_srec_image(redboot_getc, base);
            } else {
                redboot_getc_terminate(true);
                err_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);
            }
        }
    }
#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
    flash_load_finish();
#endif

    redboot_getc_close();  // Clean up
    return;
}
Example #20
0
/*************************************************************
Display the enforcer hit
*************************************************************/
static void enforcer_display_hit (const TCHAR *addressmode, uae_u32 pc, uaecptr addr)
{
	uae_u32 a7;
	uae_u32 sysbase;
	uae_u32 this_task;
	uae_u32 task_name;
	TCHAR *native_task_name = NULL;
	int i, j;
	static TCHAR buf[256],instrcode[256];
	static TCHAR lines[INSTRUCTIONLINES/2][256];
	static uaecptr bestpc_array[INSTRUCTIONLINES/2][5];
	static int bestpc_idxs[INSTRUCTIONLINES/2];
	TCHAR *enforcer_buf_ptr = enforcer_buf;
	uaecptr bestpc, pospc, nextpc, temppc;

	if (enforcer_hit)
		return; /* our function itself generated a hit ;), avoid endless loop */
	if (regs.vbr < 0x100 && addr >= 0x0c && addr < 0x80)
		return;

	enforcer_hit = 1;

	sysbase = get_long (4);
	if (sysbase < 0x100 || !valid_address (sysbase, 1000))
		goto end;
	this_task = get_long (sysbase + 276);
	if (this_task < 0x100 || !valid_address (this_task, 1000))
		goto end;

	task_name = get_long (this_task + 10); /* ln_Name */
	native_task_name = au ((char*)amiga2native (task_name, 100));
	/*if (strcmp(native_task_name,"c:MCP")!=0)
	{
	Exception (0x2d,0);
	}*/
	_tcscpy (enforcer_buf_ptr, _T("Enforcer Hit! Bad program\n"));
	enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

	_stprintf (buf, _T("Illegal %s: %08x"), addressmode, addr);
	_stprintf (enforcer_buf_ptr, _T("%-48sPC: %08x\n"), buf, pc);
	enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

	/* Data registers */
	_stprintf (enforcer_buf_ptr, _T("Data: %08x %08x %08x %08x %08x %08x %08x %08x\n"),
		m68k_dreg (regs, 0), m68k_dreg (regs, 1), m68k_dreg (regs, 2), m68k_dreg (regs, 3),
		m68k_dreg (regs, 4), m68k_dreg (regs, 5), m68k_dreg (regs, 6), m68k_dreg (regs, 7));
	enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

	/* Address registers */
	_stprintf (enforcer_buf_ptr, _T("Addr: %08x %08x %08x %08x %08x %08x %08x %08x\n"),
		m68k_areg (regs, 0), m68k_areg (regs, 1), m68k_areg (regs, 2), m68k_areg (regs, 3),
		m68k_areg (regs, 4), m68k_areg (regs, 5), m68k_areg (regs, 6), m68k_areg (regs, 7));
	enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

	/* Stack */
	a7 = m68k_areg (regs, 7);
	for (i = 0; i < 8 * STACKLINES; i++) {
		a7 += 4;
		if (!(i % 8)) {
			_tcscpy (enforcer_buf_ptr, _T("Stck:"));
			enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);
		}
		_stprintf (enforcer_buf_ptr, _T(" %08x"),get_long (a7));
		enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

		if (i%8 == 7)
			*enforcer_buf_ptr++ = '\n';
	}

	/* Segtracker output */
	if (enforcer_decode_hunk_and_offset (buf, pc)) {
		_tcscpy (enforcer_buf_ptr, buf);
		enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);
	}

	uae_u32 oldaddrs[BACKTRACELONGS];
	a7 = m68k_areg (regs, 7);
	for (i = 0; i < BACKTRACELONGS; i++) {
		uae_u32 addr;
		a7 += 4;
		addr = get_long (a7);
		for (j = 0; j < i; j++) {
			if (oldaddrs[j] == addr)
				break;
		}
		oldaddrs[i] = addr;
		if (j == i && addr != pc) {
			if (enforcer_decode_hunk_and_offset (buf, addr)) {
				int l = _tcslen (buf);

				if (ENFORCER_BUF_SIZE - (enforcer_buf_ptr - enforcer_buf) > l + 256) {
					_tcscpy (enforcer_buf_ptr, buf);
					enforcer_buf_ptr += l;
				}
			}
		}
	}

	/* Decode the instructions around the pc where the enforcer hit was caused.
	*
	* At first, the area before the pc, this not always done correctly because
	* it's done backwards */
	temppc = pc;

	memset (bestpc_array, 0, sizeof (bestpc_array));
	for (i = 0; i < INSTRUCTIONLINES / 2; i++)
		bestpc_idxs[i] = -1;

	for (i = 0; i < INSTRUCTIONLINES / 2; i++) {
		pospc = temppc;
		bestpc = 0;

		if (bestpc_idxs[i] == -1) {
			for (j = 0; j < 5; j++) {
				pospc -= 2;
				sm68k_disasm (buf, NULL, pospc, &nextpc);
				if (nextpc == temppc) {
					bestpc_idxs[i] = j;
					bestpc_array[i][j] = bestpc = pospc;
				}
			}
		} else {
			bestpc = bestpc_array[i][bestpc_idxs[i]];
		}

		if (!bestpc) {
			/* there was no best pc found, so it is high probable that
			* a former used best pc was wrong.
			*
			* We trace back and use the former best pc instead
			*/

			int former_idx;
			int leave = 0;

			do {
				if (!i) {
					leave = 1;
					break;
				}
				i--;
				former_idx = bestpc_idxs[i];
				bestpc_idxs[i] = -1;
				bestpc_array[i][former_idx] = 0;

				for (j = former_idx - 1; j >= 0; j--) {
					if (bestpc_array[i][j]) {
						bestpc_idxs[i] = j;
						break;
					}
				}
			} while (bestpc_idxs[i] == -1);
			if (leave)
				break;
			if (i)
				temppc = bestpc_array[i-1][bestpc_idxs[i-1]];
			else
				temppc = pc;
			i--; /* will be increased in after continue */
			continue;
		}

		sm68k_disasm (buf, instrcode, bestpc, NULL);
		_stprintf (lines[i], _T("%08x :   %-20s %s\n"), bestpc, instrcode, buf);
		temppc = bestpc;
	}

	i--;
	for (; i >= 0; i--) {
		_tcscpy (enforcer_buf_ptr, lines[i]);
		enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);
	}

	/* Now the instruction after the pc including the pc */
	temppc = pc;
	for (i = 0; i < (INSTRUCTIONLINES + 1) / 2; i++) {
		sm68k_disasm (buf, instrcode, temppc, &nextpc);
		_stprintf (enforcer_buf_ptr, _T("%08x : %s %-20s %s\n"), temppc,
			(i == 0 ? _T("*") : _T(" ")), instrcode, buf);
		enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);
		temppc = nextpc;
	}

	if (!native_task_name)
		native_task_name = my_strdup(_T("Unknown"));
	_stprintf (enforcer_buf_ptr, _T("Name: \"%s\"\n\n"), native_task_name);
	enforcer_buf_ptr += _tcslen (enforcer_buf_ptr);

	console_out (enforcer_buf);
	write_log (_T("%s"), enforcer_buf);
	if (!debug_enforcer()) {
		sleep_millis (5);
		doflashscreen ();
	}

end:
	xfree (native_task_name);
	enforcer_hit = 0;
}
Example #21
0
void uadecore_get_amiga_message(void)
{
  uae_u8 *ptr;
  uae_u8 *nameptr;
  int x;
  unsigned int mins, maxs, curs;
  int status;
  int src, dst, len;
  size_t off;
  char tmpstr[256];
  char *srcstr, *dststr;
  struct uade_file *f;
  uint32_t *u32ptr;
  uint8_t space[256];
  struct uade_msg *um = (struct uade_msg *) space;

  x = amiga_get_u32(SCORE_INPUT_MSG);  /* message type from amiga */

  switch (x) {

  case AMIGAMSG_SONG_END:
    uadecore_song_end("player", 0);
    break;

  case AMIGAMSG_SUBSINFO:
    mins = amiga_get_u32(SCORE_MIN_SUBSONG);
    maxs = amiga_get_u32(SCORE_MAX_SUBSONG);
    curs = amiga_get_u32(SCORE_CUR_SUBSONG);
    /* Brain damage in TFMX BC Kid Despair */
    if (maxs < mins) {
      uadecore_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs);
      maxs = mins;
    }
    /* Brain damage in Bubble bobble custom */
    if (curs > maxs) {
      uadecore_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs);
      maxs = curs;
    }
    um->msgtype = UADE_REPLY_SUBSONG_INFO;
    um->size = 12;
    u32ptr = (uint32_t *) um->data;
    u32ptr[0] = htonl(mins);
    u32ptr[1] = htonl(maxs);
    u32ptr[2] = htonl(curs);
    if (uade_send_message(um, &uadecore_ipc)) {
      fprintf(stderr, "uadecore: Could not send subsong info message.\n");
      exit(1);
    }
    break;

  case AMIGAMSG_PLAYERNAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_PLAYERNAME, tmpstr, &uadecore_ipc);
    break;

  case AMIGAMSG_MODULENAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_MODULENAME, tmpstr, &uadecore_ipc);
    break;

  case AMIGAMSG_FORMATNAME:
    strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr);
    uade_send_string(UADE_REPLY_FORMATNAME, tmpstr, &uadecore_ipc);
    break;

  case AMIGAMSG_GENERALMSG:
    uadecore_send_debug((char *) get_real_address(0x204));
    break;

  case AMIGAMSG_CHECKERROR:
    uadecore_song_end("module check failed", 1);
    break;

  case AMIGAMSG_SCORECRASH:
    if (uadecore_debug) {
      fprintf(stderr, "uadecore: Score crashed.\n");
      activate_debugger();
      break;
    }
    uadecore_song_end("score crashed", 1);
    break;

  case AMIGAMSG_SCOREDEAD:
     if (uadecore_debug) {
      fprintf(stderr, "uadecore: Score is dead.\n");
      activate_debugger();
      break;
    }
     uadecore_song_end("score died", 1);
    break;

  case AMIGAMSG_LOADFILE:
    /*
     * Load a file named at 0x204 (name pointer) to address pointed by
     * 0x208 and insert the length to 0x20C.
     * For example, R-Type (TFMX format) uses this.
     */
    src = amiga_get_u32(0x204);
    if (!uade_valid_string(src)) {
	    fprintf(stderr, "uadecore: Load name in invalid address range.\n");
	    break;
    }
    nameptr = get_real_address(src);
    f = lookup_amiga_file_cache((const char *) nameptr);
    if (f == NULL) {
	    uadecore_send_debug("load: request error: %s", nameptr);
	    exit(1);
    }
    if (f->data == NULL) {
	    /* File not found */
	    uadecore_send_debug("load: file not found: %s", nameptr);
	    break;
    }
    dst = amiga_get_u32(0x208);
    len = uade_safe_copy(dst, f->data, f->size);
    if (len == 0 && f->size > 0)
	    uadecore_send_debug("load: too long a file to copy");
    uade_put_long(0x20C, len);
    uadecore_send_debug("load: %s ptr 0x%x size 0x%x", nameptr, dst, len);
    break;

  case AMIGAMSG_READ:
    /* Used by "mdat.Crystal_Palace-1", for example */
    src = amiga_get_u32(0x204);
    if (!uade_valid_string(src)) {
	    fprintf(stderr, "uadecore: Read name in invalid address range.\n");
	    break;
    }
    nameptr = get_real_address(src);
    f = lookup_amiga_file_cache((const char *) nameptr);
    if (f == NULL) {
	    uadecore_send_debug("read: request error: %s", nameptr);
	    exit(1);
    }
    x = 0;
    if (f->data != NULL) {
	    dst = amiga_get_u32(0x208);
	    off = amiga_get_u32(0x20C);
	    len = amiga_get_u32(0x210);
	    if (off >= f->size) {
		    uadecore_send_debug("read: file offset over the file end");
	    } else {
		    size_t endpos = off + ((size_t) len);
		    size_t tocopy = len;
		    if (endpos > f->size)
			    tocopy = f->size - off;
		    x = uade_safe_copy(dst, f->data + off, tocopy);
	    }
	    uadecore_send_debug("read: %s dst 0x%x off 0x%x len 0x%x bytesread 0x%x", nameptr, dst, off, len, x);
    } else {
	    uadecore_send_debug("read: file not found: %s", nameptr);
    }
    uade_put_long(0x214, x);
    break;

  case AMIGAMSG_FILESIZE:
    /* Used by "mdat.Crystal_Palace-1", for example */
    src = amiga_get_u32(0x204);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: Filesize name in invalid address range.\n");
      break;
    }
    nameptr = get_real_address(src);
    f = lookup_amiga_file_cache((const char *) nameptr);
    if (f == NULL) {
	    uadecore_send_debug("filesize: request error: %s", nameptr);
	    exit(1);
    }
    len = 0;
    x = 0;
    if (f->data != NULL) {
	    len = f->size;
	    x = -1;
	    uadecore_send_debug("filesize: file %s res 0x%x", nameptr, len);
    } else {
	    /* Note, f->size == -1 if file does not exist */
	    uadecore_send_debug("filesize: file not found: %s", nameptr);
    }
    uade_put_long(0x208, len);
    uade_put_long(0x20C, x);
    break;

  case AMIGAMSG_TIME_CRITICAL:
    uadecore_time_critical = amiga_get_u32(0x204) ? 1 : 0;
    if (speed_hack < 0) {
      /* a negative value forbids use of speed hack */
      uadecore_time_critical = 0;
    }
    break;

  case AMIGAMSG_GET_INFO:
    src = amiga_get_u32(0x204);
    dst = amiga_get_u32(0x208);
    len = amiga_get_u32(0x20C);
    if (!uade_valid_string(src)) {
      fprintf(stderr, "uadecore: get info: Invalid src: 0x%x\n", src);
      break;
    }
    if (len <= 0) {
      fprintf(stderr, "uadecore: get info: len = %d\n", len);
      break;
    }
    if (!valid_address(dst, len)) {
      fprintf(stderr, "uadecore: get info: Invalid dst: 0x%x\n", dst);
      break;
    }
    srcstr = (char *) get_real_address(src);
    dststr = (char *) get_real_address(dst);
    uadecore_send_debug("score issued an info request: %s (maxlen %d)", srcstr, len);
    len = get_info_for_ep(dststr, srcstr, len);
    /* Send printable debug */
    do {
      size_t i;
      size_t maxspace = sizeof space;
      if (len <= 0) {
	maxspace = 1;
      } else {
	if (len < maxspace)
	  maxspace = len;
      }
      for (i = 0; i < maxspace; i++) {
	space[i] = dststr[i];
	if (space[i] == 0)
	  space[i] = ' ';
      }
      if (i < maxspace) {
	space[i] = 0;
      } else {
	space[maxspace - 1] = 0;
      }
      uadecore_send_debug("reply to score: %s (total len %d)", space, len);
    } while (0);
    uade_put_long(0x20C, len);
    break;

  case AMIGAMSG_START_OUTPUT:
    uadecore_audio_output = 1;
    break;

  default:
    fprintf(stderr,"uadecore: Unknown message from score (%d)\n", x);
    break;
  }
}