summaryrefslogtreecommitdiffstats
path: root/src/include/usr/ipmi/ipmiif.H
blob: 55546d13ef0e6906925d09d42a023dd0aaf449f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/usr/ipmi/ipmiif.H $                               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2017                        */
/* [+] Google Inc.                                                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __IPMI_IPMIIF_H
#define __IPMI_IPMIIF_H

#include <sys/msg.h>
#include <errl/errlentry.H>
#include <map>

namespace IPMI
{
    // Message types which travel on the IPMI message queues
    enum msg_type
    {
        // Sent when the interface goes idle *and* we had write which
        // was told the interface was busy. We won't get notified of
        // the general idle state.
        MSG_STATE_IDLE,

        // Ready to read a response
        MSG_STATE_RESP,

        // Ready to read an event/sms
        MSG_STATE_EVNT,

        // A message which needs to be sent
        MSG_STATE_SEND,

        MSG_STATE_SHUTDOWN,

        MSG_STATE_SHUTDOWN_SEL,

        MSG_STATE_GRACEFUL_SHUTDOWN,

        // initiate a reboot request
        MSG_STATE_INITIATE_POWER_CYCLE,

        // Used to check range. Leave as last.
        MSG_LAST_TYPE = MSG_STATE_INITIATE_POWER_CYCLE,
    };

    /**
     *  @brief Returns whether IPMI message type is related to
     *    system shutdown/reboot or not
     *
     *  @param[in] i_msgType IPMI message type in question
     *
     *  @return bool True or false value indicating whether requested IPMI
     *     message type is related to system shutdown/reboot or not
     */
    inline bool validShutdownRebootMsgType(const msg_type i_msgType)
    {
        return (   (i_msgType == MSG_STATE_SHUTDOWN)
                || (i_msgType == MSG_STATE_SHUTDOWN_SEL)
                || (i_msgType == MSG_STATE_GRACEFUL_SHUTDOWN)
                || (i_msgType == MSG_STATE_INITIATE_POWER_CYCLE));
    }

    // chassis power off request types
    enum power_request_type
    {
        CHASSIS_POWER_OFF = 0x00,
        CHASSIS_POWER_SOFT_RESET = 0x01,
        CHASSIS_POWER_CYCLE = 0x02,
        CHASSIS_POWER_RESET = 0x03,
    };

    // Used in the factory for creating the proper subclass.
    enum message_type
    {
        TYPE_SYNC = 0,
        TYPE_ASYNC = 1,
        TYPE_EVENT = 2,
    };

    // IPMI network functions
    enum network_function
    {
        // These are the command network functions, the response
        // network functions are the function + 1. So to determine
        // the proper network function which issued the command
        // associated with a response, subtract 1.
        // Note: these are also shifted left to make room for the LUN.
        NETFUN_CHASSIS  = (0x00 << 2),
        NETFUN_BRIDGE   = (0x02 << 2),
        NETFUN_SENSOR   = (0x04 << 2),
        NETFUN_APP      = (0x06 << 2),
        NETFUN_FIRMWARE = (0x08 << 2),
        NETFUN_STORAGE  = (0x0a << 2),
        NETFUN_TRANPORT = (0x0c << 2),
        NETFUN_GRPEXT   = (0x2c << 2),
        NETFUN_IBM =      (0x3a << 2),

        // Overload the OEM netfun for a "none" netfun. We use this as a
        // default for objects which will have their netfun filled in
        NETFUN_NONE     = (0x30 << 2),
    };

    // SMS_ATN OEM Event constants
    enum oem_event
    {
        OEM_VALID_NETFUN      = 0x3a,
        OEM_VALID_SEL_ID      = 0x5555,
        OEM_VALID_RECORD_TYPE = 0xC0,
    };

    // IPMI Completion Codes
    enum completion_code
    {
        CC_OK        = 0x00,
        CC_CMDSPC1   = 0x80, // command specific completion code
        CC_CMDSPC2   = 0x81, // command specific completion code
        CC_BUSY      = 0xc0,
        CC_INVALID   = 0xc1,
        CC_CMDLUN    = 0xc2,
        CC_TIMEOUT   = 0xc3,
        CC_NOSPACE   = 0xc4,
        CC_BADRESV   = 0xc5,
        CC_TRUNC     = 0xc6,
        CC_BADLEN    = 0xc7,
        CC_TOOLONG   = 0xc8,
        CC_OORANGE   = 0xc9,
        CC_LONGREPLY = 0xca,
        CC_BADSENSOR = 0xcb,
        CC_REQINVAL  = 0xcc,
        CC_CMDSENSOR = 0xcd,
        CC_CANTREPLY = 0xce,
        CC_DUPREQ    = 0xcf,
        CC_SDRUPDATE = 0xd0,
        CC_FMWUPDATE = 0xd1,
        CC_BMCINIT   = 0xd2,
        CC_BADDEST   = 0xd3,
        CC_NOPERM    = 0xd4,
        CC_BADSTATE  = 0xd5,
        CC_ILLPARAM  = 0xd6,
        CC_UNKBAD    = 0xff
    };

    // per IPMI Spec, section 32.2 OEM SEL Event Records
    struct oemSEL {

        enum Constants
        {
            MANUF_LENGTH = 3,
            CMD_LENGTH = 5,
            LENGTH = 16,
        };

        // ID used for SEL Record access. The Record ID values 0000h and FFFFh
        // have special meaning in the Event Access commands and must not be
        // used as Record ID values for stored SEL Event Records.
        uint16_t iv_record;

        // [7:0] - Record Type
        //  02h     = system event record
        //  C0h-DFh = OEM timestamped, bytes 8-16 OEM defined
        //  E0h-FFh = OEM non-timestamped, bytes 4-16 OEM defined
        uint8_t iv_record_type;

        // Time when event was logged. LS byte first.
        uint32_t iv_timestamp;

        // 3 bytes for the manuf id
        uint8_t iv_manufacturer[MANUF_LENGTH];

        // Presently 0x3A for IBM
        uint8_t iv_netfun;

        // Current command and arguments
        uint8_t iv_cmd[CMD_LENGTH];

        // @brief Populate a selRecord from the wire representation of an event
        // @param[in] i_raw_event_data, pointer to the raw data
        void populateFromEvent(uint8_t const* i_raw_event_data);

        // ctor
        oemSEL():
            iv_record(0),
            iv_record_type(0),
            iv_timestamp(0),
            iv_netfun(0)
            {
                memset(iv_manufacturer, 0, MANUF_LENGTH);
                memset(iv_cmd, 0, CMD_LENGTH);
            };

        // @Brief Create a selRecord from the wire representation of an event
        // @param[in] i_event_data, pointer to the event data
        oemSEL( uint8_t const* i_event_data )
            { populateFromEvent( i_event_data ); }

    };

    //
    // Network function, command pairs.
    //
    typedef std::pair<network_function, uint8_t> command_t;


    // Application messages
    inline const command_t get_device_id(void)
    { return std::make_pair(NETFUN_APP, 0x01); }

    inline const command_t set_acpi_power_state(void)
    { return std::make_pair(NETFUN_APP, 0x06); }

    inline const command_t set_watchdog(void)
    { return std::make_pair(NETFUN_APP, 0x24); }

    inline const command_t reset_watchdog(void)
    { return std::make_pair(NETFUN_APP, 0x22); }

    inline const command_t read_event(void)
    { return std::make_pair(NETFUN_APP, 0x35); }

    inline const command_t get_capabilities(void)
    { return std::make_pair(NETFUN_APP, 0x36); }


    // Chassis messages
    inline const command_t chassis_power_off(void)
    { return std::make_pair(NETFUN_CHASSIS, 0x02); }


    // Storage messages
    inline const command_t get_sel_time(void)
    { return std::make_pair(NETFUN_STORAGE, 0x48); }

    inline const command_t set_sel_time(void)
    { return std::make_pair(NETFUN_STORAGE, 0x49); }

    inline const command_t write_fru_data(void)
    { return std::make_pair(NETFUN_STORAGE, 0x12); }

    inline const command_t get_sel_info(void)
    { return std::make_pair(NETFUN_STORAGE, 0x40); }

    inline const command_t reserve_sel(void)
    { return std::make_pair(NETFUN_STORAGE, 0x42); }

    inline const command_t add_sel(void)
    { return std::make_pair(NETFUN_STORAGE, 0x44); }

    inline const command_t partial_add_esel(void)
    { return std::make_pair(NETFUN_IBM, 0xf0); }

    // event messages
    inline const command_t platform_event(void)
    { return std::make_pair(NETFUN_SENSOR, 0x02); }

    // Sensor messages
    inline const command_t set_sensor_reading(void)
    { return std::make_pair(NETFUN_SENSOR, 0x30); }

    inline const command_t get_sensor_reading(void)
    { return std::make_pair(NETFUN_SENSOR, 0x2D); }

    inline const command_t get_sensor_type(void)
    { return std::make_pair(NETFUN_SENSOR, 0x2F); }

    // OEM Messages
    inline const command_t power_off(void)
    { return std::make_pair(NETFUN_IBM, 0x04); }

    inline const command_t pnor_request(void)
    { return std::make_pair(NETFUN_IBM, 0x07); }

    inline const command_t pnor_response(void)
    { return std::make_pair(NETFUN_IBM, 0x08); }

    // $TODO RTC:123256 - need to add code to get dcmi capabilities
    // This is a dcmi message used to request the
    // user defined power limit from the BMC.
    inline const command_t get_power_limit(void)
    { return std::make_pair(NETFUN_GRPEXT, 0x03); }

    // Some helper messages
    // Used to create an empty message for reception
    inline const command_t no_command(void)
    { return std::make_pair(NETFUN_NONE, 0x00); }

    // This is a message used only for testing. The ipmid responder
    // will drop this message so we can test timeouts.
    inline const command_t test_drop(void)
    { return std::make_pair(NETFUN_APP, 0x3e); }

    /**
     * Send message asynchronously
     * @param[in] i_cmd, the network function and command
     * @param[in] i_len, the length of the buffer
     * @param[in] i_data, the buffer - must be new'd
     * @param[in] i_type, the message type EVENT/ASYNC- defaults to ASYNC
     * @example uint8_t* data = new uint8_t[length];
     * @warning do *not* delete data, the resource provider will do that.
     *
     * @return errlHndl_t, NULL on success
     */
    errlHndl_t send(const command_t& i_cmd,
                    const size_t i_len,
                    uint8_t* i_data,
                    message_type i_type = TYPE_ASYNC);

    /**
     * Send message synchronously
     * @param[in] i_cmd, the command and network function
     * @param[out] o_completion_code,  the completion code
     * @param[in,out] io_len, the length of the buffer
     * @param[in] i_data, the buffer - must be new'd
     * @example uint8_t* data = new uint8_t[length];
     * @example delete[] data;
     *
     * @return errlHndl_t, NULL on success
     */
    errlHndl_t sendrecv(const command_t& i_cmd,
                        completion_code& o_completion_code,
                        size_t& io_len, uint8_t*& io_data);

    /**
     * Synchronously send an event
     * @param[in] i_sensor_type, the sensor type
     * @param[in] i_sensor_num, the sensor number
     * @param[in] i_assertion, bool true is assert, false is deassert.
     * @param[in] i_type, event type
     * @param[out] o_completion_code, completion code
     * @param[in] i_len, number of data bytes (1-3)
     * @param[in] i_data, data bytes
     *
     * @return errlHndl_t, NULL on success
     */
    errlHndl_t send_event(const uint8_t i_sensor_type,
                          const uint8_t i_sensor_number,
                          const bool i_assertion,
                          const uint8_t i_type,
                          completion_code& o_completion_code,
                          const size_t i_len,
                          uint8_t* i_data);

    /**
     * Get the max buffer size
     * @param void
     *
     * @return the maximum space allowed for data, per message
     * (max message for the transport - the header size)
     */
    size_t max_buffer(void);

    /**
     *  @brief Initiate a graceful reboot sequence via the IPMI resource
     *    provider
     */
    void initiateReboot();

    /**
     *  @brief Initiate a power off sequence via the IPMI resource provider
     */
    void initiatePowerOff();

    /**
     * Structure to return BMC/IPMI information in
     */
    struct BmcInfo_t
    {
        uint64_t bulkTransferLpcBaseAddr; //< Base address of the bulk transfer
                            //  LPC bus. Relative to the IO space on the LPC
        uint32_t bulkTransferSize; //< Size of bulk transfer device address
                                   //  space on the LPC bus
        uint8_t chipVersion; //< ML2 chip version
        uint8_t smsAttnInterrupt; //< SMS attention interrupt number
        uint8_t bmcToHostInterrupt; //< BMC to Host response interrupt
        char bmcVendor[32]; //< BMC vendor string. AMI, Aten or OpenBmc
    };

    /**
     * Retrieve some information about the BMC and the connection
     * we have to it.
     *
     * @return Structure of BMC data
     */
    BmcInfo_t getBmcInfo(void);


}; // end namespace IPMI

#endif
OpenPOWER on IntegriCloud