xref: /openbmc/ipmitool/lib/ipmi_ime.c (revision 2d79e69f)
1*c18ec02fSPetter Reinholdtsen /*
2*c18ec02fSPetter Reinholdtsen  * Copyright (c) 2007 Kontron Canada, Inc.  All Rights Reserved.
3*c18ec02fSPetter Reinholdtsen  *
4*c18ec02fSPetter Reinholdtsen  * Base on code from
5*c18ec02fSPetter Reinholdtsen  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
6*c18ec02fSPetter Reinholdtsen  *
7*c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
8*c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
9*c18ec02fSPetter Reinholdtsen  * are met:
10*c18ec02fSPetter Reinholdtsen  *
11*c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
12*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
13*c18ec02fSPetter Reinholdtsen  *
14*c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
15*c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
16*c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
17*c18ec02fSPetter Reinholdtsen  *
18*c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
19*c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
20*c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
21*c18ec02fSPetter Reinholdtsen  *
22*c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
23*c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
24*c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
25*c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
26*c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
27*c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
28*c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
29*c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
30*c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
31*c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
32*c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
33*c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34*c18ec02fSPetter Reinholdtsen  */
35*c18ec02fSPetter Reinholdtsen 
36*c18ec02fSPetter Reinholdtsen /****************************************************************************
37*c18ec02fSPetter Reinholdtsen *
38*c18ec02fSPetter Reinholdtsen *       Copyright (c) 2009 Kontron Canada, Inc.  All Rights Reserved.
39*c18ec02fSPetter Reinholdtsen *
40*c18ec02fSPetter Reinholdtsen *                              IME
41*c18ec02fSPetter Reinholdtsen *                    Intel Manageability Engine
42*c18ec02fSPetter Reinholdtsen *                      Firmware Update Agent
43*c18ec02fSPetter Reinholdtsen *
44*c18ec02fSPetter Reinholdtsen * The ME is an IPMI-enabled component included in Intel(R) Next Generation
45*c18ec02fSPetter Reinholdtsen *  Server Chipset Nehalem-EP platforms.
46*c18ec02fSPetter Reinholdtsen *
47*c18ec02fSPetter Reinholdtsen * These are a few synonyms for the ME :
48*c18ec02fSPetter Reinholdtsen *
49*c18ec02fSPetter Reinholdtsen * - Dynamic Power Node Manager
50*c18ec02fSPetter Reinholdtsen * - Intelligent Power Node Manager
51*c18ec02fSPetter Reinholdtsen *
52*c18ec02fSPetter Reinholdtsen * Consult Intel litterature for more information on this technology.
53*c18ec02fSPetter Reinholdtsen *
54*c18ec02fSPetter Reinholdtsen * The ME firmware resides on the platform boot flash and contains read only
55*c18ec02fSPetter Reinholdtsen * boot code for the ME as well as boot image redundancy support.
56*c18ec02fSPetter Reinholdtsen *
57*c18ec02fSPetter Reinholdtsen * This module implements an Upgrade Agent for the ME firwmare. Because the ME
58*c18ec02fSPetter Reinholdtsen * implements IPMI command handling, the agent speaks directly to the ME. In other
59*c18ec02fSPetter Reinholdtsen * words, in order the reach the ME, the BMC must implement IPMB bridging.
60*c18ec02fSPetter Reinholdtsen *
61*c18ec02fSPetter Reinholdtsen * The update is done through IPMI (this is IPMITOOL right !), not HECI.
62*c18ec02fSPetter Reinholdtsen *
63*c18ec02fSPetter Reinholdtsen * Example: ME available at address 0x88 on IPMI channel 8:
64*c18ec02fSPetter Reinholdtsen *   ipmitool  -m 0x20 -t 0x88 -b 8 ime info
65*c18ec02fSPetter Reinholdtsen *
66*c18ec02fSPetter Reinholdtsen * !! WARNING - You MUST use an image provided by your board vendor. - WARNING !!
67*c18ec02fSPetter Reinholdtsen *
68*c18ec02fSPetter Reinholdtsen * author:
69*c18ec02fSPetter Reinholdtsen *  Jean-Michel.Audet@ca.kontron.com
70*c18ec02fSPetter Reinholdtsen *  Francois.Isabelle@ca.kontron.com
71*c18ec02fSPetter Reinholdtsen *
72*c18ec02fSPetter Reinholdtsen *****************************************************************************/
73*c18ec02fSPetter Reinholdtsen /*
74*c18ec02fSPetter Reinholdtsen  * HISTORY
75*c18ec02fSPetter Reinholdtsen  * ===========================================================================
76*c18ec02fSPetter Reinholdtsen  * 2009-04-20
77*c18ec02fSPetter Reinholdtsen  *
78*c18ec02fSPetter Reinholdtsen  * First public release of Kontron
79*c18ec02fSPetter Reinholdtsen  *
80*c18ec02fSPetter Reinholdtsen */
81*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_ime.h>
82*c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
83*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
84*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
85*c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
86*c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
87*c18ec02fSPetter Reinholdtsen 
88*c18ec02fSPetter Reinholdtsen 
89*c18ec02fSPetter Reinholdtsen #undef OUTPUT_DEBUG
90*c18ec02fSPetter Reinholdtsen 
91*c18ec02fSPetter Reinholdtsen #include <stdlib.h>
92*c18ec02fSPetter Reinholdtsen #include <string.h>
93*c18ec02fSPetter Reinholdtsen #include <errno.h>
94*c18ec02fSPetter Reinholdtsen #include <time.h>
95*c18ec02fSPetter Reinholdtsen 
96*c18ec02fSPetter Reinholdtsen static const int IME_SUCCESS              = 0;
97*c18ec02fSPetter Reinholdtsen static const int IME_ERROR                = -1;
98*c18ec02fSPetter Reinholdtsen static const int IME_RESTART              = -2;
99*c18ec02fSPetter Reinholdtsen 
100*c18ec02fSPetter Reinholdtsen #define IME_UPGRADE_BUFFER_SIZE           22
101*c18ec02fSPetter Reinholdtsen #define IME_RETRY_COUNT                   5
102*c18ec02fSPetter Reinholdtsen 
103*c18ec02fSPetter Reinholdtsen typedef struct ImeUpdateImageCtx
104*c18ec02fSPetter Reinholdtsen {
105*c18ec02fSPetter Reinholdtsen    uint32_t   size;
106*c18ec02fSPetter Reinholdtsen    uint8_t *  pData;
107*c18ec02fSPetter Reinholdtsen    uint8_t    crc8;
108*c18ec02fSPetter Reinholdtsen }tImeUpdateImageCtx;
109*c18ec02fSPetter Reinholdtsen 
110*c18ec02fSPetter Reinholdtsen typedef enum eImeState
111*c18ec02fSPetter Reinholdtsen {
112*c18ec02fSPetter Reinholdtsen    IME_STATE_IDLE                = 0,
113*c18ec02fSPetter Reinholdtsen    IME_STATE_UPDATE_REQUESTED    = 1,
114*c18ec02fSPetter Reinholdtsen    IME_STATE_UPDATE_IN_PROGRESS  = 2,
115*c18ec02fSPetter Reinholdtsen    IME_STATE_SUCCESS             = 3,
116*c18ec02fSPetter Reinholdtsen    IME_STATE_FAILED              = 4,
117*c18ec02fSPetter Reinholdtsen    IME_STATE_ROLLED_BACK         = 5,
118*c18ec02fSPetter Reinholdtsen    IME_STATE_ABORTED             = 6,
119*c18ec02fSPetter Reinholdtsen    IME_STATE_INIT_FAILED         = 7
120*c18ec02fSPetter Reinholdtsen } tImeStateEnum;
121*c18ec02fSPetter Reinholdtsen 
122*c18ec02fSPetter Reinholdtsen 
123*c18ec02fSPetter Reinholdtsen typedef enum tImeUpdateType
124*c18ec02fSPetter Reinholdtsen {
125*c18ec02fSPetter Reinholdtsen    IME_UPDTYPE_NORMAL            = 1,
126*c18ec02fSPetter Reinholdtsen    IME_UPDTYPE_MANUAL_ROLLBACK   = 3,
127*c18ec02fSPetter Reinholdtsen    IME_UPDTYPE_ABORT             = 4
128*c18ec02fSPetter Reinholdtsen } tImeUpdateType;
129*c18ec02fSPetter Reinholdtsen 
130*c18ec02fSPetter Reinholdtsen 
131*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
132*c18ec02fSPetter Reinholdtsen #pragma pack(1)
133*c18ec02fSPetter Reinholdtsen #endif
134*c18ec02fSPetter Reinholdtsen typedef struct sImeStatus {
135*c18ec02fSPetter Reinholdtsen    uint8_t image_status;
136*c18ec02fSPetter Reinholdtsen    tImeStateEnum update_state;
137*c18ec02fSPetter Reinholdtsen    uint8_t update_attempt_status;
138*c18ec02fSPetter Reinholdtsen    uint8_t rollback_attempt_status;
139*c18ec02fSPetter Reinholdtsen    uint8_t update_type;
140*c18ec02fSPetter Reinholdtsen    uint8_t dependent_flag;
141*c18ec02fSPetter Reinholdtsen    uint8_t free_area_size[4];
142*c18ec02fSPetter Reinholdtsen } ATTRIBUTE_PACKING tImeStatus ;
143*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
144*c18ec02fSPetter Reinholdtsen #pragma pack(0)
145*c18ec02fSPetter Reinholdtsen #endif
146*c18ec02fSPetter Reinholdtsen 
147*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
148*c18ec02fSPetter Reinholdtsen #pragma pack(1)
149*c18ec02fSPetter Reinholdtsen #endif
150*c18ec02fSPetter Reinholdtsen typedef struct sImeCaps {
151*c18ec02fSPetter Reinholdtsen    uint8_t area_supported;
152*c18ec02fSPetter Reinholdtsen    uint8_t special_caps;
153*c18ec02fSPetter Reinholdtsen } ATTRIBUTE_PACKING tImeCaps ;
154*c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
155*c18ec02fSPetter Reinholdtsen #pragma pack(0)
156*c18ec02fSPetter Reinholdtsen #endif
157*c18ec02fSPetter Reinholdtsen 
158*c18ec02fSPetter Reinholdtsen 
159*c18ec02fSPetter Reinholdtsen static void ImePrintUsage(void);
160*c18ec02fSPetter Reinholdtsen static int  ImeGetInfo(struct ipmi_intf *intf);
161*c18ec02fSPetter Reinholdtsen static int  ImeUpgrade(struct ipmi_intf *intf, char* imageFilename);
162*c18ec02fSPetter Reinholdtsen static int  ImeManualRollback(struct ipmi_intf *intf);
163*c18ec02fSPetter Reinholdtsen static int  ImeUpdatePrepare(struct ipmi_intf *intf);
164*c18ec02fSPetter Reinholdtsen static int  ImeUpdateOpenArea(struct ipmi_intf *intf);
165*c18ec02fSPetter Reinholdtsen static int  ImeUpdateWriteArea(
166*c18ec02fSPetter Reinholdtsen                               struct ipmi_intf *intf,
167*c18ec02fSPetter Reinholdtsen                               uint8_t sequence,
168*c18ec02fSPetter Reinholdtsen                               uint8_t length,
169*c18ec02fSPetter Reinholdtsen                               uint8_t * pBuf
170*c18ec02fSPetter Reinholdtsen                           );
171*c18ec02fSPetter Reinholdtsen static int  ImeUpdateCloseArea(
172*c18ec02fSPetter Reinholdtsen                               struct ipmi_intf *intf,
173*c18ec02fSPetter Reinholdtsen                               uint32_t size,
174*c18ec02fSPetter Reinholdtsen                               uint16_t checksum
175*c18ec02fSPetter Reinholdtsen                           );
176*c18ec02fSPetter Reinholdtsen 
177*c18ec02fSPetter Reinholdtsen static int ImeUpdateGetStatus(struct ipmi_intf *intf, tImeStatus *pStatus);
178*c18ec02fSPetter Reinholdtsen static int ImeUpdateGetCapabilities(struct ipmi_intf *intf, tImeCaps *pCaps );
179*c18ec02fSPetter Reinholdtsen static int  ImeUpdateRegisterUpdate(struct ipmi_intf *intf, tImeUpdateType type);
180*c18ec02fSPetter Reinholdtsen 
181*c18ec02fSPetter Reinholdtsen static int  ImeImageCtxFromFile(
182*c18ec02fSPetter Reinholdtsen                                  char * imageFilename,
183*c18ec02fSPetter Reinholdtsen                                  tImeUpdateImageCtx * pImageCtx);
184*c18ec02fSPetter Reinholdtsen static int ImeUpdateShowStatus(struct ipmi_intf *intf);
185*c18ec02fSPetter Reinholdtsen 
186*c18ec02fSPetter Reinholdtsen static uint8_t ImeCrc8( uint32_t length, uint8_t * pBuf );
187*c18ec02fSPetter Reinholdtsen 
188*c18ec02fSPetter Reinholdtsen 
ImeGetInfo(struct ipmi_intf * intf)189*c18ec02fSPetter Reinholdtsen static int ImeGetInfo(struct ipmi_intf *intf)
190*c18ec02fSPetter Reinholdtsen {
191*c18ec02fSPetter Reinholdtsen    int rc = IME_ERROR;
192*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
193*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
194*c18ec02fSPetter Reinholdtsen    struct ipm_devid_rsp *devid;
195*c18ec02fSPetter Reinholdtsen    const char *product=NULL;
196*c18ec02fSPetter Reinholdtsen    tImeStatus status;
197*c18ec02fSPetter Reinholdtsen    tImeCaps caps;
198*c18ec02fSPetter Reinholdtsen 
199*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
200*c18ec02fSPetter Reinholdtsen    req.msg.netfn = IPMI_NETFN_APP;
201*c18ec02fSPetter Reinholdtsen    req.msg.cmd = BMC_GET_DEVICE_ID;
202*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 0;
203*c18ec02fSPetter Reinholdtsen 
204*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
205*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
206*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "Get Device ID command failed");
207*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
208*c18ec02fSPetter Reinholdtsen    }
209*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
210*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "Get Device ID command failed: %s",
211*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
212*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
213*c18ec02fSPetter Reinholdtsen    }
214*c18ec02fSPetter Reinholdtsen 
215*c18ec02fSPetter Reinholdtsen    devid = (struct ipm_devid_rsp *) rsp->data;
216*c18ec02fSPetter Reinholdtsen 
217*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG,"Device ID                 : %i", devid->device_id);
218*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG,"Device Revision           : %i",
219*c18ec02fSPetter Reinholdtsen                            devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK);
220*c18ec02fSPetter Reinholdtsen 
221*c18ec02fSPetter Reinholdtsen    if(
222*c18ec02fSPetter Reinholdtsen       (devid->device_id == 0)
223*c18ec02fSPetter Reinholdtsen       &&
224*c18ec02fSPetter Reinholdtsen       ((devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK) == 0)
225*c18ec02fSPetter Reinholdtsen       &&
226*c18ec02fSPetter Reinholdtsen       (
227*c18ec02fSPetter Reinholdtsen          (devid->manufacturer_id[0] == 0x57) // Intel
228*c18ec02fSPetter Reinholdtsen          &&
229*c18ec02fSPetter Reinholdtsen          (devid->manufacturer_id[1] == 0x01) // Intel
230*c18ec02fSPetter Reinholdtsen          &&
231*c18ec02fSPetter Reinholdtsen          (devid->manufacturer_id[2] == 0x00) // Intel
232*c18ec02fSPetter Reinholdtsen       )
233*c18ec02fSPetter Reinholdtsen       &&
234*c18ec02fSPetter Reinholdtsen       (
235*c18ec02fSPetter Reinholdtsen          (devid->product_id[1] == 0x0b)
236*c18ec02fSPetter Reinholdtsen          &&
237*c18ec02fSPetter Reinholdtsen          (devid->product_id[0] == 0x00)
238*c18ec02fSPetter Reinholdtsen       )
239*c18ec02fSPetter Reinholdtsen      )
240*c18ec02fSPetter Reinholdtsen    {
241*c18ec02fSPetter Reinholdtsen       rc = IME_SUCCESS;
242*c18ec02fSPetter Reinholdtsen       printf("Manufacturer Name          : %s\n",
243*c18ec02fSPetter Reinholdtsen                val2str( (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id),
244*c18ec02fSPetter Reinholdtsen                ipmi_oem_info) );
245*c18ec02fSPetter Reinholdtsen 
246*c18ec02fSPetter Reinholdtsen       printf("Product ID                 : %u (0x%02x%02x)\n",
247*c18ec02fSPetter Reinholdtsen          buf2short((uint8_t *)(devid->product_id)),
248*c18ec02fSPetter Reinholdtsen          devid->product_id[1], devid->product_id[0]);
249*c18ec02fSPetter Reinholdtsen 
250*c18ec02fSPetter Reinholdtsen       product=oemval2str(IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id),
251*c18ec02fSPetter Reinholdtsen                       (devid->product_id[1]<<8)+devid->product_id[0],
252*c18ec02fSPetter Reinholdtsen                       ipmi_oem_product_info);
253*c18ec02fSPetter Reinholdtsen 
254*c18ec02fSPetter Reinholdtsen       if (product!=NULL)
255*c18ec02fSPetter Reinholdtsen       {
256*c18ec02fSPetter Reinholdtsen          printf("Product Name               : %s\n", product);
257*c18ec02fSPetter Reinholdtsen       }
258*c18ec02fSPetter Reinholdtsen 
259*c18ec02fSPetter Reinholdtsen       printf("Intel ME Firmware Revision : %x.%02x.%02x.%x%x%x.%x\n",
260*c18ec02fSPetter Reinholdtsen             ((devid->fw_rev1 & IPM_DEV_FWREV1_MAJOR_MASK )         ),
261*c18ec02fSPetter Reinholdtsen             ((devid->fw_rev2                             ) >>     4),
262*c18ec02fSPetter Reinholdtsen             ((devid->fw_rev2                             )  &  0x0f),
263*c18ec02fSPetter Reinholdtsen             ((devid->aux_fw_rev[1]                       ) >>     4),
264*c18ec02fSPetter Reinholdtsen             ((devid->aux_fw_rev[1]                       )  &  0x0f),
265*c18ec02fSPetter Reinholdtsen             ((devid->aux_fw_rev[2]                       ) >>     4),
266*c18ec02fSPetter Reinholdtsen             ((devid->aux_fw_rev[2]                       )  &  0x0f)
267*c18ec02fSPetter Reinholdtsen       );
268*c18ec02fSPetter Reinholdtsen 
269*c18ec02fSPetter Reinholdtsen       printf("SPS FW IPMI cmd version    : %x.%x\n",
270*c18ec02fSPetter Reinholdtsen          devid->aux_fw_rev[0] >>     4,
271*c18ec02fSPetter Reinholdtsen          devid->aux_fw_rev[0] &  0x0f);
272*c18ec02fSPetter Reinholdtsen 
273*c18ec02fSPetter Reinholdtsen       lprintf(LOG_DEBUG,"Flags: %xh", devid->aux_fw_rev[3]);
274*c18ec02fSPetter Reinholdtsen 
275*c18ec02fSPetter Reinholdtsen       printf("Current Image Type         : ");
276*c18ec02fSPetter Reinholdtsen       switch( (devid->aux_fw_rev[3] & 0x03) )
277*c18ec02fSPetter Reinholdtsen       {
278*c18ec02fSPetter Reinholdtsen          case 0:
279*c18ec02fSPetter Reinholdtsen             printf("Recovery\n");
280*c18ec02fSPetter Reinholdtsen          break;
281*c18ec02fSPetter Reinholdtsen 
282*c18ec02fSPetter Reinholdtsen          case 1:
283*c18ec02fSPetter Reinholdtsen             printf("Operational Image 1\n");
284*c18ec02fSPetter Reinholdtsen          break;
285*c18ec02fSPetter Reinholdtsen 
286*c18ec02fSPetter Reinholdtsen          case 2:
287*c18ec02fSPetter Reinholdtsen             printf("Operational Image 2\n");
288*c18ec02fSPetter Reinholdtsen          break;
289*c18ec02fSPetter Reinholdtsen 
290*c18ec02fSPetter Reinholdtsen          case 3:
291*c18ec02fSPetter Reinholdtsen          default:
292*c18ec02fSPetter Reinholdtsen             printf("Unknown\n");
293*c18ec02fSPetter Reinholdtsen          break;
294*c18ec02fSPetter Reinholdtsen       }
295*c18ec02fSPetter Reinholdtsen    }
296*c18ec02fSPetter Reinholdtsen    else
297*c18ec02fSPetter Reinholdtsen    {
298*c18ec02fSPetter Reinholdtsen          printf("Supported ME not found\n");
299*c18ec02fSPetter Reinholdtsen    }
300*c18ec02fSPetter Reinholdtsen 
301*c18ec02fSPetter Reinholdtsen    if(rc == IME_SUCCESS)
302*c18ec02fSPetter Reinholdtsen    {
303*c18ec02fSPetter Reinholdtsen       rc = ImeUpdateGetStatus(intf, &status);
304*c18ec02fSPetter Reinholdtsen 
305*c18ec02fSPetter Reinholdtsen       if(rc == IME_SUCCESS)
306*c18ec02fSPetter Reinholdtsen       {
307*c18ec02fSPetter Reinholdtsen          rc = ImeUpdateGetCapabilities(intf, &caps);
308*c18ec02fSPetter Reinholdtsen       }
309*c18ec02fSPetter Reinholdtsen 
310*c18ec02fSPetter Reinholdtsen    }
311*c18ec02fSPetter Reinholdtsen 
312*c18ec02fSPetter Reinholdtsen    if(rc == IME_SUCCESS)
313*c18ec02fSPetter Reinholdtsen    {
314*c18ec02fSPetter Reinholdtsen       uint8_t newImage  = ((status.image_status >> 1) & 0x01);
315*c18ec02fSPetter Reinholdtsen       uint8_t rollImage = ((status.image_status >> 2) & 0x01);
316*c18ec02fSPetter Reinholdtsen       uint8_t runArea   = ((status.image_status >> 3) & 0x03);
317*c18ec02fSPetter Reinholdtsen       uint8_t rollSup   = ((caps.special_caps   >> 0) & 0x01);
318*c18ec02fSPetter Reinholdtsen       uint8_t recovSup  = ((caps.special_caps   >> 1) & 0x01);
319*c18ec02fSPetter Reinholdtsen 
320*c18ec02fSPetter Reinholdtsen       uint8_t operSup   = ((caps.area_supported   >> 1) & 0x01);
321*c18ec02fSPetter Reinholdtsen       uint8_t piaSup    = ((caps.area_supported   >> 2) & 0x01);
322*c18ec02fSPetter Reinholdtsen       uint8_t sdrSup    = ((caps.area_supported   >> 3) & 0x01);
323*c18ec02fSPetter Reinholdtsen 
324*c18ec02fSPetter Reinholdtsen       printf("\nSupported Area\n");
325*c18ec02fSPetter Reinholdtsen       printf("   Operation Code          : %s\n", (operSup ? "Supported" : "Unsupported"));
326*c18ec02fSPetter Reinholdtsen       printf("   PIA                     : %s\n", (piaSup ? "Supported" : "Unsupported"));
327*c18ec02fSPetter Reinholdtsen       printf("   SDR                     : %s\n", (sdrSup ? "Supported" : "Unsupported"));
328*c18ec02fSPetter Reinholdtsen 
329*c18ec02fSPetter Reinholdtsen       printf("\nSpecial Capabilities\n");
330*c18ec02fSPetter Reinholdtsen       printf("   Rollback                : %s\n", (rollSup ? "Supported" : "Unsupported"));
331*c18ec02fSPetter Reinholdtsen       printf("   Recovery                : %s\n", (recovSup ? "Supported" : "Unsupported"));
332*c18ec02fSPetter Reinholdtsen 
333*c18ec02fSPetter Reinholdtsen       printf("\nImage Status\n");
334*c18ec02fSPetter Reinholdtsen       printf("   Staging (new)           : %s\n", (newImage ? "Valid" : "Invalid"));
335*c18ec02fSPetter Reinholdtsen       printf("   Rollback                : %s\n", (rollImage ? "Valid" : "Invalid"));
336*c18ec02fSPetter Reinholdtsen       if(runArea == 0)
337*c18ec02fSPetter Reinholdtsen          printf("   Running Image Area      : CODE\n");
338*c18ec02fSPetter Reinholdtsen       else
339*c18ec02fSPetter Reinholdtsen          printf("   Running Image Area      : CODE%d\n", runArea);
340*c18ec02fSPetter Reinholdtsen 
341*c18ec02fSPetter Reinholdtsen   }
342*c18ec02fSPetter Reinholdtsen 
343*c18ec02fSPetter Reinholdtsen    return rc;
344*c18ec02fSPetter Reinholdtsen }
345*c18ec02fSPetter Reinholdtsen 
346*c18ec02fSPetter Reinholdtsen 
ImeUpgrade(struct ipmi_intf * intf,char * imageFilename)347*c18ec02fSPetter Reinholdtsen static int ImeUpgrade(struct ipmi_intf *intf, char* imageFilename)
348*c18ec02fSPetter Reinholdtsen {
349*c18ec02fSPetter Reinholdtsen    int rc = IME_SUCCESS;
350*c18ec02fSPetter Reinholdtsen    tImeUpdateImageCtx imgCtx;
351*c18ec02fSPetter Reinholdtsen    tImeStatus imeStatus;
352*c18ec02fSPetter Reinholdtsen    time_t start,end,current;
353*c18ec02fSPetter Reinholdtsen 
354*c18ec02fSPetter Reinholdtsen    time(&start);
355*c18ec02fSPetter Reinholdtsen 
356*c18ec02fSPetter Reinholdtsen    memset(&imgCtx, 0, sizeof(tImeUpdateImageCtx));
357*c18ec02fSPetter Reinholdtsen 
358*c18ec02fSPetter Reinholdtsen    rc = ImeImageCtxFromFile(imageFilename, &imgCtx);
359*c18ec02fSPetter Reinholdtsen 
360*c18ec02fSPetter Reinholdtsen    if(
361*c18ec02fSPetter Reinholdtsen       (rc == IME_ERROR) ||
362*c18ec02fSPetter Reinholdtsen       (imgCtx.pData == NULL) ||
363*c18ec02fSPetter Reinholdtsen       (imgCtx.size == 0)
364*c18ec02fSPetter Reinholdtsen      )
365*c18ec02fSPetter Reinholdtsen    {
366*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
367*c18ec02fSPetter Reinholdtsen    }
368*c18ec02fSPetter Reinholdtsen 
369*c18ec02fSPetter Reinholdtsen    ImeUpdateGetStatus(intf,&imeStatus);
370*c18ec02fSPetter Reinholdtsen 
371*c18ec02fSPetter Reinholdtsen    if(rc == IME_SUCCESS)
372*c18ec02fSPetter Reinholdtsen    {
373*c18ec02fSPetter Reinholdtsen       rc = ImeUpdatePrepare(intf);
374*c18ec02fSPetter Reinholdtsen       ImeUpdateGetStatus(intf,&imeStatus);
375*c18ec02fSPetter Reinholdtsen    }
376*c18ec02fSPetter Reinholdtsen 
377*c18ec02fSPetter Reinholdtsen    if(
378*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
379*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_UPDATE_REQUESTED)
380*c18ec02fSPetter Reinholdtsen      )
381*c18ec02fSPetter Reinholdtsen    {
382*c18ec02fSPetter Reinholdtsen       rc = ImeUpdateOpenArea(intf);
383*c18ec02fSPetter Reinholdtsen       ImeUpdateGetStatus(intf,&imeStatus);
384*c18ec02fSPetter Reinholdtsen    }
385*c18ec02fSPetter Reinholdtsen    else if(rc == IME_SUCCESS)
386*c18ec02fSPetter Reinholdtsen    {
387*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERROR,"ME state error (%i), aborting", imeStatus.update_state);
388*c18ec02fSPetter Reinholdtsen       rc = IME_ERROR;
389*c18ec02fSPetter Reinholdtsen    }
390*c18ec02fSPetter Reinholdtsen 
391*c18ec02fSPetter Reinholdtsen 
392*c18ec02fSPetter Reinholdtsen    if(
393*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
394*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_UPDATE_IN_PROGRESS)
395*c18ec02fSPetter Reinholdtsen      )
396*c18ec02fSPetter Reinholdtsen    {
397*c18ec02fSPetter Reinholdtsen       uint8_t sequence = 0;
398*c18ec02fSPetter Reinholdtsen       uint32_t counter = 0;
399*c18ec02fSPetter Reinholdtsen       uint8_t retry = 0;
400*c18ec02fSPetter Reinholdtsen       uint8_t shownPercent = 0xff;
401*c18ec02fSPetter Reinholdtsen 
402*c18ec02fSPetter Reinholdtsen       while(
403*c18ec02fSPetter Reinholdtsen             (counter < imgCtx.size) &&
404*c18ec02fSPetter Reinholdtsen             (rc == IME_SUCCESS) &&
405*c18ec02fSPetter Reinholdtsen             (retry < IME_RETRY_COUNT)
406*c18ec02fSPetter Reinholdtsen            )
407*c18ec02fSPetter Reinholdtsen       {
408*c18ec02fSPetter Reinholdtsen          uint8_t length = IME_UPGRADE_BUFFER_SIZE;
409*c18ec02fSPetter Reinholdtsen          uint8_t currentPercent;
410*c18ec02fSPetter Reinholdtsen 
411*c18ec02fSPetter Reinholdtsen          if( (imgCtx.size - counter) < IME_UPGRADE_BUFFER_SIZE )
412*c18ec02fSPetter Reinholdtsen          {
413*c18ec02fSPetter Reinholdtsen             length = (imgCtx.size - counter);
414*c18ec02fSPetter Reinholdtsen          }
415*c18ec02fSPetter Reinholdtsen 
416*c18ec02fSPetter Reinholdtsen          rc = ImeUpdateWriteArea(intf,sequence,length,&imgCtx.pData[counter]);
417*c18ec02fSPetter Reinholdtsen 
418*c18ec02fSPetter Reinholdtsen          /*
419*c18ec02fSPetter Reinholdtsen          As per the flowchart Intel Dynamic Power Node Manager 1.5 IPMI Iface
420*c18ec02fSPetter Reinholdtsen          page 65
421*c18ec02fSPetter Reinholdtsen          We shall send the GetStatus command each time following a write area
422*c18ec02fSPetter Reinholdtsen          but this add too much time to the upgrade
423*c18ec02fSPetter Reinholdtsen          */
424*c18ec02fSPetter Reinholdtsen          /*  ImeUpdateGetStatus(intf,&imeStatus); */
425*c18ec02fSPetter Reinholdtsen          counter += length;
426*c18ec02fSPetter Reinholdtsen          sequence ++;
427*c18ec02fSPetter Reinholdtsen 
428*c18ec02fSPetter Reinholdtsen 
429*c18ec02fSPetter Reinholdtsen          currentPercent = ((float)counter/imgCtx.size)*100;
430*c18ec02fSPetter Reinholdtsen 
431*c18ec02fSPetter Reinholdtsen          if(currentPercent != shownPercent)
432*c18ec02fSPetter Reinholdtsen          {
433*c18ec02fSPetter Reinholdtsen             uint16_t timeElapsedSecond;
434*c18ec02fSPetter Reinholdtsen             shownPercent = currentPercent;
435*c18ec02fSPetter Reinholdtsen             printf("Percent: %02i,  ", shownPercent);
436*c18ec02fSPetter Reinholdtsen             time(&current);
437*c18ec02fSPetter Reinholdtsen             timeElapsedSecond = (current-start) + ((current-start)%60);
438*c18ec02fSPetter Reinholdtsen             printf("Elapsed time %02ld:%02ld\r",((current-start)/60), ((current-start)%60));
439*c18ec02fSPetter Reinholdtsen             fflush(stdout);
440*c18ec02fSPetter Reinholdtsen 
441*c18ec02fSPetter Reinholdtsen          }
442*c18ec02fSPetter Reinholdtsen       }
443*c18ec02fSPetter Reinholdtsen       ImeUpdateGetStatus(intf,&imeStatus);
444*c18ec02fSPetter Reinholdtsen       printf("\n");
445*c18ec02fSPetter Reinholdtsen    }
446*c18ec02fSPetter Reinholdtsen    else if(rc == IME_SUCCESS)
447*c18ec02fSPetter Reinholdtsen    {
448*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERROR,"ME state error (%i), aborting", imeStatus.update_state);
449*c18ec02fSPetter Reinholdtsen       rc = IME_ERROR;
450*c18ec02fSPetter Reinholdtsen    }
451*c18ec02fSPetter Reinholdtsen 
452*c18ec02fSPetter Reinholdtsen    if(
453*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
454*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_UPDATE_IN_PROGRESS)
455*c18ec02fSPetter Reinholdtsen      )
456*c18ec02fSPetter Reinholdtsen    {
457*c18ec02fSPetter Reinholdtsen       rc = ImeUpdateCloseArea(intf, imgCtx.size, imgCtx.crc8);
458*c18ec02fSPetter Reinholdtsen       ImeUpdateGetStatus(intf,&imeStatus);
459*c18ec02fSPetter Reinholdtsen    }
460*c18ec02fSPetter Reinholdtsen    else if(rc == IME_SUCCESS)
461*c18ec02fSPetter Reinholdtsen    {
462*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERROR,"ME state error, aborting");
463*c18ec02fSPetter Reinholdtsen       rc = IME_ERROR;
464*c18ec02fSPetter Reinholdtsen    }
465*c18ec02fSPetter Reinholdtsen 
466*c18ec02fSPetter Reinholdtsen    if(
467*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
468*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_UPDATE_REQUESTED)
469*c18ec02fSPetter Reinholdtsen      )
470*c18ec02fSPetter Reinholdtsen    {
471*c18ec02fSPetter Reinholdtsen       printf("UpdateCompleted, Activate now\n");
472*c18ec02fSPetter Reinholdtsen       rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_NORMAL);
473*c18ec02fSPetter Reinholdtsen       ImeUpdateGetStatus(intf,&imeStatus);
474*c18ec02fSPetter Reinholdtsen    }
475*c18ec02fSPetter Reinholdtsen    else if(rc == IME_SUCCESS)
476*c18ec02fSPetter Reinholdtsen    {
477*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERROR,"ME state error, aborting");
478*c18ec02fSPetter Reinholdtsen       rc = IME_ERROR;
479*c18ec02fSPetter Reinholdtsen    }
480*c18ec02fSPetter Reinholdtsen 
481*c18ec02fSPetter Reinholdtsen    if(
482*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
483*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_SUCCESS)
484*c18ec02fSPetter Reinholdtsen      )
485*c18ec02fSPetter Reinholdtsen    {
486*c18ec02fSPetter Reinholdtsen       time(&end);
487*c18ec02fSPetter Reinholdtsen       printf("Update Completed in %02ld:%02ld\n",(end-start)/60, (end-start)%60);
488*c18ec02fSPetter Reinholdtsen    }
489*c18ec02fSPetter Reinholdtsen    else
490*c18ec02fSPetter Reinholdtsen    {
491*c18ec02fSPetter Reinholdtsen       time(&end);
492*c18ec02fSPetter Reinholdtsen       printf("Update Error\n");
493*c18ec02fSPetter Reinholdtsen       printf("\nTime Taken %02ld:%02ld\n",(end-start)/60, (end-start)%60);
494*c18ec02fSPetter Reinholdtsen    }
495*c18ec02fSPetter Reinholdtsen 
496*c18ec02fSPetter Reinholdtsen    return rc;
497*c18ec02fSPetter Reinholdtsen }
498*c18ec02fSPetter Reinholdtsen 
499*c18ec02fSPetter Reinholdtsen 
ImeUpdatePrepare(struct ipmi_intf * intf)500*c18ec02fSPetter Reinholdtsen static int ImeUpdatePrepare(struct ipmi_intf *intf)
501*c18ec02fSPetter Reinholdtsen {
502*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
503*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
504*c18ec02fSPetter Reinholdtsen 
505*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
506*c18ec02fSPetter Reinholdtsen    printf("ImeUpdatePrepare\n");
507*c18ec02fSPetter Reinholdtsen    #endif
508*c18ec02fSPetter Reinholdtsen 
509*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
510*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
511*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA0;
512*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 0;
513*c18ec02fSPetter Reinholdtsen 
514*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
515*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
516*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed");
517*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
518*c18ec02fSPetter Reinholdtsen    }
519*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
520*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
521*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
522*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
523*c18ec02fSPetter Reinholdtsen    }
524*c18ec02fSPetter Reinholdtsen 
525*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
526*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
527*c18ec02fSPetter Reinholdtsen }
528*c18ec02fSPetter Reinholdtsen 
ImeUpdateOpenArea(struct ipmi_intf * intf)529*c18ec02fSPetter Reinholdtsen static int ImeUpdateOpenArea(struct ipmi_intf *intf)
530*c18ec02fSPetter Reinholdtsen {
531*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
532*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
533*c18ec02fSPetter Reinholdtsen    uint8_t buffer[ 2 ];
534*c18ec02fSPetter Reinholdtsen 
535*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
536*c18ec02fSPetter Reinholdtsen    printf("ImeUpdateOpenArea\n");
537*c18ec02fSPetter Reinholdtsen    #endif
538*c18ec02fSPetter Reinholdtsen 
539*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
540*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
541*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA1;
542*c18ec02fSPetter Reinholdtsen 
543*c18ec02fSPetter Reinholdtsen    buffer[0] = 0x01; // Area Type : Operational code
544*c18ec02fSPetter Reinholdtsen    buffer[1] = 0x00; // Reserved : 0
545*c18ec02fSPetter Reinholdtsen    req.msg.data = buffer;
546*c18ec02fSPetter Reinholdtsen 
547*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 2;
548*c18ec02fSPetter Reinholdtsen 
549*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
550*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
551*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateOpenArea command failed");
552*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
553*c18ec02fSPetter Reinholdtsen    }
554*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
555*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateOpenArea command failed: %s",
556*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
557*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
558*c18ec02fSPetter Reinholdtsen    }
559*c18ec02fSPetter Reinholdtsen 
560*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdateOpenArea command succeed");
561*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
562*c18ec02fSPetter Reinholdtsen }
563*c18ec02fSPetter Reinholdtsen 
ImeUpdateWriteArea(struct ipmi_intf * intf,uint8_t sequence,uint8_t length,uint8_t * pBuf)564*c18ec02fSPetter Reinholdtsen static int ImeUpdateWriteArea(
565*c18ec02fSPetter Reinholdtsen                               struct ipmi_intf *intf,
566*c18ec02fSPetter Reinholdtsen                               uint8_t sequence,
567*c18ec02fSPetter Reinholdtsen                               uint8_t length,
568*c18ec02fSPetter Reinholdtsen                               uint8_t * pBuf
569*c18ec02fSPetter Reinholdtsen                           )
570*c18ec02fSPetter Reinholdtsen {
571*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
572*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
573*c18ec02fSPetter Reinholdtsen    uint8_t buffer[ IME_UPGRADE_BUFFER_SIZE + 1 ];
574*c18ec02fSPetter Reinholdtsen 
575*c18ec02fSPetter Reinholdtsen //   printf("ImeUpdateWriteArea %i\n", sequence);
576*c18ec02fSPetter Reinholdtsen 
577*c18ec02fSPetter Reinholdtsen    if(length > IME_UPGRADE_BUFFER_SIZE)
578*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
579*c18ec02fSPetter Reinholdtsen 
580*c18ec02fSPetter Reinholdtsen    buffer[0] = sequence;
581*c18ec02fSPetter Reinholdtsen    memcpy(&buffer[1], pBuf, length);
582*c18ec02fSPetter Reinholdtsen 
583*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
584*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
585*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA2;
586*c18ec02fSPetter Reinholdtsen    req.msg.data = buffer;
587*c18ec02fSPetter Reinholdtsen    req.msg.data_len = length + 1;
588*c18ec02fSPetter Reinholdtsen 
589*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
590*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
591*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateWriteArea command failed");
592*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
593*c18ec02fSPetter Reinholdtsen    }
594*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
595*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateWriteArea command failed: %s",
596*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
597*c18ec02fSPetter Reinholdtsen       if( rsp->ccode == 0x80) // restart operation
598*c18ec02fSPetter Reinholdtsen          return IME_RESTART;
599*c18ec02fSPetter Reinholdtsen       else
600*c18ec02fSPetter Reinholdtsen          return IME_ERROR;
601*c18ec02fSPetter Reinholdtsen    }
602*c18ec02fSPetter Reinholdtsen 
603*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdateWriteArea command succeed");
604*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
605*c18ec02fSPetter Reinholdtsen }
606*c18ec02fSPetter Reinholdtsen 
ImeUpdateCloseArea(struct ipmi_intf * intf,uint32_t size,uint16_t checksum)607*c18ec02fSPetter Reinholdtsen static int ImeUpdateCloseArea(
608*c18ec02fSPetter Reinholdtsen                               struct ipmi_intf *intf,
609*c18ec02fSPetter Reinholdtsen                               uint32_t size,
610*c18ec02fSPetter Reinholdtsen                               uint16_t checksum
611*c18ec02fSPetter Reinholdtsen                           )
612*c18ec02fSPetter Reinholdtsen {
613*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
614*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
615*c18ec02fSPetter Reinholdtsen    uint8_t length = sizeof( uint32_t ) + sizeof( uint16_t );
616*c18ec02fSPetter Reinholdtsen    uint8_t buffer[ sizeof( uint32_t ) + sizeof( uint16_t ) ];
617*c18ec02fSPetter Reinholdtsen 
618*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
619*c18ec02fSPetter Reinholdtsen    printf( "ImeUpdateCloseArea\n");
620*c18ec02fSPetter Reinholdtsen    #endif
621*c18ec02fSPetter Reinholdtsen 
622*c18ec02fSPetter Reinholdtsen    buffer[0] = (uint8_t)((size & 0x000000ff) >>  0);
623*c18ec02fSPetter Reinholdtsen    buffer[1] = (uint8_t)((size & 0x0000ff00) >>  8);
624*c18ec02fSPetter Reinholdtsen    buffer[2] = (uint8_t)((size & 0x00ff0000) >> 16);
625*c18ec02fSPetter Reinholdtsen    buffer[3] = (uint8_t)((size & 0xff000000) >> 24);
626*c18ec02fSPetter Reinholdtsen 
627*c18ec02fSPetter Reinholdtsen    buffer[4] = (uint8_t)((checksum & 0x00ff) >>  0);
628*c18ec02fSPetter Reinholdtsen    buffer[5] = (uint8_t)((checksum & 0xff00) >>  8);
629*c18ec02fSPetter Reinholdtsen 
630*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
631*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
632*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA3;
633*c18ec02fSPetter Reinholdtsen    req.msg.data = buffer;
634*c18ec02fSPetter Reinholdtsen    req.msg.data_len = length;
635*c18ec02fSPetter Reinholdtsen 
636*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
637*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
638*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateCloseArea command failed");
639*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
640*c18ec02fSPetter Reinholdtsen    }
641*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
642*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdateCloseArea command failed: %s",
643*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
644*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
645*c18ec02fSPetter Reinholdtsen    }
646*c18ec02fSPetter Reinholdtsen 
647*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdateCloseArea command succeed");
648*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
649*c18ec02fSPetter Reinholdtsen }
650*c18ec02fSPetter Reinholdtsen 
ImeUpdateGetStatus(struct ipmi_intf * intf,tImeStatus * pStatus)651*c18ec02fSPetter Reinholdtsen static int ImeUpdateGetStatus(struct ipmi_intf *intf, tImeStatus *pStatus )
652*c18ec02fSPetter Reinholdtsen {
653*c18ec02fSPetter Reinholdtsen    struct      ipmi_rs * rsp;
654*c18ec02fSPetter Reinholdtsen    struct      ipmi_rq req;
655*c18ec02fSPetter Reinholdtsen    tImeStatus *pGetStatus;
656*c18ec02fSPetter Reinholdtsen 
657*c18ec02fSPetter Reinholdtsen    memset(pStatus, 0, sizeof(tImeStatus));
658*c18ec02fSPetter Reinholdtsen    pStatus->update_state = IME_STATE_ABORTED;
659*c18ec02fSPetter Reinholdtsen 
660*c18ec02fSPetter Reinholdtsen 
661*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
662*c18ec02fSPetter Reinholdtsen    printf("ImeUpdateGetStatus: ");
663*c18ec02fSPetter Reinholdtsen    #endif
664*c18ec02fSPetter Reinholdtsen 
665*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
666*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
667*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA6;
668*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 0;
669*c18ec02fSPetter Reinholdtsen 
670*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
671*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
672*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed");
673*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
674*c18ec02fSPetter Reinholdtsen    }
675*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
676*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
677*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
678*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
679*c18ec02fSPetter Reinholdtsen    }
680*c18ec02fSPetter Reinholdtsen 
681*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
682*c18ec02fSPetter Reinholdtsen 
683*c18ec02fSPetter Reinholdtsen    pGetStatus = (tImeStatus *) rsp->data;
684*c18ec02fSPetter Reinholdtsen 
685*c18ec02fSPetter Reinholdtsen    memcpy( pStatus, pGetStatus, sizeof(tImeStatus));
686*c18ec02fSPetter Reinholdtsen 
687*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
688*c18ec02fSPetter Reinholdtsen    printf("%x - ", pStatus->updateState);
689*c18ec02fSPetter Reinholdtsen 
690*c18ec02fSPetter Reinholdtsen    switch( pStatus->update_state )
691*c18ec02fSPetter Reinholdtsen    {
692*c18ec02fSPetter Reinholdtsen       case IME_STATE_IDLE:
693*c18ec02fSPetter Reinholdtsen          printf("IDLE\n");
694*c18ec02fSPetter Reinholdtsen       break;
695*c18ec02fSPetter Reinholdtsen       case IME_STATE_UPDATE_REQUESTED:
696*c18ec02fSPetter Reinholdtsen          printf("Update Requested\n");
697*c18ec02fSPetter Reinholdtsen       break;
698*c18ec02fSPetter Reinholdtsen       case IME_STATE_UPDATE_IN_PROGRESS:
699*c18ec02fSPetter Reinholdtsen          printf("Update in Progress\n");
700*c18ec02fSPetter Reinholdtsen       break;
701*c18ec02fSPetter Reinholdtsen       case IME_STATE_SUCCESS:
702*c18ec02fSPetter Reinholdtsen          printf("Update Success\n");
703*c18ec02fSPetter Reinholdtsen       break;
704*c18ec02fSPetter Reinholdtsen       case IME_STATE_FAILED:
705*c18ec02fSPetter Reinholdtsen          printf("Update Failed\n");
706*c18ec02fSPetter Reinholdtsen       break;
707*c18ec02fSPetter Reinholdtsen       case IME_STATE_ROLLED_BACK:
708*c18ec02fSPetter Reinholdtsen          printf("Update Rolled Back\n");
709*c18ec02fSPetter Reinholdtsen       break;
710*c18ec02fSPetter Reinholdtsen       case IME_STATE_ABORTED:
711*c18ec02fSPetter Reinholdtsen          printf("Update Aborted\n");
712*c18ec02fSPetter Reinholdtsen       break;
713*c18ec02fSPetter Reinholdtsen       case IME_STATE_INIT_FAILED:
714*c18ec02fSPetter Reinholdtsen          printf("Update Init Failed\n");
715*c18ec02fSPetter Reinholdtsen       break;
716*c18ec02fSPetter Reinholdtsen       default:
717*c18ec02fSPetter Reinholdtsen          printf("Unknown, reserved\n");
718*c18ec02fSPetter Reinholdtsen       break;
719*c18ec02fSPetter Reinholdtsen    }
720*c18ec02fSPetter Reinholdtsen    #endif
721*c18ec02fSPetter Reinholdtsen 
722*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
723*c18ec02fSPetter Reinholdtsen }
724*c18ec02fSPetter Reinholdtsen 
ImeUpdateGetCapabilities(struct ipmi_intf * intf,tImeCaps * pCaps)725*c18ec02fSPetter Reinholdtsen static int ImeUpdateGetCapabilities(struct ipmi_intf *intf, tImeCaps *pCaps )
726*c18ec02fSPetter Reinholdtsen {
727*c18ec02fSPetter Reinholdtsen    struct      ipmi_rs * rsp;
728*c18ec02fSPetter Reinholdtsen    struct      ipmi_rq req;
729*c18ec02fSPetter Reinholdtsen    tImeCaps *  pGetCaps;
730*c18ec02fSPetter Reinholdtsen 
731*c18ec02fSPetter Reinholdtsen    memset(pCaps, 0, sizeof(tImeCaps));
732*c18ec02fSPetter Reinholdtsen 
733*c18ec02fSPetter Reinholdtsen 
734*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
735*c18ec02fSPetter Reinholdtsen    printf("ImeUpdateGetStatus: ");
736*c18ec02fSPetter Reinholdtsen    #endif
737*c18ec02fSPetter Reinholdtsen 
738*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
739*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
740*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA7;
741*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 0;
742*c18ec02fSPetter Reinholdtsen 
743*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
744*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
745*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed");
746*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
747*c18ec02fSPetter Reinholdtsen    }
748*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
749*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
750*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
751*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
752*c18ec02fSPetter Reinholdtsen    }
753*c18ec02fSPetter Reinholdtsen 
754*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
755*c18ec02fSPetter Reinholdtsen 
756*c18ec02fSPetter Reinholdtsen    pGetCaps = (tImeCaps *) rsp->data;
757*c18ec02fSPetter Reinholdtsen 
758*c18ec02fSPetter Reinholdtsen    memcpy( pCaps, pGetCaps, sizeof(tImeCaps));
759*c18ec02fSPetter Reinholdtsen 
760*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
761*c18ec02fSPetter Reinholdtsen }
762*c18ec02fSPetter Reinholdtsen 
763*c18ec02fSPetter Reinholdtsen 
ImeUpdateRegisterUpdate(struct ipmi_intf * intf,tImeUpdateType type)764*c18ec02fSPetter Reinholdtsen static int ImeUpdateRegisterUpdate(struct ipmi_intf *intf, tImeUpdateType type)
765*c18ec02fSPetter Reinholdtsen {
766*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
767*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
768*c18ec02fSPetter Reinholdtsen    uint8_t buffer[ 2 ];
769*c18ec02fSPetter Reinholdtsen 
770*c18ec02fSPetter Reinholdtsen    #ifdef OUTPUT_DEBUG
771*c18ec02fSPetter Reinholdtsen    printf( "ImeUpdateRegisterUpdate\n");
772*c18ec02fSPetter Reinholdtsen    #endif
773*c18ec02fSPetter Reinholdtsen 
774*c18ec02fSPetter Reinholdtsen    buffer[0] = type;  // Normal Update
775*c18ec02fSPetter Reinholdtsen    buffer[1] = 0;  // Flags, reserved
776*c18ec02fSPetter Reinholdtsen 
777*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
778*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
779*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA4;
780*c18ec02fSPetter Reinholdtsen    req.msg.data = buffer;
781*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 2;
782*c18ec02fSPetter Reinholdtsen 
783*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
784*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
785*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "ImeUpdateRegisterUpdate command failed");
786*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
787*c18ec02fSPetter Reinholdtsen    }
788*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
789*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "ImeUpdateRegisterUpdate command failed: %s",
790*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
791*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
792*c18ec02fSPetter Reinholdtsen    }
793*c18ec02fSPetter Reinholdtsen 
794*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "ImeUpdateRegisterUpdate command succeed");
795*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
796*c18ec02fSPetter Reinholdtsen }
797*c18ec02fSPetter Reinholdtsen 
798*c18ec02fSPetter Reinholdtsen 
799*c18ec02fSPetter Reinholdtsen 
800*c18ec02fSPetter Reinholdtsen 
ImeUpdateShowStatus(struct ipmi_intf * intf)801*c18ec02fSPetter Reinholdtsen static int ImeUpdateShowStatus(struct ipmi_intf *intf)
802*c18ec02fSPetter Reinholdtsen {
803*c18ec02fSPetter Reinholdtsen    struct ipmi_rs * rsp;
804*c18ec02fSPetter Reinholdtsen    struct ipmi_rq req;
805*c18ec02fSPetter Reinholdtsen    tImeStatus *pStatus;
806*c18ec02fSPetter Reinholdtsen 
807*c18ec02fSPetter Reinholdtsen    printf("ImeUpdateGetStatus: ");
808*c18ec02fSPetter Reinholdtsen 
809*c18ec02fSPetter Reinholdtsen    memset(&req, 0, sizeof(req));
810*c18ec02fSPetter Reinholdtsen    req.msg.netfn = 0x30;  // OEM NetFn
811*c18ec02fSPetter Reinholdtsen    req.msg.cmd = 0xA6;
812*c18ec02fSPetter Reinholdtsen    req.msg.data_len = 0;
813*c18ec02fSPetter Reinholdtsen 
814*c18ec02fSPetter Reinholdtsen    rsp = intf->sendrecv(intf, &req);
815*c18ec02fSPetter Reinholdtsen    if (rsp == NULL) {
816*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed");
817*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
818*c18ec02fSPetter Reinholdtsen    }
819*c18ec02fSPetter Reinholdtsen    if (rsp->ccode > 0) {
820*c18ec02fSPetter Reinholdtsen       lprintf(LOG_ERR, "UpdatePrepare command failed: %s",
821*c18ec02fSPetter Reinholdtsen          val2str(rsp->ccode, completion_code_vals));
822*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
823*c18ec02fSPetter Reinholdtsen    }
824*c18ec02fSPetter Reinholdtsen 
825*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG, "UpdatePrepare command succeed");
826*c18ec02fSPetter Reinholdtsen 
827*c18ec02fSPetter Reinholdtsen    pStatus = (tImeStatus *) rsp->data ;
828*c18ec02fSPetter Reinholdtsen 
829*c18ec02fSPetter Reinholdtsen 
830*c18ec02fSPetter Reinholdtsen    printf("image_status: %x - ", pStatus->image_status);
831*c18ec02fSPetter Reinholdtsen 
832*c18ec02fSPetter Reinholdtsen    printf("update_state: %x - ", pStatus->update_state);
833*c18ec02fSPetter Reinholdtsen 
834*c18ec02fSPetter Reinholdtsen    switch( pStatus->update_state )
835*c18ec02fSPetter Reinholdtsen    {
836*c18ec02fSPetter Reinholdtsen       case IME_STATE_IDLE:
837*c18ec02fSPetter Reinholdtsen          printf("IDLE\n");
838*c18ec02fSPetter Reinholdtsen       break;
839*c18ec02fSPetter Reinholdtsen       case IME_STATE_UPDATE_REQUESTED:
840*c18ec02fSPetter Reinholdtsen          printf("Update Requested\n");
841*c18ec02fSPetter Reinholdtsen       break;
842*c18ec02fSPetter Reinholdtsen       case IME_STATE_UPDATE_IN_PROGRESS:
843*c18ec02fSPetter Reinholdtsen          printf("Update in Progress\n");
844*c18ec02fSPetter Reinholdtsen       break;
845*c18ec02fSPetter Reinholdtsen       case IME_STATE_SUCCESS:
846*c18ec02fSPetter Reinholdtsen          printf("Update Success\n");
847*c18ec02fSPetter Reinholdtsen       break;
848*c18ec02fSPetter Reinholdtsen       case IME_STATE_FAILED:
849*c18ec02fSPetter Reinholdtsen          printf("Update Failed\n");
850*c18ec02fSPetter Reinholdtsen       break;
851*c18ec02fSPetter Reinholdtsen       case IME_STATE_ROLLED_BACK:
852*c18ec02fSPetter Reinholdtsen          printf("Update Rolled Back\n");
853*c18ec02fSPetter Reinholdtsen       break;
854*c18ec02fSPetter Reinholdtsen       case IME_STATE_ABORTED:
855*c18ec02fSPetter Reinholdtsen          printf("Update Aborted\n");
856*c18ec02fSPetter Reinholdtsen       break;
857*c18ec02fSPetter Reinholdtsen       case IME_STATE_INIT_FAILED:
858*c18ec02fSPetter Reinholdtsen          printf("Update Init Failed\n");
859*c18ec02fSPetter Reinholdtsen       break;
860*c18ec02fSPetter Reinholdtsen       default:
861*c18ec02fSPetter Reinholdtsen          printf("Unknown, reserved\n");
862*c18ec02fSPetter Reinholdtsen       break;
863*c18ec02fSPetter Reinholdtsen    }
864*c18ec02fSPetter Reinholdtsen    printf("update_attempt_status  : %x\n", pStatus->update_attempt_status);
865*c18ec02fSPetter Reinholdtsen    printf("rollback_attempt_status: %x\n", pStatus->rollback_attempt_status);
866*c18ec02fSPetter Reinholdtsen    printf("update_type            : %x\n", pStatus->update_type);
867*c18ec02fSPetter Reinholdtsen    printf("dependent_flag         : %x\n", pStatus->dependent_flag);
868*c18ec02fSPetter Reinholdtsen    printf("free_area_size         : %x\n", pStatus->free_area_size[0]);
869*c18ec02fSPetter Reinholdtsen    printf("                       : %x\n", pStatus->free_area_size[1]);
870*c18ec02fSPetter Reinholdtsen    printf("                       : %x\n", pStatus->free_area_size[2]);
871*c18ec02fSPetter Reinholdtsen    printf("                       : %x\n", pStatus->free_area_size[3]);
872*c18ec02fSPetter Reinholdtsen 
873*c18ec02fSPetter Reinholdtsen    return IME_SUCCESS;
874*c18ec02fSPetter Reinholdtsen }
875*c18ec02fSPetter Reinholdtsen 
876*c18ec02fSPetter Reinholdtsen 
ImeImageCtxFromFile(char * imageFilename,tImeUpdateImageCtx * pImageCtx)877*c18ec02fSPetter Reinholdtsen static int ImeImageCtxFromFile(
878*c18ec02fSPetter Reinholdtsen                                  char* imageFilename,
879*c18ec02fSPetter Reinholdtsen                                  tImeUpdateImageCtx * pImageCtx
880*c18ec02fSPetter Reinholdtsen                                )
881*c18ec02fSPetter Reinholdtsen {
882*c18ec02fSPetter Reinholdtsen    int rc = IME_SUCCESS;
883*c18ec02fSPetter Reinholdtsen    FILE* pImageFile = fopen(imageFilename, "rb");
884*c18ec02fSPetter Reinholdtsen 
885*c18ec02fSPetter Reinholdtsen    if ( pImageFile == NULL )
886*c18ec02fSPetter Reinholdtsen    {
887*c18ec02fSPetter Reinholdtsen       lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename);
888*c18ec02fSPetter Reinholdtsen       rc = IME_ERROR;
889*c18ec02fSPetter Reinholdtsen    }
890*c18ec02fSPetter Reinholdtsen 
891*c18ec02fSPetter Reinholdtsen    if ( rc == IME_SUCCESS )
892*c18ec02fSPetter Reinholdtsen    {
893*c18ec02fSPetter Reinholdtsen       /* Get the raw data in file */
894*c18ec02fSPetter Reinholdtsen       fseek(pImageFile, 0, SEEK_END);
895*c18ec02fSPetter Reinholdtsen       pImageCtx->size  = ftell(pImageFile);
896*c18ec02fSPetter Reinholdtsen       if (pImageCtx->size <= 0) {
897*c18ec02fSPetter Reinholdtsen          if (pImageCtx->size < 0)
898*c18ec02fSPetter Reinholdtsen             lprintf(LOG_ERR, "Error seeking %s. %s\n", imageFilename, strerror(errno));
899*c18ec02fSPetter Reinholdtsen          rc = IME_ERROR;
900*c18ec02fSPetter Reinholdtsen          fclose(pImageFile);
901*c18ec02fSPetter Reinholdtsen          return rc;
902*c18ec02fSPetter Reinholdtsen       }
903*c18ec02fSPetter Reinholdtsen       pImageCtx->pData = malloc(sizeof(unsigned char)*pImageCtx->size);
904*c18ec02fSPetter Reinholdtsen       rewind(pImageFile);
905*c18ec02fSPetter Reinholdtsen 
906*c18ec02fSPetter Reinholdtsen       if ( pImageCtx->pData != NULL )
907*c18ec02fSPetter Reinholdtsen       {
908*c18ec02fSPetter Reinholdtsen          if (pImageCtx->size < fread(pImageCtx->pData, sizeof(unsigned char),
909*c18ec02fSPetter Reinholdtsen                                                    pImageCtx->size, pImageFile))
910*c18ec02fSPetter Reinholdtsen             rc = IME_ERROR;
911*c18ec02fSPetter Reinholdtsen       }
912*c18ec02fSPetter Reinholdtsen       else
913*c18ec02fSPetter Reinholdtsen       {
914*c18ec02fSPetter Reinholdtsen          rc = IME_ERROR;
915*c18ec02fSPetter Reinholdtsen       }
916*c18ec02fSPetter Reinholdtsen    }
917*c18ec02fSPetter Reinholdtsen 
918*c18ec02fSPetter Reinholdtsen    // Calculate checksum CRC8
919*c18ec02fSPetter Reinholdtsen    if ( rc == IME_SUCCESS )
920*c18ec02fSPetter Reinholdtsen    {
921*c18ec02fSPetter Reinholdtsen       pImageCtx->crc8 = ImeCrc8(pImageCtx->size, pImageCtx->pData);
922*c18ec02fSPetter Reinholdtsen    }
923*c18ec02fSPetter Reinholdtsen 
924*c18ec02fSPetter Reinholdtsen 
925*c18ec02fSPetter Reinholdtsen    if( pImageFile != NULL)
926*c18ec02fSPetter Reinholdtsen    {
927*c18ec02fSPetter Reinholdtsen       fclose(pImageFile);
928*c18ec02fSPetter Reinholdtsen    }
929*c18ec02fSPetter Reinholdtsen 
930*c18ec02fSPetter Reinholdtsen    return rc;
931*c18ec02fSPetter Reinholdtsen }
932*c18ec02fSPetter Reinholdtsen 
ImeCrc8(uint32_t length,uint8_t * pBuf)933*c18ec02fSPetter Reinholdtsen static uint8_t ImeCrc8( uint32_t length, uint8_t * pBuf )
934*c18ec02fSPetter Reinholdtsen {
935*c18ec02fSPetter Reinholdtsen    uint8_t crc = 0;
936*c18ec02fSPetter Reinholdtsen    uint32_t bufCount;
937*c18ec02fSPetter Reinholdtsen 
938*c18ec02fSPetter Reinholdtsen    for ( bufCount = 0; bufCount < length; bufCount++ )
939*c18ec02fSPetter Reinholdtsen    {
940*c18ec02fSPetter Reinholdtsen       uint8_t count;
941*c18ec02fSPetter Reinholdtsen 
942*c18ec02fSPetter Reinholdtsen       crc = crc ^ pBuf[bufCount];
943*c18ec02fSPetter Reinholdtsen 
944*c18ec02fSPetter Reinholdtsen       for ( count = 0; count < 8; count++ )
945*c18ec02fSPetter Reinholdtsen       {
946*c18ec02fSPetter Reinholdtsen          if (( crc & 0x80 ) != 0 )
947*c18ec02fSPetter Reinholdtsen          {
948*c18ec02fSPetter Reinholdtsen             crc <<= 1;
949*c18ec02fSPetter Reinholdtsen             crc ^= 0x07;
950*c18ec02fSPetter Reinholdtsen          }
951*c18ec02fSPetter Reinholdtsen          else
952*c18ec02fSPetter Reinholdtsen          {
953*c18ec02fSPetter Reinholdtsen             crc <<= 1;
954*c18ec02fSPetter Reinholdtsen          }
955*c18ec02fSPetter Reinholdtsen       }
956*c18ec02fSPetter Reinholdtsen    }
957*c18ec02fSPetter Reinholdtsen 
958*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG,"CRC8: %02xh\n", crc);
959*c18ec02fSPetter Reinholdtsen    return crc;
960*c18ec02fSPetter Reinholdtsen }
961*c18ec02fSPetter Reinholdtsen 
962*c18ec02fSPetter Reinholdtsen 
ImeManualRollback(struct ipmi_intf * intf)963*c18ec02fSPetter Reinholdtsen static int ImeManualRollback(struct ipmi_intf *intf)
964*c18ec02fSPetter Reinholdtsen {
965*c18ec02fSPetter Reinholdtsen    int rc = IME_SUCCESS;
966*c18ec02fSPetter Reinholdtsen    tImeStatus imeStatus;
967*c18ec02fSPetter Reinholdtsen 
968*c18ec02fSPetter Reinholdtsen    rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_MANUAL_ROLLBACK);
969*c18ec02fSPetter Reinholdtsen    ImeUpdateGetStatus(intf,&imeStatus);
970*c18ec02fSPetter Reinholdtsen 
971*c18ec02fSPetter Reinholdtsen 
972*c18ec02fSPetter Reinholdtsen    if(
973*c18ec02fSPetter Reinholdtsen       (rc == IME_SUCCESS) &&
974*c18ec02fSPetter Reinholdtsen       (imeStatus.update_state == IME_STATE_ROLLED_BACK)
975*c18ec02fSPetter Reinholdtsen      )
976*c18ec02fSPetter Reinholdtsen    {
977*c18ec02fSPetter Reinholdtsen       printf("Manual Rollback Succeed\n");
978*c18ec02fSPetter Reinholdtsen       return IME_SUCCESS;
979*c18ec02fSPetter Reinholdtsen    }
980*c18ec02fSPetter Reinholdtsen    else
981*c18ec02fSPetter Reinholdtsen    {
982*c18ec02fSPetter Reinholdtsen       printf("Manual Rollback Completed With Error\n");
983*c18ec02fSPetter Reinholdtsen       return IME_ERROR;
984*c18ec02fSPetter Reinholdtsen    }
985*c18ec02fSPetter Reinholdtsen }
986*c18ec02fSPetter Reinholdtsen 
987*c18ec02fSPetter Reinholdtsen 
988*c18ec02fSPetter Reinholdtsen 
ImePrintUsage(void)989*c18ec02fSPetter Reinholdtsen static void ImePrintUsage(void)
990*c18ec02fSPetter Reinholdtsen {
991*c18ec02fSPetter Reinholdtsen    lprintf(LOG_NOTICE,"help                    - This help menu");
992*c18ec02fSPetter Reinholdtsen    lprintf(LOG_NOTICE,"info                    - Information about the present Intel ME");
993*c18ec02fSPetter Reinholdtsen    lprintf(LOG_NOTICE,"update <file>           - Upgrade the ME firmware from received image <file>");
994*c18ec02fSPetter Reinholdtsen    lprintf(LOG_NOTICE,"rollback                - Manual Rollback ME");
995*c18ec02fSPetter Reinholdtsen //   lprintf(LOG_NOTICE,"rollback                - Rollback ME Firmware");
996*c18ec02fSPetter Reinholdtsen }
997*c18ec02fSPetter Reinholdtsen 
998*c18ec02fSPetter Reinholdtsen 
999*c18ec02fSPetter Reinholdtsen 
ipmi_ime_main(struct ipmi_intf * intf,int argc,char ** argv)1000*c18ec02fSPetter Reinholdtsen int ipmi_ime_main(struct ipmi_intf * intf, int argc, char ** argv)
1001*c18ec02fSPetter Reinholdtsen {
1002*c18ec02fSPetter Reinholdtsen    int rc = IME_SUCCESS;
1003*c18ec02fSPetter Reinholdtsen 
1004*c18ec02fSPetter Reinholdtsen    lprintf(LOG_DEBUG,"ipmi_ime_main()");
1005*c18ec02fSPetter Reinholdtsen 
1006*c18ec02fSPetter Reinholdtsen 
1007*c18ec02fSPetter Reinholdtsen    if ( (argc == 0) || (strcmp(argv[0], "help") == 0) )
1008*c18ec02fSPetter Reinholdtsen    {
1009*c18ec02fSPetter Reinholdtsen       ImePrintUsage();
1010*c18ec02fSPetter Reinholdtsen    }
1011*c18ec02fSPetter Reinholdtsen    else if ( (argc == 0) || (strcmp(argv[0], "info") == 0) )
1012*c18ec02fSPetter Reinholdtsen    {
1013*c18ec02fSPetter Reinholdtsen       rc = ImeGetInfo(intf);
1014*c18ec02fSPetter Reinholdtsen    }
1015*c18ec02fSPetter Reinholdtsen    else if ( strcmp(argv[0], "update") == 0)
1016*c18ec02fSPetter Reinholdtsen    {
1017*c18ec02fSPetter Reinholdtsen       if(argc == 2)
1018*c18ec02fSPetter Reinholdtsen       {
1019*c18ec02fSPetter Reinholdtsen          lprintf(LOG_NOTICE,"Update using file: %s", argv[1]);
1020*c18ec02fSPetter Reinholdtsen          rc = ImeUpgrade(intf, argv[1]);
1021*c18ec02fSPetter Reinholdtsen       }
1022*c18ec02fSPetter Reinholdtsen       else
1023*c18ec02fSPetter Reinholdtsen       {
1024*c18ec02fSPetter Reinholdtsen          lprintf(LOG_ERROR,"File must be provided with this option, see help\n");
1025*c18ec02fSPetter Reinholdtsen          rc = IME_ERROR;
1026*c18ec02fSPetter Reinholdtsen       }
1027*c18ec02fSPetter Reinholdtsen    }
1028*c18ec02fSPetter Reinholdtsen    else if ( (argc == 0) || (strcmp(argv[0], "rollback") == 0) )
1029*c18ec02fSPetter Reinholdtsen    {
1030*c18ec02fSPetter Reinholdtsen       rc = ImeManualRollback(intf);
1031*c18ec02fSPetter Reinholdtsen    }
1032*c18ec02fSPetter Reinholdtsen    else
1033*c18ec02fSPetter Reinholdtsen    {
1034*c18ec02fSPetter Reinholdtsen       ImePrintUsage();
1035*c18ec02fSPetter Reinholdtsen    }
1036*c18ec02fSPetter Reinholdtsen 
1037*c18ec02fSPetter Reinholdtsen    return rc;
1038*c18ec02fSPetter Reinholdtsen }
1039*c18ec02fSPetter Reinholdtsen 
1040*c18ec02fSPetter Reinholdtsen 
1041*c18ec02fSPetter Reinholdtsen 
1042