⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 *  SHELL_ERROR_OVERFLOW :  Range overflow
 *  SHELL_ERROR_TLB :       Mapped address with no match in TLB
 *  SHELL_ERROR_TLB_WP :    Write access to mapped write protected address
 *  SHELL_ERROR_RAM_RANGE : Address in unused RAM space
 *
 ************************************************************************/
UINT32
sys_validate_range(
    UINT32 addr,	/* Start address				*/
    UINT32 count,	/* Byte count					*/
    UINT8  size,	/* Access size (number of bytes)		*/
    bool   write )	/* Write access					*/
{
    UINT32  last, pagesize;
    bool    sys_mmu_tlb;
    UINT32  phys;
    UINT32  rc = OK;

    if( !sys_legal_align( addr, size ) )
        rc = SHELL_ERROR_ALIGN;

    if( (rc == OK) && !sys_legal_align( count, size ) )
        rc = SHELL_ERROR_ALIGN;

    if( (rc == OK) && (count == 0) )
        return OK;

    if( rc == OK )
    {
        last = addr + (count - size);
 
        if( last < addr )
	    rc = SHELL_ERROR_OVERFLOW;
    }

    if( rc == OK )
    {
        /* Determine physical addresses based on MMU and
	 * validate RAM range.
	 */

        SYSCON_read( SYSCON_CPU_TLB_AVAIL_ID,
	             (void *)&sys_mmu_tlb,
	             sizeof( bool ) );

	if( !sys_mmu_tlb )
	{
	    /*  Assume Fixed Mapping MMU.
	     *  We check for KSEG0/KSEG1 only (TBD : Could be improved).
	     */

            if( 
	        ((KSEG0( addr ) == addr) && (KSEG0( last ) == last)) ||
	        ((KSEG1( addr ) == addr) && (KSEG1( last ) == last)) ) 
	    {
	        /* Range contained within KSEG0 or KSEG1 */
                return sys_validate_ram_range( PHYS(addr), 
					       PHYS(last) );
	    }
	    else 
	        return SHELL_ERROR_ADDRESS;
	}
	else
	{
            /* MMU = TLB */

            while( (rc == OK) && (addr <= last) )
            {
                if( KSEG0( addr ) == addr ) 
	        {
	            /*  KSEG0, check if range leaves KSEG0 */

                    if( KSEG0( last ) == last )
	            {
		        /* Range contained within KSEG0 */
	                rc = sys_validate_ram_range( PHYS(addr), 
						     PHYS(last) );

			if( rc == OK )
			    return OK;
	            }
	            else
		    {
		        /* Range overflows KSEG0 */
	                rc = sys_validate_ram_range( PHYS(addr), 
						     PHYS(KSEG1BASE-size) );

			if( rc == OK )
			{
			    /* Continue in KSEG1 */
	                    addr = KSEG1BASE;
			}
		    }
		}
                else if( KSEG1( addr ) == addr ) 
	        {
	            /*  KSEG1, check if range leaves KSEG1 */

                    if( KSEG1( last ) == last )
	            {
		        /* Range contained within KSEG1 */
	                rc = sys_validate_ram_range( PHYS(addr), 
						     PHYS(last) );

			if( rc == OK )
			    return OK;
	            }
	            else
		    {
		        /* Range overflows KSEG1 */
	                rc = sys_validate_ram_range( PHYS(addr), 
						     PHYS(KSSEGBASE-size) );
	                
			if( rc == OK )
			{
			    /* Continue in KSSEG */
			    addr = KSSEGBASE;
			}
		    }
		}
	        else
	        {
	            /* KUSEG/KSSEG/KSEG3, i.e. TLB mapped */
	            switch( sys_tlb_lookup( addr, &phys, &pagesize ) )
                    {
		      case SYS_TLB_WP :
		        if( write )
			    rc = SHELL_ERROR_TLB_WP;
			/* Fallthrough !! */   
		      case SYS_TLB_OK :
		        if( rc == OK )
			{
			    rc = sys_validate_ram_range( phys, 
						         phys + pagesize - size );
			}

	                if( rc == OK )
			{
	                    /* Calc next page start */
			    addr += pagesize;
			}
			break;
		      case SYS_TLB_NOTFOUND :
		      case SYS_TLB_NOTVALID :
		      default : /* Should not happen */
		        rc = SHELL_ERROR_TLB;
			break;
	            }
		}
    	    }
        }
    }

    if(	(rc == SHELL_ERROR_TLB)		||
        (rc == SHELL_ERROR_TLB_WP) )
    {
        sprintf( msg, "Address = 0x%08x", addr );
	shell_error_data = msg;
    }

    return rc;
}


/************************************************************************
 *
 *                          sys_kseg0
 *  Description :
 *  -------------
 *
 *  Determine KSEG0 address corresponding to input address.
 * 
 *  In case input address is TLB mapped, a lookup is performed in the
 *  TLB to determine the physical address. Then, the corresponding
 *  KSEG0 address is calculated.
 *
 *  In case input address is in KSEG1 range, it is converted to KSEG0.
 *
 *  Return values :
 *  ---------------
 *
 *  TRUE if conversion was successfull, otherwise FALSE
 *
 ************************************************************************/
bool
sys_kseg0(
    UINT32 addr,		/* Address to be converted		*/
    UINT32 *kseg0addr )		/* OUT : Converted address		*/
{
    UINT32 phys, pagesize;
    bool   sys_mmu_tlb;

    SYSCON_read( SYSCON_CPU_TLB_AVAIL_ID,
                 (void *)&sys_mmu_tlb,
	         sizeof( bool ) );

    if( sys_mmu_tlb )
    {
        /* MMU = TLB */
        if( (KSEG0( addr ) == addr) || (KSEG1( addr ) == addr) )
        {
            *kseg0addr = KSEG0(addr);
	    return TRUE;
        }
	else
	{
	    if( sys_tlb_lookup( addr, &phys, &pagesize ) == SYS_TLB_OK )
	    {
	        *kseg0addr = KSEG0( phys );
		return TRUE;
	    }
	    else
	        return FALSE;
	}
    }
    else
    {
	/* Assume Fixed Mapping MMU */
        if( (KSEG0( addr ) == addr) || (KSEG1( addr ) == addr) )
        {
            *kseg0addr = KSEG0(addr);
	    return TRUE;
        }
	else
	    return FALSE;
    }
}


/************************************************************************
 *
 *                          sys_legal_align
 *  Description :
 *  -------------
 *
 *  Determine if alignment of address is legal
 *
 *  Return values :
 *  ---------------
 *
 *  TRUE -> Legal alignment, FALSE -> Illegal alignment
 *
 ************************************************************************/
bool
sys_legal_align(
    UINT32 address,
    UINT32 align )
{
    return (address == (address & ~(align - 1))) ? TRUE : FALSE;
}


/************************************************************************
 *  Implementation : static functions
 ************************************************************************/


/************************************************************************
 *                          determine_dev
 ************************************************************************/
static bool
determine_dev( 
    UINT32 port, 
    UINT32 *major, 
    UINT32 *minor )
{
    UINT32 id_major, id_minor;

    if( port == PORT_TTY0 )
    {
	id_major = SYSCON_COM_TTY0_MAJOR;
	id_minor = SYSCON_COM_TTY0_MINOR;
    }
    else if( port == PORT_TTY1 )
    {	
	id_major = SYSCON_COM_TTY1_MAJOR;
	id_minor = SYSCON_COM_TTY1_MINOR;
    }
    else
	return FALSE;

    SYSCON_read( id_major,
	         (void *)(major),
		 sizeof(UINT32) );

    SYSCON_read( id_minor,
	         (void *)(minor),
	         sizeof(UINT32) );
		     
    return TRUE;
}


/************************************************************************
 *
 *                          sys_validate_ram_range
 *  Description :
 *  -------------
 *
 *  Perform range check relating to RAM use.
 *
 *  The range defined by parameters 'start' and 'last' is checked with
 *  relation to RAM use.
 *
 *  The memory map allocates a range for RAM. In case the RAM
 *  module does not occupy this entire range, there will be an
 *  "empty" RAM range. We detect whether the specified range
 *  hits this empty RAM range. If so, we return an error code. 
 *  Otherwise, OK is returned.
 *
 *  In case of a hit in the unused range, shell_err_data is set to a 
 *  text string stating the illegal address. This may be used by 
 *  error handling.
 *
 *  Return values :
 *  ---------------
 *
 *  OK :		    No error
 *  SHELL_ERROR_RAM_RANGE : Error detected
 *
 ************************************************************************/
static UINT32
sys_validate_ram_range(
    UINT32 start,		/* Start address (physical)		*/
    UINT32 last )		/* Last address (physical)		*/
{
    static void    *ram_base;
    static UINT32  ram_actual_size, ram_size;
    static UINT32  ram_range_unused_start;
    static UINT32  ram_range_unused_last;
    static bool    first = TRUE;
    
    if( first )
    {
        /* Self-initialisation */

        first = FALSE;

        SYSCON_read( SYSCON_BOARD_SYSTEMRAM_ACTUAL_SIZE_ID,
		     (void *)&ram_actual_size,
		     sizeof(UINT32) );

        SYSCON_read( SYSCON_BOARD_SYSTEMRAM_BASE_ID,
		     (void *)&ram_base,
		     sizeof(void *) );

        SYSCON_read( SYSCON_BOARD_SYSTEMRAM_SIZE_ID,
		     (void *)&ram_size,
		     sizeof(UINT32) );

        ram_range_unused_start = (UINT32)ram_base + ram_actual_size;
        ram_range_unused_last  = (UINT32)ram_base + ram_size - 1;
    }

    if( ram_actual_size == ram_size )
        return OK;  /* No unused RAM space */
    
    if( (start >= ram_range_unused_start) &&
        (start <= ram_range_unused_last) )
    {
        sprintf( msg, "Address = 0x%08x", start );
	shell_error_data = msg;

	return SHELL_ERROR_RAM_RANGE;
    }

    if( (last >= ram_range_unused_start) &&
        (last <= ram_range_unused_last) )
    {
        sprintf( msg, "Address = 0x%08x", ram_range_unused_start );
	shell_error_data = msg;

	return SHELL_ERROR_RAM_RANGE;
    }

    return OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -