aboutsummaryrefslogtreecommitdiff
path: root/slof
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2016-09-09 21:52:03 +0200
committerAlexey Kardashevskiy <aik@ozlabs.ru>2016-09-14 17:50:40 +1000
commite0dc16c217b3d7f98165ff2c7473c9222c879354 (patch)
tree882baa32b5d7389727a3e9e5b3ba3ce18d2b11c2 /slof
parent91d86c568ebb45f940ce75575ce4d08420638617 (diff)
downloadSLOF-e0dc16c217b3d7f98165ff2c7473c9222c879354.zip
SLOF-e0dc16c217b3d7f98165ff2c7473c9222c879354.tar.gz
SLOF-e0dc16c217b3d7f98165ff2c7473c9222c879354.tar.bz2
paflof: Add socket(), send() and recv() functions to paflof
Code is slightly based on the implementation from net-snk, but has been adapted to use the forth_eval() and forth_push/pop() macros instead. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'slof')
-rw-r--r--slof/ppc64.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/slof/ppc64.c b/slof/ppc64.c
index 4fc92b9..7169cb0 100644
--- a/slof/ppc64.c
+++ b/slof/ppc64.c
@@ -11,6 +11,7 @@
*****************************************************************************/
#include <unistd.h>
+#include <sys/socket.h>
#include <cpu.h>
void asm_cout(long Character,long UART,long NVRAM);
@@ -92,3 +93,112 @@ asm_cout(long Character, long UART, long NVRAM __attribute__((unused)))
if (UART)
io_putchar(Character);
}
+
+#define FILEIO_TYPE_EMPTY 0
+#define FILEIO_TYPE_FILE 1
+#define FILEIO_TYPE_SOCKET 2
+
+struct fileio_type {
+ int type;
+ int ih; /* ihandle */
+};
+
+#define FILEIO_MAX 32
+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";
+ uint8_t *prop_addr;
+ int prop_len;
+ int fd;
+
+ /* search free file descriptor (and skip stdio handlers) */
+ for (fd = 3; fd < FILEIO_MAX; ++fd) {
+ if (fd_array[fd].type == FILEIO_TYPE_EMPTY) {
+ break;
+ }
+ }
+ if (fd == FILEIO_MAX) {
+ puts("Can not open socket, file descriptor list is full");
+ return -2;
+ }
+
+ forth_eval("my-parent");
+ fd_array[fd].ih = forth_pop();
+ if (fd_array[fd].ih == 0) {
+ puts("Can not open socket, no parent instance");
+ 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");
+ if (forth_pop())
+ return -1;
+ prop_len = forth_pop();
+ prop_addr = (uint8_t *)forth_pop();
+ memcpy(mac_addr, &prop_addr[prop_len - 6], 6);
+
+ fd_array[fd].type = FILEIO_TYPE_SOCKET;
+
+ return fd;
+}
+
+static inline int is_valid_fd(int fd)
+{
+ return fd >= 0 && fd < FILEIO_MAX &&
+ fd_array[fd].type != FILEIO_TYPE_EMPTY;
+}
+
+int close(int fd)
+{
+ if (!is_valid_fd(fd))
+ return -1;
+
+ fd_array[fd].type = FILEIO_TYPE_EMPTY;
+
+ return 0;
+}
+
+/**
+ * Standard recv function for the libc.
+ *
+ * @param fd socket file descriptor
+ * @param buf pointer to the array where the packet should be stored
+ * @param len maximum length in bytes of the packet
+ * @param flags currently unused, should be 0
+ * @return the number of bytes that have been received successfully
+ */
+int recv(int fd, void *buf, int len, int flags)
+{
+ if (!is_valid_fd(fd))
+ return -1;
+
+ forth_push((unsigned long)buf);
+ forth_push(len);
+
+ return forth_eval_pop("read");
+}
+
+/**
+ * Standard send function for the libc.
+ *
+ * @param fd socket file descriptor
+ * @param buf pointer to the array with the output packet
+ * @param len length in bytes of the packet
+ * @param flags currently unused, should be 0
+ * @return the number of bytes that have been sent successfully
+ */
+int send(int fd, const void *buf, int len, int flags)
+{
+ if (!is_valid_fd(fd))
+ return -1;
+
+ forth_push((unsigned long)buf);
+ forth_push(len);
+
+ return forth_eval_pop("write");
+}