123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- /*
- * Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved.
- *
- * Base on code from
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind.
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
- * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
- * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
- * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
- * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
- * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
- * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
- * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <unistd.h>
- #include <ipmitool/log.h>
- #include <ipmitool/helper.h>
- #include <ipmitool/ipmi.h>
- #include <ipmitool/ipmi_fwum.h>
- #include <ipmitool/ipmi_intf.h>
- #include <ipmitool/ipmi_mc.h>
- extern int verbose;
- unsigned char firmBuf[1024*512];
- tKFWUM_SaveFirmwareInfo save_fw_nfo;
- int KfwumGetFileSize(const char *pFileName,
- unsigned long *pFileSize);
- int KfwumSetupBuffersFromFile(const char *pFileName,
- unsigned long fileSize);
- void KfwumShowProgress(const char *task, unsigned long current,
- unsigned long total);
- unsigned short KfwumCalculateChecksumPadding(unsigned char *pBuffer,
- unsigned long totalSize);
- int KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
- unsigned char *pNumBank);
- int KfwumGetDeviceInfo(struct ipmi_intf *intf,
- unsigned char output, tKFWUM_BoardInfo *pBoardInfo);
- int KfwumGetStatus(struct ipmi_intf *intf);
- int KfwumManualRollback(struct ipmi_intf *intf);
- int KfwumStartFirmwareImage(struct ipmi_intf *intf,
- unsigned long length, unsigned short padding);
- int KfwumSaveFirmwareImage(struct ipmi_intf *intf,
- unsigned char sequenceNumber, unsigned long address,
- unsigned char *pFirmBuf, unsigned char *pInBufLength);
- int KfwumFinishFirmwareImage(struct ipmi_intf *intf,
- tKFWUM_InFirmwareInfo firmInfo);
- int KfwumUploadFirmware(struct ipmi_intf *intf,
- unsigned char *pBuffer, unsigned long totalSize);
- int KfwumStartFirmwareUpgrade(struct ipmi_intf *intf);
- int KfwumGetInfoFromFirmware(unsigned char *pBuf,
- unsigned long bufSize, tKFWUM_InFirmwareInfo *pInfo);
- void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo *pInfo);
- int KfwumGetTraceLog(struct ipmi_intf *intf);
- int ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
- tKFWUM_InFirmwareInfo firmInfo);
- int ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action);
- int ipmi_fwum_info(struct ipmi_intf *intf);
- int ipmi_fwum_status(struct ipmi_intf *intf);
- void printf_kfwum_help(void);
- void printf_kfwum_info(tKFWUM_BoardInfo boardInfo,
- tKFWUM_InFirmwareInfo firmInfo);
- /* String table */
- /* Must match eFWUM_CmdId */
- const char *CMD_ID_STRING[] = {
- "GetFwInfo",
- "KickWatchdog",
- "GetLastAnswer",
- "BootHandshake",
- "ReportStatus",
- "CtrlIPMBLine",
- "SetFwState",
- "GetFwStatus",
- "GetSpiMemStatus",
- "StartFwUpdate",
- "StartFwImage",
- "SaveFwImage",
- "FinishFwImage",
- "ReadFwImage",
- "ManualRollback",
- "GetTraceLog"
- };
- const char *EXT_CMD_ID_STRING[] = {
- "FwUpgradeLock",
- "ProcessFwUpg",
- "ProcessFwRb",
- "WaitHSAfterUpg",
- "WaitFirstHSUpg",
- "FwInfoStateChange"
- };
- const char *CMD_STATE_STRING[] = {
- "Invalid",
- "Begin",
- "Progress",
- "Completed"
- };
- const struct valstr bankStateValS[] = {
- { 0x00, "Not programmed" },
- { 0x01, "New firmware" },
- { 0x02, "Wait for validation" },
- { 0x03, "Last Known Good" },
- { 0x04, "Previous Good" }
- };
- /* ipmi_fwum_main - entry point for this ipmitool mode
- *
- * @intf: ipmi interface
- * @arc: number of arguments
- * @argv: point to argument array
- *
- * returns 0 on success
- * returns -1 on error
- */
- int
- ipmi_fwum_main(struct ipmi_intf *intf, int argc, char **argv)
- {
- int rc = 0;
- printf("FWUM extension Version %d.%d\n", VER_MAJOR, VER_MINOR);
- if (argc < 1) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- printf_kfwum_help();
- return (-1);
- }
- if (strncmp(argv[0], "help", 4) == 0) {
- printf_kfwum_help();
- rc = 0;
- } else if (strncmp(argv[0], "info", 4) == 0) {
- rc = ipmi_fwum_info(intf);
- } else if (strncmp(argv[0], "status", 6) == 0) {
- rc = ipmi_fwum_status(intf);
- } else if (strncmp(argv[0], "rollback", 8) == 0) {
- rc = KfwumManualRollback(intf);
- } else if (strncmp(argv[0], "download", 8) == 0) {
- if ((argc < 2) || (strlen(argv[1]) < 1)) {
- lprintf(LOG_ERR,
- "Path and file name must be specified.");
- return (-1);
- }
- printf("Firmware File Name : %s\n", argv[1]);
- rc = ipmi_fwum_fwupgrade(intf, argv[1], 0);
- } else if (strncmp(argv[0], "upgrade", 7) == 0) {
- if ((argc >= 2) && (strlen(argv[1]) > 0)) {
- printf("Upgrading using file name %s\n", argv[1]);
- rc = ipmi_fwum_fwupgrade(intf, argv[1], 1);
- } else {
- rc = KfwumStartFirmwareUpgrade(intf);
- }
- } else if (strncmp(argv[0], "tracelog", 8) == 0) {
- rc = KfwumGetTraceLog(intf);
- } else {
- lprintf(LOG_ERR, "Invalid KFWUM command: %s", argv[0]);
- printf_kfwum_help();
- rc = (-1);
- }
- return rc;
- }
- void
- printf_kfwum_help(void)
- {
- lprintf(LOG_NOTICE,
- "KFWUM Commands: info status download upgrade rollback tracelog");
- }
- /* private definitions and macros */
- typedef enum eFWUM_CmdId
- {
- KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0,
- KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1,
- KFWUM_CMD_ID_GET_LAST_ANSWER = 2,
- KFWUM_CMD_ID_BOOT_HANDSHAKE = 3,
- KFWUM_CMD_ID_REPORT_STATUS = 4,
- KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7,
- KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9,
- KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a,
- KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b,
- KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c,
- KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d,
- KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e,
- KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f,
- KFWUM_CMD_ID_STD_MAX_CMD,
- KFWUM_CMD_ID_EXTENDED_CMD = 0xC0
- } tKFWUM_CmdId;
- int
- ipmi_fwum_info(struct ipmi_intf *intf)
- {
- tKFWUM_BoardInfo b_info;
- int rc = 0;
- unsigned char not_used;
- if (verbose) {
- printf("Getting Kontron FWUM Info\n");
- }
- if (KfwumGetDeviceInfo(intf, 1, &b_info) != 0) {
- rc = (-1);
- }
- if (KfwumGetInfo(intf, 1, ¬_used) != 0) {
- rc = (-1);
- }
- return rc;
- }
- int
- ipmi_fwum_status(struct ipmi_intf *intf)
- {
- if (verbose) {
- printf("Getting Kontron FWUM Status\n");
- }
- if (KfwumGetStatus(intf) != 0) {
- return (-1);
- }
- return 0;
- }
- /* ipmi_fwum_fwupgrade - function implements download/upload of the firmware
- * data received as parameters
- *
- * @file: fw file
- * @action: 0 = download, 1 = upload/start upload
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action)
- {
- tKFWUM_BoardInfo b_info;
- tKFWUM_InFirmwareInfo fw_info = { 0 };
- unsigned short padding;
- unsigned long fsize = 0;
- unsigned char not_used;
- if (file == NULL) {
- lprintf(LOG_ERR, "No file given.");
- return (-1);
- }
- if (KfwumGetFileSize(file, &fsize) != 0) {
- return (-1);
- }
- if (KfwumSetupBuffersFromFile(file, fsize) != 0) {
- return (-1);
- }
- padding = KfwumCalculateChecksumPadding(firmBuf, fsize);
- if (KfwumGetInfoFromFirmware(firmBuf, fsize, &fw_info) != 0) {
- return (-1);
- }
- if (KfwumGetDeviceInfo(intf, 0, &b_info) != 0) {
- return (-1);
- }
- if (ipmi_kfwum_checkfwcompat(b_info, fw_info) != 0) {
- return (-1);
- }
- KfwumGetInfo(intf, 0, ¬_used);
- printf_kfwum_info(b_info, fw_info);
- if (KfwumStartFirmwareImage(intf, fsize, padding) != 0) {
- return (-1);
- }
- if (KfwumUploadFirmware(intf, firmBuf, fsize) != 0) {
- return (-1);
- }
- if (KfwumFinishFirmwareImage(intf, fw_info) != 0) {
- return (-1);
- }
- if (KfwumGetStatus(intf) != 0) {
- return (-1);
- }
- if (action != 0) {
- if (KfwumStartFirmwareUpgrade(intf) != 0) {
- return (-1);
- }
- }
- return 0;
- }
- /* KfwumGetFileSize - gets the file size
- *
- * @pFileName : filename ptr
- * @pFileSize : output ptr for filesize
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- KfwumGetFileSize(const char *pFileName, unsigned long *pFileSize)
- {
- FILE *pFileHandle = NULL;
- pFileHandle = fopen(pFileName, "rb");
- if (pFileHandle == NULL) {
- return (-1);
- }
- if (fseek(pFileHandle, 0L , SEEK_END) == 0) {
- *pFileSize = ftell(pFileHandle);
- }
- fclose(pFileHandle);
- if (*pFileSize != 0) {
- return 0;
- }
- return (-1);
- }
- /* KfwumSetupBuffersFromFile - small buffers are used to store the file data
- *
- * @pFileName : filename ptr
- * unsigned long : filesize
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- KfwumSetupBuffersFromFile(const char *pFileName, unsigned long fileSize)
- {
- int rc = (-1);
- FILE *pFileHandle = NULL;
- int count;
- int modulus;
- int qty = 0;
- pFileHandle = fopen(pFileName, "rb");
- if (pFileHandle == NULL) {
- lprintf(LOG_ERR, "Failed to open '%s' for reading.",
- pFileName);
- return (-1);
- }
- count = fileSize / MAX_BUFFER_SIZE;
- modulus = fileSize % MAX_BUFFER_SIZE;
- rewind(pFileHandle);
- for (qty = 0; qty < count; qty++) {
- KfwumShowProgress("Reading Firmware from File",
- qty, count);
- if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
- MAX_BUFFER_SIZE,
- pFileHandle) == MAX_BUFFER_SIZE) {
- rc = 0;
- }
- }
- if (modulus) {
- if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
- modulus, pFileHandle) == modulus) {
- rc = 0;
- }
- }
- if (rc == 0) {
- KfwumShowProgress("Reading Firmware from File", 100, 100);
- }
- fclose(pFileHandle);
- return rc;
- }
- /* KfwumShowProgress - helper routine to display progress bar
- *
- * Converts current/total in percent
- *
- * *task : string identifying current operation
- * current: progress
- * total : limit
- */
- void
- KfwumShowProgress(const char *task, unsigned long current, unsigned long total)
- {
- # define PROG_LENGTH 42
- static unsigned long staticProgress=0xffffffff;
- unsigned char spaces[PROG_LENGTH + 1];
- unsigned short hash;
- float percent = ((float)current / total);
- unsigned long progress = 100 * (percent);
- if (staticProgress == progress) {
- /* We displayed the same last time.. so don't do it */
- return;
- }
- staticProgress = progress;
- printf("%-25s : ", task); /* total 20 bytes */
- hash = (percent * PROG_LENGTH);
- memset(spaces, '#', hash);
- spaces[hash] = '\0';
- printf("%s", spaces);
- memset(spaces, ' ', (PROG_LENGTH - hash));
- spaces[(PROG_LENGTH - hash)] = '\0';
- printf("%s", spaces );
- printf(" %3ld %%\r", progress); /* total 7 bytes */
- if (progress == 100) {
- printf("\n");
- }
- fflush(stdout);
- }
- /* KfwumCalculateChecksumPadding - TBD
- */
- unsigned short
- KfwumCalculateChecksumPadding(unsigned char *pBuffer, unsigned long totalSize)
- {
- unsigned short sumOfBytes = 0;
- unsigned short padding;
- unsigned long counter;
- for (counter = 0; counter < totalSize; counter ++) {
- sumOfBytes += pBuffer[counter];
- }
- padding = 0 - sumOfBytes;
- return padding;
- }
- /* KfwumGetInfo - Get Firmware Update Manager (FWUM) information
- *
- * *intf : IPMI interface
- * output : when set to non zero, queried information is displayed
- * pNumBank: output ptr for number of banks
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
- unsigned char *pNumBank)
- {
- int rc = 0;
- static struct KfwumGetInfoResp *pGetInfo;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
- req.msg.data_len = 0;
- rsp = intf->sendrecv(intf, &req);
- if (!rsp) {
- lprintf(LOG_ERR, "Error in FWUM Firmware Get Info Command.");
- return (-1);
- } else if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "FWUM Firmware Get Info returned %x",
- rsp->ccode);
- return (-1);
- }
- pGetInfo = (struct KfwumGetInfoResp *)rsp->data;
- if (output) {
- printf("\nFWUM info\n");
- printf("=========\n");
- printf("Protocol Revision : %02Xh\n",
- pGetInfo->protocolRevision);
- printf("Controller Device Id : %02Xh\n",
- pGetInfo->controllerDeviceId);
- printf("Firmware Revision : %u.%u%u",
- pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
- pGetInfo->firmRev2 & 0x0f);
- if (pGetInfo->byte.mode != 0) {
- printf(" - DEBUG BUILD\n");
- } else {
- printf("\n");
- }
- printf("Number Of Memory Bank : %u\n", pGetInfo->numBank);
- }
- *pNumBank = pGetInfo->numBank;
- /* Determine wich type of download to use: */
- /* Old FWUM or Old IPMC fw (data_len < 7)
- * --> Address with small buffer size
- */
- if ((pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 )) {
- save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
- save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
- save_fw_nfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
- if (verbose) {
- printf("Protocol Revision :");
- printf(" <= 5 detected, adjusting buffers\n");
- }
- } else {
- /* Both fw are using the new protocol */
- save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
- save_fw_nfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
- /* Buffer size depending on access type (Local or remote) */
- /* Look if we run remote or locally */
- if (verbose) {
- printf("Protocol Revision :");
- printf(" > 5 optimizing buffers\n");
- }
- if (strstr(intf->name,"lan") != NULL) {
- /* also covers lanplus */
- save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
- if (verbose) {
- printf("IOL payload size : %d\n",
- save_fw_nfo.bufferSize);
- }
- } else if ((strstr(intf->name,"open")!= NULL)
- && intf->target_addr != IPMI_BMC_SLAVE_ADDR
- && (intf->target_addr != intf->my_addr)) {
- save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
- if (verbose) {
- printf("IPMB payload size : %d\n",
- save_fw_nfo.bufferSize);
- }
- } else {
- save_fw_nfo.bufferSize = KFWUM_BIG_BUFFER;
- if (verbose) {
- printf("SMI payload size : %d\n",
- save_fw_nfo.bufferSize);
- }
- }
- }
- return rc;
- }
- /* KfwumGetDeviceInfo - Get IPMC/Board information
- *
- * *intf: IPMI interface
- * output: when set to non zero, queried information is displayed
- * tKFWUM_BoardInfo: output ptr for IPMC/Board information
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output,
- tKFWUM_BoardInfo *pBoardInfo)
- {
- struct ipm_devid_rsp *pGetDevId;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- /* Send Get Device Id */
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_APP;
- req.msg.cmd = BMC_GET_DEVICE_ID;
- req.msg.data_len = 0;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Error in Get Device Id Command");
- return (-1);
- } else if (rsp->ccode != 0) {
- lprintf(LOG_ERR, "Get Device Id returned %x",
- rsp->ccode);
- return (-1);
- }
- pGetDevId = (struct ipm_devid_rsp *)rsp->data;
- pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
- pBoardInfo->boardId = buf2short(pGetDevId->product_id);
- if (output) {
- printf("\nIPMC Info\n");
- printf("=========\n");
- printf("Manufacturer Id : %u\n",
- pBoardInfo->iana);
- printf("Board Id : %u\n",
- pBoardInfo->boardId);
- printf("Firmware Revision : %u.%u%u",
- pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
- pGetDevId->fw_rev2 & 0x0f);
- if (((pBoardInfo->iana == IPMI_OEM_KONTRON)
- && (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002))) {
- printf(" SDR %u", pGetDevId->aux_fw_rev[0]);
- }
- printf("\n");
- }
- return 0;
- }
- /* KfwumGetStatus - Get (and prints) FWUM banks information
- *
- * *intf : IPMI interface
- *
- * returns 0 on success, otherwise (-1)
- */
- int
- KfwumGetStatus(struct ipmi_intf * intf)
- {
- int rc = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct KfwumGetStatusResp *pGetStatus;
- unsigned char numBank;
- unsigned char counter;
- unsigned long firmLength;
- if (verbose) {
- printf(" Getting Status!\n");
- }
- /* Retreive the number of bank */
- rc = KfwumGetInfo(intf, 0, &numBank);
- for(counter = 0;
- (counter < numBank) && (rc == 0);
- counter ++) {
- /* Retreive the status of each bank */
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
- req.msg.data = &counter;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR,
- "Error in FWUM Firmware Get Status Command.");
- rc = (-1);
- break;
- } else if (rsp->ccode) {
- lprintf(LOG_ERR,
- "FWUM Firmware Get Status returned %x",
- rsp->ccode);
- rc = (-1);
- break;
- }
- pGetStatus = (struct KfwumGetStatusResp *) rsp->data;
- printf("\nBank State %d : %s\n",
- counter,
- val2str(pGetStatus->bankState, bankStateValS));
- if (!pGetStatus->bankState) {
- continue;
- }
- firmLength = pGetStatus->firmLengthMSB;
- firmLength = firmLength << 8;
- firmLength |= pGetStatus->firmLengthMid;
- firmLength = firmLength << 8;
- firmLength |= pGetStatus->firmLengthLSB;
- printf("Firmware Length : %ld bytes\n",
- firmLength);
- printf("Firmware Revision : %u.%u%u SDR %u\n",
- pGetStatus->firmRev1,
- pGetStatus->firmRev2 >> 4,
- pGetStatus->firmRev2 & 0x0f,
- pGetStatus->firmRev3);
- }
- printf("\n");
- return rc;
- }
- /* KfwumManualRollback - Ask IPMC to rollback to previous version
- *
- * *intf : IPMI interface
- *
- * returns 0 on success
- * returns (-1) on error
- */
- int
- KfwumManualRollback(struct ipmi_intf *intf)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct KfwumManualRollbackReq thisReq;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
- thisReq.type = 0; /* Wait BMC shutdown */
- req.msg.data = (unsigned char *)&thisReq;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Error in FWUM Manual Rollback Command.");
- return (-1);
- } else if (rsp->ccode != 0) {
- lprintf(LOG_ERR,
- "Error in FWUM Manual Rollback Command returned %x",
- rsp->ccode);
- return (-1);
- }
- printf("FWUM Starting Manual Rollback \n");
- return 0;
- }
- int
- KfwumStartFirmwareImage(struct ipmi_intf *intf, unsigned long length,
- unsigned short padding)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct KfwumStartFirmwareDownloadResp *pResp;
- struct KfwumStartFirmwareDownloadReq thisReq;
- thisReq.lengthLSB = length & 0x000000ff;
- thisReq.lengthMid = (length >> 8) & 0x000000ff;
- thisReq.lengthMSB = (length >> 16) & 0x000000ff;
- thisReq.paddingLSB = padding & 0x00ff;
- thisReq.paddingMSB = (padding>> 8) & 0x00ff;
- thisReq.useSequence = 0x01;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
- req.msg.data = (unsigned char *) &thisReq;
- /* Look for download type */
- if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
- req.msg.data_len = 5;
- } else {
- req.msg.data_len = 6;
- }
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR,
- "Error in FWUM Firmware Start Firmware Image Download Command.");
- return (-1);
- } else if (rsp->ccode) {
- lprintf(LOG_ERR,
- "FWUM Firmware Start Firmware Image Download returned %x",
- rsp->ccode);
- return (-1);
- }
- pResp = (struct KfwumStartFirmwareDownloadResp *)rsp->data;
- printf("Bank holding new firmware : %d\n", pResp->bank);
- sleep(5);
- return 0;
- }
- int
- KfwumSaveFirmwareImage(struct ipmi_intf *intf, unsigned char sequenceNumber,
- unsigned long address, unsigned char *pFirmBuf,
- unsigned char *pInBufLength)
- {
- int rc = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct KfwumSaveFirmwareAddressReq addr_req;
- struct KfwumSaveFirmwareSequenceReq seq_req;
- int retry = 0;
- int no_rsp = 0;
- do {
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
- if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
- addr_req.addressLSB = address & 0x000000ff;
- addr_req.addressMid = (address >> 8) & 0x000000ff;
- addr_req.addressMSB = (address >> 16) & 0x000000ff;
- addr_req.numBytes = *pInBufLength;
- memcpy(addr_req.txBuf, pFirmBuf, *pInBufLength);
- req.msg.data = (unsigned char *)&addr_req;
- req.msg.data_len = *pInBufLength + 4;
- } else {
- seq_req.sequenceNumber = sequenceNumber;
- memcpy(seq_req.txBuf, pFirmBuf, *pInBufLength);
- req.msg.data = (unsigned char *)&seq_req;
- req.msg.data_len = *pInBufLength + sizeof(unsigned char);
- /* + 1 => sequenceNumber*/
- }
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR,
- "Error in FWUM Firmware Save Firmware Image Download Command.");
- /* We don't receive "C7" on errors with IOL,
- * instead we receive nothing
- */
- if (strstr(intf->name, "lan") != NULL) {
- no_rsp++;
- if (no_rsp < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT) {
- *pInBufLength -= 1;
- continue;
- }
- lprintf(LOG_ERR,
- "Error, too many commands without response.");
- *pInBufLength = 0;
- break;
- } /* For other interface keep trying */
- } else if (rsp->ccode != 0) {
- if (rsp->ccode == 0xc0) {
- sleep(1);
- } else if ((rsp->ccode == 0xc7)
- || ((rsp->ccode == 0xc3)
- && (sequenceNumber == 0))) {
- *pInBufLength -= 1;
- retry = 1;
- } else if (rsp->ccode == 0x82) {
- /* Double sent, continue */
- rc = 0;
- break;
- } else if (rsp->ccode == 0x83) {
- if (retry == 0) {
- retry = 1;
- continue;
- }
- rc = (-1);
- break;
- } else if (rsp->ccode == 0xcf) {
- /* Ok if receive duplicated request */
- retry = 1;
- } else if (rsp->ccode == 0xc3) {
- if (retry == 0) {
- retry = 1;
- continue;
- }
- rc = (-1);
- break;
- } else {
- lprintf(LOG_ERR,
- "FWUM Firmware Save Firmware Image Download returned %x",
- rsp->ccode);
- rc = (-1);
- break;
- }
- } else {
- break;
- }
- } while (1);
- return rc;
- }
- int
- KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct KfwumFinishFirmwareDownloadReq thisReq;
- thisReq.versionMaj = firmInfo.versMajor;
- thisReq.versionMinSub = ((firmInfo.versMinor <<4)
- | firmInfo.versSubMinor);
- thisReq.versionSdr = firmInfo.sdrRev;
- thisReq.reserved = 0;
- /* Byte 4 reserved, write 0 */
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
- req.msg.data = (unsigned char *)&thisReq;
- req.msg.data_len = 4;
- /* Infinite loop if BMC doesn't reply or replies 0xc0 every time. */
- do {
- rsp = intf->sendrecv(intf, &req);
- } while (rsp == NULL || rsp->ccode == 0xc0);
- if (rsp->ccode != 0) {
- lprintf(LOG_ERR,
- "FWUM Firmware Finish Firmware Image Download returned %x",
- rsp->ccode);
- return (-1);
- }
- return 0;
- }
- int
- KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer,
- unsigned long totalSize)
- {
- int rc = (-1);
- unsigned long address = 0x0;
- unsigned char writeSize;
- unsigned char oldWriteSize;
- unsigned long lastAddress = 0;
- unsigned char sequenceNumber = 0;
- unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
- do {
- writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize;
- /* Reach the end */
- if (address + writeSize > totalSize) {
- writeSize = (totalSize - address);
- } else if (((address % KFWUM_PAGE_SIZE)
- + writeSize) > KFWUM_PAGE_SIZE) {
- /* Reach boundary end */
- writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE));
- }
- oldWriteSize = writeSize;
- rc = KfwumSaveFirmwareImage(intf, sequenceNumber,
- address, &pBuffer[address], &writeSize);
- if ((rc != 0) && (retry-- != 0)) {
- address = lastAddress;
- rc = 0;
- } else if ( writeSize == 0) {
- rc = (-1);
- } else {
- if (writeSize != oldWriteSize) {
- printf("Adjusting length to %d bytes \n",
- writeSize);
- save_fw_nfo.bufferSize -= (oldWriteSize - writeSize);
- }
- retry = FWUM_MAX_UPLOAD_RETRY;
- lastAddress = address;
- address+= writeSize;
- }
- if (rc == 0) {
- if ((address % 1024) == 0) {
- KfwumShowProgress("Writing Firmware in Flash",
- address, totalSize);
- }
- sequenceNumber++;
- }
- } while ((rc == 0) && (address < totalSize));
- if (rc == 0) {
- KfwumShowProgress("Writing Firmware in Flash",
- 100, 100);
- }
- return rc;
- }
- int
- KfwumStartFirmwareUpgrade(struct ipmi_intf *intf)
- {
- int rc = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- /* Upgrade type, wait BMC shutdown */
- unsigned char upgType = 0 ;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
- req.msg.data = (unsigned char *) &upgType;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR,
- "Error in FWUM Firmware Start Firmware Upgrade Command");
- rc = (-1);
- } else if (rsp->ccode) {
- if (rsp->ccode == 0xd5) {
- lprintf(LOG_ERR,
- "No firmware available for upgrade. Download Firmware first.");
- } else {
- lprintf(LOG_ERR,
- "FWUM Firmware Start Firmware Upgrade returned %x",
- rsp->ccode);
- }
- rc = (-1);
- }
- return rc;
- }
- int
- KfwumGetTraceLog(struct ipmi_intf *intf)
- {
- int rc = 0;
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- unsigned char chunkIdx;
- unsigned char cmdIdx;
- if (verbose) {
- printf(" Getting Trace Log!\n");
- }
- for (chunkIdx = 0;
- (chunkIdx < TRACE_LOG_CHUNK_COUNT)
- && (rc == 0);
- chunkIdx++) {
- /* Retreive each log chunk and print it */
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
- req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
- req.msg.data = &chunkIdx;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR,
- "Error in FWUM Firmware Get Trace Log Command");
- rc = (-1);
- break;
- } else if (rsp->ccode) {
- lprintf(LOG_ERR,
- "FWUM Firmware Get Trace Log returned %x",
- rsp->ccode);
- rc = (-1);
- break;
- }
- for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) {
- /* Don't diplay commands with an invalid state */
- if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
- && (rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) {
- printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
- CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx]],
- CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
- rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
- } else if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
- && (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) {
- printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
- EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
- CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
- rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
- }
- }
- }
- printf("\n");
- return rc;
- }
- int
- KfwumGetInfoFromFirmware(unsigned char *pBuf, unsigned long bufSize,
- tKFWUM_InFirmwareInfo *pInfo)
- {
- unsigned long offset = 0;
- if (bufSize < (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) {
- return (-1);
- }
- offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
- /* Now, fill the structure with read informations */
- pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + 0 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
- pInfo->checksum|= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + 1 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
- pInfo->sumToRemoveFromChecksum = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
- pInfo->sumToRemoveFromChecksum+= KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM + 1);
- pInfo->fileSize = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 0) << 24;
- pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 1) << 16;
- pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 2) << 8;
- pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 3);
- pInfo->boardId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 0) << 8;
- pInfo->boardId|= KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 1);
- pInfo->deviceId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
- pInfo->tableVers = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
- pInfo->implRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
- pInfo->versMajor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset
- + IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR)) & 0x0f;
- pInfo->versMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset
- + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB) >> 4) & 0x0f;
- pInfo->versSubMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB)) & 0x0f;
- pInfo->sdrRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_SDR_REV);
- pInfo->iana = KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
- pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
- pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
- offset + IN_FIRMWARE_INFO_OFFSET_IANA0);
- KfwumFixTableVersionForOldFirmware(pInfo);
- return 0;
- }
- void
- KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
- {
- switch(pInfo->boardId) {
- case KFWUM_BOARD_KONTRON_UNKNOWN:
- pInfo->tableVers = 0xff;
- break;
- default:
- /* pInfo->tableVers is already set for
- * the right version
- */
- break;
- }
- }
- /* ipmi_kfwum_checkfwcompat - check whether firmware we're about to upload is
- * compatible with board.
- *
- * @boardInfo:
- * @firmInfo:
- *
- * returns 0 if compatible, otherwise (-1)
- */
- int
- ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
- tKFWUM_InFirmwareInfo firmInfo)
- {
- int compatible = 0;
- if (boardInfo.iana != firmInfo.iana) {
- lprintf(LOG_ERR,
- "Board IANA does not match firmware IANA.");
- compatible = (-1);
- }
- if (boardInfo.boardId != firmInfo.boardId) {
- lprintf(LOG_ERR,
- "Board IANA does not match firmware IANA.");
- compatible = (-1);
- }
- if (compatible != 0) {
- lprintf(LOG_ERR,
- "Firmware invalid for target board. Download of upgrade aborted.");
- }
- return compatible;
- }
- void
- printf_kfwum_info(tKFWUM_BoardInfo boardInfo, tKFWUM_InFirmwareInfo firmInfo)
- {
- printf(
- "Target Board Id : %u\n", boardInfo.boardId);
- printf(
- "Target IANA number : %u\n", boardInfo.iana);
- printf(
- "File Size : %lu bytes\n", firmInfo.fileSize);
- printf(
- "Firmware Version : %d.%d%d SDR %d\n", firmInfo.versMajor,
- firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
- }
|