summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/utils/ofclient
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/utils/ofclient')
-rw-r--r--qemu/roms/openbios/utils/ofclient/Makefile14
-rw-r--r--qemu/roms/openbios/utils/ofclient/README4
-rw-r--r--qemu/roms/openbios/utils/ofclient/endian.h18
-rw-r--r--qemu/roms/openbios/utils/ofclient/of1275.c451
-rw-r--r--qemu/roms/openbios/utils/ofclient/of1275.h437
-rw-r--r--qemu/roms/openbios/utils/ofclient/of1275_io.c51
-rw-r--r--qemu/roms/openbios/utils/ofclient/ofclient.c9
7 files changed, 984 insertions, 0 deletions
diff --git a/qemu/roms/openbios/utils/ofclient/Makefile b/qemu/roms/openbios/utils/ofclient/Makefile
new file mode 100644
index 000000000..f3c515964
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/Makefile
@@ -0,0 +1,14 @@
+PROGRAM := ofclient
+OBJECTS := of1275.o of1275_io.o ofclient.o
+CC := gcc
+CFLAGS := -m32 -fpic -fno-builtin-strlen -Os
+LDFLAGS := -melf_i386 -s -N -Ttext 0x200000 -e _start
+
+$(PROGRAM): $(OBJECTS)
+ $(LD) $(LDFLAGS) -Map $(PROGRAM).map -o $(PROGRAM) $(OBJECTS)
+
+clean:
+ rm -f $(OBJECTS)
+
+distclean: clean
+ rm -f $(PROGRAM) $(PROGRAM).map
diff --git a/qemu/roms/openbios/utils/ofclient/README b/qemu/roms/openbios/utils/ofclient/README
new file mode 100644
index 000000000..785f6ec2d
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/README
@@ -0,0 +1,4 @@
+This is an example program using the openfirmware client
+interface on x86. The same program can be compiled on ppc.
+
+
diff --git a/qemu/roms/openbios/utils/ofclient/endian.h b/qemu/roms/openbios/utils/ofclient/endian.h
new file mode 100644
index 000000000..4d20e7171
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/endian.h
@@ -0,0 +1,18 @@
+
+#define __bswap32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+static int little_endian(void)
+{
+ static short one=1;
+ return *(char *)&one==1;
+}
+
+static unsigned int ntohl(unsigned int netlong)
+{
+ if(little_endian())
+ return __bswap32(netlong);
+
+ return netlong;
+}
diff --git a/qemu/roms/openbios/utils/ofclient/of1275.c b/qemu/roms/openbios/utils/ofclient/of1275.c
new file mode 100644
index 000000000..ff0778279
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/of1275.c
@@ -0,0 +1,451 @@
+
+#include "of1275.h"
+#include "endian.h"
+static int (*of1275_server) (void *) = (int (*)(void *)) -1;
+
+_start(void *residual_data_structure,
+ void *program_entry_point,
+ int (*client_interface_handler) (void *), void *args, int argslen)
+{
+ int status;
+ of1275_server = client_interface_handler;
+ status = main();
+ of1275_exit(status);
+}
+
+/* 6.3.2.1 Client interface */
+
+
+int of1275_test(const char *name, int *missing)
+{
+ int result;
+ static of1275_test_service s;
+ s.service = "test";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.name = name;
+ result = of1275_server(&s);
+ *missing = s.missing;
+ return result;
+}
+
+
+/* 6.3.2.2 Device tree */
+
+
+int of1275_peer(int phandle, int *sibling_phandle)
+{
+ int result;
+ static of1275_peer_service s;
+ s.service = "peer";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *sibling_phandle = s.sibling_phandle;
+ return result;
+}
+
+int of1275_child(int phandle, int *child_phandle)
+{
+ int result;
+ static of1275_child_service s;
+ s.service = "child";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *child_phandle = s.child_phandle;
+ return result;
+}
+
+int of1275_parent(int phandle, int *parent_phandle)
+{
+ int result;
+ static of1275_parent_service s;
+ s.service = "parent";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *parent_phandle = s.parent_phandle;
+ return result;
+}
+
+int of1275_instance_to_package(int ihandle, int *phandle)
+{
+ int result;
+ static of1275_instance_to_package_service s;
+ s.service = "instance-to-package";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ result = of1275_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int of1275_getproplen(int phandle, const char *name, int *proplen)
+{
+ int result;
+ static of1275_getproplen_service s;
+ s.service = "getproplen";
+ s.n_args = 2;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ result = of1275_server(&s);
+ *proplen = s.proplen;
+ return result;
+}
+
+int
+of1275_getprop(int phandle, const char *name, void *buf, int buflen,
+ int *size)
+{
+ int result;
+ static of1275_getprop_service s;
+ s.service = "getprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of1275_nextprop(int phandle, const char *previous, void *buf, int *flag)
+{
+ int result;
+ static of1275_nextprop_service s;
+ s.service = "nextprop";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.previous = previous;
+ s.buf = buf;
+ result = of1275_server(&s);
+ *flag = s.flag;
+ return result;
+}
+
+int
+of1275_setprop(int phandle, const char *name, void *buf, int len,
+ int *size)
+{
+ int result;
+ static of1275_setprop_service s;
+ s.service = "setprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.len = len;
+ result = of1275_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of1275_canon(const char *device_specifier, void *buf, int buflen,
+ int *length)
+{
+ int result;
+ static of1275_canon_service s;
+ s.service = "canon";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int of1275_finddevice(const char *device_specifier, int *phandle)
+{
+ int result;
+ static of1275_finddevice_service s;
+ s.service = "finddevice";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of1275_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int
+of1275_instance_to_path(int ihandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of1275_instance_to_path_service s;
+ s.service = "instance-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int of1275_package_to_path(int phandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of1275_package_to_path_service s;
+ s.service = "package-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+/* int of1275_call_method(const char *method, int ihandle, ...); */
+
+
+/* 6.3.2.3 Device I/O */
+
+
+int of1275_open(const char *device_specifier, int *ihandle)
+{
+ int result;
+ static of1275_open_service s;
+ s.service = "open";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of1275_server(&s);
+ *ihandle = s.ihandle;
+ return result;
+}
+
+int of1275_close(int ihandle)
+{
+ int result;
+ static of1275_close_service s;
+ s.service = "close";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.ihandle = ihandle;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_read(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of1275_read_service s;
+ s.service = "read";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of1275_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int of1275_write(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of1275_write_service s;
+ s.service = "write";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of1275_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status)
+{
+ int result;
+ static of1275_seek_service s;
+ s.service = "seek";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.pos_hi = pos_hi;
+ s.pos_lo = pos_lo;
+ result = of1275_server(&s);
+ *status = s.status;
+ return result;
+}
+
+
+/* 6.3.2.4 Memory */
+
+
+int of1275_claim(void *virt, int size, int align, void **baseaddr)
+{
+ int result;
+ static of1275_claim_service s;
+ s.service = "claim";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.virt = virt;
+ s.size = size;
+ s.align = align;
+ result = of1275_server(&s);
+ *baseaddr = s.baseaddr;
+ return result;
+}
+
+int of1275_release(void *virt, int size)
+{
+ int result;
+ static of1275_release_service s;
+ s.service = "release";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.virt = virt;
+ s.size = size;
+ result = of1275_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.5 Control transfer */
+
+
+int of1275_boot(const char *bootspec)
+{
+ int result;
+ static of1275_boot_service s;
+ s.service = "boot";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.bootspec = bootspec;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_enter(void)
+{
+ int result;
+ static of1275_enter_service s;
+ s.service = "enter";
+ s.n_args = 0;
+ s.n_returns = 0;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_exit(int status)
+{
+ int result;
+ static of1275_exit_service s;
+ s.service = "exit";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.status = status;
+ result = of1275_server(&s);
+ return result;
+}
+
+/* int of1275_chain(void *virt, int size, void *entry, void *args, int len); */
+
+
+/* 6.3.2.6 User interface */
+
+
+/* int of1275_interpret(const char *arg, ...); */
+
+int of1275_set_callback(void *newfunc, void **oldfunc)
+{
+ int result;
+ static of1275_set_callback_service s;
+ s.service = "set-callback";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.newfunc = newfunc;
+ result = of1275_server(&s);
+ *oldfunc = s.oldfunc;
+ return result;
+}
+
+int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym)
+{
+ int result;
+ static of1275_set_symbol_lookup_service s;
+ s.service = "set-symbol-lookup";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.sym_to_value = sym_to_value;
+ s.value_to_sym = s.value_to_sym;
+ result = of1275_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.7 Time */
+
+int of1275_milliseconds(int *ms)
+{
+ int result;
+ static of1275_milliseconds_service s;
+ s.service = "milliseconds";
+ s.n_args = 0;
+ s.n_returns = 1;
+ result = of1275_server(&s);
+ *ms = s.ms;
+ return result;
+}
+
+
+int of_find_integer_property(const char *device, const char *property)
+{
+ int phandle;
+ int integer;
+ int size;
+ /* find the device's phandle */
+ if (of1275_finddevice(device, &phandle) < 0) {
+ //printk("of1275: no such device '%s'\n", device);
+ exit(1);
+ }
+ /* find the device's property */
+ of1275_getprop(phandle, property, &integer,
+ sizeof(integer), &size);
+ if (size < sizeof(integer)) {
+ //printk("of1275: unknown integer property '%s'\n", property);
+ exit(1);
+ }
+ return ntohl(integer);
+}
+
+void
+of_find_string_property(const char *device,
+ const char *property,
+ char *string, int sizeof_string)
+{
+ int phandle;
+ int size;
+ /* find the device's phandle */
+ if (of1275_finddevice(device, &phandle) < 0) {
+ //printk("of1275: no such device '%s'\n", device);
+ exit(1);
+ }
+
+ /* find the device's property */
+ of1275_getprop(phandle, property, string, sizeof_string, &size);
+ if (size == 0 || size >= sizeof_string) {
+ //printk("of1275: unknown string property '%s'\n", property);
+ exit(1);
+ }
+}
diff --git a/qemu/roms/openbios/utils/ofclient/of1275.h b/qemu/roms/openbios/utils/ofclient/of1275.h
new file mode 100644
index 000000000..a73bb19a8
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/of1275.h
@@ -0,0 +1,437 @@
+/* OpenFirmware interface */
+
+
+/* 6.3.2.1 Client interface */
+
+
+typedef struct _of1275_test_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *name;
+ /*out */
+ int missing;
+} of1275_test_service;
+
+int of1275_test(const char *name, int *missing);
+
+
+/* 6.3.2.2 Device tree */
+
+
+typedef struct _of1275_peer_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int sibling_phandle;
+} of1275_peer_service;
+
+int of1275_peer(int phandle, int *sibling_phandle);
+
+
+typedef struct _of1275_child_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int child_phandle;
+} of1275_child_service;
+
+int of1275_child(int phandle, int *child_phandle);
+
+
+typedef struct _of1275_parent_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int parent_phandle;
+} of1275_parent_service;
+
+int of1275_child(int phandle, int *parent_phandle);
+
+
+typedef struct _of1275_instance_to_package_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ /*out */
+ int phandle;
+} of1275_instance_to_package_service;
+
+int of1275_instance_to_package(int ihandle, int *phandle);
+
+
+typedef struct _of1275_getproplen_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ /*out */
+ int proplen;
+} of1275_getproplen_service;
+
+int of1275_getproplen(int phandle, const char *name, int *proplen);
+
+
+typedef struct _of1275_getprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ void *buf;
+ int buflen;
+ /*out */
+ int size;
+} of1275_getprop_service;
+
+int of1275_getprop(int phandle, const char *name, void *buf, int buflen,
+ int *size);
+
+
+typedef struct _of1275_nextprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *previous;
+ void *buf;
+ /*out */
+ int flag;
+} of1275_nextprop_service;
+
+int of1275_nextprop(int phandle, const char *previous, void *buf,
+ int *flag);
+
+
+typedef struct _of1275_setprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ void *buf;
+ int len;
+ /*out */
+ int size;
+} of1275_setprop_service;
+
+int of1275_setprop(int phandle, const char *name, void *buf, int len,
+ int *size);
+
+
+typedef struct _of1275_canon_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_canon_service;
+
+int of1275_canon(const char *device_specifier, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_finddevice_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ /*out */
+ int phandle;
+} of1275_finddevice_service;
+
+int of1275_finddevice(const char *device_specifier, int *phandle);
+
+
+typedef struct _of1275_instance_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_instance_to_path_service;
+
+int of1275_instance_to_path(int ihandle, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_package_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_package_to_path_service;
+
+int of1275_package_to_path(int phandle, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_call_method_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *method;
+ int ihandle;
+ /*... */
+ int args[0];
+} of1275_call_method_service;
+
+int of1275_call_method(const char *method, int ihandle, ...);
+
+
+/* 6.3.2.3 Device I/O */
+
+
+typedef struct _of1275_open_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ /*out */
+ int ihandle;
+} of1275_open_service;
+
+int of1275_open(const char *device_specifier, int *ihandle);
+
+
+typedef struct _of1275_close_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ /*out */
+} of1275_close_service;
+
+int of1275_close(int ihandle);
+
+
+typedef struct _of1275_read_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *addr;
+ int len;
+ /*out */
+ int actual;
+} of1275_read_service;
+
+int of1275_read(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of1275_write_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *addr;
+ int len;
+ /*out */
+ int actual;
+} of1275_write_service;
+
+int of1275_write(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of1275_seek_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ int pos_hi;
+ int pos_lo;
+ /*out */
+ int status;
+} of1275_seek_service;
+
+int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status);
+
+
+/* 6.3.2.4 Memory */
+
+
+typedef struct _of1275_claim_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ int align;
+ /*out */
+ void *baseaddr;
+} of1275_claim_service;
+
+int of1275_claim(void *virt, int size, int align, void **baseaddr);
+
+
+typedef struct _of1275_release_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ int align;
+ /*out */
+} of1275_release_service;
+
+int of1275_release(void *virt, int size);
+
+
+/* 6.3.2.5 Control transfer */
+
+
+typedef struct _of1275_boot_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *bootspec;
+ /*out */
+} of1275_boot_service;
+
+int of1275_boot(const char *bootspec);
+
+
+typedef struct _of1275_enter_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ /*out */
+} of1275_enter_service;
+
+int of1275_enter(void);
+
+typedef struct _of1275_exit_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int status;
+ /*out */
+} of1275_exit_service;
+
+int of1275_exit(int status);
+
+
+typedef struct _of1275_chain_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ void *entry;
+ void *args;
+ int len;
+ /*out */
+} of1275_chain_service;
+
+int of1275_chain(void *virt, int size, void *entry, void *args, int len);
+
+
+/* 6.3.2.6 User interface */
+
+
+typedef struct _of1275_interpret_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *cmd;
+ int args[0];
+ /*... */
+ /*out */
+ /*... */
+} of1275_interpret_service;
+
+int of1275_interpret(const char *arg, ...);
+
+
+typedef struct _of1275_set_callback_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *newfunc;
+ /*out */
+ void *oldfunc;
+} of1275_set_callback_service;
+
+int of1275_set_callback(void *newfunc, void **oldfunc);
+
+
+typedef struct _of1275_set_symbol_lookup_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *sym_to_value;
+ void *value_to_sym;
+ /*out */
+} of1275_set_symbol_lookup_service;
+
+int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym);
+
+
+/* 6.3.2.7 Time */
+
+
+typedef struct _of1275_milliseconds_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ /*out */
+ int ms;
+} of1275_milliseconds_service;
+
+int of1275_milliseconds(int *ms);
+
+
+/* Common and useful utilities */
+
+
+int of_find_integer_property(const char *path, const char *property);
+
+void of_find_string_property(const char *path, const char *property,
+ char *string, int sizeof_string);
diff --git a/qemu/roms/openbios/utils/ofclient/of1275_io.c b/qemu/roms/openbios/utils/ofclient/of1275_io.c
new file mode 100644
index 000000000..25d1132c3
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/of1275_io.c
@@ -0,0 +1,51 @@
+#include "of1275.h"
+
+static int of_write_initialized = 0;
+static int stdout_ihandle = 0;
+static int of_read_initialized = 0;
+static int stdin_ihandle = 0;
+
+int write(int fd, char *buf, int len)
+{
+ int actual;
+
+ if (fd != 1 && fd != 2) {
+ // printk("write: bad id %x\n", fd);
+ exit(1);
+ }
+
+ if (!of_write_initialized) {
+ stdout_ihandle =
+ of_find_integer_property("/chosen", "stdout");
+ // printk("stdout_ihandle: %x\n",stdout_ihandle);
+ of_write_initialized = 1;
+ }
+
+ of1275_write(stdout_ihandle, buf, len, &actual);
+ return actual;
+}
+
+int read(int fd, char *buf, int len)
+{
+ int actual;
+
+ if (fd != 0) {
+ // printk("write: bad id %x\n", fd);
+ exit(1);
+ }
+
+ if (!of_read_initialized) {
+ stdin_ihandle =
+ of_find_integer_property("/chosen", "stdin");
+ of_read_initialized = 1;
+ }
+
+ of1275_read(stdin_ihandle, buf, len, &actual);
+ return actual;
+}
+
+exit(int status)
+{
+ of1275_exit(status);
+ while (1);
+}
diff --git a/qemu/roms/openbios/utils/ofclient/ofclient.c b/qemu/roms/openbios/utils/ofclient/ofclient.c
new file mode 100644
index 000000000..94214c6ca
--- /dev/null
+++ b/qemu/roms/openbios/utils/ofclient/ofclient.c
@@ -0,0 +1,9 @@
+#include "of1275.h"
+
+int write(int fd, char *buf, int len);
+
+int main(void)
+{
+ write(1, "Hello world!\n", 13 );
+ return 0;
+}