From a28b396d9e7d7bdeb405f17307676655b8206098 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 19 May 2021 17:15:01 +0200 Subject: [PATCH] zipl: make IPL sections defined with BLS to inherit a target field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Javier Martinez Canillas Reviewed-by: Stefan Haberland Tested-by: Marc Hartmayer Signed-off-by: Jan Höppner --- zipl/src/scan.c | 253 ++++++++++++++++++++++++++++++------------------ 1 file changed, 157 insertions(+), 96 deletions(-) diff --git a/zipl/src/scan.c b/zipl/src/scan.c index 0248f1d2..17a9e46a 100644 --- a/zipl/src/scan.c +++ b/zipl/src/scan.c @@ -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. */