Skip to content

Commit

Permalink
s390x: add zVM Secure IPL support
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-dubrovskii committed Nov 17, 2023
1 parent 77416a8 commit 28f29c8
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ nav_order: 8

Major changes:

- install: Add zVM Secure IPL support

Minor changes:

Expand Down
5 changes: 5 additions & 0 deletions scripts/coreos-installer-service
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ if karg_bool coreos.inst.insecure; then
args+=("--insecure")
fi

# zVM Secure IPL support
if karg_bool coreos.inst.secure_ipl; then
args+=("--secure-ipl")
fi

# Always retry HTTP requests; we've got nothing to lose since we fail anyway.
args+=("--fetch-retries" "infinite")

Expand Down
7 changes: 7 additions & 0 deletions src/cmdline/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ pub struct InstallConfig {
#[serde(skip_serializing_if = "is_default")]
#[arg(long, value_name = "N", default_value_t, help_heading = ADVANCED)]
pub fetch_retries: FetchRetries,
/// Enable zVM Secure IPL
#[serde(skip_serializing_if = "is_default")]
#[arg(long, help_heading = ADVANCED)]
pub secure_ipl: bool,

// positional args
/// Destination device
Expand Down Expand Up @@ -361,6 +365,7 @@ mod test {
stream_base_url: Some(Url::parse("http://example.com/t").unwrap()),
preserve_on_error: true,
fetch_retries: FetchRetries::from_str("3").unwrap(),
secure_ipl: true,
dest_device: Some("u".into()),
};
let expected = vec![
Expand Down Expand Up @@ -412,6 +417,7 @@ mod test {
"--preserve-on-error",
"--fetch-retries",
"3",
"--secure-ipl",
"u",
];
assert_eq!(config.to_args().unwrap(), expected);
Expand Down Expand Up @@ -484,6 +490,7 @@ dest-device: u
stream_base_url: Some(Url::parse("http://example.com/t").unwrap()),
preserve_on_error: true,
fetch_retries: FetchRetries::from_str("3").unwrap(),
secure_ipl: false,
dest_device: Some("u".into()),
};
let config = InstallConfig::from_args(&["--config-file", f.path().to_str().unwrap()])
Expand Down
3 changes: 3 additions & 0 deletions src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ fn write_disk(
None,
)?;
s390x::chreipl(device)?;
if config.secure_ipl {
s390x::set_loaddev(device)?;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/s390x/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod zipl;

pub use dasd::{dasd_try_get_sector_size, image_copy_s390x, prepare_dasd};
pub use zipl::chreipl;
pub use zipl::set_loaddev;
pub use zipl::zipl;
mod eckd;
mod fba;
Expand Down
62 changes: 60 additions & 2 deletions src/s390x/zipl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

use crate::blockdev::Mount;
use crate::io::{visit_bls_entry, visit_bls_entry_options, Initrd, KargsEditor};
use crate::runcmd;
use crate::s390x::ZiplSecexMode;
use crate::util::cmd_output;
use anyhow::{anyhow, Context, Result};
use crate::{runcmd, runcmd_output};
use anyhow::{anyhow, bail, Context, Result};
use lazy_static::lazy_static;
use nix::mount::MsFlags;
use regex::Regex;
use std::fs::{copy, create_dir_all, read_dir, DirEntry, File};
Expand All @@ -33,6 +34,63 @@ pub fn chreipl<P: AsRef<Path>>(dev: P) -> Result<()> {
Ok(())
}

/// Sets zVM secure loaddev to `dev`.
pub fn set_loaddev<P: AsRef<Path>>(dev: P) -> Result<()> {
eprintln!("Setting LOADDEV");
let output = runcmd_output!(
"lszdev",
"-n",
"--columns",
"TYPE,ID",
"--by-node",
dev.as_ref()
)?;
let (devtype, id) = output
.trim()
.split_once(' ')
.with_context(|| format!("parsing {output}"))?;

let mut cmd = Command::new("vmcp");
cmd.arg("set").arg("loaddev");
match devtype {
"dasd-eckd" => {
lazy_static! {
static ref REGEX: Regex =
Regex::new(r#"[[:digit:]].[[:digit:]].([[:xdigit:]]+)"#).unwrap();
}
for cap in REGEX.captures_iter(id) {
cmd.arg("eckd").arg("dev").arg(&cap[1]);
}
}
"zfcp-lun" => {
lazy_static! {
static ref REGEX: Regex = Regex::new(
r#"[[:digit:]].[[:digit:]].([[:xdigit:]]+):0x([[:xdigit:]]+):0x([[:xdigit:]]+)"#
)
.unwrap();
}
// CP tool wants portname/lun to be splitted at 8th character:
// This fails: $ vmcp set loaddev dev 8007 portname 500507630400d1e3 lun 4001404c00000000
// HCPZPM002E Invalid operand - 500507630400D1E3
// This works: $ vmcp set loaddev dev 8007 portname 50050763 0400d1e3 lun 4001404c 00000000
for cap in REGEX.captures_iter(id) {
cmd.arg("dev")
.arg(&cap[1])
.arg("portname")
.arg(&cap[2][0..8])
.arg(&cap[2][8..])
.arg("lun")
.arg(&cap[3][0..8])
.arg(&cap[3][8..]);
}
}
_ => bail!("unsupported device: {} id: {}", devtype, id),
};
cmd.arg("secure");
cmd_output(&mut cmd)?;
Ok(())
}

fn secure_execution_is_enabled() -> Result<bool> {
let sysfs_flag = "/sys/firmware/uv/prot_virt_guest";
match File::open(sysfs_flag) {
Expand Down
5 changes: 5 additions & 0 deletions systemd/coreos-installer-generator
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@ if [ -n "$(karg coreos.inst.install_dev)" -o \
if ! karg_bool coreos.inst.skip_reboot; then
touch /run/coreos-installer-reboot
fi

# Create precondition for coreos-installer-reboot-loaddev.service if requested
if karg_bool coreos.inst.secure_ipl; then
touch /run/coreos-installer-loaddev
fi
fi
1 change: 1 addition & 0 deletions systemd/coreos-installer-post.target
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ AllowIsolate=yes
Requires=coreos-installer.target
Requires=coreos-installer-reboot.service
Requires=coreos-installer-noreboot.service
Requires=coreos-installer-reboot-loaddev.service
16 changes: 16 additions & 0 deletions systemd/coreos-installer-reboot-loaddev.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=Reboot from zVM LOADDEV after CoreOS Installer
ConditionVirtualization=zvm
ConditionPathExists=/run/coreos-installer-loaddev

Requires=coreos-installer.target
After=coreos-installer.target
After=coreos-installer-reboot.service
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly

[Service]
Type=simple
ExecStart=/usr/sbin/vmcp ipl loaddev
StandardOutput=kmsg+console
StandardError=kmsg+console

0 comments on commit 28f29c8

Please sign in to comment.