Blame lib/ipmi_ime.c

Packit Service ed0f68
/*
Packit Service ed0f68
 * Copyright (c) 2007 Kontron Canada, Inc.  All Rights Reserved.
Packit Service ed0f68
 *
Packit Service ed0f68
 * Base on code from
Packit Service ed0f68
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit Service ed0f68
 *
Packit Service ed0f68
 * Redistribution and use in source and binary forms, with or without
Packit Service ed0f68
 * modification, are permitted provided that the following conditions
Packit Service ed0f68
 * are met:
Packit Service ed0f68
 *
Packit Service ed0f68
 * Redistribution of source code must retain the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer.
Packit Service ed0f68
 *
Packit Service ed0f68
 * Redistribution in binary form must reproduce the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer in the
Packit Service ed0f68
 * documentation and/or other materials provided with the distribution.
Packit Service ed0f68
 *
Packit Service ed0f68
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit Service ed0f68
 * contributors may be used to endorse or promote products derived
Packit Service ed0f68
 * from this software without specific prior written permission.
Packit Service ed0f68
 *
Packit Service ed0f68
 * This software is provided "AS IS," without a warranty of any kind.
Packit Service ed0f68
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit Service ed0f68
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit Service ed0f68
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit Service ed0f68
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit Service ed0f68
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit Service ed0f68
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit Service ed0f68
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit Service ed0f68
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit Service ed0f68
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit Service ed0f68
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit Service ed0f68
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service ed0f68
 */
Packit Service ed0f68
Packit Service ed0f68
/****************************************************************************
Packit Service ed0f68
*
Packit Service ed0f68
*       Copyright (c) 2009 Kontron Canada, Inc.  All Rights Reserved.
Packit Service ed0f68
*
Packit Service ed0f68
*                              IME
Packit Service ed0f68
*                    Intel Manageability Engine
Packit Service ed0f68
*                      Firmware Update Agent
Packit Service ed0f68
*
Packit Service ed0f68
* The ME is an IPMI-enabled component included in Intel(R) Next Generation
Packit Service ed0f68
*  Server Chipset Nehalem-EP platforms.
Packit Service ed0f68
*
Packit Service ed0f68
* These are a few synonyms for the ME :
Packit Service ed0f68
*
Packit Service ed0f68
* - Dynamic Power Node Manager
Packit Service ed0f68
* - Intelligent Power Node Manager
Packit Service ed0f68
* 
Packit Service ed0f68
* Consult Intel litterature for more information on this technology.
Packit Service ed0f68
*
Packit Service ed0f68
* The ME firmware resides on the platform boot flash and contains read only
Packit Service ed0f68
* boot code for the ME as well as boot image redundancy support. 
Packit Service ed0f68
*
Packit Service ed0f68
* This module implements an Upgrade Agent for the ME firwmare. Because the ME 
Packit Service ed0f68
* implements IPMI command handling, the agent speaks directly to the ME. In other
Packit Service ed0f68
* words, in order the reach the ME, the BMC must implement IPMB bridging.
Packit Service ed0f68
*
Packit Service ed0f68
* The update is done through IPMI (this is IPMITOOL right !), not HECI.
Packit Service ed0f68
*
Packit Service ed0f68
* Example: ME available at address 0x88 on IPMI channel 8:
Packit Service ed0f68
*   ipmitool  -m 0x20 -t 0x88 -b 8 ime info
Packit Service ed0f68
*
Packit Service ed0f68
* !! WARNING - You MUST use an image provided by your board vendor. - WARNING !!
Packit Service ed0f68
*
Packit Service ed0f68
* author:
Packit Service ed0f68
*  Jean-Michel.Audet@ca.kontron.com
Packit Service ed0f68
*  Francois.Isabelle@ca.kontron.com
Packit Service ed0f68
*
Packit Service ed0f68
*****************************************************************************/
Packit Service ed0f68
/*
Packit Service ed0f68
 * HISTORY
Packit Service ed0f68
 * ===========================================================================
Packit Service ed0f68
 * 2009-04-20
Packit Service ed0f68
 *
Packit Service ed0f68
 * First public release of Kontron
Packit Service ed0f68
 *
Packit Service ed0f68
*/
Packit Service ed0f68
#include <ipmitool/ipmi_ime.h>
Packit Service ed0f68
#include <ipmitool/log.h>
Packit Service ed0f68
#include <ipmitool/ipmi_intf.h>
Packit Service ed0f68
#include <ipmitool/ipmi_mc.h>
Packit Service ed0f68
#include <ipmitool/helper.h>
Packit Service ed0f68
#include <ipmitool/ipmi_strings.h>
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
#undef OUTPUT_DEBUG
Packit Service ed0f68
Packit Service ed0f68
#include <stdlib.h>
Packit Service ed0f68
#include <string.h>
Packit Service ed0f68
#include <errno.h>
Packit Service ed0f68
#include <time.h>
Packit Service ed0f68
Packit Service ed0f68
static const int IME_SUCCESS              = 0;
Packit Service ed0f68
static const int IME_ERROR                = -1;
Packit Service ed0f68
static const int IME_RESTART              = -2;
Packit Service ed0f68
Packit Service ed0f68
#define IME_UPGRADE_BUFFER_SIZE           22
Packit Service ed0f68
#define IME_RETRY_COUNT                   5
Packit Service ed0f68
Packit Service ed0f68
typedef struct ImeUpdateImageCtx
Packit Service ed0f68
{
Packit Service ed0f68
   uint32_t   size;
Packit Service ed0f68
   uint8_t *  pData;
Packit Service ed0f68
   uint8_t    crc8;
Packit Service ed0f68
}tImeUpdateImageCtx;
Packit Service ed0f68
Packit Service ed0f68
typedef enum eImeState
Packit Service ed0f68
{
Packit Service ed0f68
   IME_STATE_IDLE                = 0,
Packit Service ed0f68
   IME_STATE_UPDATE_REQUESTED    = 1,
Packit Service ed0f68
   IME_STATE_UPDATE_IN_PROGRESS  = 2,
Packit Service ed0f68
   IME_STATE_SUCCESS             = 3,
Packit Service ed0f68
   IME_STATE_FAILED              = 4,
Packit Service ed0f68
   IME_STATE_ROLLED_BACK         = 5,
Packit Service ed0f68
   IME_STATE_ABORTED             = 6,
Packit Service ed0f68
   IME_STATE_INIT_FAILED         = 7
Packit Service ed0f68
} tImeStateEnum;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
typedef enum tImeUpdateType
Packit Service ed0f68
{
Packit Service ed0f68
   IME_UPDTYPE_NORMAL            = 1,
Packit Service ed0f68
   IME_UPDTYPE_MANUAL_ROLLBACK   = 3,
Packit Service ed0f68
   IME_UPDTYPE_ABORT             = 4
Packit Service ed0f68
} tImeUpdateType;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
#ifdef HAVE_PRAGMA_PACK
Packit Service ed0f68
#pragma pack(1)
Packit Service ed0f68
#endif
Packit Service ed0f68
typedef struct sImeStatus {
Packit Service ed0f68
   uint8_t image_status;
Packit Service ed0f68
   tImeStateEnum update_state;
Packit Service ed0f68
   uint8_t update_attempt_status;
Packit Service ed0f68
   uint8_t rollback_attempt_status;
Packit Service ed0f68
   uint8_t update_type;
Packit Service ed0f68
   uint8_t dependent_flag;
Packit Service ed0f68
   uint8_t free_area_size[4];
Packit Service ed0f68
} ATTRIBUTE_PACKING tImeStatus ;
Packit Service ed0f68
#ifdef HAVE_PRAGMA_PACK
Packit Service ed0f68
#pragma pack(0)
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#ifdef HAVE_PRAGMA_PACK
Packit Service ed0f68
#pragma pack(1)
Packit Service ed0f68
#endif
Packit Service ed0f68
typedef struct sImeCaps {
Packit Service ed0f68
   uint8_t area_supported;
Packit Service ed0f68
   uint8_t special_caps;
Packit Service ed0f68
} ATTRIBUTE_PACKING tImeCaps ;
Packit Service ed0f68
#ifdef HAVE_PRAGMA_PACK
Packit Service ed0f68
#pragma pack(0)
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static void ImePrintUsage(void);
Packit Service ed0f68
static int  ImeGetInfo(struct ipmi_intf *intf);
Packit Service ed0f68
static int  ImeUpgrade(struct ipmi_intf *intf, char* imageFilename);
Packit Service ed0f68
static int  ImeManualRollback(struct ipmi_intf *intf);
Packit Service ed0f68
static int  ImeUpdatePrepare(struct ipmi_intf *intf);
Packit Service ed0f68
static int  ImeUpdateOpenArea(struct ipmi_intf *intf);
Packit Service ed0f68
static int  ImeUpdateWriteArea(
Packit Service ed0f68
                              struct ipmi_intf *intf,
Packit Service ed0f68
                              uint8_t sequence, 
Packit Service ed0f68
                              uint8_t length, 
Packit Service ed0f68
                              uint8_t * pBuf
Packit Service ed0f68
                          );
Packit Service ed0f68
static int  ImeUpdateCloseArea(
Packit Service ed0f68
                              struct ipmi_intf *intf,
Packit Service ed0f68
                              uint32_t size, 
Packit Service ed0f68
                              uint16_t checksum
Packit Service ed0f68
                          );
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateGetStatus(struct ipmi_intf *intf, tImeStatus *pStatus);
Packit Service ed0f68
static int ImeUpdateGetCapabilities(struct ipmi_intf *intf, tImeCaps *pCaps );
Packit Service ed0f68
static int  ImeUpdateRegisterUpdate(struct ipmi_intf *intf, tImeUpdateType type);
Packit Service ed0f68
Packit Service ed0f68
static int  ImeImageCtxFromFile(
Packit Service ed0f68
                                 char * imageFilename, 
Packit Service ed0f68
                                 tImeUpdateImageCtx * pImageCtx);
Packit Service ed0f68
static int ImeUpdateShowStatus(struct ipmi_intf *intf);
Packit Service ed0f68
Packit Service ed0f68
static uint8_t ImeCrc8( uint32_t length, uint8_t * pBuf );
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeGetInfo(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
   int rc = IME_ERROR;
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   struct ipm_devid_rsp *devid;
Packit Service ed0f68
   const char *product=NULL;
Packit Service ed0f68
   tImeStatus status;
Packit Service ed0f68
   tImeCaps caps;
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = IPMI_NETFN_APP;
Packit Service ed0f68
   req.msg.cmd = BMC_GET_DEVICE_ID;
Packit Service ed0f68
   req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "Get Device ID command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "Get Device ID command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   devid = (struct ipm_devid_rsp *) rsp->data;
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG,"Device ID                 : %i", devid->device_id);
Packit Service ed0f68
   lprintf(LOG_DEBUG,"Device Revision           : %i",
Packit Service ed0f68
                           devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK);
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (devid->device_id == 0)
Packit Service ed0f68
      &&
Packit Service ed0f68
      ((devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK) == 0)
Packit Service ed0f68
      &&
Packit Service ed0f68
      (
Packit Service ed0f68
         (devid->manufacturer_id[0] == 0x57) // Intel
Packit Service ed0f68
         &&
Packit Service ed0f68
         (devid->manufacturer_id[1] == 0x01) // Intel
Packit Service ed0f68
         &&
Packit Service ed0f68
         (devid->manufacturer_id[2] == 0x00) // Intel
Packit Service ed0f68
      )
Packit Service ed0f68
      &&
Packit Service ed0f68
      (
Packit Service ed0f68
         (devid->product_id[1] == 0x0b)
Packit Service ed0f68
         &&
Packit Service ed0f68
         (devid->product_id[0] == 0x00)
Packit Service ed0f68
      )
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = IME_SUCCESS;
Packit Service ed0f68
      printf("Manufacturer Name          : %s\n",
Packit Service ed0f68
               val2str( (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id), 
Packit Service ed0f68
               ipmi_oem_info) );
Packit Service ed0f68
Packit Service ed0f68
      printf("Product ID                 : %u (0x%02x%02x)\n",
Packit Service ed0f68
         buf2short((uint8_t *)(devid->product_id)),
Packit Service ed0f68
         devid->product_id[1], devid->product_id[0]);
Packit Service ed0f68
 
Packit Service ed0f68
      product=oemval2str(IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id),
Packit Service ed0f68
                      (devid->product_id[1]<<8)+devid->product_id[0],
Packit Service ed0f68
                      ipmi_oem_product_info);
Packit Service ed0f68
Packit Service ed0f68
      if (product!=NULL) 
Packit Service ed0f68
      {
Packit Service ed0f68
         printf("Product Name               : %s\n", product);
Packit Service ed0f68
      }
Packit Service ed0f68
Packit Service ed0f68
      printf("Intel ME Firmware Revision : %x.%02x.%02x.%x%x%x.%x\n",
Packit Service ed0f68
            ((devid->fw_rev1 & IPM_DEV_FWREV1_MAJOR_MASK )         ),
Packit Service ed0f68
            ((devid->fw_rev2                             ) >>     4),
Packit Service ed0f68
            ((devid->fw_rev2                             )  &  0x0f),
Packit Service ed0f68
            ((devid->aux_fw_rev[1]                       ) >>     4),
Packit Service ed0f68
            ((devid->aux_fw_rev[1]                       )  &  0x0f),
Packit Service ed0f68
            ((devid->aux_fw_rev[2]                       ) >>     4),
Packit Service ed0f68
            ((devid->aux_fw_rev[2]                       )  &  0x0f)
Packit Service ed0f68
      );
Packit Service ed0f68
Packit Service ed0f68
      printf("SPS FW IPMI cmd version    : %x.%x\n",
Packit Service ed0f68
         devid->aux_fw_rev[0] >>     4,
Packit Service ed0f68
         devid->aux_fw_rev[0] &  0x0f);
Packit Service ed0f68
Packit Service ed0f68
      lprintf(LOG_DEBUG,"Flags: %xh", devid->aux_fw_rev[3]);
Packit Service ed0f68
Packit Service ed0f68
      printf("Current Image Type         : ");
Packit Service ed0f68
      switch( (devid->aux_fw_rev[3] & 0x03) )
Packit Service ed0f68
      {
Packit Service ed0f68
         case 0:
Packit Service ed0f68
            printf("Recovery\n");
Packit Service ed0f68
         break;
Packit Service ed0f68
Packit Service ed0f68
         case 1:
Packit Service ed0f68
            printf("Operational Image 1\n");
Packit Service ed0f68
         break;
Packit Service ed0f68
Packit Service ed0f68
         case 2:
Packit Service ed0f68
            printf("Operational Image 2\n");
Packit Service ed0f68
         break;
Packit Service ed0f68
Packit Service ed0f68
         case 3:
Packit Service ed0f68
         default:
Packit Service ed0f68
            printf("Unknown\n");
Packit Service ed0f68
         break;
Packit Service ed0f68
      }
Packit Service ed0f68
   }
Packit Service ed0f68
   else
Packit Service ed0f68
   {
Packit Service ed0f68
         printf("Supported ME not found\n");
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeUpdateGetStatus(intf, &status);
Packit Service ed0f68
   
Packit Service ed0f68
      if(rc == IME_SUCCESS)
Packit Service ed0f68
      {
Packit Service ed0f68
         rc = ImeUpdateGetCapabilities(intf, &caps);
Packit Service ed0f68
      }
Packit Service ed0f68
Packit Service ed0f68
   }
Packit Service ed0f68
   
Packit Service ed0f68
   if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      uint8_t newImage  = ((status.image_status >> 1) & 0x01);
Packit Service ed0f68
      uint8_t rollImage = ((status.image_status >> 2) & 0x01);
Packit Service ed0f68
      uint8_t runArea   = ((status.image_status >> 3) & 0x03);
Packit Service ed0f68
      uint8_t rollSup   = ((caps.special_caps   >> 0) & 0x01);
Packit Service ed0f68
      uint8_t recovSup  = ((caps.special_caps   >> 1) & 0x01);
Packit Service ed0f68
Packit Service ed0f68
      uint8_t operSup   = ((caps.area_supported   >> 1) & 0x01);
Packit Service ed0f68
      uint8_t piaSup    = ((caps.area_supported   >> 2) & 0x01);
Packit Service ed0f68
      uint8_t sdrSup    = ((caps.area_supported   >> 3) & 0x01);
Packit Service ed0f68
Packit Service ed0f68
      printf("\nSupported Area\n");
Packit Service ed0f68
      printf("   Operation Code          : %s\n", (operSup ? "Supported" : "Unsupported"));
Packit Service ed0f68
      printf("   PIA                     : %s\n", (piaSup ? "Supported" : "Unsupported"));
Packit Service ed0f68
      printf("   SDR                     : %s\n", (sdrSup ? "Supported" : "Unsupported"));
Packit Service ed0f68
Packit Service ed0f68
      printf("\nSpecial Capabilities\n");
Packit Service ed0f68
      printf("   Rollback                : %s\n", (rollSup ? "Supported" : "Unsupported"));
Packit Service ed0f68
      printf("   Recovery                : %s\n", (recovSup ? "Supported" : "Unsupported"));
Packit Service ed0f68
Packit Service ed0f68
      printf("\nImage Status\n");
Packit Service ed0f68
      printf("   Staging (new)           : %s\n", (newImage ? "Valid" : "Invalid"));
Packit Service ed0f68
      printf("   Rollback                : %s\n", (rollImage ? "Valid" : "Invalid"));
Packit Service ed0f68
      if(runArea == 0)
Packit Service ed0f68
         printf("   Running Image Area      : CODE\n");
Packit Service ed0f68
      else
Packit Service ed0f68
         printf("   Running Image Area      : CODE%d\n", runArea);
Packit Service ed0f68
Packit Service ed0f68
  }
Packit Service ed0f68
Packit Service ed0f68
   return rc;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpgrade(struct ipmi_intf *intf, char* imageFilename)
Packit Service ed0f68
{
Packit Service ed0f68
   int rc = IME_SUCCESS;
Packit Service ed0f68
   tImeUpdateImageCtx imgCtx;
Packit Service ed0f68
   tImeStatus imeStatus;
Packit Service ed0f68
   time_t start,end,current;
Packit Service ed0f68
   
Packit Service ed0f68
   time(&start;;
Packit Service ed0f68
Packit Service ed0f68
   memset(&imgCtx, 0, sizeof(tImeUpdateImageCtx));
Packit Service ed0f68
Packit Service ed0f68
   rc = ImeImageCtxFromFile(imageFilename, &imgCtx);
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_ERROR) ||
Packit Service ed0f68
      (imgCtx.pData == NULL) ||
Packit Service ed0f68
      (imgCtx.size == 0)
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
Packit Service ed0f68
   if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeUpdatePrepare(intf);
Packit Service ed0f68
      ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_UPDATE_REQUESTED) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeUpdateOpenArea(intf);
Packit Service ed0f68
      ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
   }
Packit Service ed0f68
   else if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      lprintf(LOG_ERROR,"ME state error (%i), aborting", imeStatus.update_state);
Packit Service ed0f68
      rc = IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_UPDATE_IN_PROGRESS) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      uint8_t sequence = 0;
Packit Service ed0f68
      uint32_t counter = 0;
Packit Service ed0f68
      uint8_t retry = 0;
Packit Service ed0f68
      uint8_t shownPercent = 0xff;
Packit Service ed0f68
Packit Service ed0f68
      while(   
Packit Service ed0f68
            (counter < imgCtx.size) && 
Packit Service ed0f68
            (rc == IME_SUCCESS) &&
Packit Service ed0f68
            (retry < IME_RETRY_COUNT)
Packit Service ed0f68
           )
Packit Service ed0f68
      {
Packit Service ed0f68
         uint8_t length = IME_UPGRADE_BUFFER_SIZE;
Packit Service ed0f68
         uint8_t currentPercent;
Packit Service ed0f68
Packit Service ed0f68
         if( (imgCtx.size - counter) < IME_UPGRADE_BUFFER_SIZE )
Packit Service ed0f68
         {
Packit Service ed0f68
            length = (imgCtx.size - counter);
Packit Service ed0f68
         }
Packit Service ed0f68
Packit Service ed0f68
         rc = ImeUpdateWriteArea(intf,sequence,length,&imgCtx.pData[counter]);
Packit Service ed0f68
         
Packit Service ed0f68
         /*
Packit Service ed0f68
         As per the flowchart Intel Dynamic Power Node Manager 1.5 IPMI Iface
Packit Service ed0f68
         page 65
Packit Service ed0f68
         We shall send the GetStatus command each time following a write area
Packit Service ed0f68
         but this add too much time to the upgrade
Packit Service ed0f68
         */   
Packit Service ed0f68
         /*  ImeUpdateGetStatus(intf,&imeStatus); */
Packit Service ed0f68
         counter += length;
Packit Service ed0f68
         sequence ++;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
         currentPercent = ((float)counter/imgCtx.size)*100;
Packit Service ed0f68
Packit Service ed0f68
         if(currentPercent != shownPercent)
Packit Service ed0f68
         {
Packit Service ed0f68
            shownPercent = currentPercent;
Packit Service ed0f68
            printf("Percent: %02i,  ", shownPercent);
Packit Service ed0f68
            time(¤t;;
Packit Service ed0f68
            printf("Elapsed time %02ld:%02ld\r",((current-start)/60), ((current-start)%60));
Packit Service ed0f68
            fflush(stdout);
Packit Service ed0f68
Packit Service ed0f68
         }
Packit Service ed0f68
      }
Packit Service ed0f68
      ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
      printf("\n");
Packit Service ed0f68
   }
Packit Service ed0f68
   else if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      lprintf(LOG_ERROR,"ME state error (%i), aborting", imeStatus.update_state);
Packit Service ed0f68
      rc = IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_UPDATE_IN_PROGRESS) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeUpdateCloseArea(intf, imgCtx.size, imgCtx.crc8);
Packit Service ed0f68
      ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
   }
Packit Service ed0f68
   else if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      lprintf(LOG_ERROR,"ME state error, aborting");
Packit Service ed0f68
      rc = IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_UPDATE_REQUESTED) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      printf("UpdateCompleted, Activate now\n");
Packit Service ed0f68
      rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_NORMAL);
Packit Service ed0f68
      ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
   }
Packit Service ed0f68
   else if(rc == IME_SUCCESS)
Packit Service ed0f68
   {
Packit Service ed0f68
      lprintf(LOG_ERROR,"ME state error, aborting");
Packit Service ed0f68
      rc = IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_SUCCESS) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      time(&end;;
Packit Service ed0f68
      printf("Update Completed in %02ld:%02ld\n",(end-start)/60, (end-start)%60);
Packit Service ed0f68
   }
Packit Service ed0f68
   else
Packit Service ed0f68
   {
Packit Service ed0f68
      time(&end;;
Packit Service ed0f68
      printf("Update Error\n");
Packit Service ed0f68
      printf("\nTime Taken %02ld:%02ld\n",(end-start)/60, (end-start)%60);
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   return rc;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdatePrepare(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf("ImeUpdatePrepare\n");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA0;
Packit Service ed0f68
   req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateOpenArea(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   uint8_t buffer[ 2 ];
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf("ImeUpdateOpenArea\n");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA1;
Packit Service ed0f68
Packit Service ed0f68
   buffer[0] = 0x01; // Area Type : Operational code
Packit Service ed0f68
   buffer[1] = 0x00; // Reserved : 0
Packit Service ed0f68
   req.msg.data = buffer;
Packit Service ed0f68
Packit Service ed0f68
   req.msg.data_len = 2;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateOpenArea command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateOpenArea command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdateOpenArea command succeed");
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateWriteArea(
Packit Service ed0f68
                              struct ipmi_intf *intf,
Packit Service ed0f68
                              uint8_t sequence, 
Packit Service ed0f68
                              uint8_t length, 
Packit Service ed0f68
                              uint8_t * pBuf
Packit Service ed0f68
                          )
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   uint8_t buffer[ IME_UPGRADE_BUFFER_SIZE + 1 ];
Packit Service ed0f68
Packit Service ed0f68
//   printf("ImeUpdateWriteArea %i\n", sequence);
Packit Service ed0f68
Packit Service ed0f68
   if(length > IME_UPGRADE_BUFFER_SIZE)
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
Packit Service ed0f68
   buffer[0] = sequence;
Packit Service ed0f68
   memcpy(&buffer[1], pBuf, length);
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA2;
Packit Service ed0f68
   req.msg.data = buffer;
Packit Service ed0f68
   req.msg.data_len = length + 1;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateWriteArea command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateWriteArea command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      if( rsp->ccode == 0x80) // restart operation
Packit Service ed0f68
         return IME_RESTART;
Packit Service ed0f68
      else
Packit Service ed0f68
         return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdateWriteArea command succeed");
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateCloseArea(
Packit Service ed0f68
                              struct ipmi_intf *intf,
Packit Service ed0f68
                              uint32_t size, 
Packit Service ed0f68
                              uint16_t checksum
Packit Service ed0f68
                          )
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   uint8_t length = sizeof( uint32_t ) + sizeof( uint16_t ); 
Packit Service ed0f68
   uint8_t buffer[ sizeof( uint32_t ) + sizeof( uint16_t ) ];
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf( "ImeUpdateCloseArea\n");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   buffer[0] = (uint8_t)((size & 0x000000ff) >>  0);
Packit Service ed0f68
   buffer[1] = (uint8_t)((size & 0x0000ff00) >>  8);
Packit Service ed0f68
   buffer[2] = (uint8_t)((size & 0x00ff0000) >> 16);
Packit Service ed0f68
   buffer[3] = (uint8_t)((size & 0xff000000) >> 24);
Packit Service ed0f68
Packit Service ed0f68
   buffer[4] = (uint8_t)((checksum & 0x00ff) >>  0);
Packit Service ed0f68
   buffer[5] = (uint8_t)((checksum & 0xff00) >>  8);
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA3;
Packit Service ed0f68
   req.msg.data = buffer;
Packit Service ed0f68
   req.msg.data_len = length;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateCloseArea command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdateCloseArea command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdateCloseArea command succeed");
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateGetStatus(struct ipmi_intf *intf, tImeStatus *pStatus )
Packit Service ed0f68
{
Packit Service ed0f68
   struct      ipmi_rs * rsp;
Packit Service ed0f68
   struct      ipmi_rq req;
Packit Service ed0f68
   tImeStatus *pGetStatus;
Packit Service ed0f68
   
Packit Service ed0f68
   memset(pStatus, 0, sizeof(tImeStatus));
Packit Service ed0f68
   pStatus->update_state = IME_STATE_ABORTED;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf("ImeUpdateGetStatus: ");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA6;
Packit Service ed0f68
   req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
Packit Service ed0f68
Packit Service ed0f68
   pGetStatus = (tImeStatus *) rsp->data;
Packit Service ed0f68
   
Packit Service ed0f68
   memcpy( pStatus, pGetStatus, sizeof(tImeStatus));
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf("%x - ", pStatus->updateState);
Packit Service ed0f68
Packit Service ed0f68
   switch( pStatus->update_state )
Packit Service ed0f68
   {
Packit Service ed0f68
      case IME_STATE_IDLE:
Packit Service ed0f68
         printf("IDLE\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_UPDATE_REQUESTED:
Packit Service ed0f68
         printf("Update Requested\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_UPDATE_IN_PROGRESS:
Packit Service ed0f68
         printf("Update in Progress\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_SUCCESS:
Packit Service ed0f68
         printf("Update Success\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_FAILED:
Packit Service ed0f68
         printf("Update Failed\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_ROLLED_BACK:
Packit Service ed0f68
         printf("Update Rolled Back\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_ABORTED:
Packit Service ed0f68
         printf("Update Aborted\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_INIT_FAILED:
Packit Service ed0f68
         printf("Update Init Failed\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      default:
Packit Service ed0f68
         printf("Unknown, reserved\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
   }
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateGetCapabilities(struct ipmi_intf *intf, tImeCaps *pCaps )
Packit Service ed0f68
{
Packit Service ed0f68
   struct      ipmi_rs * rsp;
Packit Service ed0f68
   struct      ipmi_rq req;
Packit Service ed0f68
   tImeCaps *  pGetCaps;
Packit Service ed0f68
   
Packit Service ed0f68
   memset(pCaps, 0, sizeof(tImeCaps));
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf("ImeUpdateGetStatus: ");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA7;
Packit Service ed0f68
   req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
Packit Service ed0f68
Packit Service ed0f68
   pGetCaps = (tImeCaps *) rsp->data;
Packit Service ed0f68
   
Packit Service ed0f68
   memcpy( pCaps, pGetCaps, sizeof(tImeCaps));
Packit Service ed0f68
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateRegisterUpdate(struct ipmi_intf *intf, tImeUpdateType type)
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   uint8_t buffer[ 2 ];
Packit Service ed0f68
Packit Service ed0f68
   #ifdef OUTPUT_DEBUG
Packit Service ed0f68
   printf( "ImeUpdateRegisterUpdate\n");
Packit Service ed0f68
   #endif
Packit Service ed0f68
Packit Service ed0f68
   buffer[0] = type;  // Normal Update
Packit Service ed0f68
   buffer[1] = 0;  // Flags, reserved
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA4;
Packit Service ed0f68
   req.msg.data = buffer;
Packit Service ed0f68
   req.msg.data_len = 2;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "ImeUpdateRegisterUpdate command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "ImeUpdateRegisterUpdate command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "ImeUpdateRegisterUpdate command succeed");
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeUpdateShowStatus(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
   struct ipmi_rs * rsp;
Packit Service ed0f68
   struct ipmi_rq req;
Packit Service ed0f68
   tImeStatus *pStatus;
Packit Service ed0f68
Packit Service ed0f68
   printf("ImeUpdateGetStatus: ");
Packit Service ed0f68
Packit Service ed0f68
   memset(&req, 0, sizeof(req));
Packit Service ed0f68
   req.msg.netfn = 0x30;  // OEM NetFn
Packit Service ed0f68
   req.msg.cmd = 0xA6;
Packit Service ed0f68
   req.msg.data_len = 0;
Packit Service ed0f68
Packit Service ed0f68
   rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
   if (rsp == NULL) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   if (rsp->ccode > 0) {
Packit Service ed0f68
      lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
Packit Service ed0f68
         val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
Packit Service ed0f68
Packit Service ed0f68
   pStatus = (tImeStatus *) rsp->data ;
Packit Service ed0f68
Packit Service ed0f68
   
Packit Service ed0f68
   printf("image_status: %x - ", pStatus->image_status);
Packit Service ed0f68
Packit Service ed0f68
   printf("update_state: %x - ", pStatus->update_state);
Packit Service ed0f68
Packit Service ed0f68
   switch( pStatus->update_state )
Packit Service ed0f68
   {
Packit Service ed0f68
      case IME_STATE_IDLE:
Packit Service ed0f68
         printf("IDLE\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_UPDATE_REQUESTED:
Packit Service ed0f68
         printf("Update Requested\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_UPDATE_IN_PROGRESS:
Packit Service ed0f68
         printf("Update in Progress\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_SUCCESS:
Packit Service ed0f68
         printf("Update Success\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_FAILED:
Packit Service ed0f68
         printf("Update Failed\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_ROLLED_BACK:
Packit Service ed0f68
         printf("Update Rolled Back\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_ABORTED:
Packit Service ed0f68
         printf("Update Aborted\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      case IME_STATE_INIT_FAILED:
Packit Service ed0f68
         printf("Update Init Failed\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
      default:
Packit Service ed0f68
         printf("Unknown, reserved\n");
Packit Service ed0f68
      break;
Packit Service ed0f68
   }
Packit Service ed0f68
   printf("update_attempt_status  : %x\n", pStatus->update_attempt_status);
Packit Service ed0f68
   printf("rollback_attempt_status: %x\n", pStatus->rollback_attempt_status);
Packit Service ed0f68
   printf("update_type            : %x\n", pStatus->update_type);
Packit Service ed0f68
   printf("dependent_flag         : %x\n", pStatus->dependent_flag);
Packit Service ed0f68
   printf("free_area_size         : %x\n", pStatus->free_area_size[0]);
Packit Service ed0f68
   printf("                       : %x\n", pStatus->free_area_size[1]);
Packit Service ed0f68
   printf("                       : %x\n", pStatus->free_area_size[2]);
Packit Service ed0f68
   printf("                       : %x\n", pStatus->free_area_size[3]);
Packit Service ed0f68
Packit Service ed0f68
   return IME_SUCCESS;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeImageCtxFromFile(
Packit Service ed0f68
                                 char* imageFilename, 
Packit Service ed0f68
                                 tImeUpdateImageCtx * pImageCtx
Packit Service ed0f68
                               )
Packit Service ed0f68
{
Packit Service ed0f68
   int rc = IME_SUCCESS;
Packit Service ed0f68
   FILE* pImageFile = fopen(imageFilename, "rb");
Packit Service ed0f68
   
Packit Service ed0f68
   if ( pImageFile == NULL )
Packit Service ed0f68
   {
Packit Service ed0f68
      lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename);
Packit Service ed0f68
      rc = IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
   
Packit Service ed0f68
   if ( rc == IME_SUCCESS )
Packit Service ed0f68
   {
Packit Service ed0f68
      /* Get the raw data in file */
Packit Service ed0f68
      fseek(pImageFile, 0, SEEK_END);
Packit Service ed0f68
      pImageCtx->size  = ftell(pImageFile); 
Packit Service ed0f68
      if (pImageCtx->size <= 0) {
Packit Service ed0f68
         if (pImageCtx->size < 0)
Packit Service ed0f68
            lprintf(LOG_ERR, "Error seeking %s. %s\n", imageFilename, strerror(errno));
Packit Service ed0f68
         rc = IME_ERROR;
Packit Service ed0f68
         fclose(pImageFile);
Packit Service ed0f68
         return rc;
Packit Service ed0f68
      }
Packit Service ed0f68
      pImageCtx->pData = malloc(sizeof(unsigned char)*pImageCtx->size);
Packit Service ed0f68
      rewind(pImageFile);
Packit Service ed0f68
Packit Service ed0f68
      if ( pImageCtx->pData != NULL )
Packit Service ed0f68
      {
Packit Service ed0f68
         if (pImageCtx->size < fread(pImageCtx->pData, sizeof(unsigned char), 
Packit Service ed0f68
                                                   pImageCtx->size, pImageFile))
Packit Service ed0f68
            rc = IME_ERROR;
Packit Service ed0f68
      }
Packit Service ed0f68
      else
Packit Service ed0f68
      {
Packit Service ed0f68
         rc = IME_ERROR;
Packit Service ed0f68
      }
Packit Service ed0f68
   }
Packit Service ed0f68
   
Packit Service ed0f68
   // Calculate checksum CRC8  
Packit Service ed0f68
   if ( rc == IME_SUCCESS )
Packit Service ed0f68
   {
Packit Service ed0f68
      pImageCtx->crc8 = ImeCrc8(pImageCtx->size, pImageCtx->pData);
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
    
Packit Service ed0f68
   if( pImageFile != NULL)
Packit Service ed0f68
   {
Packit Service ed0f68
      fclose(pImageFile);
Packit Service ed0f68
   }
Packit Service ed0f68
    
Packit Service ed0f68
   return rc;
Packit Service ed0f68
}  
Packit Service ed0f68
Packit Service ed0f68
static uint8_t ImeCrc8( uint32_t length, uint8_t * pBuf )
Packit Service ed0f68
{
Packit Service ed0f68
   uint8_t crc = 0;
Packit Service ed0f68
   uint32_t bufCount;
Packit Service ed0f68
Packit Service ed0f68
   for ( bufCount = 0; bufCount < length; bufCount++ )
Packit Service ed0f68
   {
Packit Service ed0f68
      uint8_t count;
Packit Service ed0f68
Packit Service ed0f68
      crc = crc ^ pBuf[bufCount];
Packit Service ed0f68
  
Packit Service ed0f68
      for ( count = 0; count < 8; count++ ) 
Packit Service ed0f68
      {
Packit Service ed0f68
         if (( crc & 0x80 ) != 0 )
Packit Service ed0f68
         {
Packit Service ed0f68
            crc <<= 1;
Packit Service ed0f68
            crc ^= 0x07;
Packit Service ed0f68
         }
Packit Service ed0f68
         else
Packit Service ed0f68
         {
Packit Service ed0f68
            crc <<= 1;
Packit Service ed0f68
         }
Packit Service ed0f68
      }
Packit Service ed0f68
   }
Packit Service ed0f68
Packit Service ed0f68
   lprintf(LOG_DEBUG,"CRC8: %02xh\n", crc);
Packit Service ed0f68
   return crc;
Packit Service ed0f68
} 
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int ImeManualRollback(struct ipmi_intf *intf)
Packit Service ed0f68
{
Packit Service ed0f68
   int rc = IME_SUCCESS;
Packit Service ed0f68
   tImeStatus imeStatus;
Packit Service ed0f68
Packit Service ed0f68
   rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_MANUAL_ROLLBACK);
Packit Service ed0f68
   ImeUpdateGetStatus(intf,&imeStatus);
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
   if(
Packit Service ed0f68
      (rc == IME_SUCCESS) &&
Packit Service ed0f68
      (imeStatus.update_state == IME_STATE_ROLLED_BACK) 
Packit Service ed0f68
     )
Packit Service ed0f68
   {
Packit Service ed0f68
      printf("Manual Rollback Succeed\n");
Packit Service ed0f68
      return IME_SUCCESS;
Packit Service ed0f68
   }
Packit Service ed0f68
   else
Packit Service ed0f68
   {
Packit Service ed0f68
      printf("Manual Rollback Completed With Error\n");
Packit Service ed0f68
      return IME_ERROR;
Packit Service ed0f68
   }
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static void ImePrintUsage(void)
Packit Service ed0f68
{
Packit Service ed0f68
   lprintf(LOG_NOTICE,"help                    - This help menu");   
Packit Service ed0f68
   lprintf(LOG_NOTICE,"info                    - Information about the present Intel ME");   
Packit Service ed0f68
   lprintf(LOG_NOTICE,"update <file>           - Upgrade the ME firmware from received image <file>");
Packit Service ed0f68
   lprintf(LOG_NOTICE,"rollback                - Manual Rollback ME");
Packit Service ed0f68
//   lprintf(LOG_NOTICE,"rollback                - Rollback ME Firmware");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
int ipmi_ime_main(struct ipmi_intf * intf, int argc, char ** argv)
Packit Service ed0f68
{
Packit Service ed0f68
   int rc = IME_SUCCESS;
Packit Service ed0f68
   
Packit Service ed0f68
   lprintf(LOG_DEBUG,"ipmi_ime_main()");
Packit Service ed0f68
   
Packit Service ed0f68
Packit Service ed0f68
   if ( (argc == 0) || (strcmp(argv[0], "help") == 0) ) 
Packit Service ed0f68
   {
Packit Service ed0f68
      ImePrintUsage();
Packit Service ed0f68
   }
Packit Service ed0f68
   else if ( (argc == 0) || (strcmp(argv[0], "info") == 0) ) 
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeGetInfo(intf);
Packit Service ed0f68
   }
Packit Service ed0f68
   else if ( strcmp(argv[0], "update") == 0) 
Packit Service ed0f68
   {
Packit Service ed0f68
      if(argc == 2)
Packit Service ed0f68
      {
Packit Service ed0f68
         lprintf(LOG_NOTICE,"Update using file: %s", argv[1]);
Packit Service ed0f68
         rc = ImeUpgrade(intf, argv[1]);
Packit Service ed0f68
      }
Packit Service ed0f68
      else
Packit Service ed0f68
      {
Packit Service ed0f68
         lprintf(LOG_ERROR,"File must be provided with this option, see help\n");
Packit Service ed0f68
         rc = IME_ERROR;
Packit Service ed0f68
      }
Packit Service ed0f68
   }
Packit Service ed0f68
   else if ( (argc == 0) || (strcmp(argv[0], "rollback") == 0) ) 
Packit Service ed0f68
   {
Packit Service ed0f68
      rc = ImeManualRollback(intf);
Packit Service ed0f68
   }
Packit Service ed0f68
   else
Packit Service ed0f68
   {
Packit Service ed0f68
      ImePrintUsage(); 
Packit Service ed0f68
   }
Packit Service ed0f68
   
Packit Service ed0f68
   return rc;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68