diff options
Diffstat (limited to 'common')
47 files changed, 2474 insertions, 1306 deletions
diff --git a/common/recipes-connectivity/openssh/openssh_6.5%.bbappend b/common/recipes-connectivity/openssh/openssh_%.bbappend index 60b164b..60b164b 100644 --- a/common/recipes-connectivity/openssh/openssh_6.5%.bbappend +++ b/common/recipes-connectivity/openssh/openssh_%.bbappend diff --git a/common/recipes-core/consoled/files/consoled.c b/common/recipes-core/consoled/files/consoled.c index 9f17e31..b15011e 100644 --- a/common/recipes-core/consoled/files/consoled.c +++ b/common/recipes-core/consoled/files/consoled.c @@ -49,7 +49,7 @@ write_data(int file, char *buf, int len, char *fname) { len -= wlen; tbuf = tbuf + wlen; } else { - syslog(LOG_ALERT, "write_data: write() failed to file %s | errno: %d", + syslog(LOG_WARNING, "write_data: write() failed to file %s | errno: %d", fname, errno); return; } @@ -124,7 +124,7 @@ run_console(char* fru_name, int term) { (O_RDONLY | O_NOCTTY | O_NONBLOCK); if ((tty = open(devtty, flags)) < 0) { - syslog(LOG_ALERT, "Cannot open the file %s", devtty); + syslog(LOG_WARNING, "Cannot open the file %s", devtty); exit(-1); } fcntl(tty, F_SETFL, O_RDWR); @@ -144,7 +144,7 @@ run_console(char* fru_name, int term) { sprintf(old_bfname, "/tmp/consoled_%s_log-old", fru_name); sprintf(bfname, "/tmp/consoled_%s_log", fru_name); if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) { - syslog(LOG_ALERT, "Cannot open the file %s", bfname); + syslog(LOG_WARNING, "Cannot open the file %s", bfname); exit(-1); } @@ -213,7 +213,7 @@ run_console(char* fru_name, int term) { remove(old_bfname); rename(bfname, old_bfname); if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) { - syslog(LOG_ALERT, "Cannot open the file %s", bfname); + syslog(LOG_WARNING, "Cannot open the file %s", bfname); exit(-1); } nline = 0; diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp index 49c6f6b..ccfbdb1 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp +++ b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp @@ -40,11 +40,14 @@ /* Yeah, the file ends in .cpp, but it's a C program. Deal. */ -#if !defined(CONFIG_YOSEMITE) && !defined(CONFIG_WEDGE) +/* XXX: Both CONFIG_WEDGE and CONFIG_WEDGE100 are defined for Wedge100 */ + +#if !defined(CONFIG_YOSEMITE) && !defined(CONFIG_WEDGE) && \ + !defined(CONFIG_WEDGE100) #error "No hardware platform defined!" #endif #if defined(CONFIG_YOSEMITE) && defined(CONFIG_WEDGE) -#error "Both hardware platform defined!" +#error "Two hardware platforms defined!" #endif #include <stdio.h> @@ -54,12 +57,12 @@ #include <errno.h> #include <signal.h> #include <syslog.h> -#ifdef CONFIG_YOSEMITE +#if defined(CONFIG_YOSEMITE) #include <openbmc/ipmi.h> #include <facebook/bic.h> #include <facebook/yosemite_sensor.h> #endif -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) #include <facebook/wedge_eeprom.h> #endif @@ -67,23 +70,15 @@ /* Sensor definitions */ -#ifdef CONFIG_WEDGE -#define INTERNAL_TEMPS(x) ((x) * 1000) // stored a C * 1000 +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) +#define INTERNAL_TEMPS(x) ((x) * 1000) // stored as C * 1000 #define EXTERNAL_TEMPS(x) ((x) / 1000) -#elif CONFIG_YOSEMITE +#elif defined(CONFIG_YOSEMITE) #define INTERNAL_TEMPS(x) (x) #define EXTERNAL_TEMPS(x) (x) #define TOTAL_1S_SERVERS 4 #endif -#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 @@ -91,10 +86,10 @@ * the entire configuration. JSON file? */ -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) #define USERVER_TEMP_FUDGE INTERNAL_TEMPS(10) #else -#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(1) +#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(0) #endif #define BAD_TEMP INTERNAL_TEMPS(-60) @@ -104,25 +99,47 @@ #define FAN_SHUTDOWN_THRESHOLD 20 /* How long fans can be failed before */ /* we just shut down the whole thing. */ +#if defined(CONFIG_WEDGE100) +#define PWM_DIR "/sys/bus/i2c/drivers/fancpld/8-0033/" -#define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0" +#define PWM_UNIT_MAX 31 -#define PWM_UNIT_MAX 96 +#define LM75_DIR "/sys/bus/i2c/drivers/lm75/" +#define PANTHER_PLUS_DIR "/sys/bus/i2c/drivers/panther_plus/" -#define LARGEST_DEVICE_NAME 120 +#define INTAKE_TEMP_DEVICE LM75_DIR "3-0048" +#define CHIP_TEMP_DEVICE LM75_DIR "3-004b" +#define EXHAUST_TEMP_DEVICE LM75_DIR "3-0048" +#define USERVER_TEMP_DEVICE PANTHER_PLUS_DIR "4-0040" -#define GPIO_USERVER_POWER_DIRECTION "/sys/class/gpio/gpio25/direction" -#define GPIO_USERVER_POWER "/sys/class/gpio/gpio25/value" -#define GPIO_T2_POWER_DIRECTION "/tmp/gpionames/T2_POWER_UP/direction" -#define GPIO_T2_POWER "/tmp/gpionames/T2_POWER_UP/value" +#define FAN_READ_RPM_FORMAT "fan%d_input" + +#define FAN0_LED PWM_DIR "fantray1_led_ctrl" +#define FAN1_LED PWM_DIR "fantray2_led_ctrl" +#define FAN2_LED PWM_DIR "fantray3_led_ctrl" +#define FAN3_LED PWM_DIR "fantray4_led_ctrl" +#define FAN4_LED PWM_DIR "fantray5_led_ctrl" + +#define FAN_LED_BLUE "0x1" +#define FAN_LED_RED "0x2" + +#define MAIN_POWER "/sys/bus/i2c/drivers/syscpld/12-0031/pwr_main_n" +#define USERVER_POWER "/sys/bus/i2c/drivers/syscpld/12-0031/pwr_usrv_en" + +#elif defined(CONFIG_WEDGE) +#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 CHIP_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" -#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 FAN0_LED "/sys/class/gpio/gpio53/value" +#define FAN1_LED "/sys/class/gpio/gpio54/value" +#define FAN2_LED "/sys/class/gpio/gpio55/value" +#define FAN3_LED "/sys/class/gpio/gpio72/value" #define FAN_LED_RED "0" #define FAN_LED_BLUE "1" @@ -142,13 +159,45 @@ const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED, #define REV_ID_NEW_BOARD_ID 3 #define GPIO_BOARD_ID_START_NEW 166 +#elif defined(CONFIG_YOSEMITE) +#define FAN_LED_RED "0" +#define FAN_LED_BLUE "1" +#endif + +#if (defined(CONFIG_YOSEMITE) || defined(CONFIG_WEDGE)) && \ + !defined(CONFIG_WEDGE100) +#define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0" + +#define PWM_UNIT_MAX 96 +#define FAN_READ_RPM_FORMAT "tacho%d_rpm" + +#define GPIO_USERVER_POWER_DIRECTION "/sys/class/gpio/gpio25/direction" +#define GPIO_USERVER_POWER "/sys/class/gpio/gpio25/value" +#define GPIO_T2_POWER_DIRECTION "/tmp/gpionames/T2_POWER_UP/direction" +#define GPIO_T2_POWER "/tmp/gpionames/T2_POWER_UP/value" +#endif + +#define LARGEST_DEVICE_NAME 120 + +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) +const char *fan_led[] = {FAN0_LED, FAN1_LED, FAN2_LED, FAN3_LED, +#if defined(CONFIG_WEDGE100) + FAN4_LED, +#endif +}; +#endif + #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(80) +#define SWITCH_LIMIT INTERNAL_TEMPS(80) +#if defined(CONFIG_YOSEMITE) +#define USERVER_LIMIT INTERNAL_TEMPS(110) +#else #define USERVER_LIMIT INTERNAL_TEMPS(90) +#endif #define TEMP_TOP INTERNAL_TEMPS(70) #define TEMP_BOTTOM INTERNAL_TEMPS(40) @@ -165,7 +214,11 @@ const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED, #define WEDGE_FAN_LOW 35 #define WEDGE_FAN_MEDIUM 50 #define WEDGE_FAN_HIGH 70 +#if defined(CONFIG_WEDGE100) +#define WEDGE_FAN_MAX 100 +#else #define WEDGE_FAN_MAX 99 +#endif #define SIXPACK_FAN_LOW 35 #define SIXPACK_FAN_MEDIUM 55 @@ -177,19 +230,28 @@ const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED, * RPM measuring and PWM setting, naturally. Doh. */ -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE100) +int fan_to_rpm_map[] = {1, 3, 5, 7, 9}; +int fan_to_pwm_map[] = {1, 2, 3, 4, 5}; +#define FANS 5 +// Tacho offset between front and rear fans: +#define REAR_FAN_OFFSET 1 +#define BACK_TO_BACK_FANS + +#elif defined(CONFIG_WEDGE) int fan_to_rpm_map[] = {3, 2, 0, 1}; int fan_to_pwm_map[] = {7, 6, 0, 1}; #define FANS 4 // Tacho offset between front and rear fans: #define REAR_FAN_OFFSET 4 #define BACK_TO_BACK_FANS -#else +#elif defined(CONFIG_YOSEMITE) int fan_to_rpm_map[] = {0, 1}; int fan_to_pwm_map[] = {0, 1}; #define FANS 2 // Tacho offset between front and rear fans: #define REAR_FAN_OFFSET 1 + #endif @@ -205,11 +267,49 @@ int fan_to_pwm_map[] = {0, 1}; */ struct rpm_to_pct_map { - ushort pct; - ushort rpm; + uint pct; + uint rpm; }; -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE100) +struct rpm_to_pct_map rpm_front_map[] = {{20, 4200}, + {25, 5550}, + {30, 6180}, + {35, 7440}, + {40, 8100}, + {45, 9300}, + {50, 10410}, + {55, 10920}, + {60, 11910}, + {65, 12360}, + {70, 13260}, + {75, 14010}, + {80, 14340}, + {85, 15090}, + {90, 15420}, + {95, 15960}, + {100, 16200}}; +#define FRONT_MAP_SIZE (sizeof(rpm_front_map) / sizeof(struct rpm_to_pct_map)) + +struct rpm_to_pct_map rpm_rear_map[] = {{20, 2130}, + {25, 3180}, + {30, 3690}, + {35, 4620}, + {40, 5130}, + {45, 6120}, + {50, 7050}, + {55, 7560}, + {60, 8580}, + {65, 9180}, + {70, 10230}, + {75, 11280}, + {80, 11820}, + {85, 12870}, + {90, 13350}, + {95, 14370}, + {100, 14850}}; +#define REAR_MAP_SIZE (sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map)) +#elif defined(CONFIG_WEDGE) struct rpm_to_pct_map rpm_front_map[] = {{30, 6150}, {35, 7208}, {40, 8195}, @@ -243,22 +343,21 @@ struct rpm_to_pct_map rpm_rear_map[] = {{30, 3911}, {95, 15516}, {100, 15897}}; #define REAR_MAP_SIZE (sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map)) -#else -struct rpm_to_pct_map rpm_map[] = {{30, 3413}, - {35, 3859}, - {40, 4305}, - {45, 4686}, - {50, 5032}, - {55, 5432}, - {60, 5991}, - {65, 6460}, - {70, 6927}, - {75, 7379}, - {80, 7733}, - {85, 8156}, - {90, 8599}, - {95, 9049}, - {100, 9265}}; +#elif defined(CONFIG_YOSEMITE) + +/* XXX: Note that 0% is far from 0 RPM. */ +struct rpm_to_pct_map rpm_map[] = {{0, 989}, + {10, 1654}, + {20, 2650}, + {30, 3434}, + {40, 4318}, + {50, 5202}, + {60, 5969}, + {70, 6869}, + {80, 7604}, + {90, 8525}, + {100, 9325}}; + struct rpm_to_pct_map *rpm_front_map = rpm_map; struct rpm_to_pct_map *rpm_rear_map = rpm_map; #define MAP_SIZE (sizeof(rpm_map) / sizeof(struct rpm_to_pct_map)) @@ -267,6 +366,50 @@ struct rpm_to_pct_map *rpm_rear_map = rpm_map; #endif +/* + * Mappings from temperatures recorded from sensors to fan speeds; + * note that in some cases, we want to be able to look at offsets + * from the CPU temperature margin rather than an absolute temperature, + * so we use ints. + */ + +struct temp_to_pct_map { + int temp; + unsigned speed; +}; + +#if defined(CONFIG_YOSEMITE) +struct temp_to_pct_map intake_map[] = {{25, 15}, + {27, 16}, + {29, 17}, + {31, 18}, + {33, 19}, + {35, 20}, + {37, 21}, + {39, 22}, + {41, 23}, + {43, 24}, + {45, 25}}; +#define INTAKE_MAP_SIZE (sizeof(intake_map) / sizeof(struct temp_to_pct_map)) + +struct temp_to_pct_map cpu_map[] = {{-28, 10}, + {-26, 20}, + {-24, 25}, + {-22, 30}, + {-20, 35}, + {-18, 40}, + {-16, 45}, + {-14, 50}, + {-12, 55}, + {-10, 60}, + {-8, 65}, + {-6, 70}, + {-4, 80}, + {-2, 100}}; +#define CPU_MAP_SIZE (sizeof(cpu_map) / sizeof(struct temp_to_pct_map)) +#endif + + #define FAN_FAILURE_OFFSET 30 int fan_low = WEDGE_FAN_LOW; @@ -355,7 +498,7 @@ int write_device(const char *device, const char *value) { } } -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) int read_temp(const char *device, int *value) { char full_name[LARGEST_DEVICE_NAME + 1]; @@ -365,7 +508,9 @@ int read_temp(const char *device, int *value) { full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device); return read_device(full_name, value); } +#endif +#if defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) int read_gpio_value(const int id, const char *device, int *value) { char full_name[LARGEST_DEVICE_NAME]; @@ -448,7 +593,7 @@ int read_fan_value(const int fan, const char *device, int *value) { 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); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR,device_name); return read_device(full_name, value); } @@ -512,11 +657,11 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { real_fan = fan_to_rpm_map[fan]; front_fan = 0; - read_fan_value(real_fan, "tacho%d_rpm", &front_fan); + read_fan_value(real_fan, FAN_READ_RPM_FORMAT, &front_fan); front_pct = fan_rpm_to_pct(rpm_front_map, FRONT_MAP_SIZE, front_fan); #ifdef BACK_TO_BACK_FANS rear_fan = 0; - read_fan_value(real_fan + REAR_FAN_OFFSET, "tacho%d_rpm", &rear_fan); + read_fan_value(real_fan + REAR_FAN_OFFSET, FAN_READ_RPM_FORMAT, &rear_fan); rear_pct = fan_rpm_to_pct(rpm_rear_map, REAR_MAP_SIZE, rear_fan); #endif @@ -539,7 +684,7 @@ int fan_speed_okay(const int fan, const int speed, const int slop) { #endif if (!okay || verbose) { - syslog(!okay ? LOG_ALERT : LOG_INFO, + syslog(!okay ? LOG_WARNING : LOG_INFO, #ifdef BACK_TO_BACK_FANS "fan %d rear %d (%d%%), front %d (%d%%), expected %d", #else @@ -570,11 +715,19 @@ int write_fan_speed(const int fan, const int value) { int real_fan = fan_to_pwm_map[fan]; if (value == 0) { +#if defined(CONFIG_WEDGE100) + return write_fan_value(real_fan, "fantray%d_pwm", 0); +#else return write_fan_value(real_fan, "pwm%d_en", 0); +#endif } else { int unit = value * PWM_UNIT_MAX / 100; int status; +#if defined(CONFIG_WEDGE100) + // Note that PWM for Wedge100 is in 32nds of a cycle + return write_fan_value(real_fan, "fantray%d_pwm", unit); +#else if (unit == PWM_UNIT_MAX) unit = 0; @@ -584,14 +737,25 @@ int write_fan_speed(const int fan, const int value) { (status = write_fan_value(real_fan, "pwm%d_en", 1)) != 0) { return status; } +#endif + } +} + +#if defined(CONFIG_YOSEMITE) +int temp_to_fan_speed(int temp, struct temp_to_pct_map *map, int map_size) { + int i = map_size - 1; + + while (i > 0 && temp < map[i].temp) { + --i; } + return map[i].speed; } +#endif /* Set up fan LEDs */ -int write_fan_led(const int fan, const char *color) -{ -#ifdef CONFIG_WEDGE +int write_fan_led(const int fan, const char *color) { +#if defined(CONFIG_WEDGE100) || defined(CONFIG_WEDGE) return write_device(fan_led[fan], color); #else return 0; @@ -605,9 +769,14 @@ int server_shutdown(const char *why) { } syslog(LOG_EMERG, "Shutting down: %s", why); +#if defined(CONFIG_WEDGE100) + write_device(USERVER_POWER, "0"); + sleep(5); + write_device(MAIN_POWER, "0"); +#endif +#if defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) write_device(GPIO_USERVER_POWER_DIRECTION, "out"); write_device(GPIO_USERVER_POWER, "0"); -#ifdef CONFIG_WEDGE /* * Putting T2 in reset generates a non-maskable interrupt to uS, * the kernel running on uS might panic depending on its version. @@ -627,7 +796,6 @@ int server_shutdown(const char *why) { system("rmmod adm1275"); system("i2cset -y 12 0x10 0x01 00"); } - #else // TODO(7088822): try throttling, then shutting down server. syslog(LOG_EMERG, "Need to implement actual shutdown!\n"); @@ -654,7 +822,7 @@ void fand_interrupt(int sig) write_fan_speed(fan + fan_offset, fan_max); } - syslog(LOG_ALERT, "Shutting down fand on signal %s", strsignal(sig)); + syslog(LOG_WARNING, "Shutting down fand on signal %s", strsignal(sig)); if (sig == SIGUSR1) { stop_watchdog(); } @@ -664,10 +832,10 @@ void fand_interrupt(int sig) int main(int argc, char **argv) { /* Sensor values */ -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) int intake_temp; int exhaust_temp; - int t2_temp; + int switch_temp; int userver_temp; #else float intake_temp; @@ -702,7 +870,7 @@ int main(int argc, char **argv) { openlog("fand", LOG_CONS, LOG_DAEMON); -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) if (is_two_fan_board(false)) { /* Alternate, two fan configuration */ total_fans = 2; @@ -779,11 +947,25 @@ int main(int argc, char **argv) { write_fan_led(fan + fan_offset, FAN_LED_BLUE); } -#ifdef CONFIG_YOSEMITE +#if defined(CONFIG_YOSEMITE) /* Ensure that we can read from sensors before proceeding. */ - while (yosemite_sensor_read(1, BIC_SENSOR_SOC_TEMP, &userver_temp)) - syslog(LOG_DEBUG, "Failed reading of SOC_TEMP."); + int found = 0; + userver_temp = 100; + while (!found) { + for (int node = 1; node <= TOTAL_1S_SERVERS && !found; node++) { + if (!yosemite_sensor_read(node, BIC_SENSOR_SOC_THERM_MARGIN, + &userver_temp) && + userver_temp < 0) { + syslog(LOG_DEBUG, "SOC_THERM_MARGIN first valid read of %f.", + userver_temp); + found = 1; + } + sleep(5); + } + // XXX: Will it ever be a problem that we don't exit this until + // we see a valid value? + } #endif /* Start watchdog in manual mode */ @@ -801,10 +983,10 @@ int main(int argc, char **argv) { /* Read sensors */ -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) read_temp(INTAKE_TEMP_DEVICE, &intake_temp); read_temp(EXHAUST_TEMP_DEVICE, &exhaust_temp); - read_temp(T2_TEMP_DEVICE, &t2_temp); + read_temp(CHIP_TEMP_DEVICE, &switch_temp); read_temp(USERVER_TEMP_DEVICE, &userver_temp); /* @@ -813,13 +995,13 @@ int main(int argc, char **argv) { */ if ((intake_temp == BAD_TEMP || exhaust_temp == BAD_TEMP || - t2_temp == BAD_TEMP)) { + switch_temp == BAD_TEMP)) { bad_reads++; } #else - userver_temp = BAD_TEMP; - if (yosemite_sensor_read(1, SP_SENSOR_INLET_TEMP, &intake_temp) || - yosemite_sensor_read(1, SP_SENSOR_OUTLET_TEMP, &exhaust_temp)) + intake_temp = exhaust_temp = userver_temp = BAD_TEMP; + if (yosemite_sensor_read(FRU_SPB, SP_SENSOR_INLET_TEMP, &intake_temp) || + yosemite_sensor_read(FRU_SPB, SP_SENSOR_OUTLET_TEMP, &exhaust_temp)) bad_reads++; /* @@ -829,11 +1011,15 @@ int main(int argc, char **argv) { */ for (int node = 1; node <= TOTAL_1S_SERVERS; node++) { float new_temp; - if (!yosemite_sensor_read(node, BIC_SENSOR_SOC_TEMP, &new_temp)) { + if (!yosemite_sensor_read(node, BIC_SENSOR_SOC_THERM_MARGIN, + &new_temp)) { if (userver_temp < new_temp) { userver_temp = new_temp; } } + + // Since the yosemite_sensor_read() times out after 8secs, keep WDT from expiring + kick_watchdog(); } #endif @@ -843,7 +1029,7 @@ int main(int argc, char **argv) { if (log_count++ % report_temp == 0) { syslog(LOG_DEBUG, -#ifdef CONFIG_WEDGE +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) "Temp intake %d, t2 %d, " " userver %d, exhaust %d, " "fan speed %d, speed changes %d", @@ -852,8 +1038,8 @@ int main(int argc, char **argv) { "fan speed %d, speed changes %d", #endif intake_temp, -#ifdef CONFIG_WEDGE - t2_temp, +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) + switch_temp, #endif userver_temp, exhaust_temp, @@ -867,8 +1053,8 @@ int main(int argc, char **argv) { server_shutdown("Intake temp limit reached"); } -#ifdef CONFIG_WEDGE - if (t2_temp > T2_LIMIT) { +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) + if (switch_temp > SWITCH_LIMIT) { server_shutdown("T2 temp limit reached"); } #endif @@ -885,20 +1071,28 @@ int main(int argc, char **argv) { * as well. */ -#ifdef CONFIG_WEDGE - if (t2_temp > userver_temp + USERVER_TEMP_FUDGE) { - max_temp = t2_temp; +#if defined(CONFIG_YOSEMITE) + /* Use tables to lookup the new fan speed for Yosemite. */ + + int intake_speed = temp_to_fan_speed(intake_temp, intake_map, + INTAKE_MAP_SIZE); + int cpu_speed = temp_to_fan_speed(userver_temp, cpu_map, CPU_MAP_SIZE); + + if (fan_speed == fan_max && fan_failure != 0) { + /* Don't change a thing */ + } else if (intake_speed > cpu_speed) { + fan_speed = intake_speed; } else { - max_temp = userver_temp + USERVER_TEMP_FUDGE; + fan_speed = cpu_speed; } #else - /* Yosemite could have no servers turned on, so ignore that case. */ - if (userver_temp + USERVER_TEMP_FUDGE > exhaust_temp) { - max_temp = userver_temp + USERVER_TEMP_FUDGE; + /* Other systems use a simpler built-in table to determine fan speed. */ + + if (switch_temp > userver_temp + USERVER_TEMP_FUDGE) { + max_temp = switch_temp; } else { - max_temp = exhaust_temp; + max_temp = userver_temp + USERVER_TEMP_FUDGE; } -#endif /* * If recovering from a fan problem, spin down fans gradually in case @@ -924,6 +1118,7 @@ int main(int argc, char **argv) { fan_speed = fan_medium; } } +#endif /* * Update fans only if there are no failed ones. If any fans failed @@ -962,7 +1157,7 @@ int main(int argc, char **argv) { 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, + syslog(LOG_CRIT, "Fan %d has recovered", fan); } @@ -982,7 +1177,7 @@ int main(int argc, char **argv) { if (fan_failure > 0) { if (prev_fans_bad != fan_failure) { - syslog(LOG_ALERT, "%d fans failed", fan_failure); + syslog(LOG_CRIT, "%d fans failed", fan_failure); } /* @@ -999,6 +1194,15 @@ int main(int argc, char **argv) { write_fan_speed(fan + fan_offset, fan_speed); } +#if defined(CONFIG_WEDGE) || defined(CONFIG_WEDGE100) + /* + * On Wedge, we want to shut down everything if none of the fans + * are visible, since there isn't automatic protection to shut + * off the server or switch chip. On other platforms, the CPUs + * generating the heat will automatically turn off, so this is + * unnecessary. + */ + if (fan_failure == total_fans) { int count = 0; for (fan = 0; fan < total_fans; fan++) { @@ -1009,7 +1213,7 @@ int main(int argc, char **argv) { server_shutdown("all fans are bad for more than 12 cycles"); } } - +#endif /* * Fans can be hot swapped and replaced; in which case the fan daemon diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp index ebb390a..f6e5a45 100644 --- a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp +++ b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp @@ -100,7 +100,7 @@ int start_watchdog(const int auto_mode) { 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"); + syslog(LOG_WARNING, "system watchdog already started.\n"); return 0; } @@ -128,7 +128,7 @@ fail: } pthread_mutex_unlock(&watchdog_lock); - syslog(LOG_ALERT, "system watchdog failed to start!\n"); + syslog(LOG_WARNING, "system watchdog failed to start!\n"); return 0; } diff --git a/common/recipes-core/fruid/files/fruid-util.c b/common/recipes-core/fruid/files/fruid-util.c index 3c8d2e1..d0e19b8 100644 --- a/common/recipes-core/fruid/files/fruid-util.c +++ b/common/recipes-core/fruid/files/fruid-util.c @@ -18,11 +18,37 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <syslog.h> +#include <string.h> #include <openbmc/fruid.h> #include <openbmc/pal.h> +#define EEPROM_READ 0x1 +#define EEPROM_WRITE 0x2 +#define FRUID_SIZE 256 + +/* To copy the bin files */ +static int +copy_file(int out, int in, int bs) { + + ssize_t bytes_rd, bytes_wr; + uint64_t tmp[FRUID_SIZE]; + + while ((bytes_rd = read(in, tmp, FRUID_SIZE)) > 0) { + bytes_wr = write(out, tmp, bytes_rd); + if (bytes_wr != bytes_rd) { + return errno; + } + } + return 0; +} + /* Print the FRUID in detail */ -void print_fruid_info(fruid_info_t *fruid, const char *name) +static void +print_fruid_info(fruid_info_t *fruid, const char *name) { /* Print format */ printf("%-27s: %s", "\nFRU Information", @@ -78,18 +104,27 @@ void get_fruid_info(uint8_t fru, char *path, char* name) { static int print_usage() { - printf("Usage: fruid-util [ %s ]\n", pal_fru_list); + printf("Usage: fruid-util [ %s ]\n" + "Usage: fruid-util [%s] [--dump | --write ] <file>\n", + pal_fru_list, pal_fru_list); } /* Utility to just print the FRUID */ int main(int argc, char * argv[]) { int ret; + int rw = 0; + int fd_tmpbin; + int fd_newbin; + int fd_eeprom; uint8_t fru; + char *file_path = NULL; char path[64] = {0}; + char eeprom_path[64] = {0}; char name[64] = {0}; + char command[128] = {0}; - if (argc != 2) { + if (argc != 2 && argc != 4) { print_usage(); exit(-1); } @@ -100,8 +135,119 @@ int main(int argc, char * argv[]) { return ret; } - if (fru == 0) { + if (fru == 0 && argc > 2) { + print_usage(); + exit(-1); + } + + if (argc > 2) { + if (!strcmp(argv[2], "--dump")) { + rw = EEPROM_READ; + file_path = argv[3]; + } else if (!strcmp(argv[2], "--write")) { + rw = EEPROM_WRITE; + file_path = argv[3]; + } + } + + // Check if the new eeprom binary file exits. + // TODO: Add file size check before adding to the eeprom + if (rw == EEPROM_WRITE && (access(file_path, F_OK) == -1)) { + print_usage(); + exit(-1); + } + + if (fru != 0) { + ret = pal_get_fruid_path(fru, path); + if (ret < 0) { + return ret; + } + + errno = 0; + + /* FRUID BINARY DUMP */ + if (rw == EEPROM_READ) { + fd_tmpbin = open(path, O_RDONLY); + if (fd_tmpbin == -1) { + syslog(LOG_ERR, "Unable to open the %s file: %s", path, strerror(errno)); + return errno; + } + + fd_newbin = open(file_path, O_WRONLY | O_CREAT, 0644); + if (fd_newbin == -1) { + syslog(LOG_ERR, "Unable to create %s file: %s", file_path, strerror(errno)); + return errno; + } + + ret = copy_file(fd_newbin, fd_tmpbin, FRUID_SIZE); + if (ret < 0) { + syslog(LOG_ERR, "copy: write to %s file failed: %s", + file_path, strerror(errno)); + return ret; + } + + close(fd_newbin); + close(fd_tmpbin); + + } else if (rw == EEPROM_WRITE) { + + /* FRUID BINARY WRITE */ + + fd_tmpbin = open(path, O_WRONLY); + if (fd_tmpbin == -1) { + syslog(LOG_ERR, "Unable to open the %s file: %s", path, strerror(errno)); + return errno; + } + + fd_newbin = open(file_path, O_RDONLY); + if (fd_newbin == -1) { + syslog(LOG_ERR, "Unable to open the %s file: %s", file_path, strerror(errno)); + return errno; + } + + ret = pal_get_fruid_eeprom_path(fru, eeprom_path); + if (ret < 0) { + //Can not handle in common, so call pal libray for update + pal_fruid_write(fru, file_path); + } else { + if (access(eeprom_path, F_OK) == -1) { + syslog(LOG_ERR, "cannot access the eeprom file : %s for fru %d", + eeprom_path, fru); + close(fd_newbin); + close(fd_tmpbin); + return -1; + } + sprintf(command, "dd if=%s of=%s bs=%d count=1", file_path, eeprom_path, FRUID_SIZE); + system(command); + } + + ret = copy_file(fd_tmpbin, fd_newbin, FRUID_SIZE); + if (ret < 0) { + syslog(LOG_ERR, "copy: write to %s file failed: %s", + path, strerror(errno)); + return ret; + } + + close(fd_newbin); + close(fd_tmpbin); + + } else { + /* FRUID PRINT ONE FRU */ + + ret = pal_get_fruid_name(fru, name); + if (ret < 0) { + return ret; + } + + get_fruid_info(fru, path, name); + } + + } else if (fru == 0) { + + /* FRUID PRINT ALL FRUs */ + fru = 1; + while (fru <= MAX_NUM_FRUS) { ret = pal_get_fruid_path(fru, path); if (ret < 0) { @@ -113,32 +259,10 @@ int main(int argc, char * argv[]) { return ret; } - if (fru == FRU_NIC) { - printf("fruid-util does not support nic\n"); - exit(-1); - } - get_fruid_info(fru, path, name); fru++; } - } else { - ret = pal_get_fruid_path(fru, path); - if (ret < 0) { - return ret; - } - - ret = pal_get_fruid_name(fru, name); - if (ret < 0) { - return ret; - } - - if (fru == FRU_NIC) { - printf("fruid-util does not support nic\n"); - exit(-1); - } - - get_fruid_info(fru, path, name); } return 0; diff --git a/common/recipes-core/healthd/files/Makefile b/common/recipes-core/healthd/files/Makefile new file mode 100644 index 0000000..13c0f66 --- /dev/null +++ b/common/recipes-core/healthd/files/Makefile @@ -0,0 +1,26 @@ +# Copyright 2015-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 + +all: healthd + +healthd: healthd.c + $(CC) $(CFLAGS) -pthread -lm -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o healthd diff --git a/common/recipes-core/healthd/files/healthd.c b/common/recipes-core/healthd/files/healthd.c new file mode 100644 index 0000000..f02a363 --- /dev/null +++ b/common/recipes-core/healthd/files/healthd.c @@ -0,0 +1,77 @@ +/* + * healthd + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <syslog.h> +#include <errno.h> +#include <unistd.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/file.h> +#include <openbmc/pal.h> + +static void +initilize_all_kv() { + pal_set_def_key_value(); +} + +static void +check_all_daemon_health() { + while(1) { + + /* + * TODO: Check if all the daemons are running fine + * TODO: Move the HB led control to this daemon + * TODO: Move the watchdog timer to this daemon + */ + sleep(10); + } +} + +int +main(int argc, void **argv) { + int dev, rc, pid_file; + + if (argc > 1) { + exit(1); + } + + pid_file = open("/var/run/healthd.pid", O_CREAT | O_RDWR, 0666); + rc = flock(pid_file, LOCK_EX | LOCK_NB); + if(rc) { + if(EWOULDBLOCK == errno) { + printf("Another healthd instance is running...\n"); + exit(-1); + } + } else { + + daemon(0,1); + openlog("healthd", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, "healthd: daemon started"); + } + + initilize_all_kv(); + check_all_daemon_health(); + return 0; +} + diff --git a/common/recipes-core/healthd/files/setup-healthd.sh b/common/recipes-core/healthd/files/setup-healthd.sh new file mode 100644 index 0000000..b64be65 --- /dev/null +++ b/common/recipes-core/healthd/files/setup-healthd.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright 2015-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: setup-healthd +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Setup sensor monitoring +### END INIT INFO + +echo -n "Setup healthd for BMC " + +/usr/local/bin/healthd + +echo "done." diff --git a/common/recipes-core/healthd/healthd_0.1.bb b/common/recipes-core/healthd/healthd_0.1.bb new file mode 100644 index 0000000..0c4b2e9 --- /dev/null +++ b/common/recipes-core/healthd/healthd_0.1.bb @@ -0,0 +1,42 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Health Monitoring Daemon" +DESCRIPTION = "Daemon for BMC Health monitoring" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://healthd.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://healthd.c \ + file://setup-healthd.sh \ + " +S = "${WORKDIR}" + +LDFLAGS =+ " -lpal " + +DEPENDS =+ " libpal " + +binfiles = "healthd" + +pkgdir = "healthd" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 healthd ${dst}/healthd + ln -snf ../fbpackages/${pkgdir}/healthd ${bin}/healthd + + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-healthd.sh ${D}${sysconfdir}/init.d/setup-healthd.sh + update-rc.d -r ${D} setup-healthd.sh start 91 5 . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/healthd ${prefix}/local/bin ${sysconfdir} " + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb b/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb deleted file mode 100644 index 6743e3f..0000000 --- a/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb +++ /dev/null @@ -1,38 +0,0 @@ -DESCRIPTION = "i2c tools" -SECTION = "base" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" - -SRCREV = "6235" -SRC_URI = "svn://lm-sensors.org/svn/i2c-tools/branches/;protocol=http;module=i2c-tools-3.1 \ - " - -S = "${WORKDIR}/i2c-tools-3.1" - -i2ctools = "i2cdetect \ - i2cdump \ - i2cget \ - i2cset \ - " - -eepromtools = "eepromer \ - eeprom \ - eeprog \ - " - -do_compile() { - make -C eepromer - make -} - -do_install() { - mkdir -p ${D}/${bindir} - for f in ${i2ctools}; do - install -m 755 tools/$f ${D}/${bindir}/$f - done - for f in ${eepromtools}; do - install -m 755 eepromer/$f ${D}/${bindir}/$f - done -} - -FILES_${PN} = "${bindir}" diff --git a/common/recipes-core/init-ifupdown/files/dhcpv6_down b/common/recipes-core/init-ifupdown/files/dhcpv6_down new file mode 100644 index 0000000..a44deb4 --- /dev/null +++ b/common/recipes-core/init-ifupdown/files/dhcpv6_down @@ -0,0 +1,27 @@ +#!/bin/bash +# +# Copyright 2015-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 +# + +pid="/var/run/dhclient6.${IFACE}.pid" + +if [ -f "${pid}" ]; then + kill -9 `cat ${pid}` 2>/dev/null +fi + +exit 0 diff --git a/common/recipes-core/init-ifupdown/files/dhcpv6_up b/common/recipes-core/init-ifupdown/files/dhcpv6_up new file mode 100644 index 0000000..6469b9f --- /dev/null +++ b/common/recipes-core/init-ifupdown/files/dhcpv6_up @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright 2015-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 +# + +# only care about 'eth0' and 'oob' intf +[ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0 + +pid="/var/run/dhclient6.${IFACE}.pid" + +dhclient -6 -nw -pf ${pid} ${IFACE} + +exit 0 diff --git a/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend b/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend index 7d74521..e715c27 100644 --- a/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend +++ b/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend @@ -1,2 +1,18 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://dhcpv6_up \ + file://dhcpv6_down \ + " + +do_install_append() { + # rules to request dhcpv6 + install -d ${D}/${sysconfdir}/network/if-up.d + install -m 755 ${WORKDIR}/dhcpv6_up ${D}${sysconfdir}/network/if-up.d/dhcpv6_up + install -d ${D}/${sysconfdir}/network/if-down.d + install -m 755 ${WORKDIR}/dhcpv6_down ${D}${sysconfdir}/network/if-down.d/dhcpv6_down +} + +FILES_${PN} += "${sysconfdir}/network/if-up.d/dhcpv6_up \ + ${sysconfdir}/network/if-down.d/dhcpv6_down \ + " diff --git a/common/recipes-core/ipmbd/files/ipmbd.c b/common/recipes-core/ipmbd/files/ipmbd.c index 5ea5af3..ae40ec7 100644 --- a/common/recipes-core/ipmbd/files/ipmbd.c +++ b/common/recipes-core/ipmbd/files/ipmbd.c @@ -73,7 +73,7 @@ #define MQ_IPMB_REQ "/mq_ipmb_req" #define MQ_IPMB_RES "/mq_ipmb_res" #define MQ_MAX_MSG_SIZE MAX_BYTES -#define MQ_MAX_NUM_MSGS 10 +#define MQ_MAX_NUM_MSGS 20 #define SEQ_NUM_MAX 64 @@ -108,6 +108,8 @@ pthread_mutex_t m_seq; pthread_mutex_t m_i2c; +static int g_bus_id = 0; // store the i2c bus ID for debug print + #ifdef CONFIG_YOSEMITE // Returns the payload ID from IPMB bus routing // Slot#1: bus#3, Slot#2: bus#1, Slot#3: bus#7, Slot#4: bus#5 @@ -129,7 +131,7 @@ get_payload_id(uint8_t bus_id) { payload_id = 3; break; default: - syslog(LOG_ALERT, "get_payload_id: Wrong bus ID\n"); + syslog(LOG_WARNING, "get_payload_id: Wrong bus ID\n"); break; } @@ -138,9 +140,9 @@ get_payload_id(uint8_t bus_id) { #endif // Returns an unused seq# from all possible seq# -static uint8_t +static int8_t seq_get_new(void) { - uint8_t ret = -1; + int8_t ret = -1; uint8_t index; pthread_mutex_lock(&m_seq); @@ -183,13 +185,13 @@ i2c_open(uint8_t bus_num) { snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus_num); fd = open(fn, O_RDWR); if (fd == -1) { - syslog(LOG_ALERT, "Failed to open i2c device %s", fn); + syslog(LOG_WARNING, "Failed to open i2c device %s", fn); return -1; } rc = ioctl(fd, I2C_SLAVE, BRIDGE_SLAVE_ADDR); if (rc < 0) { - syslog(LOG_ALERT, "Failed to open slave @ address 0x%x", BRIDGE_SLAVE_ADDR); + syslog(LOG_WARNING, "Failed to open slave @ address 0x%x", BRIDGE_SLAVE_ADDR); close(fd); return -1; } @@ -227,7 +229,7 @@ i2c_write(int fd, uint8_t *buf, uint8_t len) { } if (rc < 0) { - syslog(LOG_ALERT, "Failed to do raw io"); + syslog(LOG_WARNING, "Failed to do raw io"); pthread_mutex_unlock(&m_i2c); return -1; } @@ -249,7 +251,7 @@ i2c_slave_open(uint8_t bus_num) { snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus_num); fd = open(fn, O_RDWR); if (fd == -1) { - syslog(LOG_ALERT, "Failed to open i2c device %s", fn); + syslog(LOG_WARNING, "Failed to open i2c device %s", fn); return -1; } @@ -266,7 +268,7 @@ i2c_slave_open(uint8_t bus_num) { rc = ioctl(fd, I2C_SLAVE_RDWR, &data); if (rc < 0) { - syslog(LOG_ALERT, "Failed to open slave @ address 0x%x", BMC_SLAVE_ADDR); + syslog(LOG_WARNING, "Failed to open slave @ address 0x%x", BMC_SLAVE_ADDR); close(fd); } @@ -341,22 +343,22 @@ ipmb_req_handler(void *bus_num) { // Open the i2c bus for sending response fd = i2c_open(*bnum); if (fd < 0) { - syslog(LOG_ALERT, "i2c_open failure\n"); + syslog(LOG_WARNING, "i2c_open failure\n"); close(mq); return NULL; } // Loop to process incoming requests while (1) { - if ((rlen = mq_receive(mq, rxbuf, MQ_MAX_MSG_SIZE, NULL)) < 0) { + if ((rlen = mq_receive(mq, rxbuf, MQ_MAX_MSG_SIZE, NULL)) <= 0) { sleep(1); continue; } #ifdef DEBUG - syslog(LOG_ALERT, "Received Request of %d bytes\n", rlen); + syslog(LOG_WARNING, "Received Request of %d bytes\n", rlen); for (i = 0; i < rlen; i++) { - syslog(LOG_ALERT, "0x%X", rxbuf[i]); + syslog(LOG_WARNING, "0x%X", rxbuf[i]); } #endif @@ -407,9 +409,9 @@ ipmb_req_handler(void *bus_num) { p_ipmb_res->data[tlen-IPMI_RESP_HDR_SIZE]; #ifdef DEBUG - syslog(LOG_ALERT, "Sending Response of %d bytes\n", tlen+IPMB_HDR_SIZE-1); + syslog(LOG_WARNING, "Sending Response of %d bytes\n", tlen+IPMB_HDR_SIZE-1); for (i = 1; i < tlen+IPMB_HDR_SIZE; i++) { - syslog(LOG_ALERT, "0x%X:", txbuf[i]); + syslog(LOG_WARNING, "0x%X:", txbuf[i]); } #endif @@ -428,45 +430,65 @@ ipmb_res_handler(void *bus_num) { ipmb_res_t *p_res; uint8_t index; char mq_ipmb_res[64] = {0}; + uint8_t hack = 0; sprintf(mq_ipmb_res, "%s_%d", MQ_IPMB_RES, *bnum); // Open the message queue mq = mq_open(mq_ipmb_res, O_RDONLY); if (mq == (mqd_t) -1) { - syslog(LOG_ALERT, "mq_open fails\n"); + syslog(LOG_WARNING, "mq_open fails\n"); return NULL; } // Loop to wait for incomng response messages while (1) { - if ((len = mq_receive(mq, buf, MQ_MAX_MSG_SIZE, NULL)) < 0) { + if ((len = mq_receive(mq, buf, MQ_MAX_MSG_SIZE, NULL)) <= 0) { sleep(1); continue; } p_res = (ipmb_res_t *) buf; + // Check the seq# of response index = p_res->seq_lun >> LUN_OFFSET; + // TODO: observed the IPMB packets with missing slave address at first byte; + // detect and correct them for now, but need fix in i2c driver + hack = 0; + if ((p_res->res_slave_addr != (BRIDGE_SLAVE_ADDR << 1)) || + (p_res->res_slave_addr == p_res->hdr_cksum)) { + index = p_res->res_slave_addr >> LUN_OFFSET; + hack = 1; + } // Check if the response is being waited for pthread_mutex_lock(&m_seq); if (g_seq.seq[index].in_use) { // Copy the response to the requester's buffer - memcpy(g_seq.seq[index].p_buf, buf, len); - g_seq.seq[index].len = len; + if (hack) { + // TODO: hack to correct the packet with missing slave address for now + *(g_seq.seq[index].p_buf) = (BMC_SLAVE_ADDR << 1); + memcpy(g_seq.seq[index].p_buf+1, buf, len); + g_seq.seq[index].len = len+1; + } else { + memcpy(g_seq.seq[index].p_buf, buf, len); + g_seq.seq[index].len = len; + } // Wake up the worker thread to receive the response sem_post(&g_seq.seq[index].s_seq); + } else { + // Either the IPMB packet is corrupted or arrived late after client exits + syslog(LOG_WARNING, "bus: %d, WRONG packet received with seq#%d\n", g_bus_id, index); } pthread_mutex_unlock(&m_seq); #ifdef DEBUG - syslog(LOG_ALERT, "Received Response of %d bytes\n", len); + syslog(LOG_WARNING, "Received Response of %d bytes\n", len); int i; for (i = 0; i < len; i++) { - syslog(LOG_ALERT, "0x%X:", buf[i]); + syslog(LOG_WARNING, "0x%X:", buf[i]); } #endif } @@ -494,7 +516,7 @@ ipmb_rx_handler(void *bus_num) { // Open the i2c bus as a slave fd = i2c_slave_open(*bnum); if (fd < 0) { - syslog(LOG_ALERT, "i2c_slave_open fails\n"); + syslog(LOG_WARNING, "i2c_slave_open fails\n"); goto cleanup; } @@ -504,13 +526,13 @@ ipmb_rx_handler(void *bus_num) { // Open the message queues for post processing mq_req = mq_open(mq_ipmb_req, O_WRONLY); if (mq_req == (mqd_t) -1) { - syslog(LOG_ALERT, "mq_open req fails\n"); + syslog(LOG_WARNING, "mq_open req fails\n"); goto cleanup; } mq_res = mq_open(mq_ipmb_res, O_WRONLY); if (mq_res == (mqd_t) -1) { - syslog(LOG_ALERT, "mq_open res fails\n"); + syslog(LOG_WARNING, "mq_open res fails\n"); goto cleanup; } @@ -532,9 +554,9 @@ ipmb_rx_handler(void *bus_num) { tmq = mq_req; } // Post message to approriate Queue for further processing - if (mq_send(tmq, buf, len, 0)) { - syslog(LOG_ALERT, "mq_send failed\n"); - sleep(1); + if (mq_timedsend(tmq, buf, len, 0, &req)) { + //syslog(LOG_WARNING, "mq_send failed for queue %d\n", tmq); + nanosleep(&req, &rem); continue; } } @@ -563,7 +585,7 @@ ipmb_handle (int fd, unsigned char *request, unsigned char req_len, ipmb_req_t *req = (ipmb_req_t *) request; ipmb_res_t *res = (ipmb_res_t *) response; - uint8_t index; + int8_t index; struct timespec ts; // Allocate right sequence Number @@ -598,12 +620,12 @@ ipmb_handle (int fd, unsigned char *request, unsigned char req_len, // Wait on semaphore for that sequence Number clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += TIMEOUT_IPMI; + ts.tv_sec += TIMEOUT_IPMB; int ret; ret = sem_timedwait(&g_seq.seq[index].s_seq, &ts); if (ret == -1) { - syslog(LOG_ALERT, "No response for sequence number: %d\n", index); + syslog(LOG_DEBUG, "No response for sequence number: %d\n", index); *res_len = 0; } @@ -628,17 +650,26 @@ void unsigned char req_buf[MAX_IPMI_MSG_SIZE]; unsigned char res_buf[MAX_IPMI_MSG_SIZE]; unsigned char res_len = 0; + struct timeval tv; + + // setup timeout for receving on socket + tv.tv_sec = TIMEOUT_IPMB; + tv.tv_usec = 0; + + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); n = recv(sock, req_buf, sizeof(req_buf), 0); if (n <= 0) { - syslog(LOG_ALERT, "ipmbd: recv() failed with %d\n", n); + syslog(LOG_WARNING, "ipmbd: recv() failed with %d\n", n); goto conn_cleanup; } ipmb_handle(fd, req_buf, n, res_buf, &res_len); if (send(sock, res_buf, res_len, MSG_NOSIGNAL) < 0) { - syslog(LOG_ALERT, "ipmbd: send() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "ipmbd: send() failed\n"); +#endif } conn_cleanup: @@ -659,11 +690,12 @@ ipmb_lib_handler(void *bus_num) { int fd; uint8_t *bnum = (uint8_t*) bus_num; char sock_path[20] = {0}; + int rc = 0; // Open the i2c bus for sending request fd = i2c_open(*bnum); if (fd < 0) { - syslog(LOG_ALERT, "i2c_open failure\n"); + syslog(LOG_WARNING, "i2c_open failure\n"); return NULL; } @@ -680,7 +712,7 @@ ipmb_lib_handler(void *bus_num) { if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { - syslog(LOG_ALERT, "ipmbd: socket() failed\n"); + syslog(LOG_WARNING, "ipmbd: socket() failed\n"); exit (1); } @@ -692,22 +724,25 @@ ipmb_lib_handler(void *bus_num) { len = strlen (local.sun_path) + sizeof (local.sun_family); if (bind (s, (struct sockaddr *) &local, len) == -1) { - syslog(LOG_ALERT, "ipmbd: bind() failed\n"); + syslog(LOG_WARNING, "ipmbd: bind() failed\n"); exit (1); } if (listen (s, 5) == -1) { - syslog(LOG_ALERT, "ipmbd: listen() failed\n"); + syslog(LOG_WARNING, "ipmbd: listen() failed\n"); exit (1); } while(1) { int n; t = sizeof (remote); + // TODO: Seen accept() call failure and need further debug if ((s2 = accept (s, (struct sockaddr *) &remote, &t)) < 0) { - syslog(LOG_ALERT, "ipmbd: accept() failed\n"); - break; + rc = errno; + syslog(LOG_WARNING, "ipmbd: accept() failed with ret: %x, errno: %x\n", s2, rc); + sleep(5); + continue; } // Creating a worker thread to handle the request @@ -718,7 +753,7 @@ ipmb_lib_handler(void *bus_num) { sfd->fd = fd; sfd->sock = s2; if (pthread_create(&tid, NULL, conn_handler, (void*) sfd) < 0) { - syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + syslog(LOG_WARNING, "ipmbd: pthread_create failed\n"); close(s2); continue; } @@ -743,17 +778,20 @@ main(int argc, char * const argv[]) { struct mq_attr attr; char mq_ipmb_req[64] = {0}; char mq_ipmb_res[64] = {0}; + int rc = 0; daemon(1, 0); openlog("ipmbd", LOG_CONS, LOG_DAEMON); if (argc != 2) { - syslog(LOG_ALERT, "ipmbd: Usage: ipmbd <bus#>"); + syslog(LOG_WARNING, "ipmbd: Usage: ipmbd <bus#>"); exit(1); } ipmb_bus_num = atoi(argv[1]); -syslog(LOG_ALERT, "ipmbd: bus#:%d\n", ipmb_bus_num); + g_bus_id = ipmb_bus_num; + + syslog(LOG_WARNING, "ipmbd: bus#:%d\n", ipmb_bus_num); pthread_mutex_init(&m_i2c, NULL); @@ -769,44 +807,44 @@ syslog(LOG_ALERT, "ipmbd: bus#:%d\n", ipmb_bus_num); // Remove the MQ if exists mq_unlink(mq_ipmb_req); - errno = 0; mqd_req = mq_open(mq_ipmb_req, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &attr); if (mqd_req == (mqd_t) -1) { - syslog(LOG_ALERT, "ipmbd: mq_open request failed errno:%d\n", errno); + rc = errno; + syslog(LOG_WARNING, "ipmbd: mq_open request failed errno:%d\n", rc); goto cleanup; } // Remove the MQ if exists mq_unlink(mq_ipmb_res); - errno = 0; mqd_res = mq_open(mq_ipmb_res, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &attr); if (mqd_res == (mqd_t) -1) { - syslog(LOG_ALERT, "ipmbd: mq_open response failed errno: %d\n", errno); + rc = errno; + syslog(LOG_WARNING, "ipmbd: mq_open response failed errno: %d\n", rc); goto cleanup; } // Create thread to handle IPMB Requests if (pthread_create(&tid_req_handler, NULL, ipmb_req_handler, (void*) &ipmb_bus_num) < 0) { - syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + syslog(LOG_WARNING, "ipmbd: pthread_create failed\n"); goto cleanup; } // Create thread to handle IPMB Responses if (pthread_create(&tid_res_handler, NULL, ipmb_res_handler, (void*) &ipmb_bus_num) < 0) { - syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + syslog(LOG_WARNING, "ipmbd: pthread_create failed\n"); goto cleanup; } // Create thread to retrieve ipmb traffic from i2c bus as slave if (pthread_create(&tid_ipmb_rx, NULL, ipmb_rx_handler, (void*) &ipmb_bus_num) < 0) { - syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + syslog(LOG_WARNING, "ipmbd: pthread_create failed\n"); goto cleanup; } // Create thread to receive ipmb library requests from apps if (pthread_create(&tid_lib_handler, NULL, ipmb_lib_handler, (void*) &ipmb_bus_num) < 0) { - syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + syslog(LOG_WARNING, "ipmbd: pthread_create failed\n"); goto cleanup; } diff --git a/common/recipes-core/ipmid/files/ipmid.c b/common/recipes-core/ipmid/files/ipmid.c index c79d3e2..0930cc2 100644 --- a/common/recipes-core/ipmid/files/ipmid.c +++ b/common/recipes-core/ipmid/files/ipmid.c @@ -35,6 +35,11 @@ #include <sys/un.h> #include <openbmc/ipmi.h> +#define SIZE_IANA_ID 3 +#define SIZE_SYS_GUID 16 + +extern void plat_lan_init(lan_config_t *lan); + // TODO: Once data storage is finalized, the following structure needs // to be retrieved/updated from persistant backend storage static lan_config_t g_lan_config = { 0 }; @@ -245,6 +250,27 @@ app_get_device_guid (unsigned char *response, unsigned char *res_len) *res_len = data - &res->data[0]; } +// Get Device System GUID (IPMI/Section 22.14) +static void +app_get_device_sys_guid (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + int ret; + + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + // Get the 16 bytes of System GUID from PAL library + ret = pal_get_sys_guid(req->payload_id, res->data); + if (ret) { + res->cc = CC_UNSPECIFIED_ERROR; + *res_len = 0x00; + } else { + res->cc = CC_SUCCESS; + *res_len = SIZE_SYS_GUID; + } +} + // Get BMC Global Enables (IPMI/Section 22.2) static void app_get_global_enables (unsigned char *response, unsigned char *res_len) @@ -255,7 +281,7 @@ app_get_global_enables (unsigned char *response, unsigned char *res_len) res->cc = CC_SUCCESS; - *data++ = 0x09; // Global Enable + *data++ = 0x0D; // Global Enable *res_len = data - &res->data[0]; } @@ -279,6 +305,7 @@ app_set_sys_info_params (unsigned char *request, unsigned char *response, break; case SYS_INFO_PARAM_SYSFW_VER: memcpy(g_sys_info_params.sysfw_ver, &req->data[1], SIZE_SYSFW_VER); + pal_set_sysfw_ver(req->payload_id, g_sys_info_params.sysfw_ver); break; case SYS_INFO_PARAM_SYS_NAME: memcpy(g_sys_info_params.sys_name, &req->data[1], SIZE_SYS_NAME); @@ -327,6 +354,7 @@ app_get_sys_info_params (unsigned char *request, unsigned char *response, *data++ = g_sys_info_params.set_in_prog; break; case SYS_INFO_PARAM_SYSFW_VER: + pal_get_sysfw_ver(req->payload_id, g_sys_info_params.sysfw_ver); memcpy(data, g_sys_info_params.sysfw_ver, SIZE_SYSFW_VER); data += SIZE_SYSFW_VER; break; @@ -385,12 +413,11 @@ ipmi_handle_app (unsigned char *request, unsigned char req_len, app_get_selftest_results (response, res_len); break; case CMD_APP_GET_DEVICE_GUID: - case CMD_APP_GET_SYSTEM_GUID: - // Get Device GUID and Get System GUID returns same data - // from IPMI stack. FYI, Get System GUID will have to be - // sent with in an IPMI session that includes session info app_get_device_guid (response, res_len); break; + case CMD_APP_GET_SYSTEM_GUID: + app_get_device_sys_guid (request, response, res_len); + break; case CMD_APP_GET_GLOBAL_ENABLES: app_get_global_enables (response, res_len); break; @@ -558,8 +585,10 @@ storage_get_sdr (unsigned char *request, unsigned char *response, } static void -storage_get_sel_info (unsigned char *response, unsigned char *res_len) +storage_get_sel_info (unsigned char *request, unsigned char *response, + unsigned char *res_len) { + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; ipmi_res_t *res = (ipmi_res_t *) response; unsigned char *data = &res->data[0]; int num_entries; // number of log entries @@ -568,10 +597,10 @@ storage_get_sel_info (unsigned char *response, unsigned char *res_len) time_stamp_t ts_recent_erase; // Recent Erasure Timestamp // Use platform APIs to get SEL information - num_entries = sel_num_entries (); - free_space = sel_free_space (); - sel_ts_recent_add (&ts_recent_add); - sel_ts_recent_erase (&ts_recent_erase); + num_entries = sel_num_entries (req->payload_id); + free_space = sel_free_space (req->payload_id); + sel_ts_recent_add (req->payload_id, &ts_recent_add); + sel_ts_recent_erase (req->payload_id, &ts_recent_erase); res->cc = CC_SUCCESS; @@ -595,14 +624,16 @@ storage_get_sel_info (unsigned char *response, unsigned char *res_len) } static void -storage_rsv_sel (unsigned char *response, unsigned char *res_len) +storage_rsv_sel (unsigned char * request, unsigned char *response, + unsigned char *res_len) { + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; ipmi_res_t *res = (ipmi_res_t *) response; unsigned char *data = &res->data[0]; int rsv_id; // SEL reservation ID // Use platform APIs to get a SEL reservation ID - rsv_id = sel_rsv_id (); + rsv_id = sel_rsv_id (req->payload_id); if (rsv_id < 0) { res->cc = CC_SEL_ERASE_PROG; @@ -634,7 +665,7 @@ storage_get_sel (unsigned char *request, unsigned char *response, read_rec_id = (req->data[3] >> 8) | req->data[2]; // Use platform API to read the record Id and get next ID - ret = sel_get_entry (read_rec_id, &entry, &next_rec_id); + ret = sel_get_entry (req->payload_id, read_rec_id, &entry, &next_rec_id); if (ret) { res->cc = CC_UNSPECIFIED_ERROR; @@ -670,7 +701,7 @@ storage_add_sel (unsigned char *request, unsigned char *response, memcpy(entry.msg, req->data, SIZE_SEL_REC); // Use platform APIs to add the new SEL entry - ret = sel_add_entry (&entry, &record_id); + ret = sel_add_entry (req->payload_id, &entry, &record_id); if (ret) { res->cc = CC_UNSPECIFIED_ERROR; @@ -711,11 +742,11 @@ storage_clr_sel (unsigned char *request, unsigned char *response, // Use platform APIs to clear or get status if (req->data[5] == IPMI_SEL_INIT_ERASE) { - ret = sel_erase (rsv_id); + ret = sel_erase (req->payload_id, rsv_id); } else if (req->data[5] == IPMI_SEL_ERASE_STAT) { - ret = sel_erase_status (rsv_id, &status); + ret = sel_erase_status (req->payload_id, rsv_id, &status); } else { @@ -739,6 +770,37 @@ storage_clr_sel (unsigned char *request, unsigned char *response, } static void +storage_get_sel_time (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + + res->cc = CC_SUCCESS; + + time_stamp_fill(res->data); + + *res_len = SIZE_TIME_STAMP; + + return; +} + +static void +storage_get_sel_utc (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = CC_SUCCESS; + + // TODO: For now, the SEL time stamp is based on UTC time, + // so return 0x0000 as offset. Might need to change once + // supporting zones in SEL time stamps + *data++ = 0x00; + *data++ = 0x00; + + *res_len = data - &res->data[0]; +} + +static void ipmi_handle_storage (unsigned char *request, unsigned char req_len, unsigned char *response, unsigned char *res_len) { @@ -759,10 +821,10 @@ ipmi_handle_storage (unsigned char *request, unsigned char req_len, storage_get_fruid_data (request, response, res_len); break; case CMD_STORAGE_GET_SEL_INFO: - storage_get_sel_info (response, res_len); + storage_get_sel_info (request, response, res_len); break; case CMD_STORAGE_RSV_SEL: - storage_rsv_sel (response, res_len); + storage_rsv_sel (request, response, res_len); break; case CMD_STORAGE_ADD_SEL: storage_add_sel (request, response, res_len); @@ -773,6 +835,12 @@ ipmi_handle_storage (unsigned char *request, unsigned char req_len, case CMD_STORAGE_CLR_SEL: storage_clr_sel (request, response, res_len); break; + case CMD_STORAGE_GET_SEL_TIME: + storage_get_sel_time (response, res_len); + break; + case CMD_STORAGE_GET_SEL_UTC: + storage_get_sel_utc (response, res_len); + break; case CMD_STORAGE_GET_SDR_INFO: storage_get_sdr_info (response, res_len); break; @@ -871,6 +939,9 @@ transport_set_lan_config (unsigned char *request, unsigned char *response, case LAN_PARAM_DEST_ADDR: memcpy(g_lan_config.dest_addr, &req->data[2], SIZE_DEST_ADDR); break; + case LAN_PARAM_IP6_ADDR: + memcpy(g_lan_config.ip6_addr, &req->data[2], SIZE_IP6_ADDR); + break; default: res->cc = CC_INVALID_PARAM; break; @@ -905,6 +976,7 @@ transport_get_lan_config (unsigned char *request, unsigned char *response, data += SIZE_AUTH_ENABLES; break; case LAN_PARAM_IP_ADDR: + plat_lan_init(&g_lan_config); memcpy(data, g_lan_config.ip_addr, SIZE_IP_ADDR); data += SIZE_IP_ADDR; break; @@ -968,6 +1040,11 @@ transport_get_lan_config (unsigned char *request, unsigned char *response, memcpy(data, g_lan_config.dest_addr, SIZE_DEST_ADDR); data += SIZE_DEST_ADDR; break; + case LAN_PARAM_IP6_ADDR: + plat_lan_init(&g_lan_config); + memcpy(data, g_lan_config.ip6_addr, SIZE_IP6_ADDR); + data += SIZE_IP6_ADDR; + break; default: res->cc = CC_INVALID_PARAM; break; @@ -1070,6 +1147,42 @@ oem_set_post_end (unsigned char *request, unsigned char *response, } static void +oem_get_slot_info(unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + int ret; + uint8_t pres = 0x00; + uint8_t sinfo = 0x00; + + // Slot info: + // Bit[7]: Not Present/Present (from pal) + // Bit[6]: Platform type (TODO from pal) + // Bit[5-0] : Slot# (payload_id indicates) + ret = pal_is_server_prsnt(req->payload_id, &pres); + if (ret) { + res->cc = CC_UNSPECIFIED_ERROR; + *res_len = 0x00; + return; + } + + // Populate the presence bit[7] + if (pres) { + sinfo = 0x80; + } + + // Populate the slot number + sinfo |= req->payload_id; + + // Prepare response buffer + res->cc = CC_SUCCESS; + res->data[0] = sinfo; + *res_len = 0x01; +} + +static void ipmi_handle_oem (unsigned char *request, unsigned char req_len, unsigned char *response, unsigned char *res_len) { @@ -1093,6 +1206,9 @@ ipmi_handle_oem (unsigned char *request, unsigned char req_len, case CMD_OEM_SET_POST_END: oem_set_post_end (request, response, res_len); break; + case CMD_OEM_GET_SLOT_INFO: + oem_get_slot_info (request, response, res_len); + break; default: res->cc = CC_INVALID_CMD; break; @@ -1114,21 +1230,22 @@ oem_1s_handle_ipmb_kcs(unsigned char *request, unsigned char req_len, // Add the payload id from the bridged command req_buf[0] = req->payload_id; - // Remove OEM IPMI Header + 1 byte for BIC interface + // Remove OEM IPMI Header (including 1 byte for interface type, 3 bytes for IANA ID) // The offset moves by one due to the payload ID - memcpy(&req_buf[1], &request[BIC_INTF_HDR_SIZE + 1], req_len - BIC_INTF_HDR_SIZE); + memcpy(&req_buf[1], &request[BIC_INTF_HDR_SIZE], req_len - BIC_INTF_HDR_SIZE + 1); // Send the bridged KCS command along with the payload ID // The offset moves by one due to the payload ID ipmi_handle(req_buf, req_len - BIC_INTF_HDR_SIZE + 1, res_buf, res_len); - // Copy the response back - memcpy(&res->data[1], res_buf, *res_len); + // Copy the response back (1 byte interface type, 3 bytes for IANA ID) + memcpy(&res->data[4], res_buf, *res_len); // Add the OEM command's response res->cc = CC_SUCCESS; - res->data[0] = req->data[0]; // Bridge-IC interface - *res_len += 1; + memcpy(res->data, &req->data, SIZE_IANA_ID); // IANA ID + res->data[3] = req->data[3]; // Bridge-IC interface + *res_len += 4; // Interface type + IANA ID } static void @@ -1139,32 +1256,38 @@ oem_1s_handle_ipmb_req(unsigned char *request, unsigned char req_len, ipmi_res_t *res = (ipmi_res_t *) response; // handle based on Bridge-IC interface - switch(req->data[0]) { + switch(req->data[3]) { case BIC_INTF_ME: // TODO: Need to call ME command handler +#ifdef DEBUG syslog(LOG_INFO, "oem_1s_handle_ipmb_req: Command received from ME for " "payload#%d\n", req->payload_id); - res->data[0] = BIC_INTF_ME; +#endif + memcpy(res->data, req->data, 4); //IANA ID + Interface type res->cc = CC_SUCCESS; - *res_len = 1; + *res_len = 4; break; case BIC_INTF_SOL: // TODO: Need to call Optional SoL message handler +#ifdef DEBUG syslog(LOG_INFO, "oem_1s_handle_ipmb_req: Command received from SOL for " "payload#%d\n", req->payload_id); - res->data[0] = BIC_INTF_SOL; +#endif + memcpy(res->data, req->data, 4); //IANA ID + Interface type res->cc = CC_SUCCESS; - *res_len = 1; + *res_len = 4; break; case BIC_INTF_KCS: + case BIC_INTF_KCS_SMM: oem_1s_handle_ipmb_kcs(request, req_len, response, res_len); break; default: // TODO: Need to add additonal interface handler, if supported - syslog(LOG_ALERT, "oem_1s_handle_ipmb_req: Command received on intf#%d " - "for payload#%d", req->data[0], req->payload_id); + syslog(LOG_WARNING, "oem_1s_handle_ipmb_req: Command received on intf#%d " + "for payload#%d", req->data[3], req->payload_id); + memcpy(res->data, req->data, 4); //IANA ID + Interface type res->cc = CC_INVALID_PARAM; - *res_len = 0; + *res_len = 4; break; } } @@ -1187,62 +1310,70 @@ ipmi_handle_oem_1s(unsigned char *request, unsigned char req_len, break; case CMD_OEM_1S_INTR: syslog(LOG_INFO, "ipmi_handle_oem_1s: 1S server interrupt#%d received " - "for payload#%d\n", req->data[0], req->payload_id); + "for payload#%d\n", req->data[3], req->payload_id); res->cc = CC_SUCCESS; - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; case CMD_OEM_1S_POST_BUF: - for (i = 1; i <= req->data[0]; i++) { + // Skip the first 3 bytes of IANA ID and one byte of length field + for (i = SIZE_IANA_ID+1; i <= req->data[3]; i++) { pal_post_handle(req->payload_id, req->data[i]); } res->cc = CC_SUCCESS; - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; case CMD_OEM_1S_PLAT_DISC: syslog(LOG_INFO, "ipmi_handle_oem_1s: Platform Discovery received for " "payload#%d\n", req->payload_id); res->cc = CC_SUCCESS; - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; case CMD_OEM_1S_BIC_RESET: syslog(LOG_INFO, "ipmi_handle_oem_1s: BIC Reset received " "for payload#%d\n", req->payload_id); - if (req->data[0] == 0x0) { - syslog(LOG_ALERT, "Cold Reset by Firmware Update\n"); + if (req->data[3] == 0x0) { + syslog(LOG_WARNING, "Cold Reset by Firmware Update\n"); res->cc = CC_SUCCESS; - } else if (req->data[1] == 0x01) { - syslog(LOG_ALERT, "WDT Reset\n"); + } else if (req->data[3] == 0x01) { + syslog(LOG_WARNING, "WDT Reset\n"); res->cc = CC_SUCCESS; } else { - syslog(LOG_ALERT, "Error\n"); + syslog(LOG_WARNING, "Error\n"); res->cc = CC_INVALID_PARAM; } - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; case CMD_OEM_1S_BIC_UPDATE_MODE: +#ifdef DEBUG syslog(LOG_INFO, "ipmi_handle_oem_1s: BIC Update Mode received " "for payload#%d\n", req->payload_id); - - if (req->data[0] == 0x0) { +#endif + if (req->data[3] == 0x0) { syslog(LOG_INFO, "Normal Mode\n"); res->cc = CC_SUCCESS; - } else if (req->data[1] == 0x0F) { + } else if (req->data[3] == 0x0F) { syslog(LOG_INFO, "Update Mode\n"); res->cc = CC_SUCCESS; } else { - syslog(LOG_ALERT, "Error\n"); + syslog(LOG_WARNING, "Error\n"); res->cc = CC_INVALID_PARAM; } - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; default: res->cc = CC_INVALID_CMD; - *res_len = 0; + memcpy(res->data, req->data, SIZE_IANA_ID); //IANA ID + *res_len = 3; break; } pthread_mutex_unlock(&m_oem_1s); @@ -1306,26 +1437,37 @@ ipmi_handle (unsigned char *request, unsigned char req_len, void *conn_handler(void *socket_desc) { - int sock = *(int*)socket_desc; + int *p_sock = (int*)socket_desc; + int sock = *p_sock; int n; unsigned char req_buf[MAX_IPMI_MSG_SIZE]; unsigned char res_buf[MAX_IPMI_MSG_SIZE]; unsigned char res_len = 0; + struct timeval tv; + int rc = 0; + + // setup timeout for receving on socket + tv.tv_sec = TIMEOUT_IPMI; + tv.tv_usec = 0; + + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); n = recv (sock, req_buf, sizeof(req_buf), 0); + rc = errno; if (n <= 0) { - syslog(LOG_ALERT, "ipmid: recv() failed with %d\n", n); + syslog(LOG_WARNING, "ipmid: recv() failed with %d, errno: %d\n", n, rc); goto conn_cleanup; } ipmi_handle(req_buf, n, res_buf, &res_len); if (send (sock, res_buf, res_len, 0) < 0) { - syslog(LOG_ALERT, "ipmid: send() failed\n"); + syslog(LOG_WARNING, "ipmid: send() failed\n"); } conn_cleanup: close(sock); + free(p_sock); pthread_exit(NULL); return 0; @@ -1338,13 +1480,16 @@ main (void) int s, s2, t, len; struct sockaddr_un local, remote; pthread_t tid; + int *p_s2; + int rc = 0; - daemon(1, 0); + daemon(1, 1); openlog("ipmid", LOG_CONS, LOG_DAEMON); plat_fruid_init(); plat_sensor_init(); + plat_lan_init(&g_lan_config); sdr_init(); sel_init(); @@ -1358,7 +1503,7 @@ main (void) if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) { - syslog(LOG_ALERT, "ipmid: socket() failed\n"); + syslog(LOG_WARNING, "ipmid: socket() failed\n"); exit (1); } @@ -1368,30 +1513,35 @@ main (void) len = strlen (local.sun_path) + sizeof (local.sun_family); if (bind (s, (struct sockaddr *) &local, len) == -1) { - syslog(LOG_ALERT, "ipmid: bind() failed\n"); + syslog(LOG_WARNING, "ipmid: bind() failed\n"); exit (1); } if (listen (s, 5) == -1) { - syslog(LOG_ALERT, "ipmid: listen() failed\n"); + syslog(LOG_WARNING, "ipmid: listen() failed\n"); exit (1); } while(1) { int n; t = sizeof (remote); + // TODO: seen accept() call fails and need further debug if ((s2 = accept (s, (struct sockaddr *) &remote, &t)) < 0) { - syslog(LOG_ALERT, "ipmid: accept() failed\n"); - break; + rc = errno; + syslog(LOG_WARNING, "ipmid: accept() failed with ret: %x, errno: %x\n", s2, rc); + sleep(5); + continue; } // Creating a worker thread to handle the request // TODO: Need to monitor the server performance with higher load and // see if we need to create pre-defined number of workers and schedule // the requests among them. - if (pthread_create(&tid, NULL, conn_handler, (void*) &s2) < 0) { - syslog(LOG_ALERT, "ipmid: pthread_create failed\n"); + p_s2 = malloc(sizeof(int)); + *p_s2 = s2; + if (pthread_create(&tid, NULL, conn_handler, (void*) p_s2) < 0) { + syslog(LOG_WARNING, "ipmid: pthread_create failed\n"); close(s2); continue; } diff --git a/common/recipes-core/ipmid/files/sdr.c b/common/recipes-core/ipmid/files/sdr.c index 91a4df5..78d74c3 100644 --- a/common/recipes-core/ipmid/files/sdr.c +++ b/common/recipes-core/ipmid/files/sdr.c @@ -88,7 +88,7 @@ static int sdr_add_entry(sdr_rec_t *rec, int *rec_id) { // If SDR is full, return error if (sdr_num_entries() == SDR_RECORDS_MAX) { - syslog(LOG_ALERT, "sdr_add_entry: SDR full\n"); + syslog(LOG_WARNING, "sdr_add_entry: SDR full\n"); return -1; } @@ -137,7 +137,7 @@ sdr_add_mgmt_rec(sensor_mgmt_t *p_rec) { // Add this record to SDR repo if (sdr_add_entry(&sdr, &rec_id)) { - syslog(LOG_ALERT, "sdr_add_mgmt_rec: sdr_add_entry failed\n"); + syslog(LOG_WARNING, "sdr_add_mgmt_rec: sdr_add_entry failed\n"); return -1; } @@ -176,7 +176,7 @@ sdr_add_disc_rec(sensor_disc_t *p_rec) { // Add this record to SDR repo if (sdr_add_entry(&sdr, &rec_id)) { - syslog(LOG_ALERT, "sdr_add_disc_rec: sdr_add_entry failed\n"); + syslog(LOG_WARNING, "sdr_add_disc_rec: sdr_add_entry failed\n"); return -1; } @@ -237,7 +237,7 @@ sdr_add_thresh_rec(sensor_thresh_t *p_rec) { // Add this record to SDR repo if (sdr_add_entry(&sdr, &rec_id)) { - syslog(LOG_ALERT, "sdr_add_thresh_rec: sdr_add_entry failed\n"); + syslog(LOG_WARNING, "sdr_add_thresh_rec: sdr_add_entry failed\n"); return -1; } @@ -263,7 +263,7 @@ sdr_add_oem_rec(sensor_oem_t *p_rec) { // Add this record to SDR repo if (sdr_add_entry(&sdr, &rec_id)) { - syslog(LOG_ALERT, "sdr_add_oem_rec: sdr_add_entry failed\n"); + syslog(LOG_WARNING, "sdr_add_oem_rec: sdr_add_entry failed\n"); return -1; } @@ -323,7 +323,7 @@ sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, // Make sure the rsv_id matches if (rsv_id != g_rsv_id) { - syslog(LOG_ALERT, "sdr_get_entry: Reservation ID mismatch\n"); + syslog(LOG_WARNING, "sdr_get_entry: Reservation ID mismatch\n"); return -1; } @@ -338,19 +338,19 @@ sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, // If the SDR repo is empty return error if (sdr_num_entries() == 0) { - syslog(LOG_ALERT, "sdr_get_entry: No entries\n"); + syslog(LOG_WARNING, "sdr_get_entry: No entries\n"); return -1; } // Check for boundary conditions if ((index < SDR_INDEX_MIN) || (index > SDR_INDEX_MAX)) { - syslog(LOG_ALERT, "sdr_get_entry: Invalid Record ID %d\n", read_rec_id); + syslog(LOG_WARNING, "sdr_get_entry: Invalid Record ID %d\n", read_rec_id); return -1; } // Check to make sure the given id is valid if (index < g_sdr_hdr.begin || index >= g_sdr_hdr.end) { - syslog(LOG_ALERT, "sdr_get_entry: Wrong Record ID %d\n", read_rec_id); + syslog(LOG_WARNING, "sdr_get_entry: Wrong Record ID %d\n", read_rec_id); return -1; } diff --git a/common/recipes-core/ipmid/files/sel.c b/common/recipes-core/ipmid/files/sel.c index d598bb1..1b45b42 100644 --- a/common/recipes-core/ipmid/files/sel.c +++ b/common/recipes-core/ipmid/files/sel.c @@ -31,9 +31,19 @@ #include <errno.h> #include <syslog.h> #include <string.h> +#include <stdint.h> +#include <sys/types.h> + + +#if defined(CONFIG_YOSEMITE) +#define MAX_NODES 4 +#else +#define MAX_NODES 1 +#endif // SEL File. -#define SEL_LOG_FILE "/mnt/data/sel.bin" +#define SEL_LOG_FILE "/mnt/data/sel%d.bin" +#define SIZE_PATH_MAX 32 // SEL Header magic number #define SEL_HDR_MAGIC 0xFBFBFBFB @@ -75,24 +85,27 @@ typedef struct { } sel_hdr_t; // Keep track of last Reservation ID -static int g_rsv_id = 0x01; +static int g_rsv_id[MAX_NODES+1]; // Cached version of SEL Header and data -static sel_hdr_t g_sel_hdr; -static sel_msg_t g_sel_data[SEL_ELEMS_MAX]; +static sel_hdr_t g_sel_hdr[MAX_NODES+1]; +static sel_msg_t g_sel_data[MAX_NODES+1][SEL_ELEMS_MAX]; // Local helper functions to interact with file system static int -file_get_sel_hdr(void) { +file_get_sel_hdr(int node) { FILE *fp; + char fpath[SIZE_PATH_MAX] = {0}; + + sprintf(fpath, SEL_LOG_FILE, node); - fp = fopen(SEL_LOG_FILE, "r"); + fp = fopen(fpath, "r"); if (fp == NULL) { return -1; } - if (fread(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { - syslog(LOG_ALERT, "file_get_sel_hdr: fread\n"); + if (fread(&g_sel_hdr[node], sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_WARNING, "file_get_sel_hdr: fread\n"); fclose (fp); return -1; } @@ -102,25 +115,28 @@ file_get_sel_hdr(void) { } static int -file_get_sel_data(void) { +file_get_sel_data(int node) { FILE *fp; int i, j; + char fpath[SIZE_PATH_MAX] = {0}; - fp = fopen(SEL_LOG_FILE, "r"); + sprintf(fpath, SEL_LOG_FILE, node); + + fp = fopen(fpath, "r"); if (fp == NULL) { - syslog(LOG_ALERT, "file_get_sel_data: fopen\n"); + syslog(LOG_WARNING, "file_get_sel_data: fopen\n"); return -1; } if (fseek(fp, SEL_DATA_OFFSET, SEEK_SET)) { - syslog(LOG_ALERT, "file_get_sel_data: fseek\n"); + syslog(LOG_WARNING, "file_get_sel_data: fseek\n"); fclose(fp); return -1; } unsigned char buf[SEL_ELEMS_MAX * 16]; if (fread(buf, 1, SEL_ELEMS_MAX * sizeof(sel_msg_t), fp) <= 0) { - syslog(LOG_ALERT, "file_get_sel_data: fread\n"); + syslog(LOG_WARNING, "file_get_sel_data: fread\n"); fclose(fp); return -1; } @@ -129,7 +145,7 @@ file_get_sel_data(void) { for (i = 0; i < SEL_ELEMS_MAX; i++) { for (j = 0; j < sizeof(sel_msg_t);j++) { - g_sel_data[i].msg[j] = buf[i*16 + j]; + g_sel_data[node][i].msg[j] = buf[i*16 + j]; } } @@ -137,17 +153,20 @@ file_get_sel_data(void) { } static int -file_store_sel_hdr(void) { +file_store_sel_hdr(int node) { FILE *fp; + char fpath[SIZE_PATH_MAX] = {0}; + + sprintf(fpath, SEL_LOG_FILE, node); - fp = fopen(SEL_LOG_FILE, "r+"); + fp = fopen(fpath, "r+"); if (fp == NULL) { - syslog(LOG_ALERT, "file_store_sel_hdr: fopen\n"); + syslog(LOG_WARNING, "file_store_sel_hdr: fopen\n"); return -1; } - if (fwrite(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { - syslog(LOG_ALERT, "file_store_sel_hdr: fwrite\n"); + if (fwrite(&g_sel_hdr[node], sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_WARNING, "file_store_sel_hdr: fwrite\n"); fclose(fp); return -1; } @@ -158,13 +177,16 @@ file_store_sel_hdr(void) { } static int -file_store_sel_data(int recId, sel_msg_t *data) { +file_store_sel_data(int node, int recId, sel_msg_t *data) { FILE *fp; int index; + char fpath[SIZE_PATH_MAX] = {0}; - fp = fopen(SEL_LOG_FILE, "r+"); + sprintf(fpath, SEL_LOG_FILE, node); + + fp = fopen(fpath, "r+"); if (fp == NULL) { - syslog(LOG_ALERT, "file_store_sel_data: fopen\n"); + syslog(LOG_WARNING, "file_store_sel_data: fopen\n"); return -1; } @@ -172,13 +194,13 @@ file_store_sel_data(int recId, sel_msg_t *data) { index = (recId-1) * sizeof(sel_msg_t); if (fseek(fp, SEL_DATA_OFFSET+index, SEEK_SET)) { - syslog(LOG_ALERT, "file_store_sel_data: fseek\n"); + syslog(LOG_WARNING, "file_store_sel_data: fseek\n"); fclose(fp); return -1; } if (fwrite(data->msg, sizeof(sel_msg_t), 1, fp) <= 0) { - syslog(LOG_ALERT, "file_store_sel_data: fwrite\n"); + syslog(LOG_WARNING, "file_store_sel_data: fwrite\n"); fclose(fp); return -1; } @@ -188,37 +210,103 @@ file_store_sel_data(int recId, sel_msg_t *data) { return 0; } +static void +dump_sel_syslog(int fru, sel_msg_t *data) { + int i = 0; + char temp_str[8] = {0}; + char str[128] = {0}; + + for (i = 0; i < 15; i++) { + sprintf(temp_str, "%02X:", data->msg[i]); + strcat(str, temp_str); + } + sprintf(temp_str, "%02X", data->msg[15]); + strcat(str, temp_str); + + syslog(LOG_CRIT, "SEL Entry, FRU: %d, Content: %s\n", fru, str); +} + +static void +parse_sel(uint8_t fru, sel_msg_t *data) { + int i = 0; + uint32_t timestamp; + char *sel = data->msg; + uint8_t sensor_type; + uint8_t sensor_num; + uint8_t event_dir; + uint8_t type_num; + uint8_t event_data[3]; + char sensor_name[32]; + char error_log[64]; + char error_type[64]; + char status[16]; + int ret; + + //memcpy(timestamp, (uint8_t *) &sel[3], 4); + timestamp = 0; + timestamp |= sel[3]; + timestamp |= sel[4] << 8; + timestamp |= sel[5] << 16; + timestamp |= sel[6] << 24; + + sensor_type = (uint8_t) sel[10]; + sensor_num = (uint8_t) sel[11]; + event_dir = ((uint8_t) sel[12] & (1 << 7)) >> 7; /* Bit 7 of sel[12] */ + type_num = (uint8_t) sel[12]; /* Bits 6:0 */ + memcpy(event_data, (uint8_t *) &sel[13], 3); + + sprintf(status, event_dir ? "DEASSERT" : "ASSERT"); + + if (type_num == 0x1) { + sprintf(error_type, "Threshold"); + } else if (type_num >= 0x2 || type_num <= 0xC || type_num == 0x6F) { + sprintf(error_type, "Discrete"); + } else if (type_num >= 0x70 || type_num <= 0x7F) { + sprintf(error_type, "OEM"); + } else { + sprintf(error_type, "Unknown"); + } + + ret = pal_get_event_sensor_name(fru, sensor_num, sensor_name); + ret = pal_parse_sel(fru, sensor_num, event_data, error_log); + ret = pal_sel_handler(fru, sensor_num); + + syslog(LOG_CRIT, "SEL Entry, %s: FRU: %d, Sensor: 0x%X, Name: %s," + " Timestamp: %u, Event Type: %s, Event Data: %s", + status, fru, sensor_num, sensor_name, timestamp, error_type, error_log); +} + // Platform specific SEL API entry points // Retrieve time stamp for recent add operation void -sel_ts_recent_add(time_stamp_t *ts) { - memcpy(ts->ts, g_sel_hdr.ts_add.ts, 0x04); +sel_ts_recent_add(int node, time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr[node].ts_add.ts, 0x04); } // Retrieve time stamp for recent erase operation void -sel_ts_recent_erase(time_stamp_t *ts) { - memcpy(ts->ts, g_sel_hdr.ts_erase.ts, 0x04); +sel_ts_recent_erase(int node, time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr[node].ts_erase.ts, 0x04); } // Retrieve total number of entries in SEL log int -sel_num_entries(void) { - if (g_sel_hdr.begin <= g_sel_hdr.end) { - return (g_sel_hdr.end - g_sel_hdr.begin); +sel_num_entries(int node) { + if (g_sel_hdr[node].begin <= g_sel_hdr[node].end) { + return (g_sel_hdr[node].end - g_sel_hdr[node].begin); } else { - return (g_sel_hdr.end + (SEL_INDEX_MAX - g_sel_hdr.begin + 1)); + return (g_sel_hdr[node].end + (SEL_INDEX_MAX - g_sel_hdr[node].begin + 1)); } } // Retrieve total free space available in SEL log int -sel_free_space(void) { +sel_free_space(int node) { int total_space; int used_space; total_space = SEL_RECORDS_MAX * sizeof(sel_msg_t); - used_space = sel_num_entries() * sizeof(sel_msg_t); + used_space = sel_num_entries(node) * sizeof(sel_msg_t); return (total_space - used_space); } @@ -226,28 +314,28 @@ sel_free_space(void) { // Reserve an ID that will be used in later operations // IPMI/Section 31.4 int -sel_rsv_id() { +sel_rsv_id(int node) { // Increment the current reservation ID and return - if (g_rsv_id++ == SEL_RSVID_MAX) { - g_rsv_id = SEL_RSVID_MIN; + if (g_rsv_id[node]++ == SEL_RSVID_MAX) { + g_rsv_id[node] = SEL_RSVID_MIN; } - return g_rsv_id; + return g_rsv_id[node]; } // Get the SEL entry for a given record ID // IPMI/Section 31.5 int -sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { +sel_get_entry(int node, int read_rec_id, sel_msg_t *msg, int *next_rec_id) { int index; // Find the index in to array based on given index if (read_rec_id == SEL_RECID_FIRST) { - index = g_sel_hdr.begin; + index = g_sel_hdr[node].begin; } else if (read_rec_id == SEL_RECID_LAST) { - if (g_sel_hdr.end) { - index = g_sel_hdr.end - 1; + if (g_sel_hdr[node].end) { + index = g_sel_hdr[node].end - 1; } else { index = SEL_INDEX_MAX; } @@ -256,34 +344,34 @@ sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { } // If the log is empty return error - if (sel_num_entries() == 0) { - syslog(LOG_ALERT, "sel_get_entry: No entries\n"); + if (sel_num_entries(node) == 0) { + syslog(LOG_WARNING, "sel_get_entry: No entries\n"); return -1; } // Check for boundary conditions if ((index < SEL_INDEX_MIN) || (index > SEL_INDEX_MAX)) { - syslog(LOG_ALERT, "sel_get_entry: Invalid Record ID %d\n", read_rec_id); + syslog(LOG_WARNING, "sel_get_entry: Invalid Record ID %d\n", read_rec_id); return -1; } // If begin < end, check to make sure the given id falls between - if (g_sel_hdr.begin < g_sel_hdr.end) { - if (index < g_sel_hdr.begin || index >= g_sel_hdr.end) { - syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID %d\n", read_rec_id); + if (g_sel_hdr[node].begin < g_sel_hdr[node].end) { + if (index < g_sel_hdr[node].begin || index >= g_sel_hdr[node].end) { + syslog(LOG_WARNING, "sel_get_entry: Wrong Record ID %d\n", read_rec_id); return -1; } } // If end < begin, check to make sure the given id is valid - if (g_sel_hdr.begin > g_sel_hdr.end) { - if (index >= g_sel_hdr.end && index < g_sel_hdr.begin) { - syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID2 %d\n", read_rec_id); + if (g_sel_hdr[node].begin > g_sel_hdr[node].end) { + if (index >= g_sel_hdr[node].end && index < g_sel_hdr[node].begin) { + syslog(LOG_WARNING, "sel_get_entry: Wrong Record ID2 %d\n", read_rec_id); return -1; } } - memcpy(msg->msg, g_sel_data[index].msg, sizeof(sel_msg_t)); + memcpy(msg->msg, g_sel_data[node][index].msg, sizeof(sel_msg_t)); // Return the next record ID in the log *next_rec_id = read_rec_id++; @@ -292,7 +380,7 @@ sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { } // If this is the last entry in the log, return 0xFFFF - if (*next_rec_id == g_sel_hdr.end) { + if (*next_rec_id == g_sel_hdr[node].end) { *next_rec_id = SEL_RECID_LAST; } @@ -302,13 +390,13 @@ sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { // Add a new entry in to SEL log // IPMI/Section 31.6 int -sel_add_entry(sel_msg_t *msg, int *rec_id) { +sel_add_entry(int node, sel_msg_t *msg, int *rec_id) { // If the SEL if full, roll over. To keep track of empty condition, use // one empty location less than the max records. - if (sel_num_entries() == SEL_RECORDS_MAX) { - syslog(LOG_ALERT, "sel_add_entry: SEL rollover\n"); - if (++g_sel_hdr.begin > SEL_INDEX_MAX) { - g_sel_hdr.begin = SEL_INDEX_MIN; + if (sel_num_entries(node) == SEL_RECORDS_MAX) { + syslog(LOG_WARNING, "sel_add_entry: SEL rollover\n"); + if (++g_sel_hdr[node].begin > SEL_INDEX_MAX) { + g_sel_hdr[node].begin = SEL_INDEX_MIN; } } @@ -316,27 +404,33 @@ sel_add_entry(sel_msg_t *msg, int *rec_id) { time_stamp_fill(&msg->msg[3]); // Add the enry at end - memcpy(g_sel_data[g_sel_hdr.end].msg, msg->msg, sizeof(sel_msg_t)); + memcpy(g_sel_data[node][g_sel_hdr[node].end].msg, msg->msg, sizeof(sel_msg_t)); // Return the newly added record ID - *rec_id = g_sel_hdr.end+1; + *rec_id = g_sel_hdr[node].end+1; - if (file_store_sel_data(*rec_id, msg)) { - syslog(LOG_ALERT, "sel_add_entry: file_store_sel_data\n"); + // Print the data in syslog + dump_sel_syslog(node, msg); + + // Parse the SEL message + parse_sel((uint8_t) node, msg); + + if (file_store_sel_data(node, *rec_id, msg)) { + syslog(LOG_WARNING, "sel_add_entry: file_store_sel_data\n"); return -1; } // Increment the end pointer - if (++g_sel_hdr.end > SEL_INDEX_MAX) { - g_sel_hdr.end = SEL_INDEX_MIN; + if (++g_sel_hdr[node].end > SEL_INDEX_MAX) { + g_sel_hdr[node].end = SEL_INDEX_MIN; } // Update timestamp for add in header - time_stamp_fill(g_sel_hdr.ts_add.ts); + time_stamp_fill(g_sel_hdr[node].ts_add.ts); // Store the structure persistently - if (file_store_sel_hdr()) { - syslog(LOG_ALERT, "sel_add_entry: file_store_sel_hdr\n"); + if (file_store_sel_hdr(node)) { + syslog(LOG_WARNING, "sel_add_entry: file_store_sel_hdr\n"); return -1; } @@ -347,21 +441,21 @@ sel_add_entry(sel_msg_t *msg, int *rec_id) { // IPMI/Section 31.9 // Note: To reduce wear/tear, instead of erasing, manipulating the metadata int -sel_erase(int rsv_id) { - if (rsv_id != g_rsv_id) { +sel_erase(int node, int rsv_id) { + if (rsv_id != g_rsv_id[node]) { return -1; } // Erase SEL Logs - g_sel_hdr.begin = SEL_INDEX_MIN; - g_sel_hdr.end = SEL_INDEX_MIN; + g_sel_hdr[node].begin = SEL_INDEX_MIN; + g_sel_hdr[node].end = SEL_INDEX_MIN; // Update timestamp for erase in header - time_stamp_fill(g_sel_hdr.ts_erase.ts); + time_stamp_fill(g_sel_hdr[node].ts_erase.ts); // Store the structure persistently - if (file_store_sel_hdr()) { - syslog(LOG_ALERT, "sel_erase: file_store_sel_hdr\n"); + if (file_store_sel_hdr(node)) { + syslog(LOG_WARNING, "sel_erase: file_store_sel_hdr\n"); return -1; } @@ -372,8 +466,8 @@ sel_erase(int rsv_id) { // IPMI/Section 31.2 // Note: Since we are not doing offline erasing, need not return in-progress state int -sel_erase_status(int rsv_id, sel_erase_stat_t *status) { - if (rsv_id != g_rsv_id) { +sel_erase_status(int node, int rsv_id, sel_erase_stat_t *status) { + if (rsv_id != g_rsv_id[node]) { return -1; } @@ -384,21 +478,24 @@ sel_erase_status(int rsv_id, sel_erase_stat_t *status) { } // Initialize SEL log file -int -sel_init(void) { +static int +sel_node_init(int node) { FILE *fp; int i; + char fpath[SIZE_PATH_MAX] = {0}; + + sprintf(fpath, SEL_LOG_FILE, node); // Check if the file exists or not - if (access(SEL_LOG_FILE, F_OK) == 0) { + if (access(fpath, F_OK) == 0) { // Since file is present, fetch all the contents to cache - if (file_get_sel_hdr()) { - syslog(LOG_ALERT, "init_sel: file_get_sel_hdr\n"); + if (file_get_sel_hdr(node)) { + syslog(LOG_WARNING, "init_sel: file_get_sel_hdr\n"); return -1; } - if (file_get_sel_data()) { - syslog(LOG_ALERT, "init_sel: file_get_sel_data\n"); + if (file_get_sel_data(node)) { + syslog(LOG_WARNING, "init_sel: file_get_sel_data\n"); return -1; } @@ -406,35 +503,52 @@ sel_init(void) { } // File not present, so create the file - fp = fopen(SEL_LOG_FILE, "w+"); + fp = fopen(fpath, "w+"); if (fp == NULL) { - syslog(LOG_ALERT, "init_sel: fopen\n"); + syslog(LOG_WARNING, "init_sel: fopen\n"); return -1; } fclose (fp); // Populate SEL Header in to the file - g_sel_hdr.magic = SEL_HDR_MAGIC; - g_sel_hdr.version = SEL_HDR_VERSION; - g_sel_hdr.begin = SEL_INDEX_MIN; - g_sel_hdr.end = SEL_INDEX_MIN; - memset(g_sel_hdr.ts_add.ts, 0x0, 4); - memset(g_sel_hdr.ts_erase.ts, 0x0, 4); - - if (file_store_sel_hdr()) { - syslog(LOG_ALERT, "init_sel: file_store_sel_hdr\n"); + g_sel_hdr[node].magic = SEL_HDR_MAGIC; + g_sel_hdr[node].version = SEL_HDR_VERSION; + g_sel_hdr[node].begin = SEL_INDEX_MIN; + g_sel_hdr[node].end = SEL_INDEX_MIN; + memset(g_sel_hdr[node].ts_add.ts, 0x0, 4); + memset(g_sel_hdr[node].ts_erase.ts, 0x0, 4); + + if (file_store_sel_hdr(node)) { + syslog(LOG_WARNING, "init_sel: file_store_sel_hdr\n"); return -1; } // Populate SEL Data in to the file for (i = 1; i <= SEL_RECORDS_MAX; i++) { sel_msg_t msg = {0}; - if (file_store_sel_data(i, &msg)) { - syslog(LOG_ALERT, "init_sel: file_store_sel_data\n"); + if (file_store_sel_data(node, i, &msg)) { + syslog(LOG_WARNING, "init_sel: file_store_sel_data\n"); return -1; } } + g_rsv_id[node] = 0x01; + return 0; } + +int +sel_init(void) { + int ret; + int i; + + for (i = 1; i < MAX_NODES+1; i++) { + ret = sel_node_init(i); + if (ret) { + return ret; + } + } + + return ret; +} diff --git a/common/recipes-core/ipmid/files/sel.h b/common/recipes-core/ipmid/files/sel.h index 3bb9a2f..500b078 100644 --- a/common/recipes-core/ipmid/files/sel.h +++ b/common/recipes-core/ipmid/files/sel.h @@ -37,15 +37,15 @@ typedef struct { unsigned char msg[16]; } sel_msg_t; -void sel_ts_recent_add(time_stamp_t *ts); -void sel_ts_recent_erase(time_stamp_t *ts); -int sel_num_entries(void); -int sel_free_space(void); -int sel_rsv_id(); -int sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id); -int sel_add_entry(sel_msg_t *msg, int *rec_id); -int sel_erase(int rsv_id); -int sel_erase_status(int rsv_id, sel_erase_stat_t *status); +void sel_ts_recent_add(int node, time_stamp_t *ts); +void sel_ts_recent_erase(int node, time_stamp_t *ts); +int sel_num_entries(int node); +int sel_free_space(int node); +int sel_rsv_id(int node); +int sel_get_entry(int node, int read_rec_id, sel_msg_t *msg, int *next_rec_id); +int sel_add_entry(int node, sel_msg_t *msg, int *rec_id); +int sel_erase(int node, int rsv_id); +int sel_erase_status(int node, int rsv_id, sel_erase_stat_t *status); int sel_init(void); #endif /* __SEL_H__ */ diff --git a/common/recipes-core/log-util/files/lib_pal.py b/common/recipes-core/log-util/files/lib_pal.py new file mode 100644 index 0000000..dcae08a --- /dev/null +++ b/common/recipes-core/log-util/files/lib_pal.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# +# Copyright 2015-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 ctypes import * + +lpal_hndl = CDLL("libpal.so") + +def pal_get_fru_name(fru): + name = create_string_buffer(16) + ret = lpal_hndl.pal_get_fru_name(c_uint8(fru), name) + if ret: + return None + else: + return name.value diff --git a/common/recipes-core/log-util/files/log-util.py b/common/recipes-core/log-util/files/log-util.py new file mode 100644 index 0000000..565e9a1 --- /dev/null +++ b/common/recipes-core/log-util/files/log-util.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# Copyright 2015-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 re +from datetime import datetime +import sys +from ctypes import * +from lib_pal import * + +SYSLOGFILE = '/mnt/data/logfile' +APPNAME = 'log-util' + +def print_usage(): + print 'Usage: %s --show' % (APPNAME) + +def log_main(): + + if len(sys.argv) is not 2: + print_usage() + return -1 + + if sys.argv[1] != '--show': + print_usage() + return -1 + + fd = open(SYSLOGFILE, 'r') + syslog = fd.readlines() + fd.close() + + print '%-4s %-8s %-22s %-16s %s' % ( + "FRU#", + "FRU_NAME", + "TIME_STAMP", + "APP_NAME", + "MESSAGE" + ) + + for log in syslog: + if not (re.search(r' bmc [a-z]*.crit ', log)): + continue + if re.search(r'FRU: [0-9]{1,2}', log, re.IGNORECASE): + fru = ''.join(re.findall(r'FRU: [0-9]{1,2}', log, re.IGNORECASE)) + # fru is in format "FRU: X" + fru = fru[5] + + # Name of the FRU from the PAL library + name = pal_get_fru_name(int(fru)) + else : + fru = '0' + + name = 'all' + + + temp = re.split(r' bmc [a-z]*.crit ', log) + + # Time format Sep 28 22:10:50 + ts = temp[0] + currtime = datetime.now() + ts = '%d %s' % (currtime.year, ts) + time = datetime.strptime(ts, '%Y %b %d %H:%M:%S') + time = time.strftime('%Y-%m-%d %H:%M:%S') + + temp2 = re.split(r': ', temp[1], 1) + app = temp2[0] + message = temp2[1] + + print '%-4s %-8s %-22s %-16s %s' % ( + fru, + name, + time, + app, + message + ) + + +if __name__ == '__main__': + log_main() diff --git a/common/recipes-core/log-util/log-util_0.1.bb b/common/recipes-core/log-util/log-util_0.1.bb new file mode 100644 index 0000000..0782688 --- /dev/null +++ b/common/recipes-core/log-util/log-util_0.1.bb @@ -0,0 +1,57 @@ +# Copyright 2015-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 +SUMMARY = "Log Utility" +DESCRIPTION = "Utility to parse and display logs." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://log-util.py;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + + +SRC_URI = "file://log-util.py \ + file://lib_pal.py \ + " + +S = "${WORKDIR}" + +DEPENDS += "libpal" + +binfiles = "log-util.py lib_pal.py" + +pkgdir = "log-util" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + install -d $dst + localbindir="${D}/usr/local/bin" + install -d ${localbindir} + + install -m 755 log-util.py ${dst}/log-util + ln -s ../fbpackages/${pkgdir}/log-util ${localbindir}/log-util + + install -m 755 lib_pal.py ${dst}/lib_pal.py + ln -s ../fbpackages/${pkgdir}/lib_pal.py ${localbindir}/lib_pal.py +} + +RDEPENDS_${PN} += "libpal" + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/log-util ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/power-util/files/power-util.c b/common/recipes-core/power-util/files/power-util.c index 0fda9d6..07e7c23 100644 --- a/common/recipes-core/power-util/files/power-util.c +++ b/common/recipes-core/power-util/files/power-util.c @@ -32,8 +32,8 @@ #define POWER_ON_STR "on" #define POWER_OFF_STR "off" -const char *pwr_option_list = "status, graceful-shutdown, off, on, cycle, 12V-off," - "12V-on, 12V-cycle"; +const char *pwr_option_list = "status, graceful-shutdown, off, on, cycle, " + "12V-off, 12V-on, 12V-cycle"; enum { PWR_STATUS = 1, @@ -47,22 +47,6 @@ enum { PWR_SLED_CYCLE }; -static int -set_last_pwr_state(uint8_t fru, char * state) { - - int ret; - char key[MAX_KEY_LEN] = {0}; - - sprintf(key, "pwr_server%d_last_state", (int) fru); - - ret = pal_set_key_value(key, state); - if (ret < 0) { - syslog(LOG_ALERT, "set_last_pwr_state: pal_set_key_value failed for " - "fru %u", fru); - } - return ret; -} - static void print_usage() { printf("Usage: power-util [ %s ] [ %s ]\nUsage: power-util sled-cycle\n", @@ -107,7 +91,7 @@ power_util(uint8_t fru, uint8_t opt) { case PWR_STATUS: ret = pal_get_server_power(fru, &status); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_get_server_power failed for fru %u\n", fru); + syslog(LOG_WARNING, "power_util: pal_get_server_power failed for fru %u\n", fru); return ret; } printf("Power status for fru %u : %s\n", fru, status?"ON":"OFF"); @@ -119,22 +103,24 @@ power_util(uint8_t fru, uint8_t opt) { ret = pal_set_server_power(fru, SERVER_GRACEFUL_SHUTDOWN); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" " fru %u", fru); return ret; } else if (ret == 1) { printf("fru %u is already powered OFF...\n", fru); return 0; + } else { + syslog(LOG_CRIT, "SERVER_GRACEFUL_SHUTDOWN successful for FRU: %d", fru); } - ret = set_last_pwr_state(fru, POWER_OFF_STR); + ret = pal_set_last_pwr_state(fru, POWER_OFF_STR); if (ret < 0) { return ret; } ret = pal_set_led(fru, LED_STATE_OFF); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); return ret; } break; @@ -145,22 +131,24 @@ power_util(uint8_t fru, uint8_t opt) { ret = pal_set_server_power(fru, SERVER_POWER_OFF); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" " fru %u", fru); return ret; } else if (ret == 1) { printf("fru %u is already powered OFF...\n", fru); return 0; + } else { + syslog(LOG_CRIT, "SERVER_POWER_OFF successful for FRU: %d", fru); } - ret = set_last_pwr_state(fru, POWER_OFF_STR); + ret = pal_set_last_pwr_state(fru, POWER_OFF_STR); if (ret < 0) { return ret; } ret = pal_set_led(fru, LED_STATE_OFF); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); return ret; } break; @@ -171,22 +159,24 @@ power_util(uint8_t fru, uint8_t opt) { ret = pal_set_server_power(fru, SERVER_POWER_ON); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" " fru %u", fru); return ret; } else if (ret == 1) { printf("fru %u is already powered ON...\n", fru); return 0; + } else { + syslog(LOG_CRIT, "SERVER_POWER_ON successful for FRU: %d", fru); } - ret = set_last_pwr_state(fru, POWER_ON_STR); + ret = pal_set_last_pwr_state(fru, POWER_ON_STR); if (ret < 0) { return ret; } ret = pal_set_led(fru, LED_STATE_ON); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); return ret; } break; @@ -197,41 +187,97 @@ power_util(uint8_t fru, uint8_t opt) { ret = pal_set_server_power(fru, SERVER_POWER_CYCLE); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" " fru %u", fru); return ret; + } else { + syslog(LOG_CRIT, "SERVER_POWER_CYCLE successful for FRU: %d", fru); } - ret = set_last_pwr_state(fru, POWER_ON_STR); + ret = pal_set_last_pwr_state(fru, POWER_ON_STR); if (ret < 0) { return ret; } ret = pal_set_led(fru, LED_STATE_ON); if (ret < 0) { - syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); return ret; } break; case PWR_12V_OFF: - ret = 0; // TODO: Need to add the API to support this power state setting + + printf("12V Powering fru %u to OFF state...\n", fru); + + ret = pal_set_server_power(fru, SERVER_12V_OFF); + if (ret < 0) { + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else { + syslog(LOG_CRIT, "SERVER_12V_OFF successful for FRU: %d", fru); + } + + ret = pal_set_last_pwr_state(fru, POWER_OFF_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_OFF); + if (ret < 0) { + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } break; case PWR_12V_ON: - ret = 0; // TODO: Need to add the API to support this power state setting + + printf("12V Powering fru %u to ON state...\n", fru); + + ret = pal_set_server_power(fru, SERVER_12V_ON); + if (ret < 0) { + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else { + syslog(LOG_CRIT, "SERVER_12V_ON successful for FRU: %d", fru); + } break; case PWR_12V_CYCLE: - ret = 0; // TODO: Need to add the API to support this power state setting + + printf("12V Power cycling fru %u...\n", fru); + + ret = pal_set_server_power(fru, SERVER_12V_CYCLE); + if (ret < 0) { + syslog(LOG_WARNING, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else { + syslog(LOG_CRIT, "SERVER_12V_CYCLE successful for FRU: %d", fru); + } + + ret = pal_set_last_pwr_state(fru, POWER_OFF_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_OFF); + if (ret < 0) { + syslog(LOG_WARNING, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } break; case PWR_SLED_CYCLE: + syslog(LOG_CRIT, "SLED_CYCLE successful"); + sleep(1); pal_sled_cycle(); break; default: - syslog(LOG_ALERT, "power_util: wrong option"); + syslog(LOG_WARNING, "power_util: wrong option"); } @@ -292,4 +338,6 @@ main(int argc, char **argv) { print_usage(); return ret; } + + return ret; } diff --git a/common/recipes-core/python/python_2.7.9.bbappend b/common/recipes-core/python/python_2.7.9.bbappend new file mode 100644 index 0000000..c3f1fa1 --- /dev/null +++ b/common/recipes-core/python/python_2.7.9.bbappend @@ -0,0 +1,21 @@ +# 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 + +# Patch from here - http://patchwork.openembedded.org/patch/96953/ +# is not available upstream yet . Until then we are adding ourselves to +# satisfy ssl.py that has a dependency on this module. +RDEPENDS_${PN}-io += "${PN}-contextlib" diff --git a/common/recipes-core/sensor-mon/files/sensord.c b/common/recipes-core/sensor-mon/files/sensord.c index 1852af3..0ad00f7 100644 --- a/common/recipes-core/sensor-mon/files/sensord.c +++ b/common/recipes-core/sensor-mon/files/sensord.c @@ -32,73 +32,17 @@ #include <facebook/bic.h> #include <openbmc/ipmi.h> #include <openbmc/sdr.h> -#ifdef CONFIG_YOSEMITE -#include <facebook/yosemite_sensor.h> -#endif /* CONFIG_YOSEMITE */ - -#define MAX_SENSOR_NUM 0xFF -#define NORMAL_STATE 0x00 - -#define SETBIT(x, y) (x | (1 << y)) -#define GETBIT(x, y) ((x & (1 << y)) > y) -#define CLEARBIT(x, y) (x & (~(1 << y))) -#define GETMASK(y) (1 << y) - - - -/* Enum for type of Upper and Lower threshold values */ -enum { - UCR_THRESH = 0x01, - UNC_THRESH, - UNR_THRESH, - LCR_THRESH, - LNC_THRESH, - LNR_THRESH, - POS_HYST, - NEG_HYST, -}; - -/* To hold the sensor info and calculated threshold values from the SDR */ -typedef struct { - uint8_t flag; - float ucr_thresh; - float unc_thresh; - float unr_thresh; - float lcr_thresh; - float lnc_thresh; - float lnr_thresh; - float pos_hyst; - float neg_hyst; - int curr_state; - char name[23]; - char units[64]; - -} thresh_sensor_t; - -/* Function pointer to read sensor current value */ -static int (*read_snr_val)(uint8_t, uint8_t, void *); - -#ifdef CONFIG_YOSEMITE - -// TODO: Change to 6 after adding SPB and NIC -#define MAX_NUM_FRUS 4 -#define YOSEMITE_SDR_PATH "/tmp/sdr_%s.bin" - -static thresh_sensor_t snr_slot1[MAX_SENSOR_NUM] = {0}; -static thresh_sensor_t snr_slot2[MAX_SENSOR_NUM] = {0}; -static thresh_sensor_t snr_slot3[MAX_SENSOR_NUM] = {0}; -static thresh_sensor_t snr_slot4[MAX_SENSOR_NUM] = {0}; -static thresh_sensor_t snr_spb[MAX_SENSOR_NUM] = {0}; -static thresh_sensor_t snr_nic[MAX_SENSOR_NUM] = {0}; - -static sensor_info_t sinfo_slot1[MAX_SENSOR_NUM] = {0}; -static sensor_info_t sinfo_slot2[MAX_SENSOR_NUM] = {0}; -static sensor_info_t sinfo_slot3[MAX_SENSOR_NUM] = {0}; -static sensor_info_t sinfo_slot4[MAX_SENSOR_NUM] = {0}; -static sensor_info_t sinfo_spb[MAX_SENSOR_NUM] = {0}; -static sensor_info_t sinfo_nic[MAX_SENSOR_NUM] = {0}; -#endif /* CONFIG_YOSEMITE */ +#include <openbmc/pal.h> +#define DELAY 2 + +static thresh_sensor_t g_snr[MAX_NUM_FRUS][MAX_SENSOR_NUM] = {0}; + +static void +print_usage() { + printf("Usage: sensord <options>\n"); + printf("Options: [ %s ]\n", pal_fru_list); +} /* * Returns the pointer to the struct holding all sensor info and @@ -109,502 +53,58 @@ get_struct_thresh_sensor(uint8_t fru) { thresh_sensor_t *snr; -#ifdef CONFIG_YOSEMITE - switch (fru) { - case FRU_SLOT1: - snr = snr_slot1; - break; - case FRU_SLOT2: - snr = snr_slot2; - break; - case FRU_SLOT3: - snr = snr_slot3; - break; - case FRU_SLOT4: - snr = snr_slot4; - break; - case FRU_SPB: - snr = snr_spb; - break; - case FRU_NIC: - snr = snr_nic; - break; - default: - syslog(LOG_ALERT, "get_struct_thresh_sensor: Wrong FRU ID %d\n", fru); - return NULL; - } -#endif /* CONFIG_YOSEMITE */ - - return snr; -} - - -/* Returns the all the SDRs for the particular fru# */ -static sensor_info_t * -get_struct_sensor_info(uint8_t fru) { - - sensor_info_t *sinfo; - -#ifdef CONFIG_YOSEMITE - switch (fru) { - case FRU_SLOT1: - sinfo = sinfo_slot1; - break; - case FRU_SLOT2: - sinfo = sinfo_slot2; - break; - case FRU_SLOT3: - sinfo = sinfo_slot3; - break; - case FRU_SLOT4: - sinfo = sinfo_slot4; - break; - case FRU_SPB: - sinfo = sinfo_spb; - break; - case FRU_NIC: - sinfo = sinfo_nic; - break; - default: - syslog(LOG_ALERT, "get_struct_sensor_info: Wrong FRU ID %d\n", fru); - return NULL; - } -#endif /* CONFIG_YOSEMITE */ - - return sinfo; -} - - -/* Returns the SDR for a particular sensor of particular fru# */ -static sdr_full_t * -get_struct_sdr(uint8_t fru, uint8_t snr_num) { - - sdr_full_t *sdr; - sensor_info_t *sinfo; - sinfo = get_struct_sensor_info(fru); - if (sinfo == NULL) { - syslog(LOG_ALERT, "get_struct_sdr: get_struct_sensor_info failed\n"); + if (fru < 1 || fru > MAX_NUM_FRUS) { + syslog(LOG_WARNING, "get_struct_thresh_sensor: Wrong FRU ID %d\n", fru); return NULL; } - sdr = &sinfo[snr_num].sdr; - return sdr; + snr = g_snr[fru-1]; + return snr; } -/* Get the threshold values from the SDRs */ +/* Initialize all thresh_sensor_t structs for all the Yosemite sensors */ static int -get_sdr_thresh_val(uint8_t fru, uint8_t snr_num, uint8_t thresh, void *value) { +init_fru_snr_thresh(uint8_t fru) { + int i; int ret; - uint8_t x; - uint8_t m_lsb, m_msb, m; - uint8_t b_lsb, b_msb, b; - int8_t b_exp, r_exp; - uint8_t thresh_val; - sdr_full_t *sdr; - - sdr = get_struct_sdr(fru, snr_num); - if (sdr == NULL) { - syslog(LOG_ALERT, "get_sdr_thresh_val: get_struct_sdr failed\n"); - return -1; - } - - switch (thresh) { - case UCR_THRESH: - thresh_val = sdr->uc_thresh; - break; - case UNC_THRESH: - thresh_val = sdr->unc_thresh; - break; - case UNR_THRESH: - thresh_val = sdr->unr_thresh; - break; - case LCR_THRESH: - thresh_val = sdr->lc_thresh; - break; - case LNC_THRESH: - thresh_val = sdr->lnc_thresh; - break; - case LNR_THRESH: - thresh_val = sdr->lnr_thresh; - break; - case POS_HYST: - thresh_val = sdr->pos_hyst; - break; - case NEG_HYST: - thresh_val = sdr->neg_hyst; - break; - default: - syslog(LOG_ERR, "get_sdr_thresh_val: reading unknown threshold val"); - return -1; - } - - // y = (mx + b * 10^b_exp) * 10^r_exp - x = thresh_val; - - m_lsb = sdr->m_val; - m_msb = sdr->m_tolerance >> 6; - m = (m_msb << 8) | m_lsb; - - b_lsb = sdr->b_val; - b_msb = sdr->b_accuracy >> 6; - b = (b_msb << 8) | b_lsb; - - // exponents are 2's complement 4-bit number - b_exp = sdr->rb_exp & 0xF; - if (b_exp > 7) { - b_exp = (~b_exp + 1) & 0xF; - b_exp = -b_exp; - } - r_exp = (sdr->rb_exp >> 4) & 0xF; - if (r_exp > 7) { - r_exp = (~r_exp + 1) & 0xF; - r_exp = -r_exp; - } - - * (float *) value = ((m * x) + (b * pow(10, b_exp))) * (pow(10, r_exp)); - - return 0; -} - -/* - * Populate all fields of thresh_sensor_t struct for a particular sensor. - * Incase the threshold value is 0 mask the check for that threshvold - * value in flag field. - */ -int -init_snr_thresh(uint8_t fru, uint8_t snr_num, uint8_t flag) { - - int value; - float fvalue; - uint8_t op, modifier; + uint8_t snr_num; + int sensor_cnt; + uint8_t *sensor_list; thresh_sensor_t *snr; - sdr_full_t *sdr; - - sdr = get_struct_sdr(fru, snr_num); - if (sdr == NULL) { - syslog(LOG_ALERT, "init_snr_name: get_struct_sdr failed\n"); - return -1; - } - snr = get_struct_thresh_sensor(fru); if (snr == NULL) { - syslog(LOG_ALERT, "init_snr_thresh: get_struct_thresh_sensor failed"); - return -1; - } - - snr[snr_num].flag = flag; - snr[snr_num].curr_state = NORMAL_STATE; - - if (sdr_get_sensor_name(sdr, snr[snr_num].name)) { - syslog(LOG_ALERT, "sdr_get_sensor_name: FRU %d: num: 0x%X: reading name" - " from SDR failed.", fru, snr_num); - return -1; - } - - // TODO: Add support for modifier (Mostly modifier is zero) - if (sdr_get_sensor_units(sdr, &op, &modifier, snr[snr_num].units)) { - syslog(LOG_ALERT, "sdr_get_sensor_units: FRU %d: num 0x%X: reading units" - " from SDR failed.", fru, snr_num); +#ifdef DEBUG + syslog(LOG_WARNING, "init_fru_snr_thresh: get_struct_thresh_sensor failed"); +#endif /* DEBUG */ return -1; } - if (get_sdr_thresh_val(fru, snr_num, UCR_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UCR_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].ucr_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UCR_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, UCR_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); - } + ret = pal_get_fru_sensor_list(fru, &sensor_list, &sensor_cnt); + if (ret < 0) { + return ret; } - if (get_sdr_thresh_val(fru, snr_num, UNC_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNC_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].unc_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UNC_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, UNC_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); - } - } - - if (get_sdr_thresh_val(fru, snr_num, UNR_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNR_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].unr_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UNR_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, UNR_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); - } - } - - if (get_sdr_thresh_val(fru, snr_num, LCR_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LCR_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].lcr_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LCR_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, LCR_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); - } - } - - if (get_sdr_thresh_val(fru, snr_num, LNC_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNC_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].lnc_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LNC_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, LNC_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); + for (i < 0; i < sensor_cnt; i++) { + snr_num = sensor_list[i]; + ret = sdr_get_snr_thresh(fru, snr_num, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH), &snr[snr_num]); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_WARNING, "init_fru_snr_thresh: sdr_get_snr_thresh for FRU: %d", fru); +#endif /* DEBUG */ + continue; } } - if (get_sdr_thresh_val(fru, snr_num, LNR_THRESH, &fvalue)) { - syslog(LOG_ERR, - "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNR_THRESH", - fru, snr_num, snr[snr_num].name); - } else { - snr[snr_num].lnr_thresh = fvalue; - if (!(fvalue)) { - snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LNR_THRESH); - syslog(LOG_ALERT, - "FRU: %d, num: 0x%X, %-16s, LNR_THRESH check disabled val->%.2f", - fru, snr_num, snr[snr_num].name, fvalue); - } + // TODO: This is a HACK. Need to add the pal_threshold_verify support + if (fru > 0 && fru < 5) { + snr[BIC_SENSOR_SOC_THERM_MARGIN].flag = SETBIT(snr[BIC_SENSOR_SOC_THERM_MARGIN].flag, UCR_THRESH); } - if (get_sdr_thresh_val(fru, snr_num, POS_HYST, &fvalue)) { - syslog(LOG_ERR, "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, POS_HYST", - fru, snr_num, snr[snr_num].name); - } else - snr[snr_num].pos_hyst = fvalue; - - if (get_sdr_thresh_val(fru, snr_num, NEG_HYST, &fvalue)) { - syslog(LOG_ERR, "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, NEG_HYST", - fru, snr_num, snr[snr_num].name); - } else - snr[snr_num].neg_hyst = fvalue; - return 0; } -#ifdef CONFIG_YOSEMITE -/* Initialize all thresh_sensor_t structs for all the Yosemite sensors */ -static void -init_yosemite_snr_thresh(uint8_t fru) { - - int i; - - switch (fru) { - case FRU_SLOT1: - case FRU_SLOT2: - case FRU_SLOT3: - case FRU_SLOT4: - - for (i < 0; i < bic_sensor_cnt; i++) { - init_snr_thresh(fru, bic_sensor_list[i], GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - } - /* - init_snr_thresh(fru, BIC_SENSOR_MB_OUTLET_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_1V05PCH_VR_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_MB_INLET_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_PCH_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_THERM_MARGIN, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_CURR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_1V05_PCH_VR_CURR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_POUT, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_CURR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_VOL, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_INA230_POWER, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_PACKAGE_PWR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_TJMAX, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_POUT, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_CURR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_VOL, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_CURR, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_VOL, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_POUT, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_POUT, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_VOL, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_1V05_PCH_VR_VOL, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMA0_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMA1_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMB0_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMB1_TEMP, GETMASK(UCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_P3V3_MB, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_P12V_MB, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_P1V05_PCH, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_P3V3_STBY_MB, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_P5V_STBY_MB, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_PV_BAT, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_PVDDR, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - - init_snr_thresh(fru, BIC_SENSOR_PVCC_GBE, - GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); - // TODO: Add Support for Discrete sensors - // init_snr_thresh(fru, BIC_SENSOR_POST_ERR, //Event-only - // init_snr_thresh(fru, BIC_SENSOR_SYSTEM_STATUS, //Discrete - // init_snr_thresh(fru, BIC_SENSOR_SPS_FW_HLTH); //Event-only - // init_snr_thresh(fru, BIC_SENSOR_POWER_THRESH_EVENT, //Event-only - // init_snr_thresh(fru, BIC_SENSOR_MACHINE_CHK_ERR, //Event-only - // init_snr_thresh(fru, BIC_SENSOR_PCIE_ERR); //Event-only - // init_snr_thresh(fru, BIC_SENSOR_OTHER_IIO_ERR); //Event-only - // init_snr_thresh(fru, BIC_SENSOR_PROC_HOT_EXT); //Event-only - // init_snr_thresh(fru, BIC_SENSOR_POWER_ERR); //Event-only - // init_snr_thresh(fru, , ); //Event-only - // init_snr_thresh(fru, BIC_SENSOR_PROC_FAIL); //Discrete - // init_snr_thresh(fru, BIC_SENSOR_SYS_BOOT_STAT ); //Discrete - // init_snr_thresh(fru, BIC_SENSOR_VR_HOT); //Discrete - // init_snr_thresh(fru, BIC_SENSOR_CPU_DIMM_HOT ); //Discrete - // init_snr_thresh(fru, BIC_SENSOR_CAT_ERR, //Event-only - - */ - - break; - - case FRU_SPB: - // TODO: Add support for threshold calculation for SP sensors - /* - init_snr_thresh(fru, SP_SENSOR_INLET_TEMP, "SP_SENSOR_INLET_TEMP"); - init_snr_thresh(fru, SP_SENSOR_OUTLET_TEMP, "SP_SENSOR_OUTLET_TEMP"); - init_snr_thresh(fru, SP_SENSOR_MEZZ_TEMP, "SP_SENSOR_MEZZ_TEMP"); - init_snr_thresh(fru, SP_SENSOR_FAN0_TACH, "SP_SENSOR_FAN0_TACH"); - init_snr_thresh(fru, SP_SENSOR_FAN1_TACH, "SP_SENSOR_FAN1_TACH"); - init_snr_thresh(fru, SP_SENSOR_AIR_FLOW, "SP_SENSOR_AIR_FLOW"); - init_snr_thresh(fru, SP_SENSOR_P5V, "SP_SENSOR_P5V"); - init_snr_thresh(fru, SP_SENSOR_P12V, "SP_SENSOR_P12V"); - init_snr_thresh(fru, SP_SENSOR_P3V3_STBY, "SP_SENSOR_P3V3_STBY"); - init_snr_thresh(fru, SP_SENSOR_P12V_SLOT0, "SP_SENSOR_P12V_SLOT0"); - init_snr_thresh(fru, SP_SENSOR_P12V_SLOT1, "SP_SENSOR_P12V_SLOT1"); - init_snr_thresh(fru, SP_SENSOR_P12V_SLOT2, "SP_SENSOR_P12V_SLOT2"); - init_snr_thresh(fru, SP_SENSOR_P12V_SLOT3, "SP_SENSOR_P12V_SLOT3"); - init_snr_thresh(fru, SP_SENSOR_P3V3, "SP_SENSOR_P3V3"); - init_snr_thresh(fru, SP_SENSOR_HSC_IN_VOLT, "SP_SENSOR_HSC_IN_VOLT"); - init_snr_thresh(fru, SP_SENSOR_HSC_OUT_CURR, "SP_SENSOR_HSC_OUT_CURR"); - init_snr_thresh(fru, SP_SENSOR_HSC_TEMP, "SP_SENSOR_HSC_TEMP"); - init_snr_thresh(fru, SP_SENSOR_HSC_IN_POWER, "SP_SENSOR_HSC_IN_POWER"); - */ - break; - - case FRU_NIC: - // TODO: Add support for NIC sensor threshold, if any. - break; - - default: - syslog(LOG_ALERT, "init_yosemite_snr_thresh: wrong FRU ID"); - exit(-1); - } -} -#endif /* CONFIG_YOSEMITE */ - -/* Wrapper function to initialize all the platform sensors */ -static void -init_all_snr_thresh() { - int fru; - - char path[64] = {0}; - sensor_info_t *sinfo; - - -#ifdef CONFIG_YOSEMITE - for (fru = FRU_SLOT1; fru < (FRU_SLOT1 + MAX_NUM_FRUS); fru++) { - - if (get_fru_sdr_path(fru, path) < 0) { - syslog(LOG_ALERT, "yosemite_sdr_init: get_fru_sdr_path failed\n"); - continue; - } -#endif /* CONFIG_YOSEMITE */ - - sinfo = get_struct_sensor_info(fru); - - if (sdr_init(path, sinfo) < 0) - syslog(LOG_ERR, "init_all_snr_thresh: sdr_init failed for FRU %d", fru); - } - -#ifdef CONFIG_YOSEMITE - for (fru = FRU_SLOT1; fru < (FRU_SLOT1 + MAX_NUM_FRUS); fru++) { - init_yosemite_snr_thresh(fru); - } -#endif /* CONFIG_YOSEMITE */ -} - - - - static float get_snr_thresh_val(uint8_t fru, uint8_t snr_num, uint8_t thresh) { @@ -633,7 +133,7 @@ get_snr_thresh_val(uint8_t fru, uint8_t snr_num, uint8_t thresh) { val = snr[snr_num].lnr_thresh; break; default: - syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + syslog(LOG_WARNING, "get_snr_thresh_val: wrong thresh enum value"); exit(-1); } @@ -662,7 +162,7 @@ check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, switch (thresh) { case UNC_THRESH: - if (curr_val <= thresh_val) { + if (curr_val < (thresh_val - snr[snr_num].pos_hyst)) { curr_state = ~(SETBIT(curr_state, UNR_THRESH) | SETBIT(curr_state, UCR_THRESH) | SETBIT(curr_state, UNC_THRESH)); @@ -671,7 +171,7 @@ check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, break; case UCR_THRESH: - if (curr_val <= thresh_val) { + if (curr_val < (thresh_val - snr[snr_num].pos_hyst)) { curr_state = ~(SETBIT(curr_state, UCR_THRESH) | SETBIT(curr_state, UNR_THRESH)); sprintf(thresh_name, "Upper Critical"); @@ -679,14 +179,14 @@ check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, break; case UNR_THRESH: - if (curr_val <= thresh_val) { + if (curr_val < (thresh_val - snr[snr_num].pos_hyst)) { curr_state = ~(SETBIT(curr_state, UNR_THRESH)); sprintf(thresh_name, "Upper Non Recoverable"); } break; case LNC_THRESH: - if (curr_val >= thresh_val) { + if (curr_val > (thresh_val + snr[snr_num].neg_hyst)) { curr_state = ~(SETBIT(curr_state, LNR_THRESH) | SETBIT(curr_state, LCR_THRESH) | SETBIT(curr_state, LNC_THRESH)); @@ -695,7 +195,7 @@ check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, break; case LCR_THRESH: - if (curr_val >= thresh_val) { + if (curr_val > (thresh_val + snr[snr_num].neg_hyst)) { curr_state = ~(SETBIT(curr_state, LCR_THRESH) | SETBIT(curr_state, LNR_THRESH)); sprintf(thresh_name, "Lower Critical"); @@ -703,23 +203,23 @@ check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, break; case LNR_THRESH: - if (curr_val >= thresh_val) { + if (curr_val > (thresh_val + snr[snr_num].neg_hyst)) { curr_state = ~(SETBIT(curr_state, LNR_THRESH)); sprintf(thresh_name, "Lower Non Recoverable"); } break; default: - syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + syslog(LOG_WARNING, "get_snr_thresh_val: wrong thresh enum value"); exit(-1); } if (curr_state) { snr[snr_num].curr_state &= curr_state; - syslog(LOG_CRIT, "DEASSERT: %s threshold raised - FRU: %d, num: 0x%X," - " snr: %-16s,",thresh_name, fru, snr_num, snr[snr_num].name); - syslog(LOG_CRIT, "curr_val: %.2f %s, thresh_val: %.2f %s cf: %u", - curr_val, snr[snr_num].units, thresh_val, snr[snr_num].units, snr[snr_num].curr_state); + syslog(LOG_CRIT, "DEASSERT: %s threshold - settled - FRU: %d, num: 0x%X " + "curr_val: %.2f %s, thresh_val: %.2f %s, snr: %-16s",thresh_name, + fru, snr_num,curr_val, snr[snr_num].units, thresh_val, + snr[snr_num].units, snr[snr_num].name); } } @@ -794,17 +294,99 @@ check_thresh_assert(uint8_t fru, uint8_t snr_num, uint8_t thresh, break; default: - syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + syslog(LOG_WARNING, "get_snr_thresh_val: wrong thresh enum value"); exit(-1); } if (curr_state) { curr_state &= snr[snr_num].flag; snr[snr_num].curr_state |= curr_state; - syslog(LOG_CRIT, "ASSERT: %s threshold raised - FRU: %d, num: 0x%X," - " snr: %-16s,",thresh_name, fru, snr_num, snr[snr_num].name); - syslog(LOG_CRIT, "curr_val: %.2f %s, thresh_val: %.2f %s cf: %u", - curr_val, snr[snr_num].units, thresh_val, snr[snr_num].units, snr[snr_num].curr_state); + syslog(LOG_CRIT, "ASSERT: %s threshold - raised - FRU: %d, num: 0x%X" + " curr_val: %.2f %s, thresh_val: %.2f %s, snr: %-16s", thresh_name, + fru, snr_num, curr_val, snr[snr_num].units, thresh_val, + snr[snr_num].units, snr[snr_num].name); + } +} + + +/* + * Starts monitoring all the sensors on a fru for all discrete sensors. + * Each pthread runs this monitoring for a different fru. + */ +static void * +snr_discrete_monitor(void *arg) { + +#ifdef DEBUG2 + char tmplog[1000]; +#endif /* DEBUG2 */ + uint8_t fru = *(uint8_t *) arg; + int i, ret; + uint8_t discrete_cnt; + uint8_t snr_num; + //uint8_t *discrete_list; + thresh_sensor_t *snr; + float normal_val, curr_val; + + // TODO: Need to resolve the SEGFAULT in the call below and replace HACK here. + /* + ret = pal_get_fru_discrete_list(fru, &discrete_list, &discrete_cnt); + if (ret < 0) { + return; + } + */ + /* HACK */ + uint8_t discrete_list[3]; + if (fru != FRU_SPB && fru != FRU_NIC) { + discrete_list[0] = BIC_SENSOR_SYSTEM_STATUS; + discrete_list[1] = BIC_SENSOR_VR_HOT; + discrete_list[2] = BIC_SENSOR_CPU_DIMM_HOT; + } else { + return -1; + } + + discrete_cnt = 3; + + snr = get_struct_thresh_sensor(fru); + if (snr == NULL) { + syslog(LOG_WARNING, "snr_thresh_monitor: get_struct_thresh_sensor failed"); + exit(-1); + } + + for (i = 0; i < discrete_cnt; i++) { + snr_num = discrete_list[i]; + pal_get_sensor_name(fru, snr_num, snr[snr_num].name); + } + +#if defined(TESTING) || defined(DEBUG) + int cnt = 0; +#endif + while(1) { + for (i = 0; i < discrete_cnt; i++) { + snr_num = discrete_list[i]; + ret = pal_sensor_read(fru, snr_num, &curr_val); + +#ifdef DEBUG2 + sprintf(tmplog, "echo 0x%X %s %d >> /tmp/discretetest%d", snr_num, snr[snr_num].name, (int) curr_val, fru); + system(tmplog); +#endif /* DEBUG2 */ + +#if defined(TESTING) || defined(DEBUG) + if (cnt == 2 && snr_num == BIC_SENSOR_SYSTEM_STATUS) { + curr_val = ((int) curr_val) | 0x1; + } else if (cnt == 6 && snr_num == BIC_SENSOR_SYSTEM_STATUS) { + curr_val = ((int) curr_val) & 0x0; + } +#endif + if ((snr[snr_num].curr_state != (int) curr_val) && !ret) { + pal_sensor_discrete_check(fru, snr_num, snr[snr_num].name, + snr[snr_num].curr_state, (int) curr_val); + snr[snr_num].curr_state = (int) curr_val; + } + } +#if defined(TESTING) || defined(DEBUG) + cnt ++; +#endif + sleep(DELAY); } } @@ -813,24 +395,28 @@ check_thresh_assert(uint8_t fru, uint8_t snr_num, uint8_t thresh, * Each pthread runs this monitoring for a different fru. */ static void * -snr_monitor(void *arg) { +snr_thresh_monitor(void *arg) { uint8_t fru = *(uint8_t *) arg; int f, ret, snr_num; float normal_val, curr_val; thresh_sensor_t *snr; -#ifdef TESTING +#if defined(TESTING) || defined(DEBUG) float temp_thresh; int cnt = 0; #endif /* TESTING */ snr = get_struct_thresh_sensor(fru); if (snr == NULL) { - syslog(LOG_ALERT, "snr_monitor: get_struct_thresh_sensor failed"); + syslog(LOG_WARNING, "snr_thresh_monitor: get_struct_thresh_sensor failed"); exit(-1); } +#ifdef DEBUG2 + char tmplog[1000]; +#endif /* DEBUG2 */ + while(1) { #ifdef TESTING @@ -840,8 +426,11 @@ snr_monitor(void *arg) { for (snr_num = 0; snr_num < MAX_SENSOR_NUM; snr_num++) { curr_val = 0; if (snr[snr_num].flag) { - if (!(ret = read_snr_val(fru, snr_num, &curr_val))) { - + if (!(ret = pal_sensor_read(fru, snr_num, &curr_val))) { +#ifdef DEBUG2 + sprintf(tmplog, "echo 0x%X %s %.2f >> /tmp/analog%d", snr_num, snr[snr_num].name, curr_val, fru); + system(tmplog); +#endif /* DEBUG2 */ #ifdef TESTING /* @@ -871,7 +460,6 @@ snr_monitor(void *arg) { snr[snr_num].units); } #endif /* DEBUG */ - check_thresh_assert(fru, snr_num, UNR_THRESH, curr_val); check_thresh_assert(fru, snr_num, UCR_THRESH, curr_val); check_thresh_assert(fru, snr_num, UNC_THRESH, curr_val); @@ -885,117 +473,149 @@ snr_monitor(void *arg) { check_thresh_deassert(fru, snr_num, LNC_THRESH, curr_val); check_thresh_deassert(fru, snr_num, LCR_THRESH, curr_val); check_thresh_deassert(fru, snr_num, LNR_THRESH, curr_val); - } else { /* - * Incase the read_snr_val failed for a sensor, + * Incase the pal_sensor_read failed for a sensor, * disable all the threshold checks for that sensor * after logging an approciate syslog message. */ + if (ret == ERR_NOT_READY) { + continue; + } + if (ret) { +#ifdef DEBUG syslog(LOG_ERR, "FRU: %d, num: 0x%X, snr:%-16s, read failed", fru, snr_num, snr[snr_num].name); - syslog(LOG_ERR, "FRU: %d, num: 0x%X, snr:%-16s, check disabled", - fru, snr_num, snr[snr_num].name); - snr[snr_num].flag = 0; - //} +#endif + + /* + * Check if the fru is up and running before disabling the sensor. + * If the fru is powered down, DO NOT disable the sensor check. + */ + char state[MAX_VALUE_LEN]; + + pal_get_last_pwr_state(fru, state); + if (!strcmp(state, "on")) { + snr[snr_num].flag = 0; + syslog(LOG_ERR, "FRU: %d, num: 0x%X, snr:%-16s, check disabled", + fru, snr_num, snr[snr_num].name); + } } - } /* read_snr_val return check */ + } /* pal_sensor_read return check */ } /* flag check */ } /* loop for all sensors */ - sleep(5); + sleep(DELAY); } /* while loop*/ } /* function definition */ +#ifdef DEBUG +void print_snr_thread(uint8_t fru, thresh_sensor_t *snr) +{ + int i,j; + float curr_val; + char tmplog[1000]; + char print[1000]; + + for (i = 0; i <= MAX_SENSOR_NUM; i++) { + if (snr[i].flag) { + curr_val = 0; + if(!(pal_sensor_read(fru, i, &curr_val))) { + sprintf(tmplog, "%-30s: %s %.2f %.2f %.2f %.2f\n", + snr[i].name, snr[i].units, + snr[i].ucr_thresh, + snr[i].lcr_thresh, + snr[i].pos_hyst, + snr[i].neg_hyst); + sprintf(print, "echo %s >> /tmp/print%d", tmplog, fru); + system(print); + } + } + } +} +#endif /* DEBUG */ + /* Spawns a pthread for each fru to monitor all the sensors on it */ -static void +static int run_sensord(int argc, char **argv) { - int i, arg; + int ret, arg; + uint8_t fru; + uint8_t fru_flag = 0; pthread_t thread_snr[MAX_NUM_FRUS]; - int fru[MAX_NUM_FRUS] = {0}; - - for (arg = 1; arg < argc; arg ++) { -#ifdef CONFIG_YOSEMITE - if (!(strcmp(argv[arg], "slot1"))) - fru[FRU_SLOT1 - 1] = FRU_SLOT1; - else if (!(strcmp(argv[arg], "slot2"))) - fru[FRU_SLOT2 - 1] = FRU_SLOT2; - else if (!(strcmp(argv[arg], "slot3"))) - fru[FRU_SLOT3 - 1] = FRU_SLOT3; - else if (!(strcmp(argv[arg], "slot4"))) - fru[FRU_SLOT4 - 1] = FRU_SLOT4; - else if (!(strcmp(argv[arg], "spb"))) - fru[FRU_SPB - 1] = FRU_SPB; - else if (!(strcmp(argv[arg], "nic"))) - fru[FRU_NIC - 1] = FRU_NIC; - else { - syslog(LOG_ALERT, "Wrong argument: %s", argv[arg]); - exit(1); - } -#endif /* CONFIG_YOSEMITE */ + pthread_t discrete_snr[MAX_NUM_FRUS]; + + arg = 1; + while(arg < argc) { + ret = pal_get_fru_id(argv[arg], &fru); + if (ret < 0) + return ret; + + fru_flag = SETBIT(fru_flag, fru); + arg++; } - for (i = 0; i < MAX_NUM_FRUS; i++) { - if (fru[i]) { - if (pthread_create(&thread_snr[i], NULL, snr_monitor, - (void*) &fru[i]) < 0) { - syslog(LOG_ALERT, "pthread_create for FRU %d failed\n", fru[i]); + for (fru = 1; fru <= MAX_NUM_FRUS; fru++) { + + if (GETBIT(fru_flag, fru)) { + + if (init_fru_snr_thresh(fru)) + return ret; + + /* Threshold Sensors */ + if (pthread_create(&thread_snr[fru-1], NULL, snr_thresh_monitor, + (void*) &fru) < 0) { + syslog(LOG_WARNING, "pthread_create for FRU %d failed\n", fru); } #ifdef DEBUG else { - syslog(LOG_ALERT, "pthread_create for FRU %d succeed\n", fru[i]); + syslog(LOG_WARNING, "pthread_create for FRU %d succeed\n", fru); } #endif /* DEBUG */ + sleep(1); + + /* Discrete Sensors */ + if (pthread_create(&discrete_snr[fru-1], NULL, snr_discrete_monitor, + (void*) &fru) < 0) { + syslog(LOG_WARNING, "pthread_create for FRU %d failed\n", fru); + } +#ifdef DEBUG + else { + syslog(LOG_WARNING, "pthread_create for discrete FRU %d succeed\n", fru); + } +#endif /* DEBUG */ + sleep(1); } - sleep(1); } - for (i = 0; i < MAX_NUM_FRUS; i++) { - if (fru[i]) - pthread_join(thread_snr[i], NULL); - } -} +#ifdef DEBUG + int i; + for (i = 1; i <= MAX_NUM_FRUS; i++) + print_snr_thread(i, g_snr[i-1]); +#endif /* DEBUG */ + for (fru = 1; fru <= MAX_NUM_FRUS; fru++) { -#ifdef DEBUG -void print_snr_thread(uint8_t fru, thresh_sensor_t *snr) -{ - int i; - float curr_val; + if (GETBIT(fru_flag, fru)) + pthread_join(discrete_snr[fru-1], NULL); + } - for (i = 1; i <= MAX_SENSOR_NUM; i++) { - if (snr[i].flag) { - curr_val = 0; - if(!(read_snr_val(fru, i, &curr_val))) { - printf("%-30s:\t%.2f %s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n", - snr[i].name, curr_val,snr[i].units, - snr[i].ucr_thresh, - snr[i].unc_thresh, - snr[i].lcr_thresh, - snr[i].lnr_thresh, - snr[i].pos_hyst, - snr[i].neg_hyst); - } else - printf("Reading failed: %-16s\n", snr[i].name); - } + for (fru = 1; fru <= MAX_NUM_FRUS; fru++) { + + if (GETBIT(fru_flag, fru)) + pthread_join(thread_snr[fru-1], NULL); } } -#endif /* DEBUG */ + int main(int argc, void **argv) { int dev, rc, pid_file; if (argc < 2) { - syslog(LOG_ALERT, "Usage: sensord <options>"); - printf("Usage: sensord <options>\n"); -#ifdef CONFIG_YOSEMITE - syslog(LOG_ALERT, "Options: [slot1 | slot2 | slot3 | slot4 | spb | nic]"); - printf("Options: [slot1 | slot2 | slot3 | slot4 | spb | nic]\n"); -#endif /* CONFIG_YOSEMITE */ + print_usage(); exit(1); } @@ -1008,24 +628,15 @@ main(int argc, void **argv) { } } else { -#ifdef CONFIG_YOSEMITE - read_snr_val = &yosemite_sensor_read; -#endif /* CONFIG_YOSEMITE */ - - init_all_snr_thresh(); - -#ifdef DEBUG - print_snr_thread(1, snr_slot1); - print_snr_thread(2, snr_slot2); - print_snr_thread(3, snr_slot3); - print_snr_thread(4, snr_slot4); -#endif /* DEBUG */ - daemon(0,1); openlog("sensord", LOG_CONS, LOG_DAEMON); syslog(LOG_INFO, "sensord: daemon started"); - run_sensord(argc, (char **) argv); - } + rc = run_sensord(argc, (char **) argv); + if (rc < 0) { + print_usage(); + return -1; + } + } return 0; } diff --git a/common/recipes-core/sensor-mon/sensor-mon_0.1.bb b/common/recipes-core/sensor-mon/sensor-mon_0.1.bb index adbd4cb..2cd2e4d 100644 --- a/common/recipes-core/sensor-mon/sensor-mon_0.1.bb +++ b/common/recipes-core/sensor-mon/sensor-mon_0.1.bb @@ -31,9 +31,9 @@ S = "${WORKDIR}" binfiles = "sensord \ " -CFLAGS += " -lsdr " +CFLAGS += " -lsdr -lpal " -DEPENDS += " libsdr " +DEPENDS += " libpal libsdr " pkgdir = "sensor-mon" diff --git a/common/recipes-core/sensor-util/files/Makefile b/common/recipes-core/sensor-util/files/Makefile index 2d39a04..168e4d7 100644 --- a/common/recipes-core/sensor-util/files/Makefile +++ b/common/recipes-core/sensor-util/files/Makefile @@ -3,7 +3,7 @@ all: sensor-util sensor-util: sensor-util.o - $(CC) $(CFLAGS) -lpal -lrt -lm -std=gnu99 -o $@ $^ $(LDFLAGS) + $(CC) $(CFLAGS) -lsdr -lpal -lrt -lm -std=gnu99 -o $@ $^ $(LDFLAGS) .PHONY: clean diff --git a/common/recipes-core/sensor-util/files/sensor-util.c b/common/recipes-core/sensor-util/files/sensor-util.c index eb38d65..c37fc38 100644 --- a/common/recipes-core/sensor-util/files/sensor-util.c +++ b/common/recipes-core/sensor-util/files/sensor-util.c @@ -26,72 +26,74 @@ #include <stdint.h> #include <string.h> #include <errno.h> +#include <stdbool.h> #include <openbmc/pal.h> +#include <openbmc/sdr.h> static int print_usage() { - printf("Usage: sensor-util [ %s ] <sensor num>\n" - "sensor num is optional.", pal_fru_list); + printf("Usage: sensor-util [ %s ] <--threshold> <sensor num>\n", + pal_fru_list); } static void -print_single_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt, uint8_t num) { - - int i; - float fvalue; - char name[24]; - char units[64]; - int ret = 0; - - for (i = 0; i < sensor_cnt; i++) { - - if (sensor_list[i] == num) { - ret = 1; - pal_get_sensor_name(fru, sensor_list[i], name); - pal_get_sensor_units(fru, sensor_list[i], units); - - if (pal_sensor_read(fru, sensor_list[i], &fvalue) < 0) { - - printf("pal_sensor_read failed: fru: %d num: 0x%X name: %-23s\n", - fru, sensor_list[i], name); - } else { - printf("%-23s: %.2f %s\n", name, fvalue, units); - } - - break; - } +print_sensor_reading(float fvalue, thresh_sensor_t *thresh, bool threshold) { + + if (threshold) { + printf("%-23s: Curr: %.2f %-8s\t" + " UCR: %.2f " + " UNC: %.2f " + " UNR: %.2f " + " LCR: %.2f " + " LNC: %.2f " + " LNR: %.2f \n", + thresh->name, fvalue, thresh->units, + thresh->ucr_thresh, + thresh->unc_thresh, + thresh->unr_thresh, + thresh->lcr_thresh, + thresh->lnc_thresh, + thresh->lnr_thresh); + } else { + printf("%-23s: %.2f %s\n", thresh->name, fvalue, thresh->units); } - if (!ret) { - printf("Wrong sensor number!\n"); - print_usage(); - exit(-1); - } } static void -print_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt) { +calculate_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt, int num, bool threshold) { int i; + uint8_t snr_num; float fvalue; - char name[24]; - char units[64]; + char path[64]; + thresh_sensor_t thresh; for (i = 0; i < sensor_cnt; i++) { - /* Clear the variable */ - sprintf(name, ""); - sprintf(units, ""); + snr_num = sensor_list[i]; - pal_get_sensor_name(fru, sensor_list[i], name); - pal_get_sensor_units(fru, sensor_list[i], units); + /* If calculation is for a single sensor, ignore all others. */ + if (num && snr_num != num) { + continue; + } - if (pal_sensor_read(fru, sensor_list[i], &fvalue) < 0) { + if (threshold) { + if (sdr_get_snr_thresh(fru, snr_num, 0, &thresh)) + syslog(LOG_ERR, "sdr_init_snr_thresh failed for FRU %d num: 0x%X", fru, snr_num); + } else { + sdr_get_sensor_name(fru, sensor_list[i], thresh.name); + sdr_get_sensor_units(fru, sensor_list[i], thresh.units); + } - printf("pal_sensor_read failed: fru: %d num: 0x%X name: %-23s\n", - fru, sensor_list[i], name); + usleep(50); + + if (pal_sensor_read(fru, snr_num, &fvalue) < 0) { + printf("pal_sensor_read failed: FRU: %d num: 0x%X name: %-23s\n", + fru, sensor_list[i], thresh.name, thresh.units); + continue; } else { - printf("%-23s: %.2f %s\n", name, fvalue, units); + print_sensor_reading(fvalue, &thresh, threshold); } } } @@ -99,25 +101,32 @@ print_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt) { int main(int argc, char **argv) { + int i; int ret; int sensor_cnt; uint8_t *sensor_list; uint8_t fru; - uint8_t num; + uint8_t num = 0; + bool threshold = false; - if (argc < 2 || argc > 3) { + if (argc < 2 || argc > 4) { print_usage(); exit(-1); } - if (argc == 3) { - errno = 0; - num = (uint8_t) strtol(argv[2], NULL, 0); - if (errno) { - printf("Sensor number format incorrect.\n"); - print_usage(); - exit(-1); + i = 3; /* Starting at argument 3*/ + while (argc > 2 && i <= argc) { + if (!(strcmp(argv[i-1], "--threshold"))) { + threshold = true; + } else { + errno = 0; + num = (uint8_t) strtol(argv[i-1], NULL, 0); + if (errno) { + print_usage(); + exit(-1); + } } + i++; } @@ -131,42 +140,24 @@ main(int argc, char **argv) { fru = 1; while (fru <= MAX_NUM_FRUS) { - if (fru == FRU_NIC) { - printf("\nsensor-util does not support nic\n"); - exit(-1); - } - ret = pal_get_fru_sensor_list(fru, &sensor_list, &sensor_cnt); if (ret < 0) { return ret; } - if (num) { - print_single_sensor_reading(fru, sensor_list, sensor_cnt, num); - } else { - print_sensor_reading(fru, sensor_list, sensor_cnt); - } + calculate_sensor_reading(fru, sensor_list, sensor_cnt, num, threshold); fru++; printf("\n"); } } else { - if (fru == FRU_NIC) { - printf("\nsensor-util does not support nic\n"); - //exit(-1); - } - ret = pal_get_fru_sensor_list(fru, &sensor_list, &sensor_cnt); if (ret < 0) { return ret; } - if (num) { - print_single_sensor_reading(fru, sensor_list, sensor_cnt, num); - } else { - print_sensor_reading(fru, sensor_list, sensor_cnt); - } + calculate_sensor_reading(fru, sensor_list, sensor_cnt, num, threshold); } return 0; diff --git a/common/recipes-core/sensor-util/sensor-util_0.1.bb b/common/recipes-core/sensor-util/sensor-util_0.1.bb index 227ec53..d802694 100644 --- a/common/recipes-core/sensor-util/sensor-util_0.1.bb +++ b/common/recipes-core/sensor-util/sensor-util_0.1.bb @@ -13,7 +13,7 @@ S = "${WORKDIR}" binfiles = "sensor-util" -DEPENDS =+ " libpal " +DEPENDS =+ " libsdr libpal " pkgdir = "sensor-util" diff --git a/common/recipes-lib/fruid/files/fruid.c b/common/recipes-lib/fruid/files/fruid.c index dc71ac8..e665c27 100644 --- a/common/recipes-lib/fruid/files/fruid.c +++ b/common/recipes-lib/fruid/files/fruid.c @@ -65,7 +65,9 @@ static char * calculate_time(uint8_t * mfg_time) char * mfg_time_str = (char *) malloc(len); if (!mfg_time_str) { - syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "fruid: malloc: memory allocation failed\n"); +#endif return NULL; } @@ -120,13 +122,17 @@ static char * get_chassis_type(uint8_t type_hex) /* If the type is not in the list defined.*/ if (type > FRUID_CHASSIS_TYPECODE_MAX || type < FRUID_CHASSIS_TYPECODE_MIN) { +#ifdef DEBUG syslog(LOG_INFO, "fruid: chassis area: invalid chassis type\n"); +#endif return NULL; } char * type_str = (char *) malloc(strlen(fruid_chassis_type[type])); if (!type_str) { - syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "fruid: malloc: memory allocation failed\n"); +#endif return NULL; } @@ -179,7 +185,9 @@ static char * _fruid_area_field_read(uint8_t *offset) field_len_eff > 0 ? (field = (char *) malloc(field_len_eff + 1)) : (field = (char *) malloc(strlen(FIELD_EMPTY))); if (!field) { - syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "fruid: malloc: memory allocation failed\n"); +#endif return NULL; } @@ -327,7 +335,9 @@ int parse_fruid_area_product(uint8_t * product, /* Check if the format version is as per IPMI FRUID v1.0 format spec */ fruid_product->format_ver = product[index++]; if (fruid_product->format_ver != FRUID_FORMAT_VER) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: product_area: format version not supported"); +#endif return EPROTONOSUPPORT; } @@ -339,7 +349,9 @@ int parse_fruid_area_product(uint8_t * product, fruid_product->area_len, fruid_product->chksum); if (ret) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: product_area: chksum not verified."); +#endif return EBADF; } @@ -401,7 +413,9 @@ int parse_fruid_area_board(uint8_t * board, /* Check if the format version is as per IPMI FRUID v1.0 format spec */ fruid_board->format_ver = board[index++]; if (fruid_board->format_ver != FRUID_FORMAT_VER) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: board_area: format version not supported"); +#endif return EPROTONOSUPPORT; } fruid_board->area_len = board[index++] * FRUID_AREA_LEN_MULTIPLIER; @@ -412,7 +426,9 @@ int parse_fruid_area_board(uint8_t * board, fruid_board->area_len, fruid_board->chksum); if (ret) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: board_area: chksum not verified."); +#endif return EBADF; } @@ -471,7 +487,9 @@ int parse_fruid_area_chassis(uint8_t * chassis, /* Check if the format version is as per IPMI FRUID v1.0 format spec */ fruid_chassis->format_ver = chassis[index++]; if (fruid_chassis->format_ver != FRUID_FORMAT_VER) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: chassis_area: format version not supported"); +#endif return EPROTONOSUPPORT; } @@ -482,7 +500,9 @@ int parse_fruid_area_chassis(uint8_t * chassis, ret = verify_chksum((uint8_t *) chassis, fruid_chassis->area_len, fruid_chassis->chksum); if (ret) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: chassis_area: chksum not verified."); +#endif return EBADF; } @@ -540,7 +560,9 @@ int parse_fruid_header(uint8_t * eeprom, fruid_header_t * header) ret = verify_chksum((uint8_t *) header, sizeof(fruid_header_t), header->chksum); if (ret) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: common_header: chksum not verified."); +#endif return EBADF; } @@ -634,7 +656,9 @@ int fruid_parse(const char * bin, fruid_info_t * fruid) /* Open the FRUID binary file */ fruid_fd = fopen(bin, "rb"); if (!fruid_fd) { +#ifdef DEBUG syslog(LOG_ERR, "fruid: unable to open the file"); +#endif return ENOENT; } @@ -646,7 +670,9 @@ int fruid_parse(const char * bin, fruid_info_t * fruid) eeprom = (uint8_t *) malloc(fruid_len); if (!eeprom) { - syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "fruid: malloc: memory allocation failed\n"); +#endif return ENOMEM; } diff --git a/common/recipes-lib/ipmb/files/ipmb.c b/common/recipes-lib/ipmb/files/ipmb.c index 731eeba..9fe12f5 100644 --- a/common/recipes-lib/ipmb/files/ipmb.c +++ b/common/recipes-lib/ipmb/files/ipmb.c @@ -42,26 +42,39 @@ lib_ipmb_handle(unsigned char bus_id, int s, t, len; struct sockaddr_un remote; char sock_path[64] = {0}; + struct timeval tv; sprintf(sock_path, "%s_%d", SOCK_PATH_IPMB, bus_id); // TODO: Need to update to reuse the socket instead of creating new if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - syslog(LOG_ALERT, "lib_ipmb_handle: socket() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmb_handle: socket() failed\n"); +#endif return; } + // setup timeout for receving on socket + tv.tv_sec = TIMEOUT_IPMB + 1; + tv.tv_usec = 0; + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + remote.sun_family = AF_UNIX; strcpy(remote.sun_path, sock_path); len = strlen(remote.sun_path) + sizeof(remote.sun_family); if (connect(s, (struct sockaddr *)&remote, len) == -1) { - syslog(LOG_ALERT, "ipmb_handle: connect() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "ipmb_handle: connect() failed\n"); +#endif goto clean_exit; } if (send(s, request, req_len, 0) == -1) { - syslog(LOG_ALERT, "ipmb_handle: send() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "ipmb_handle: send() failed\n"); +#endif goto clean_exit; } @@ -69,9 +82,13 @@ lib_ipmb_handle(unsigned char bus_id, *res_len = t; } else { if (t < 0) { - syslog(LOG_ALERT, "lib_ipmb_handle: recv() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmb_handle: recv() failed\n"); +#endif } else { - printf("Server closed connection\n"); +#ifdef DEBUG + syslog(LOG_DEBUG, "Server closed connection\n"); +#endif } } diff --git a/common/recipes-lib/ipmb/files/ipmb.h b/common/recipes-lib/ipmb/files/ipmb.h index d9bc16b..070e7ed 100644 --- a/common/recipes-lib/ipmb/files/ipmb.h +++ b/common/recipes-lib/ipmb/files/ipmb.h @@ -40,7 +40,10 @@ extern "C" { // Slot#0 is on I2C Bus1 #define IPMB_BUS_SLOT0 1 -#define TIMEOUT_IPMI 4 +// TODO: Some IPMB responses take about 5-6 seconds +// Need to add a timeout parameter to IPMB request +// For now changing global timeout to 8 seconds +#define TIMEOUT_IPMB 8 #define MAX_IPMB_RES_LEN 255 typedef struct _ipmb_req_t { diff --git a/common/recipes-lib/ipmi/files/ipmi.c b/common/recipes-lib/ipmi/files/ipmi.c index 3579eca..1b0f210 100644 --- a/common/recipes-lib/ipmi/files/ipmi.c +++ b/common/recipes-lib/ipmi/files/ipmi.c @@ -41,24 +41,37 @@ lib_ipmi_handle(unsigned char *request, unsigned char req_len, int s, t, len; struct sockaddr_un remote; + struct timeval tv; // TODO: Need to update to reuse the socket instead of creating new if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - syslog(LOG_ALERT, "lib_ipmi_handle: socket() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmi_handle: socket() failed\n"); +#endif return; } + // setup timeout for receving on socket + tv.tv_sec = TIMEOUT_IPMI + 1; + tv.tv_usec = 0; + + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + remote.sun_family = AF_UNIX; strcpy(remote.sun_path, SOCK_PATH_IPMI); len = strlen(remote.sun_path) + sizeof(remote.sun_family); if (connect(s, (struct sockaddr *)&remote, len) == -1) { - syslog(LOG_ALERT, "lib_ipmi_handle: connect() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmi_handle: connect() failed\n"); +#endif return; } if (send(s, request, req_len, 0) == -1) { - syslog(LOG_ALERT, "lib_ipmi_handle: send() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmi_handle: send() failed\n"); +#endif return; } @@ -66,7 +79,9 @@ lib_ipmi_handle(unsigned char *request, unsigned char req_len, *res_len = t; } else { if (t < 0) { - syslog(LOG_ALERT, "lib_ipmi_handle: recv() failed\n"); +#ifdef DEBUG + syslog(LOG_WARNING, "lib_ipmi_handle: recv() failed\n"); +#endif } else { printf("Server closed connection"); } diff --git a/common/recipes-lib/ipmi/files/ipmi.h b/common/recipes-lib/ipmi/files/ipmi.h index 2ae7f1c..7b54dd1 100644 --- a/common/recipes-lib/ipmi/files/ipmi.h +++ b/common/recipes-lib/ipmi/files/ipmi.h @@ -36,6 +36,7 @@ extern "C" { #define SIZE_AUTH_ENABLES 5 #define SIZE_IP_ADDR 4 +#define SIZE_IP6_ADDR 16 #define SIZE_MAC_ADDR 6 #define SIZE_NET_MASK 4 #define SIZE_IP_HDR 3 @@ -58,7 +59,8 @@ extern "C" { #define SIZE_SEL_REC 16 -#define BIC_INTF_HDR_SIZE 3 +// NetFn, Command, Checksum, IANAID(3 bytes), BIC Interface type +#define BIC_INTF_HDR_SIZE 7 #define LUN_OFFSET 2 @@ -76,6 +78,8 @@ extern "C" { #define TYPE_ASCII_6BIT 2 #define TYPE_ASCII_8BIT 3 +#define TIMEOUT_IPMI 5 + // IPMI request Structure (IPMI/Section 9.2) typedef struct { @@ -231,6 +235,7 @@ typedef struct unsigned char no_of_dest; unsigned char dest_type[SIZE_DEST_TYPE]; unsigned char dest_addr[SIZE_DEST_ADDR]; + unsigned char ip6_addr[SIZE_IP6_ADDR]; } lan_config_t; // Structure to store Processor Information @@ -322,6 +327,7 @@ enum { CMD_STORAGE_GET_FRUID_INFO = 0x10, CMD_STORAGE_READ_FRUID_DATA = 0x11, + CMD_STORAGE_WRITE_FRUID_DATA = 0x12, CMD_STORAGE_GET_SDR_INFO = 0x20, CMD_STORAGE_RSV_SDR = 0x22, CMD_STORAGE_GET_SDR = 0x23, @@ -354,17 +360,21 @@ enum CMD_OEM_SET_DIMM_INFO = 0x1C, CMD_OEM_SET_POST_START = 0x73, CMD_OEM_SET_POST_END = 0x74, + CMD_OEM_GET_SLOT_INFO = 0x7E, }; // OEM 1S Command Codes (Quanta/FB defined commands) enum { CMD_OEM_1S_MSG_IN = 0x1, + CMD_OEM_1S_MSG_OUT = 0x2, CMD_OEM_1S_GET_GPIO = 0x3, CMD_OEM_1S_GET_GPIO_CONFIG = 0x5, CMD_OEM_1S_SET_GPIO_CONFIG = 0x6, CMD_OEM_1S_INTR = 0x7, CMD_OEM_1S_POST_BUF = 0x8, + CMD_OEM_1S_UPDATE_FW = 0x9, + CMD_OEM_1S_GET_FW_VER = 0xB, CMD_OEM_1S_GET_CONFIG = 0xE, CMD_OEM_1S_PLAT_DISC = 0xF, CMD_OEM_1S_SET_CONFIG = 0x10, @@ -408,6 +418,7 @@ enum LAN_PARAM_NO_OF_DEST, LAN_PARAM_DEST_TYPE, LAN_PARAM_DEST_ADDR, + LAN_PARAM_IP6_ADDR = 197, /* OEM parameter for IPv6 */ }; // Boot Option Parameters (IPMI/Table 28-14) @@ -441,6 +452,7 @@ enum BIC_INTF_ME = 0x01, BIC_INTF_SOL = 0x02, BIC_INTF_KCS = 0x03, + BIC_INTF_KCS_SMM = 0x04, }; void lib_ipmi_handle(unsigned char *request, unsigned char req_len, diff --git a/common/recipes-lib/sdr/files/Makefile b/common/recipes-lib/sdr/files/Makefile index 11fe3ee..607f914 100644 --- a/common/recipes-lib/sdr/files/Makefile +++ b/common/recipes-lib/sdr/files/Makefile @@ -3,7 +3,7 @@ lib: libsdr.so libsdr.so: sdr.c $(CC) $(CFLAGS) -fPIC -c -o sdr.o sdr.c - $(CC) -lm -shared -o libsdr.so sdr.o -lc + $(CC) -lpal -lm -shared -o libsdr.so sdr.o -lc .PHONY: clean diff --git a/common/recipes-lib/sdr/files/sdr.c b/common/recipes-lib/sdr/files/sdr.c index 208b10f..2b05bf5 100644 --- a/common/recipes-lib/sdr/files/sdr.c +++ b/common/recipes-lib/sdr/files/sdr.c @@ -27,6 +27,7 @@ #include <fcntl.h> #include <errno.h> #include <syslog.h> +#include <string.h> #include "sdr.h" #define FIELD_RATE_UNIT(x) ((x & (0x07 << 3)) >> 3) @@ -34,7 +35,9 @@ #define FIELD_PERCENTAGE(x) (x & 0x01) #define FIELD_TYPE(x) ((x & (0x03 << 6)) >> 6) -#define FIELD_LEN(x) (x & 0xF) +#define FIELD_LEN(x) (x & 0x1F) + +#define MAX_NAME_LEN 16 /* Array for BCD Plus definition. */ const char bcd_plus_array[] = "0123456789 -.XXX"; @@ -48,10 +51,11 @@ const char * ascii_6bit[4] = { }; /* Get the units of the sensor from the SDR */ -int -sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, +static int +_sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, char *units) { + int ret; uint8_t percent; uint8_t rate_idx; uint8_t base_idx; @@ -88,10 +92,46 @@ sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, return 0; } +int +sdr_get_sensor_units(uint8_t fru, uint8_t snr_num, char *units) { + + int ret = 0; + uint8_t op; + uint8_t modifier; + sdr_full_t *sdr; + + sensor_info_t sinfo[MAX_SENSOR_NUM] = {0}; + + if (pal_sensor_sdr_init(fru, sinfo) < 0) { + sdr = NULL; + } else { + sdr = &sinfo[snr_num].sdr; + } + + if (sdr != NULL) { + ret = _sdr_get_sensor_units(sdr, &op, &modifier, units); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "_sdr_get_sensor_units failed for FRU: %d snr_num: %d", + fru, snr_num); +#endif + } + } else { + ret = pal_get_sensor_units(fru, snr_num, units); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "pal_get_sensor_units failed for FRU: %d snr_num: %d", + fru, snr_num); +#endif + } + } + + return ret; +} /* Get the name of the sensor from the SDR */ -int -sdr_get_sensor_name(sdr_full_t *sdr, char *name) { +static int +_sdr_get_sensor_name(sdr_full_t *sdr, char *name) { int field_type, field_len; int idx, idx_eff, val; char *str; @@ -105,9 +145,9 @@ sdr_get_sensor_name(sdr_full_t *sdr, char *name) { /* Case: length is zero */ if (field_len == 1) { - syslog(LOG_ALERT, "get_sensor_name: str length is 0\n"); - // TODO: Fix this hack later - sprintf(name, "%s", str); +#ifdef DEBUG + syslog(LOG_WARNING, "get_sensor_name: str length is 0\n"); +#endif return -1; } @@ -174,37 +214,326 @@ sdr_get_sensor_name(sdr_full_t *sdr, char *name) { return 0; } -/* Populates all sensor_info_t struct using the path to SDR dump */ int -sdr_init(char *path, sensor_info_t *sinfo) { - int fd; - uint8_t buf[MAX_SDR_LEN] = {0}; - uint8_t bytes_rd = 0; - uint8_t snr_num = 0; +sdr_get_sensor_name(uint8_t fru, uint8_t snr_num, char *name) { + + int ret = 0; sdr_full_t *sdr; - while (access(path, F_OK) == -1) { - sleep(5); + sensor_info_t sinfo[MAX_SENSOR_NUM] = {0}; + + if (pal_sensor_sdr_init(fru, sinfo) < 0) { + sdr = NULL; + } else { + sdr = &sinfo[snr_num].sdr; } - fd = open(path, O_RDONLY); - if (fd < 0) { - syslog(LOG_ERR, "sdr_init: open failed for %s\n", path); - return -1; + if (sdr != NULL) { + ret = _sdr_get_sensor_name(sdr, name); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "_sdr_get_sensor_name failed for FRU: %d snr_num: %d", + fru, snr_num); +#endif + } + } else { + ret = pal_get_sensor_name(fru, snr_num, name); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "pal_get_sensor_name failed for FRU: %d snr_num: %d", + fru, snr_num); +#endif + } } - while ((bytes_rd = read(fd, buf, sizeof(sdr_full_t))) > 0) { - if (bytes_rd != sizeof(sdr_full_t)) { - syslog(LOG_ERR, "sdr_init: read returns %d bytes\n", bytes_rd); + return ret; +} + +/* Get the threshold values from the SDRs */ +static int +get_sdr_thresh_val(uint8_t fru, sdr_full_t *sdr, uint8_t snr_num, + uint8_t thresh, void *value) { + + int ret; + uint8_t x; + uint8_t m_lsb, m_msb, m; + uint8_t b_lsb, b_msb, b; + int8_t b_exp, r_exp; + uint8_t thresh_val; + + switch (thresh) { + case UCR_THRESH: + thresh_val = sdr->uc_thresh; + break; + case UNC_THRESH: + thresh_val = sdr->unc_thresh; + break; + case UNR_THRESH: + thresh_val = sdr->unr_thresh; + break; + case LCR_THRESH: + thresh_val = sdr->lc_thresh; + break; + case LNC_THRESH: + thresh_val = sdr->lnc_thresh; + break; + case LNR_THRESH: + thresh_val = sdr->lnr_thresh; + break; + case POS_HYST: + thresh_val = sdr->pos_hyst; + break; + case NEG_HYST: + thresh_val = sdr->neg_hyst; + break; + default: +#ifdef DEBUG + syslog(LOG_ERR, "get_sdr_thresh_val: reading unknown threshold val"); +#endif return -1; + } + + // y = (mx + b * 10^b_exp) * 10^r_exp + x = thresh_val; + + m_lsb = sdr->m_val; + m_msb = sdr->m_tolerance >> 6; + m = (m_msb << 8) | m_lsb; + + b_lsb = sdr->b_val; + b_msb = sdr->b_accuracy >> 6; + b = (b_msb << 8) | b_lsb; + + // exponents are 2's complement 4-bit number + b_exp = sdr->rb_exp & 0xF; + if (b_exp > 7) { + b_exp = (~b_exp + 1) & 0xF; + b_exp = -b_exp; + } + r_exp = (sdr->rb_exp >> 4) & 0xF; + if (r_exp > 7) { + r_exp = (~r_exp + 1) & 0xF; + r_exp = -r_exp; + } + + * (float *) value = ((m * x) + (b * pow(10, b_exp))) * (pow(10, r_exp)); + + return 0; +} + + + +/* + * Populate all fields of thresh_sensor_t struct for a particular sensor. + * Incase the threshold value is 0 mask the check for that threshvold + * value in flag field. + */ +static int +_sdr_get_snr_thresh(uint8_t fru, sdr_full_t *sdr, uint8_t snr_num, + uint8_t flag, thresh_sensor_t *snr) { + + int ret; + int value; + float fvalue; + uint8_t op, modifier; + + snr->flag = flag; + snr->curr_state = NORMAL_STATE; + + if (_sdr_get_sensor_name(sdr, snr->name)) { +#ifdef DEBUG + syslog(LOG_WARNING, "sdr_get_sensor_name: FRU %d: num: 0x%X: reading name" + " from SDR failed.", fru, snr_num); +#endif + return -1; + } + + // TODO: Add support for modifier (Mostly modifier is zero) + if (_sdr_get_sensor_units(sdr, &op, &modifier, snr->units)) { +#ifdef DEBUG + syslog(LOG_WARNING, "sdr_get_sensor_units: FRU %d: num 0x%X: reading units" + " from SDR failed.", fru, snr_num); +#endif + return -1; + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, UCR_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UCR_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->ucr_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, UCR_THRESH); + } + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, UNC_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNC_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->unc_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, UNC_THRESH); + } + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, UNR_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNR_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->unr_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, UNR_THRESH); + } + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, LCR_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LCR_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->lcr_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, LCR_THRESH); } + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, LNC_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNC_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->lnc_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, LNC_THRESH); + } + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, LNR_THRESH, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNR_THRESH", + fru, snr_num, snr->name); +#endif + } else { + snr->lnr_thresh = fvalue; + if (!(fvalue)) { + snr->flag = CLEARBIT(snr->flag, LNR_THRESH); + } + } - sdr = (sdr_full_t *) buf; - snr_num = sdr->sensor_num; - sinfo[snr_num].valid = true; - memcpy(&sinfo[snr_num].sdr, sdr, sizeof(sdr_full_t)); + if (get_sdr_thresh_val(fru, sdr, snr_num, POS_HYST, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, POS_HYST", + fru, snr_num, snr->name); +#endif + } else { + snr->pos_hyst = fvalue; + } + + if (get_sdr_thresh_val(fru, sdr, snr_num, NEG_HYST, &fvalue)) { +#ifdef DEBUG + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, NEG_HYST", + fru, snr_num, snr->name); +#endif + } else { + snr->neg_hyst = fvalue; } return 0; } +int +sdr_get_snr_thresh(uint8_t fru,uint8_t snr_num, uint8_t flag, + thresh_sensor_t *snr) { + + int ret = 0; + sdr_full_t *sdr; +#ifdef DEBUG + int cnt = 0; +#endif /* DEBUG */ + int retry = 0; + + sensor_info_t sinfo[MAX_SENSOR_NUM] = {0}; + + ret = pal_sensor_sdr_init(fru, sinfo); + + while (ret == ERR_NOT_READY) { + + if (retry++ > MAX_RETRIES_SDR_INIT) { + syslog(LOG_INFO, "sdr_get_snr_thresh: failed for fru: %d", fru); + return -1; + } +#ifdef DEBUG + syslog(LOG_INFO, "sdr_get_snr_thresh: fru: %d, ret: %d cnt: %d", fru, ret, cnt++); +#endif /* DEBUG */ + sleep(1); + ret = pal_sensor_sdr_init(fru, sinfo); + } + + + if (ret < 0) { + sdr = NULL; + } else { + sdr = &sinfo[snr_num].sdr; + } + + if (sdr != NULL) { + ret = _sdr_get_snr_thresh(fru, sdr, snr_num, flag, snr); + if (ret < 0) { +#ifdef DEBUG + syslog(LOG_ERR, "_sdr_get_snr_thresh failed for FRU: %d snr_num: %d", + fru, snr_num); +#endif + } + } else { + + snr->flag = flag; + ret = pal_get_sensor_name(fru, snr_num, snr->name); + ret = pal_get_sensor_units(fru, snr_num, snr->units); + ret = pal_get_sensor_threshold(fru, snr_num, UCR_THRESH, &(snr->ucr_thresh)); + if (!(snr->ucr_thresh)) { + snr->flag = CLEARBIT(snr->flag, UCR_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, UNC_THRESH, &(snr->unc_thresh)); + if (!(snr->unc_thresh)) { + snr->flag = CLEARBIT(snr->flag, UNC_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, UNR_THRESH, &(snr->unr_thresh)); + if (!(snr->unr_thresh)) { + snr->flag = CLEARBIT(snr->flag, UNR_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, LCR_THRESH, &(snr->lcr_thresh)); + if (!(snr->lcr_thresh)) { + snr->flag = CLEARBIT(snr->flag, LCR_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, LNC_THRESH, &(snr->lnc_thresh)); + if (!(snr->lnc_thresh)) { + snr->flag = CLEARBIT(snr->flag, LNC_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, LNR_THRESH, &(snr->lnr_thresh)); + if (!(snr->lnr_thresh)) { + snr->flag = CLEARBIT(snr->flag, LNR_THRESH); + } + ret = pal_get_sensor_threshold(fru, snr_num, POS_HYST, &(snr->pos_hyst)); + ret = pal_get_sensor_threshold(fru, snr_num, NEG_HYST, &(snr->neg_hyst)); + + } + + return ret; +} diff --git a/common/recipes-lib/sdr/files/sdr.h b/common/recipes-lib/sdr/files/sdr.h index c474fb1..c260914 100644 --- a/common/recipes-lib/sdr/files/sdr.h +++ b/common/recipes-lib/sdr/files/sdr.h @@ -23,21 +23,40 @@ #include <stdbool.h> #include <openbmc/ipmi.h> +#include <openbmc/pal.h> #ifdef __cplusplus extern "C" { #endif #define MAX_SDR_LEN 64 - +#define NORMAL_STATE 0x00 +#define MAX_SENSOR_NUM 0xFF #define MAX_SENSOR_RATE_UNIT 7 #define MAX_SENSOR_BASE_UNIT 92 -typedef struct _sensor_info_t { - bool valid; - sdr_full_t sdr; -} sensor_info_t; +#define SETBIT(x, y) (x | (1 << y)) +#define GETBIT(x, y) ((x & (1 << y)) > y) +#define CLEARBIT(x, y) (x & (~(1 << y))) +#define GETMASK(y) (1 << y) + +/* To hold the sensor info and calculated threshold values from the SDR */ +typedef struct { + uint8_t flag; + float ucr_thresh; + float unc_thresh; + float unr_thresh; + float lcr_thresh; + float lnc_thresh; + float lnr_thresh; + float pos_hyst; + float neg_hyst; + int curr_state; + char name[17]; + char units[64]; + +} thresh_sensor_t; /* List of all the Sensor Rate Units types. */ const char * sensor_rate_units[] = { @@ -150,11 +169,10 @@ const char * sensor_base_units[] = { "", /* 093 */ }; -int sdr_init(char *path, sensor_info_t *sinfo); - -int sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, - char *units); -int sdr_get_sensor_name(sdr_full_t *sdr, char *name); +int sdr_get_sensor_name(uint8_t fru, uint8_t snr_num, char *name); +int sdr_get_sensor_units(uint8_t fru, uint8_t snr_num, char *units); +int sdr_get_snr_thresh(uint8_t fru, uint8_t snr_num, uint8_t flag, + thresh_sensor_t *snr); #ifdef __cplusplus } // extern "C" diff --git a/common/recipes-lib/sdr/libsdr_0.1.bb b/common/recipes-lib/sdr/libsdr_0.1.bb index 958e0c6..73ebf3f 100644 --- a/common/recipes-lib/sdr/libsdr_0.1.bb +++ b/common/recipes-lib/sdr/libsdr_0.1.bb @@ -16,7 +16,7 @@ SRC_URI = "file://Makefile \ S = "${WORKDIR}" -DEPENDS += " libipmi " +DEPENDS += " libipmi libpal " do_install() { install -d ${D}${libdir} diff --git a/common/recipes-rest/cherryPy/cherryPy_3.8.0.bb b/common/recipes-rest/cherryPy/cherryPy_3.8.0.bb new file mode 100644 index 0000000..3c2179e --- /dev/null +++ b/common/recipes-rest/cherryPy/cherryPy_3.8.0.bb @@ -0,0 +1,14 @@ +DESCRIPTION = "CherryPy HTTP framework" +SECTION = "base" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://cherrypy/LICENSE.txt;md5=a476d86a3f85c89411ecaad012eed1e3" + +SRC_URI = "https://pypi.python.org/packages/source/C/CherryPy/CherryPy-${PV}.tar.gz" +SRC_URI[md5sum] = "542b96b2cd825e8120e8cd822bc18f4b" +SRC_URI[sha256sum] = "ffcdb43667d4098247efaf8c82dd36d3dd4f8e5dc768ef5e90b480899e523bea" + +S = "${WORKDIR}/CherryPy-${PV}" + +inherit setuptools + +FILES_${PN} += "/usr/lib/* /usr/share/cherrypy" diff --git a/common/recipes-rest/rest-api/files/node_server.py b/common/recipes-rest/rest-api/files/node_server.py index 57a5c42..cf64f03 100644 --- a/common/recipes-rest/rest-api/files/node_server.py +++ b/common/recipes-rest/rest-api/files/node_server.py @@ -56,7 +56,7 @@ class serverNode(node): else: res = 'success' - result = { "result": res } + result = { "result": res } return result @@ -64,6 +64,9 @@ def get_node_server(num): actions = ["power-on", "power-off", "power-cycle", - "graceful-shutdown" + "graceful-shutdown", + "12v-on", + "12v-off", + "12v-cycle" ] return serverNode(num = num, actions = actions) diff --git a/common/recipes-rest/rest-api/files/pal.py b/common/recipes-rest/rest-api/files/pal.py index 8faef30..f0e076d 100644 --- a/common/recipes-rest/rest-api/files/pal.py +++ b/common/recipes-rest/rest-api/files/pal.py @@ -67,6 +67,14 @@ def pal_set_server_power(slot_id, command): cmd.value = 2 elif command == 'graceful-shutdown': cmd.value = 3 + elif command == '12v-off': + cmd.value = 4 + elif command == '12v-on': + cmd.value = 5 + elif command == '12v-cycle': + cmd.value = 6 + else: + return -1 ret = lpal_hndl.pal_set_server_power(slot_id, cmd) if ret: return -1 diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py deleted file mode 100644 index 7c126d9..0000000 --- a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/python -tt -# Copyright 2015-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 - -from board_gpio_table import board_gpio_table -from soc_gpio_table import soc_gpio_table - -import openbmc_gpio -import openbmc_gpio_table - -import logging -import sys - - -def setup_board_gpio(soc_gpio_table, board_gpio_table, validate=True): - soc = openbmc_gpio_table.SocGPIOTable(soc_gpio_table) - gpio_configured = [] - for gpio in board_gpio_table: - try: - soc.config_function(gpio.gpio, write_through=False) - gpio_configured.append(gpio.gpio) - except openbmc_gpio_table.ConfigUnknownFunction as e: - # not multiple-function GPIO pin - pass - except openbmc_gpio_table.NotSmartEnoughException as e: - logging.error('Failed to configure "%s" for "%s": %s' - % (gpio.gpio, gpio.shadow, str(e))) - - soc.write_to_hw() - - if validate: - all_functions = set(soc.get_active_functions(refresh=True)) - for gpio in gpio_configured: - if gpio not in all_functions: - raise Exception('Failed to configure function "%s"' % gpio) - - for gpio in board_gpio_table: - openbmc_gpio.gpio_export(gpio.gpio, gpio.shadow) - if gpio.value == openbmc_gpio_table.GPIO_INPUT: - continue - elif gpio.value == openbmc_gpio_table.GPIO_OUT_HIGH: - openbmc_gpio.gpio_set(gpio.gpio, 1) - elif gpio.value == openbmc_gpio_table.GPIO_OUT_LOW: - openbmc_gpio.gpio_set(gpio.gpio, 0) - else: - raise Exception('Invalid value "%s"' % gpio.value) - -def main(): - print('Setting up GPIOs ... ', end='') - sys.stdout.flush() - openbmc_gpio.setup_shadow() - setup_board_gpio(soc_gpio_table, board_gpio_table) - print('Done') - sys.stdout.flush() - return 0 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py index dda8a98..d188dcb 100644 --- a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py @@ -21,6 +21,7 @@ from __future__ import unicode_literals from soc_gpio import soc_get_register +import openbmc_gpio import logging import os import sys @@ -267,3 +268,36 @@ class BoardGPIO(object): self.gpio = gpio self.shadow = shadow self.value = value + +def setup_board_gpio(soc_gpio_table, board_gpio_table, validate=True): + soc = SocGPIOTable(soc_gpio_table) + gpio_configured = [] + for gpio in board_gpio_table: + try: + soc.config_function(gpio.gpio, write_through=False) + gpio_configured.append(gpio.gpio) + except ConfigUnknownFunction as e: + # not multiple-function GPIO pin + pass + except NotSmartEnoughException as e: + logging.error('Failed to configure "%s" for "%s": %s' + % (gpio.gpio, gpio.shadow, str(e))) + + soc.write_to_hw() + + if validate: + all_functions = set(soc.get_active_functions(refresh=True)) + for gpio in gpio_configured: + if gpio not in all_functions: + raise Exception('Failed to configure function "%s"' % gpio) + + for gpio in board_gpio_table: + openbmc_gpio.gpio_export(gpio.gpio, gpio.shadow) + if gpio.value == GPIO_INPUT: + continue + elif gpio.value == GPIO_OUT_HIGH: + openbmc_gpio.gpio_set(gpio.gpio, 1) + elif gpio.value == GPIO_OUT_LOW: + openbmc_gpio.gpio_set(gpio.gpio, 0) + else: + raise Exception('Invalid value "%s"' % gpio.value) diff --git a/common/recipes-utils/openbmc-gpio/files/setup.py b/common/recipes-utils/openbmc-gpio/files/setup.py index 59c7de4..bf7be3d 100644 --- a/common/recipes-utils/openbmc-gpio/files/setup.py +++ b/common/recipes-utils/openbmc-gpio/files/setup.py @@ -18,6 +18,7 @@ from distutils.core import setup +from setup_board import board_py_modules setup( name = 'openbmc-gpio', @@ -31,6 +32,6 @@ setup( 'phymemory', 'soc_gpio', 'soc_gpio_table', - 'board_gpio_table', - ], + 'board_gpio_table', ] + + board_py_modules , ) diff --git a/common/recipes-utils/openbmc-gpio/files/setup_board.py b/common/recipes-utils/openbmc-gpio/files/setup_board.py new file mode 100644 index 0000000..aff7398 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/setup_board.py @@ -0,0 +1,23 @@ +# Copyright 2015-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 + +# This is a dummy board GPIO table. If this is included in the final image, +# please double check the configuration of your image to define the correct +# GPIO table to be used for your board. + +board_py_modules = [ +] diff --git a/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb index 6bf4cc1..a2b46d4 100644 --- a/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb +++ b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb @@ -25,12 +25,12 @@ SRC_URI = " \ file://board_gpio_table.py \ file://openbmc_gpio.py \ file://openbmc_gpio_table.py \ - file://openbmc_gpio_setup.py \ file://openbmc_gpio_util.py \ file://phymemory.py \ file://setup.py \ file://soc_gpio.py \ file://soc_gpio_table.py \ + file://setup_board.py \ " S = "${WORKDIR}" @@ -41,9 +41,6 @@ OPENBMC_GPIO_UTILS = " \ OPENBMC_GPIO_SOC_TABLE = "soc_gpio_table.py" -# Change OPENBMC_GPIO_SETUP to "0" to exclude openbmc_gpio_setup.py from the image -OPENBMC_GPIO_SETUP = "1" - inherit distutils DEPENDS_${PN} = "python python-distribute update-rc.d-native" @@ -63,13 +60,5 @@ do_install_append() { for f in ${OPENBMC_GPIO_UTILS}; do install -m 755 $f ${localbindir}/${f} done - - install -d ${D}${sysconfdir}/init.d - install -d ${D}${sysconfdir}/rcS.d - if [ "${OPENBMC_GPIO_SETUP}" == "1" ]; then - install -m 755 openbmc_gpio_setup.py ${D}${sysconfdir}/init.d/openbmc_gpio_setup.py - update-rc.d -r ${D} openbmc_gpio_setup.py start 59 S . - fi } -FILES_${PN} += "/usr/local/bin ${sysconfdir}" diff --git a/common/recipes-utils/spatula/files/setup-spatula.sh b/common/recipes-utils/spatula/files/setup-spatula.sh index 391a212..238f395 100644 --- a/common/recipes-utils/spatula/files/setup-spatula.sh +++ b/common/recipes-utils/spatula/files/setup-spatula.sh @@ -31,7 +31,7 @@ . /etc/init.d/functions ACTION="$1" -CMD="/usr/local/bin/spatula_wrapper.py" +CMD="/usr/local/bin/spatula_wrapper.py --lldp" case "$ACTION" in start) echo -n "Setting up Spatula: " diff --git a/common/recipes-utils/spatula/files/spatula_wrapper.py b/common/recipes-utils/spatula/files/spatula_wrapper.py index 2717bef..770e4e8 100644 --- a/common/recipes-utils/spatula/files/spatula_wrapper.py +++ b/common/recipes-utils/spatula/files/spatula_wrapper.py @@ -24,35 +24,81 @@ import os import subprocess import time import argparse +import re SPATULA_FILE = '/etc/spatula/spatula' +LLDP_UTIL = '/usr/bin/lldp-util' LOG_FORMAT = '[%(levelname)s] %(asctime)s: %(message)s' DATE_FORMAT = '%Y-%m-%d %H:%M:%S' DEFAULT_SLEEP = 900 # default sleep 15 mins +DEFAULT_PORT = 8087 +DEFAULT_INTERFACE = 'usb0' class SpatulaWrapper(object): def __init__(self, address='fe80::2', interface='usb0', - port=8087, ssl=False): - proto = 'http' - if ssl: - proto = 'https' + port=8087, tls=False, lldp=False): + self.interface = interface + self.lldp = lldp + self.port = port + self.proto = 'http' + if tls: + self.proto = 'https' + # not used if auto-discovering self.url = '{proto}://{address}%{iface}:{port}'.format( - proto = proto, + proto = self.proto, address = address, - iface = interface, - port = port) + iface = self.interface, + port = self.port) + + def _getLldpMessage(self): + try: + if os.path.exists(LLDP_UTIL): + # request a single packet and time out in 30 seconds + lldp = subprocess.Popen([LLDP_UTIL, '-n', '4', '-t', '30'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + found = [] + for line in lldp.stdout: + # example (one line): + # LLDP: local_port=eth0 \ + # remote_system=rsw1bz.19.snc1.facebook.com \ + # remote_port=00:90:fb:52:1a:49 + if line.startswith('LLDP: '): + matches = re.findall(r'\w+=\S+', line.replace('LLDP: ', '')) + matches = [m.split('=', 1) for m in matches] + found.append(dict(matches)) + if not found: + raise Exception('timed out waiting for LLDP packet') + # dedupe before returning since we may get multiple packets + # from the same device + return [dict(t) for t in set([tuple(d.items()) for d in found])] + else: + raise Exception('missing lldp-util: {}'.format(LLDP_UTIL)) + except Exception as err: + raise Exception('failed discovering management system via LLDP: {}'.format(err)) def _getSpatula(self, endpoint='/spatula'): ''' Get the executable spatula script from the host. ''' - url = '{}{}'.format(self.url, endpoint) - try: - request = urllib2.Request(url) - response = urllib2.urlopen(request) - return response.read() - except Exception as err: - raise Exception('failed getting Spatula {}: {}'.format(url, err)) + urls = [] + urls.append('{}{}'.format(self.url, endpoint)) + if self.lldp: + for lldp in self._getLldpMessage(): + urls.append('{proto}://{address}%{iface}:{port}{endpoint}'.format( + proto = self.proto, + address = lldp['remote_system'], + iface = lldp['local_port'], + port = self.port, + endpoint = endpoint)) + for url in urls: + try: + request = urllib2.Request(url) + response = urllib2.urlopen(request) + return response.read() + except Exception as err: + continue + raise Exception('failed getting Spatula {}: {}'.format(urls, err)) def _success(self, endpoint='/success'): ''' @@ -114,7 +160,18 @@ if __name__ == '__main__': args = argparse.ArgumentParser() args.add_argument('-s', '--sleep', default=DEFAULT_SLEEP, help='Sleep time between spatula runs (default=%(default)s)') + args.add_argument('--interface', '-i', default=DEFAULT_INTERFACE, + help='Interface to use for management system') + args.add_argument('--port', '-p', default=DEFAULT_PORT, + help='Port to contact on management system') + args.add_argument('--lldp', default=False, action="store_true", + help='Automatically discover management system with LLDP') + args.add_argument('--tls', default=False, action="store_true", + help='Connect to bmc_proxy using TLS') params = args.parse_args() logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT) - wrapper = SpatulaWrapper() + wrapper = SpatulaWrapper(interface=params.interface, + tls=params.tls, + port=params.port, + lldp=params.lldp) wrapper.run(params.sleep) |