iucode_tool: do not scan-system while parsing

Instead of processing -s and -S/--scan-system while parsing, queue all
filters so that we can call scan_system_processors() later.  This was
the only complex operation that was being carried out while parsing the
command line.

This change ensures that global options such as -q and -v, that are not
supposed to be sensitive to their position in the command line, will
work as expected.
parent ab9e562d
......@@ -177,12 +177,15 @@ struct microcode_iterator_data {
static struct microcode_iterator_data microcode_iterator_data;
/* Filter masks */
#define IUCODE_FILTERMASK_SCANCPUS 0xffffffffU
struct microcode_filter_entry {
struct microcode_filter_entry *next;
uint32_t cpuid; /* exact match */
uint32_t pfm; /* common bits set match */
int invert;
};
static struct microcode_filter_entry *uc_filter_queue = NULL;
static struct microcode_filter_entry *uc_filter_queue_tail = NULL;
static struct microcode_filter_entry *uc_filter_list = NULL;
static int filter_list_allow = 1;
......@@ -1898,7 +1901,6 @@ static int is_in_date_range(const struct intel_ucode_metadata * const m)
return !!((d > datefilter_min) && (d < datefilter_max));
}
static void free_filter_list(struct microcode_filter_entry *f) __attribute__((unused));
static void free_filter_list(struct microcode_filter_entry *f)
{
static struct microcode_filter_entry *p;
......@@ -1930,6 +1932,9 @@ static int add_filter_to_list(uint32_t cpuid, uint32_t pf_mask, int invert,
assert(base);
if (!cpuid || cpuid == IUCODE_FILTERMASK_SCANCPUS)
return EINVAL;
if (!pf_mask)
pf_mask = PFMASK_MATCH_ANY;
......@@ -2799,6 +2804,65 @@ static int scan_system_processors(void)
return (rc > 0) ? rc : 0;
}
static int cmdline_queue_ucode_filter(uint32_t cpuid, uint32_t pf_mask, int invert)
{
struct microcode_filter_entry *n;
n = malloc(sizeof(struct microcode_filter_entry));
if (!n)
return ENOMEM;
n->cpuid = cpuid;
n->pfm = pf_mask;
n->invert = invert;
n->next = NULL;
if (uc_filter_queue_tail) {
uc_filter_queue_tail->next = n;
} else {
uc_filter_queue = n;
}
uc_filter_queue_tail = n;
return 0;
}
static int process_ucode_filter_queue(void)
{
struct microcode_filter_entry *p = uc_filter_queue;
int rc = 0;
while(p && !rc) {
if (p->cpuid != IUCODE_FILTERMASK_SCANCPUS) {
rc = add_filter_to_list(p->cpuid, p->pfm, p->invert, &uc_filter_list);
if (rc == EEXIST)
rc = 0;
} else {
rc = scan_system_processors();
}
p = p->next;
}
uc_filter_queue_tail = NULL;
free_filter_list(uc_filter_queue);
uc_filter_queue = NULL;
switch(rc) {
case 0:
return 0;
case ENOMEM:
print_err("Cannot add filter entry: out of memory");
break;
case EINVAL:
print_err("Internal error while processing filter list");
break;
}
return 1;
}
/* Command line processing */
static const char program_version[] =
......@@ -3023,7 +3087,7 @@ static void free_filename_list(void)
}
/* -s ! | [!]cpuid[,pf_mask] */
static int add_ucode_filter(const char *arg)
static int cmdline_parse_ucode_filter(const char *arg)
{
char *p;
uint32_t acpuid, amask;
......@@ -3072,7 +3136,7 @@ static int add_ucode_filter(const char *arg)
if (!invert)
filter_list_allow = 0;
return add_filter_to_list(acpuid, amask, invert, &uc_filter_list);
return cmdline_queue_ucode_filter(acpuid, amask, invert);
}
/* YYYY-MM-DD */
......@@ -3286,17 +3350,16 @@ static error_t cmdline_do_parse_arg(int key, char *arg,
break;
case 's':
rc = add_ucode_filter(arg);
rc = cmdline_parse_ucode_filter(arg);
switch (rc) {
case 0:
case EEXIST:
break; /* success */
case EINVAL:
argp_error(state, "invalid filter: '%s'", arg);
break; /* not reached */
default:
argp_failure(state, EXIT_SWFAILURE, rc,
"could not add filter '%s'", arg);
"could not queue filter '%s'", arg);
}
command_line_actions |= IUCODE_F_UCSELECT;
break;
......@@ -3304,11 +3367,10 @@ static error_t cmdline_do_parse_arg(int key, char *arg,
if (command_line_actions & IUCODE_DO_SELPROC)
argp_error(state,
"--scan-system option can be specified only once");
if (scan_system_processors()) {
argp_failure(state, EXIT_SWFAILURE, 0,
"fatal failure while scanning for system processors");
}
rc = cmdline_queue_ucode_filter(IUCODE_FILTERMASK_SCANCPUS, 0, 0);
if (rc)
argp_failure(state, EXIT_SWFAILURE, rc,
"could not queue --scan-system action");
command_line_actions |= IUCODE_DO_SELPROC | IUCODE_F_UCSELECT;
break;
......@@ -3384,6 +3446,11 @@ int main(int argc, char *argv[])
goto do_nothing;
}
if (process_ucode_filter_queue()) {
rc = EXIT_SWFAILURE;
goto err_exit;
}
if (command_line_actions & IUCODE_DO_LOADFILE) {
struct filename_list *fn = input_files;
while (fn && next_bundle_id) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment