OpenBMC 添加一个新的系统
添加新系统到 OpenBMC
内容: 如何添加一个新的系统到 OpenBMC
版本
受众: 熟悉 OpenBMC
的开发者
需求: 完成了环境配置文档
我的博客
总览
本文档将描述如下的内容:
- 回顾
Yocto
与BitBake
的历史 - 创建新的系统层
- 完善这个新的层
- 编译新的系统并使用
QEMU
进行测试 - 为
sensor
,LED
,资产
等内容添加配置
背景
OpenBMC
版本基于Yocto项目。Yocto
项目允许开发者创建定制化的 Linux
发行版本。 OpenBMC
使用 Yocto
创建自己的运行在各种设备尚的嵌入式 Linux
版本。
Yocto
具有一个层架构的概念。当你构建一个基于 Yocto
的构建版本时,你会定义关于该版本的一系列的层。OpenBMC
使用一些 Yocto
中通用的层以及自己构建的层。OpenBMC
中定义的层可以在 OpenBMC
的 GitHub项目的 meta-*
目录中找到。
Yocto
的层是定义在这个层中的构成这个层的不同包的组合。其中一个关键的层是BitBake使用的食谱。
BitBake
具有自身完备的功能性。在本文档中,我们将仅专注于添加一个新的系统过程中需要使用的 BitBake
内容。
启动 BitBake 初始化
你需要至少100GB的存储空间的开发环境,尽可能多的内存以及CPU核。第一次构建 OpenBMC
版本可能会消耗几个小时。一旦初次构建完成,未来的构建将会使用第一次构建中生成的缓存数据进行构建,从而大幅加速了后续的构建过程。
首先,跟着 Github
中的项目文档进行初次构建。
创建一个新的系统
如果上面的工作能够顺利完成,让我们开始创建我们的新系统吧。与前面的内容相同,我们将会使用 Romulus
作为我们的参考内容。我们新的系统将称为 romulus-prime
。
在之前克隆的openbmc的仓库中,Romulus
等位于 meta-ibm/meta-romulus/
目录下。 Romulus
层定义在 conf
子目录下。在 conf
目录中,可以看到如下的结构:
meta-ibm/meta-romulus/conf/
├── bblayers.conf.sample
├── conf-notes.txt
├── layer.conf
├── local.conf.sample
└── machine
└── romulus.conf
为了创建我们自己的 romulus-prime
系统,首先复制当前的 romulus
层:
cp -R meta-ibm/meta-romulus meta-ibm/meta-romulus-prime
让我们调整在新的层中需要的每个文件:
-
meta-ibm/meta-romulus-prime/conf/bblayers.conf.sample
这个文件定义了要引入到meta-romulus-prime
版本中的层,你可以在这个文件中看到不同的Yocto
层(比如meta
,meta-openembedded/meta-oe
等)。它也有OpenBMC
的层,比如meta-phosphor
,meta-openpower
,meta-ibm
以及meta-ibm/meta-romulus
。对这个文件要做出的唯一修改是将其中的两个
meta-romulus
实例,修改为meta-romulus-prime
,这将允许你使用你新构建的层。 -
meta-ibm/meta-romulus-prime/conf/conf-notes.txt
这个文件简单陈述你构建的新层要构建的默认目标,这个文件保留不变,因为这个文件在所有的OpenBMC
系统都保持一致。 -
meta-ibm/meta-romulus-prime/conf/layer.conf
这个文件的主要目的是告诉BitBake
去哪里查找食谱(*.bb)文件,食谱文件以.bb
作为后缀名,包含不同层的打包逻辑。.bbappend
文件也是食谱文件,但是却是作为.bb
文件的补充。.bbapped
文件通常用来添加或移除相关联的.bb
文件中的内容。 -
meta-ibm/meta-romulus-prime/conf/local.conf.sample
这个文件中包含你的层中的本地配置设置信息。这个文件中的内容写的很好,值得一读。唯一需要改变的内容是,将MACHINE
修改为romulus-prime
。 -
meta-ibm/meta-romulus-prime/conf/machine/romulus.conf
这个文件描述了你的机型的规定的内容,你定义使用的内核设备树,你引入的覆写特性,以及其他的系统特性。这个文件是创建新系统变动不同的内容时的好参考(内核设备树,MRW,LED设置,资产访问等)。
首先,你需要将这个文件重命名为romulus-prime.conf
。
这个配置数据的主体数据不再使用了,但是在完全移除它之前,你依然需要提供这些内容。
构建新系统
上面的工作顺利完成后,再继续进行后续的操作。后面的操作过程中,可能会出现一些错误,但是这些错误可以帮助你更好的理解构建新系统的过程。
-
为当前的构建调整
conf
在shell
中,你进行了bitbake
的初始化操作,现在需要为你新构建的系统重置conf
文件,你可以手动的复制新文件,或只是移除它,让BitBake
帮助你完成:cd .. rm -rf ./build/conf export TEMPLATECONF=meta-ibm/meta-romulus-prime/conf . openbmc-env
运行你想运行的
bitbake
命令。 -
没有 RPROVIDES 'romulus-prime-config'
这是你在新系统中运行bitbake obmc-phosphor-image
之后出现的第一个错误。
在初始化OpenBMC
的原型初始化时,会使用openbmc/skeleton
仓库,在这个仓库中是 configs 目录。
既然这个仓库与文件是这样的情况,我们将简单地快速解决这个问题。
创建如下的配置文件:cp meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-config.bb meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-prime-config.bb vi meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-prime-config.bb SUMMARY = "Romulus board wiring" DESCRIPTION = "Board wiring information for the Romulus OpenPOWER system." PR = "r1" inherit config-in-skeleton #Use Romulus config do_make_setup() { cp ${S}/Romulus.py \ ${S}/obmc_system_config.py cat <<EOF > ${S}/setup.py from distutils.core import setup setup(name='${BPN}', version='${PR}', py_modules=['obmc_system_config'], ) EOF }
重新运行你的
bitbake
命令。 -
提取
URL
失败: file://romulus.cfg
这是内核需要的一个配置文件,在这里你可以放置一些额外的内核配置参数。在我们的需求中,只需要调整romulus-prime
来使用romulus.cfg
文件。我们只需要添加-prime
来扩展路径。vi ./meta-ibm/meta-romulus-prime/recipes-kernel/linux/linux-aspeed_%.bbappend FILESEXTRAPATHS_prepend_romulus-prime := "${THISDIR}/${PN}:" SRC_URI += "file://romulus.cfg"
现在重新运行你的 `bitbake 命令。
-
没有提供目标
arch/arm/boot/dts/aspeed-bmc-opp-romulus-prime.dtb.dtb
文件是设备树块文件。这个文件在Linux
内核基于对应的.dts
文件编译过程中生成的文件。当你引入一个新的OpenBMC
系统时,你需要发送这些内核更新上游内容。链接邮件 thread 是这个过程的例子。在本文档中,我们只简单的使用Romulus
内核配置文件:vi ./meta-ibm/meta-romulus-prime/conf/machine/romulus-prime.conf # Replace the ${MACHINE} variable in the KERNEL_DEVICETREE # Use romulus device tree KERNEL_DEVICETREE = "${KMACHINE}-bmc-opp-romulus.dtb"
重新运行你的
bitbake
命令。
启动新系统
现在,你编译了你的新的系统镜像!有很多可以继续定制化的内容,但在现在,我们先验证一下我们的工作吧!
你的新镜像在编译完成后,它会位于相对于你的 bitbake
命令使用的目录于:
./tmp/deploy/images/romulus-prime/obmc-phosphor-image-romulus-prime.static.mtd
复制这个镜像到你配置的 QEMU
位置,重新运行启动 QEMU
命令(在 dev-environment.md 中的 qemu-system-arm
命令),并使用你的新的文件作为输入。
一旦启动,你将会看到如下的登录接口:
romulus-prime login:
好了!现在,你已经成功的实现了初步的创建、启动以及构建一个新的系统。这虽然在实际意义上并不是一个新的系统,但是你现在有了定制自己需要系统的基础。
深度客制化
在创建一个新系统时,有很多可以定制化的内容。
修改内核
本小节介绍如何修改内核,以移植 OpenBMC
到新的设备。设备树位于 https://github.com/openbmc/linux/tree/dev-4.13/arch/arm/boot/dts 中。比如,查看 aspeed-bmc-opp-romulus.dts 或相似的设备。完成下面的步骤来做出内核的修改:
- 添加新机型的设备树
- 描述
GPIOs
,即LED
,FSI
,gpio-keys
等内容。你应该可以从硬件原理图中获取到需要配置的信息 - 描述
i2c
总线以及设备,通常包含不同的硬件检测hwmon
sensor
- 描述其他的设备,即
uarts
,mac
等内容 - 通常
flash
布局不需要改变,只需要包含openbmc-flash-layout.dtsi
- 描述
- 调整
Makefile
来编译设备树 - 参考 openbmc kernel doc 提交补丁到邮件列表
注意:
- 在
dev-4.10
中,arch/arm/mach-aspeed/aspeed.c
中具有通用的以及指定设备的代码,这个文件是用来通用的初始化,以及指定的机型的设置。在branch
dev-4.13
中,没有这样的初始化代码。大多数初始化是与时钟以及重置驱动中完成的 - 如果设备需要特定的配置(即 uart 路由),请发送邮件到邮件列表 the mailing list 进行讨论
工作簿
在旧版的 OpenBMC
中,有一个"工作簿"描述设备的服务、传感器以及FRU等信息。这个工作簿是一个 python
配置文件,且它被 skeleton 的其他服务使用。在最新版的 OpenBMC
中,skeleton
服务大多数被 phosphor-xxx
服务替代,因此skeleton
已经被抛弃了。但是在当前的构建中依旧需要"工作簿"。
meta-quanta是一个在 OpenBMC
树中定义的自有的配置示例,尽管是伪造的,它不再依赖于 skeleton
。
在 e0e69be 中,或在 v2.4
标签之前,OpenPOWER
机型使用 GPIO
相关的一些配置,例如,在 Romulus.py 中,配置细节如下:
GPIO_CONFIG['BMC_POWER_UP'] = \
{'gpio_pin': 'D1', 'direction': 'out'}
GPIO_CONFIG['SYS_PWROK_BUFF'] = \
{'gpio_pin': 'D2', 'direction': 'in'}
GPIO_CONFIGS = {
'power_config' : {
'power_good_in' : 'SYS_PWROK_BUFF',
'power_up_outs' : [
('BMC_POWER_UP', True),
],
'reset_outs' : [
],
},
}
编译时需要 PowerUp
以及 PowerOK
GPIOs
,来上电机箱并检测上电状态。
在这之后,GPIO
相关的配置从工作簿移除,并被 gpio_defs.json
替换,即 2a80da2 引入了对Romulus
的 GPIO
json
配置。
{
"gpio_configs": {
"power_config": {
"power_good_in": "SYS_PWROK_BUFF",
"power_up_outs": [
{ "name": "SOFTWARE_PGOOD", "polarity": true},
{ "name": "BMC_POWER_UP", "polarity": true}
],
"reset_outs": [
]
}
},
"gpio_definitions": [
{
"name": "SOFTWARE_PGOOD",
"pin": "R1",
"direction": "out"
},
{
"name": "BMC_POWER_UP",
"pin": "D1",
"direction": "out"
},
...
}
每一个机型必须定义相似的 json
配置来描述 GPIO
配置。
硬件检测传感器
硬件检测传感器(hwmon sensors)包括板卡上的传感器(即温度传感器、风扇)以及 OCC
传感器。配置文件路径以及名称必须于设备树中的设备匹配。
在下面的文档中具有一些细节: doc/architecture/sensor-architecture。
现在让我们以 Romulus
为例,配置文件为 meta-romulus/recipes-phosphor/sensors,它包含板上传感器以及 OCC
传感器,其中板卡上的传感器通过 i2c
访问,OCC
传感器通过 FSI
访问。
-
w83773g@4c.conf 定义了
w83773
温度传感器,包含三个温度LABEL_temp1 = "outlet" ... LABEL_temp2 = "inlet_cpu" ... LABEL_temp3 = "inlet_io"
这些设备定义为它的设备树 w83773g@4c 中,当
BMC
启动时,udev
规则将会启动phosphor-hwmon
,它将基于sysfs
属性创建在如下D-Bus
温度传感器对象:/xyz/openbmc_project/sensors/temperature/outlet /xyz/openbmc_project/sensors/temperature/inlet_cpu /xyz/openbmc_project/sensors/temperature/inlet_io
-
pwm-tacho-controller@1e786000.conf 定义了风扇以及配置于上面类似,不同点是,它创建
fan_tach
传感器 -
occ-hwmon.1.conf 为主
CPU
定义了occ
硬件检测传感器,这个配置有点不同,它必须告知phosphor-hwmon
读取标识,而不是直接获取传感器的索引,因为CPU
内核以及DIMMs
可以是动态的,即CPU
核可以被关闭,DIMMs
可以被取出MODE_temp1 = "label" MODE_temp2 = "label" ... MODE_temp31 = "label" MODE_temp32 = "label" LABEL_temp91 = "p0_core0_temp" LABEL_temp92 = "p0_core1_temp" ... LABEL_temp33 = "dimm6_temp" LABEL_temp34 = "dimm7_temp" LABEL_power2 = "p0_power" ...
MODE_temp* = "label"
表示,如果要查看tempX
,必须读取sensor id
即label
LABEL_temp* = "xxx"
表示,通过sensor id
获取到的sensor name
- 比如,如果
temp1_input
为 37000 且temp1_label
在sysfs
中为 91,phosphor-hwmon
直到temp1_input
是sensor id
为 91 的值,即p0_core0_temp
,因此它将创建xyz/openbmc_project/sensors/temperatur/p0_core0_temp
,且其值为 37000 - 对于
Romulus
功率传感器不需要读取标识,因为所有的功率在系统上是可以获取到的 - 对于
Witherspoon
,功率传感器与温度传感器相似,它必须告知hwmon
读取function_id
而不是直接获取到传感器的索引值
LED灯
一些部分涉及到了LED灯。
- 在内核设备树中,必须描述
LEDs
,如在 romulus dts 描述了3盏LED
灯,故障灯、定位灯以及电源指示灯:leds { compatible = "gpio-leds"; fault { gpios = <&gpio ASPEED_GPIO(N, 2) GPIO_ACTIVE_LOW>; }; identify { gpios = <&gpio ASPEED_GPIO(N, 4) GPIO_ACTIVE_HIGH>; }; power { gpios = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_LOW>; }; };
- 在机型层,
LEDs
必须通过yaml
进行配置,用以描述它们的功能,如在 Romulus led yaml 中:
它表示bmc_booted: power: Action: 'Blink' DutyOn: 50 Period: 1000 Priority: 'On' power_on: power: Action: 'On' DutyOn: 50 Period: 0 Priority: 'On' ...
LED
电源指示灯在BMC
启动后闪烁,当主机上电之后常量。 - 在运行时,
LED
管理基于上面的yaml
配置自动设置LEDs
亮/灭/闪烁 LED
可以通过/xyz/openbmc_project/led/
手动的访问,比如:- 获取定位灯状态:
curl -b cjar -k https://$bmc/xyz/openbmc_project/led/physical/identify
- 设置定位灯状态为闪烁:
curl -b cjar -k -X PUT -H "Content-Type: application/json" -d '{"data": "xyz.openbmc_project.Led.Physical.Action.Blink" }' https://$bmc/xyz/openbmc_project/led/physical/identify/attr/State
- 获取定位灯状态:
- 当发生
FRU
相关的故障时,将在日志中创建一条带有CALLOUT
路径的事件日志,phosphor-fru-fault-monitor 检测日志:- 当带有
CALLOUT
路径的故障发生时,修改相关灯的状态 - 当日志显式相关的事件解除或被删除时,修改相关灯的状态
- 当带有
注意: 这个 yaml
配置可以通过 phosphor-mrw-tools 的MRW自动生成,详情查看Witherspoon example
资产信息以及其他传感器
资产信息,其他传感器(比如 CPU/DIMM 温度),以及 FRU
在 ipmi
的 yaml
配置文件中定义。
比如,meta-romulus/recipes-phosphor/ipmi
romulus-ipmi-inventory-map
定义了常规的资产信息,如,CPU,内存,母板等phosphor-ipmi-fru-properties
定义了额外的资产信息属性phosphor-ipmi-sensor-inventory
定义了 IPMI 的传感器romulus-ipmi-inventory-sel
定义了 IPMI SEL 使用的资产
对于资产映射以及FRU属性,它们在不同的系统下都十分相似,你可以参考这些例子,并制作自己的系统。
对于 ipmi-sensor-inventory
,IPMI 中的传感器因系统而异,因此你需要定义你自己的传感器,比如:
0x08:
sensorType: 0x07
path: /org/open_power/control/occ0
...
0x1e:
sensorType: 0x0C
path: /system/chassis/motherboard/dimm0
...
0x22:
sensorType: 0x07
path: /system/chassis/motherboard/cpu0/core0
第一个值 0x08
,0x1e
,0x22
是 IPMI 的 sensor id
,在 MRW 中定义。你应该遵从系统的 MRW 来定义上面的配置。
注意: yaml
配置可以自动从它的 MRW 的 phosphor-mrw-tools 中自动生成,详情查看 Witherspoon example
风扇
phosphor-fan-presence 管理所有的风扇有关的服务:
phosphor-fan-presence
检查风扇是否在位,在资产信息中创建风扇D-Bus
对象,并更新Present
状态属性phosphor-fan-monitor
检测风扇是否有效,并更新D-Bus
对象中的Functional
资产属性phosphor-fan-control
按照条件设置风扇速度目标(如,基于温度)来设置风扇转速phosphor-cooling-type
通过设置/xyz/openbmc_project/inventory/system/chassis
对象属性,检测并设置系统是风冷还是水冷
所有上面的服务都是可配置的,比如通过 yaml
配置,因此在移植 OpenBMC
到新的系统时,机型相关的配置必须写入。
以 Romulus
为例,它是风冷且具有3个风扇,无 GPIO 在位检测的。
风扇在位
Romulus
没有 GPIO 在位检测,因此它通过检测风扇转速传感器:
- name: fan0
path: /system/chassis/motherboard/fan0
methods:
- type: tach
sensors:
- fan0
yaml
配置表示:
- 它必须在资产中创建
/system/chassis/motherboard/fan0
对象 - 它必须检测
fan0
转速传感器 (/sensors/fan_tach/fan0
) 来设置fan0
对象的Present
属性
风扇监测
Romulus
风扇使用 pwm
实现风扇速度控制,pwm
范围为 0-255,风扇速度为 0-7000。因此它需要一个一个机制将 pwm
转换为 speed
- inventory: /system/chassis/motherboard/fan0
allowed_out_of_range_time: 30
deviation: 15
num_sensors_nonfunc_for_fan_nonfunc: 1
sensors:
- name: fan0
has_target: true
target_interface: xyz.openbmc_project.Control.FanPwm
factor: 21
offset: 1600
这个 yaml
配置表示:
- 它必须使用
FanPwm
作为转速传感器的目标接口 - 它必须以
target*21 + 1600
计算期望的风扇速度 - 偏差是 15$,因此如果风扇速度在期望的工作范围外工作超过30秒,
fan0
必将被设置为无效风扇
风扇控制
风扇控制服务需要4个 yaml
配置文件:
-
zone-condition
定义制冷区条件,Romulus
总是通过风冷制冷,因此配置比较简单,定义为air-cooled-chassis
- name: air_cooled_chassis type: getProperty properties: - property: WaterCooled interface: xyz.openbmc_project.Inventory.Decorator.CoolingType path: /xyz/openbmc_project/inventory/system/chassis type: bool value: false
-
zone-config
定义制冷区,Romulus
只有一个区zones: - zone: 0 full_speed: 255 default_floor: 195 increase_delay: 5 decrease_interval: 30
它定义了风扇的满转速度以及默认地板速度,因此,全速状态下,
pwm
将会设置为255;默认地板状态下,将会设置为195 -
fan-config
定义了在哪个区需要控制哪个风扇,哪个目标接口必须使用,比如,下面的yaml
配置中,定义了fan0
必须在zone0
进行控制,必须使用FanPwm
接口:- inventory: /system/chassis/motherboard/fan0 cooling_zone: 0 sensors: - fan0 target_interface: xyz.openbmc_project.Control.FanPwm ...
-
event-config
定义了不同的事件,及事件处理。比如,在哪个温度必须设置哪个风扇。这个配置有一点复杂,example event yaml 提供了示例与文档,Romulus
例子如下:- name: set_air_cooled_speed_boundaries_based_on_ambient groups: - name: zone0_ambient interface: xyz.openbmc_project.Sensor.Value property: name: Value type: int64_t matches: - name: propertiesChanged actions: - name: set_floor_from_average_sensor_value map: value: - 27000: 85 - 32000: 112 - 37000: 126 - 40000: 141 type: std::map<int64_t, uint64_t> - name: set_ceiling_from_average_sensor_value map: value: - 25000: 175 - 27000: 255 type: std::map<int64_t, uint64_t>
在上面的
yaml
配置中,定义了在zone0_ambient
不同温度下的风扇的地板以及天花板速度,如
i. 当温度低于 27 摄氏度,地板速度为 85
ii. 当温度在 27-32 摄氏度之间,地板速度为 112注意:
Romulus
风扇比较简单,如果想看复杂的例子,可以参考 Witherspoon fan configurations,在这个例子有如下的额外配置:- 通过 GPIO 监测在位信息
- 通过 GPIO 监测风冷还是水冷
- 具有更多的传感器及更多的事件
GPIOs
本小节主要关注于设备树中必须监控的 GPIOs,比如:
- 一个 GPIO 可能表示一个主机故障点信号(host checkstop)
- 一个 GPIO 可能表示一个按钮按下(button)
- 一个 GPIO 可能表示设备链接(device attach)
有 phosphor-gpio-presense
用来监测设备在位,phosphor-gpio-monitor
用于监测一个 GPIO。
设备树中的 GPIO
所有监测的 GPIOs 必须在设备树中进行描述,比如:
gpio-keys {
compatible = "gpio-keys";
checkstop {
label = "checkstop";
gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
linux,code = <ASPEED_GPIO(J, 2)>;
};
id-button {
label = "id-button";
gpios = <&gpio ASPEED_GPIO(Q, 7) GPIO_ACTIVE_LOW>;
linux,code = <ASPEED_GPIO(Q, 7)>;
};
};
如下的代码描述两个 GPIO 引脚,一个是 checkstop
另一个是 id-button
,引脚代码来在aspeed-gpio.h:
#define ASPEED_GPIO_PORT_A 0
#define ASPEED_GPIO_PORT_B 1
...
#define ASPEED_GPIO_PORT_Y 24
#define ASPEED_GPIO_PORT_Z 25
#define ASPEED_GPIO_PORT_AA 26
...
#define ASPEED_GPIO(port, offset) \
((ASPEED_GPIO_PORT_##port * 8) + offset)
GPIO 在位
Witherspoon
以及 Zaius
具有 GPIO 在位的例子:
-
INVENTORY=/system/chassis/motherboard/powersupply0 DEVPATH=/dev/input/by-path/platform-gpio-keys-event KEY=104 NAME=powersupply0 DRIVERS=/sys/bus/i2c/drivers/ibm-cffps,3-0069
它监测 GPIO 引脚 104,作为
powersupply0
的在位情况,创建资产对象,并绑定或解除绑定驱动 -
INVENTORY=/system/chassis/pcie_card_e2b DEVPATH=/dev/input/by-path/platform-gpio-keys-event KEY=39 NAME=pcie_card_e2b
它监测 GPIO 引脚 39,作为
pcie_card_e2b
的在位情况,创建资产目标
GPIO 监测
通常的 GPIO 监测用来监测主机的故障点事件,或按钮按下。
- checkstop monitor 是一个
OpenPOWER
机型的常用服务
默认情况下,它监测 GPIO 引脚 74,如果它触发,将告知DEVPATH=/dev/input/by-path/platform-gpio-keys-event KEY=74 POLARITY=1 TARGET=obmc-host-crash@0.target
systemd
启动obmc-host-crash@0.target
。
对于使用不同 GPIO 引脚作为故障监测点的,它简单在meat-machine
层指定自己的配置文件,来覆盖原有的默认的配置即可。
比如 Zaius's checkstop config.
注意: 当引脚触发,phosphor-gpio-monitor
启动目标并退出 - id-button monitor 是
Romulus
中的服务,用来监测定位按钮按下
它监测 GPIO 引脚 135 按钮按下,并启动服务DEVPATH=/dev/input/by-path/platform-gpio-keys-event KEY=135 POLARITY=1 TARGET=id-button-pressed.service EXTRA_ARGS=--continue
id-button-pressed.service
,这个服务设置定位指示灯触发相应的Assert
动作
注意: 它具有额外的参数--continue
,告知phosphor-gpio-monitor
按钮按下后,不要退出,继续工作