summaryrefslogtreecommitdiffstats
path: root/common/recipes-core/consoled
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-core/consoled')
-rw-r--r--common/recipes-core/consoled/consoled_0.1.bb36
-rw-r--r--common/recipes-core/consoled/files/Makefile11
-rw-r--r--common/recipes-core/consoled/files/consoled.c284
3 files changed, 331 insertions, 0 deletions
diff --git a/common/recipes-core/consoled/consoled_0.1.bb b/common/recipes-core/consoled/consoled_0.1.bb
new file mode 100644
index 0000000..5b6edd1
--- /dev/null
+++ b/common/recipes-core/consoled/consoled_0.1.bb
@@ -0,0 +1,36 @@
+# Copyright 2015-present Facebook. All Rights Reserved.
+SUMMARY = "Serial Buffer"
+DESCRIPTION = "Daemon for serial buffering"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://consoled.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238"
+
+SRC_URI = "file://Makefile \
+ file://consoled.c \
+ "
+S = "${WORKDIR}"
+
+LDFLAGS =+ " -lpal "
+
+DEPENDS =+ " libpal "
+
+binfiles = "consoled"
+
+pkgdir = "consoled"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ install -m 755 consoled ${dst}/consoled
+ ln -snf ../fbpackages/${pkgdir}/consoled ${bin}/consoled
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/consoled ${prefix}/local/bin"
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/common/recipes-core/consoled/files/Makefile b/common/recipes-core/consoled/files/Makefile
new file mode 100644
index 0000000..2b30ef2
--- /dev/null
+++ b/common/recipes-core/consoled/files/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2015-present Facebook. All Rights Reserved.
+all: consoled
+
+
+consoled: consoled.o
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o consoled
diff --git a/common/recipes-core/consoled/files/consoled.c b/common/recipes-core/consoled/files/consoled.c
new file mode 100644
index 0000000..9f17e31
--- /dev/null
+++ b/common/recipes-core/consoled/files/consoled.c
@@ -0,0 +1,284 @@
+/*
+ * consoled
+ *
+ * Copyright 2015-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <termios.h>
+#include <signal.h>
+#include <openbmc/pal.h>
+
+#define BAUDRATE B57600
+#define CTRL_X 0x18
+#define ASCII_ENTER 0x0D
+
+static sig_atomic_t sigexit = 0;
+
+static void
+write_data(int file, char *buf, int len, char *fname) {
+ int wlen = 0;
+ char *tbuf = buf;
+ while(len > 0) {
+ errno = 0;
+ wlen = write(file, tbuf, len);
+ // In case wlen < 0, retry write()
+ if (wlen >= 0) {
+ len -= wlen;
+ tbuf = tbuf + wlen;
+ } else {
+ syslog(LOG_ALERT, "write_data: write() failed to file %s | errno: %d",
+ fname, errno);
+ return;
+ }
+ }
+}
+
+static void
+exit_session(int sig)
+{
+ sigexit = sig;
+}
+
+static void
+print_usage() {
+ printf("Usage: consoled [ %s ]\n", pal_server_list);
+}
+
+static void
+run_console(char* fru_name, int term) {
+
+ int i;
+ int tty; // serial port
+ int buf_fd; // Buffer File
+ int blen; // len for
+ int nfd = 0; // For number of fd
+ int nevents; // For number of events in fd
+ int nline = 0;
+ //int pid_fd;
+ int flags;
+ pid_t pid; // For pid of the daemon
+ uint8_t fru;
+ char in; // For stdin character
+ char data[32];
+ char pid_file[64];
+ char devtty[32]; // For tty dev path
+ char bfname[32]; // For buffer file path
+ char old_bfname[32]; // For old buffer file path
+ char buf[256]; // For buffer data
+ struct termios ottytio, nttytio; // For the tty dev
+
+ int stdi; // STDIN_FILENO
+ int stdo; // STDOUT_FILENO
+ struct termios ostditio, nstditio; // For STDIN_FILENO
+ struct termios ostdotio, nstdotio; // For STDOUT_FILENO
+
+ struct pollfd pfd[2];
+
+ /* Start Daemon for the console buffering */
+ if (!term) {
+ daemon(0,1);
+ openlog("consoled", LOG_CONS, LOG_DAEMON);
+ syslog(LOG_INFO, "consoled: daemon started");
+ }
+
+ if (pal_get_fru_id(fru_name, &fru)) {
+ exit(-1);
+ }
+
+ if (pal_get_fru_devtty(fru, devtty)) {
+ exit(-1);
+ }
+
+ /* Handling the few Signals differently */
+ signal(SIGHUP, exit_session);
+ signal(SIGINT, exit_session);
+ signal(SIGTERM, exit_session);
+ signal(SIGPIPE, exit_session);
+ signal(SIGQUIT, exit_session);
+
+ /* Different flag value for tty dev */
+ flags = term == 1 ? (O_RDWR | O_NOCTTY | O_NONBLOCK) :
+ (O_RDONLY | O_NOCTTY | O_NONBLOCK);
+
+ if ((tty = open(devtty, flags)) < 0) {
+ syslog(LOG_ALERT, "Cannot open the file %s", devtty);
+ exit(-1);
+ }
+ fcntl(tty, F_SETFL, O_RDWR);
+
+ /* Changing the attributes of the tty dev */
+ tcgetattr(tty, &ottytio);
+ memcpy(&nttytio, &ottytio, sizeof(struct termios));
+ cfmakeraw(&nttytio);
+ cfsetspeed(&nttytio, BAUDRATE);
+ tcflush(tty, TCIFLUSH);
+ tcsetattr(tty, TCSANOW, &nttytio);
+ pfd[0].fd = tty;
+ pfd[0].events = POLLIN;
+ nfd++;
+
+ /* Buffering the console data into a file */
+ sprintf(old_bfname, "/tmp/consoled_%s_log-old", fru_name);
+ sprintf(bfname, "/tmp/consoled_%s_log", fru_name);
+ if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) {
+ syslog(LOG_ALERT, "Cannot open the file %s", bfname);
+ exit(-1);
+ }
+
+ if (term) {
+ /* Changing the attributes of STDIN_FILENO */
+ stdi = STDIN_FILENO;
+ tcgetattr(stdi, &ostditio);
+ memcpy(&nstditio, &ostditio, sizeof(struct termios));
+ cfmakeraw(&nstditio);
+ tcflush(stdi, TCIFLUSH);
+ tcsetattr(stdi, TCSANOW, &nstditio);
+
+ /* Changing the attributes of STDOUT_FILENO */
+ stdo = STDOUT_FILENO;
+ tcgetattr(stdo, &ostdotio);
+ memcpy(&nstdotio, &ostdotio, sizeof(struct termios));
+ cfmakeraw(&nstdotio);
+ tcflush(stdo, TCIFLUSH);
+ tcsetattr(stdo, TCSANOW, &nstdotio);
+
+ /* Adding STDIN_FILENO to the poll fd set */
+ pfd[1].fd = stdi;
+ pfd[1].events = POLLIN;
+ nfd++;
+ }
+
+ /* Handling the input event from the terminal and tty dev */
+ while (!sigexit && (nevents = poll(pfd, nfd, -1 /* Timeout */))) {
+
+ /* Input to the terminal from the user */
+ if (term && nevents && nfd > 1 && pfd[1].revents > 0) {
+ blen = read(stdi, &in, sizeof(in));
+ if (blen < 1) {
+ nfd--;
+ }
+
+ if (in == CTRL_X) {
+ break;
+ }
+
+ write_data(tty, &in, sizeof(in), "tty");
+
+ nevents--;
+ }
+
+ /* Input from the tty dev */
+ if (nevents && pfd[0].revents > 0) {
+ blen = read(tty, buf, sizeof(buf));
+ if (blen > 0) {
+ for (i = 0; i < blen; i++) {
+ if (buf[i] == 0xD)
+ nline++;
+ }
+ write_data(buf_fd, buf, blen, bfname);
+ fsync(buf_fd);
+ if (term) {
+ write_data(stdo, buf, blen, "STDOUT_FILENO");
+ }
+ } else if (blen < 0) {
+ raise(SIGHUP);
+ }
+
+ /* Log Rotation */
+ if (nline >= 300) {
+ close(buf_fd);
+ remove(old_bfname);
+ rename(bfname, old_bfname);
+ if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) {
+ syslog(LOG_ALERT, "Cannot open the file %s", bfname);
+ exit(-1);
+ }
+ nline = 0;
+ }
+ nevents--;
+ }
+ }
+
+ /* Close the console buffer file */
+ close(buf_fd);
+
+ /* Revert the tty dev to old attributes */
+ tcflush(tty, TCIFLUSH);
+ tcsetattr(tty, TCSANOW, &ottytio);
+
+ /* Revert STDIN to old attributes */
+ if (term) {
+ tcflush(stdo, TCIFLUSH);
+ tcsetattr(stdo, TCSANOW, &ostdotio);
+ tcflush(stdi, TCIFLUSH);
+ tcsetattr(stdi, TCSANOW, &ostditio);
+ }
+
+ /* Delete the pid file */
+ if (!term)
+ remove(pid_file);
+}
+
+int
+main(int argc, void **argv) {
+ int dev, rc, lock_file;
+ char file[64];
+ int term;
+ char *fru_name;
+
+ if (argc != 3) {
+ print_usage();
+ exit(1);
+ }
+
+ // A lock file for one instance of consoled for each fru
+ sprintf(file, "/var/lock/consoled_%s", argv[1]);
+ lock_file = open(file, O_CREAT | O_RDWR, 0666);
+ rc = flock(lock_file, LOCK_EX | LOCK_NB);
+ if(rc) {
+ if(errno == EWOULDBLOCK) {
+ printf("Another consoled %s instance is running...\n", argv[1]);
+ exit(-1);
+ }
+ } else {
+
+ fru_name = argv[1];
+
+ if (!strcmp(argv[2], "--buffer")) {
+ term = 0;
+ } else if (!strcmp(argv[2], "--term")) {
+ term = 1;
+ } else {
+ print_usage();
+ exit(-1);
+ }
+
+ run_console(fru_name, term);
+ }
+
+ return sigexit;
+}
+
OpenPOWER on IntegriCloud