aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/emul_chirp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/ppc/emul_chirp.c')
-rw-r--r--sim/ppc/emul_chirp.c762
1 files changed, 530 insertions, 232 deletions
diff --git a/sim/ppc/emul_chirp.c b/sim/ppc/emul_chirp.c
index 9c20262..9eb3a4e 100644
--- a/sim/ppc/emul_chirp.c
+++ b/sim/ppc/emul_chirp.c
@@ -74,11 +74,135 @@ struct _os_emul_data {
unsigned_word catching_instruction_ea;
cap *phandles;
device *root;
+ chirp_services *services;
};
+/* Read in the argument list and make the most basic check that number
+ of argumnets are consistent with what was expected */
+
+static int
+chirp_read_args(void *args,
+ int sizeof_args,
+ int n_args,
+ int n_returns,
+ os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct base_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ } *base;
+ emul_read_buffer(args, data->arguments,
+ sizeof_args,
+ processor, cia);
+ base = (struct base_args*)args;
+ if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) {
+ TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n",
+ (long)T2H_4(base->n_args),
+ (long)T2H_4(base->n_returns)));
+ return -1;
+ }
+ return 0;
+}
+
+
/* OpenBoot emulation functions */
+/* client interface */
+
+static int
+chirp_emul_test(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct test_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 name; /*string*/
+ /*out*/
+ unsigned32 missing;
+ } args;
+ char name[32];
+ chirp_services *service = data->services;
+ /* read in the arguments */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ emul_read_string(name, T2H_4(args.name), sizeof(name),
+ processor, cia);
+ TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
+ /* see if we know about the service */
+ while (service->name != NULL && strcmp(service->name, name) != 0) {
+ service++;
+ }
+ if (service->name == NULL)
+ args.missing = -1;
+ else
+ args.missing = 0;
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("test - out - missing=%ld\n",
+ (long)args.missing));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
+ return 0;
+}
+
+
+/* Device tree */
+
+static int
+chirp_emul_peer(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct peer_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 phandle;
+ /*out*/
+ unsigned32 sibling_phandle;
+ } args;
+ device *dev;
+ device *sibling_dev = NULL;
+ /* read in the arguments */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ dev = cap_internal(data->phandles, args.phandle);
+ TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.phandle),
+ (unsigned long)dev,
+ (dev == NULL ? "" : device_name(dev))));
+ /* find the peer */
+ if (dev == NULL && args.phandle != 0)
+ return -1;
+ if (args.phandle == 0)
+ sibling_dev = data->root;
+ else
+ sibling_dev = device_sibling(dev);
+ if (sibling_dev == NULL)
+ args.sibling_phandle = 0;
+ else
+ args.sibling_phandle = cap_external(data->phandles, sibling_dev);
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.sibling_phandle),
+ (unsigned long)sibling_dev,
+ (sibling_dev == NULL
+ ? ""
+ : device_name(sibling_dev))));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
+ return 0;
+}
+
static int
chirp_emul_child(os_emul_data *data,
cpu *processor,
@@ -95,21 +219,15 @@ chirp_emul_child(os_emul_data *data,
} args;
device *dev;
device *child_dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("child - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read the arguments in */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
dev = cap_internal(data->phandles, args.phandle);
TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
(dev == NULL ? "" : device_name(dev))));
+ /* find a child */
if (dev == (device*)0)
return -1;
child_dev = device_child(dev);
@@ -117,6 +235,7 @@ chirp_emul_child(os_emul_data *data,
args.child_phandle = 0;
else
args.child_phandle = cap_external(data->phandles, child_dev);
+ /* write the result out */
TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.child_phandle),
(unsigned long)child_dev,
@@ -128,55 +247,101 @@ chirp_emul_child(os_emul_data *data,
}
static int
-chirp_emul_exit(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+chirp_emul_parent(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
{
- cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ struct parent_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 phandle;
+ /*out*/
+ unsigned32 parent_phandle;
+ } args;
+ device *dev;
+ device *parent_dev;
+ /* read the args in */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ dev = cap_internal(data->phandles, args.phandle);
+ TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.phandle),
+ (unsigned long)dev,
+ (dev == NULL ? "" : device_name(dev))));
+ /* find a parent */
+ if (dev == (device*)0)
+ return -1;
+ parent_dev = device_parent(dev);
+ if (parent_dev == NULL)
+ args.parent_phandle = 0;
+ else
+ args.parent_phandle = cap_external(data->phandles, parent_dev);
+ /* return the result */
+ TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.parent_phandle),
+ (unsigned long)parent_dev,
+ (parent_dev == NULL ? "" : device_name(parent_dev))));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
return 0;
}
static int
-chirp_emul_finddevice(os_emul_data *data,
+chirp_emul_instance_to_package(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: instance-to-package unimplemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_getproplen(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct finddevice_args {
+ struct getproplen_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 device_specifier;
- /*out*/
unsigned32 phandle;
+ unsigned32 name;
+ /*out*/
+ unsigned32 proplen;
} args;
- char device_specifier[1024];
+ char name[32];
device *dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("finddevice - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ const device_property *prop;
+ /* read the args in */
+ if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
return -1;
- }
- emul_read_string(device_specifier,
- T2H_4(args.device_specifier),
- sizeof(device_specifier),
- processor, cia);
- TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
- device_specifier));
- dev = device_tree_find_device(data->root,
- device_specifier);
+ dev = cap_internal(data->phandles, args.phandle);
+ /* find our prop and get its length */
if (dev == (device*)0)
- args.phandle = -1;
- else
- args.phandle = cap_external(data->phandles, dev);
- TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
+ return -1;
+ emul_read_string(name,
+ T2H_4(args.name),
+ sizeof(name),
+ processor, cia);
+ TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
+ (dev == NULL ? "" : device_name(dev)),
+ name));
+ prop = device_find_property(dev, name);
+ if (prop == (device_property*)0) {
+ args.proplen = -1;
+ }
+ else {
+ args.proplen = H2T_4(prop->sizeof_array);
+ }
+ /* return the result */
+ TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
+ (unsigned long)T2H_4(args.proplen)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -203,16 +368,9 @@ chirp_emul_getprop(os_emul_data *data,
char name[32];
device *dev;
const device_property *prop;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("getprop - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read in the args */
+ if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
dev = cap_internal(data->phandles, args.phandle);
emul_read_string(name,
T2H_4(args.name),
@@ -225,6 +383,7 @@ chirp_emul_getprop(os_emul_data *data,
name,
(unsigned long)T2H_4(args.buf),
(unsigned long)T2H_4(args.buflen)));
+ /* get the property */
if (dev == (device*)0)
return -1;
prop = device_find_property(dev, name);
@@ -248,6 +407,7 @@ chirp_emul_getprop(os_emul_data *data,
default:
break;
}
+ /* write back the result */
TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
(unsigned long)T2H_4(args.size)));
emul_write_buffer(&args, data->arguments,
@@ -257,54 +417,69 @@ chirp_emul_getprop(os_emul_data *data,
}
static int
-chirp_emul_getproplen(os_emul_data *data,
+chirp_emul_nextprop(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: nextprop not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_setprop(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: setprop not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_canon(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: canon not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_finddevice(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct getproplen_args {
+ struct finddevice_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 phandle;
- unsigned32 name;
+ unsigned32 device_specifier;
/*out*/
- unsigned32 proplen;
+ unsigned32 phandle;
} args;
- char name[32];
+ char device_specifier[1024];
device *dev;
- const device_property *prop;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 2 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("getproplen - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* get the args */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- if (dev == (device*)0)
- return -1;
- emul_read_string(name,
- T2H_4(args.name),
- sizeof(name),
+ emul_read_string(device_specifier,
+ T2H_4(args.device_specifier),
+ sizeof(device_specifier),
processor, cia);
- TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
+ TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
+ device_specifier));
+ /* find the device */
+ dev = device_tree_find_device(data->root,
+ device_specifier);
+ if (dev == (device*)0)
+ args.phandle = -1;
+ else
+ args.phandle = cap_external(data->phandles, dev);
+ /* return its phandle */
+ TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
- (dev == NULL ? "" : device_name(dev)),
- name));
- prop = device_find_property(dev, name);
- if (prop == (device_property*)0) {
- args.proplen = -1;
- }
- else {
- args.proplen = H2T_4(prop->sizeof_array);
- }
- TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
- (unsigned long)T2H_4(args.proplen)));
+ (dev == NULL ? "" : device_name(dev))));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -312,6 +487,36 @@ chirp_emul_getproplen(os_emul_data *data,
}
static int
+chirp_emul_instance_to_path(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: instance_to_path not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_package_to_path(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: package_to_path not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_call_method(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: call-method implemented\n");
+ return 0;
+}
+
+
+/* Device I/O */
+
+static int
chirp_emul_open(os_emul_data *data,
cpu *processor,
unsigned_word cia)
@@ -326,24 +531,19 @@ chirp_emul_open(os_emul_data *data,
unsigned32 ihandle;
} args;
char name[1024];
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("open - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read the args */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
emul_read_string(name,
T2H_4(args.device_specifier),
sizeof(name),
processor, cia);
TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
name));
+ /* open the device */
printf_filtered("OpenBoot - open unimplemented for %s\n", name);
args.ihandle = -1;
+ /* return the ihandle result */
TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
(unsigned long)T2H_4(args.ihandle)));
emul_write_buffer(&args, data->arguments,
@@ -353,98 +553,59 @@ chirp_emul_open(os_emul_data *data,
}
static int
-chirp_emul_parent(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+chirp_emul_close(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
{
- struct parent_args {
- unsigned32 service;
- unsigned32 n_args;
- unsigned32 n_returns;
- /*in*/
- unsigned32 phandle;
- /*out*/
- unsigned32 parent_phandle;
- } args;
- device *dev;
- device *parent_dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("parent - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
- return -1;
- }
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.phandle),
- (unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
- if (dev == (device*)0)
- return -1;
- parent_dev = device_parent(dev);
- if (parent_dev == NULL)
- args.parent_phandle = 0;
- else
- args.parent_phandle = cap_external(data->phandles, parent_dev);
- TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.parent_phandle),
- (unsigned long)parent_dev,
- (parent_dev == NULL ? "" : device_name(parent_dev))));
- emul_write_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
+ error("chirp: close not implemented\n");
return 0;
}
static int
-chirp_emul_peer(os_emul_data *data,
+chirp_emul_read(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct peer_args {
+ struct read_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 phandle;
+ unsigned32 ihandle;
+ unsigned32 addr;
+ unsigned32 len;
/*out*/
- unsigned32 sibling_phandle;
+ unsigned32 actual;
} args;
- device *dev;
- device *sibling_dev = NULL;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("peer - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ char buf[1024];
+ int actual;
+ /* read the args */
+ if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
+ TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n",
+ (unsigned long)args.ihandle,
+ (unsigned long)T2H_4(args.addr),
+ (unsigned long)T2H_4(args.len)));
+ /* do the read */
+ actual = T2H_4(args.len);
+ if (actual >= sizeof(buf))
+ actual = sizeof(buf) - 1;
+ actual = read(BE2H_4(args.ihandle), buf, actual);
+ if (actual >= 0) {
+ emul_write_buffer(buf,
+ T2H_4(args.addr),
+ actual,
+ processor, cia);
+ args.actual = H2T_4(actual);
+ buf[actual] = '\0';
}
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.phandle),
- (unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
- if (dev == NULL && args.phandle != 0)
- return -1;
- if (args.phandle == 0)
- sibling_dev = data->root;
- else
- sibling_dev = device_sibling(dev);
- if (sibling_dev == NULL)
- args.sibling_phandle = 0;
- else
- args.sibling_phandle = cap_external(data->phandles, sibling_dev);
- TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.sibling_phandle),
- (unsigned long)sibling_dev,
- (sibling_dev == NULL ? "" : device_name(sibling_dev))));
+ else {
+ args.actual = 0;
+ }
+ /* return the result */
+ TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
+ (long)T2H_4(args.actual),
+ (actual >= 0 ? buf : "")));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -452,11 +613,11 @@ chirp_emul_peer(os_emul_data *data,
}
static int
-chirp_emul_read(os_emul_data *data,
+chirp_emul_write(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct read_args {
+ struct write_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
@@ -469,16 +630,9 @@ chirp_emul_read(os_emul_data *data,
} args;
char buf[1024];
int actual;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("read - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* get the args */
+ if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
actual = T2H_4(args.len);
if (actual >= sizeof(buf))
actual = sizeof(buf) - 1;
@@ -487,12 +641,16 @@ chirp_emul_read(os_emul_data *data,
actual,
processor, cia);
buf[actual] = '\0';
- /* read it in */
- TRACE(trace_os_emul, ("read - in - ihandle=0x%lx `%s' (%ld)\n",
+ TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
(unsigned long)args.ihandle, buf, (long)actual));
- read(BE2H_4(args.ihandle), buf, actual);
- args.actual = H2T_4(actual);
- TRACE(trace_os_emul, ("read - out - actual=%ld\n",
+ /* write it out */
+ actual = write(BE2H_4(args.ihandle), buf, actual);
+ if (actual < 0)
+ args.actual = 0;
+ else
+ args.actual = H2T_4(actual);
+ /* return the result */
+ TRACE(trace_os_emul, ("write - out - actual=%ld\n",
(long)T2H_4(args.actual)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
@@ -501,48 +659,130 @@ chirp_emul_read(os_emul_data *data,
}
static int
-chirp_emul_write(os_emul_data *data,
+chirp_emul_seek(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct write_args {
+ error("chirp: seek not implemented\n");
+ return 0;
+}
+
+
+/* memory */
+
+static int
+chirp_emul_claim(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: claim not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_release(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: release not implemented\n");
+ return 0;
+}
+
+
+/* Control transfer */
+
+static int
+chirp_emul_boot(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: boot not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_enter(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: enter not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_exit(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ return 0;
+}
+
+static int
+chirp_emul_chain(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: chain not implemented\n");
+ return 0;
+}
+
+
+/* user interface */
+
+static int
+chirp_emul_interpret(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: interpret not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_set_callback(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: set_callback not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_set_symbol_lookup(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: set_symbol_lookup not implemented\n");
+ return 0;
+}
+
+
+/* Time */
+
+static int
+chirp_emul_milliseconds(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct test_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 ihandle;
- unsigned32 addr;
- unsigned32 len;
/*out*/
- unsigned32 actual;
+ unsigned32 ms;
} args;
- char buf[1024];
- int actual;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("write - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
- return -1;
- }
+ unsigned64 time;
/* read in the arguments */
- actual = T2H_4(args.len);
- if (actual >= sizeof(buf))
- actual = sizeof(buf) - 1;
- emul_read_buffer(buf,
- T2H_4(args.addr),
- actual,
- processor, cia);
- buf[actual] = '\0';
- /* write it out */
- TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
- (unsigned long)args.ihandle, buf, (long)actual));
- write(BE2H_4(args.ihandle), buf, actual);
- args.actual = H2T_4(actual);
- TRACE(trace_os_emul, ("write - out - actual=%ld\n",
- (long)T2H_4(args.actual)));
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ /* make up a number */
+ time = event_queue_time(cpu_event_queue(processor)) / 1000000;
+ args.ms = H2T_4(time);
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
+ (unsigned long)T2H_4(args.ms)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -550,17 +790,54 @@ chirp_emul_write(os_emul_data *data,
}
-chirp_services services[] = {
+
+
+static chirp_services services[] = {
+
+ /* client interface */
+ { "test", chirp_emul_test },
+
+ /* device tree */
+ { "peer", chirp_emul_peer },
{ "child", chirp_emul_child },
- { "exit", chirp_emul_exit },
- { "finddevice", chirp_emul_finddevice },
- { "getprop", chirp_emul_getprop },
+ { "parent", chirp_emul_parent },
+ { "instance-to-package", chirp_emul_instance_to_package },
{ "getproplen", chirp_emul_getproplen },
+ { "getprop", chirp_emul_getprop },
+ { "nextprop", chirp_emul_nextprop },
+ { "setprop", chirp_emul_setprop },
+ { "canon", chirp_emul_canon },
+ { "finddevice", chirp_emul_finddevice },
+ { "instance-to-path", chirp_emul_instance_to_path },
+ { "package-to-path", chirp_emul_package_to_path },
+ { "call-method", chirp_emul_call_method },
+
+ /* device I/O */
{ "open", chirp_emul_open },
- { "parent", chirp_emul_parent },
- { "peer", chirp_emul_peer },
+ { "close", chirp_emul_close },
{ "read", chirp_emul_read },
{ "write", chirp_emul_write },
+ { "seek", chirp_emul_seek },
+ { "write", chirp_emul_write },
+
+ /* memory */
+ { "claim", chirp_emul_claim },
+ { "release", chirp_emul_release },
+
+ /* control transfer */
+ { "boot", chirp_emul_boot },
+ { "enter", chirp_emul_enter },
+ { "exit", chirp_emul_exit },
+ { "chain", chirp_emul_chain },
+
+ /* user interface */
+ { "interpret", chirp_emul_interpret },
+ { "set_callback", chirp_emul_set_callback },
+ { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
+
+ /* time */
+ { "milliseconds", chirp_emul_milliseconds },
+
{ 0, /* sentinal */ },
};
@@ -613,18 +890,33 @@ map_over_chirp_note(bfd *image,
return;
note->found = 1;
/* check the name field */
- if (head.namesz > sizeof(name))
+ if (head.namesz > sizeof(name)) {
+ printf_filtered("open-boot warning: note name too long (%ld)\n",
+ (long)head.namesz);
return;
+ }
if (!bfd_get_section_contents(image, sect,
- name, sizeof(head), head.namesz))
+ name, sizeof(head), head.namesz)) {
+ printf_filtered("open-boot warning: note name unreadable\n");
return;
- if (strcmp(name, "PowerPC") != 0)
+ }
+ if (strcmp(name, "PowerPC") != 0) {
+ printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
+ name);
return;
+ }
/* get the contents */
+ if (head.descsz != sizeof(note->desc)) {
+ printf_filtered("open-boot warning: note descriptor of wrong size\n");
+ return;
+ }
if (!bfd_get_section_contents(image, sect,
- &note->desc, sizeof(head) + head.namesz,
- head.descsz))
+ &note->desc, /* page align start */
+ ((sizeof(head) + head.namesz) + 3) & ~3,
+ head.descsz)) {
+ printf_filtered("open-boot warning: note descriptor unreadable\n");
return;
+ }
note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
@@ -753,18 +1045,25 @@ emul_chirp_create(device *root,
device_add_integer_property(init_register,
"r5",
code_client_va);
+ /* client interface */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_client_va - code_va),
- 4, 0x1); /*emul-call*/
+ 4, emul_call_instruction);
+ device_tree_add_found_uw_u_u(init, "",
+ "data",
+ code_ra + (code_client_va - code_va) + 4,
+ 4, emul_blr_instruction);
+ /* callback return address */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_callback_va - code_va),
- 4, 0x1); /*emul-call*/
+ 4, emul_call_instruction);
+ /* loop to keep other processors busy */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_loop_va - code_va),
- 4, 0x48000000); /*b .*/
+ 4, emul_loop_instruction);
device_add_integer_property(init_register,
"msr",
(msr_machine_check_enable
@@ -843,6 +1142,7 @@ emul_chirp_create(device *root,
data->catching_instruction_ea = code_callback_va;
data->phandles = cap_create("chirp");
data->root = root;
+ data->services = services;
return data;
}
}
@@ -923,9 +1223,7 @@ emul_chirp_instruction_call(cpu *processor,
}
- /* return to caller */
- cpu_registers(processor)->gpr[3] = result;
- cpu_restart(processor, emul_data->return_address);
+ /* return to caller - instruction following this is a function return */
return 1;
}