mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
This patches copies all needed ppc files to qemu and modifies them. The generated OpenBIOS image must be loaded at adresse 0xfff00000 by Qemu. It is able to load Yaboot from disk and Yaboot is able to load Linux, but Linux hangs somewhere... of course it needs more work (but this cleans up my patch queue). Thank you to Blue Swirl and Aurelien Jarno for their help. Signed-off-by: Laurent Vivier <Laurent@lvivier.info> git-svn-id: svn://coreboot.org/openbios/openbios-devel@301 f158a5a8-5612-0410-a976-696ce0be7e32
305 lines
5.8 KiB
C
305 lines
5.8 KiB
C
/*
|
|
* Creation Date: <2004/08/28 18:38:22 greg>
|
|
* Time-stamp: <2004/08/28 18:38:22 greg>
|
|
*
|
|
* <methods.c>
|
|
*
|
|
* Misc device node methods
|
|
*
|
|
* Copyright (C) 2004 Greg Watson
|
|
*
|
|
* Based on MOL specific code which is
|
|
*
|
|
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2
|
|
*
|
|
*/
|
|
|
|
#include "openbios/config.h"
|
|
#include "openbios/bindings.h"
|
|
#include "openbios/drivers.h"
|
|
#include "libc/string.h"
|
|
#include "qemu/qemu.h"
|
|
#include "ofmem.h"
|
|
#include "ppc/processor.h"
|
|
|
|
/************************************************************************/
|
|
/* RTAS (run-time abstraction services) */
|
|
/************************************************************************/
|
|
|
|
#ifdef USE_RTAS
|
|
DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
|
|
|
|
/* ( physbase -- rtas_callback ) */
|
|
static void
|
|
rtas_instantiate( void )
|
|
{
|
|
int physbase = POP();
|
|
int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
|
|
ulong virt;
|
|
|
|
while( s < size )
|
|
s += 0x1000;
|
|
virt = ofmem_claim_virt( 0, s, 0x1000 );
|
|
ofmem_map( physbase, virt, s, -1 );
|
|
memcpy( (char*)virt, of_rtas_start, size );
|
|
|
|
printk("RTAS instantiated at %08x\n", physbase );
|
|
flush_icache_range( (char*)virt, (char*)virt + size );
|
|
|
|
PUSH( physbase );
|
|
}
|
|
|
|
NODE_METHODS( rtas ) = {
|
|
{ "instantiate", rtas_instantiate },
|
|
{ "instantiate-rtas", rtas_instantiate },
|
|
};
|
|
#endif
|
|
|
|
|
|
/************************************************************************/
|
|
/* tty */
|
|
/************************************************************************/
|
|
|
|
DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
|
|
|
|
/* ( addr len -- actual ) */
|
|
static void
|
|
tty_read( void )
|
|
{
|
|
int ch, len = POP();
|
|
char *p = (char*)POP();
|
|
int ret=0;
|
|
|
|
if( len > 0 ) {
|
|
ret = 1;
|
|
ch = getchar();
|
|
if( ch >= 0 ) {
|
|
*p = ch;
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
}
|
|
PUSH( ret );
|
|
}
|
|
|
|
/* ( addr len -- actual ) */
|
|
static void
|
|
tty_write( void )
|
|
{
|
|
int i, len = POP();
|
|
char *p = (char*)POP();
|
|
for( i=0; i<len; i++ )
|
|
putchar( *p++ );
|
|
RET( len );
|
|
}
|
|
|
|
NODE_METHODS( tty ) = {
|
|
{ "read", tty_read },
|
|
{ "write", tty_write },
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* client interface 'quiesce' */
|
|
/************************************************************************/
|
|
|
|
DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" );
|
|
|
|
/* ( -- ) */
|
|
static void
|
|
ciface_quiesce( ulong args[], ulong ret[] )
|
|
{
|
|
#if 0
|
|
ulong msr;
|
|
/* This seems to be the correct thing to do - but I'm not sure */
|
|
asm volatile("mfmsr %0" : "=r" (msr) : );
|
|
msr &= ~(MSR_IR | MSR_DR);
|
|
asm volatile("mtmsr %0" :: "r" (msr) );
|
|
#endif
|
|
}
|
|
|
|
/* ( -- ms ) */
|
|
static void
|
|
ciface_milliseconds( ulong args[], ulong ret[] )
|
|
{
|
|
extern unsigned long get_timer_freq(void);
|
|
static ulong mticks=0, usecs=0;
|
|
ulong t;
|
|
|
|
asm volatile("mftb %0" : "=r" (t) : );
|
|
if( mticks )
|
|
usecs += get_timer_freq() / 1000000 * ( t-mticks );
|
|
mticks = t;
|
|
|
|
PUSH( usecs/1000 );
|
|
}
|
|
|
|
|
|
NODE_METHODS( ciface ) = {
|
|
{ "quiesce", ciface_quiesce },
|
|
{ "milliseconds", ciface_milliseconds },
|
|
};
|
|
|
|
|
|
/************************************************************************/
|
|
/* MMU/memory methods */
|
|
/************************************************************************/
|
|
|
|
DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
|
|
DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
|
|
DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" );
|
|
|
|
|
|
/* ( phys size align --- base ) */
|
|
static void
|
|
mem_claim( void )
|
|
{
|
|
int align = POP();
|
|
int size = POP();
|
|
int phys = POP();
|
|
int ret = ofmem_claim_phys( phys, size, align );
|
|
|
|
if( ret == -1 ) {
|
|
printk("MEM: claim failure\n");
|
|
throw( -13 );
|
|
return;
|
|
}
|
|
PUSH( ret );
|
|
}
|
|
|
|
/* ( phys size --- ) */
|
|
static void
|
|
mem_release( void )
|
|
{
|
|
POP(); POP();
|
|
}
|
|
|
|
/* ( phys size align --- base ) */
|
|
static void
|
|
mmu_claim( void )
|
|
{
|
|
int align = POP();
|
|
int size = POP();
|
|
int phys = POP();
|
|
int ret = ofmem_claim_virt( phys, size, align );
|
|
|
|
if( ret == -1 ) {
|
|
printk("MMU: CLAIM failure\n");
|
|
throw( -13 );
|
|
return;
|
|
}
|
|
PUSH( ret );
|
|
}
|
|
|
|
/* ( phys size --- ) */
|
|
static void
|
|
mmu_release( void )
|
|
{
|
|
POP(); POP();
|
|
}
|
|
|
|
/* ( phys virt size mode -- [ret???] ) */
|
|
static void
|
|
mmu_map( void )
|
|
{
|
|
int mode = POP();
|
|
int size = POP();
|
|
int virt = POP();
|
|
int phys = POP();
|
|
int ret;
|
|
|
|
/* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
|
|
ret = ofmem_map( phys, virt, size, mode );
|
|
|
|
if( ret ) {
|
|
printk("MMU: map failure\n");
|
|
throw( -13 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* ( virt size -- ) */
|
|
static void
|
|
mmu_unmap( void )
|
|
{
|
|
POP(); POP();
|
|
}
|
|
|
|
/* ( virt -- false | phys mode true ) */
|
|
static void
|
|
mmu_translate( void )
|
|
{
|
|
ulong mode;
|
|
int virt = POP();
|
|
int phys = ofmem_translate( virt, &mode );
|
|
|
|
if( phys == -1 ) {
|
|
PUSH( 0 );
|
|
} else {
|
|
PUSH( phys );
|
|
PUSH( (int)mode );
|
|
PUSH( -1 );
|
|
}
|
|
}
|
|
|
|
/* ( virt size align -- baseaddr|-1 ) */
|
|
static void
|
|
ciface_claim( void )
|
|
{
|
|
int align = POP();
|
|
int size = POP();
|
|
int virt = POP();
|
|
int ret = ofmem_claim( virt, size, align );
|
|
|
|
/* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
|
|
PUSH( ret );
|
|
}
|
|
|
|
/* ( virt size -- ) */
|
|
static void
|
|
ciface_release( void )
|
|
{
|
|
POP();
|
|
POP();
|
|
}
|
|
|
|
|
|
NODE_METHODS( memory ) = {
|
|
{ "claim", mem_claim },
|
|
{ "release", mem_release },
|
|
};
|
|
|
|
NODE_METHODS( mmu ) = {
|
|
{ "claim", mmu_claim },
|
|
{ "release", mmu_release },
|
|
{ "map", mmu_map },
|
|
{ "unmap", mmu_unmap },
|
|
{ "translate", mmu_translate },
|
|
};
|
|
|
|
NODE_METHODS( mmu_ciface ) = {
|
|
{ "claim", ciface_claim },
|
|
{ "release", ciface_release },
|
|
};
|
|
|
|
|
|
/************************************************************************/
|
|
/* init */
|
|
/************************************************************************/
|
|
|
|
void
|
|
node_methods_init( void )
|
|
{
|
|
#ifdef USE_RTAS
|
|
REGISTER_NODE( rtas );
|
|
#endif
|
|
REGISTER_NODE( ciface );
|
|
REGISTER_NODE( memory );
|
|
REGISTER_NODE( mmu );
|
|
REGISTER_NODE( mmu_ciface );
|
|
REGISTER_NODE( tty );
|
|
}
|