meta-facebook/meta-fbtp/recipes-fbtp/plat-utils/files/kcs-test/kcs-test.c (308 lines of code) (raw):
/*
* kcs-test
*
* Copyright 2015-present Facebook. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <termios.h>
/*
* NetFNs
*/
#define IPMI_CHASSIS_NETFN 0x00
#define IPMI_BRIDGE_NETFN 0x02
#define IPMI_SENSOR_EVENT_NETFN 0x04
#define IPMI_APP_NETFN 0x06
#define IPMI_FIRMWARE_NETFN 0x08
#define IPMI_STORAGE_NETFN 0x0a
#define IPMI_TRANSPORT_NETFN 0x0c
#define IPMI_GROUP_EXTENSION_NETFN 0x2c
#define IPMI_OEM_GROUP_NETFN 0x2e
//#define IPMI_APP_NETFN 6
#define IPMI_GET_DEVICE_ID_CMD 0x01
#define IPMI_BROADCAST_GET_DEVICE_ID_CMD 0x01
#define IPMI_COLD_RESET_CMD 0x02
#define IPMI_WARM_RESET_CMD 0x03
#define IPMI_GET_SELF_TEST_RESULTS_CMD 0x04
#define IPMI_MANUFACTURING_TEST_ON_CMD 0x05
#define IPMI_SET_ACPI_POWER_STATE_CMD 0x06
#define IPMI_GET_ACPI_POWER_STATE_CMD 0x07
#define IPMI_GET_DEVICE_GUID_CMD 0x08
#define IPMI_RESET_WATCHDOG_TIMER_CMD 0x22
#define IPMI_SET_WATCHDOG_TIMER_CMD 0x24
#define IPMI_GET_WATCHDOG_TIMER_CMD 0x25
#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
#define IPMI_GET_MSG_FLAGS_CMD 0x31
#define IPMI_ENABLE_MESSAGE_CHANNEL_RCV_CMD 0x32
#define IPMI_GET_MSG_CMD 0x33
#define IPMI_SEND_MSG_CMD 0x34
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
#define IPMI_GET_BT_INTERFACE_CAPABILITIES_CMD 0x36
#define IPMI_GET_SYSTEM_GUID_CMD 0x37
#define IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD 0x38
#define IPMI_GET_SESSION_CHALLENGE_CMD 0x39
#define IPMI_ACTIVATE_SESSION_CMD 0x3a
#define IPMI_SET_SESSION_PRIVILEGE_CMD 0x3b
#define IPMI_CLOSE_SESSION_CMD 0x3c
#define IPMI_GET_SESSION_INFO_CMD 0x3d
#define IPMI_GET_AUTHCODE_CMD 0x3f
#define IPMI_SET_CHANNEL_ACCESS_CMD 0x40
#define IPMI_GET_CHANNEL_ACCESS_CMD 0x41
#define IPMI_GET_CHANNEL_INFO_CMD 0x42
#define IPMI_SET_USER_ACCESS_CMD 0x43
#define IPMI_GET_USER_ACCESS_CMD 0x44
#define IPMI_SET_USER_NAME_CMD 0x45
#define IPMI_GET_USER_NAME_CMD 0x46
#define IPMI_SET_USER_PASSWORD_CMD 0x47
#define IPMI_ACTIVATE_PAYLOAD_CMD 0x48
#define IPMI_DEACTIVATE_PAYLOAD_CMD 0x49
#define IPMI_GET_PAYLOAD_ACTIVATION_STATUS_CMD 0x4a
#define IPMI_GET_PAYLOAD_INSTANCE_INFO_CMD 0x4b
#define IPMI_SET_USER_PAYLOAD_ACCESS_CMD 0x4c
#define IPMI_GET_USER_PAYLOAD_ACCESS_CMD 0x4d
#define IPMI_GET_CHANNEL_PAYLOAD_SUPPORT_CMD 0x4e
#define IPMI_GET_CHANNEL_PAYLOAD_VERSION_CMD 0x4f
#define IPMI_GET_CHANNEL_OEM_PAYLOAD_INFO_CMD 0x50
#define IPMI_MASTER_READ_WRITE_CMD 0x52
#define IPMI_GET_CHANNEL_CIPHER_SUITES_CMD 0x54
#define IPMI_SUSPEND_RESUME_PAYLOAD_ENCRYPTION_CMD 0x55
#define IPMI_SET_CHANNEL_SECURITY_KEY_CMD 0x56
#define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD 0x57
/* Setion 9.2 KCS Request Message Format */
typedef struct
{
unsigned char netfn_lun; //byte 1 : netfn [8:2], lun[1:0]
unsigned char cmd; //byte 2
unsigned char data[]; //byte 3:N
} ipmi_req_t;
// IPMI response Structure (IPMI/Section 9.3)
typedef struct
{
unsigned char netfn_lun;
unsigned char cmd;
unsigned char cc;
unsigned char data[];
} ipmi_res_t;
static void
usage(FILE *fp, int argc, char **argv)
{
fprintf(fp,
"Usage: %s [options]\n\n"
"Options:\n"
" -h | --help Print this message\n"
" -n | --node device node [/dev/ast-kcs.2]\n"
" -a | --addr address [CA2]\n"
" -d | --debug debug mode\n"
"",
argv[0]);
}
static const char short_options [] = "hdn:a:";
static const struct option
long_options [] = {
{ "help", no_argument, NULL, 'h' },
{ "node", required_argument, NULL, 'n' },
{ "addr", required_argument, NULL, 'a' },
{ "debug", no_argument, NULL, 'd' },
{ 0, 0, 0, 0 }
};
static unsigned char devid_data[] = {
0x20, 0x01, 0x00, 0x48, 0x02, 0x9f, 0x22, 0x03, 0x00, 0x11, 0x43,
0x00, 0x11, 0x00, 0x04
};
static unsigned char guid_data[] = {
0x00, 0x01, 0x00, 0x48, 0x02, 0x9f, 0xaa, 0x01,
0x00, 0x23, 0x00, 0x00, 0x11, 0x00, 0x04, 0x99
};
static unsigned char bt_interface_data[] = {
0x01, 0x40, 0x40, 0x05, 0x03
};
static unsigned char test_data[] = {
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36
};
#if 0
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E,
0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0xff
#endif
static unsigned char self_test_data[] = {
0x55, 0x00
};
int debug = 0;
int ipmi_app_handler(ipmi_req_t *req_buf, unsigned char *req_len, ipmi_res_t* res_buf, unsigned char *res_len)
{
int ret = 0;
switch(req_buf->cmd) {
//for performace test
case 0xF:
if(debug) printf("performance test\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = 0xf;
res_buf->cc = 0;
*res_len += sizeof(test_data);
memcpy(&res_buf->data, test_data, sizeof(test_data));
break;
case IPMI_GET_DEVICE_ID_CMD:
if(debug) printf("IPMI_GET_DEVICE_ID_CMD\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = IPMI_GET_DEVICE_ID_CMD;
res_buf->cc = 0;
*res_len += sizeof(devid_data);
memcpy(&res_buf->data, devid_data, sizeof(devid_data));
break;
case IPMI_GET_SELF_TEST_RESULTS_CMD:
if(debug) printf("IPMI_GET_SELF_TEST_RESULTS_CMD\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = IPMI_GET_SELF_TEST_RESULTS_CMD;
res_buf->cc = 0;
*res_len += sizeof(self_test_data);
memcpy(&res_buf->data, self_test_data, sizeof(self_test_data));
break;
case IPMI_GET_DEVICE_GUID_CMD:
if(debug) printf("IPMI_GET_DEVICE_GUID_CMD\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = IPMI_GET_DEVICE_GUID_CMD;
res_buf->cc = 0;
*res_len += sizeof(guid_data);
memcpy(&res_buf->data, guid_data, sizeof(guid_data));
break;
case IPMI_GET_BMC_GLOBAL_ENABLES_CMD:
if(debug) printf("IPMI_GET_BMC_GLOBAL_ENABLES_CMD\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
res_buf->cc = 0;
*res_len += 1;
res_buf->data[0] = 0x00;
break;
case IPMI_CLEAR_MSG_FLAGS_CMD:
if(debug) printf("IPMI_CLEAR_MSG_FLAGS_CMD\n");
res_buf->netfn_lun = 0x1c;
res_buf->cmd = IPMI_CLEAR_MSG_FLAGS_CMD;
res_buf->cc = 0;
*res_len += 1;
res_buf->data[0] = 0x00;
break;
default:
printf("app unsupport cmd %x \n", req_buf->cmd);
res_buf->netfn_lun = 0x1c;
res_buf->cmd = req_buf->cmd;
res_buf->cc = 0xC1;
break;
}
return ret;
}
unsigned char req_buf[256];
unsigned char res_buf[256];
void *kcs_thread(void *data) {
ipmi_req_t *req = (ipmi_req_t *) req_buf;
ipmi_res_t *res = (ipmi_res_t *) res_buf;
unsigned char req_len, res_len;
int i = 0;
int kcs_fd = (int) data;
while(1) {
get_req:
req_len = read(kcs_fd, req_buf, sizeof(req_buf));
if (req_len > 0) {
//dump read data
if(debug) {
printf("Req [%d] : ", req_len);
for(i=0;i<req_len;i++) {
printf("%x ", req_buf[i]);
}
printf("\n");
}
res_len = 3;
switch(req->netfn_lun >> 2) {
case IPMI_APP_NETFN:
ipmi_app_handler(req, &req_len, res, &res_len);
break;
default:
printf("other unsupport cmd %x \n", req->cmd);
res->netfn_lun = ((req->netfn_lun >> 2) + 1) << 2;
res->cmd = req->cmd;
res->cc = 0xC1;
break;
}
} else {
continue;
}
res_len = write(kcs_fd, res_buf, res_len);
}
}
int main(int argc, char *argv[])
{
int kcs_fd;
int i;
long retVal;
pthread_t thread;
char option;
char dev_node[100]="", kcs_addr[100]="";
unsigned long node_no = 2;
unsigned long addr = 0xca2;
while((option=getopt_long(argc, argv, short_options, long_options, NULL))!=(char)-1){
// printf("option is c %c\n", option);
switch(option){
case 'h':
usage(stdout, argc, argv);
exit(EXIT_SUCCESS);
break;
case 'n':
node_no = strtoul(optarg, 0, 0);
break;
case 'a':
strcpy(kcs_addr, optarg);
if(!strcmp(kcs_addr, "")){
printf("No input kcs addr\n");
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
break;
case 'd':
debug = 1;
// printf("debug is %d\n",debug);
break;
default:
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
}
if(debug) printf("kcs node: %d \n", node_no);
switch(node_no) {
case 0:
system("echo 1 > /sys/devices/platform/ast-kcs.0/enable");
break;
case 1:
system("echo 1 > /sys/devices/platform/ast-kcs.1/enable");
break;
case 2:
system("echo 1 > /sys/devices/platform/ast-kcs.2/enable");
break;
case 3:
system("echo 1 > /sys/devices/platform/ast-kcs.3/enable");
break;
case 4:
system("echo 1 > /sys/devices/platform/ast-kcs.4/enable");
break;
}
sprintf(dev_node, "/dev/ast-kcs.%d", node_no);
printf("ast-kcs.%d, addr : %x\n", node_no, addr);
if(!strcmp(dev_node, "")){
printf("No input device node!\n");
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
kcs_fd = open(dev_node, O_RDWR);
sleep(1);
pthread_create(&thread, NULL, kcs_thread, kcs_fd);
sleep(1);
pthread_join(thread, NULL);
printf("Done.\n"); /* User press Ctrl + C */
close(kcs_fd);
return 0;
}