aboutsummaryrefslogtreecommitdiff
path: root/slof/ppc64.c
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2016-10-14 09:55:08 +0200
committerAlexey Kardashevskiy <aik@ozlabs.ru>2016-10-17 11:02:13 +1100
commitab3ce014ea462642de0ae29fdfab42fd99aa927c (patch)
tree4ea3756c0547d9953e27eab4415705aa456cacae /slof/ppc64.c
parent8e92d6b3e8d6ac0625356f058da6ddae316e2cdc (diff)
downloadSLOF-ab3ce014ea462642de0ae29fdfab42fd99aa927c.zip
SLOF-ab3ce014ea462642de0ae29fdfab42fd99aa927c.tar.gz
SLOF-ab3ce014ea462642de0ae29fdfab42fd99aa927c.tar.bz2
Remember execution tokens of "write" and "read" for socket operations
The recv() and send() functions are currently assuming that the dictionary of the NIC node is available, so that they can call "read" or "write" directly. While this is working fine when only doing network loading from the Open Firmware prompt, this does not work anymore when a client like yaboot is trying to load additional files. Fix this issue by looking up the execution tokens of "read" and "write" while opening the socket, so we can use these XT values during recv() and send() later. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'slof/ppc64.c')
-rw-r--r--slof/ppc64.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/slof/ppc64.c b/slof/ppc64.c
index e88b240..a3e84ae 100644
--- a/slof/ppc64.c
+++ b/slof/ppc64.c
@@ -94,13 +94,26 @@ asm_cout(long Character, long UART, long NVRAM __attribute__((unused)))
io_putchar(Character);
}
+static type_u find_method(type_u phandle, const char *name)
+{
+ forth_push((type_u)name);
+ forth_push(strlen(name));
+ forth_push(phandle);
+ forth_eval("find-method");
+ if (forth_pop())
+ return forth_pop();
+
+ return 0;
+}
+
#define FILEIO_TYPE_EMPTY 0
#define FILEIO_TYPE_FILE 1
#define FILEIO_TYPE_SOCKET 2
struct fileio_type {
int type;
- int ih; /* ihandle */
+ type_u read_xt;
+ type_u write_xt;
};
#define FILEIO_MAX 32
@@ -109,6 +122,7 @@ static struct fileio_type fd_array[FILEIO_MAX];
int socket(int domain, int type, int proto, char *mac_addr)
{
const char mac_prop_name[] = "local-mac-address";
+ type_u phandle;
uint8_t *prop_addr;
int prop_len;
int fd;
@@ -124,18 +138,30 @@ int socket(int domain, int type, int proto, char *mac_addr)
return -2;
}
- forth_eval("my-parent");
- fd_array[fd].ih = forth_pop();
- if (fd_array[fd].ih == 0) {
+ /* Assume that obp-tftp package is the current one, so
+ * my-parent is the NIC node that we are interested in */
+ forth_eval("my-parent ?dup IF ihandle>phandle THEN");
+ phandle = forth_pop();
+ if (phandle == 0) {
puts("Can not open socket, no parent instance");
return -1;
}
+ fd_array[fd].read_xt = find_method(phandle, "read");
+ if (!fd_array[fd].read_xt) {
+ puts("Can not open socket, no 'read' method");
+ return -1;
+ }
+ fd_array[fd].write_xt = find_method(phandle, "write");
+ if (!fd_array[fd].write_xt) {
+ puts("Can not open socket, no 'write' method");
+ return -1;
+ }
/* Read MAC address from device */
forth_push((unsigned long)mac_prop_name);
forth_push(strlen(mac_prop_name));
- forth_push(fd_array[fd].ih);
- forth_eval("ihandle>phandle get-property");
+ forth_push(phandle);
+ forth_eval("get-property");
if (forth_pop())
return -1;
prop_len = forth_pop();
@@ -179,8 +205,8 @@ int recv(int fd, void *buf, int len, int flags)
forth_push((unsigned long)buf);
forth_push(len);
-
- return forth_eval_pop("read");
+ forth_push(fd_array[fd].read_xt);
+ return forth_eval_pop("EXECUTE");
}
/**
@@ -199,8 +225,9 @@ int send(int fd, const void *buf, int len, int flags)
forth_push((unsigned long)buf);
forth_push(len);
+ forth_push(fd_array[fd].write_xt);
+ return forth_eval_pop("EXECUTE");
- return forth_eval_pop("write");
}
/**