|
root / docs / SMF_MIGRATION.md
SMF_MIGRATION.md markdown 1110 lines 59.7 KB

SMF Migration — Handoff to Hammerhead

This document hands off the remaining SMF-removal work from the zyginit project to
the Hammerhead team. It covers source vendoring, build integration, the decision
process for converting each SMF manifest to a zyginit TOML service definition,
worked examples, anti-patterns drawn from the iter 1-20 development history,
per-category guidance, and a coarse catalog of all 128 manifests found on
hh-prototest as of 2026-05-02.

See also: docs/DESIGN.md for the zyginit architecture reference;
docs/ROADMAP.md for the forward-looking task checklist.


1. Handoff Brief

This section orients the Hammerhead team on what zyginit has done, what is left,
and where to ask questions.

What zyginit has done (through rev 82)

zyginit is a working replacement for svc.startd, svc.configd, and the SMF
master restarter — a single Reef process that acts as PID 1, supervises services
defined in TOML files, and exposes an administrative socket for zygctl.

As of rev 82 (2026-05-02), zyginit boots Hammerhead to a fully-functional
multi-user state on hh-prototest (192.168.122.50) without any SMF
infrastructure running:

  • Multi-user boot — all tier-0 through tier-7 services start cleanly.
  • Single-user mode — boot arg -s or runtime zygctl single drops to
    /sbin/sh on /dev/console.
  • Runtime runlevel transitionszygctl single / zygctl multi (and the
    init s / init 3 sysv wrappers) work bidirectionally.
  • Clean shutdownzygctl halt / reboot / poweroff perform a
    reverse-tier stop, ZFS sync, umountall -l, and uadmin from a forked
    non-PID-1 child.
  • utmpx integrationwho -b, who -r, and uptime report correctly.
  • 18 services converted — the current boot chain in services/hammerhead/
    covers the essential Hammerhead daemons. These TOMLs are the starting point
    for the Hammerhead source tree.

What the Hammerhead team must do

  1. Vendor zyginit source into hammerhead-userland (see Section 5 for the
    file-by-file layout and build instructions).
  2. Wire the build to produce /sbin/init (zyginit), /sbin/zygctl, and
    /sbin/sysv-wrapper with its symlinks.
  3. Migrate the 18 existing TOMLs from services/hammerhead/ into the
    Hammerhead source tree.
  4. Validate that the vendored source builds and boots identically to
    hh-prototest before starting new conversions.
  5. Convert the remaining ~110 SMF manifests using the decision tree in
    Section 2, the worked examples in Section 3, the per-category guidance in
    Section 6, and the catalog in Section 7.
  6. Remove SMF infrastructuresvc.startd, svc.configd, master restarter
    binaries, manifest infrastructure, and libscf-only consumers — from
    hammerhead-userland packaging.

Done criteria for "SMF removal complete"

  • Hammerhead boots to multi-user without svc.startd or svc.configd ever
    being invoked (verify with pgrep -fl svc.startd; expect zero results).
  • libscf is not linked into any binary in the default boot path (acceptable to
    keep libscf installed for optional/zports consumers, but no required boot
    service calls into it).
  • All 18 zyginit-managed services continue to work at least as well as the
    SMF-managed equivalents they replaced.
  • Manifest XML files and svc:/ repository infrastructure are removed from
    default packaging (they may be retained in a smf-compat optional package
    for administrators who need to run SMF tooling temporarily).
  • halt, reboot, poweroff, and init <N> reach the hardware-level
    operation cleanly.

Coordination

  • Questions about existing zyginit behavior — open an issue against the
    zyginit repo. Include the service name, the symptom, and the hh-prototest log
    output.
  • TOML fields that don't fit a service's needs — file an RFE against zyginit.
    Do not work around missing features in the service scripts; get the runtime
    feature first.
  • Hammerhead team's scope — modifying hammerhead-userland is the
    Hammerhead team's job. The zyginit CLAUDE.md constraint "DO NOT modify
    Hammerhead source code" applies to the zyginit-project Claude, not to the
    Hammerhead Claude. The Hammerhead Claude should freely modify its own tree.

See also: Section 5 (Integration with Hammerhead), docs/ROADMAP.md
"SMF Removal from Hammerhead."


2. Decision Tree

This section is the core reference for every manifest conversion. Walk each
manifest through the three steps in order.

Step 1 — Should this service exist on Hammerhead at all?

Does Hammerhead ship this functionality?
   |
   +-- No: deprecated, SPARC-only, SMF infrastructure, or NIS/iSCSI/etc.
   |     --> DROP. Remove from packaging; do not write a TOML.
   |         The catalog (Section 7) lists the obvious drops.
   |
   +-- Possibly, but as an optional zports add-on (Kerberos KDC, iSNS, etc.)
   |     --> DEFER. Out of scope for hammerhead-userland; leave for zports.
   |
   +-- Yes, ships in hammerhead-userland
         --> Continue to Step 2.

Mandatory: do not skip Step 1. Converting a service "because it exists" is
the single biggest source of wasted effort. The 128 manifests include services
Hammerhead does not and should never ship (SMF infrastructure, SPARC platform
code, NIS, iSCSI target, Trusted Extensions label daemon, etc.). These are
straightforward drops.

Step 2 — Is the service coupled to SMF infrastructure at runtime?

Does the daemon call into svc.configd / libscf / the SMF repository door
at runtime (not just at startup)?
   |
   +-- Yes, fundamentally requires libscf or the repository for ongoing
   |   operation (e.g., svc.startd, svc.configd themselves)
   |     --> DROP (if it IS SMF) or INVESTIGATE (if it merely uses libscf).
   |         For investigate: look for a foreground/standalone mode flag.
   |         Coordinate with the daemon's upstream if none exists.
   |
   +-- Yes at startup, but the daemon has a non-SMF mode flag
   |   (-d, -f, -D, or similar) that skips the startup gate and the
   |   daemonize double-fork
   |     --> CONVERT using the foreground-mode pattern. See Example 1.
   |         Known flags on Hammerhead daemons:
   |           dlmgmtd   -d   (debug/foreground; bypasses SMF_FMRI gate)
   |           ipmgmtd   -f   (identical pattern)
   |           sshd      -D   (standard OpenSSH; no daemonize)
   |           syslogd   -d   (foreground; standard illumos)
   |           fmd       -f   (foreground; from fmd source)
   |         Check each daemon's man page and source before assuming
   |         SMF coupling is unavoidable.
   |
   +-- No SMF coupling, or coupling is purely cosmetic (e.g., SMF_FMRI
       env var used only for a cache-file name)
         --> Continue to Step 3.

Getting Step 2 wrong was the entire iter 1-5 dead end. When dlmgmtd was
started without its foreground flag, it failed silently — no error on stderr
(daemonize had already closed fd 2), and the network never came up. See
memory/pid1_boot_iter11_15.md for the full diagnosis.

Step 3 — What runs the service today?

What does the SMF exec_method actually invoke?
   |
   +-- Direct daemon binary (no method script)
   |     --> CONVERT with a simple TOML. exec.start = the binary + args.
   |         Most daemons with exec=':kill' for stop use the contract
   |         signal by default — omit [stop] unless you need custom signal.
   |
   +-- /lib/svc/method/<name> shell script
   |     |
   |     +-- Script is trivial (rm a FIFO, mkdir, then exec the daemon)
   |     |     --> INLINE the setup into a wrapper start.sh. See Example 2.
   |     |         Services that take this path: cron (rm FIFO + exec),
   |     |         syslogd (touch /var/adm/messages + exec), console-login
   |     |         (write utmpx entry + exec ttymon).
   |     |
   |     +-- Script sources /lib/svc/share/smf_include.sh AND calls
   |     |   smf_present() or smf_clear_method_context()
   |     |     --> Check if smf_present() branch is the failure path only.
   |     |         If so, the script works fine without configd (smf_present
   |     |         returns false; the relevant branch is skipped). Test
   |     |         carefully. Many scripts are safe even with smf_include.sh.
   |     |
   |     +-- Script does substantial, maintained setup work
   |           --> KEEP the method script as exec.start. Add SMF_FMRI to
   |               [exec] environment if the script requires it for
   |               non-configd purposes (e.g., FIFO name, log prefix).
   |               See Example 2 alternate form.
   |
   +-- Oneshot configuration command (mountall, swapadd, dumpadm, coreadm)
   |     --> CONVERT as type = "oneshot". See services/hammerhead/
   |         root-fs.toml, swap.toml, filesystem.toml for patterns.
   |         Onshots use restart.on = "never".
   |
   +-- inetd-managed service (not a standalone daemon)
         --> DROP unless there is a strong reason to keep inetd.
             Hammerhead does not run inetd. If the underlying
             functionality is needed (e.g., legacy RPC), the service
             needs its own TOML as a standalone daemon.

Field-by-field translation table

SMF manifest element TOML field Notes
<service name='X'> [service] name Strip the category prefix (e.g., network/ssh"sshd")
<template><common_name> [service] description Plain string; omit XML whitespace
SMF behavior class [service] type Map: continuous daemon → "daemon"; fire-and-forget → "oneshot"; transient SMF → "transient"
<exec_method name='start' exec='...'> [exec] start Replace with binary + foreground flag if Step 2 says foreground-mode; or use method script path if Step 3 says keep
<exec_method name='stop' exec=':kill'> (omit — default) :kill in SMF = send contract signal; zyginit does this by default via [stop] method = "contract"
<exec_method name='stop' exec='some-cmd'> [stop] method = "exec" + [exec] stop = "some-cmd" For custom stop scripts
<dependency type='service' ...><service_fmri value='svc:/X'> [dependencies] requires = ["X"] Translate FMRI basename; drop all SMF-internal dependencies (milestone/, system/svc/, restarter)
<dependency type='path' ...> [dependencies] requires = ["filesystem"] Path deps mean "filesystem is up"; map to the filesystem service
<property_group name='startd'><propval name='duration' value='transient'> [service] type = "oneshot" SMF transient duration = zyginit oneshot
<property_group name='general'><propval name='enabled'> (not in TOML) Enabled state is set by the operator via symlink in /etc/zyginit/enabled.d/
Restart policy [restart] on = "always|failure|never" SMF ignore_erroron = "failure"; SMF restart contract → on = "always"
<property_group name='startd'><propval name='ignore_error' value='core,signal'> [restart] on = "failure" Core + signal ignores = only restart on clean failure
<method_context><method_credential user='X' group='Y'> [exec] user = "X" and [exec] group = "Y" Drop privileges before exec
<method_context working_directory='/'> [exec] working_directory = "/" Inherited if omitted; specify if non-root
Contract params [contract] param = [...] Defaults (["inherit", "noorphan"]) are correct for most services

See also: docs/man/man5/zyginit.5 for the authoritative field-by-field
TOML format reference; this table covers patterns and translation, not syntax.


3. Worked Examples

This section walks three representative manifests through the full
conversion process.


Example 1 — Foreground-mode conversion: dlmgmtd

Manifest: /lib/svc/manifest/network/dlmgmt.xml
Result: services/hammerhead/dlmgmtd.toml
Pattern: foreground-mode (Decision Tree Step 2, middle branch)

Original manifest (key lines)

<service name='network/datalink-management' type='service' version='1'>
    <dependent name='dlmgmt-device-system' grouping='require_all'
        restart_on='none'>
        <service_fmri value='svc:/system/device/local' />
    </dependent>
    <exec_method type='method' name='start'
        exec='/lib/svc/method/svc-dlmgmtd' timeout_seconds='60' />
    <exec_method type='method' name='stop' exec=':kill' timeout_seconds='3' />

/lib/svc/method/svc-dlmgmtd checks for SMF_FMRI and calls dlmgmtd
with no additional flags — dlmgmtd daemonizes on its own.

Decision-tree walk

  • Step 1: Yes, Hammerhead ships dlmgmtd. It is required for ifconfig plumb
    and dladm to work at all on illumos; libdladm resolves link names through
    dlmgmtd's door.
  • Step 2: Yes, dlmgmtd checks getenv("SMF_FMRI") at startup to derive a
    cache-file name, then calls daemonize(). Without the foreground flag, both
    checks happen even when started outside SMF. But dlmgmtd -d skips both:
    the debug-mode branch in dlmgmt_main.c bypasses the SMF_FMRI check and
    the dlmgmt_daemonize() call entirely. The door is still created at the same
    path. This is the foreground-mode pattern — use -d.
  • Step 3: not reached (Step 2 resolved it).

Resulting TOML

The existing services/hammerhead/dlmgmtd.toml is the production result.
Its comment block explains each decision:

# dlmgmtd — Datalink management daemon
#
# Runs in `-d` (debug) mode, which on dlmgmtd means "single foreground
# process, no double-fork daemonize." Three reasons we use it:
#   1. Skips the SMF_FMRI startup gate (debug mode bypasses the check).
#   2. Keeps stderr connected to our log; without it dlmgmtd's daemonize
#      runs fdwalk(closefunc), closing fd 2 — any startup error then
#      goes to syslog, which isn't running yet at this tier.
#   3. zyginit's contract tracks a single PID instead of dealing with
#      the parent-exits-0-after-handshake daemonize pattern.
# Cosmetic effect: the cache file is named "dlmgmtd.debug.cache" instead
# of "network-datalink-management:default.cache". Nothing external reads
# this file — only dlmgmtd itself, for fast restart state recovery.

[service]
name = "dlmgmtd"
description = "Datalink management daemon (foreground)"
type = "daemon"

[exec]
start = "/sbin/dlmgmtd -d"

[dependencies]
requires = ["filesystem"]

[restart]
on = "failure"
delay = 5
max_retries = 3

[contract]
param = ["inherit", "noorphan"]
fatal = ["hwerr"]

Key field mapping decisions

  • name — FMRI basename network/datalink-management collapsed to dlmgmtd.
  • exec.start — direct binary + flag; method script path dropped entirely.
  • dependencies.requires = ["filesystem"] — the SMF <dependent> blocks on
    network/physical are dropped (SMF-internal ordering, not real deps).
  • stop — omitted; SMF's :kill = zyginit's default contract signal.
  • contract.fatal = ["hwerr"] not ["hwerr", "empty"] — the daemonize
    handshake transiently empties the contract; zyginit handles that correctly.

Verify after boot: pgrep -fl dlmgmtd shows dlmgmtd -d; ls /etc/svc/volatile/dladm/dlmgmt_door shows the door; dladm show-phys returns the NIC list.

See also: memory/pid1_boot_iter11_15.md for the diagnostic history;
services/hammerhead/ipmgmtd.toml for the identical pattern applied to ipmgmtd.


Example 2 — Method-script wrap: cron

Manifest: /lib/svc/manifest/system/cron.xml
Result: services/hammerhead/cron.toml + services/hammerhead/cron/start.sh
Pattern: trivial method-script inlined (Decision Tree Step 3, inline branch)

Original manifest (key lines)

<service name='system/cron' type='service' version='1'>
    <dependency name='usr' type='service' grouping='require_all' restart_on='none'>
        <service_fmri value='svc:/system/filesystem/local' />
    </dependency>
    <dependency name='ns' type='service' grouping='require_all' restart_on='none'>
        <service_fmri value='svc:/milestone/name-services' />
    </dependency>
    <exec_method type='method' name='start' exec='/lib/svc/method/svc-cron'
        timeout_seconds='60'>
        <method_context><method_credential user='root' group='root' /></method_context>
    </exec_method>
    <exec_method type='method' name='stop' exec=':kill' timeout_seconds='60' />

/lib/svc/method/svc-cron sources smf_include.sh (for $SMF_EXIT_*
constants and smf_zonename — no configd call), removes /etc/cron.d/FIFO if
stale, and runs /usr/sbin/cron &.

Decision-tree walk

  • Step 1: Yes, Hammerhead ships cron. Required for log rotation and
    scheduled tasks.
  • Step 2: No SMF coupling. svc-cron sources smf_include.sh only for
    $SMF_EXIT_* constants and smf_zonename (which calls /sbin/zonename — no
    configd). The exit codes are not observed by zyginit's contract model anyway.
    No configd calls anywhere.
  • Step 3: Method script. Assessment: trivial. The script does two things
    before starting cron: check for a stale FIFO and remove it. The pgrep guard
    is irrelevant under zyginit (supervisor doesn't double-start). The cron &
    backgrounding is replaced by exec /usr/sbin/cron in the wrapper.

Two valid TOML forms

Form A — Inline the setup in a wrapper start.sh (production choice):

[service]
name = "cron"
description = "cron daemon"
type = "daemon"

[exec]
start = "/etc/zyginit/cron/start.sh"

[dependencies]
requires = ["syslogd"]

[restart]
on = "failure"
delay = 5
max_retries = 3

[contract]
param = ["inherit", "noorphan"]
fatal = ["hwerr"]

With services/hammerhead/cron/start.sh:

#!/bin/zsh
# Clean up stale FIFO before starting cron.
# /usr/sbin/cron creates /etc/cron.d/FIFO at startup and refuses to
# start if the file already exists — mirrors svc-cron's behavior.
set -e
/bin/rm -f /etc/cron.d/FIFO
exec /usr/sbin/cron

Form B — Use method script directly (transitional):

[exec]
start = "/lib/svc/method/svc-cron"
environment = ["SMF_FMRI=svc:/system/cron:default"]

Choose Form A when the setup is short and you want to decouple from SMF method
script files (the preferred end state — /lib/svc/method/svc-cron will be
removed). Choose Form B as a transitional step when the method script does
substantial correct setup and does not call smf_present() in any required
code path.

Key field mapping decisions

  • dependencies.requires = ["syslogd"] — SMF's milestone deps (filesystem/local,
    name-services) are replaced with direct deps on zyginit services. Drop all
    milestone FMRI references; they don't exist in zyginit.
  • type = "daemon" — continuous daemon; SMF's <single_instance/> is implicit.
  • stop omitted; working_directory and user/group = root omitted (defaults).

See also: services/hammerhead/syslogd.toml and
services/hammerhead/syslogd/start.sh for the same pattern (touch log file +
exec daemon); services/hammerhead/console-login/ for a more involved wrapper
(write utmpx entry + exec ttymon).


Example 3 — Drop: svc.startd / system/svc/restarter

Manifest: /lib/svc/manifest/system/svc/restarter.xml
Result: DROP — no TOML.
Pattern: Decision Tree Step 1, no branch.

Original manifest (key lines)

<service name='system/svc/restarter' type='restarter' version='1'>
    <create_default_instance enabled='true' />
    <exec_method type='method' name='start' exec=':true' timeout_seconds='0' />
    <exec_method type='method' name='stop'  exec=':true' timeout_seconds='0' />

FMRI: svc:/system/svc/restarter:default. The exec methods are :true because
the kernel never invokes them — init starts svc.startd directly, and this
manifest exists only so svc.startd can store its own properties in the
SMF repository.

Decision-tree walk

  • Step 1: No. This manifest IS SMF. zyginit replaces the functionality of
    svc.startd, svc.configd, and the master restarter framework entirely.
    There is nothing to convert. DROP.

The cascade

Every other SMF manifest on the system has at least one <dependency> block
referencing SMF-internal FMRIs. When you convert those services, drop all such
references. They are not real ordering constraints between daemons — they are
SMF's internal "this-service-needs-the-SMF-infrastructure" boilerplate.

Common SMF-internal FMRIs to drop from requires when converting:

svc:/system/svc/restarter:default     (the restarter framework itself)
svc:/milestone/single-user:default    (SMF single-user milestone)
svc:/milestone/multi-user:default     (SMF multi-user milestone)
svc:/milestone/name-services:default  (SMF name-services milestone)
svc:/milestone/network:default        (SMF network milestone)
svc:/milestone/sysconfig:default      (SMF sysconfig milestone)
svc:/system/manifest-import:default   (SMF manifest import oneshot)
svc:/system/early-manifest-import:default

Replace the real ordering constraints (filesystem, syslogd, dlmgmtd, etc.)
with bare service names pointing at the corresponding zyginit-managed services.

Companion drops

The following manifests are all SMF infrastructure and must be dropped along
with the restarter:

Manifest FMRI Reason
system/svc/restarter.xml svc:/system/svc/restarter:default Is svc.startd
system/svc/global.xml svc:/system/svc/global:default SMF global property store
system/early-manifest-import.xml svc:/system/early-manifest-import:default SMF import at boot
system/manifest-import.xml svc:/system/manifest-import:default SMF import daemon

The SMF binaries to remove from hammerhead-userland packaging:
/lib/svc/bin/svc.startd, /lib/svc/bin/svc.configd,
/usr/sbin/svcadm, /usr/sbin/svccfg, /usr/sbin/svcs,
/usr/sbin/svcprop. The /lib/svc/share/smf_include.sh helper library
can remain if any method scripts continue to be used during the transition
(Form B of method-wrap); remove it when all method scripts are replaced.

See also: Section 6 "Per-Category Guidance" for the full system/svc/
category drop rule.


4. Anti-patterns and Gotchas

This section documents known failure modes from the iter 1-20 development
history. Each entry gives the symptom, root cause, and fix.

1. configd-coupled daemons degrade silently

Symptom: Service starts (fork succeeds, contract created), but functionality
is absent — dladm show-phys returns empty, ifconfig plumb returns
"no such interface."

Cause: Daemon checks getenv("SMF_FMRI") or calls into libscf at startup.
Without svc.configd running, the check fails or the call blocks/returns
error, and the daemon silently skips its initialization. No log output because
the daemon's daemonize() call has already closed stderr (fd 2) before the
error is reached.

Fix: Use the daemon's foreground/debug flag (see Decision Tree Step 2).
In foreground mode the SMF_FMRI check is bypassed AND stderr stays connected
to zyginit's log, so startup errors are visible. Never start a configd-coupled
daemon without its foreground flag.

Reference: memory/pid1_boot_iter11_15.md (dlmgmtd and ipmgmtd diagnosis).

2. Foreground-flag names vary by daemon

Symptom: You know a foreground mode exists but can't find the right flag.

Cause: There is no standard flag name. Each daemon chose its own.

Fix: Check the daemon's man page, its main() usage string, and
(for open-source daemons) its source. Known Hammerhead flags:

Daemon Flag Effect
dlmgmtd -d foreground, no daemonize, bypass SMF_FMRI gate
ipmgmtd -f identical pattern
sshd -D foreground, no daemonize (standard OpenSSH)
syslogd -d foreground (standard illumos)
fmd -f foreground (Fault Manager Daemon)
inetd n/a SMF_FMRI env var required instead

For daemons where no foreground flag exists, consider Form B method-wrap
(keep the SMF method script) as a transitional option.

3. soconfig must run before any network sockets

Symptom: socket(AF_INET, ...) returns EAFNOSUPPORT even though the
network interface is up.

Cause: illumos sockfs's protocol map is not populated until soconfig -d /etc/sock2path.d runs. SMF's system/device/local did this; without it AF_INET is unknown to the kernel.

Fix: services/hammerhead/devfs/start.sh runs soconfig in the devfs tier.
All services that need networking depend (directly or transitively) on devfs.
Reference: memory/pid1_boot_iter11_15.md, iter 11.

4. Daemonize handshake: supervisor sees "stopped (exit 0)"

Symptom: zygctl status shows a daemon as STOPPED right after start even though it is running.

Cause: Double-fork daemonize — the wrapper parent exits 0 while the daemon child is alive in the contract.

Fix: zyginit (rev 78+) detects the handshake: type = "daemon" + parent exits 0 + contract still has processes → clear rt.pid but keep the contract. Ensure TOML says type = "daemon", not "oneshot".
Reference: memory/pid1_boot_iter16.md.

5. /var/run is not tmpfs in the current zyginit BE

Symptom: Stale socket, PID, or lock files survive reboots.

Cause: Standard illumos mounts /var/run as tmpfs via fs-minimal. zyginit's filesystem/start.sh does not yet do this.

Fix (short-term): Add rm -f /var/run/<svc>.pid in affected start.sh wrappers. Long-term: add mount -F tmpfs swap /var/run to filesystem/start.sh. socket.reef already handles stale socket recovery via unlink-before-bind.

6. utmpx record positioning for who(1) -r

Symptom: who -r reports the wrong runlevel after a zygctl single / zygctl multi transition.

Cause: pututxline(3C) appends a new RUN_LVL record unless getutxid positions the cursor on an existing one first. who -r reads only the first matching record.

Fix: Call getutxid before pututxline. The zyginit_write_runlvl_utmpx helper in src/helpers.c does this correctly; use it.
Reference: memory/pid1_boot_iter18.md.

7. Do not set ZFS readonly=on during shutdown

Symptom: After zygctl reboot, the next boot sees pre-shutdown state — stale socket, daemons appear wrong.

Cause: zfs set readonly=on on the live root mid-shutdown makes all subsequent writes (including socket unlink and log writes) silently fail. ZFS records the pre-readonly txg; next boot sees it.

Fix: Remove readonly=on from any stop script. ZFS is transactionally consistent; zpool sync + umountall -l + kernel's vfs_syncall (in mdboot) is sufficient. root-fs/stop.sh was corrected in rev 82.
Reference: memory/pid1_shutdown_fix.md, bug #2.

8. uadmin must not be called from PID 1

Symptom: zygctl reboot completes the shutdown log but does not reset the hardware. The kernel re-execs /sbin/init; uptime does not reset; orphaned daemons collide with the new instance.

Cause: uadmin called from PID 1 hits the restart_init path — the kernel re-execs init before mdboot() fires the hardware reset.

Fix: Fork a child; call uadmin from the child (non-PID-1). Parent enters infinite sleep. This mirrors cmd/svc/startd/graph.c:do_uadmin. See src/main.reef shutdown sequence.
Reference: memory/pid1_shutdown_fix.md, bug #1.

9. /etc/hosts: localhost only, no hostname entry

Symptom: SSH login takes ~20 seconds even with the network up.

Cause: The bare Hammerhead BE ships /etc/hosts with only localhost. sshd does a reverse DNS lookup on the client address; without a local entry or working resolver, it times out.

Fix (operator): Add the system's IP and hostname to /etc/hosts.
Fix (upstream): File as a Hammerhead base-system bug; the install or identity service should populate /etc/hosts. Not a zyginit issue.


5. Integration with Hammerhead

This section specifies how to vendor zyginit into hammerhead-userland and
wire it into the Hammerhead build.

5.1 Source layout

Recommended target layout in the Hammerhead source tree (BSD/illumos convention
for cmd/ userland utilities):

usr/src/cmd/init/
    src/                  <- zyginit Reef source files
    src/helpers.c         <- required C helper (non-optional)
    services/             <- service TOML definitions and start/stop scripts
    reef.toml             <- reefc project config

usr/src/cmd/zygctl/
    src/                  <- zygctl Reef source files
    src/symlink_wrapper.c <- required C helper for zygctl

usr/src/cmd/sysv-wrapper/
    wrapper.c
    Makefile
    <- builds /sbin/sysv-wrapper; Makefile install creates symlinks

usr/src/man/man5/
    zyginit.5

usr/src/man/man8/
    zyginit.8
    zygctl.8

The sync mechanism (git submodule, source snapshot, or fetch-and-extract)
is the Hammerhead team's call. A simple approach: tag zyginit releases in its
repo, fetch a source archive at a known tag, unpack under usr/src/cmd/init/.

5.2 File-by-file source mapping

zyginit repo path Hammerhead target Notes
src/*.reef usr/src/cmd/init/src/ All Reef source files
src/helpers.c usr/src/cmd/init/src/ Required for link
src/contract_linux_stubs.c DROP Linux-only stubs; not for Hammerhead
services/hammerhead/*.toml usr/src/cmd/init/services/ 18 converted service definitions
services/hammerhead/*/ usr/src/cmd/init/services/<svc>/ Per-service start.sh / stop.sh subdirs
reef.toml usr/src/cmd/init/reef.toml reefc project config
tools/zygctl/src/ usr/src/cmd/zygctl/src/ zygctl Reef source
tools/zygctl/src/symlink_wrapper.c usr/src/cmd/zygctl/src/ Required for zygctl link
tools/zygctl/reef.toml usr/src/cmd/zygctl/reef.toml zygctl reefc config
tools/sysv-wrapper/wrapper.c usr/src/cmd/sysv-wrapper/ sysv-init compat wrapper
tools/sysv-wrapper/Makefile usr/src/cmd/sysv-wrapper/ Builds + installs symlinks
docs/man/man5/zyginit.5 usr/src/man/man5/
docs/man/man8/zyginit.8 usr/src/man/man8/
docs/man/man8/zygctl.8 usr/src/man/man8/

5.3 Build invocation

The Hammerhead master build must invoke these steps for usr/src/cmd/init/:

# Build helpers.o
gcc -c src/helpers.c -o build/helpers.o

# Build zyginit daemon (produces build/zyginit)
reefc build -l contract --obj build/helpers.o

# Install
cp build/zyginit /sbin/init

For usr/src/cmd/zygctl/:

gcc -c src/symlink_wrapper.c -o build/symlink_wrapper.o
reefc build --obj build/symlink_wrapper.o
cp build/zygctl /sbin/zygctl

For usr/src/cmd/sysv-wrapper/:

make
make install
# Creates /sbin/sysv-wrapper and symlinks:
#   /sbin/halt -> /sbin/sysv-wrapper
#   /sbin/reboot -> /sbin/sysv-wrapper
#   /sbin/poweroff -> /sbin/sysv-wrapper
#   /sbin/telinit -> /sbin/sysv-wrapper

Service files must be installed to /etc/zyginit/:

# Install TOML service definitions
cp services/<svc>.toml /etc/zyginit/

# Install per-service script directories
cp -r services/<svc>/ /etc/zyginit/

# Enable services by symlinking into enabled.d/
ln -s /etc/zyginit/<svc>.toml /etc/zyginit/enabled.d/<tier>-<svc>.toml

The enabled.d/ naming convention is <tier>-<svcname>.toml where tier is a
two-digit number (e.g., 00-root-fs.toml, 07-sshd.toml). See
services/hammerhead/enabled.d/ on hh-prototest for the current tier
assignments.

5.4 Reef compiler dependency

Hammerhead's build requires reefc. Options:

  1. Bootstrap from Reef repo — clone ~/repos/reef-lang/ (or the Reef
    upstream repo) and build reefc as part of the Hammerhead build setup.
    Required version: Reef 0.4.0+.
  2. Pre-built reefc — package a pre-built reefc binary for the Hammerhead
    build host (the hammerhead-build VM at 192.168.122.66 already has
    a working reefc). Simpler short-term; breaks if the build host is
    reprovisioned.

clang is not available on Hammerhead (standard Hammerhead build host uses
gcc); use gcc for helpers.c and symlink_wrapper.c.

5.5 First migration step (concrete deliverable)

Before starting any new manifest conversions, complete this validation
sequence:

  1. Vendor zyginit source at a known rev into usr/src/cmd/init/ and
    usr/src/cmd/zygctl/ and usr/src/cmd/sysv-wrapper/.
  2. Wire the build to produce /sbin/init, /sbin/zygctl, and
    /sbin/sysv-wrapper.
  3. Vendor the 18 existing TOMLs from services/hammerhead/ into
    usr/src/cmd/init/services/; install them to /etc/zyginit/ and
    symlink them in enabled.d/.
  4. Build a Hammerhead BE with the new binaries and service definitions.
  5. Boot hh-prototest from the new BE; verify all 18 services reach
    RUNNING in zygctl status; verify SSH is reachable; verify console
    login works.
  6. Only then begin the per-manifest conversion work using the decision
    tree and catalog.

Starting new conversions before step 5 is validated means any new issue
could be caused by the vendoring/build change rather than the conversion.

5.6 SMF removal step

Removing SMF infrastructure is a separate Hammerhead task after all needed
services have been converted. The sequence:

  1. Remove svc.startd and svc.configd binaries from the build and packaging.
  2. Remove SMF manifest XML files from /lib/svc/manifest/ packaging.
  3. Remove libscf linkage from any binary that links it but can be updated
    (check with ldd -r /sbin/init and any other boot-path binary).
  4. Remove svcadm, svccfg, svcs, svcprop from the default packaging
    (optionally retain in a smf-compat package for administrators).
  5. Verify boot still works end-to-end.

5.7 Upstream sync workflow

When zyginit ships new features (new TOML fields, runtime improvements):

  1. Fetch the zyginit repo at a new tag or commit hash.
  2. Refresh the vendored source under usr/src/cmd/init/.
  3. Resolve any local Hammerhead patches that conflict.
  4. Rebuild and test on hh-prototest.
  5. Record the sync point (commit hash / rev number) in Hammerhead's
    changelog entry.

See also: Section 2 (Decision Tree), docs/man/man5/zyginit.5.


6. Per-Category Guidance

This section gives top-down guidance for each SMF manifest tree category.
Read once for orientation, then drop into the catalog appendix (Section 7)
for per-manifest decisions.

milestone/

Default: DROP all. The six milestone manifests (single-user, multi-user,
multi-user-server, network, name-services, sysconfig) are SMF's
internal synchronization fences. zyginit replaces them with tier-ordered
service startup. When converting other manifests, drop all <dependency>
references to milestone FMRIs; replace with direct deps on the zyginit-managed
services that actually matter for ordering.

platform/

Default: keep amd64; drop all others. There is only one platform manifest
on hh-prototest: platform/amd64/acpihpd.xml (ACPI hotplug daemon).
Hammerhead is amd64-only; no sun4u/sun4v entries exist on this system.
acpihpd is an amd64-platform-specific daemon for hotplug events —
investigate whether Hammerhead ships the hardware that needs it;
needs-investigation until confirmed.

network/

Selective. Core networking (dlmgmtd, ipmgmtd — already converted, sshd)
are kept. The decision landscape:

  • Already converted: dlmgmtd, ipmgmtd, sshd.
  • Consolidated into network.toml: loopback, physical, initial, netmask,
    service, routing-setup — all collapsed into the single network oneshot.
  • Needs investigation: NFS (does Hammerhead ship NFS client? server?),
    DNS resolver (likely needed; investigate whether to use a standalone
    resolv.conf or run nscd), ipfilter (does Hammerhead use it?),
    IPsec (policy and algs may be needed).
  • Drop: NIS (/network/nis/ — deprecated everywhere), iSCSI target/initiator
    (storage-specific; defer to zports), iSNS server, SMB client/server (defer),
    Kerberos KDC components (server-role only; defer to zports), LDAP client
    (environment-specific), loadbalancer (ilbd), Trusted Networking (tnctl/tnd
    — Trusted Extensions, which Hammerhead does not ship).
  • Drop inetd: Hammerhead does not run inetd. The inetd.xml and
    inetd-upgrade.xml manifests are dropped. If any inetd-managed service is
    needed, write a standalone TOML for it.

system/

The largest category; mixed disposition:

  • Already converted: cron, cryptosvc (as crypto), devfs (devices-local),
    filesystem (local-fs + minimal-fs + root-fs), fmd, identity, pfexecd,
    syseventd, system-log (as syslogd), utmp (as utmpd), zones is pending.
  • Keep and convert: coreadm, dumpadm, hotplug (if hardware warrants it),
    intrd (interrupt balancer daemon), keymap, power (powerd), rbac (config
    oneshot), scheduler, vtdaemon (VT multiplexer).
  • Needs investigation: auditd (does Hammerhead ship BSM auditing?), idmap
    (identity mapping — needed if SMB/NFS Kerberos are used), name-service-cache
    (nscd), pools (resource pools — does Hammerhead use them?), rcap (resource
    capping), zonestat (zone statistics — relevant once zones are enabled).
  • Drop: All of system/svc/ (SMF infrastructure itself), manifest-import,
    early-manifest-import, logadm-upgrade (upgrade artifact), boot-archive
    and boot-archive-update (SMF-managed tasks; zyginit doesn't use
    boot-archive service), update-man-index (defer), extended-accounting
    (rarely used), fcoe_initiator / fcoe_target (storage-specific), IBSRP
    target (InfiniBand SRP — hardware-specific), i2csimd (platform-specific
    sensor daemon from a test tree), labeld (Trusted Extensions label daemon —
    Hammerhead does not ship TX), tsol-zones (Trusted Extensions zones), ndmp
    (backup protocol — defer to zports), stmf (SCSI Target Mode Framework —
    storage specific), vscan (virus scan framework — defer), ipagent (from
    a specific Nexenta/Triton context — likely irrelevant), hostid (sets
    hardware hostid; verify if Hammerhead needs it), process-security (noop
    service — just drop).

system/filesystem/

Default: all converted or redundant. All four filesystem-related manifests
(minimal-fs, local-fs, root-fs, usr-fs) are collapsed into zyginit's
filesystem.toml and root-fs.toml onshots. autofs should be dropped
unless Hammerhead actively uses automounting. vscan is dropped.

system/fm/

fmd.xml is already converted. notify-params.xml and smtp-notify.xml are
SMF notification hooks — drop or defer; zyginit has no equivalent mechanism.

system/device/

devices-local.xml is the basis for services/hammerhead/devfs.toml (the
devfsadm + soconfig oneshot). devices-audio.xml can be method-wrapped or
dropped depending on whether Hammerhead ships audio support. mpxio-upgrade.xml
is an upgrade artifact; drop.

See also: Section 7 (Catalog Appendix) for per-manifest classification.


7. Catalog Appendix

This appendix is a snapshot of all 128 SMF manifests found in
/lib/svc/manifest/ and /var/svc/manifest/ on hh-prototest as of
2026-05-02. It is a starting-point reference, not a living index — as
Hammerhead evolves, this catalog will drift from the actual source tree.

Classifications: already-converted (TOML exists in services/hammerhead/),
drop (should not be in Hammerhead), foreground (use daemon's foreground
flag), method-wrap (keep the SMF method script as exec.start), or
needs-investigation (Hammerhead-team policy decision required).

Manifest path Category Classification Note
/lib/svc/manifest/milestone/multi-user-server.xml milestone drop SMF milestone — no zyginit equivalent; referenced <dependency> blocks must be dropped from other conversions
/lib/svc/manifest/milestone/multi-user.xml milestone drop SMF milestone — tier ordering replaces it
/lib/svc/manifest/milestone/name-services.xml milestone drop SMF milestone — no zyginit equivalent
/lib/svc/manifest/milestone/network.xml milestone drop SMF milestone — network.toml replaces it
/lib/svc/manifest/milestone/single-user.xml milestone drop SMF milestone — single-user-shell.toml and runlevel mode replace it
/lib/svc/manifest/milestone/sysconfig.xml milestone drop SMF milestone — exec=:true; purely a dependency fence
/lib/svc/manifest/platform/amd64/acpihpd.xml platform needs-investigation ACPI hotplug daemon; amd64-specific; method script /lib/svc/method/svc-acpihpd; determine if Hammerhead hardware needs hotplug events
/lib/svc/manifest/network/bridge.xml network needs-investigation Bridge networking daemon; determine if Hammerhead uses software bridging
/lib/svc/manifest/network/dlmgmt.xml network already-converted services/hammerhead/dlmgmtd.toml; foreground flag -d
/lib/svc/manifest/network/dns/client.xml network needs-investigation DNS client configuration service (exec=:true — just stores resolver config in SMF repo); in zyginit world resolv.conf is written directly by the installer; determine if a service is needed
/lib/svc/manifest/network/dns/install.xml network drop Install-time DNS setup artifact
/lib/svc/manifest/network/dns/multicast.xml network needs-investigation mDNS daemon (/usr/lib/inet/mdnsd); determine if Hammerhead needs mDNS
/lib/svc/manifest/network/forwarding.xml network needs-investigation IPv4/IPv6 forwarding toggle; determine if Hammerhead acts as a router
/lib/svc/manifest/network/ibd-post-upgrade.xml network drop InfiniBand IPoIB upgrade artifact
/lib/svc/manifest/network/inetd-upgrade.xml network drop inetd upgrade artifact; Hammerhead does not run inetd
/lib/svc/manifest/network/inetd.xml network drop Hammerhead does not run inetd; existing inetd.toml in repo is an experiment, not production
/lib/svc/manifest/network/ipfilter.xml network needs-investigation IP packet filter daemon; determine if Hammerhead uses ipfilter for firewall
/lib/svc/manifest/network/ipsec/ipsecalgs.xml network needs-investigation IPsec algorithm loader (ipsecalgs -s); needed if Hammerhead uses IPsec; simple oneshot
/lib/svc/manifest/network/ipsec/manual-key.xml network needs-investigation IPsec manual key management; needs-investigation if IPsec is used
/lib/svc/manifest/network/ipsec/policy.xml network needs-investigation IPsec policy loader; simple oneshot if used
/lib/svc/manifest/network/ipsec/tcpkey.xml network needs-investigation TCP MD5 key loading; obscure; likely drop
/lib/svc/manifest/network/iscsi/iscsi-initiator.xml network drop iSCSI initiator; storage-specific; defer to zports
/lib/svc/manifest/network/iscsi/iscsi-target.xml network drop iSCSI target; storage-specific; defer to zports
/lib/svc/manifest/network/isns_server.xml network drop iSNS server; storage-specific; defer to zports
/lib/svc/manifest/network/ldap/client.xml network drop LDAP client; enterprise-specific; defer to zports or site customization
/lib/svc/manifest/network/loadbalancer/ilbd.xml network drop illumos load balancer daemon; Hammerhead does not ship this use case
/lib/svc/manifest/network/network-initial.xml network drop Consolidated into network.toml
/lib/svc/manifest/network/network-install.xml network drop Install-time artifact
/lib/svc/manifest/network/network-ipmgmt.xml network already-converted services/hammerhead/ipmgmtd.toml; foreground flag -f
/lib/svc/manifest/network/network-ipmp.xml network needs-investigation IP Multipathing daemon (in.mpathd); needed if Hammerhead uses IPMP for NIC bonding
/lib/svc/manifest/network/network-ipqos.xml network needs-investigation IP Quality of Service configuration; determine if Hammerhead uses IPQoS
/lib/svc/manifest/network/network-iptun.xml network needs-investigation IP tunnel interfaces (GRE, etc.); determine if Hammerhead uses IP tunnels
/lib/svc/manifest/network/network-location.xml network drop Network location/profile management (NWAM); Hammerhead uses static config
/lib/svc/manifest/network/network-loopback.xml network drop Consolidated into network.toml
/lib/svc/manifest/network/network-netmask.xml network drop Consolidated into network.toml; netmask config read directly
/lib/svc/manifest/network/network-physical.xml network drop Consolidated into network.toml
/lib/svc/manifest/network/network-routing-setup.xml network drop Consolidated into network.toml; static routing via /etc/defaultrouter
/lib/svc/manifest/network/network-service.xml network drop Consolidated into network.toml
/lib/svc/manifest/network/nfs/cbd.xml network needs-investigation NFS v4 callback daemon; needed only if NFS client is active
/lib/svc/manifest/network/nfs/client.xml network needs-investigation NFS client; determine if Hammerhead ships NFS client support
/lib/svc/manifest/network/nfs/mapid.xml network needs-investigation NFS v4 user/group ID mapping; needed with NFS v4
/lib/svc/manifest/network/nfs/nfslogd.xml network needs-investigation NFS logging daemon; server-side; drop unless NFS server is shipped
/lib/svc/manifest/network/nfs/nlockmgr.xml network needs-investigation NFS lock manager; needed with NFS client or server
/lib/svc/manifest/network/nfs/rquota.xml network needs-investigation Remote quota daemon; server-side; likely drop
/lib/svc/manifest/network/nfs/server.xml network needs-investigation NFS server; determine if Hammerhead ships NFS server
/lib/svc/manifest/network/nfs/status.xml network needs-investigation NFS status monitor; needed with NFS client or server
/lib/svc/manifest/network/routing/legacy-routing.xml network drop Legacy in.routed/in.rdisc; Hammerhead uses static routing
/lib/svc/manifest/network/routing/ndp.xml network needs-investigation IPv6 NDP daemon (in.ndpd); needed for IPv6 operation
/lib/svc/manifest/network/routing/ripng.xml network drop RIPng routing daemon; dynamic routing; not needed for base system
/lib/svc/manifest/network/rpc/bind.xml network already-converted services/hammerhead/rpcbind.toml; direct exec /usr/sbin/rpcbind
/lib/svc/manifest/network/rpc/gss.xml network drop GSSAPI daemon; needed only with Kerberos/NFS
/lib/svc/manifest/network/rpc/smserver.xml network drop Removable media RPC service; obsolete
/lib/svc/manifest/network/security/kadmin.xml network drop Kerberos admin server; server-role; defer to zports
/lib/svc/manifest/network/security/krb5_prop.xml network drop Kerberos slave propagation; server-role
/lib/svc/manifest/network/security/krb5kdc.xml network drop Kerberos KDC; server-role; defer to zports
/lib/svc/manifest/network/security/ktkt_warn.xml network drop Kerberos ticket warning daemon; drop unless Kerberos client is used
/lib/svc/manifest/network/shares/group.xml network drop Share group management (NFS/SMB shares); defer to zports
/lib/svc/manifest/network/shares/reparsed.xml network drop Reparse point daemon (CIFS/SMB); drop
/lib/svc/manifest/network/smb/client.xml network drop SMB client (smbfs); defer to zports
/lib/svc/manifest/network/smb/server.xml network drop SMB server (smbd); defer to zports
/lib/svc/manifest/network/ssh.xml network already-converted services/hammerhead/sshd.toml; foreground flag -D
/lib/svc/manifest/network/tnctl.xml network drop Trusted Extensions network control; TX not shipped in Hammerhead
/lib/svc/manifest/network/tnd.xml network drop Trusted Extensions network daemon; TX not shipped in Hammerhead
/lib/svc/manifest/network/varpd.xml network needs-investigation Virtual ARP daemon for overlay networking (VXLAN); determine if Hammerhead ships overlay networking
/lib/svc/manifest/network/wpa.xml network needs-investigation WPA supplicant daemon; determine if Hammerhead supports Wi-Fi
/lib/svc/manifest/system/auditd.xml system needs-investigation BSM audit daemon; determine if Hammerhead ships BSM auditing; method-wrap /lib/svc/method/svc-auditd if kept
/lib/svc/manifest/system/auditset.xml system needs-investigation Audit policy oneshot; companion to auditd; same decision
/lib/svc/manifest/system/boot-archive-update.xml system drop Updates boot archive after upgrade; SMF-infrastructure concern
/lib/svc/manifest/system/boot-archive.xml system drop Checks boot archive consistency; zyginit does not manage boot archive
/lib/svc/manifest/system/boot-config.xml system drop SMF boot config property store; no zyginit equivalent needed
/lib/svc/manifest/system/consadm.xml system needs-investigation Console administration (alternate console); determine if needed
/lib/svc/manifest/system/console-login.xml system already-converted services/hammerhead/console-login.toml; complex wrapper writes utmpx entry before exec of ttymon
/lib/svc/manifest/system/coreadm.xml system method-wrap coreadm -U to apply coreadm configuration; simple oneshot; inline coreadm -U directly in a TOML oneshot
/lib/svc/manifest/system/cron.xml system already-converted services/hammerhead/cron.toml; start.sh removes stale FIFO
/lib/svc/manifest/system/cryptosvc.xml system already-converted services/hammerhead/crypto.toml; cryptoadm oneshot
/lib/svc/manifest/system/device/devices-audio.xml system needs-investigation Audio device setup; determine if Hammerhead ships audio support
/lib/svc/manifest/system/device/devices-local.xml system already-converted services/hammerhead/devfs.toml; start.sh runs devfsadm + soconfig
/lib/svc/manifest/system/device/mpxio-upgrade.xml system drop MPXIO upgrade artifact
/lib/svc/manifest/system/dumpadm.xml system method-wrap svc-dumpadm applies crash dump configuration; oneshot; wrap or inline /usr/sbin/dumpadm -r /
/lib/svc/manifest/system/early-manifest-import.xml system drop SMF manifest import; exec=:true; no-op without SMF repo
/lib/svc/manifest/system/extended-accounting.xml system needs-investigation Process/task/flow accounting via acctadm; rare use case
/lib/svc/manifest/system/fcoe_initiator.xml system drop FCoE initiator; storage-specific; defer to zports
/lib/svc/manifest/system/fcoe_target.xml system drop FCoE target; storage-specific; defer to zports
/lib/svc/manifest/system/filesystem/autofs.xml system drop Automounter; not needed unless Hammerhead actively uses autofs
/lib/svc/manifest/system/filesystem/local-fs.xml system already-converted Consolidated into services/hammerhead/filesystem.toml
/lib/svc/manifest/system/filesystem/minimal-fs.xml system already-converted Consolidated into services/hammerhead/filesystem.toml; /var/run tmpfs mount is a follow-up
/lib/svc/manifest/system/filesystem/root-fs.xml system already-converted services/hammerhead/root-fs.toml; ZFS readonly assertion
/lib/svc/manifest/system/filesystem/usr-fs.xml system already-converted Consolidated into services/hammerhead/filesystem.toml
/lib/svc/manifest/system/filesystem/vscan.xml system drop Virus scan framework; defer to zports
/lib/svc/manifest/system/fm/notify-params.xml system drop SMF notification hooks (exec=:true); no zyginit equivalent
/lib/svc/manifest/system/fm/smtp-notify.xml system needs-investigation SMTP fault notification daemon; determine if Hammerhead ships this; foreground check: try smtp-notify without args
/lib/svc/manifest/system/fmd.xml system already-converted services/hammerhead/fmd.toml; foreground flag -f
/lib/svc/manifest/system/hostid.xml system needs-investigation Sets hardware hostid via svc-hostid script; verify if Hammerhead needs a hostid set at boot
/lib/svc/manifest/system/hotplug.xml system needs-investigation Hotplug daemon (hotplugd via svc-hotplug); determine if Hammerhead hardware needs it
/lib/svc/manifest/system/i2csimd.xml system drop I2C sensor daemon from a test harness (/opt/i2c-tests/); not part of base system
/lib/svc/manifest/system/ibsrp/target.xml system drop InfiniBand SRP target; hardware-specific; defer to zports
/lib/svc/manifest/system/identity.xml system already-converted services/hammerhead/identity.toml; sets hostname/nodename
/lib/svc/manifest/system/idmap.xml system needs-investigation Identity mapping daemon (idmapd); needed with SMB or Kerberos
/lib/svc/manifest/system/intrd.xml system foreground Interrupt distribution daemon; svc-intrd calls /usr/lib/intrd; check intrd source for -f or -d flag; method-wrap if no flag
/lib/svc/manifest/system/ipagent.xml system drop Triton/SmartOS IP agent; not part of base Hammerhead
/lib/svc/manifest/system/keymap.xml system method-wrap Keyboard map configuration; keymap script applies console keymap; simple oneshot via method-wrap or inline
/lib/svc/manifest/system/labeld.xml system drop Trusted Extensions label daemon; TX not shipped in Hammerhead
/lib/svc/manifest/system/logadm-upgrade.xml system drop Log rotation config upgrade artifact
/lib/svc/manifest/system/manifest-import.xml system drop SMF manifest import daemon
/lib/svc/manifest/system/name-service-cache.xml system needs-investigation nscd name service cache daemon; determine if Hammerhead needs nscd
/lib/svc/manifest/system/ndmp.xml system drop NDMP backup protocol; defer to zports
/lib/svc/manifest/system/pfexecd.xml system already-converted services/hammerhead/pfexecd.toml; direct exec /usr/lib/pfexecd
/lib/svc/manifest/system/picl.xml system drop PICL platform information daemon; Sun hardware-specific; not relevant for x86 virtual hardware
/lib/svc/manifest/system/pools.xml system needs-investigation Resource pools (FSSv2); determine if Hammerhead uses resource pools
/lib/svc/manifest/system/power.xml system already-converted services/hammerhead/powerd.toml; direct exec or method-wrap svc-power
/lib/svc/manifest/system/process-security.xml system drop Noop service (exec=:true); no functionality
/lib/svc/manifest/system/rbac.xml system method-wrap RBAC database initialization; svc-rbac start oneshot; method-wrap or inline /usr/sbin/svcadm alternative — check what svc-rbac actually does
/lib/svc/manifest/system/rcap.xml system needs-investigation Resource capping daemon (rcapd); determine if Hammerhead uses resource capping
/lib/svc/manifest/system/resource-mgmt.xml system needs-investigation Resource management configuration; companion to pools and rcap
/lib/svc/manifest/system/rmtmpfiles.xml system method-wrap Removes tmp files at boot (rmtmpfiles oneshot); simple method-wrap or inline /bin/rm -rf /tmp/* equivalent
/lib/svc/manifest/system/sar.xml system needs-investigation System activity reporter (sar/sa); determine if Hammerhead ships sar
/lib/svc/manifest/system/scheduler.xml system method-wrap Sets default scheduler class (svc-scheduler); oneshot; inspect svc-scheduler and inline if trivial
/lib/svc/manifest/system/stmf.xml system drop SCSI Target Mode Framework; storage-specific; defer to zports
/lib/svc/manifest/system/svc/global.xml system drop SMF global property store
/lib/svc/manifest/system/svc/restarter.xml system drop IS svc.startd; zyginit replaces it
/lib/svc/manifest/system/sysevent.xml system already-converted services/hammerhead/syseventd.toml; method-wrap svc-syseventd
/lib/svc/manifest/system/system-log.xml system already-converted services/hammerhead/syslogd.toml; foreground flag -d; start.sh touches /var/adm/messages first
/lib/svc/manifest/system/tsol-zones.xml system drop Trusted Extensions zones; TX not shipped in Hammerhead
/lib/svc/manifest/system/update-man-index.xml system drop Man page index update; not needed at every boot
/lib/svc/manifest/system/utmp.xml system already-converted services/hammerhead/utmpd.toml; method-wrap svc-utmpd
/lib/svc/manifest/system/vtdaemon.xml system method-wrap Virtual terminal multiplexer; vtdaemon script; determine if Hammerhead uses VTs; method-wrap if kept
/lib/svc/manifest/system/zones.xml system needs-investigation Zones boot/halt service; zyginit will need a zones oneshot for autoboot=true zones; see docs/DESIGN.md Zones section
/lib/svc/manifest/system/zonestat.xml system needs-investigation Zone statistics daemon (zonestatd); needed once zones are enabled

Catalog summary:

Classification Count
already-converted 19
drop 61
foreground 1
method-wrap 7
needs-investigation 40
Total 128

8. Format Reference Pointer

This section points to the authoritative TOML format documentation.

The zyginit service definition format — all valid fields, their types,
defaults, and semantics — is documented in docs/man/man5/zyginit.5.

The decision tree (Section 2) and catalog appendix (Section 7) use
field names from that reference. If a field name here appears to conflict
with what man zyginit.5 says, the man page is authoritative.

For runtime behavior, signal handling, and socket protocol, see
docs/man/man8/zyginit.8 and docs/man/man8/zygctl.8.


9. Glossary

Definitions of SMF concepts that appear in this document for readers
without an illumos background.

BE (Boot Environment): A ZFS dataset snapshot that represents a complete,
bootable OS image. Hammerhead supports multiple BEs; beadm (or direct
zpool set bootfs) selects which one the kernel boots.

Contract (process contract): A Hammerhead kernel mechanism that groups
related processes. When all processes in a contract exit, the kernel fires a
contract event. zyginit uses contracts to track service processes and detect
daemon exit without polling. See docs/DESIGN.md Contracts section.

FMRI (Fault Management Resource Identifier): SMF's naming scheme for
services, e.g., svc:/network/ssh:default. zyginit uses bare names (e.g.,
sshd) in TOML files instead.

libcontract: The Hammerhead userland library for managing process contracts.
zyginit links against it (-l contract). Not available on Linux.

libscf (Service Configuration Facility): The Hammerhead userland library
for reading and writing the SMF repository. Calls into svc.configd via a
door. A daemon that calls scf_handle_create() at startup requires configd
to be running.

Manifest: An XML file that describes an SMF service — its name, method
(start/stop command), dependencies, and properties. Stored in
/lib/svc/manifest/. zyginit replaces manifests with TOML files in
/etc/zyginit/.

Method (SMF method): The start, stop, or refresh command for an SMF
service, optionally implemented as a shell script in /lib/svc/method/.
The equivalent in zyginit is [exec] start and [exec] stop.

Profile (SMF profile): An XML file that selects which services are enabled
by default. zyginit replaces profiles with symlinks in /etc/zyginit/enabled.d/.

Repository: The SMF configuration database managed by svc.configd.
Stored in /etc/svc/repository.db (SQLite). zyginit has no database — service
state is in-memory only; configuration is in TOML files.

Restarter: In SMF, a service that manages other services. The master
restarter is svc.startd. zyginit is a single-process init that plays the
role of the restarter for all services.

soconfig: A Hammerhead utility (/sbin/soconfig) that loads the sockfs
protocol-to-module mapping from /etc/sock2path.d/. Must run before any
socket(AF_INET, ...) call succeeds. See Anti-patterns section 3.

uadmin: The Hammerhead system call for administrative operations including
halt, reboot, and poweroff. Must be called from a non-PID-1 process to avoid
the restart_init race. See Anti-patterns section 8.