use std::ffi::CStr;
use std::io;
use crate::{classify_errno, KexecError};
const SYS_KEXEC_FILE_LOAD: libc::c_long = libc::SYS_kexec_file_load;
const KEXEC_FILE_DEFAULT_FLAGS: libc::c_ulong = 0;
const KEXEC_FILE_NO_INITRAMFS: libc::c_ulong = 0x4;
pub(crate) fn kexec_file_load(
kernel_fd: libc::c_int,
initrd_fd: Option<libc::c_int>,
cmdline: &CStr,
) -> Result<(), KexecError> {
let (initrd, flags) = match initrd_fd {
Some(fd) => (fd, KEXEC_FILE_DEFAULT_FLAGS),
None => (-1, KEXEC_FILE_NO_INITRAMFS),
};
let cmdline_len = cmdline.to_bytes_with_nul().len();
#[allow(unsafe_code)]
let rc = unsafe {
libc::syscall(
SYS_KEXEC_FILE_LOAD,
libc::c_long::from(kernel_fd),
libc::c_long::from(initrd),
cmdline_len as libc::c_ulong,
cmdline.as_ptr(),
flags,
)
};
if rc == 0 {
Ok(())
} else {
let errno = io::Error::last_os_error().raw_os_error().unwrap_or(0);
Err(classify_errno(errno))
}
}
pub(crate) fn reboot_kexec() -> Result<(), KexecError> {
#[allow(unsafe_code)]
let rc = unsafe { libc::reboot(libc::LINUX_REBOOT_CMD_KEXEC) };
if rc < 0 {
Err(KexecError::Io(io::Error::last_os_error()))
} else {
Ok(())
}
}