summaryrefslogtreecommitdiffstats
path: root/meta-facebook/meta-wedge/recipes-wedge
diff options
context:
space:
mode:
Diffstat (limited to 'meta-facebook/meta-wedge/recipes-wedge')
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb22
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile13
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c236
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h66
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c107
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h42
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c336
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c317
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README5
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp851
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp201
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h60
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb59
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb86
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions222
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py260
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py178
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh83
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh15
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h59
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh34
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf6
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile2
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py60
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py175
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py26
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh2
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb2
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/bmc_command.py112
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py155
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_psu_update.py81
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py15
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh53
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb4
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh9
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c40
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h14
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c9
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb2
41 files changed, 681 insertions, 3358 deletions
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb
deleted file mode 100644
index 443d81d..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-SUMMARY = "Device driver using GPIO bitbang"
-DESCRIPTION = "Various device driver using GPIO bitbang"
-SECTION = "base"
-PR = "r1"
-LICENSE = "GPLv2"
-LIC_FILES_CHKSUM = "file://bitbang.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
-
-SRC_URI = "file://src \
- "
-
-DEPENDS += "fbutils"
-
-S = "${WORKDIR}/src"
-
-do_install() {
- install -d ${D}${bindir}
- install -m 755 spi-bb ${D}${bindir}/spi-bb
- install -m 755 mdio-bb ${D}${bindir}/mdio-bb
-}
-
-FILES_${PN} = "${bindir}"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile
deleted file mode 100644
index 102ac4e..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-all: spi-bb mdio-bb
-
-spi-bb: spi_bb.o bitbang.o gpio.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-mdio-bb: mdio_bb.o bitbang.o gpio.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-.PHONY: clean
-
-clean:
- rm -rf *.o spi-bb mdio-bb
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c
deleted file mode 100644
index cf7dcd3..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-//#define DEBUG
-//#define VERBOSE
-
-#include "bitbang.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "facebook/log.h"
-
-#define NANOSEC_IN_SEC (1000 * 1000 * 1000)
-
-#define BITBANG_FREQ_MAX (500 * 1000 * 1000) /* 500M Hz */
-#define BITBANG_FREQ_DEFAULT (1 * 1000 * 1000) /* 1M Hz */
-
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
-struct bitbang_handle {
- bitbang_init_st bbh_init;
- uint32_t bbh_half_clk; /* ns per clock cycle */
-};
-
-void bitbang_init_default(bitbang_init_st *init)
-{
- memset(init, sizeof(*init), 0);
- init->bbi_clk_start = BITBANG_PIN_HIGH;
- init->bbi_data_out = BITBANG_CLK_EDGE_FALLING;
- init->bbi_data_in = BITBANG_CLK_EDGE_RISING;
- init->bbi_freq = BITBANG_FREQ_DEFAULT;
-}
-
-bitbang_handle_st* bitbang_open(const bitbang_init_st *init)
-{
- bitbang_handle_st *hdl;
-
- if (!init || !init->bbi_pin_f
- || !init->bbi_freq || init->bbi_freq > BITBANG_FREQ_MAX) {
- LOG_ERR(EINVAL, "Invalid init structure");
- return NULL;
- }
-
- hdl = calloc(1, sizeof(*hdl));
- if (!hdl) {
- return NULL;
- }
-
- hdl->bbh_init = *init;
- hdl->bbh_half_clk = NANOSEC_IN_SEC / init->bbi_freq / 2;
-
- LOG_DBG("Bitbang open with initial %s, data out at %s, data in at %s, "
- "freq at %uHz, half clk %uns",
- (init->bbi_clk_start == BITBANG_PIN_LOW) ? "LOW" : "HIGH",
- (init->bbi_data_out == BITBANG_CLK_EDGE_RISING)
- ? "RISING" : "FALLING",
- (init->bbi_data_in == BITBANG_CLK_EDGE_RISING)
- ? "RISING" : "FALLING",
- init->bbi_freq, hdl->bbh_half_clk);
-
- return hdl;
-}
-
-void bitbang_close(bitbang_handle_st *hdl)
-{
- free(hdl);
-}
-
-/*
- * The threshold (ns) to use spin instead of nanosleep().
- * Before adding the high resolution timer support, either spin or nanosleep()
- * will not bring the process wakeup within 10ms. It turns out the system time
- * update is also controlled by HZ (100).
- * After I added the high resolution timer support, the spin works as the
- * system time is updated more frequently. However, nanosleep() solution is
- * still noticable slower comparing with spin. There could be some kernel
- * scheduling tweak missing. Did not get time on that yet.
- * For now, use 10ms as the threshold to determine if spin or nanosleep()
- * is used.
- */
-#define BITBANG_SPIN_THRESHOLD (10 * 1000 * 1000)
-
-static int sleep_ns(uint32_t clk)
-{
- struct timespec req, rem;
- int rc = 0;
- if (clk <= BITBANG_SPIN_THRESHOLD) {
- struct timespec orig;
- rc = clock_gettime(CLOCK_MONOTONIC, &req);
- orig = req;
- while (!rc && clk) {
- uint32_t tmp;
- rc = clock_gettime(CLOCK_MONOTONIC, &rem);
- tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC;
- if (rem.tv_nsec >= req.tv_nsec) {
- tmp += rem.tv_nsec - req.tv_nsec;
- } else {
- tmp -= req.tv_nsec - rem.tv_nsec;
- }
- if (tmp >= clk) {
- break;
- }
- clk -= tmp;
- req = rem;
- }
- } else {
- req.tv_sec = 0;
- req.tv_nsec = clk;
- while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) {
- req = rem;
- }
- }
- if (rc == -1) {
- rc = errno;
- LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk);
- }
- return rc;
-}
-
-int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io)
-{
- int rc = 0;
- uint32_t clk = hdl->bbh_half_clk;
- const struct {
- bitbang_pin_value_en value;
- bitbang_clk_edge_en edge;
- } clks[] = {
- {BITBANG_PIN_HIGH, BITBANG_CLK_EDGE_FALLING},
- {BITBANG_PIN_LOW, BITBANG_CLK_EDGE_RISING},
- };
- int clk_idx;
- int n_clk = 0;
- int n_bits = 0;
- const uint8_t *dout = io->bbio_dout;
- uint8_t *din = io->bbio_din;
- int bit_pos = 7;
- bitbang_pin_func pin_f = hdl->bbh_init.bbi_pin_f;
- void *context = hdl->bbh_init.bbi_context;
-
- if ((io->bbio_in_bits == 0 && io->bbio_din)
- || (io->bbio_in_bits > 0 && !io->bbio_din)) {
- rc = EINVAL;
- LOG_ERR(rc, "Incorrect in bits and in buffer");
- goto out;
- }
-
- if ((io->bbio_out_bits == 0 && io->bbio_dout)
- || (io->bbio_out_bits > 0 && !io->bbio_dout)) {
- rc = EINVAL;
- LOG_ERR(rc, "Incorrect out bits and out buffer");
- goto out;
- }
-
- if (io->bbio_in_bits == 0 && io->bbio_out_bits == 0) {
- rc = EINVAL;
- LOG_ERR(rc, "Both in and out bits are 0");
- goto out;
- }
-
- if (hdl->bbh_init.bbi_clk_start == BITBANG_PIN_HIGH) {
- clk_idx = 0;
- } else {
- clk_idx = 1;
- }
-
- /* set the CLK pin start position */
- pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context);
-
- /* clear the first byte of din */
- if (din && io->bbio_in_bits) {
- memset(din, 0, (io->bbio_in_bits + 7) / 8);
- }
-
- do {
- if ((rc = sleep_ns(clk))) {
- goto out;
- }
-
- /* output first */
- if (hdl->bbh_init.bbi_data_out == clks[clk_idx].edge) {
- if (dout && n_bits < io->bbio_out_bits) {
- pin_f(BITBANG_DATA_OUT, (*dout >> bit_pos) & 0x1, context);
- }
- }
-
- /* then, input */
- if (hdl->bbh_init.bbi_data_in == clks[clk_idx].edge) {
- if (din && n_bits < io->bbio_in_bits) {
- *din |= (pin_f(BITBANG_DATA_IN, 0, context) & 0x1) << bit_pos;
- }
- }
-
- if (++n_clk % 2 == 0) {
- /* one bit for every 2 half clks */
- n_bits ++;
- if (bit_pos == 0) {
- if (dout) {
- dout++;
- }
- if (din) {
- din++;
- }
- bit_pos = 7;
- } else {
- bit_pos --;
- }
- }
- clk_idx = 1 - clk_idx;
- pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context);
- } while (n_bits < MAX(io->bbio_in_bits, io->bbio_out_bits));
-
- out:
-
- return -rc;
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h
deleted file mode 100644
index 0f21a49..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-#ifndef BITBANG_H
-#define BITBANG_H
-
-#include <stdint.h>
-
-typedef enum {
- BITBANG_CLK_PIN,
- BITBANG_DATA_IN,
- BITBANG_DATA_OUT,
-} bitbang_pin_type_en;
-
-typedef enum {
- BITBANG_PIN_LOW = 0,
- BITBANG_PIN_HIGH = 1,
-} bitbang_pin_value_en;
-
-typedef enum {
- BITBANG_CLK_EDGE_RISING,
- BITBANG_CLK_EDGE_FALLING,
-} bitbang_clk_edge_en;
-
-typedef bitbang_pin_value_en (* bitbang_pin_func)(
- bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context);
-
-typedef struct {
- bitbang_pin_value_en bbi_clk_start;
- bitbang_clk_edge_en bbi_data_out;
- bitbang_clk_edge_en bbi_data_in;
- uint32_t bbi_freq;
- bitbang_pin_func bbi_pin_f;
- void *bbi_context;
-} bitbang_init_st;
-
-typedef struct bitbang_handle bitbang_handle_st;
-
-void bitbang_init_default(bitbang_init_st *init);
-bitbang_handle_st* bitbang_open(const bitbang_init_st *init);
-void bitbang_close(bitbang_handle_st *hdl);
-
-typedef struct {
- uint32_t bbio_in_bits;
- uint32_t bbio_out_bits;
- uint8_t *bbio_dout;
- uint8_t *bbio_din;
-} bitbang_io_st;
-
-int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io);
-
-#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c
deleted file mode 100644
index 026aebc..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-//#define DEBUG
-//#define VERBOSE
-
-#include "gpio.h"
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-
-#include "facebook/log.h"
-
-void gpio_init_default(gpio_st *g) {
- g->gs_gpio = -1;
- g->gs_fd = -1;
-}
-
-int gpio_open(gpio_st *g, int gpio)
-{
- char buf[128];
- int rc;
-
- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/value", gpio);
- rc = open(buf, O_RDWR);
- if (rc == -1) {
- rc = errno;
- LOG_ERR(rc, "Failed to open %s", buf);
- return -rc;
- }
- g->gs_fd = rc;
- g->gs_gpio = gpio;
- return 0;
-}
-
-void gpio_close(gpio_st *g)
-{
- if (g && g->gs_fd != -1) {
- close(g->gs_fd);
- }
- gpio_init_default(g);
-}
-
-gpio_value_en gpio_read(gpio_st *g)
-{
- char buf[32] = {0};
- gpio_value_en v;
- lseek(g->gs_fd, 0, SEEK_SET);
- read(g->gs_fd, buf, sizeof(buf));
- v = atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW;
- LOG_VER("read gpio=%d value=%d %d", g->gs_gpio, atoi(buf), v);
- return v;
-}
-
-void gpio_write(gpio_st *g, gpio_value_en v)
-{
- lseek(g->gs_fd, 0, SEEK_SET);
- write(g->gs_fd, (v == GPIO_VALUE_HIGH) ? "1" : "0", 1);
- LOG_VER("write gpio=%d value=%d", g->gs_gpio, v);
-}
-
-int gpio_change_direction(gpio_st *g, gpio_direction_en dir)
-{
- char buf[128];
- char *val;
- int fd = -1;
- int rc = 0;
-
- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", g->gs_gpio);
- fd = open(buf, O_WRONLY);
- if (fd == -1) {
- rc = errno;
- LOG_ERR(rc, "Failed to open %s", buf);
- return -rc;
- }
-
- val = (dir == GPIO_DIRECTION_IN) ? "in" : "out";
- write(fd, val, strlen(val));
-
- LOG_VER("change gpio=%d direction=%s", g->gs_gpio, val);
-
- out:
- if (fd != -1) {
- close(fd);
- }
- return -rc;
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h
deleted file mode 100644
index 3303986..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-#ifndef GPIO_H
-#define GPIO_H
-
-typedef struct {
- int gs_gpio;
- int gs_fd;
-} gpio_st;
-
-typedef enum {
- GPIO_DIRECTION_IN,
- GPIO_DIRECTION_OUT,
-} gpio_direction_en;
-
-typedef enum {
- GPIO_VALUE_LOW = 0,
- GPIO_VALUE_HIGH = 1,
-} gpio_value_en;
-
-int gpio_open(gpio_st* g, int gpio);
-void gpio_close(gpio_st *g);
-gpio_value_en gpio_read(gpio_st *g);
-void gpio_write(gpio_st *g, gpio_value_en v);
-int gpio_change_direction(gpio_st *g, gpio_direction_en dir);
-
-#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c
deleted file mode 100644
index ef0c567..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-//#define DEBUG
-//#define VERBOSE
-
-#include "bitbang.h"
-#include "gpio.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "facebook/log.h"
-
-
-typedef struct {
- gpio_st m_mdc;
- gpio_st m_mdio;
-} mdio_context_st;
-
-/*
- * 32b preamble, 2b start of frame, 2b operation code,
- * 5b phy addr, 5b register addr, 2b turnaround, 16b data
- */
-#define N_BITS (32 + 2 + 2 + 5 + 5 + 2 + 16)
-#define N_BYTES (N_BITS + 7 / 8)
-
-#define START_OF_FRAME 0x1
-#define OP_READ 0x2
-#define OP_WRITE 0x1
-#define TURNAROUND 0x2 /* TA for write, for read, phy sends out TA */
-
-void usage()
-{
- fprintf(stderr,
- "Usage:\n"
- "mdio-bb: -c <GPIO for MDC> [-C <HIGH|low>]\n"
- " -d <GPIO for MDIO> [-O <rising|FALLING>]\n"
- " [-I <RISING|falling>] [-p] [-b]\n"
- " <read|write> <phy address> <register address>\n"
- " [value to write]\n");
-}
-
-bitbang_pin_value_en mdio_pin_f(
- bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context)
-{
- mdio_context_st *ctx = (mdio_context_st *)context;
- gpio_st *gpio;
- bitbang_pin_value_en res;
-
- switch (pin) {
- case BITBANG_CLK_PIN:
- gpio = &ctx->m_mdc;
- break;
- case BITBANG_DATA_IN:
- case BITBANG_DATA_OUT:
- gpio = &ctx->m_mdio;
- break;
- }
- if (pin == BITBANG_DATA_IN) {
- res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW;
- } else {
- res = value;
- gpio_write(gpio, ((res == BITBANG_PIN_HIGH)
- ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
- }
- return res;
-}
-
-int main(int argc, char* const argv[])
-{
- int opt;
- int mdc = -1, mdio = -1;
- bitbang_pin_value_en mdc_start = BITBANG_PIN_HIGH;
- bitbang_clk_edge_en out_edge = BITBANG_CLK_EDGE_FALLING;
- bitbang_clk_edge_en in_edge = BITBANG_CLK_EDGE_RISING;
- int is_write;
- uint32_t phy_addr;
- uint32_t reg_addr;
- uint32_t data; /* data to write/read*/
- uint8_t buf[N_BYTES];
- uint8_t *buf_p;
- mdio_context_st ctx;
- bitbang_init_st init;
- bitbang_handle_st *hdl = NULL;
- bitbang_io_st io;
- int n_bits;
- int i;
- int rc = 0;
- int preamble = 0;
- int binary = 0;
-
- while ((opt = getopt(argc, argv, "bc:C:d:D:p")) != -1) {
- switch (opt) {
- case 'b':
- binary = 1;
- break;
- case 'c':
- mdc = atoi(optarg);
- break;
- case 'C':
- if (!strcasecmp(optarg, "high")) {
- mdc_start = BITBANG_PIN_HIGH;
- } else if (!strcasecmp(optarg, "low")) {
- mdc_start = BITBANG_PIN_LOW;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'd':
- mdio = atoi(optarg);
- break;
- case 'I':
- if (!strcasecmp(optarg, "rising")) {
- in_edge = BITBANG_CLK_EDGE_RISING;
- } if (!strcasecmp(optarg, "falling")) {
- in_edge = BITBANG_CLK_EDGE_FALLING;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'O':
- if (!strcasecmp(optarg, "rising")) {
- out_edge = BITBANG_CLK_EDGE_RISING;
- } if (!strcasecmp(optarg, "falling")) {
- out_edge = BITBANG_CLK_EDGE_FALLING;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'p':
- preamble = 1;
- break;
- default:
- usage();
- exit(-1);
- }
- }
-
- if (mdc < 0 || mdio < 0) {
- usage();
- exit(-1);
- }
-
- if (optind + 2 >= argc) {
- usage();
- exit(-1);
- }
-
- /* read or write */
- if (!strcasecmp(argv[optind], "read")) {
- is_write = 0;
- } else if (!strcasecmp(argv[optind], "write")) {
- is_write = 1;
- } else {
- usage();
- exit(-1);
- }
-
- /* phy address, 5 bits only, so must be <= 0x1f */
- phy_addr = strtoul(argv[optind + 1], NULL, 0);
- if (phy_addr > 0x1f) {
- usage();
- exit(-1);
- }
-
- /* register address, 5 bits only, so must be <= 0x1f */
- reg_addr = strtoul(argv[optind + 2], NULL, 0);
- if (reg_addr > 0x1f) {
- usage();
- exit(-1);
- }
-
- /* data */
- if (is_write) {
- if ((!binary && (optind + 4 != argc)) ||
- (binary && (optind + 3 != argc))) {
- usage();
- exit(-1);
- }
- if (binary) {
- uint16_t temp = 0;
- if (fread(&temp, sizeof(temp), 1, stdin) != 1) {
- usage();
- exit(-1);
- }
- data = htons(temp);
- } else {
- data = strtoul(argv[optind + 3], NULL, 0);
- }
- if (data > 0xFFFF) {
- usage();
- exit(-1);
- }
- } else {
- if ((!binary && (optind + 3 != argc)) ||
- (binary && (optind + 2 != argc))) {
- usage();
- exit(-1);
- }
- }
-
- /* open all gpio */
- memset(&ctx, sizeof(ctx), 0);
- gpio_init_default(&ctx.m_mdc);
- gpio_init_default(&ctx.m_mdio);
- if (gpio_open(&ctx.m_mdc, mdc) || gpio_open(&ctx.m_mdio, mdio)) {
- goto out;
- }
-
- if (gpio_change_direction(&ctx.m_mdc, GPIO_DIRECTION_OUT)
- || gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_OUT)) {
- goto out;
- }
-
- bitbang_init_default(&init);
- init.bbi_clk_start = mdc_start;
- init.bbi_data_out = out_edge;
- init.bbi_data_in = in_edge;
- init.bbi_freq = 1000 * 1000; /* 1M Hz */
- init.bbi_pin_f = mdio_pin_f;
- init.bbi_context = &ctx;
- hdl = bitbang_open(&init);
- if (!hdl) {
- goto out;
- }
-
- if (is_write) {
- buf[0] = (data >> 8) & 0xFF;
- buf[1] = data & 0xFF;
- io.bbio_out_bits = 16;
- io.bbio_dout = buf;
- io.bbio_in_bits = 0;
- io.bbio_din = NULL;
- } else {
- io.bbio_in_bits = 16;
- io.bbio_din = buf;
- io.bbio_out_bits = 0;
- io.bbio_dout = NULL;
- }
-
- /* preamble, 32b */
- buf_p = buf;
- n_bits = 0;
- if (preamble) {
- /* 32 bit of 1 for preamble */
- for (i = 0; i < 4; i++) {
- *buf_p++ = 0xFF;
- }
- n_bits += 32;
- }
-
- /*
- * MDIO transaction header is:
- * 2b START, 2b OPER CODE, 5b PHY ADDR, 5b register addr, 2b TURNROUND
- */
- *buf_p++ = (START_OF_FRAME << 6) | (((is_write) ? OP_WRITE : OP_READ) << 4)
- | ((phy_addr >> 1) & 0xF);
- *buf_p++ = ((phy_addr & 0x1) << 7) | ((reg_addr & 0x1F) << 2) | TURNAROUND;
- if (is_write) {
- *buf_p++ = (data >> 8) & 0xFF;
- *buf_p++ = data & 0xFF;
- /* total # of bits is transaction header + 2 bytes to write */
- n_bits += 2 + 2 + 5 + 5 + 2 + 16;
- } else {
- /* for read, master does not send TR, so, n_bits should not include TR */
- n_bits += 2 + 2 + 5 + 5;
- }
-
- memset(&io, sizeof(io), 0);
- io.bbio_out_bits = n_bits;
- io.bbio_dout = buf;
- io.bbio_in_bits = 0;
- io.bbio_din = NULL;
-
- rc = bitbang_io(hdl, &io);
- if (rc != 0) {
- goto out;
- }
-
- /* for read, need to do another io for (2b TR + 16b data) reading */
- if (!is_write) {
- /* first, change the MDIO to input */
- gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_IN);
- /* then, run the clock for read */
- memset(&io, sizeof(io), 0);
- io.bbio_out_bits = 0;
- io.bbio_dout = NULL;;
- io.bbio_in_bits = 18;
- io.bbio_din = buf;
-
- rc = bitbang_io(hdl, &io);
- if (rc != 0) {
- goto out;
- }
-
- data = ((buf[0] << 2) | (buf[1] >> 6)) & 0xFF;
- data <<= 8;
- data |= ((buf[1] << 2) | (buf[2] >> 6)) & 0xFF;
- }
-
- if (binary) {
- if (!is_write) {
- uint16_t temp = ntohs(data);
- fwrite(&temp, sizeof(temp), 1, stdout);
- }
- } else {
- printf("%s: 0x%02x\n", (is_write) ? "Wrote" : "Read", data);
- }
-
- out:
- if (hdl) {
- bitbang_close(hdl);
- }
- gpio_close(&ctx.m_mdc);
- gpio_close(&ctx.m_mdio);
-
- return 0;
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c
deleted file mode 100644
index ce366a5..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-//#define DEBUG
-//#define VERBOSE
-
-#include "bitbang.h"
-#include "gpio.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "facebook/log.h"
-
-void usage()
-{
- fprintf(stderr,
- "Usage:\n"
- "spi-bb: -s <GPIO for CS> [-S <HIGH|low>]\n"
- " -c <GPIO for CLK> [-C <HIGH|low>]\n"
- " -o <GPIO for MOSI> [-O <rising|FALLING>]\n"
- " -i <GPIO for MISO> [-I <RISING|falling>]\n"
- " [-b]\n"
- " < [-r <number of bits to read>]\n"
- " [-w <number of bits to write> <byte 1> [... byte N]>\n\n"
- "Note: If both '-r' and '-w' are provided, 'write' will be performed\n"
- " before 'read'.\n");
-}
-
-typedef struct {
- gpio_st sc_clk;
- gpio_st sc_mosi;
- gpio_st sc_miso;
-} spi_context_st;
-
-bitbang_pin_value_en spi_pin_f(
- bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context)
-{
- spi_context_st *ctx = (spi_context_st *)context;
- gpio_st *gpio;
- bitbang_pin_value_en res;
-
- switch (pin) {
- case BITBANG_CLK_PIN:
- gpio = &ctx->sc_clk;
- break;
- case BITBANG_DATA_IN:
- gpio = &ctx->sc_miso;
- break;
- case BITBANG_DATA_OUT:
- gpio = &ctx->sc_mosi;
- break;
- }
- if (pin == BITBANG_DATA_IN) {
- res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW;
- } else {
- res = value;
- gpio_write(gpio, ((res == BITBANG_PIN_HIGH)
- ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
- }
- return res;
-}
-
-int main(int argc, char * const argv[])
-{
- bitbang_init_st init;
- bitbang_handle_st *hdl = NULL;
- int cs = -1, clk = -1, in = -1, out = -1;
- gpio_st cs_gpio;
- int opt;
- int is_write = 0;
- int is_read = 0;
- int read_bits = 0;
- int write_bits = 0;
- int read_bytes = 0;
- int write_bytes = 0;
- int i;
- uint8_t *read_buf = NULL;;
- uint8_t *write_buf = NULL;;
- bitbang_clk_edge_en dout_edge = BITBANG_CLK_EDGE_FALLING;
- bitbang_clk_edge_en din_edge = BITBANG_CLK_EDGE_RISING;
- bitbang_pin_value_en clk_start = BITBANG_PIN_HIGH;
- bitbang_pin_value_en cs_value = BITBANG_PIN_HIGH;
- spi_context_st ctx;
- bitbang_io_st io;
- int rc = 0;
- int binary = 0;
-
- memset(&ctx, sizeof(ctx), 0);
- gpio_init_default(&ctx.sc_clk);
- gpio_init_default(&ctx.sc_mosi);
- gpio_init_default(&ctx.sc_miso);
- gpio_init_default(&cs_gpio);
-
- while ((opt = getopt(argc, argv, "bs:S:c:C:o:O:i:I:w:r:")) != -1) {
- switch (opt) {
- case 'b':
- binary = 1;
- break;
- case 's':
- cs = atoi(optarg);
- break;
- case 'S':
- if (!strcmp(optarg, "high")) {
- cs_value = BITBANG_PIN_HIGH;
- } else if (!strcmp(optarg, "low")) {
- cs_value = BITBANG_PIN_LOW;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'c':
- clk = atoi(optarg);
- break;
- case 'C':
- if (!strcasecmp(optarg, "high")) {
- clk_start = BITBANG_PIN_HIGH;
- } else if (!strcasecmp(optarg, "low")) {
- clk_start = BITBANG_PIN_LOW;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'o':
- out = atoi(optarg);
- break;
- case 'O':
- if (!strcasecmp(optarg, "rising")) {
- dout_edge = BITBANG_CLK_EDGE_RISING;
- } else if (!strcasecmp(optarg, "falling")) {
- dout_edge = BITBANG_CLK_EDGE_FALLING;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'i':
- in = atoi(optarg);
- break;
- case 'I':
- if (!strcasecmp(optarg, "rising")) {
- din_edge = BITBANG_CLK_EDGE_RISING;
- } else if (!strcasecmp(optarg, "falling")) {
- din_edge = BITBANG_CLK_EDGE_FALLING;
- } else {
- usage();
- exit(-1);
- }
- break;
- case 'w':
- is_write = 1;
- write_bits = atoi(optarg);
- if (write_bits <= 0) {
- usage();
- exit(-1);
- }
- break;
- case 'r':
- is_read = 1;
- read_bits = atoi(optarg);
- if (read_bits <= 0) {
- usage();
- exit(-1);
- }
- break;
- default:
- usage();
- exit(-1);
- }
- }
-
- if (clk < 0 || in < 0 || out < 0) {
- usage();
- exit(-1);
- }
-
- if ((!is_read && !is_write)) {
- usage();
- exit(-1);
- }
-
- write_bytes = ((write_bits + 7) / 8);
- if (write_bytes) {
- write_buf = calloc(write_bytes, sizeof(uint8_t));
- if (!write_buf) {
- goto out;
- }
- if (binary) {
- size_t written_bytes;
- written_bytes = fread(write_buf, sizeof(*write_buf), write_bytes, stdin);
- if( written_bytes != write_bytes ) {
- goto out;
- }
- } else {
- for (i = 0; i < write_bytes && i + optind < argc; i++) {
- write_buf[i] = strtoul(argv[i + optind], NULL, 0);
- }
- }
- }
-
- read_bytes = ((read_bits + 7) / 8);
- if (read_bytes) {
- read_buf = calloc(read_bytes, sizeof(uint8_t));
- if (!read_buf) {
- goto out;
- }
- }
-
- if (gpio_open(&ctx.sc_clk, clk) || gpio_open(&ctx.sc_miso, in)
- || gpio_open(&ctx.sc_mosi, out)) {
- goto out;
- }
-
- /* change GPIO directions, only MISO is input, all others are output */
- if (gpio_change_direction(&ctx.sc_clk, GPIO_DIRECTION_OUT)
- || gpio_change_direction(&ctx.sc_miso, GPIO_DIRECTION_IN)
- || gpio_change_direction(&ctx.sc_mosi, GPIO_DIRECTION_OUT)) {
- goto out;
- }
-
- if (cs != -1) {
- if (gpio_open(&cs_gpio, cs)) {
- goto out;
- }
- if (gpio_change_direction(&cs_gpio, GPIO_DIRECTION_OUT)) {
- goto out;
- }
- }
-
- bitbang_init_default(&init);
- init.bbi_clk_start = clk_start;
- init.bbi_data_out = dout_edge;
- init.bbi_data_in = din_edge;
- init.bbi_freq = 1000 * 1000; /* 1M Hz */
- init.bbi_pin_f = spi_pin_f;
- init.bbi_context = &ctx;
-
- hdl = bitbang_open(&init);
- if (!hdl) {
- goto out;
- }
-
- if (cs != -1) {
- /* have chip select */
- gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH)
- ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
- }
-
- memset(&io, sizeof(io), 0);
- io.bbio_in_bits = read_bits;
- io.bbio_din = read_buf;
- io.bbio_out_bits = write_bits;
- io.bbio_dout = write_buf;
-
- rc = bitbang_io(hdl, &io);
- if (rc != 0) {
- goto out;
- }
-
- if (binary) {
- fwrite(read_buf, sizeof(*read_buf), read_bytes, stdout);
- } else {
- if (write_bits) {
- printf("Wrote %u bits:", write_bits);
- for (i = 0; i < write_bytes; i++) {
- printf(" %02x", write_buf[i]);
- }
- printf("\n");
- }
-
- if (read_bits) {
- printf("Read %u bits:", read_bits);
- for (i = 0; i < read_bytes; i++) {
- printf(" %02x", read_buf[i]);
- }
- printf("\n");
- }
- }
-
- out:
- if (hdl) {
- bitbang_close(hdl);
- }
- gpio_close(&ctx.sc_clk);
- gpio_close(&ctx.sc_miso);
- gpio_close(&ctx.sc_mosi);
- if (cs != -1) {
- /* reset have chip select */
- gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH)
- ? GPIO_VALUE_LOW : GPIO_VALUE_HIGH));
- gpio_close(&cs_gpio);
- }
-
- if (read_buf) {
- free(read_buf);
- }
- if (write_buf) {
- free(write_buf);
- }
- return rc;
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile
deleted file mode 100644
index fa9a8f4..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-all: fand
-
-fand: fand.cpp watchdog.cpp
- $(CXX) -pthread -o $@ $^ $(LDFLAGS) -lwedge_eeprom
-
-.PHONY: clean
-
-clean:
- rm -rf *.o fand
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README
deleted file mode 100644
index 2a92b9d..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README
+++ /dev/null
@@ -1,5 +0,0 @@
-The AST PWM/Tach driver is in the kernel sources at drivers/hwmon/ast_pwm_fan.c
-
-There are 7 PWM output pins. Each PWM can be configured in one of 3 types (M,
-N, or O). The clock settings for each type are configurable. See init_pwm.sh
-for more comments about how we configure the settings.
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp
deleted file mode 100644
index 24e107c..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * fand
- *
- * Copyright 2014-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.
- *
- * Daemon to manage the fan speed to ensure that we stay within a reasonable
- * temperature range. We're using a simplistic algorithm to get started:
- *
- * If the fan is already on high, we'll move it to medium if we fall below
- * a top temperature. If we're on medium, we'll move it to high
- * if the temperature goes over the top value, and to low if the
- * temperature falls to a bottom level. If the fan is on low,
- * we'll increase the speed if the temperature rises to the top level.
- *
- * To ensure that we're not just turning the fans up, then back down again,
- * we'll require an extra few degrees of temperature drop before we lower
- * the fan speed.
- *
- * We check the RPM of the fans against the requested RPMs to determine
- * whether the fans are failing, in which case we'll turn up all of
- * the other fans and report the problem..
- *
- * TODO: Implement a PID algorithm to closely track the ideal temperature.
- * TODO: Determine if the daemon is already started.
- */
-
-/* Yeah, the file ends in .cpp, but it's a C program. Deal. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <syslog.h>
-#include "watchdog.h"
-
-#include "facebook/wedge_eeprom.h"
-
-/* Sensor definitions */
-
-#define INTERNAL_TEMPS(x) ((x) * 1000) // stored a C * 1000
-#define EXTERNAL_TEMPS(x) ((x) / 1000)
-
-#define I2C_BUS_3_DIR "/sys/class/i2c-adapter/i2c-3/"
-#define I2C_BUS_4_DIR "/sys/class/i2c-adapter/i2c-4/"
-
-#define INTAKE_TEMP_DEVICE I2C_BUS_3_DIR "3-0048"
-#define T2_TEMP_DEVICE I2C_BUS_3_DIR "3-0049"
-#define EXHAUST_TEMP_DEVICE I2C_BUS_3_DIR "3-004a"
-#define USERVER_TEMP_DEVICE I2C_BUS_4_DIR "4-0040"
-
-/*
- * The sensor for the uServer CPU is not on the CPU itself, so it reads
- * a little low. We are special casing this, but we should obviously
- * be thinking about a way to generalize these tweaks, and perhaps
- * the entire configuration. JSON file?
- */
-
-#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(10)
-
-#define BAD_TEMP INTERNAL_TEMPS(-60)
-
-#define BAD_READ_THRESHOLD 4 /* How many times can reads fail */
-#define FAN_FAILURE_THRESHOLD 4 /* How many times can a fan fail */
-
-#define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0"
-
-#define PWM_UNIT_MAX 96
-
-#define LARGEST_DEVICE_NAME 120
-
-#define GPIO_USERVER_POWER_DIRECTION "/sys/class/gpio/gpio25/direction"
-#define GPIO_USERVER_POWER "/sys/class/gpio/gpio25/value"
-#define GPIO_T2_POWER_DIRECTION "/sys/class/gpio/gpio41/direction"
-#define GPIO_T2_POWER "/sys/class/gpio/gpio41/value"
-
-#define GPIO_FAN0_LED "/sys/class/gpio/gpio53/value"
-#define GPIO_FAN1_LED "/sys/class/gpio/gpio54/value"
-#define GPIO_FAN2_LED "/sys/class/gpio/gpio55/value"
-#define GPIO_FAN3_LED "/sys/class/gpio/gpio72/value"
-
-const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED,
- GPIO_FAN2_LED, GPIO_FAN3_LED};
-
-#define FAN_LED_RED "0"
-#define FAN_LED_BLUE "1"
-
-#define GPIO_PIN_ID "/sys/class/gpio/gpio%d/value"
-#define REV_IDS 3
-#define GPIO_REV_ID_START 192
-
-#define BOARD_IDS 4
-#define GPIO_BOARD_ID_START 160
-
-/*
- * With hardware revisions after 3, we use a different set of pins for
- * the BOARD_ID.
- */
-
-#define REV_ID_NEW_BOARD_ID 3
-#define GPIO_BOARD_ID_START_NEW 166
-
-#define REPORT_TEMP 720 /* Report temp every so many cycles */
-
-/* Sensor limits and tuning parameters */
-
-#define INTAKE_LIMIT INTERNAL_TEMPS(60)
-#define T2_LIMIT INTERNAL_TEMPS(95)
-#define USERVER_LIMIT INTERNAL_TEMPS(75)
-
-#define TEMP_TOP INTERNAL_TEMPS(70)
-#define TEMP_BOTTOM INTERNAL_TEMPS(40)
-
-/*
- * Toggling the fan constantly will wear it out (and annoy anyone who
- * can hear it), so we'll only turn down the fan after the temperature
- * has dipped a bit below the point at which we'd otherwise switch
- * things up.
- */
-
-#define COOLDOWN_SLOP INTERNAL_TEMPS(6)
-
-#define FAN_LOW 35
-#define FAN_MEDIUM 50
-#define FAN_HIGH 70
-#define FAN_MAX 99
-
-/*
- * Mapping physical to hardware addresses for fans; it's different for
- * RPM measuring and PWM setting, naturally. Doh.
- */
-
-int fan_to_rpm_map[] = {3, 2, 0, 1};
-int fan_to_pwm_map[] = {7, 6, 0, 1};
-
-#define FANS 4
-
-/*
- * The measured RPM of the fans doesn't match linearly to the requested
- * rate. In addition, there are coaxially mounted fans, so the rear fans
- * feed into the front fans. The rear fans will run slower since they're
- * grabbing still air, and the front fants are getting an extra boost.
- *
- * We'd like to measure the fan RPM and compare it to the expected RPM
- * so that we can detect failed fans, so we have a table (derived from
- * hardware testing):
- */
-
-struct rpm_to_pct_map {
- ushort pct;
- ushort rpm;
-};
-
-struct rpm_to_pct_map rpm_front_map[] = {{30, 6150},
- {35, 7208},
- {40, 8195},
- {45, 9133},
- {50, 10017},
- {55, 10847},
- {60, 11612},
- {65, 12342},
- {70, 13057},
- {75, 13717},
- {80, 14305},
- {85, 14869},
- {90, 15384},
- {95, 15871},
- {100, 16095}};
-
-struct rpm_to_pct_map rpm_rear_map[] = {{30, 3911},
- {35, 4760},
- {40, 5587},
- {45, 6434},
- {50, 7295},
- {55, 8187},
- {60, 9093},
- {65, 10008},
- {70, 10949},
- {75, 11883},
- {80, 12822},
- {85, 13726},
- {90, 14690},
- {95, 15516},
- {100, 15897}};
-
-#define FAN_FAILURE_OFFSET 30
-
-int fan_low = FAN_LOW;
-int fan_medium = FAN_MEDIUM;
-int fan_high = FAN_HIGH;
-int fan_max = FAN_MAX;
-int total_fans = FANS;
-int fan_offset = 0;
-
-int temp_bottom = TEMP_BOTTOM;
-int temp_top = TEMP_TOP;
-
-int report_temp = REPORT_TEMP;
-bool verbose = false;
-
-void usage() {
- fprintf(stderr,
- "fand [-v] [-l <low-pct>] [-m <medium-pct>] "
- "[-h <high-pct>]\n"
- "\t[-b <temp-bottom>] [-t <temp-top>] [-r <report-temp>]\n\n"
- "\tlow-pct defaults to %d%% fan\n"
- "\tmedium-pct defaults to %d%% fan\n"
- "\thigh-pct defaults to %d%% fan\n"
- "\ttemp-bottom defaults to %dC\n"
- "\ttemp-top defaults to %dC\n"
- "\treport-temp defaults to every %d measurements\n\n"
- "fand compensates for uServer temperature reading %d degrees low\n"
- "kill with SIGUSR1 to stop watchdog\n",
- fan_low,
- fan_medium,
- fan_high,
- EXTERNAL_TEMPS(temp_bottom),
- EXTERNAL_TEMPS(temp_top),
- report_temp,
- EXTERNAL_TEMPS(USERVER_TEMP_FUDGE));
- exit(1);
-}
-
-/* We need to open the device each time to read a value */
-
-int read_device(const char *device, int *value) {
- FILE *fp;
- int rc;
-
- fp = fopen(device, "r");
- if (!fp) {
- int err = errno;
-
- syslog(LOG_INFO, "failed to open device %s", device);
- return err;
- }
-
- rc = fscanf(fp, "%d", value);
- fclose(fp);
-
- if (rc != 1) {
- syslog(LOG_INFO, "failed to read device %s", device);
- return ENOENT;
- } else {
- return 0;
- }
-}
-
-/* We need to open the device again each time to write a value */
-
-int write_device(const char *device, const char *value) {
- FILE *fp;
- int rc;
-
- fp = fopen(device, "w");
- if (!fp) {
- int err = errno;
-
- syslog(LOG_INFO, "failed to open device for write %s", device);
- return err;
- }
-
- rc = fputs(value, fp);
- fclose(fp);
-
- if (rc < 0) {
- syslog(LOG_INFO, "failed to write device %s", device);
- return ENOENT;
- } else {
- return 0;
- }
-}
-
-int read_temp(const char *device, int *value) {
- char full_name[LARGEST_DEVICE_NAME + 1];
-
- /* We set an impossible value to check for errors */
- *value = BAD_TEMP;
- snprintf(
- full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device);
- return read_device(full_name, value);
-}
-
-int read_gpio_value(const int id, const char *device, int *value) {
- char full_name[LARGEST_DEVICE_NAME];
-
- snprintf(full_name, LARGEST_DEVICE_NAME, device, id);
- return read_device(full_name, value);
-}
-
-int read_gpio_values(const int start, const int count,
- const char *device, int *result) {
- int status = 0;
- int value;
-
- *result = 0;
- for (int i = 0; i < count; i++) {
- status |= read_gpio_value(start + i, GPIO_PIN_ID, &value);
- *result |= value << i;
- }
- return status;
-}
-
-int read_ids(int *rev_id, int *board_id) {
- int status = 0;
- int value;
-
- status = read_gpio_values(GPIO_REV_ID_START, REV_IDS, GPIO_PIN_ID, rev_id);
- if (status != 0) {
- syslog(LOG_INFO, "failed to read rev_id");
- return status;
- }
-
- int board_id_start;
- if (*rev_id >= REV_ID_NEW_BOARD_ID) {
- board_id_start = GPIO_BOARD_ID_START_NEW;
- } else {
- board_id_start = GPIO_BOARD_ID_START;
- }
-
- status = read_gpio_values(board_id_start, BOARD_IDS, GPIO_PIN_ID, board_id);
- if (status != 0) {
- syslog(LOG_INFO, "failed to read board_id");
- }
- return status;
-}
-
-bool is_two_fan_board(bool verbose) {
- struct wedge_eeprom_st eeprom;
- /* Retrieve the board type from EEPROM */
- if (wedge_eeprom_parse(NULL, &eeprom) == 0) {
- /* able to parse EEPROM */
- if (verbose) {
- syslog(LOG_INFO, "board type is %s", eeprom.fbw_location);
- }
- /* only WEDGE is NOT two-fan board */
- return strncasecmp(eeprom.fbw_location, "wedge",
- sizeof(eeprom.fbw_location));
- } else {
- int status;
- int board_id = 0;
- int rev_id = 0;
- /*
- * Could not parse EEPROM. Most likely, it is an old HW without EEPROM.
- * In this case, use board ID to distinguish if it is wedge or 6-pack.
- */
- status = read_ids(&rev_id, &board_id);
- if (verbose) {
- syslog(LOG_INFO, "rev ID %d, board id %d", rev_id, board_id);
- }
- if (status == 0 && board_id != 0xf) {
- return true;
- } else {
- return false;
- }
- }
-}
-
-int read_fan_value(const int fan, const char *device, int *value) {
- char device_name[LARGEST_DEVICE_NAME];
- char output_value[LARGEST_DEVICE_NAME];
- char full_name[LARGEST_DEVICE_NAME];
-
- snprintf(device_name, LARGEST_DEVICE_NAME, device, fan);
- snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name);
- return read_device(full_name, value);
-}
-
-int write_fan_value(const int fan, const char *device, const int value) {
- char full_name[LARGEST_DEVICE_NAME];
- char device_name[LARGEST_DEVICE_NAME];
- char output_value[LARGEST_DEVICE_NAME];
-
- snprintf(device_name, LARGEST_DEVICE_NAME, device, fan);
- snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name);
- snprintf(output_value, LARGEST_DEVICE_NAME, "%d", value);
- return write_device(full_name, output_value);
-}
-
-/* Return fan speed as a percentage of maximum -- not necessarily linear. */
-
-int fan_rpm_to_pct(const struct rpm_to_pct_map *table,
- const int table_len,
- int rpm) {
- int i;
-
- for (i = 0; i < table_len; i++) {
- if (table[i].rpm > rpm) {
- break;
- }
- }
-
- /*
- * If the fan RPM is lower than the lowest value in the table,
- * we may have a problem -- fans can only go so slow, and it might
- * have stopped. In this case, we'll return an interpolated
- * percentage, as just returning zero is even more problematic.
- */
-
- if (i == 0) {
- return (rpm * table[i].pct) / table[i].rpm;
- } else if (i == table_len) { // Fell off the top?
- return table[i - 1].pct;
- }
-
- // Interpolate the right percentage value:
-
- int percent_diff = table[i].pct - table[i - 1].pct;
- int rpm_diff = table[i].rpm - table[i - 1].rpm;
- int fan_diff = table[i].rpm - rpm;
-
- return table[i].pct - (fan_diff * percent_diff / rpm_diff);
-}
-
-int fan_speed_okay(const int fan, const int speed, const int slop) {
- int front_fan, rear_fan;
- int front_pct, rear_pct;
- int real_fan;
- int okay;
-
- /*
- * The hardware fan numbers are different from the physical order
- * in the box, so we have to map them:
- */
-
- real_fan = fan_to_rpm_map[fan];
-
- front_fan = 0;
- rear_fan = 0;
- read_fan_value(real_fan, "tacho%d_rpm", &front_fan);
- read_fan_value(real_fan + 4, "tacho%d_rpm", &rear_fan);
-
- front_pct =
- fan_rpm_to_pct(rpm_front_map,
- sizeof(rpm_front_map) / sizeof(struct rpm_to_pct_map),
- front_fan);
- rear_pct =
- fan_rpm_to_pct(rpm_rear_map,
- sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map),
- rear_fan);
-
- /*
- * If the fans are broken, the measured rate will be rather
- * different from the requested rate, and we can turn up the
- * rest of the fans to compensate. The slop is the percentage
- * of error that we'll tolerate.
- *
- * XXX: I suppose that we should only measure negative values;
- * running too fast isn't really a problem.
- */
-
- okay = (abs(front_pct - speed) * 100 / speed < slop &&
- abs(rear_pct - speed) * 100 / speed < slop);
-
- if (!okay || verbose) {
- syslog(!okay ? LOG_ALERT : LOG_INFO,
- "fan %d rear %d (%d%%), front %d (%d%%), expected %d",
- fan,
- rear_fan,
- rear_pct,
- front_fan,
- front_pct,
- speed);
- }
-
- return okay;
-}
-
-/* Set fan speed as a percentage */
-
-int write_fan_speed(const int fan, const int value) {
- /*
- * The hardware fan numbers for pwm control are different from
- * both the physical order in the box, and the mapping for reading
- * the RPMs per fan, above.
- */
-
- int real_fan = fan_to_pwm_map[fan];
-
- if (value == 0) {
- return write_fan_value(real_fan, "pwm%d_en", 0);
- } else {
- int unit = value * PWM_UNIT_MAX / 100;
- int status;
-
- if (unit == PWM_UNIT_MAX)
- unit = 0;
-
- if ((status = write_fan_value(real_fan, "pwm%d_type", 0)) != 0 ||
- (status = write_fan_value(real_fan, "pwm%d_rising", 0)) != 0 ||
- (status = write_fan_value(real_fan, "pwm%d_falling", unit)) != 0 ||
- (status = write_fan_value(real_fan, "pwm%d_en", 1)) != 0) {
- return status;
- }
- }
-}
-
-/* Set up fan LEDs */
-
-int write_fan_led(const int fan, const char *color)
-{
- return write_device(fan_led[fan], color);
-}
-
-int server_shutdown(const char *why) {
- int fan;
- for (fan = 0; fan < total_fans; fan++) {
- write_fan_speed(fan + fan_offset, fan_max);
- }
-
- syslog(LOG_EMERG, "Shutting down: %s", why);
- write_device(GPIO_USERVER_POWER_DIRECTION, "out");
- write_device(GPIO_USERVER_POWER, "0");
- /*
- * Putting T2 in reset generating a non-maskable interrupt to uS,
- * the kernel running on uS might panic depending on its version.
- * sleep 5s here to make sure uS is completely down.
- */
- sleep(5);
- write_device(GPIO_T2_POWER_DIRECTION, "out");
- write_device(GPIO_T2_POWER, "0");
-
- /*
- * We have to stop the watchdog, or the system will be automatically
- * rebooted some seconds after fand exits (and stops kicking the
- * watchdog).
- */
-
- stop_watchdog();
-
- sleep(2);
- exit(2);
-}
-
-/* Gracefully shut down on receipt of a signal */
-
-void fand_interrupt(int sig)
-{
- int fan;
- for (fan = 0; fan < total_fans; fan++) {
- write_fan_speed(fan + fan_offset, fan_max);
- }
-
- syslog(LOG_ALERT, "Shutting down fand on signal %s", strsignal(sig));
- if (sig == SIGUSR1) {
- stop_watchdog();
- }
- exit(3);
-}
-
-int main(int argc, char **argv) {
- /* Sensor values */
-
- int intake_temp;
- int exhaust_temp;
- int t2_temp;
- int userver_temp;
-
- int fan_speed = FAN_HIGH;
- int bad_reads = 0;
- int fan_failure = 0;
- int fan_speed_changes = 0;
- int old_speed;
-
- int fan_bad[FANS];
- int fan;
-
- unsigned log_count = 0; // How many times have we logged our temps?
- int opt;
- int prev_fans_bad = 0;
-
- struct sigaction sa;
-
- sa.sa_handler = fand_interrupt;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
-
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
-
- while ((opt = getopt(argc, argv, "l:m:h:b:t:r:v")) != -1) {
- switch (opt) {
- case 'l':
- fan_low = atoi(optarg);
- break;
- case 'm':
- fan_medium = atoi(optarg);
- break;
- case 'h':
- fan_high = atoi(optarg);
- break;
- case 'b':
- temp_bottom = INTERNAL_TEMPS(atoi(optarg));
- break;
- case 't':
- temp_top = INTERNAL_TEMPS(atoi(optarg));
- break;
- case 'r':
- report_temp = atoi(optarg);
- break;
- case 'v':
- verbose = true;
- break;
- default:
- usage();
- break;
- }
- }
-
- if (optind > argc) {
- usage();
- }
-
- if (temp_bottom > temp_top) {
- fprintf(stderr,
- "Should temp-bottom (%d) be higher than "
- "temp-top (%d)? Starting anyway.\n",
- EXTERNAL_TEMPS(temp_bottom),
- EXTERNAL_TEMPS(temp_top));
- }
-
- if (fan_low > fan_medium || fan_low > fan_high || fan_medium > fan_high) {
- fprintf(stderr,
- "fan RPMs not strictly increasing "
- "-- %d, %d, %d, starting anyway\n",
- fan_low,
- fan_medium,
- fan_high);
- }
-
- daemon(1, 0);
- openlog("fand", LOG_CONS, LOG_DAEMON);
-
- /* Start watchdog in manual mode */
- start_watchdog(0);
-
- /* Set watchdog to persistent mode so timer expiry will happen independent
- * of this process's liveliness. */
- set_persistent_watchdog(WATCHDOG_SET_PERSISTENT);
-
- if (is_two_fan_board(verbose)) {
- /* Alternate, two fan configuration */
- total_fans = 2;
- fan_offset = 2; /* fan 3 is the first */
- }
-
- for (fan = 0; fan < total_fans; fan++) {
- fan_bad[fan] = 0;
- write_fan_speed(fan + fan_offset, fan_speed);
- write_fan_led(fan + fan_offset, FAN_LED_BLUE);
- }
-
- sleep(5); /* Give the fans time to come up to speed */
-
- while (1) {
- int max_temp;
- old_speed = fan_speed;
-
- /* Read sensors */
-
- read_temp(INTAKE_TEMP_DEVICE, &intake_temp);
- read_temp(EXHAUST_TEMP_DEVICE, &exhaust_temp);
- read_temp(T2_TEMP_DEVICE, &t2_temp);
- read_temp(USERVER_TEMP_DEVICE, &userver_temp);
-
- /*
- * uServer can be powered down, but all of the rest of the sensors
- * should be readable at any time.
- */
-
- if ((intake_temp == BAD_TEMP || exhaust_temp == BAD_TEMP ||
- t2_temp == BAD_TEMP)) {
- bad_reads++;
- }
-
- if (bad_reads > BAD_READ_THRESHOLD) {
- server_shutdown("Some sensors couldn't be read");
- }
-
- if (log_count++ % report_temp == 0) {
- syslog(LOG_DEBUG,
- "Temp intake %d, t2 %d, userver %d, exhaust %d, "
- "fan speed %d, speed changes %d",
- intake_temp,
- t2_temp,
- userver_temp,
- exhaust_temp,
- fan_speed,
- fan_speed_changes);
- }
-
- /* Protection heuristics */
-
- if (intake_temp > INTAKE_LIMIT) {
- server_shutdown("Intake temp limit reached");
- }
-
- if (t2_temp > T2_LIMIT) {
- server_shutdown("T2 temp limit reached");
- }
-
- if (userver_temp + USERVER_TEMP_FUDGE > USERVER_LIMIT) {
- server_shutdown("uServer temp limit reached");
- }
-
- /*
- * Calculate change needed -- we should eventually
- * do something more sophisticated, like PID.
- *
- * We should use the intake temperature to adjust this
- * as well.
- */
-
- if (t2_temp > userver_temp + USERVER_TEMP_FUDGE) {
- max_temp = t2_temp;
- } else {
- max_temp = userver_temp + USERVER_TEMP_FUDGE;
- }
-
- /*
- * If recovering from a fan problem, spin down fans gradually in case
- * temperatures are still high. Gradual spin down also reduces wear on
- * the fans.
- */
- if (fan_speed == fan_max) {
- if (fan_failure == 0) {
- fan_speed = fan_high;
- }
- } else if (fan_speed == fan_high) {
- if (max_temp + COOLDOWN_SLOP < temp_top) {
- fan_speed = fan_medium;
- }
- } else if (fan_speed == fan_medium) {
- if (max_temp > temp_top) {
- fan_speed = fan_high;
- } else if (max_temp + COOLDOWN_SLOP < temp_bottom) {
- fan_speed = fan_low;
- }
- } else {/* low */
- if (max_temp > temp_bottom) {
- fan_speed = fan_medium;
- }
- }
-
- /*
- * Update fans only if there are no failed ones. If any fans failed
- * earlier, all remaining fans should continue to run at max speed.
- */
-
- if (fan_failure == 0 && fan_speed != old_speed) {
- syslog(LOG_NOTICE,
- "Fan speed changing from %d to %d",
- old_speed,
- fan_speed);
- fan_speed_changes++;
- for (fan = 0; fan < total_fans; fan++) {
- write_fan_speed(fan + fan_offset, fan_speed);
- }
- }
-
- /*
- * Wait for some change. Typical I2C temperature sensors
- * only provide a new value every second and a half, so
- * checking again more quickly than that is a waste.
- *
- * We also have to wait for the fan changes to take effect
- * before measuring them.
- */
-
- sleep(5);
-
- /* Check fan RPMs */
-
- for (fan = 0; fan < total_fans; fan++) {
- /*
- * Make sure that we're within some percentage
- * of the requested speed.
- */
- if (fan_speed_okay(fan + fan_offset, fan_speed, FAN_FAILURE_OFFSET)) {
- if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) {
- write_fan_led(fan + fan_offset, FAN_LED_BLUE);
- syslog(LOG_NOTICE,
- "Fan %d has recovered",
- fan);
- }
- fan_bad[fan] = 0;
- } else {
- fan_bad[fan]++;
- }
- }
-
- fan_failure = 0;
- for (fan = 0; fan < total_fans; fan++) {
- if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) {
- fan_failure++;
- write_fan_led(fan + fan_offset, FAN_LED_RED);
- }
- }
-
- if (fan_failure > 0) {
- if (prev_fans_bad != fan_failure) {
- syslog(LOG_ALERT, "%d fans failed", fan_failure);
- }
-
- /*
- * If fans are bad, we need to blast all of the
- * fans at 100%; we don't bother to turn off
- * the bad fans, in case they are all that is left.
- *
- * Note that we have a temporary bug with setting fans to
- * 100% so we only do fan_max = 99%.
- */
-
- fan_speed = fan_max;
- for (fan = 0; fan < total_fans; fan++) {
- write_fan_speed(fan + fan_offset, fan_speed);
- }
-
- /*
- * Fans can be hot swapped and replaced; in which case the fan daemon
- * will automatically detect the new fan and (assuming the new fan isn't
- * itself faulty), automatically readjust the speeds for all fans down
- * to a more suitable rpm. The fan daemon does not need to be restarted.
- */
- }
-
- /* Suppress multiple warnings for similar number of fan failures. */
- prev_fans_bad = fan_failure;
-
- /* if everything is fine, restart the watchdog countdown. If this process
- * is terminated, the persistent watchdog setting will cause the system
- * to reboot after the watchdog timeout. */
- kick_watchdog();
- }
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp
deleted file mode 100644
index ebb390a..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * watchdog
- *
- * Copyright 2014-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 "watchdog.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#define WATCHDOG_START_KEY "x"
-#define WATCHDOG_STOP_KEY "X"
-/* The "magic close" character (as defined in Linux watchdog specs). */
-#define WATCHDOG_PERSISTENT_KEY "V"
-#define WATCHDOG_NON_PERSISTENT_KEY "a"
-
-static int watchdog_dev = -1;
-
-/* This is needed to prevent rapid consecutive stop/start watchdog calls from
- * generating multiple threads. */
-static int watchdog_started = 0;
-
-static const char* watchdog_kick_key = WATCHDOG_PERSISTENT_KEY;
-static pthread_t watchdog_tid;
-static pthread_mutex_t watchdog_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* Forward declarations. */
-static void* watchdog_thread(void* args);
-static int kick_watchdog_unsafe();
-
-/*
- * When started, this background thread will constantly reset the watchdog
- * at every 5 second interval.
- */
-
-static void* watchdog_thread(void* args) {
-
- pthread_detach(pthread_self());
-
- /* Make sure another instance of the thread hasn't already been started. */
- pthread_mutex_lock(&watchdog_lock);
- if (watchdog_started) {
- goto done;
- } else {
- watchdog_started = 1;
- }
- pthread_mutex_unlock(&watchdog_lock);
-
- /* Actual loop for refreshing the watchdog timer. */
- while (1) {
- pthread_mutex_lock(&watchdog_lock);
- if (watchdog_dev != -1) {
- kick_watchdog_unsafe();
- } else {
- break;
- }
- pthread_mutex_unlock(&watchdog_lock);
- sleep(5);
- }
-
- /* Broke out of loop because watchdog was stopped. */
- watchdog_started = 0;
-done:
- pthread_mutex_unlock(&watchdog_lock);
- return NULL;
-}
-
-/*
- * Starts the watchdog timer. timer counts down and restarts the ARM chip
- * upon timeout. use kick_watchdog() to restart the timer.
- *
- * Returns: 1 on success; 0 otherwise.
- */
-
-int start_watchdog(const int auto_mode) {
- int status;
-
- pthread_mutex_lock(&watchdog_lock);
-
- /* Don't start the watchdog again if it has already been started. */
- if (watchdog_dev != -1) {
- while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0
- && errno == EINTR);
- pthread_mutex_unlock(&watchdog_lock);
- syslog(LOG_ALERT, "system watchdog already started.\n");
- return 0;
- }
-
- while (((watchdog_dev = open("/dev/watchdog", O_WRONLY)) == -1) &&
- errno == EINTR);
-
- /* Fail if watchdog device is invalid or if the user asked for auto
- * mode and the thread failed to spawn. */
- if ((watchdog_dev == -1) ||
- (auto_mode == 1 && watchdog_started == 0 &&
- pthread_create(&watchdog_tid, NULL, watchdog_thread, NULL) != 0)) {
- goto fail;
- }
-
- while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0
- && errno == EINTR);
- pthread_mutex_unlock(&watchdog_lock);
- syslog(LOG_INFO, "system watchdog started.\n");
- return 1;
-
-fail:
- if (watchdog_dev != -1) {
- close(watchdog_dev);
- watchdog_dev = -1;
- }
-
- pthread_mutex_unlock(&watchdog_lock);
- syslog(LOG_ALERT, "system watchdog failed to start!\n");
- return 0;
-}
-
-/*
- * Toggles between watchdog persistent modes. In persistent mode, the watchdog
- * timer will continue to tick even after process shutdown. Under non-
- * persistent mode, the watchdog timer will automatically be disabled when the
- * process shuts down.
- */
-void set_persistent_watchdog(enum watchdog_persistent_en persistent) {
- switch (persistent) {
- case WATCHDOG_SET_PERSISTENT:
- watchdog_kick_key = WATCHDOG_PERSISTENT_KEY;
- break;
- default:
- watchdog_kick_key = WATCHDOG_NON_PERSISTENT_KEY;
- break;
- }
- kick_watchdog();
-}
-
-/*
- * Restarts the countdown timer on the watchdog, delaying restart by another
- * timeout period (default: 11 seconds as configured in the device driver).
- *
- * This function assumes the watchdog lock has already been acquired and is
- * only used internally within the watchdog code.
- *
- * Returns 1 on success; 0 or -1 indicates failure (check errno).
- */
-
-static int kick_watchdog_unsafe() {
- int status = 0;
- if (watchdog_dev != -1) {
- while ((status = write(watchdog_dev, watchdog_kick_key, 1)) == 0
- && errno == EINTR);
- }
- return status;
-}
-
-/*
- * Acquires the watchdog lock and resets the watchdog atomically. For use by
- * library users.
- */
-
-int kick_watchdog() {
- int result;
- pthread_mutex_lock(&watchdog_lock);
- result = kick_watchdog_unsafe();
- pthread_mutex_unlock(&watchdog_lock);
-
- return result;
-}
-
-/* Shuts down the watchdog gracefully and disables the watchdog timer so that
- * restarts no longer happen.
- */
-
-void stop_watchdog() {
- int status;
- pthread_mutex_lock(&watchdog_lock);
- if (watchdog_dev != -1) {
- while ((status = write(watchdog_dev, WATCHDOG_STOP_KEY, 1)) == 0
- && errno == EINTR);
- close(watchdog_dev);
- watchdog_dev = -1;
- syslog(LOG_INFO, "system watchdog stopped.\n");
- }
- pthread_mutex_unlock(&watchdog_lock);
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h
deleted file mode 100644
index 19b9944..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * watchdog
- *
- * Copyright 2014-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.
- *
- * Utility library to handle the aspeed watchdog. Only one watchdog
- * should be in use at any time throughout the entire system (multiple users
- * will not cause adverse effects but the behavior of the watchdog becomes
- * undefined).
- *
- * The watchdog can be started in either manual or automatic mode. In manual
- * mode, the watchdog has to be constantly reset by the user via the
- * kick_watchdog() function. Under automatic mode, the watchdog will
- * run in a separate thread and reset the timer on its own so no intervention
- * is required from the user.
- *
- * In both modes, the watchdog timer will not stop when the process is
- * terminated, unless a call to stop_watchdog() has been made beforehand, or
- * if the user runs in manual mode and uses a non persistent watchdog kick.
- *
- * The default timeout for the watchdog is 11 seconds. When this time period
- * elapses, the ARM chip is restarted and the kernel is rebooted. Other
- * hardware state is not reset, so this may introduce strange behavior on
- * reboot (example: an I2C bus may be left in the open state, triggering
- * constant interrupts). In rare cases, this could result in the kernel
- * failing to fully restart itself and thus preclude the possibility of
- * reinitializing the watchdog timer. Someone will then have to go over and
- * physically restart the machine.
- *
- * The alternative to the soft reset is to request the watchdog device driver
- * for a hard reset on timeout. However this will stop the fans. If the
- * kernel fails to fully boot and restart the fan daemon, the system could
- * overheat. For this reason, we've chosen to take the risk of a stuck soft
- * reset instead.
- *
- */
-
-/* Forward declarations. */
-int start_watchdog(const int auto_mode);
-enum watchdog_persistent_en {
- WATCHDOG_SET_PERSISTENT,
- WATCHDOG_SET_NONPERSISTENT,
-};
-void set_persistent_watchdog(enum watchdog_persistent_en persistent);
-int kick_watchdog();
-void stop_watchdog();
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb
deleted file mode 100644
index 6e0c980..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-SUMMARY = "Fan controller"
-DESCRIPTION = "The utilities to control fan."
-SECTION = "base"
-PR = "r1"
-LICENSE = "GPLv2"
-LIC_FILES_CHKSUM = "file://fand.cpp;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec"
-
-DEPENDS_append = "libwedge-eeprom update-rc.d-native"
-
-SRC_URI = "file://get_fan_speed.sh \
- file://init_pwm.sh \
- file://set_fan_speed.sh \
- file://README \
- file://setup-fan.sh \
- file://Makefile \
- file://fand.cpp \
- file://watchdog.h \
- file://watchdog.cpp \
- "
-
-S = "${WORKDIR}"
-
-binfiles = "get_fan_speed.sh \
- init_pwm.sh \
- set_fan_speed.sh \
- fand \
- "
-
-otherfiles = "README"
-
-pkgdir = "fan_ctrl"
-
-do_install() {
- dst="${D}/usr/local/fbpackages/${pkgdir}"
- bin="${D}/usr/local/bin"
- install -d $dst
- install -d $bin
- for f in ${binfiles}; do
- install -m 755 $f ${dst}/$f
- ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f
- done
- for f in ${otherfiles}; do
- install -m 644 $f ${dst}/$f
- done
- install -d ${D}${sysconfdir}/init.d
- install -d ${D}${sysconfdir}/rcS.d
- install -m 755 setup-fan.sh ${D}${sysconfdir}/init.d/setup-fan.sh
- update-rc.d -r ${D} setup-fan.sh start 91 S .
-}
-
-FBPACKAGEDIR = "${prefix}/local/fbpackages"
-
-FILES_${PN} = "${FBPACKAGEDIR}/fan_ctrl ${prefix}/local/bin ${sysconfdir} "
-
-# Inhibit complaints about .debug directories for the fand binary:
-
-INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
-INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb
deleted file mode 100644
index 753adbe..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-SUMMARY = "Utilities"
-DESCRIPTION = "Various utilities"
-SECTION = "base"
-PR = "r1"
-LICENSE = "GPLv2"
-LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
-
-SRC_URI = "file://ast-functions \
- file://us_console.sh \
- file://sol.sh \
- file://power_led.sh \
- file://post_led.sh \
- file://reset_usb.sh \
- file://setup-gpio.sh \
- file://setup_rov.sh \
- file://mdio.py \
- file://bcm5396.py \
- file://bcm5396_util.py \
- file://mount_data0.sh \
- file://eth0_mac_fixup.sh \
- file://wedge_power.sh \
- file://power-on.sh \
- file://wedge_us_mac.sh \
- file://setup_switch.py \
- file://create_vlan_intf \
- file://watch-fc.sh \
- file://fcswitcher.sh \
- file://rc.early \
- file://rc.local \
- file://src \
- file://COPYING \
- "
-
-pkgdir = "utils"
-
-S = "${WORKDIR}"
-
-binfiles = "us_console.sh sol.sh power_led.sh post_led.sh \
- reset_usb.sh mdio.py setup_rov.sh wedge_power.sh wedge_us_mac.sh \
- bcm5396.py bcm5396_util.py setup_switch.py watch-fc.sh"
-
-DEPENDS_append = "update-rc.d-native"
-
-do_install() {
- dst="${D}/usr/local/fbpackages/${pkgdir}"
- install -d $dst
- install -m 644 ast-functions ${dst}/ast-functions
- localbindir="${D}/usr/local/bin"
- install -d ${localbindir}
- for f in ${binfiles}; do
- install -m 755 $f ${dst}/${f}
- ln -s ../fbpackages/${pkgdir}/${f} ${localbindir}/${f}
- done
-
- # common lib and include files
- install -d ${D}${includedir}/facebook
- install -m 0644 src/include/log.h ${D}${includedir}/facebook/log.h
- install -m 0644 src/include/i2c-dev.h ${D}${includedir}/facebook/i2c-dev.h
-
- # init
- install -d ${D}${sysconfdir}/init.d
- install -d ${D}${sysconfdir}/rcS.d
- # the script to mount /mnt/data
- install -m 0755 ${WORKDIR}/mount_data0.sh ${D}${sysconfdir}/init.d/mount_data0.sh
- update-rc.d -r ${D} mount_data0.sh start 03 S .
- install -m 0755 ${WORKDIR}/rc.early ${D}${sysconfdir}/init.d/rc.early
- update-rc.d -r ${D} rc.early start 04 S .
- install -m 755 setup-gpio.sh ${D}${sysconfdir}/init.d/setup-gpio.sh
- update-rc.d -r ${D} setup-gpio.sh start 59 S .
- # create VLAN intf automatically
- install -d ${D}/${sysconfdir}/network/if-up.d
- install -m 755 create_vlan_intf ${D}${sysconfdir}/network/if-up.d/create_vlan_intf
- # networking is done after rcS, any start level within rcS
- # for mac fixup should work
- install -m 755 eth0_mac_fixup.sh ${D}${sysconfdir}/init.d/eth0_mac_fixup.sh
- update-rc.d -r ${D} eth0_mac_fixup.sh start 70 S .
- install -m 755 power-on.sh ${D}${sysconfdir}/init.d/power-on.sh
- update-rc.d -r ${D} power-on.sh start 85 S .
- install -m 755 fcswitcher.sh ${D}${sysconfdir}/init.d/fcswitcher.sh
- update-rc.d -r ${D} fcswitcher.sh start 90 S .
- install -m 0755 ${WORKDIR}/rc.local ${D}${sysconfdir}/init.d/rc.local
- update-rc.d -r ${D} rc.local start 99 2 3 4 5 .
-}
-
-FILES_${PN} += "/usr/local ${sysconfdir}"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
deleted file mode 100644
index dd53ad1..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright 2014-present Facebook. All Rights Reserved.
-DEVMEM=/sbin/devmem
-
-devmem_set_bit() {
- local addr
- local val
- addr=$1
- val=$($DEVMEM $addr)
- val=$((val | (0x1 << $2)))
- $DEVMEM $addr 32 $val
-}
-
-devmem_clear_bit() {
- local addr
- local val
- addr=$1
- val=$($DEVMEM $addr)
- val=$((val & ~(0x1 << $2)))
- $DEVMEM $addr 32 $val
-}
-
-scu_addr() {
- echo $((0x1E6E2000 + 0x$1))
-}
-
-GPIODIR="/sys/class/gpio"
-GPIOEXPORT="$GPIODIR/export"
-
-gpio_dir() {
- echo "$GPIODIR/gpio$1"
-}
-
-gpio_name2value() {
- local first remaining base val
- remaining=$1
- val=0
- while [ -n "$remaining" ]; do
- first=${remaining:0:1}
- case "$first" in
- [[:lower:]])
- base=$(printf "%d" "'$first'")
- base=$((base - 96))
- val=$((val * 26 + base))
- ;;
- [[:upper:]])
- base=$(printf "%d" "'$first'")
- base=$((base - 64))
- val=$((val * 26 + base))
- ;;
- *)
- if [ $val -gt 0 ]; then
- val=$((val-1))
- fi
- val=$((val * 8 + $remaining))
- break
- ;;
- esac
- remaining=${remaining:1}
- done
- echo "$val"
-}
-
-gpio_export() {
- local gpio
- gpio=$(gpio_name2value $1)
- dir=$(gpio_dir $gpio)
- if [ ! -d ${dir} ]; then
- echo $gpio > $GPIOEXPORT
- fi
-}
-
-gpio_set() {
- local gpio
- local val
- gpio=$(gpio_name2value $1)
- val=$2
- dir=$(gpio_dir $gpio)
- if [ ! -d ${dir} ]; then
- echo $gpio > $GPIOEXPORT
- fi
- echo out > ${dir}/direction
- echo $val > ${dir}/value
-}
-
-gpio_get() {
- local gpio
- local val
- gpio=$(gpio_name2value $1)
- dir=$(gpio_dir $gpio)
- if [ ! -d ${dir} ]; then
- echo $gpio > $GPIOEXPORT
- fi
- echo in > ${dir}/direction
- cat ${dir}/value
-}
-
-wedge_iso_buf_enable() {
- # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
- devmem_clear_bit $(scu_addr 90) 0
- devmem_clear_bit $(scu_addr 90) 24
- gpio_set 18 0
-}
-
-wedge_iso_buf_disable() {
- # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
- devmem_clear_bit $(scu_addr 90) 0
- devmem_clear_bit $(scu_addr 90) 24
- gpio_set 18 1
-}
-
-wedge_is_us_on() {
- local val n retries prog
- if [ $# -gt 0 ]; then
- retries="$1"
- else
- retries=1
- fi
- if [ $# -gt 1 ]; then
- prog="$2"
- else
- prog=""
- fi
- n=1
- while true; do
- val=$(cat /sys/class/i2c-adapter/i2c-4/4-0040/gpio_inputs 2>/dev/null)
- if [ -n "$val" ]; then
- break
- fi
- n=$((n+1))
- if [ $n -gt $retries ]; then
- echo -n " failed to read GPIO. "
- val=0
- break
- fi
- echo -n "$prog"
- sleep 1
- done
- if [ "$((val & (0x1 << 14)))" != "0" ]; then
- # powered on already
- return 0
- else
- return 1
- fi
-}
-
-
-# Return the board type, 'LC', 'FC-LEFT', 'FC-RIGHT', or, 'WEDGE'
-wedge_board_type() {
- local pn
- pn=$(/usr/bin/weutil 2> /dev/null | grep -i '^Location on Fabric:')
- case "$pn" in
- *LEFT*)
- echo 'FC-LEFT'
- ;;
- *RIGHT*)
- echo 'FC-RIGHT'
- ;;
- *LC*)
- echo 'LC'
- ;;
- *)
- echo 'WEDGE'
- ;;
- esac
-}
-
-# On FC, FAB_SLOT_ID (GPIOU0), low == FC0; high == FC1
-# On LC, Wedge,
-# board rev < 3:
-# GPIOU0(ID0), GPIOU1(ID1), GPIOU2(ID2), GPIOU3(ID3)
-# else:
-# GPIOU6(ID0), GPIOU7(ID1), GPIOV0(ID2), GPIOV1(ID3)
-#
-# ID[2:0] ID3 Slot#
-# 000 0 1
-# 000 1 2
-# 001 0 3
-# 001 1 4
-# 010 0 5
-# 010 1 6
-# 011 0 7
-# 011 1 8
-
-wedge_slot_id() {
- local type slot id3 id2 id1 id0 FC_CARD_BASE board_rev
- FC_CARD_BASE=65
- if [ "$1" = "FC-LEFT" ]; then
- # fabric card left
- slot=$(gpio_get U0)
- slot=$((FC_CARD_BASE + slot * 2))
- elif [ "$1" = "FC-RIGHT" ]; then
- # fabric card right
- slot=$(gpio_get U0)
- slot=$((FC_CARD_BASE + slot * 2 + 1))
- else
- # either edge or LC
- # need to check the board rev
- board_rev=$(wedge_board_rev)
- if [ $board_rev -lt 3 ]; then
- id0=$(gpio_get U0)
- id1=$(gpio_get U1)
- id2=$(gpio_get U2)
- id3=$(gpio_get U3)
- else
- id0=$(gpio_get U6)
- id1=$(gpio_get U7)
- id2=$(gpio_get V0)
- id3=$(gpio_get V1)
- fi
- slot=$(((id2 * 4 + id1 * 2 + id0) * 2 + id3 + 1))
- fi
- echo "$slot"
-}
-
-# wedge_board_rev() is only valid after GPIO Y0, Y1, and Y2 are enabled
-wedge_board_rev() {
- local val0 val1 val2
- val0=$(cat /sys/class/gpio/gpio192/value 2>/dev/null)
- val1=$(cat /sys/class/gpio/gpio193/value 2>/dev/null)
- val2=$(cat /sys/class/gpio/gpio194/value 2>/dev/null)
- echo $((val0 | (val1 << 1) | (val2 << 2)))
-}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
deleted file mode 100644
index 368b807..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
+++ /dev/null
@@ -1,260 +0,0 @@
-# Copyright 2004-present Facebook. All rights reserved.
-
-import subprocess
-import struct
-import sys
-
-class VerboseLogger:
- def __init__(self, verbose=False):
- self.verbose = verbose
-
- def _verbose_print(self, caption, bytestream=None):
- '''
- Print a bytestream to stdout if verbose is enabled.
- '''
- if self.verbose:
- if bytestream is not None:
- sys.stderr.write("{}: {}\n".format(caption, " ".join(['{:02X}'.format(ord(x)) for x in bytestream])))
- else:
- sys.stderr.write("{}\n".format(caption))
-
-class AT93C46SPI(VerboseLogger):
- '''The class to access AT93C46 through SPI intf'''
- SPI_CMD = 'spi-bb'
-
- def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
- verbose=False):
- if bus_width != 8 and bus_width != 16:
- raise Exception("Invalid bus width for AT93C46!")
-
- self.bus_width = bus_width
- self.gpio_cs = gpio_cs
- self.gpio_ck = gpio_ck
- self.gpio_do = gpio_do
- self.gpio_di = gpio_di
- self.verbose = verbose
-
- self.addr_bits = 6 if self.bus_width == 16 else 7
- self.addr_mask = 0x3F if self.bus_width == 16 else 0x7F
-
- def __shift(self, bytestream, value):
- '''
- Shift an entire byte stream by value bits.
- '''
- binary = "".join(['{:08b}'.format(ord(x)) for x in bytestream])
- if value > 0:
- binary = binary[value:] + '0' * value
- else:
- binary = '0' * (-value) + binary[:value]
- return "".join([chr(int(binary[x:x+8],2)) for x in range(0, len(binary), 8)])
-
- def __io(self, op, addr, data=None):
- '''
- Perform an IO operation against the EEPROM
- '''
- write_bits = self.addr_bits + 3
- if data is not None:
- # If giving data, we are doing a write command so
- # no need to read any data.
- write_bits = write_bits + self.bus_width
- read_bits = 0
- else:
- # If not giving data, we are doing either a read
- # command or a set command, so read the result.
- # We pad with an extra bit due to a dummy bit introduced
- # by a delay for address decoding on chip.
- read_bits = self.addr_bits + 4 + self.bus_width
-
- # Format the command itself
- cmd_loc = 6 if self.bus_width == 16 else 7
- instruction = addr & self.addr_mask
- instruction = instruction | ((0x4 | (op & 0x3)) << cmd_loc)
- if data is not None:
- if self.bus_width == 16:
- write_data = struct.pack(">HH", instruction, data & 0xFFFF)
- else:
- write_data = struct.pack(">HB", instruction, data & 0xFF)
- else:
- write_data = struct.pack(">H", instruction)
- write_data = self.__shift(write_data, 16 - (cmd_loc + 3))
-
- self._verbose_print("Write data", write_data)
-
- # Run the command with the bitbang driver
- if read_bits > 0:
- data_portion = "-r {} -w {}".format(read_bits, write_bits)
- else:
- data_portion = "-w {}".format(write_bits)
-
- cmd = "{} -s {} -c {} -o {} -i {} -b {}".format(
- self.SPI_CMD, self.gpio_cs, self.gpio_ck, self.gpio_do,
- self.gpio_di, data_portion
- )
-
- self._verbose_print("Command: {}".format(cmd))
-
- out = subprocess.Popen(cmd.split(),
- stdout=subprocess.PIPE,
- stdin = subprocess.PIPE)\
- .communicate(input=write_data)
-
- # Format the response
- read_data = self.__shift(out[0], cmd_loc + 4)
- if self.bus_width == 16:
- read_data = read_data[:2]
- self._verbose_print("Read data", read_data)
- return struct.unpack(">H", read_data)[0]
- else:
- read_data = read_data[:1]
- self._verbose_print("Read data", read_data)
- return struct.unpack(">B", read_data)[0]
-
- def read(self, addr):
- return self.__io(0x2, addr)
-
- def ewen(self):
- self.__io(0x0, 0x3 << (self.addr_bits - 2))
-
- def erase(self, addr):
- self.__io(0x3, addr)
-
- def write(self, addr, data):
- self.__io(0x1, addr, data)
-
- def eral(self):
- self.__io(0x0, 0x2 << (self.addr_bits - 2))
-
- def wral(self, data):
- self.__io(0x0, 0x1 << (self.addr_bits - 2), data)
-
- def ewds(self):
- self.__io(0x0, 0x0)
-
-class AT93C46(VerboseLogger):
- '''
- The class which handles accessing memory on the AT93C46 chip.
- '''
- AT93C46_MEMORY_SIZE = 128
-
- def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
- byte_swap, verbose=False):
- self.bus_width = bus_width
- self.verbose = verbose
- self.byte_swap = byte_swap
-
- self.spi = AT93C46SPI(bus_width=bus_width, gpio_cs=gpio_cs,
- gpio_ck=gpio_ck, gpio_do=gpio_do,
- gpio_di=gpio_di, verbose=verbose)
-
- def __swap(self, value):
- '''
- Swap bytes for a 16-bit integer if instructed to do so.
- '''
- if self.bus_width == 16:
- if self.byte_swap:
- return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00)
- else:
- return value
- else:
- return value
-
- def erase(self, offset=None, limit=None):
- '''
- Erase the chip.
- '''
- if offset is None:
- offset = 0
- if limit is None:
- limit = self.AT93C46_MEMORY_SIZE
-
- if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
- raise Exception("Erase would be out of bounds!")
- if self.bus_width == 16 and \
- ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
- raise Exception("Erase can't start or end on odd boundary in 16-bit mode!")
-
- if offset == 0 and limit == self.AT93C46_MEMORY_SIZE:
- # Special case when we are erasing the entire chip
- self.spi.ewen()
- self.spi.eral()
- self.spi.ewds()
-
- self._verbose_print("Erased entire chip")
- else:
- # Regular case
- if self.bus_width == 16:
- real_offset = offset / 2
- real_limit = limit / 2
- else:
- real_offset = offset
- real_limit = limit
-
- self.spi.ewen()
- for addr in range(real_offset, real_offset + real_limit):
- self.spi.erase(addr)
- self.spi.ewds()
-
- self._verbose_print("Erased {} bytes from offset {}".format(limit, offset))
-
- def read(self, offset=None, limit=None):
- '''
- Read the chip into a memory buffer.
- '''
- if offset is None:
- offset = 0
- if limit is None:
- limit = self.AT93C46_MEMORY_SIZE
-
- if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
- raise Exception("Read would be out of bounds!")
- if self.bus_width == 16 and \
- ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
- raise Exception("Read can't start or end on odd boundary in 16-bit mode!")
-
- output = ""
- if self.bus_width == 16:
- real_offset = offset / 2
- real_limit = limit / 2
- pack_instruction = "=H"
- else:
- real_offset = offset
- real_offset
- pack_instruction = "=B"
-
- for addr in range(real_offset, real_offset + real_limit):
- output = output + struct.pack(pack_instruction, self.__swap(self.spi.read(addr)))
-
- self._verbose_print("Read {} bytes from offset {}".format(limit, offset), output)
-
- return output
-
- def write(self, data, offset=None):
- '''
- Write a memory buffer to the chip.
- '''
- if offset is None:
- offset = 0
-
- if offset < 0 or offset + len(data) > self.AT93C46_MEMORY_SIZE:
- raise Exception("Write would be out of bounds!")
- if self.bus_width == 16 and \
- ((offset & 1) != 0 or ((offset + len(data)) & 1) != 0):
- raise Exception("Write can't start or end on odd boundary in 16-bit mode!")
-
- if self.bus_width == 16:
- offset_divisor = 2
- pack_instruction = "=H"
- else:
- offset_divisor = 1
- pack_instruction = "=B"
-
- self.spi.ewen()
- for addr in range(offset, offset + len(data), offset_divisor):
- actual_addr = addr / offset_divisor
- value = self.__swap(struct.unpack(pack_instruction, data[(addr - offset):(addr - offset) + offset_divisor])[0])
-
- self.spi.erase(actual_addr)
- self.spi.write(actual_addr, value)
- self.spi.ewds()
-
- self._verbose_print("Wrote {} bytes from offset {}".format(len(data), offset), data)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
deleted file mode 100755
index 8910002..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/python -S
-# Copyright 2004-present Facebook. All rights reserved.
-
-from argparse import ArgumentParser
-from at93c46 import AT93C46, AT93C46SPI
-import sys
-
-def get_raw(args):
- return AT93C46SPI(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
- args.verbose)
-
-def get_chip(args):
- return AT93C46(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
- args.byte_swap, args.verbose)
-
-def access_parser(ap):
- # Default, based on currenct HW configuration
- SPI_CS_DEFAULT = 68
- SPI_CLK_DEFAULT = 69
- SPI_MOSI_DEFAULT = 70
- SPI_MISO_DEFAULT = 71
-
- spi_group = ap.add_argument_group('SPI Access')
- spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT,
- help='The GPIO number for SPI CS pin (default: %s)'
- % SPI_CS_DEFAULT)
- spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT,
- help='The GPIO number for SPI CLK pin (default: %s)'
- % SPI_CLK_DEFAULT)
- spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT,
- help='The GPIO number for SPI MOSI pin (default: %s)'
- % SPI_MOSI_DEFAULT)
- spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT,
- help='The GPIO number for SPI MISO pin (default: %s)'
- % SPI_MISO_DEFAULT)
-
-def bus_width_parser(ap):
- # Default, based on currenct HW configuration
- AT83C46_BUS_WIDTH = 16
-
- bus_group = ap.add_argument_group('Bus Width')
- bus_group.add_argument('--bus-width', type=int, default=AT83C46_BUS_WIDTH,
- help='The configured bus width (default: %s)'
- % AT83C46_BUS_WIDTH)
-
-def read_raw(args):
- raw = get_raw(args)
- val = raw.read(args.address)
-
- if args.int:
- print "{}".format(val)
- else:
- if args.bus_width == 16:
- print "0x{:04X}".format(val)
- else:
- print "0x{:02X}".format(val)
-
-def write_raw(args):
- if args.value[:2] == "0x":
- value = int(args.value, 16)
- else:
- value = int(args.value)
-
- raw = get_raw(args)
- raw.ewen()
- raw.erase(args.address)
- raw.write(args.address, value)
- raw.ewds()
-
-def erase_raw(args):
- raw = get_raw(args)
- raw.ewen()
- raw.erase(args.address)
- raw.ewds()
-
-def raw_subparser(subparsers):
- raw_parser = subparsers.add_parser('raw', help='Raw memory access')
- raw_sub = raw_parser.add_subparsers()
-
- read_parser = raw_sub.add_parser('read', help='Read a single memory address')
- read_parser.add_argument('address', type=int, help='The memory address')
- read_parser.add_argument('--int', action='store_true',
- help='Display output as an integer')
- read_parser.set_defaults(func=read_raw)
-
- write_parser = raw_sub.add_parser('write', help='Write a single memory address')
- write_parser.add_argument('address', type=int, help='The memory address')
- write_parser.add_argument('value', type=str, help='The value to write, either integer or hex')
- write_parser.set_defaults(func=write_raw)
-
- erase_parser = raw_sub.add_parser('erase', help='Erase a single memory address')
- erase_parser.add_argument('address', type=int, help='The memory address')
- erase_parser.set_defaults(func=erase_raw)
-
-def read_chip(args):
- chip = get_chip(args)
- data = chip.read(args.start, args.length)
-
- if args.file is None:
- sys.stdout.write(data)
- else:
- fp = open(args.file, "wb")
- fp.write(data)
-
-def write_chip(args):
- chip = get_chip(args)
-
- # Either way, limit reads to the size of the chip
- if args.file is None:
- data = sys.stdin.read(AT93C46.AT93C46_MEMORY_SIZE)
- else:
- fp = open(args.file, "rb")
- data = fp.read(AT93C46.AT93C46_MEMORY_SIZE)
-
- if args.length is not None:
- # Make sure length is correct
- if len(data) < args.length:
- data = data + '\x00' * (args.length - len(data))
- if len(data) > args.length:
- data = data[:args.length]
-
- chip.write(data, args.start)
-
-def erase_chip(args):
- chip = get_chip(args)
- chip.erase(args.start, args.length)
-
-def chip_subparser(subparsers):
- chip_parser = subparsers.add_parser('chip', help='Chip-level access')
- chip_sub = chip_parser.add_subparsers()
-
- read_parser = chip_sub.add_parser('read', help='Read from the chip')
- read_parser.add_argument('--start', type=int,
- help='The memory address to start at (default: 0)')
- read_parser.add_argument('--length', type=int,
- help='The number of bytes to read (default: whole chip)')
- read_parser.add_argument('--file', type=str,
- help='File to operate on (default: stdout)')
- read_parser.add_argument('--byte-swap', action='store_true',
- help='Byte swap values for 16-bit reads/writes')
- read_parser.set_defaults(func=read_chip)
-
- write_parser = chip_sub.add_parser('write', help='Write to the chip')
- write_parser.add_argument('--start', type=int,
- help='The memory address to start at (default: 0)')
- write_parser.add_argument('--length', type=int,
- help='The number of bytes to write (default: file length)')
- write_parser.add_argument('--file', type=str,
- help='File to operate on (default: stdin)')
- write_parser.add_argument('--byte-swap', action='store_true',
- help='Byte swap values for 16-bit reads/writes')
- write_parser.set_defaults(func=write_chip)
-
- erase_parser = chip_sub.add_parser('erase', help='Erase the chip')
- erase_parser.add_argument('--start', type=int,
- help='The memory address to start at (default: 0)')
- erase_parser.add_argument('--length', type=int,
- help='The number of bytes to erase (default: whole chip)')
- erase_parser.set_defaults(func=erase_chip)
-
-if __name__ == "__main__":
- # General arguments
- ap = ArgumentParser()
- ap.add_argument('--verbose', action='store_true',
- help='Print verbose debugging information')
-
- # SPI and bus width arguments
- access_parser(ap)
- bus_width_parser(ap)
-
- # Functionality
- subparsers = ap.add_subparsers()
- raw_subparser(subparsers)
- chip_subparser(subparsers)
-
- # Command runner
- args = ap.parse_args()
- args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
deleted file mode 100755
index 53e24f3..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#! /bin/sh
-#
-# Copyright 2014-present Facebook. All Rights Reserved.
-#
-# This program file 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; version 2 of the License.
-#
-# 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 in a file named COPYING; if not, write to the
-# Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301 USA
-#
-
-### BEGIN INIT INFO
-# Provides: usbcons
-# Required-Start:
-# Required-Stop:
-# Default-Start: S
-# Default-Stop: 0 6
-# Short-Description: Creates a virtual USB serial device and starts a console
-# on it.
-#
-### END INIT INFO
-
-PATH=/sbin:/bin:/usr/sbin:/usr/bin
-NAME="FC Switcher"
-DESC="FC Failover Daemon"
-
-# source function library
-. /etc/init.d/functions
-
-. /usr/local/fbpackages/utils/ast-functions
-
-STOPPER=
-ACTION="$1"
-
-case "$ACTION" in
- start)
- if [ "$(wedge_board_type)" = "LC" ]; then
- # Ability to prevent this from starting by editing cmdline in u-boot.
- # Keeping this here until I get gadget switching working properly. (t4906522)
- /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
- echo "$NAME."
- else
- echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
- fi
- ;;
- stop)
- echo -n "Stopping $DESC: "
- killall watch-fc.sh
- echo "$NAME."
- ;;
- restart|force-reload)
- echo -n "Restarting $DESC: "
- killall watch-fc.sh
- if [ "$(wedge_board_type)" = "LC" ]; then
- sleep 1
- /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
- echo "$NAME."
- else
- echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
- fi
- ;;
- status)
- status watch-fc.sh
- exit $?
- ;;
- *)
- N=${0##*/}
- N=${N#[SK]??}
- echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
index 1400464..4ff6f24 100755
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
@@ -56,12 +56,19 @@ target_volts=$(( $target_volts * 1 )) # normalize to decimal
rmmod pmbus
reload=$?
-# Get current voltage value
+# Get current voltage value.
+# The device here is NCP4200. It turns out the first i2c transaction to this
+# device always fails. The spec does not mention anything about NCP4200 i2c
+# engine start delay. However, each time, when the isolation buffer between the
+# BMC i2c controller and NCP4200 is disabled and re-enabled, the first i2c
+# transaction to NCP4200 always fails.
+# To workaround this issue, we are doing the first read twice.
+cur_volts=$(i2cget -y 1 0x60 0x8b w 2> /dev/null)
cur_volts=$(i2cget -y 1 0x60 0x8b w)
cur_volts=$(( $cur_volts * 1 )) # normalize to decimal
# Only bounce the T2 if we actually need to modify the voltage
-if [ $cur_volts -ne $target_volts ]; then
+if [ $cur_volts -ne $target_volts ]; then
# Set values before turning out output; we're using "PCIE, then MCS"
echo 1 > /sys/class/gpio/gpio42/value
echo 1 > /sys/class/gpio/gpio43/value
@@ -71,7 +78,7 @@ if [ $cur_volts -ne $target_volts ]; then
echo out > /sys/class/gpio/gpio16/direction
# T2 is in reset; note that this may cause NMI messages on the uServer,
# which shouldn't be up anyway when this is first run.
-
+
# Set the requested value to the current value to avoid rapid shifts
i2cset -y 1 0x60 0x21 $cur_volts w
# Enable the requested voltage
@@ -81,7 +88,7 @@ if [ $cur_volts -ne $target_volts ]; then
# Set the target voltage
i2cset -y 1 0x60 0x21 $target_volts w
-
+
sleep 1
# Let T2 come out of reset
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
deleted file mode 100644
index a69d69e..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-#ifndef LOG_H
-#define LOG_H
-
-#include <stdio.h>
-#include <string.h>
-
-//#define DEBUG
-//#define VERBOSE
-
-#define _LOG(dst, fmt, ...) do { \
- fprintf(dst, "%s:%d " fmt "\n", \
- __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- fflush(dst); \
-} while(0)
-
-#define LOG_ERR(err, fmt, ...) do { \
- char buf[128]; \
- strerror_r(err, buf, sizeof(buf)); \
- _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \
-} while(0)
-
-#define LOG_INFO(fmt, ...) do { \
- _LOG(stdout, fmt, ##__VA_ARGS__); \
-} while(0)
-
-#ifdef DEBUG
-#define LOG_DBG(fmt, ...) do { \
- _LOG(stdout, fmt, ##__VA_ARGS__); \
-} while(0)
-#else
-#define LOG_DBG(fmt, ...)
-#endif
-
-#ifdef VERBOSE
-#define LOG_VER(fmt, ...) do { \
- _LOG(stdout, fmt, ##__VA_ARGS__); \
-} while(0)
-#else
-#define LOG_VER(fmt, ...)
-#endif
-
-#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
deleted file mode 100755
index d04b7cd..0000000
--- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2014-present Facebook. All Rights Reserved.
-#
-# This program file 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; version 2 of the License.
-#
-# 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 in a file named COPYING; if not, write to the
-# Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301 USA
-#
-
-. /usr/local/fbpackages/utils/ast-functions
-
-MAC1LINK=0 # GPIOA0
-FAB0_PRES=20 # GPIOC4
-FAB1_PRES=21 # GPIOC5
-while true; do
- # fabN_pres: active low.
- if [ $(gpio_get $FAB0_PRES) = 0 ]; then
- gpio_set $MAC1LINK 0
- elif [ $(gpio_get $FAB1_PRES) = 0 ]; then
- gpio_set $MAC1LINK 1
- fi
- sleep 1
-done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf
index 44b6595..266a695 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf
+++ b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf
@@ -7,12 +7,18 @@ bus "i2c-6" "ast_i2c.6"
chip "tmp75-i2c-3-48"
label temp1 "Inlet Temp"
+ set temp1_max 70
+ set temp1_max_hyst 60
chip "tmp75-i2c-3-49"
label temp1 "Switch Temp"
+ set temp1_max 70
+ set temp1_max_hyst 60
chip "tmp75-i2c-3-4a"
label temp1 "Outlet Temp"
+ set temp1_max 70
+ set temp1_max_hyst 60
chip "tmp75-i2c-4-4c"
label temp1 "Microserver Ambient Temp"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile
index 926bf52..fa1e932 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile
@@ -15,7 +15,7 @@
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
-override CFLAGS+=-D_GNU_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=199309 -Wall -Werror -std=c99
+override CFLAGS+=-D_GNU_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=199309 -Wall -Werror -std=c99
override LDFLAGS+=-pthread
all: modbuscmd gpiowatch modbussim rackmond rackmondata
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py
index a92cf8e..34a64f8 100755
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py
@@ -2,11 +2,15 @@
from __future__ import print_function
import os.path
+import os
+import fcntl
import socket
import struct
import sys
import argparse
import traceback
+import json
+from tempfile import mkstemp
import hexfile
@@ -18,8 +22,32 @@ def auto_int(x):
parser = argparse.ArgumentParser()
parser.add_argument('--addr', type=auto_int, required=True,
help="PSU Modbus Address")
+parser.add_argument('--statusfile', default=None,
+ help="Write status to JSON file during process")
+parser.add_argument('--rmfwfile', action='store_true',
+ help="Delete FW file after update completes")
parser.add_argument('file', help="firmware file")
+status = {
+ 'pid': os.getpid(),
+ 'state': 'started'
+}
+
+statuspath = None
+
+def write_status():
+ global status
+ if statuspath is None:
+ return
+ tmppath = statuspath + '~'
+ with open(tmppath, 'wb') as tfh:
+ tfh.write(json.dumps(status))
+ os.rename(tmppath, statuspath)
+
+def status_state(state):
+ global status
+ status['state'] = state
+ write_status()
class ModbusTimeout(Exception):
pass
@@ -193,6 +221,7 @@ def write_data(addr, data):
def send_image(addr, fwimg):
+ global statuspath
total_chunks = sum([len(s) for s in fwimg.segments]) / 8
sent_chunks = 0
for s in fwimg.segments:
@@ -205,11 +234,15 @@ def send_image(addr, fwimg):
if len(chunk) < 8:
chunk = chunk + ("\xFF" * (8 - len(chunk)))
sent_chunks += 1
- print("\r[%.2f%%] Sending chunk %d of %d..." %
- (sent_chunks * 100.0 / total_chunks,
- sent_chunks, total_chunks), end="")
+ # dont fill the restapi log with junk
+ if statuspath is None:
+ print("\r[%.2f%%] Sending chunk %d of %d..." %
+ (sent_chunks * 100.0 / total_chunks,
+ sent_chunks, total_chunks), end="")
sys.stdout.flush()
write_data(addr, str(bytearray(chunk)))
+ status['flash_progress_percent'] = sent_chunks * 100.0 / total_chunks
+ write_status()
print("")
@@ -241,28 +274,45 @@ def erase_flash(addr):
def update_psu(addr, filename):
+ status_state('pausing_monitoring')
pause_monitoring()
+ status_state('parsing_fw_file')
fwimg = hexfile.load(filename)
+ status_state('bootloader_handshake')
enter_bootloader(addr)
start_programming(addr)
challenge = get_challenge(addr)
send_key(addr, delta_seccalckey(challenge))
+ status_state('erase_flash')
erase_flash(addr)
+ status_state('flashing')
send_image(addr, fwimg)
+ status_state('verifying')
verify_flash(addr)
+ status_state('resetting')
reset_psu(addr)
+ status_state('done')
def main():
args = parser.parse_args()
+ global statuspath
+ statuspath = args.statusfile
+ print("statusfile %s" % statuspath)
try:
update_psu(args.addr, args.file)
- except:
- traceback.print_exc()
+ except Exception, e:
print("Firmware update failed")
+ global status
+ status['exception'] = traceback.format_exc()
+ status_state('failed')
resume_monitoring()
+ if args.rmfwfile:
+ os.remove(args.file)
sys.exit(1)
resume_monitoring()
+ if args.rmfwfile:
+ os.remove(args.file)
sys.exit(0)
if __name__ == "__main__":
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py
index e93dfae..130f26f 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py
@@ -1,7 +1,4 @@
-from __future__ import print_function
-import struct
-import socket
-import os, os.path
+from rackmond import configure_rackmond
reglist = [
{"begin": 0x0, #MFR_MODEL
@@ -26,68 +23,198 @@ reglist = [
"length": 1,
"keep": 10, # 10-sample ring buffer
"flags": 1},
+ {"begin": 0x6B, #BBU Battery Mode
+ "length": 1,
+ "keep": 10, # 10-sample ring buffer
+ "flags": 1},
+ {"begin": 0x6C, #BBU Battery Status
+ "length": 1,
+ "keep": 10, # 10-sample ring buffer
+ "flags": 1},
+ {"begin": 0x6D, #BBU Cell Voltage 1
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x6E, #BBU Cell Voltage 2
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x6F, #BBU Cell Voltage 3
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x70, #BBU Cell Voltage 4
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x71, #BBU Cell Voltage 5
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x72, #BBU Cell Voltage 6
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x73, #BBU Cell Voltage 7
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x74, #BBU Cell Voltage 8
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x75, #BBU Cell Voltage 9
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x76, #BBU Cell Voltage 10
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x77, #BBU Cell Voltage 11
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x78, #BBU Cell Voltage 12
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x79, #BBU Cell Voltage 13
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7A, #BBU Temp 1
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7B, #BBU Temp 2
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7C, #BBU Temp 3
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7D, #BBU Temp 4
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7E, #BBU Relative State of Charge
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x7F, #BBU Absolute State of Charge
+ "length": 1,
+ "keep": 10},
{"begin": 0x80, #Input VAC
"length": 1,
"keep": 10},
+ {"begin": 0x81, #BBU Battery Voltage
+ "length": 1,
+ "keep": 10},
{"begin": 0x82, #Input Current AC
"length": 1,
"keep": 10},
+ {"begin": 0x83, #BBU Battery Current
+ "length": 1,
+ "keep": 10},
{"begin": 0x84, #Battery Voltage
"length": 1,
"keep": 10},
+ {"begin": 0x85, #BBU Average Current
+ "length": 1,
+ "keep": 10},
{"begin": 0x86, #Battery Current Output
"length": 1},
+ {"begin": 0x87, #BBU Remaining Capacity
+ "length": 1,
+ "keep": 10},
{"begin": 0x88, #Battery Current Input
"length": 1},
+ {"begin": 0x89, #BBU Full Charge Capacity
+ "length": 1,
+ "keep": 10},
{"begin": 0x8A, #Output Voltage (main converter)
"length": 1,
"keep": 10},
+ {"begin": 0x8B, #BBU Run Time to Empty
+ "length": 1,
+ "keep": 10},
{"begin": 0x8C, #Output Current (main converter)
"length": 1,
"keep": 10},
+ {"begin": 0x8D, #BBU Average Time to Empty
+ "length": 1,
+ "keep": 10},
{"begin": 0x8E, #IT Load Voltage Output
"length": 1},
+ {"begin": 0x8F, #BBU Charging Current
+ "length": 1},
{"begin": 0x90, #IT Load Current Output
"length": 1},
+ {"begin": 0x91, #BBU Charging Voltage
+ "length": 1,
+ "keep": 10},
{"begin": 0x92, #Bulk Cap Voltage
"length": 1},
+ {"begin": 0x93, #BBU Cycle Count
+ "length": 1,
+ "keep": 10},
{"begin": 0x94, #Input Power
"length": 1,
"keep": 10},
+ {"begin": 0x95, #BBU Design Capacity
+ "length": 1},
{"begin": 0x96, #Output Power
"length": 1,
"keep": 10},
+ {"begin": 0x97, #BBU Design Voltage
+ "length": 1},
{"begin": 0x98, #RPM Fan 0
"length": 1},
+ {"begin": 0x99, #BBU At Rate
+ "length": 1},
{"begin": 0x9A, #RPM Fan 1
"length": 1},
+ {"begin": 0x9B, #BBU At Rate Time to Full
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x9C, #BBU At Rate Time to Empty
+ "length": 1,
+ "keep": 10},
+ {"begin": 0x9D, #BBU At Rate OK
+ "length": 1,
+ "keep": 10},
{"begin": 0x9E, #Temp 0
"length": 1},
+ {"begin": 0x9F, #BBU Temp
+ "length": 1},
{"begin": 0xA0, #Temp 1
"length": 1},
+ {"begin": 0xA1, #BBU Max Error
+ "length": 1},
+ {"begin": 0xD0, #General Alarm Status Register
+ "length": 1},
+ {"begin": 0xD1, #PFC Alarm Status Register
+ "length": 1},
+ {"begin": 0xD2, #LLC Alarm Status Register
+ "length": 1},
+ {"begin": 0xD3, #Current Feed Alarm Status Register
+ "length": 1},
+ {"begin": 0xD4, #Auxiliary Alarm Status Register
+ "length": 1},
+ {"begin": 0xD5, #Battery Charger Alarm Status Register
+ "length": 1},
+ {"begin": 0xD7, #Temperature Alarm Status Register
+ "length": 1},
+ {"begin": 0xD8, #Fan Alarm Status Register
+ "length": 1},
+ {"begin": 0xD9, #Communication Alarm Status Register
+ "length": 1},
+ {"begin": 0x106, #BBU Specification Info
+ "length": 1},
+ {"begin": 0x107, #BBU Manufacturer Date
+ "length": 1},
+ {"begin": 0x108, #BBU Serial Number
+ "length": 1},
+ {"begin": 0x109, #BBU Device Chemistry
+ "length": 2},
+ {"begin": 0x10B, #BBU Manufacturer Data
+ "length": 2},
+ {"begin": 0x10D, #BBU Manufacturer Name
+ "length": 8},
+ {"begin": 0x115, #BBU Device Name
+ "length": 8},
+ {"begin": 0x11D, #FB Battery Status
+ "length": 4},
+ {"begin": 0x121, #SoH results
+ "length": 1},
]
def main():
- COMMAND_TYPE_SET_CONFIG = 2
- config_command = struct.pack("@HxxH",
- COMMAND_TYPE_SET_CONFIG,
- len(reglist))
- for r in reglist:
- keep = 1
- if "keep" in r:
- keep = r["keep"]
- flags = 0
- if "flags" in r:
- flags = r["flags"]
- monitor_interval = struct.pack("@HHHH", r["begin"], r["length"], keep, flags)
- config_command += monitor_interval
-
- config_packet = struct.pack("H", len(config_command)) + config_command
- srvpath = "/var/run/rackmond.sock"
- if os.path.exists(srvpath):
- client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- client.connect(srvpath)
- client.send(config_packet)
+ configure_rackmond(reglist)
if __name__ == "__main__":
main()
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py
new file mode 100644
index 0000000..35dbaa5
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.py
@@ -0,0 +1,26 @@
+import struct
+import socket
+import os, os.path
+
+def configure_rackmond(reglist):
+ COMMAND_TYPE_SET_CONFIG = 2
+ config_command = struct.pack("@HxxH",
+ COMMAND_TYPE_SET_CONFIG,
+ len(reglist))
+ for r in reglist:
+ keep = 1
+ if "keep" in r:
+ keep = r["keep"]
+ flags = 0
+ if "flags" in r:
+ flags = r["flags"]
+ monitor_interval = struct.pack("@HHHH", r["begin"], r["length"], keep, flags)
+ config_command += monitor_interval
+
+ config_packet = struct.pack("H", len(config_command)) + config_command
+ srvpath = "/var/run/rackmond.sock"
+ if os.path.exists(srvpath):
+ client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ client.connect(srvpath)
+ client.send(config_packet)
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh
index 85a1e22..b592a35 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh
@@ -16,5 +16,5 @@ echo -n "Starting rackmon background service..."
echo "done."
echo -n "Configuring rackmon service..."
-python /etc/rackmon-config.py
+PYTHONPATH=/etc python /etc/rackmon-config.py
echo "done."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
index 399f7c0..c7e78c9 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
@@ -34,6 +34,7 @@ SRC_URI = "file://Makefile \
file://rackmondata.c \
file://setup-rackmond.sh \
file://rackmon-config.py \
+ file://rackmond.py \
file://psu-update-delta.py \
file://hexfile.py \
"
@@ -66,6 +67,7 @@ do_install() {
install -d ${D}${sysconfdir}/rcS.d
install -m 755 setup-rackmond.sh ${D}${sysconfdir}/init.d/setup-rackmond.sh
install -m 755 rackmon-config.py ${D}${sysconfdir}/rackmon-config.py
+ install -m 755 rackmond.py ${D}${sysconfdir}/rackmond.py
update-rc.d -r ${D} setup-rackmond.sh start 95 2 3 4 5 .
}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/bmc_command.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/bmc_command.py
new file mode 100644
index 0000000..d4dc877
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/bmc_command.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file 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; version 2 of the License.
+#
+# 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 in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import os
+import subprocess
+import select
+import sys
+import time
+
+DEFAULT_TIMEOUT = 10 #sec
+
+# Note: Python 3.0 supports communicate() with a timeout option.
+# If we upgrade to this version we will no longer need timed_communicate
+
+class TimeoutError(Exception):
+ def __init__(self, output, error):
+ super(TimeoutError, self).__init__('process timed out')
+ self.output = output
+ self.error = error
+
+class WaitTimeoutError(Exception):
+ pass
+
+def kill_process(proc):
+ proc.terminate()
+ try:
+ timed_wait(proc, 0.1)
+ except WaitTimeoutError:
+ proc.kill()
+ try:
+ timed_wait(proc, 0.1)
+ except WaitTimeoutError:
+ # This can happen if the process is stuck waiting inside a system
+ # call for a long time. There isn't much we can do unless we want
+ # to keep waiting forever. Just give up. The child process will
+ # remain around as a zombie until we exit.
+ pass
+
+def timed_wait(proc, timeout):
+ # There unfortunately isn't a great way to wait for a process with a
+ # timeout, other than polling. (Registering for SIGCHLD and sleeping might
+ # be one option, but that's fragile and not thread-safe.)
+ poll_interval = 0.1
+ end_time = time.time() + timeout
+ while True:
+ if proc.poll() is not None:
+ return
+ time_left = max(end_time - time.time(), 0)
+ if time_left <= 0:
+ raise WaitTimeoutError()
+ time.sleep(min(time_left, poll_interval))
+
+def timed_communicate(proc, timeout=DEFAULT_TIMEOUT):
+ end_time = time.time() + timeout
+
+ p = select.poll()
+ outfd = proc.stdout.fileno()
+ errfd = proc.stderr.fileno()
+ p.register(outfd, select.POLLIN)
+ p.register(errfd, select.POLLIN)
+ results = {outfd: [], errfd: []}
+ remaining_fds = set([outfd, errfd])
+
+ bufsize = 4096
+ while remaining_fds:
+ time_left = max(end_time - time.time(), 0)
+ r = p.poll(time_left * 1000) # poll() takes timeout in milliseconds
+ if not r:
+ kill_process(proc)
+ raise TimeoutError(b''.join(results[outfd]),
+ b''.join(results[errfd]))
+ for fd, flags in r:
+ # We didn't put the fds in non-blocking mode, but we know the fd
+ # has data to read, so os.read() will return immediately.
+ d = os.read(fd, bufsize)
+ if d:
+ results[fd].append(d)
+ else:
+ # EOF on this fd, stop listening on it
+ p.unregister(fd)
+ remaining_fds.remove(fd)
+
+ try:
+ timed_wait(proc, max(end_time - time.time(), 0))
+ except WaitTimeoutError:
+ kill_process(proc)
+ raise TimeoutError(b''.join(results[outfd]),
+ b''.join(results[errfd]))
+
+ return b''.join(results[outfd]), b''.join(results[errfd])
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py
index 52c98d9..af3e75d 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py
@@ -18,11 +18,13 @@
# Boston, MA 02110-1301 USA
#
-
from ctypes import *
-from bottle import route, run, template, request, response, ServerAdapter
-from bottle import abort
-from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer
+import bottle
+from cherrypy.wsgiserver import CherryPyWSGIServer
+from cherrypy.wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter
+import datetime
+import logging
+import logging.config
import json
import ssl
import socket
@@ -34,13 +36,43 @@ import rest_bmc
import rest_gpios
import rest_modbus
import rest_slotid
+import rest_psu_update
CONSTANTS = {
'certificate': '/usr/lib/ssl/certs/rest_server.pem',
+ 'key': '/usr/lib/ssl/private/rest_server_key.pem',
+}
+
+LOGGER_CONF = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'formatters': {
+ 'default': {
+ 'format': '%(message)s'
+ },
+ },
+ 'handlers': {
+ 'file_handler': {
+ 'level': 'INFO',
+ 'formatter':'default',
+ 'class': 'logging.handlers.RotatingFileHandler',
+ 'filename':'/tmp/rest.log',
+ 'maxBytes': 1048576,
+ 'backupCount': 3,
+ 'encoding': 'utf8'
+ },
+ },
+ 'loggers': {
+ '': {
+ 'handlers': ['file_handler'],
+ 'level': 'DEBUG',
+ 'propagate': True,
+ },
+ }
}
# Handler for root resource endpoint
-@route('/api')
+@bottle.route('/api')
def rest_api():
result = {
"Information": {
@@ -53,7 +85,7 @@ def rest_api():
return result
# Handler for sys resource endpoint
-@route('/api/sys')
+@bottle.route('/api/sys')
def rest_sys():
result = {
"Information": {
@@ -67,7 +99,7 @@ def rest_sys():
return result
# Handler for sys/mb resource endpoint
-@route('/api/sys/mb')
+@bottle.route('/api/sys/mb')
def rest_sys():
result = {
"Information": {
@@ -80,73 +112,110 @@ def rest_sys():
return result
# Handler for sys/mb/fruid resource endpoint
-@route('/api/sys/mb/fruid')
+@bottle.route('/api/sys/mb/fruid')
def rest_fruid_hdl():
return rest_fruid.get_fruid()
# Handler for sys/bmc resource endpoint
-@route('/api/sys/bmc')
+@bottle.route('/api/sys/bmc')
def rest_bmc_hdl():
return rest_bmc.get_bmc()
# Handler for sys/server resource endpoint
-@route('/api/sys/server')
+@bottle.route('/api/sys/server')
def rest_server_hdl():
return rest_server.get_server()
# Handler for uServer resource endpoint
-@route('/api/sys/server', method='POST')
+@bottle.route('/api/sys/server', method='POST')
def rest_server_act_hdl():
data = json.load(request.body)
return rest_server.server_action(data)
# Handler for sensors resource endpoint
-@route('/api/sys/sensors')
+@bottle.route('/api/sys/sensors')
def rest_sensors_hdl():
return rest_sensors.get_sensors()
# Handler for sensors resource endpoint
-@route('/api/sys/gpios')
+@bottle.route('/api/sys/gpios')
def rest_gpios_hdl():
return rest_gpios.get_gpios()
-@route('/api/sys/modbus_registers')
+@bottle.route('/api/sys/modbus_registers')
def modbus_registers_hdl():
return rest_modbus.get_modbus_registers()
+@bottle.route('/api/sys/psu_update')
+def psu_update_hdl():
+ return rest_psu_update.get_jobs()
+
+@bottle.route('/api/sys/psu_update', method='POST')
+def psu_update_hdl():
+ data = json.load(request.body)
+ return rest_psu_update.begin_job(data)
+
# Handler for sensors resource endpoint
-@route('/api/sys/slotid')
+@bottle.route('/api/sys/slotid')
def rest_slotid_hdl():
return rest_slotid.get_slotid()
-run(host = "::", port = 8080)
-
# SSL Wrapper for Rest API
-class SSLWSGIRefServer(ServerAdapter):
+class SSLCherryPyServer(bottle.ServerAdapter):
def run(self, handler):
- if self.quiet:
- class QuietHandler(WSGIRequestHandler):
- def log_request(*args, **kw): pass
- self.options['handler_class'] = QuietHandler
-
- # IPv6 Support
- server_cls = self.options.get('server_class', WSGIServer)
-
- if ':' in self.host:
- if getattr(server_cls, 'address_family') == socket.AF_INET:
- class server_cls(server_cls):
- address_family = socket.AF_INET6
-
- srv = make_server(self.host, self.port, handler,
- server_class=server_cls, **self.options)
- srv.socket = ssl.wrap_socket (
- srv.socket,
- certfile=CONSTANTS['certificate'],
- server_side=True)
- srv.serve_forever()
-
-# Use SSL if the certificate exists. Otherwise, run without SSL.
-if os.access(CONSTANTS['certificate'], os.R_OK):
- run(server=SSLWSGIRefServer(host="::", port=8443))
+ server = CherryPyWSGIServer((self.host, self.port), handler)
+ server.ssl_adapter = pyOpenSSLAdapter(CONSTANTS['certificate'], CONSTANTS['key'])
+ try:
+ server.start()
+ finally:
+ server.stop()
+
+
+def log_after_request():
+ try:
+ length = bottle.response.content_length
+ except:
+ try:
+ length = len(bottle.response.body)
+ except:
+ length = 0
+
+ logging.info('{} - - [{}] "{} {} {}" {} {}'.format(
+ bottle.request.environ.get('REMOTE_ADDR'),
+ datetime.datetime.now().strftime('%d/%b/%Y %H:%M:%S'),
+ bottle.request.environ.get('REQUEST_METHOD'),
+ bottle.request.environ.get('REQUEST_URI'),
+ bottle.request.environ.get('SERVER_PROTOCOL'),
+ bottle.response.status_code,
+ length))
+
+
+# Error logging to log file
+class ErrorLogging(object):
+ def write(self, err):
+ logging.error(err)
+
+
+# Middleware to log the requests
+class LogMiddleware(object):
+ def __init__(self, app):
+ self.app = app
+
+ def __call__(self, e, h):
+ e['wsgi.errors'] = ErrorLogging()
+ ret_val = self.app(e, h)
+ log_after_request()
+ return ret_val
+
+# overwrite the stderr and stdout to log to the file
+bottle._stderr = logging.error
+bottle._stdout = logging.info
+logging.config.dictConfig(LOGGER_CONF)
+
+bottle_app = LogMiddleware(bottle.app())
+# Use SSL if the certificate and key exists. Otherwise, run without SSL.
+if (os.access(CONSTANTS['key'], os.R_OK) and
+ os.access(CONSTANTS['certificate'], os.R_OK)):
+ bottle.run(host = "::", port= 8443, server=SSLCherryPyServer, app=bottle_app)
else:
- run(host = "::", port = 8080)
+ bottle.run(host = "::", port = 8080, server='cherrypy', app=bottle_app)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py
index 167e1fa..3248e92 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py
@@ -29,9 +29,10 @@ class FRU(Structure):
("fbw_product_name", c_char * 13),
("fbw_product_number", c_char * 10),
("fbw_assembly_number", c_char * 15),
+ ("fbw_facebook_pcba_number", c_char * 15),
("fbw_facebook_pcb_number", c_char * 15),
- ("fbw_odm_pcb_number", c_char * 14),
- ("fbw_odm_pcb_serial", c_char * 13),
+ ("fbw_odm_pcba_number", c_char * 14),
+ ("fbw_odm_pcba_serial", c_char * 13),
("fbw_production_state", c_ubyte),
("fbw_product_version", c_ubyte),
("fbw_product_subversion", c_ubyte),
@@ -59,9 +60,10 @@ def get_fruid():
"Product Name": myfru.fbw_product_name,
"Product Part Number": myfru.fbw_product_number,
"System Assembly Part Number": myfru.fbw_assembly_number,
+ "Facebook PCBA Part Number": myfru.fbw_facebook_pcba_number,
"Facebook PCB Part Number": myfru.fbw_facebook_pcb_number,
- "ODM PCB Part Number": myfru.fbw_odm_pcb_number,
- "ODM PCB Serial Number": myfru.fbw_odm_pcb_serial,
+ "ODM PCBA Part Number": myfru.fbw_odm_pcba_number,
+ "ODM PCBA Serial Number": myfru.fbw_odm_pcba_serial,
"Product Production State": myfru.fbw_production_state,
"Product Version": myfru.fbw_product_version,
"Product Sub-Version": myfru.fbw_product_subversion,
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_psu_update.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_psu_update.py
new file mode 100644
index 0000000..d0e57c7
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_psu_update.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file 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; version 2 of the License.
+#
+# 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 in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+import subprocess
+from subprocess import Popen
+import os
+import os.path
+import json
+import uuid
+import urllib2
+from tempfile import mkstemp
+from bottle import HTTPError
+
+UPDATE_JOB_DIR = '/var/rackmond/update_jobs'
+UPDATERS = {'delta': '/usr/local/bin/psu-update-delta.py'}
+
+def get_jobs():
+ jobs = []
+ if not os.path.exists(UPDATE_JOB_DIR):
+ os.makedirs(UPDATE_JOB_DIR)
+ for f in os.listdir(UPDATE_JOB_DIR):
+ fullpath = os.path.join(UPDATE_JOB_DIR, f)
+ if f.endswith('.json') and os.path.isfile(fullpath):
+ with open(fullpath, 'r') as fh:
+ jdata = json.load(fh)
+ jdata['job_id'] = os.path.splitext(f)[0]
+ jobs.append(jdata)
+ return {'jobs': jobs}
+
+updater_process = None
+def begin_job(jobdesc):
+ global updater_process
+ if updater_process is not None:
+ if updater_process.poll() is not None:
+ # Update complete
+ updater_process = None
+ else:
+ body = {'error': 'update_already_running',
+ 'pid': updater_process.pid }
+ raise HTTPError(409, body)
+ job_id = str(uuid.uuid1())
+ (fwfd, fwfilepath) = mkstemp()
+ if not os.path.exists(UPDATE_JOB_DIR):
+ os.makedirs(UPDATE_JOB_DIR)
+ statusfilepath = os.path.join(UPDATE_JOB_DIR, str(job_id) + '.json')
+ status = {'pid': 0,
+ 'state': 'fetching' }
+ with open(statusfilepath, 'wb') as sfh:
+ sfh.write(json.dumps(status))
+ fwdata = urllib2.urlopen(jobdesc['fw_url'])
+ with os.fdopen(fwfd, 'wb') as fwfile:
+ fwfile.write(fwdata.read())
+ fwfile.flush()
+ updater = UPDATERS[jobdesc.get('updater', 'delta')]
+ updater_process = Popen([updater,
+ '--addr', str(jobdesc['address']),
+ '--statusfile', statusfilepath,
+ '--rmfwfile',
+ fwfilepath])
+ status = {'pid': updater_process.pid,
+ 'state': 'starting' }
+ with open(statusfilepath, 'wb') as sfh:
+ sfh.write(json.dumps(status))
+ return {'job_id': job_id, 'pid': updater_process.pid}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py
index fa65372..382513b 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py
@@ -18,15 +18,23 @@
# Boston, MA 02110-1301 USA
#
-
import json
-import os
import re
+import subprocess
+import bmc_command
# Handler for sensors resource endpoint
def get_sensors():
result = []
- data = os.popen('sensors').read()
+ proc = subprocess.Popen(['sensors'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ try:
+ data, err = bmc_command.timed_communicate(proc)
+ except bmc_command.TimeoutError as ex:
+ data = ex.output
+ err = ex.error
+
data = re.sub(r'\(.+?\)', '', data)
for edata in data.split('\n\n'):
adata = edata.split('\n', 1)
@@ -40,6 +48,7 @@ def get_sensors():
continue
sresult[tdata[0].strip()] = tdata[1].strip()
result.append(sresult)
+
fresult = {
"Information": result,
"Actions": [],
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh
index bdd79b6..2b274dc 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh
@@ -27,6 +27,53 @@
# Short-Description: Set REST API handler
### END INIT INFO
-echo -n "Setup REST API handler... "
-/usr/local/bin/rest.py > /tmp/rest.log 2>&1 &
-echo "done."
+# source function library
+. /etc/init.d/functions
+
+ACTION="$1"
+CMD="/usr/local/bin/rest.py"
+case "$ACTION" in
+ start)
+ echo -n "Setting up REST API handler: "
+ pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}')
+ if [ $pid ]; then
+ echo "already running"
+ else
+ $CMD > /tmp/rest_start.log 2>&1 &
+ echo "done."
+ fi
+ ;;
+ stop)
+ echo -n "Stopping REST API handler: "
+ pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}')
+ if [ $pid ]; then
+ kill $pid
+ fi
+ echo "done."
+ ;;
+ restart)
+ echo -n "Restarting REST API handler: "
+ pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}')
+ if [ $pid ]; then
+ kill $pid
+ fi
+ sleep 1
+ $CMD > /tmp/rest_start.log 2>&1 &
+ echo "done."
+ ;;
+ status)
+ if [[ -n $(ps | grep -v grep | grep $CMD | awk '{print $1}') ]]; then
+ echo "REST API handler is running"
+ else
+ echo "REST API is stopped"
+ fi
+ ;;
+ *)
+ N=${0##*/}
+ N=${N#[SK]??}
+ echo "Usage: $N {start|stop|status|restart}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb
index 5dec4bf..2ed3f7f 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb
@@ -33,11 +33,13 @@ SRC_URI = "file://setup-rest-api.sh \
file://rest_sensors.py \
file://rest_modbus.py \
file://rest_slotid.py \
+ file://rest_psu_update.py \
+ file://bmc_command.py \
"
S = "${WORKDIR}"
-binfiles = "rest.py rest_bmc.py rest_fruid.py rest_gpios.py rest_server.py rest_sensors.py rest_modbus.py rest_slotid.py setup-rest-api.sh"
+binfiles = "rest.py rest_bmc.py rest_fruid.py rest_gpios.py rest_server.py rest_sensors.py bmc_command.py rest_modbus.py rest_slotid.py rest_psu_update.py setup-rest-api.sh"
pkgdir = "rest-api"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh
index 0030775..2e1ee67 100755
--- a/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh
+++ b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh
@@ -19,6 +19,15 @@
#
modprobe g_cdc host_addr=02:00:00:00:00:02 dev_addr=02:00:00:00:00:01
+# For g-ether interface, if the remote side brings down the interface, BMC side
+# still treats it as up. In this case, all packets through usb0 (i.e. NDP) will
+# be queued in the kernel for this interface. Ether interface has the default
+# TX queue length as 1000, which means there could be up to 1000 package queued
+# in kernel for that. In our case, kmalloc-192 is exhausted when 298 packets
+# are queued.
+# To solve this issue, we change the TX queue length for usb0 to 64 to avoid
+# memory exhaust.
+ifconfig usb0 txqueuelen 64
while true; do
getty /dev/ttyGS0 57600
sleep 1
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c
index e66941e..7e9b50d 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c
@@ -29,8 +29,10 @@
#define FBW_EEPROM_FILE "/sys/class/i2c-adapter/i2c-6/6-0050/eeprom"
#endif
-#define FBW_EEPROM_VERSION 0
+#define FBW_EEPROM_VERSION0 0
#define FBW_EEPROM_V0_SIZE 162
+#define FBW_EEPROM_VERSION1 1
+#define FBW_EEPROM_V1_SIZE 174
/*
* The eeprom size is 8K, we only use 157 bytes for v1 format.
@@ -225,12 +227,17 @@ static int fbw_parse_buffer(
/* confirm the version number, only version is supported */
fbw_copy_uint8(&eeprom->fbw_version, &cur, FBW_EEPROM_F_VERSION);
- if (eeprom->fbw_version != FBW_EEPROM_VERSION) {
+ if ((eeprom->fbw_version != FBW_EEPROM_VERSION0) &&
+ (eeprom->fbw_version != FBW_EEPROM_VERSION1)) {
rc = EFAULT;
LOG_ERR(rc, "Unsupported version number %u", eeprom->fbw_version);
goto out;
} else {
- crc_len = FBW_EEPROM_V0_SIZE;
+ if (eeprom->fbw_version == FBW_EEPROM_VERSION0) {
+ crc_len = FBW_EEPROM_V0_SIZE;
+ } else if (eeprom->fbw_version == FBW_EEPROM_VERSION1) {
+ crc_len = FBW_EEPROM_V1_SIZE;
+ }
assert(crc_len <= len);
}
@@ -257,20 +264,27 @@ static int fbw_parse_buffer(
sizeof(eeprom->fbw_assembly_number),
&cur, FBW_EEPROM_F_ASSEMBLY_NUMBER);
- /* Facebook PCB Part Number: XXX-XXXXXXX-XX */
- fbw_copy_facebook_pcb_part(eeprom->fbw_facebook_pcb_number,
- sizeof(eeprom->fbw_facebook_pcb_number),
- &cur, FBW_EEPROM_F_FACEBOOK_PCB_NUMBER);
+ /* Facebook PCBA Part Number: XXX-XXXXXXX-XX */
+ fbw_copy_facebook_pcb_part(eeprom->fbw_facebook_pcba_number,
+ sizeof(eeprom->fbw_facebook_pcba_number),
+ &cur, FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER);
+
+ /* Facebook PCBA Part Number: XXX-XXXXXXX-XX */
+ if (eeprom->fbw_version >= FBW_EEPROM_VERSION1) {
+ fbw_copy_facebook_pcb_part(eeprom->fbw_facebook_pcb_number,
+ sizeof(eeprom->fbw_facebook_pcb_number),
+ &cur, FBW_EEPROM_F_FACEBOOK_PCB_NUMBER);
+ }
/* ODM PCB Part Number: XXXXXXXXXXXX */
- fbw_strcpy(eeprom->fbw_odm_pcb_number,
- sizeof(eeprom->fbw_odm_pcb_number),
- &cur, FBW_EEPROM_F_ODM_PCB_NUMBER);
+ fbw_strcpy(eeprom->fbw_odm_pcba_number,
+ sizeof(eeprom->fbw_odm_pcba_number),
+ &cur, FBW_EEPROM_F_ODM_PCBA_NUMBER);
/* ODM PCB Serial Number: XXXXXXXXXXXX */
- fbw_strcpy(eeprom->fbw_odm_pcb_serial,
- sizeof(eeprom->fbw_odm_pcb_serial),
- &cur, FBW_EEPROM_F_ODM_PCB_SERIAL);
+ fbw_strcpy(eeprom->fbw_odm_pcba_serial,
+ sizeof(eeprom->fbw_odm_pcba_serial),
+ &cur, FBW_EEPROM_F_ODM_PCBA_SERIAL);
/* Product Production State */
fbw_copy_uint8(&eeprom->fbw_production_state,
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h
index 2c4f39e..8aa012f 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h
@@ -29,9 +29,10 @@ extern "C" {
#define FBW_EEPROM_F_PRODUCT_NAME 12
#define FBW_EEPROM_F_PRODUCT_NUMBER 8
#define FBW_EEPROM_F_ASSEMBLY_NUMBER 12
+#define FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER 12
#define FBW_EEPROM_F_FACEBOOK_PCB_NUMBER 12
-#define FBW_EEPROM_F_ODM_PCB_NUMBER 13
-#define FBW_EEPROM_F_ODM_PCB_SERIAL 12
+#define FBW_EEPROM_F_ODM_PCBA_NUMBER 13
+#define FBW_EEPROM_F_ODM_PCBA_SERIAL 12
#define FBW_EEPROM_F_PRODUCT_STATE 1
#define FBW_EEPROM_F_PRODUCT_VERSION 1
#define FBW_EEPROM_F_PRODUCT_SUBVERSION 1
@@ -60,14 +61,17 @@ struct wedge_eeprom_st {
/* System Assembly Part Number XXX-XXXXXX-XX */
char fbw_assembly_number[FBW_EEPROM_F_ASSEMBLY_NUMBER + 3];
+ /* Facebook PCBA Part Number: XXX-XXXXXXX-XX */
+ char fbw_facebook_pcba_number[FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER + 3];
+
/* Facebook PCB Part Number: XXX-XXXXXXX-XX */
char fbw_facebook_pcb_number[FBW_EEPROM_F_FACEBOOK_PCB_NUMBER + 3];
/* ODM PCB Part Number: XXXXXXXXXXXX */
- char fbw_odm_pcb_number[FBW_EEPROM_F_ODM_PCB_NUMBER + 1];
+ char fbw_odm_pcba_number[FBW_EEPROM_F_ODM_PCBA_NUMBER + 1];
/* ODM PCB Serial Number: XXXXXXXXXXXX */
- char fbw_odm_pcb_serial[FBW_EEPROM_F_ODM_PCB_SERIAL + 1];
+ char fbw_odm_pcba_serial[FBW_EEPROM_F_ODM_PCBA_SERIAL + 1];
/* Product Production State */
uint8_t fbw_production_state;
@@ -88,7 +92,7 @@ struct wedge_eeprom_st {
char fbw_system_manufacturer[FBW_EEPROM_F_SYSTEM_MANUFACTURER + 1];
/* System Manufacturing Date: mm-dd-yy */
- char fbw_system_manufacturing_date[10];
+ uint8_t fbw_system_manufacturing_date[10];
/* PCB Manufacturer: XXXXXXXXX */
char fbw_pcb_manufacturer[FBW_EEPROM_F_PCB_MANUFACTURER + 1];
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c
index 90aca10..49d7174 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c
@@ -45,9 +45,10 @@ int main(int argc, const char *argv[])
printf("Product Name: %s\n", eeprom.fbw_product_name);
printf("Product Part Number: %s\n", eeprom.fbw_product_number);
printf("System Assembly Part Number: %s\n", eeprom.fbw_assembly_number);
+ printf("Facebook PCBA Part Number: %s\n", eeprom.fbw_facebook_pcba_number);
printf("Facebook PCB Part Number: %s\n", eeprom.fbw_facebook_pcb_number);
- printf("ODM PCB Part Number: %s\n", eeprom.fbw_odm_pcb_number);
- printf("ODM PCB Serial Number: %s\n", eeprom.fbw_odm_pcb_serial);
+ printf("ODM PCBA Part Number: %s\n", eeprom.fbw_odm_pcba_number);
+ printf("ODM PCBA Serial Number: %s\n", eeprom.fbw_odm_pcba_serial);
printf("Product Production State: %d\n", eeprom.fbw_production_state);
printf("Product Version: %d\n", eeprom.fbw_product_version);
printf("Product Sub-Version: %d\n", eeprom.fbw_product_subversion);
@@ -58,11 +59,11 @@ int main(int argc, const char *argv[])
eeprom.fbw_system_manufacturing_date);
printf("PCB Manufacturer: %s\n", eeprom.fbw_pcb_manufacturer);
printf("Assembled At: %s\n", eeprom.fbw_assembled);
- printf("Local MAC: %X:%X:%X:%X:%X:%X\n",
+ printf("Local MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
eeprom.fbw_local_mac[0], eeprom.fbw_local_mac[1],
eeprom.fbw_local_mac[2], eeprom.fbw_local_mac[3],
eeprom.fbw_local_mac[4], eeprom.fbw_local_mac[5]);
- printf("Extended MAC Base: %X:%X:%X:%X:%X:%X\n",
+ printf("Extended MAC Base: %02X:%02X:%02X:%02X:%02X:%02X\n",
eeprom.fbw_mac_base[0], eeprom.fbw_mac_base[1],
eeprom.fbw_mac_base[2], eeprom.fbw_mac_base[3],
eeprom.fbw_mac_base[4], eeprom.fbw_mac_base[5]);
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb
index 3afbed1..ea41a98 100644
--- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb
@@ -31,6 +31,8 @@ do_install() {
install -m 0755 weutil ${D}${bindir}/weutil
}
+RDEPENDS_${PN} = "libwedge-eeprom"
+
DEPENDS += "libwedge-eeprom"
FILES_${PN} = "${bindir}"
OpenPOWER on IntegriCloud