mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Some environments do not expose the /sys/firmware/reipl/*/clear attribute
(e.g. z/VM guests without "Load Normal" support). lsreipl currently tries to
read the attribute unconditionally for ECKD re-IPL and emits a confusing
"Could not read file .../clear" error when it is missing.
Re-IPL type: eckd
Device: 0.0.6d74
bootprog: 0
br_chr: auto
Bootparm: ""
Loadparm: ""
Could not read file /sys/firmware/reipl/eckd/clear: No such file or directory
clear: (null)
Secure boot: 0
Only print the "clear" field when the corresponding sysfs attribute is
present, avoiding the spurious error output.
Fixes: 7c24855ba1 ("ipl_tools: add support for list-directed IPL from ECKD DASD")
Reviewed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
245 lines
7.3 KiB
C
245 lines
7.3 KiB
C
/*
|
|
* ipl_tools - Linux for System z reipl and shutdown tools
|
|
*
|
|
* Command: lsreipl
|
|
*
|
|
* Copyright IBM Corp. 2008, 2017
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include "lib/util_path.h"
|
|
#include "lib/util_file.h"
|
|
#include "lib/util_libc.h"
|
|
|
|
#include "ipl_tools.h"
|
|
|
|
static struct {
|
|
int ipl_set; /* --ipl has been specified */
|
|
} l;
|
|
|
|
static const char *const usage_lsreipl =
|
|
"Usage: %s [OPTIONS]\n"
|
|
"\n"
|
|
"Show re-IPL or IPL settings.\n"
|
|
"\n"
|
|
"OPTIONS:\n"
|
|
" -i, --ipl Print the IPL setting\n"
|
|
" -h, --help Print this help, then exit\n"
|
|
" -v, --version Print version information, then exit\n";
|
|
|
|
static void __noreturn print_usage_lsreipl_exit(void)
|
|
{
|
|
printf(usage_lsreipl, g.prog_name);
|
|
exit(0);
|
|
}
|
|
|
|
static const char *get_ipl_banner(int show_ipl)
|
|
{
|
|
if (show_ipl)
|
|
return "IPL type:";
|
|
else
|
|
return "Re-IPL type:";
|
|
}
|
|
|
|
void print_nss(int show_ipl)
|
|
{
|
|
char *dir = show_ipl ? "ipl" : "reipl/nss";
|
|
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
|
|
|
|
printf("%-12s nss\n", get_ipl_banner(show_ipl));
|
|
print_fw_str("Name: %s\n", dir, "name");
|
|
if (access(path_bootparms, R_OK) == 0)
|
|
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
|
free(path_bootparms);
|
|
}
|
|
|
|
void print_fcp(int show_ipl, int dump)
|
|
{
|
|
char *dir = show_ipl ? "ipl" : "reipl/fcp";
|
|
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
|
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/fcp/clear");
|
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
|
char *loadparm;
|
|
|
|
if (dump)
|
|
printf("%-12s fcp_dump\n", get_ipl_banner(show_ipl));
|
|
else
|
|
printf("%-12s fcp\n", get_ipl_banner(show_ipl));
|
|
|
|
print_fw_str("WWPN: %s\n", dir, "wwpn");
|
|
print_fw_str("LUN: %s\n", dir, "lun");
|
|
print_fw_str("Device: %s\n", dir, "device");
|
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
|
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
|
if (access(path_loadparm, R_OK) == 0) {
|
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
|
util_strstrip(loadparm);
|
|
printf("Loadparm: \"%s\"\n", loadparm);
|
|
free(loadparm);
|
|
}
|
|
if (access(path_bootparms, R_OK) == 0)
|
|
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
|
print_fw_str("clear: %s\n", dir, "clear");
|
|
if (access(path_secure_boot, R_OK) == 0)
|
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
|
free(path_bootparms);
|
|
free(path_loadparm);
|
|
free(path_reipl_clear);
|
|
free(path_secure_boot);
|
|
}
|
|
|
|
void print_nvme(int show_ipl, int dump)
|
|
{
|
|
char *dir = show_ipl ? "ipl" : "reipl/nvme";
|
|
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
|
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/nvme/clear");
|
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
|
char *loadparm;
|
|
|
|
if (dump)
|
|
printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
|
|
else
|
|
printf("%-12s nvme\n", get_ipl_banner(show_ipl));
|
|
|
|
print_fw_str("FID: %s\n", dir, "fid");
|
|
print_fw_str("NSID: %s\n", dir, "nsid");
|
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
|
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
|
if (access(path_loadparm, R_OK) == 0) {
|
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
|
util_strstrip(loadparm);
|
|
printf("Loadparm: \"%s\"\n", loadparm);
|
|
free(loadparm);
|
|
}
|
|
if (access(path_bootparms, R_OK) == 0)
|
|
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
|
print_fw_str("clear: %s\n", dir, "clear");
|
|
if (access(path_secure_boot, R_OK) == 0)
|
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
|
free(path_bootparms);
|
|
free(path_loadparm);
|
|
free(path_reipl_clear);
|
|
free(path_secure_boot);
|
|
}
|
|
|
|
void print_ccw(int show_ipl)
|
|
{
|
|
char *dir = show_ipl ? "ipl" : "reipl/ccw";
|
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
|
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
|
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/ccw/clear");
|
|
char *loadparm;
|
|
|
|
printf("%-12s ccw\n", get_ipl_banner(show_ipl));
|
|
print_fw_str("Device: %s\n", dir, "device");
|
|
if (access(path_loadparm, R_OK) == 0) {
|
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
|
util_strstrip(loadparm);
|
|
printf("Loadparm: \"%s\"\n", loadparm);
|
|
free(loadparm);
|
|
}
|
|
if (access(path_bootparms, R_OK) == 0)
|
|
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
|
print_fw_str("clear: %s\n", dir, "clear");
|
|
free(path_loadparm);
|
|
free(path_bootparms);
|
|
free(path_reipl_clear);
|
|
}
|
|
|
|
void print_eckd(int show_ipl, const char *name)
|
|
{
|
|
char *dir = show_ipl ? "ipl" : "reipl/eckd";
|
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/eckd/clear");
|
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
|
char *loadparm;
|
|
|
|
printf("%-12s %s\n", get_ipl_banner(show_ipl), name);
|
|
|
|
print_fw_str("Device: %s\n", dir, "device");
|
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
|
print_fw_str("br_chr: %s\n", dir, "br_chr");
|
|
print_fw_str("Bootparm: \"%s\"\n", dir, "scp_data");
|
|
if (access(path_loadparm, R_OK) == 0) {
|
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
|
util_strstrip(loadparm);
|
|
printf("Loadparm: \"%s\"\n", loadparm);
|
|
free(loadparm);
|
|
}
|
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
|
print_fw_str("clear: %s\n", dir, "clear");
|
|
if (access(path_secure_boot, R_OK) == 0)
|
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
|
free(path_loadparm);
|
|
free(path_secure_boot);
|
|
}
|
|
|
|
static void parse_lsreipl_options(int argc, char *argv[])
|
|
{
|
|
int opt, idx;
|
|
const struct option long_opts[] = {
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "ipl", no_argument, NULL, 'i' },
|
|
{ "version", no_argument, NULL, 'v' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
while ((opt = getopt_long(argc, argv, "hvi", long_opts, &idx)) != -1) {
|
|
switch (opt) {
|
|
case 'i':
|
|
l.ipl_set = 1;
|
|
break;
|
|
case 'h':
|
|
print_usage_lsreipl_exit();
|
|
case 'v':
|
|
print_version_exit();
|
|
default:
|
|
print_help_hint_exit();
|
|
}
|
|
}
|
|
/* don't run with too many arguments */
|
|
if (optind != argc)
|
|
ERR_EXIT("Invalid positional parameter \"%s\" specified",
|
|
argv[optind]);
|
|
}
|
|
|
|
void cmd_lsreipl(int argc, char *argv[])
|
|
{
|
|
char *reipl_type_str;
|
|
|
|
parse_lsreipl_options(argc, argv);
|
|
|
|
if (l.ipl_set)
|
|
reipl_type_str = read_fw_str("ipl/ipl_type");
|
|
else
|
|
reipl_type_str = read_fw_str("reipl/reipl_type");
|
|
|
|
if (strcmp(reipl_type_str, "fcp") == 0)
|
|
print_fcp(l.ipl_set, 0);
|
|
else if (strcmp(reipl_type_str, "fcp_dump") == 0)
|
|
print_fcp(l.ipl_set, 1);
|
|
else if (strcmp(reipl_type_str, "nvme") == 0)
|
|
print_nvme(l.ipl_set, 0);
|
|
else if (strcmp(reipl_type_str, "nvme_dump") == 0)
|
|
print_nvme(l.ipl_set, 1);
|
|
else if (strcmp(reipl_type_str, "ccw") == 0)
|
|
print_ccw(l.ipl_set);
|
|
else if (strcmp(reipl_type_str, "eckd") == 0 ||
|
|
strcmp(reipl_type_str, "eckd_dump") == 0)
|
|
print_eckd(l.ipl_set, reipl_type_str);
|
|
else if (strcmp(reipl_type_str, "nss") == 0)
|
|
print_nss(l.ipl_set);
|
|
else
|
|
printf("%s: %s (unknown)\n", get_ipl_banner(l.ipl_set),
|
|
reipl_type_str);
|
|
free(reipl_type_str);
|
|
exit(0);
|
|
}
|