--- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -1006,6 +1006,12 @@ for (i=0; i < job->data.menu.num; i++) { switch (job->data.menu.entry[i].id) { case job_ipl: + if (job->data.menu.entry[i].data.ipl.ignore) { + printf("Ignore #%d: IPL section '%s'\n", + job->data.menu.entry[i].pos, + job->data.menu.entry[i].name); + break; + } printf("Adding #%d: IPL section '%s'%s", job->data.menu.entry[i].pos, job->data.menu.entry[i].name, --- a/zipl/src/scan.c +++ b/zipl/src/scan.c @@ -47,45 +47,45 @@ * ult to tofs e mete file isk ent et pt out ultm dump * rs enu * - * targ targ targ targ targ defa kdum secu - * etba etty etge etbl etof ulta p re + * targ targ targ targ targ defa kdum secu opti + * etba etty etge etbl etof ulta p re onal * se pe omet ocks fset uto * ry ize */ /* default auto */ {opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv, - opt, opt, opt, opt, opt, opt, inv, opt}, + opt, opt, opt, opt, opt, opt, inv, opt, inv}, /* default menu */ {inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, - inv, inv, inv, inv, inv, inv, inv, opt}, + inv, inv, inv, inv, inv, inv, inv, opt, inv}, /* default section */ {req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, - inv, inv, inv, inv, inv, inv, inv, opt}, + inv, inv, inv, inv, inv, inv, inv, opt, inv}, /* ipl */ {inv, inv, inv, req, opt, opt, opt, inv, req, inv, inv, inv, inv, inv, - opt, opt, opt, opt, opt, inv, opt, opt}, + opt, opt, opt, opt, opt, inv, opt, opt, opt}, /* segment load */ {inv, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, - inv, inv, inv, inv, inv, inv, inv, inv}, + inv, inv, inv, inv, inv, inv, inv, inv, inv}, /* part dump */ {inv, req, inv, inv, inv, inv, inv, inv, opt, inv, inv, inv, inv, inv, - inv, inv, inv, inv, inv, inv, inv, inv}, + inv, inv, inv, inv, inv, inv, inv, inv, inv}, /* fs dump */ {inv, inv, req, inv, opt, opt, inv, inv, req, inv, inv, inv, inv, inv, - inv, inv, inv, inv, inv, inv, inv, inv}, + inv, inv, inv, inv, inv, inv, inv, inv, inv}, /* ipl tape */ {inv, inv, inv, req, opt, opt, opt, inv, inv, inv, inv, inv, req, inv, - inv, inv, inv, inv, inv, inv, inv, inv}, + inv, inv, inv, inv, inv, inv, inv, inv, inv}, /* multi volume dump */ {inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, - inv, inv, inv, inv, inv, inv, inv, inv} + inv, inv, inv, inv, inv, inv, inv, inv, inv} }; /* Determines which keyword may be present in a menu section */ enum scan_key_state scan_menu_key_table[SCAN_KEYWORD_NUM] = { /* menu section */ opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv, - opt, opt, opt, opt, opt, inv, inv, opt + opt, opt, opt, opt, opt, inv, inv, opt, inv }; /* Mapping of keyword IDs to strings */ @@ -114,6 +114,7 @@ { "tape", scan_keyword_tape}, { "kdump", scan_keyword_kdump}, { "secure", scan_keyword_secure}, + { "optional", scan_keyword_optional}, }; /* List of keywords that are used without an assignment */ --- a/zipl/include/job.h +++ b/zipl/include/job.h @@ -13,6 +13,8 @@ #ifndef JOB_H #define JOB_H +#include + #include "disk.h" #include "zipl.h" @@ -47,6 +49,8 @@ address_t parm_addr; address_t ramdisk_addr; int is_kdump; + bool optional; + bool ignore; }; struct job_segment_data { --- a/zipl/src/job.c +++ b/zipl/src/job.c @@ -828,14 +828,20 @@ static int -check_job_ipl_data(struct job_ipl_data *ipl, char* name) +check_job_ipl_data(struct job_ipl_data *ipl, char* name, bool may_ignore) { int rc; if (ipl->image != NULL) { rc = misc_check_readable_file(ipl->image); if (rc) { - if (name == NULL) { + if (may_ignore && ipl->optional) { + printf("Ignore section '%s': Image file '%s'\n", + name, ipl->image); + error_clear_reason(); + ipl->ignore = true; + return 0; + } else if (name == NULL) { error_text("Image file '%s'", ipl->image); } else { error_text("Image file '%s' in section '%s'", @@ -847,7 +853,13 @@ if (ipl->ramdisk != NULL) { rc = misc_check_readable_file(ipl->ramdisk); if (rc) { - if (name == NULL) { + if (ipl->optional) { + printf("Ignore section '%s': Ramdisc file '%s'\n", + name, ipl->ramdisk); + error_clear_reason(); + ipl->ignore = true; + return 0; + } else if (name == NULL) { error_text("Ramdisk file '%s'", ipl->ramdisk); } else { error_text("Ramdisk file '%s' in section '%s'", @@ -944,9 +956,13 @@ switch (menu->entry[i].id) { case job_ipl: rc = check_job_ipl_data(&menu->entry[i].data.ipl, - menu->entry[i].name); + menu->entry[i].name, true); if (rc) return rc; + if (menu->default_pos == i + 1 && menu->entry[i].data.ipl.ignore) { + error_text("Can't ignore default entry."); + return -1; + } break; case job_print_usage: case job_print_version: @@ -1110,7 +1126,7 @@ rc = 0; break; case job_ipl: - rc = check_job_ipl_data(&job->data.ipl, job->name); + rc = check_job_ipl_data(&job->data.ipl, job->name, false); break; case job_menu: rc = check_job_menu_data(&job->data.menu); @@ -1402,6 +1418,8 @@ if (rc) return rc; } + job->data.ipl.optional = data[(int) scan_keyword_optional]; + job->data.ipl.ignore = false; break; case section_ipl_tape: /* Tape IPL job */ --- a/zipl/man/zipl.conf.5.in +++ b/zipl/man/zipl.conf.5.in @@ -447,6 +447,22 @@ .BR 'segment' . .PP +.B optional += +.IR 0 / 1 +(configuration only) +.IP +.B Configuration section: +.br +If this option is set to 1 the configuration section will only be included in +the boot menu if the referenced image file exists, and running +.BR zipl +will not fail if the image file is missing. + +The default value for +.B 'optional' +is 0. + .B parameters = .I kernel\-parameters --- a/zipl/include/scan.h +++ b/zipl/include/scan.h @@ -16,7 +16,7 @@ #define SCAN_SECTION_NUM 9 -#define SCAN_KEYWORD_NUM 22 +#define SCAN_KEYWORD_NUM 23 #define SCAN_KEYWORD_ONLY_NUM 1 #define SCAN_AUTOMENU_NAME "zipl-automatic-menu" @@ -52,6 +52,7 @@ scan_keyword_defaultauto = 19, scan_keyword_kdump = 20, scan_keyword_secure = 21, + scan_keyword_optional = 22, }; enum scan_section_type {