blob: 6a5f291eeeecf05eed96b070e7a79df5da6cfe37 [file] [view]
# Host State Module
<!--*
# Document freshness: For more information, see go/fresh-source.
freshness: { owner: 'tlbmc-dev' reviewed: '2026-06-05' }
*-->
## Overview & Purpose
The **Host State** subsystem in tlBMC is responsible for monitoring, reporting,
and actuating the physical power state (`PowerState`) and operating system
execution state (`OSState`) of the host machine.
When integrated into a platform, this module acts as the authoritative source
for host power transitions and drives Redfish chassis power status and
`ComputerSystem` reset actions (such as `PowerOn`, `ForceOff`,
`GracefulShutdown`, and `GracefulRestart`). It provides a flexible architecture
supporting direct hardware actuation via GPIO pins as well as seamless software
integration via Linux `inotify` file watching for platforms utilizing external
power control agents.
--------------------------------------------------------------------------------
## Abstract `PowerControl` Interface
At the core of the host state management architecture is the abstract
`PowerControl` interface defined in
[power_control.h](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/power_control.h).
This interface establishes a unified contract for querying power status,
executing reset actions, and subscribing to state transition events.
### Key Control Methods
* **`SystemResetRequest(ResetType reset_type, absl::Duration delay)`**:
Maps high-level Redfish actions to specific hardware/software actuation
sequences based on the requested `ResetType`:
* `RESET_TYPE_ON` / `FORCE_ON` $\rightarrow$ `PowerOnRequest()`
* `RESET_TYPE_FORCE_OFF` $\rightarrow$ `PowerOffRequest()`
* `RESET_TYPE_POWER_CYCLE` $\rightarrow$ `PowerCycleRequest()`
* `RESET_TYPE_FORCE_RESTART` $\rightarrow$ `ResetRequest()`
* `RESET_TYPE_GRACEFUL_SHUTDOWN` $\rightarrow$
`GracefulPowerOffRequest()`
* `RESET_TYPE_GRACEFUL_RESTART` $\rightarrow$
`GracefulPowerCycleRequest()`
* **`GetHostState()`**: Returns the complete current `HostState` protobuf
containing the host identifier, current `PowerState`, and current `OSState`.
### Event Subscription Methods
Subsystems and external services can register thread-safe callbacks triggered
during critical host transitions:
* **`RegisterHostPowerOnToOffCallback`**: Invoked when the chassis transitions
from powered-on to off.
* **`RegisterHostPowerOffToOnCallback`**: Invoked when the chassis asserts
power-ok and transitions from off to powered-on.
* **`RegisterHostOSInactiveToStandbyCallback`**: Invoked when host POST
completes successfully.
* **`RegisterHostOSStandbyToInactiveCallback`**: Invoked when OS execution
halts or resets.
--------------------------------------------------------------------------------
## Hardware Actuation Mode (`PowerControlGpio`)
The **`PowerControlGpio`** implementation
([power_control.cc](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/power_control.cc))
interacts directly with physical board logic to govern host state transitions
and actuate hardware signals.
### State Machine Transitions
`PowerControlGpio` maintains an active internal state machine representing the
chassis state:
* `POWER_STATE_ON`: Physical power is established and verified.
* `POWER_STATE_WAIT_FOR_POWER_OK`: Power-on initiated; awaiting board
assertion of physical power good.
* `POWER_STATE_OFF`: System is fully powered down.
* `POWER_STATE_TRANSITION_TO_OFF`: Actively asserting force-off pulse.
* `POWER_STATE_GRACEFUL_TRANSITION_TO_OFF`: Actively awaiting graceful ACPI
shutdown.
* `POWER_STATE_CYCLE_OFF`: Intermediate off state during a power cycle before
re-initiating power-on.
* `POWER_STATE_TRANSITION_TO_CYCLE_OFF`: Initiating hard cycle shutdown.
* `POWER_STATE_GRACEFUL_TRANSITION_TO_CYCLE_OFF`: Awaiting ACPI graceful
shutdown prior to power cycle.
* `POWER_STATE_CHECK_FOR_WARM_RESET`: POST complete deasserted; verifying if
host triggered a warm reset rather than full shutdown.
### GPIO Actuation & Monitoring
* **Output Control Pins**: Actuates hardware lines via precise time-duration
pulses using `GpioCollector::SetActiveForDuration`:
* `power_out_gpio_name`: Asserted to trigger power button presses
(`PowerPulseMs` for standard toggle, `ForceOffPulseMs` for hard power
cut).
* `reset_out_gpio_name`: Asserted to trigger warm hardware reset
(`ResetPulseMs`).
* **Input Sensing Handlers**: Subscribes to hardware line status shifts:
* `PowerOkHandler`: Monitors `power_ok_gpio_name`. Rising edges transition
the host to `POWER_STATE_ON`. Falling edges trigger power-loss callbacks
and drop state to `POWER_STATE_OFF` or `POWER_STATE_CYCLE_OFF`.
* `PostCompleteHandler`: Monitors `post_complete_gpio_name`. Rising edges
set OS execution to `OS_STATE_STANDBY`. Falling edges transition OS
execution to `OS_STATE_INACTIVE` and activate warm reset verification.
### Watchdog & Steady Timers
The hardware controller utilizes asynchronous `boost::asio::steady_timer`
instances managed by `PowerControlThreadManager`:
* **`PowerCycleTimer` (`PowerCycleMs` = 5000ms)**: Enforces a steady
off-duration delay before re-enabling power during a reboot cycle.
* **`PowerOKWatchdogTimer` (`PowerOKWatchdogMs` = 8000ms)**: Fires when
power-on is requested. If `power_ok_gpio_name` fails to assert before
expiration, aborts and resets state to `POWER_STATE_OFF`.
* **`GracefulPowerOffTimer` (`GracefulPowerOffS` = 300s)**: Sets a maximum
timeout window for OS-cooperative ACPI shutdowns.
* **`WarmResetCheckTimer` (`WarmResetCheckMs` = 500ms)**: Distinguishes
between intentional host reboot events and system crashes upon POST drop.
--------------------------------------------------------------------------------
## File/inotify Integration Mode (`PowerControlInotify`)
For platforms where host power state is managed by external daemons or openbmc
legacy layers, **`PowerControlInotify`**
([host_state_collector.cc](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/host_state_collector.cc))
operates as a zero-hardware integration bridge.
### Linux `inotify` Monitoring
Instead of polling or reading GPIO lines, `PowerControlInotify` establishes
non-blocking file descriptors using `inotify_init1` and attaches
`IN_CLOSE_WRITE` watches directly to status JSON files (`host_power_file_path`
and `os_state_file_path`). Asynchronous reads are dispatched over
`boost::asio::posix::stream_descriptor`.
### D-Bus OpenBMC State Parsing
Upon detection of an `IN_CLOSE_WRITE` event, the module parses the file payload
as JSON and evaluates canonical D-Bus state strings:
* **Power State (`PowerState`)**:
* `xyz.openbmc_project.State.Chassis.PowerState.On` $\rightarrow$
`HOST_POWER_STATE_ON`
* `xyz.openbmc_project.State.Chassis.PowerState.Off` $\rightarrow$
`HOST_POWER_STATE_OFF`
* **OS Status (`OperatingSystemState`)**:
* `xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Standby`
$\rightarrow$ `OS_STATE_STANDBY`
* `xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive`
$\rightarrow$ `OS_STATE_INACTIVE`
Transitions automatically fire registered callback collections
(`host_power_on_to_off_callbacks_`, etc.).
### Robust Initialization Retries
If target synchronization files do not exist during early boot, the module
utilizes `TaskScheduler::ScheduleOneShotAsync` to execute configurable
exponential retries (default 5 attempts, 10-second intervals) until the
integration path establishes.
--------------------------------------------------------------------------------
## Protobuf Schema Reference
The primary configurations governing host state collection and actuation reside
within
[power_control.proto](file:///google3/third_party/milotic/external/cc/tlbmc/configs/power_control.proto).
### `PowerControlConfig` Schema Table
Field Name | Type | Default | Description
:-------------------------------- | :-------------------- | :--------------------------------------- | :----------
`host_id` | `string` | empty | Unique identifier for the target host instance (e.g., `"system"`).
`chassis_id` | `string` | empty | Target chassis physical identifier (e.g., `"chassis_1"`).
`power_ok_gpio_name` | `string` | empty | Input GPIO line name detecting physical host power assertion.
`post_complete_gpio_name` | `string` | empty | Input GPIO line name detecting operating system POST readiness.
`power_out_gpio_name` | `string` | empty | Output GPIO pin line triggering power button actuation.
`reset_out_gpio_name` | `string` | empty | Output GPIO pin line triggering hardware warm reset actuation.
`timer_map` | `map<string, uint32>` | standard defaults | Custom override durations for pulse widths and watchdogs in milliseconds.
`host_power_file_path` | `string` | `"/var/lib/power-control/state.json"` | Target file path monitored via `inotify` for physical power changes.
`os_state_file_path` | `string` | `"/var/lib/power-control/os-state.json"` | Target file path monitored via `inotify` for OS state transitions.
`host_power_related_state_config` | `RelatedStateConfig` | none | Mapping linking physical power status to downstream Redfish resource dependencies.
`os_state_related_state_config` | `RelatedStateConfig` | none | Mapping linking OS execution status to processor and memory resource active visibility.
--------------------------------------------------------------------------------
## Platform Configuration Examples
Platform integrators activate and tailor host state handling by supplying an
explicit `power_control_configs.textproto` bundle loaded automatically by
`ProtoConfigParser`.
### Example 1: Direct Hardware GPIO Mode
```protobuf
# proto-file: third_party/milotic/external/cc/tlbmc/configs/power_control.proto
# proto-message: PowerControlConfigs
hotswap_pin_name: "FM_HOTSWAP_PWR_CYCLE_R"
power_control_configs {
host_id: "system1"
chassis_id: "chassis_1"
power_ok_gpio_name: "PWRGD_CPU0_PLD"
post_complete_gpio_name: "POST_DONE"
power_out_gpio_name: "PWR_BTN_N"
reset_out_gpio_name: "RESET_BTN_N"
timer_map: { key: "ForceOffPulseMs" value: 5000 }
timer_map: { key: "GracefulPowerOffS" value: 300 }
timer_map: { key: "PowerCycleMs" value: 5000 }
timer_map: { key: "PowerOKWatchdogMs" value: 8000 }
timer_map: { key: "PowerPulseMs" value: 1000 }
timer_map: { key: "ResetPulseMs" value: 100 }
}
```
### Example 2: File-Based `inotify` Bridge Mode
```protobuf
# proto-file: third_party/milotic/external/cc/tlbmc/configs/power_control.proto
# proto-message: PowerControlConfigs
power_control_configs {
host_id: "system"
chassis_id: "chassis_main"
host_power_file_path: "/var/lib/power-control/state.json"
os_state_file_path: "/var/lib/power-control/os-state.json"
host_power_related_state_config {
host_id: "system"
resource_identifiers: "/phys/M2_0"
related_state: RELATED_STATE_HOST_POWER
expected_uptime { seconds: 30 }
}
os_state_related_state_config {
host_id: "system"
resource_identifiers: "/phys/CPU0"
resource_identifiers: "/phys/DIMM0"
related_state: RELATED_STATE_OS_STATE
}
}
```
--------------------------------------------------------------------------------
## Code References
* **Main Interfaces**:
* [power_control.h](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/power_control.h)
* [host_state_collector.h](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/host_state_collector.h)
* **Primary Implementations**:
* [power_control.cc](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/power_control.cc)
* [host_state_collector.cc](file:///google3/third_party/milotic/external/cc/tlbmc/host_state/host_state_collector.cc)
* **Configuration & Schemas**:
* [power_control.proto](file:///google3/third_party/milotic/external/cc/tlbmc/configs/power_control.proto)
* [proto_config_parser.cc](file:///google3/third_party/milotic/external/cc/tlbmc/configs/proto_config_parser.cc)