/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include #include #include void asm_cout(long Character,long UART,long NVRAM); /* the exception frame should be page aligned * the_exception_frame is used by the handler to store a copy of all * registers after an exception; this copy can then be used by paflof's * exception handler to printout a register dump */ cell the_exception_frame[0x400 / CELLSIZE] __attribute__ ((aligned(PAGE_SIZE)));; /* the_client_frame is the register save area when starting a client */ cell the_client_frame[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100))); cell the_client_stack[0x8000 / CELLSIZE] __attribute__ ((aligned(0x100))); /* THE forth stack */ cell the_data_stack[0x2000 / CELLSIZE] __attribute__ ((aligned(0x100))); /* the forth return stack */ cell the_return_stack[0x2000 / CELLSIZE] __attribute__ ((aligned(0x100))); /* forth stack and return-stack pointers */ cell *restrict dp; cell *restrict rp; /* terminal input buffer */ cell the_tib[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100))); /* temporary string buffers */ char the_pockets[NUMPOCKETS * POCKETSIZE] __attribute__ ((aligned(0x100))); cell the_comp_buffer[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100))); cell the_heap[HEAP_SIZE / CELLSIZE] __attribute__ ((aligned(0x1000))); cell *the_heap_start = &the_heap[0]; cell *the_heap_end = &the_heap[HEAP_SIZE / CELLSIZE]; extern void io_putchar(unsigned char); extern unsigned long call_c(cell arg0, cell arg1, cell arg2, cell entry); static long writeLogByte_wrapper(long x, long y) { unsigned long result; SET_CI; result = writeLogByte(x, y); CLR_CI; return result; } /** * Standard write function for the libc. * * @param fd file descriptor (should always be 1 or 2) * @param buf pointer to the array with the output characters * @param count number of bytes to be written * @return the number of bytes that have been written successfully */ ssize_t write(int fd, const void *buf, size_t count) { char *ptr = (char *)buf; int len; if (fd != 1 && fd != 2) return 0; if (!init_engine || fd == 2) { len = count; while (len-- > 0) { if (*ptr == '\n') io_putchar('\r'); io_putchar(*ptr++); } return count; } while ((ptr = strchr(buf, '\n')) != NULL) { forth_push((long)buf); forth_push((long)ptr - (long)buf); forth_eval("type cr"); buf = ptr + 1; } len = strlen(buf); if (len) { forth_push((long)buf); forth_push(len); forth_eval("type"); } return count; } /* This should probably be temporary until a better solution is found */ void asm_cout(long Character, long UART, long NVRAM __attribute__((unused))) { if (UART) 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; type_u read_xt; type_u write_xt; }; #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"; type_u phandle; uint8_t *prop_addr; int prop_len; int fd; if (!(domain == AF_INET || domain == AF_INET6)) return -1; if (type != SOCK_DGRAM || proto != 0) return -1; /* 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; } /* 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(phandle); forth_eval("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) || flags) return -1; forth_push((unsigned long)buf); forth_push(len); forth_push(fd_array[fd].read_xt); return forth_eval_pop("EXECUTE"); } /** * 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) || flags) return -1; forth_push((unsigned long)buf); forth_push(len); forth_push(fd_array[fd].write_xt); return forth_eval_pop("EXECUTE"); } /** * Standard read function for the libc. * * @param fd file descriptor (should always be 0 or 2) * @param buf pointer to the array with the output characters * @param len number of bytes to be read * @return the number of bytes that have been read successfully */ ssize_t read(int fd, void *buf, size_t len) { char *ptr = (char *)buf; unsigned cnt = 0; char code; if (fd == 0 || fd == 2) { while (cnt < len) { code = forth_eval_pop("key? IF key ELSE 0 THEN"); if (!code) break; ptr[cnt++] = code; } } return cnt; }