【C5】bmc wtd,post
文章目录
- 1.bmc_wtd_cpld:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAME
 - 2.AST芯片WDT切换主备:BMC用WDT2作为主备切换的控制器
 - 2.1 AC后读取:bmc处于主primary flash(设完后:实际主,wtd1主,wtd2主)
 - 2.2 切换spi备:wtd2的2c寄存器设为0x93,换另一个flash后reboot后从备起(设完后:实际备,wtd1主,wtd2备)
 - 2.3 用WDT1切主:(设完后:实际备,wtd1备,wtd2备)
 - 2.4 用WDT2切主:(设完后:实际备,wtd1备,wtd2主)
 - 2.5 用WDT1切主:(设完后:实际主,wtd1主,wtd2主)
 - 2.6 关于清空寄存器:(设完后:WTD1主,WTD2主,实际主)
 - 2.7 结论:从主切到备,需要一个wdt的status是default也就是0的wdt,然后用0x93切换
 
- 3.BMC喂狗实现:sys/class/gpio/gpio1/value获取gpio1值
 - 3.1 watch-dog.h
 - watch-dog.c
 - main.c
 - Makefile
 - run-watch-dog.sh
 - setup-watch-dog.sh
 - watch-dog_0.1.bb
 
- 4.post code
 
1.bmc_wtd_cpld:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAME

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
WATCHDOG_LOG="/tmp/watchdog.log"usage(){program=$(basename "$0")echo "Usage:"echo "$program <operation>"echo "  <operation>  : start stop kick query restart"echo "Examples:"echo "  $program start"echo ""
}kick()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}enable()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" != "0x1" ];thenecho "0x1" > /sys/bus/i2c/devices/0-000d/wd_enelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" > $WATCHDOG_LOG
}disable()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x0" > /sys/bus/i2c/devices/0-000d/wd_enecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}check_parameter()
{if [ $# -ne 1 ];thenusageexitficase ${1} in"start" | "stop" | "kick" |"query" |"restart");;*)  #除上面的其他的usageexit;;esac
}check_parameter "$@"case ${1} in"start")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekick;;"stop")disableexit;;"kick")kickexit;;"restart")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekickexit;;"query")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "ENABLE"elseecho "DISABLE"fiexit;;
esacwhile true
doret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenkickfisleep 30
doneroot@bmc-oob:~# ps | grep wd588 root      2904 S    runsv /etc/sv/wd591 root      3036 S    {wd} /bin/bash /usr/local/bin/wd start779 root      3036 S    grep wd
root@bmc-oob:~# wd query
ENABLE
root@bmc-oob:~# wd stop
root@bmc-oob:~# wd query
DISABLE
root@bmc-oob:~# wd restart
root@bmc-oob:~# wd kick
root@bmc-oob:~# wd query
ENABLEinit()
{ret=$(ps |grep crond|grep -v grep)if [ "x$ret" = "x" ];thenecho "No found crond process"exitfiif [ ! -d /crontabs ];thenmkdir /crontabstouch /crontabs/rootficrontab -c /etc/cron/crontabs/ /etc/cron/crontabs/rootcp /var/log/watchdog.sh /usr/local/bin/watchdog.sh
}add_task()
{echo "* * * * * /usr/local/bin/watchdog.sh kick" >> /etc/cron/crontabs/rootecho "* * * * * date >> /var/log/date.log" >> /etc/cron/crontabs/root
}del_task()
{sed -i "/\* \* \* \* \* \/usr\/local\/bin\/watchdog.sh kick/d" /etc/cron/crontabs/root  #最后一个d代表删除
}
 
2.AST芯片WDT切换主备:BMC用WDT2作为主备切换的控制器
2.1 AC后读取:bmc处于主primary flash(设完后:实际主,wtd1主,wtd2主)

 如下0x100(十六进制,不是二进制)代表default flash,offset为30寄存器。
 
 
 
2.2 切换spi备:wtd2的2c寄存器设为0x93,换另一个flash后reboot后从备起(设完后:实际备,wtd1主,wtd2备)

 
 
 
 如下202第1位(不是第0位)和第9位置为1,发现这时确实WDT2可控,当前在备flash启动。
 
2.3 用WDT1切主:(设完后:实际备,wtd1备,wtd2备)

 
 
 如下10是wdt1状态寄存器,30是wdt2状态寄存器。302和202第1位都为1即second boot code。
 
2.4 用WDT2切主:(设完后:实际备,wtd1备,wtd2主)

 
2.5 用WDT1切主:(设完后:实际主,wtd1主,wtd2主)

 
 
2.6 关于清空寄存器:(设完后:WTD1主,WTD2主,实际主)

 
 wdt1和wdt2都切到备flash。
 
 如下clear寄存器清除wdt1的status,保留了reset次数,但是将code source(主备)清除为0(主)。
 
 再用wdt2切换主。
 
 这次切到了主。
 
 用wdt1切换到备。
 
 清空wdt1的status。这时如果用我们的测试脚本bootsource会判断是在主,其实是在备。
 
 尝试wdt1用0x13切换主,成功切到主。
 
 
2.7 结论:从主切到备,需要一个wdt的status是default也就是0的wdt,然后用0x93切换
从备切到主,需要满足两(三)个wdt中都从备切到主。比如wdt1是备,wdt2是备,那要对wdt1,wdt2都设一次0x93。如果wdt1,wdt2中一个是备,那对对应的wdt设0x93。
还有因为清空寄存器造成的虽然在备,但是wdt都是显示在主,这时候用0x13就可以切到主。用wdt2进行切换主备。避免使用清空寄存器0x14/0x34。
a=0x00000100 #256 (1 0000 0000)
b=$(( ((a & 0xff00) >> 8 ) ))
c=$((a & 0xff00))
d=$((a >> 8))
echo $b
echo $c
echo $d
# $ ./a.sh 
# 1
# 256
# 1# 检查当前BMC是在主还是备启动的检查函数boot_source实现如下:
check_boot_source()
{# WDT1 is on page 646 of ast2500v16.pdf# and WDT2 is on page 649 of ast2500v16.pdf# get watch dog1 timeout status registerwdt1=$(devmem 0x1e785010)# get watch dog2 timeout status registerwdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) ))  #取出高8位,自动转为十进制wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))wdt1_boot_code_source=$(( ((wdt1 & 0x2) >> 1) )) #取出第1位(不是第0)wdt2_boot_code_source=$(( ((wdt2 & 0x2) >> 1) ))boot_code_source=0# Check both WDT1 and WDT2 to indicate the boot sourceif [ $wdt1_timeout_cnt -ge 1 ] && [ $wdt1_boot_code_source -eq 1 ]; thenboot_code_source=1elif [ $wdt2_timeout_cnt -ge 1 ] && [ $wdt2_boot_code_source -eq 1 ]; thenboot_code_source=1fiecho $boot_code_source
}bmc_boot_info() {wdt1=$(devmem 0x1e785010)wdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) ))wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))boot_code_source=$(check_boot_source)boot_source="Master Flash"if [ $((boot_code_source)) -eq 1 ]; thenboot_source="Slave Flash"fiecho "WDT1 Timeout Count: " $wdt1_timeout_cntecho "WDT2 Timeout Count: " $wdt2_timeout_cntecho "Current BMC Boot Code Source: $boot_source"
}bmc_boot_from() {# Enable watchdog reset_system_after_timeout bit and WDT_enable_signal bit.# Refer to ast2500v16.pdf page 650th.boot_source=0x00000013boot_code_source=$(check_boot_source)if [ "$1" = "master" ]; thenif [ $((boot_code_source)) -eq 0 ]; thenecho "Current boot source is master, no need to switch."return 0fi# Set bit_7 to 0 : Use default boot code whenever WDT reset.boot_source=0x00000033elif [ "$1" = "slave" ]; thenif [ $((boot_code_source)) -eq 1 ]; thenecho "Current boot source is slave, no need to switch."return 0fi# No matter BMC boot from any one of master and slave.# Set bit_7 to 1 : Use second boot code whenever WDT reset.# And the sencond boot code stands for the other boot source.boot_source=0x000000b3fiecho "BMC will switch to $1 after 10 seconds..."/usr/local/bin/watch-dog stop# Clear WDT1 counter and boot code source statusdevmem 0x1e785014 w 0x77# Clear WDT2 counter and boot code source statusdevmem 0x1e785034 w 0x77# Set WDT time out 10s, 0x00989680 = 10,000,000 usdevmem 0x1e785024 32 0x00989680# WDT magic number to restart WDT counter to decrease.devmem 0x1e785028 32 0x4755devmem 0x1e78502c 32 $boot_source
}
 
3.BMC喂狗实现:sys/class/gpio/gpio1/value获取gpio1值

 bmc喂狗gpio硬件管脚:
 
 
 bmc监听gpio中断硬件管脚:
 
 
 
 
 
导出GPIO:echo $gpio_num > /sys/class/gpio/exporteg: echo 1 > /sys/class/gpio/export执行完以上命令后,如果该gpio接口存在且未被占用则会出现如下目录:/sys/class/gpio/gpio1设置方向:gpio的方向分为两类:in和outin:表示该gpio用于输入。(如该gpio连接一个按钮)out:表示该gpio用于输出。(如该gpio连接一个led灯)指定为in模式的命令:echo in > /sys/class/gpio/gpio1/direction指定为out模式的命令如下:echo out > /sys/class/gpio/gpio1/direction //默认value为0echo low > /sys/class/gpio/gpio1/direction //指定方向为out且value为0echo high > /sys/class/gpio/gpio1/direction //指定方向为out且value为1设置高低:只用当方向为out模式时才能指定gpio接口的电压的高低。这个很容易理解,因为如果是in模式的话,它的电平高低取决于所连接外设的电平高低,我们只能读取它的值,不能更改它的值echo 1 > /sys/class/gpio/gpio1/value //指定gpio1为高电平echo 0 > /sys/class/gpio/gpio1/value //指定gpio1为低电平    
 

 
3.1 watch-dog.h

#ifndef SENSOR_MON__h
#define SENSOR_MON__h#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h> 
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include <stdarg.h>
#include <syslog.h>
#include <openbmc/libgpio.h>
#include <fcntl.h>
#include <stdbool.h>
#include <poll.h>
#include <ctype.h>
#include <assert.h>
#include <libgen.h>
#include <linux/limits.h>//#define GPIO_KICK_NUM    885
//#define GPIO_KICK_NAME   "GPIOL5"
#define WDT_MASK_PATH "/sys/bus/i2c/devices/82-000d/bmc_wdt_mask"
#define GPIO_KICK_SHADOW "BMC_CPLD_GPIO69_WDO"typedef enum {WD_FUNC_START,  //0WD_FUNC_STOP,WD_FUNC_KICK,WD_FUNC_UNKNOWN,
} wd_func;typedef enum {MASK_ENABLE = 1,MASK_DISABLE = 0,
} wd_mask;// 如下LOG替换syslog , syslog像printf定义在<syslog.h>, 打印在/var/log/message
#define LOG(mode,format, ...)   syslog(mode, format, __VA_ARGS__)int bmc_wd_set(wd_mask value);
void feed_dog_func();#endif
 
watch-dog.c
#include "watch-dog.h"int bmc_wd_set(wd_mask value){   // bmc设置cpld寄存器控制wtd芯片(是外置芯片,不是bmc芯片内置的)开关FILE* pFile = fopen(WDT_MASK_PATH, "w");char regvalue[4]= {0};int ret = 0;if(value == MASK_DISABLE){ // 0sprintf(regvalue,"0x0");}else if(value == MASK_ENABLE){sprintf(regvalue,"0x1");}ret = fwrite(regvalue, sizeof(regvalue) , 1, pFile );  //ret为次数即fwrite中的1if(ret==1){fflush(pFile);ret = 0;}else{ret = -1;}fclose(pFile);return ret;
}void feed_dog_func()   // bmc通过gpio的0.5s高低电平来喂狗
{int ret = 0;struct timespec n_sleep;n_sleep.tv_sec = 0; //secondes, integer part sleep duration    // 整数n_sleep.tv_nsec = 5e8L; //nanoseconds, decimal part sleep duration   // 小数  0.5s(上行整数0,这行小数5)gpio_desc_t* desc = gpio_open_by_shadow(GPIO_KICK_SHADOW);  // libgpio-ctrl.so中的接口if (!desc) {syslog(LOG_INFO ,"gpio_open_by_shadow fail\n");return ;}ret = gpio_set_direction(desc, GPIO_DIRECTION_OUT);if (ret == -1){syslog(LOG_ERR ,"gpio_change_direction err \n");gpio_close(desc);return ;}ret = gpio_set_edge(desc, GPIO_EDGE_NONE);if (ret == -1){syslog(LOG_ERR ,"gpio_change_edge err \n");gpio_close(desc);return ;}
//BMC启动时,喂狗(硬件gpio管脚,每隔500ms翻转一次高低电平),并关闭中断MASK如下:
//cmm cpld 0X71 地址 bit0 是中断MASK (为1时MASK使能即看门狗关闭;为0时MASK失效即看门狗打开)
//i2cset -f -y 82 0xd 0x71 0xfe 做成bmc_wdt_mask节点ret=bmc_wd_set(MASK_DISABLE);  // 0开wtdif(ret == 0){syslog(LOG_INFO ,"bmc_wd_set OK\n");}else{syslog(LOG_ERR ,"bmc_wd_set Fail\n");gpio_close(desc);return;}while(1){gpio_set_value(desc,GPIO_VALUE_HIGH);nanosleep(&n_sleep, NULL);  // 0.5s 高电平gpio_set_value(desc,GPIO_VALUE_LOW);nanosleep(&n_sleep, NULL);   // 0.5s 低电平}gpio_close(desc);return ;
}
 
main.c
#include "watch-dog.h"int func_start()
{int ret = 0;ret=bmc_wd_set(MASK_DISABLE);  //mask和disable都是否定if(ret == 0){syslog(LOG_INFO ,"func_start OK\n");}else{syslog(LOG_ERR ,"func_start Fail\n");return -1;}return 0;
}int func_stop()
{int ret = 0;ret=bmc_wd_set(MASK_ENABLE);if(ret == 0){syslog(LOG_INFO ,"func_stop OK\n");}else{syslog(LOG_ERR ,"func_stop Fail\n");return -1;}return 0;
}void usage(void)
{fprintf(stderr, "usage: watch-dog <start/stop/kick> \n");exit (1);
}int func_kick()
{int rc,ret,pid_file;int pid_value;char piddata[12];char file_path[60];pthread_t tid_feed;ret = snprintf(file_path, sizeof(file_path), "/var/run/watch_dog.pid");  // /var/run/a 也可以,记录当前进程pid号if ((ret < 0) || (ret >= sizeof(file_path))) {syslog(LOG_ERR ,"watch_dog:too long for lockfile\n");return -1;}pid_file = open(file_path, O_CREAT | O_RDWR, 0666);if (pid_file < 0) {syslog(LOG_ERR ,"watch_dog: failed to acquire lock\n");exit(1);}else{pid_value=getpid();snprintf(piddata, sizeof(piddata), "%d\n", pid_value);ret=write(pid_file, piddata, sizeof(piddata));  //先open再writeif(ret < 0) {syslog(LOG_ERR ,"watch_dog: write pid err\n");}}rc = flock(pid_file, LOCK_EX | LOCK_NB); // Linux文件锁flock: 检测进程是否已经存在if(rc){if(EWOULDBLOCK == errno){syslog(LOG_ERR ,"Another watch_dog instance is running...\n");exit(1);}}syslog(LOG_INFO ,"watch_dog: daemon started\n");pthread_create(&tid_feed,NULL,(void *)feed_dog_func,NULL);  //一个pthread_create只创建一个线程pthread_join(tid_feed,NULL);if (pid_file >= 0) {unlink(file_path);  //#include<unistd.h> , unlink删除文件}syslog(LOG_INFO ,"watch_dog: daemon end\n");return 0;
}wd_func wd_func_judge(char * desc)
{if (!strcmp(desc, "start")){   // strcmp相同返回0,if(1)执行,shell中if(0)执行return WD_FUNC_START;}else if (!strcmp(desc, "stop")){return WD_FUNC_STOP;}else if (!strcmp(desc, "kick")){return WD_FUNC_KICK;}return WD_FUNC_UNKNOWN;
}int main(int argc, char* argv[])
{wd_func wd_func_sel = WD_FUNC_UNKNOWN;if (argc != 2) {usage();}wd_func_sel = wd_func_judge(argv[1]);if ( wd_func_sel == WD_FUNC_UNKNOWN ){usage();}switch (wd_func_sel){case WD_FUNC_START :func_start();break;case WD_FUNC_STOP :func_stop();break;case WD_FUNC_KICK :func_kick();break;default :break;}return 0;
}
 
Makefile
#
all: watch-dog
SRC = $(wildcard ./*.c)
CFLAGS += -Wall -Werror -D _XOPEN_SOURCE -pthread -lm -std=c99watch-dog: $(SRC)$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS).PHONY: cleanclean:rm -rf *.o watch-dog
 
run-watch-dog.sh
exec /usr/local/bin/watch-dog kick
 
setup-watch-dog.sh
WDTFUNC=/usr/local/bin/watch-dog
# /etc/init.d/setup-watch-dog.sh: start and stop the watch-dog
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/local/bin"
case "$1" instart)echo -n "Starting watch dog kick daemon..."runsv /etc/sv/watch-dog > /dev/null 2>&1 &  # runsv找/etc/sv/watch-dog/run文件运行echo "done.";;stop)echo -n "Stopping watch dog daemon..."$WDTFUNC stop > /dev/null 2>&1 &echo "done.";;*)echo "Usage: /etc/init.d/setup-watch-dog.sh {start|stop}"exit 1;;
esac
exit 0
 
watch-dog_0.1.bb
SUMMARY = "watch dog Daemon"
DESCRIPTION = "Daemon for watch dog"
SECTION = "base"
PR = "r1"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
SRC_URI = "file://COPYING \file://main.c \file://watch-dog.c \file://watch-dog.h \file://Makefile \file://setup-watch-dog.sh \file://run-watch-dog.sh \"
S = "${WORKDIR}"
binfiles = "watch-dog \"
pkgdir = "watch-dog"
LDFLAGS = "-lgpio-ctrl"
DEPENDS += "libgpio-ctrl update-rc.d-native"
RDEPENDS_${PN} += "libgpio-ctrl bash"install_sysv() {install -d ${D}${sysconfdir}/init.dinstall -d ${D}${sysconfdir}/rcS.dinstall -d ${D}${sysconfdir}/svinstall -d ${D}${sysconfdir}/sv/watch-doginstall -d ${D}${sysconfdir}/watch-doginstall -m 755 setup-watch-dog.sh ${D}${sysconfdir}/init.d/setup-watch-dog.shinstall -m 755 run-watch-dog.sh ${D}${sysconfdir}/sv/watch-dog/run  #将run-watch-dog.sh复制到/etc/sv/watch-dog/run文件里update-rc.d -r ${D} setup-watch-dog.sh defaults 93 5  #defaults :开机自动执行setup-watch-dog.sh start ,reboot自动执行setup-watch-dog.sh stop
}do_install() {dst="${D}/usr/local/fbpackages/${pkgdir}"bin="${D}/usr/local/bin"install -d $dstinstall -d $binfor f in ${binfiles}; doinstall -m 755 $f ${dst}/$fln -snf ../fbpackages/${pkgdir}/$f ${bin}/$fdoneinstall_sysv
}FBPACKAGEDIR = "${prefix}/local/fbpackages"
FILES_${PN} = "${FBPACKAGEDIR}/watch-dog ${prefix}/local/bin ${sysconfdir}"
 
4.post code

// obmc-pal.c
/* IPMI SEL: System Firmware Error string table */
struct system_fw_progress {uint8_t EventData1;char DecodeString[128];
};struct system_fw_progress system_fw_error[] = {{0x00, "Unspecified"},   // 一个{}就是一个system_fw_progress结构体,129字节{0x01, "No system memory is physically installed in the system"},{0x02, "No usable system memory, all installed memory has experienced an unrecoverable failure"}, // 88字节{0x03, "Unrecoverable hard-disk/ATAPI/IDE device failure"},{0x04, "Unrecoverable system-board failure"},{0x05, "Unrecoverable diskette subsystem failure"},{0x06, "Unrecoverable hard-disk controller failure"},{0x07, "Unrecoverable PS/2 or USB keyboard failure"},{0x08, "Removable boot media not found"},{0x09, "Unrecoverable video controller failure"},{0x0A, "No video device detected"},{0x0B, "Firmware (BIOS) ROM corruption detected"},{0x0C, "CPU voltage mismatch"},{0x0D, "CPU speed matching failure"},
};struct system_fw_progress system_fw_hang_or_progress[] = {{0x00, "Unspecified"},{0x01, "Memory initialization"},{0x02, "Hard-disk initialization"},{0x03, "Secondary processor(s) initialization"},{0x04, "User authentication"},{0x05, "User-initiated system setup"},{0x06, "USB resource configuration"},{0x07, "PCI resource configuration"},{0x08, "Option ROM initialization"},{0x09, "Video initialization"},{0x0A, "Cache initialization"},{0x0B, "SM Bus initialization"},{0x0C, "Keyboard controller initialization"},{0x0D, "Embedded controller/management controller initialization"},{0x0E, "Docking station attachment"},{0x0F, "Enabling docking station"},{0x10, "Docking station ejection"},{0x11, "Disabling docking station"},{0x12, "Calling operating system wake-up vector"},{0x13, "Starting operating system boot process, e.g. calling Int 19h"},{0x14, "Baseboard or motherboard initialization"},{0x15, "reserved"},{0x16, "Floppy initialization"},{0x17, "Keyboard test"},{0x18, "Pointing device test"},{0x19, "Primary processor initialization"},
};uint8_t *ed = &event_data[3];char temp_log[512] = {0};char add_sol_log_com[512] = "logger -p local3.info ";case POST_ERROR:if (((ed[0] >> 6) & 0x03) == 0x3) {  // table29 eventdata1第6和7位为11switch (ed[0] & 0xF) { // table29取eventdata1低四位case 0x00: // sensor offsetstrcat(error_log, "System Firmware Error (POST Error), IPMI Post Code"); // 50字节if (ed[1] <  (sizeof(system_fw_error) / sizeof(system_fw_error[0]))) { // 13*129/129=0x0dsprintf(temp_log, ", %s", system_fw_error[ed[1]].DecodeString); // 88字节,ed[1]即eventdata2} else {sprintf(temp_log, ", reserved");}break;case 0x01:strcat(error_log, "System Firmware Hang, IPMI Post Code");case 0x02:if (strcmp(error_log, "") == 0) {strcat(error_log, "System Firmware Progress, IPMI Post Code");}if (ed[1] <  (sizeof(system_fw_hang_or_progress) / sizeof(system_fw_hang_or_progress[0]))) {sprintf(temp_log, ", %s", system_fw_hang_or_progress[ed[1]].DecodeString);} else {sprintf(temp_log, ", reserved");}break;default:sprintf(temp_log, "Unknown");break;}strcat(error_log, temp_log); //138// send post code sel to sol logsprintf(temp_log, " '%s' ", error_log);strcat(add_sol_log_com, temp_log);system(add_sol_log_com);break;
 

 
相关文章:
【C5】bmc wtd,post
文章目录1.bmc_wtd_cpld:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAME2.AST芯片WDT切换主备:BMC用WDT2作为主备切换的控制器2.1 AC后读取:bmc处于主primary flash(设完后:实际主&…...
200.Spark(七):SparkSQL项目实战
一、启动环境 需要启动mysql,hadoop,hive,spark。并且能让spark连接上hive(上一章有讲) #启动mysql,并登录,密码123456 sudo systemctl start mysqld mysql -uroot -p#启动hive cd /opt/module/ myhadoop.sh start#查看启动情况 jpsall#启动hive cd /opt/module/hive/…...
区块链系统:挖矿原理
在比特币的P2P网络中,有一类节点,它们时刻不停地进行计算,试图把新的交易打包成新的区块并附加到区块链上,这类节点就是矿工。因为每打包一个新的区块,打包该区块的矿工就可以获得一笔比特币作为奖励。所以,…...
【博弈】【清华冬令营2018模拟】取石子
写完敢说全网没有这么详细的题解了。 注意:题解长是为了方便理解,所以读起来速度应该很快。 题目描述 有 nnn 堆石子,第 iii 堆有 xix_ixi 个。 AliceAliceAlice 和 BobBobBob 轮流去石子(先后手未定), …...
嵌入式:BSP的理解
BSP概念总结BSP定义BSP的特点BSP的主要工作BSP在嵌入式系统和Windowsx系统中的不同BSP和PC机主板上的BIOS区别BSP与 HAL关系嵌入式计算机系统主要由 硬件层,中间层,系统软件层和应用软件层四层组成。硬件层:包含CPU,存储器(SDRAM&…...
Linux主机Tcpdump使用-centos实例
1、安装前系统信息 ifconfig查看系统网络接口情况。这里可以看到3个interface,ens160是正常使用的网口,lo是主机的loopback地址127.0.0.1。另外,由于centos安装在虚拟主机上,virbr0是KVM默认创建的一个Bridge,其作用是为连接其上的…...
线性DP——AcWing 898. 数字三角形、AcWing 895. 最长上升子序列
AcWing 898. 数字三角形 1.题目 898. 数字三角形 2.思路 DP问题首先考虑状态转移方程,定义一个集合f ( i , j) ,表示从第一个数字(1,1)走到第 i行,第 j列(i , j)的所有方案的集合,…...
SpringMVC
SpringMVC配置 引入Maven依赖 (springmvc)web.xml配置DispatcherServlet配置 applicationContext 的 MVC 标记开发Controller控制器 几点注意事项: 在web.xml中 配置<load-on-startup> 0 </load-on-startup> 会自动创建Spring…...
C++模板基础(二)
函数模板(二) ● 模板实参的类型推导 – 如果函数模板在实例化时没有显式指定模板实参,那么系统会尝试进行推导 template<typename T> void fun(T input, T input2) {std::cout << input << \t << input2 << …...
什么是linux内核态、用户态?
目录标题为什么需要区分内核空间与用户空间内核态与用户态如何从用户空间进入内核空间整体结构为什么需要区分内核空间与用户空间 在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如…...
day8—选择题
文章目录1.Test.main() 函数执行后的输出是(D)2. JUnit主要用来完成什么(D)3.下列选项中关于Java中super关键字的说法正确的是(A)1.Test.main() 函数执行后的输出是(D) public clas…...
ngx错误日志error_log配置
ngx之error_log 日志配置格式: 常见的错误日志级别 错误日志可配置位置 关闭error_log配置 设置debug 日志级别的前提: ngx之error_log 日志配置格式: error_log 存放路径 日志级别 例: error_log /usr/local/log…...
1.11、自动化
自动化 一、java 手机自动化 首先new DesertCapabilities(这是一个类) setCapability – 设置信息 获取appium的驱动对象 new AppiumDriver – 本机IP地址:端口号/wd/hub,前面的设置值信息 driver.findElementById() – 通过id找位置 click() – 点击 &…...
函数的定义与使用及七段数码管绘制
函数的定义 函数是一段代码的表示 函数是一段具有特定功能的、可重用的语句组 函数是一种功能的抽象,一般函数表达特定功能 两个作用:降低编程难度 和 代码复用 求一个阶乘 fact就是 函数名 n就是参数 return就是输出部分即返回值 而函数的调用就是…...
怎么压缩pdf文件大小?pdf文件太大如何压缩?
喜爱看小说的小伙伴们都会在网上下载很多的pdf格式电子书以方便随时阅览,但是pdf的电子书一般都过于的冗长,下载后的储存也是一个问题,怎么pdf压缩大小呢?可以试试今天介绍的这款pdf在线压缩工具来进行pdf压缩(https:/…...
阿里云Linux服务器登录名ecs-user和root选择问题
阿里云服务器Linux系统登录名可以选择root或ecs-user,root具有操作系统的最高权限,但是root会导致的安全风险比较大,ecs-user比较安全,但是如果系统后续依赖root权限就会比较麻烦,从安全的角度,建议选择ecs…...
【云原生】 初体验阿里云Serverless应用引擎SAE(三),挂载配置文件使应用的配置和运行的镜像解耦
目录 一、前言二、SAE配置1、创建配置项2、配置SAE Nginx服务效果1、【云原生】 初体验阿里云Serverless应用引擎SAE(一),部署Nginx服务 2、【云原生】 初体验阿里云Serverless应用引擎SAE(二),前端Nginx静态文件持久化到对象存储OSS 本篇 3、【云原生】 初体验阿里云Se…...
Oracle用户密码过期,修改永不过期
修改密码有效过期时间,可以通过以下四步设置,如果再第一步发现本身的密码过期时间为无限期的,那就请各位小伙伴绕过,如果发现不是无期限的,那么必须设置第四步,才会生效。 目录 第一步:查询密码…...
welearn 视听说1-4
词汇题(55道) 1. You should carefully think over_____ the manager said at the meeting. A. that B. which C. what D. whose 1.选C,考察宾语从句连接词,主句谓语动词think over后面缺宾语,后面的宾语从句谓语动…...
【git】将本地项目同步到远程
前提:git已经安装,并与账号完成密钥绑定 在github上创建一个新仓库 在项目文件夹下,右击选择git bash here ,打开一个终端对话框 git init (在项目目录下出现隐藏的.git文件夹,目的是把该项目文件夹变成git可管理…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
