关于OpenBmc如何添加未支持的IPMI命令

关于OpenBmc如何添加未支持的IPMI命令

  • ipmi标准命令的实现代码是在phosphor-ipmi-host中进行实现的。可以使用devtool modify phosphor-ipmi-host进行下载对应的模块。

phosphor-ipmi-host模块生成相应的服务

  • 在ipmid-new.cpp文件中,main函数下,我们可以看到以下代码:

     	sdbusp->request_name("xyz.openbmc_project.Ipmi.Host");
     	auto server = sdbusplus::asio::object_server(sdbusp);
         auto iface = server.add_interface("/xyz/openbmc_project/Ipmi",
                                           "xyz.openbmc_project.Ipmi.Server");
         iface->register_method("execute", ipmi::executionEntry);
         iface->initialize();
    
  • 通过此处代码,生成了一个服务,其他模块可以通过服务名称:xyz.openbmc_project.Ipmi.Host;路径:/xyz/openbmc_project/Ipmi, xyz.openbmc_project.Ipmi.Server;方法:execute 来调用该服务。该服务调用的函数为ipmi::executionEntry。举例:在phosphor-ipmi-net 工程下,command_table.cpp文件下,Table::executeCommand函数中,通过以下代码进行了服务的调用:

bus->async_method_call(
           [handler, this](const boost::system::error_code& ec,
                           const IpmiDbusRspType& response) {
               if (!ec)
               {
                   const uint8_t& cc = std::get<3>(response);
                   const std::vector<uint8_t>& responseData =
                       std::get<4>(response);
                   std::vector<uint8_t> payload;
                   payload.reserve(1 + responseData.size());
                   payload.push_back(cc);
                   payload.insert(payload.end(), responseData.begin(),
                                  responseData.end());
                   handler->outPayload = std::move(payload);
               }
               else
               {
                   std::vector<uint8_t> payload;
                   payload.push_back(IPMI_CC_UNSPECIFIED_ERROR);
                   handler->outPayload = std::move(payload);
               }
           },
           "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
           "xyz.openbmc_project.Ipmi.Server", "execute", netFn, lun, cmd,
           commandData, options);

ipmi::executionEntry函数的调用细节

 - executionEntry  [ipmid-new.cpp]
   	   		->executeIpmiCommand(request)  [ipmid-new.cpp]
   	   				->executeIpmiCommandCommon   [ipmid-new.cpp]   [此函数通过netfn进行选择], 在该函数中,通过netfn 与cmd 组成的
   	   				关键字,在handlerMap中进行查找,找到注册上去的回调函数,并且执行回调函数。因此,在函数的开始,我们需要将实现ipmi
   	   				协议的函数注册在handlerMap中即可。

如何将实现报文的函数进行注册

  • 举例:在apphandler.cpp文件中,void register_netfn_app_function()函数下,我们注册了netfn 为 APP的回调函数。注:register_netfn_app_function函数仅仅只有声明和定义,但是并未进行调用。该函数的声明为:

    	        `void register_netfn_app_functions() __attribute__((constructor));`
    

    后缀标识为此函数在main函数执行之前要进行调用。

  • 我们以函数ipmi::registerHandler为例,讲解如何注册回调函数。
    registerHandler函数的实现在include/ipmid/handler.hpp文件中进行实现,该函数在此调用了两个函数:

     		1、ipmi::makeHandler(std::forward<Handler>(handler)),该函数的作用是生成一个handler的函数指针。此函数非常重要,涉及到
     		回调函数参数的设定。进入该函数,发现生成HandlerBase::ptr的函数指针。该函数指针调用的是
     			template <typename Handler> 
     						class IpmiHandler final : public HandlerBase  的重载函数
     		在 	HandlerBase类型下,会调用call方法来执行回调函数,所以我们需要重点查看executeCallback(request)函数。
     		该函数下,我们可以看到如下的注释:
     				        /* callbacks can contain an optional first argument of one of:
     				        * 1) boost::asio::yield_context
     				         * 2) ipmi::Context::ptr
     				         * 3) ipmi::message::Request::ptr
     				         *
     				         * If any of those is part of the callback signature as the first
     				         * argument, it will automatically get packed into the parameter pack
     				         * here.
     				         *
     				         * One more special optional argument is an ipmi::message::Payload.
     				         * This argument can be in any position, though logically it makes the
     				         * most sense if it is the last. If this class is included in the
     				         * handler signature, it will allow for the handler to unpack optional
     				         * parameters. For example, the Set LAN Configuration Parameters
     				         * command takes variable length (and type) values for each of the LAN
     				         * parameters. This means that the  only fixed data is the channel and
     				         * parameter selector. All the remaining data can be extracted using
     				         * the Payload class and the unpack API available to the Payload class.
     				         */
     		回调函数的形参,第一个参数可以是boost::asio::yield_context,  ipmi::Context::ptr, ipmi::message::Request::ptr
     		后面跟着ipmi报文中私有数据区的变量,或者形参直接为ipmi报文中私有数据区的变量。
     	2、impl::registerHandler函数的作用为根据  netfn以及cmd生成关键字,将handler函数注册到handlerMap中。
    

以netfn=chassis ,cmd = 0xa为例,进行回调函数参数说明:

  • 该回调函数的实现是在chassishandler.cpp中
ipmi::RspType<> ipmiSetFrontPanelButtonEnables(ipmi::Context::ptr ctx, bool disablePowerButton, bool disableResetButton,
                                           bool disableDiagButton, bool disableSleepButton, uint4_t reserved)
  • 该命令的协议资料,位于390页

  • 可以看到,形参列表中的第一个参数为ipmi::Context::ptr,后面的参数分别与该命令的私有变量相对应。

附:当我们要实现一个phosphor-ipmi-host中未实现的命令时,建议可以在openbmc中的oem中进行查找该命令是否实现

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值