diff options
Diffstat (limited to 'sim/ppc/emul_chirp.c')
-rw-r--r-- | sim/ppc/emul_chirp.c | 762 |
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, - ¬e->desc, sizeof(head) + head.namesz, - head.descsz)) + ¬e->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*)¬e->desc.real_mode); note->desc.real_base = bfd_get_32(image, (void*)¬e->desc.real_base); note->desc.real_size = bfd_get_32(image, (void*)¬e->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; } |