zipl: make IPL sections defined with BLS to inherit a target field

The target field is required for IPL sections, but the ones populated from
BLS snippets did not have this field. This was only working when using BLS
snippets because IPL sections inherit the target field with "defaultauto".

But that's not the case when using a menu, for example the following zipl
configuration will fail if it's used along with BLS defined IPL sections:
fail when running the zipl tool:

  [defaultboot]
  defaultmenu = menu1

  :menu1
  target = /boot
  1 = linux
  2 = test
  default = 1
  prompt = 1
  timeout = 0

Because "linux" and "test" will be defined using BLS snippets and these
don't have an option to define target fields. Let's make these to always
inherit a target field, either from the [defaultboot] section or a menu
section if there's a defaultmenu defined.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/111
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/113
[hoeppner@linux.ibm.com: Fixed a couple of style issues]
Reported-by: Renaud Métrich <rmetrich@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Javier Martinez Canillas
2021-05-19 17:15:01 +02:00
committed by Jan Höppner
parent 0012eaf68e
commit a28b396d9e

View File

@@ -795,102 +795,6 @@ static int sort_bls_fields(struct misc_file_buffer *file, char *filename)
return 0;
}
int
scan_bls(const char* blsdir, struct scan_token** token, int scan_size)
{
int count = 0;
int size, remaining = 0, n, current, rc = -1;
struct scan_token* buffer;
struct scan_token* array = *token;
struct dirent** bls_entries;
struct misc_file_buffer file;
struct stat sb;
char filename[PATH_MAX];
if (!(stat(blsdir, &sb) == 0 && S_ISDIR(sb.st_mode)))
return 0;
n = scandir(blsdir, &bls_entries, bls_filter, bls_sort);
if (n <= 0)
return n;
while (array[count].id != 0)
count++;
remaining = scan_size - count;
/* The array of scanned tokens is allocated when the zipl config file is
* parsed. Its size is a multiple of INITIAL_ARRAY_LENGTH so it may have
* enough space to scan all the tokens that are defined in the BLS files.
* Calculate if is enough assuming that a BLS fragment can contain up to
* 4 tokens: a section heading and 3 keywords (image, ramdisk, parameter).
*/
if (remaining < n * 4) {
size = scan_size - remaining + (n * 4);
buffer = (struct scan_token *)misc_malloc(size * sizeof(struct scan_token));
if (!buffer)
goto err;
memset(buffer, 0, size * sizeof(struct scan_token));
memcpy(buffer, array, count * sizeof(struct scan_token));
} else {
buffer = array;
}
while (n--) {
sprintf(filename, "%s/%s", blsdir, bls_entries[n]->d_name);
printf("Using BLS config file '%s'\n", filename);
rc = misc_get_file_buffer(filename, &file);
if (rc)
goto err;
rc = sort_bls_fields(&file, filename);
if (rc)
goto err;
while ((size_t)file.pos < file.length) {
current = misc_get_char(&file, 0);
switch (current) {
case '#':
file.pos++;
skip_line(&file);
break;
case EOF:
break;
case '\t':
case '\n':
case '\0':
case ' ':
file.pos++;
break;
default:
rc = scan_bls_field(&file, buffer, &count);
if (rc) {
error_reason("Incorrect BLS field in "
"config file %s\n", filename);
goto err;
}
break;
}
}
misc_free_file_buffer(&file);
free(bls_entries[n]);
}
*token = buffer;
rc = 0;
err:
if (n > 0) {
do {
free(bls_entries[n]);
} while (n-- > 0);
}
free(bls_entries);
return rc;
}
/* Search scanned tokens SCAN for a section/menu heading (according to
* TYPE) of the given NAME, beginning at token OFFSET. Return the index of
@@ -1359,6 +1263,163 @@ scan_get_section_keywords(struct scan_token* scan, int* index, char* name,
}
/*
* Get the default target defined either in the defaultboot section or the
* menu section for the defaultmenu if there is a default menu defined.
*/
static char *scan_get_default_target(struct scan_token *scan)
{
int keyword_line[SCAN_KEYWORD_NUM];
char *keyword[SCAN_KEYWORD_NUM];
int num_line[BOOT_MENU_ENTRIES];
char *num[BOOT_MENU_ENTRIES];
int i, j, rc;
/* Find the defaultboot section */
i = scan_find_section(scan, DEFAULTBOOT_SECTION,
scan_id_section_heading, 0);
if (i < 0) {
error_reason("No '%s' section found and no section specified on command line",
DEFAULTBOOT_SECTION);
return NULL;
}
/* Get keyword and number data */
rc = scan_get_section_keywords(scan, &i, DEFAULTBOOT_SECTION, keyword,
keyword_line, NULL, NULL);
if (rc) {
error_reason("Could not get keywords for '%s' section",
DEFAULTBOOT_SECTION);
return NULL;
}
/* Check if a defaultmenu is set */
i = (int) scan_keyword_defaultmenu;
if (keyword[i]) {
j = scan_find_section(scan, keyword[i],
scan_id_menu_heading, 0);
if (j < 0) {
error_reason("No '%s' section found", keyword[i]);
return NULL;
}
/* Get keyword and number data */
rc = scan_get_section_keywords(scan, &j, keyword[i], keyword,
keyword_line, num, num_line);
if (rc) {
error_reason("Could not get keywords for '%s' section",
keyword[i]);
return NULL;
}
}
return keyword[(int) scan_keyword_target];
}
#define BLS_TOKEN_MAX 5 /* section heading, image, ramdisk, parameter, target */
int scan_bls(const char *blsdir, struct scan_token **token, int scan_size)
{
int size, remaining = 0, n, current, rc = -1, count = 0;
struct scan_token *array = *token;
struct misc_file_buffer file;
struct dirent **bls_entries;
struct scan_token *buffer;
char filename[PATH_MAX];
char *target = NULL;
struct stat sb;
if (!(stat(blsdir, &sb) == 0 && S_ISDIR(sb.st_mode)))
return 0;
n = scandir(blsdir, &bls_entries, bls_filter, bls_sort);
if (n <= 0)
return n;
while (array[count].id != 0)
count++;
remaining = scan_size - count;
/* The array of scanned tokens is allocated when the zipl config file is
* parsed. Its size is a multiple of INITIAL_ARRAY_LENGTH so it may have
* enough space to scan all the tokens that are defined in the BLS files.
* Calculate if is enough assuming that a BLS fragment can contain up to
* BLS_TOKEN_MAX.
*/
if (remaining < n * BLS_TOKEN_MAX) {
size = scan_size - remaining + (n * BLS_TOKEN_MAX);
buffer = (struct scan_token *)misc_malloc(size * sizeof(struct scan_token));
if (!buffer)
goto err;
memset(buffer, 0, size * sizeof(struct scan_token));
memcpy(buffer, array, count * sizeof(struct scan_token));
} else {
buffer = array;
}
target = scan_get_default_target(array);
while (n--) {
sprintf(filename, "%s/%s", blsdir, bls_entries[n]->d_name);
printf("Using BLS config file '%s'\n", filename);
rc = misc_get_file_buffer(filename, &file);
if (rc)
goto err;
rc = sort_bls_fields(&file, filename);
if (rc)
goto err;
while ((size_t)file.pos < file.length) {
current = misc_get_char(&file, 0);
switch (current) {
case '#':
file.pos++;
skip_line(&file);
break;
case EOF:
break;
case '\t':
case '\n':
case '\0':
case ' ':
file.pos++;
break;
default:
rc = scan_bls_field(&file, buffer, &count);
if (rc) {
error_reason("Incorrect BLS field in config file %s\n",
filename);
goto err;
}
break;
}
}
if (target != NULL)
scan_append_keyword_assignment(buffer, &count,
scan_keyword_target,
target);
misc_free_file_buffer(&file);
free(bls_entries[n]);
}
*token = buffer;
rc = 0;
err:
if (n > 0) {
do {
free(bls_entries[n]);
} while (n-- > 0);
}
free(bls_entries);
return rc;
}
/* Check section at INDEX for compliance with config file rules. Upon success,
* return zero and advance INDEX to point to the end of the section. Return
* non-zero otherwise. */