Example #1
0
/**
 * Syscall information courtesy of Marcus Comstedt
 */
static void bios_sysinfo_vector( uint32_t syscallid )
{
    char *flash_segment, *flash_config;
    char *dest;
    DEBUG( "BIOS SYSINFO: r4 = %08X, r5 = %08X, r6 = %08x, r7= %08X", sh4r.r[4], sh4r.r[5], sh4r.r[6], sh4r.r[7] );

    switch( sh4r.r[7] ) {
    case 0: /* SYSINFO_INIT */
        /* Initialize the region 8c000068 .. 8c00007f from the flash rom
         *   uint64_t system_id;
         *   char [5] system_props;
         *   char [3] zero_pad (?)
         *   char [8] settings;
         **/
        flash_segment = mem_get_region(FLASH_SYSINFO_SEGMENT);
        flash_config = bios_find_flash_config(FLASH_CONFIG_SEGMENT,FLASH_CONFIG_LENGTH);
        dest = mem_get_region( 0x8c000068 );
        memset( dest, 0, 24 );
        memcpy( dest, flash_segment + 0x56, 8 );
        memcpy( dest + 8, flash_segment, 5 );
        if( flash_config != NULL ) {
            memcpy( dest+16, flash_config+2, 8 );
        }
        break;
    case 2: /* SYSINFO_ICON */
        /* Not supported yet */
        break;
    case 3: /* SYSINFO_ID */
        sh4r.r[0] = 0x8c000068;
        break;
    }
}
Example #2
0
gboolean bios_boot_gdrom_disc( void )
{
    cdrom_disc_t disc = gdrom_get_current_disc();

    int status = gdrom_get_drive_status();
    if( status == CDROM_DISC_NONE ) {
        ERROR( "No disc in drive" );
        return FALSE;
    }

    /* Find the bootable data track (if present) */
    cdrom_track_t track = gdrom_disc_get_boot_track(disc);
    if( track == NULL ) {
        ERROR( "Disc is not bootable" );
        return FALSE;
    }
    uint32_t lba = track->lba;
    uint32_t sectors = cdrom_disc_get_track_size(disc,track);
    if( sectors < MIN_ISO_SECTORS ) {
        ERROR( "Disc is not bootable" );
        return FALSE;
    }
    /* Load the initial bootstrap into DC ram at 8c008000 */
    size_t length = BOOTSTRAP_SIZE;
    unsigned char *bootstrap = mem_get_region(BOOTSTRAP_LOAD_ADDR);
    if( cdrom_disc_read_sectors( disc, track->lba, BOOTSTRAP_SIZE/2048,
            CDROM_READ_DATA|CDROM_READ_MODE2_FORM1, bootstrap, &length ) !=
            CDROM_ERROR_OK ) {
        ERROR( "Disc is not bootable" );
        return FALSE;
    }

    /* Check the magic just to be sure */
    dc_bootstrap_head_t metadata = (dc_bootstrap_head_t)bootstrap;
    if( memcmp( metadata->magic, BOOTSTRAP_MAGIC, BOOTSTRAP_MAGIC_SIZE ) != 0 ) {
        ERROR( "Disc is not bootable (missing dreamcast bootstrap)" );
        return FALSE;
    }

    /* Get the initial program from the bootstrap (usually 1ST_READ.BIN) */
    char program_name[18] = "/";
    memcpy(program_name+1, metadata->boot_file, 16);
    program_name[17] = '\0';
    for( int i=16; i >= 0 && program_name[i] == ' '; i-- ) {
        program_name[i] = '\0';
    }

    /* Bootstrap is good. Now find the program in the actual filesystem... */
    unsigned char *program = mem_get_region(BINARY_LOAD_ADDR);
    gboolean isGDROM = (disc->disc_type == CDROM_DISC_GDROM );
    if( !bios_load_ipl( disc, track, program_name, program, !isGDROM ) )
        return FALSE;
    asic_enable_ide_interface(isGDROM);
    dreamcast_program_loaded( "", BOOTSTRAP_ENTRY_ADDR );
    return TRUE;
}
Example #3
0
void bios_gdrom_run_command( gdrom_queue_entry_t cmd )
{
    DEBUG( "BIOS GD command %d", cmd->cmd_code );
    cdrom_error_t status = CDROM_ERROR_OK;
    sh4ptr_t ptr;
    switch( cmd->cmd_code ) {
    case GD_CMD_INIT:
        /* *shrug* */
        cmd->status = GD_CMD_STATUS_DONE;
        break;
    case GD_CMD_GETTOC2:
        ptr = mem_get_region( cmd->params.toc2.buffer );
        status = gdrom_read_toc( ptr );
        if( status == CDROM_ERROR_OK ) {
            /* Convert data to little-endian */
            struct gdrom_toc *toc = (struct gdrom_toc *)ptr;
            for( unsigned i=0; i<99; i++ ) {
                toc->track[i] = ntohl(toc->track[i]);
            }
            toc->first = ntohl(toc->first);
            toc->last = ntohl(toc->last);
            toc->leadout = ntohl(toc->leadout);
        }
        break;
    case GD_CMD_PIOREAD:
    case GD_CMD_DMAREAD:
        ptr = mem_get_region( cmd->params.readcd.buffer );
        status = gdrom_read_cd( cmd->params.readcd.lba,
                cmd->params.readcd.count, 0x28, ptr, NULL );
        break;
    default:
        WARN( "Unknown BIOS GD command %d\n", cmd->cmd_code );
        cmd->status = GD_CMD_STATUS_ERROR;
        cmd->result[0] = GD_ERROR_SYSTEM;
        return;
    }

    switch( status ) {
    case CDROM_ERROR_OK:
        cmd->status = GD_CMD_STATUS_DONE;
        cmd->result[0] = GD_ERROR_OK;
        break;
    case CDROM_ERROR_NODISC:
        cmd->status = GD_CMD_STATUS_ERROR;
        cmd->result[0] = GD_ERROR_NO_DISC;
        break;
    default:
        cmd->status = GD_CMD_STATUS_ERROR;
        cmd->result[0] = GD_ERROR_SYSTEM;
    }
}
Example #4
0
void *sbrk(int incr)
{
  struct process_info *ppi = fd32_get_current_pi();
  BYTE *prev_heap_end = NULL;
  DWORD memlimit = ppi->memlimit;

  if (memlimit != 0) {
    prev_heap_end = (BYTE *)memlimit;
    if (incr > 0) {
      if (mem_get_region(memlimit, incr) == -1) {
        message("Ermmm... SBRK problem: cannot memget(%lx %x)\n",
			memlimit, incr);
        mem_dump();
        return 0;
      }
    } else if (incr < 0) {
      mem_free(memlimit + incr, -incr);
    }
    /* Change the memlimit */
    ppi->memlimit += incr;
  } else {
    message("sbrk error: Memory Limit == 0!\n");
    fd32_abort();
  }
  
  return prev_heap_end;
}
Example #5
0
void sort_dma_transfer( )
{
    sh4addr_t table_addr = MMIO_READ( ASIC, SORTDMATBL );
    sh4addr_t data_addr = MMIO_READ( ASIC, SORTDMADATA );
    int table_size = MMIO_READ( ASIC, SORTDMATSIZ );
    int addr_shift = MMIO_READ( ASIC, SORTDMAASIZ ) ? 5 : 0;
    int count = 1;

    uint32_t *table32 = (uint32_t *)mem_get_region( table_addr );
    uint16_t *table16 = (uint16_t *)table32;
    uint32_t next = table_size ? (*table32++) : (uint32_t)(*table16++);
    while(1) {
        next &= 0x07FFFFFF;
        if( next == 1 ) {
            next = table_size ? (*table32++) : (uint32_t)(*table16++);
            count++;
            continue;
        } else if( next == 2 ) {
            asic_event( EVENT_SORT_DMA );
            break;
        } 
        uint32_t *data = (uint32_t *)mem_get_region(data_addr + (next<<addr_shift));
        if( data == NULL ) {
            break;
        }

        uint32_t *poly = pvr2_ta_find_polygon_context(data, 128);
        if( poly == NULL ) {
            asic_event( EVENT_SORT_DMA_ERR );
            break;
        }
        uint32_t size = poly[6] & 0xFF;
        if( size == 0 ) {
            size = 0x100;
        }
        next = poly[7];
        pvr2_ta_write( (unsigned char *)data, size<<5 );
    }

    MMIO_WRITE( ASIC, SORTDMACNT, count );
    MMIO_WRITE( ASIC, SORTDMACTL, 0 );
}
Example #6
0
/**
 * Locate the active config block. FIXME: This isn't completely correct, but it works
 * under at least some circumstances. 
 */
static char *bios_find_flash_config( sh4addr_t segment, uint32_t length )
{
    char *start = mem_get_region(segment);
    char *p = start + 0x80;
    char *end = p + length;
    char *result = NULL;

    if( memcmp( start, FLASH_PARTITION_MAGIC, 16 ) != 0 )
        return NULL; /* Missing magic */
    while( p < end ) {
        if( p[0] == 0x05 && p[1] == 0 ) {
            result = p;
        }
        p += 0x40;
    }
    return result;
}
Example #7
0
static gboolean file_load_binary( const gchar *filename, int fd, ERROR *err )
{
    struct stat st;

    if( fstat( fd, &st ) == -1 ) {
        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
        return FALSE;
    }

    if( st.st_size > BINARY_MAX_SIZE ) {
        SET_ERROR( err, LX_ERR_FILE_INVALID, "Binary file '%s' is too large to fit in memory", filename );
        return FALSE;
    }

    sh4ptr_t target = mem_get_region( BINARY_LOAD_ADDR );
    if( read( fd, target, st.st_size ) != st.st_size ) {
        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
        return FALSE;
    }

    file_load_postload( filename, BINARY_LOAD_ADDR );
    return TRUE;
}
Example #8
0
static gboolean file_load_elf( const gchar *filename, int fd, ERROR *err )
{
    Elf32_Ehdr head;
    Elf32_Phdr phdr;
    Elf32_Shdr shdr;
    Elf32_Sym sym;
    int i;

    if( read( fd, &head, sizeof(head) ) != sizeof(head) )
        return FALSE;
    if( !is_sh4_elf(&head) ) {
        SET_ERROR( err, LX_ERR_FILE_INVALID, "File is not an SH4 ELF executable file" );
        return FALSE;
    }

    /* Program headers */
    for( i=0; i<head.e_phnum; i++ ) {
        lseek( fd, head.e_phoff + i*head.e_phentsize, SEEK_SET );
        read( fd, &phdr, sizeof(phdr) );
        if( phdr.p_type == PT_LOAD ) {
            lseek( fd, phdr.p_offset, SEEK_SET );
            sh4ptr_t target = mem_get_region( phdr.p_vaddr );
            read( fd, target, phdr.p_filesz );
            if( phdr.p_memsz > phdr.p_filesz ) {
                memset( target + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz );
            }
        }
    }

    /* Find symbol table */
    uint32_t symtabOffset = 0, symtabSize = 0, symtabEntSize = 0;
    uint32_t strtabOffset = 0, strtabSize = 0;
    for( int i = 0; i < head.e_shnum; i++ ) {
        lseek( fd, head.e_shoff + i * head.e_shentsize, SEEK_SET );
        read( fd, &shdr, sizeof( shdr ) );
        if( shdr.sh_type == SHT_SYMTAB ) {
            symtabOffset = shdr.sh_offset;
            symtabSize = shdr.sh_size;
            symtabEntSize = shdr.sh_entsize;
        } else if( shdr.sh_type == SHT_STRTAB ) {
            strtabOffset = shdr.sh_offset;
            strtabSize = shdr.sh_size;
        }
    }
    /* Extract symbols */
    if( symtabOffset != 0 && strtabOffset != 0 ) {
        unsigned numSymtabEntries = symtabSize / symtabEntSize;
        char *data = g_malloc( numSymtabEntries * sizeof( struct sh4_symbol ) + strtabSize );
        struct sh4_symbol *symtab = ( struct sh4_symbol * )data;
        char *strings = data + ( numSymtabEntries * sizeof( struct sh4_symbol ) );
        lseek( fd, strtabOffset, SEEK_SET );
        read( fd, strings, strtabSize );
        strings[strtabSize-1] = '\0'; /* Should already be 0, but just in case */
        for( int i = 0; i < numSymtabEntries; i++ ) {
            lseek( fd, symtabOffset + ( i * symtabEntSize ), SEEK_SET );
            read( fd, &sym, sizeof( sym ) );
            if( sym.st_name < strtabSize )
            	symtab[i].name = &strings[sym.st_name];
            else
            	symtab[i].name = NULL;
            symtab[i].address = sym.st_value;
            symtab[i].size = sym.st_size;
        }
        sh4_set_symbol_table( symtab, numSymtabEntries, ( sh4_symtab_destroy_cb )free );
    }

    file_load_postload( filename, head.e_entry );
    return TRUE;
}