-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable JSON output for efibootmgr. This provides an interface for third party tools so they do not need to scrap the existing textual output. This feature is optional and is enabled by using JSON=1 when compiling: make ... JSON=1 Add parameter '-j'/--json' to use JSON output. If efibootmgr is not built with JSON output support it will print out this instead: "JSON support is not built-in" This feature adds a new (optional) dependency with libjansson. Signed-off-by: Jose M. Guisado <[email protected]>
- Loading branch information
Showing
6 changed files
with
218 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include <stdio.h> | ||
|
||
#include "list.h" | ||
|
||
void __print_json(list_t *entry_list, ebm_mode mode, | ||
char **prefices, char **order_name); | ||
|
||
#ifndef JSON | ||
#define __unused __attribute__((unused)) | ||
void print_json(list_t __unused *entry_list, ebm_mode __unused mode, | ||
char __unused **prefices, char __unused **order_name) | ||
{ | ||
printf("JSON support is not built-in\n"); | ||
} | ||
#else | ||
static inline void print_json(list_t *entry_list, ebm_mode mode, | ||
char **prefices, char **order_name) | ||
{ | ||
__print_json(entry_list, mode, prefices, order_name); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include <efiboot.h> | ||
#include <jansson.h> | ||
|
||
#include "parse_loader_data.h" | ||
#include "efibootmgr.h" | ||
#include "error.h" | ||
#include "json.h" | ||
|
||
static void | ||
json_fill_bootnext(json_t *root) | ||
{ | ||
char s[5] = {}; | ||
json_t *value; | ||
int num; | ||
|
||
num = read_u16("BootNext"); | ||
cond_warning(opts.verbose >= 2 && num < 0, | ||
"Could not read variable 'BootNext'"); | ||
if (num >= 0) { | ||
snprintf(s, sizeof(s), "%04X", num); | ||
value = json_string(s); | ||
json_object_set_new(root, "BootNext", value); | ||
} | ||
} | ||
|
||
static void | ||
json_fill_bootcurrent(json_t *root) | ||
{ | ||
char s[5] = {}; | ||
json_t *value; | ||
int num; | ||
|
||
num = read_u16("BootCurrent"); | ||
cond_warning(opts.verbose >= 2 && num < 0, | ||
"Could not read variable 'BootCurrent'"); | ||
if (num >= 0) { | ||
snprintf(s, sizeof(s), "%04X", num); | ||
value = json_string(s); | ||
json_object_set_new(root, "BootCurrent", value); | ||
} | ||
} | ||
|
||
static void | ||
json_fill_timeout(json_t *root) | ||
{ | ||
json_t *value; | ||
int num; | ||
|
||
num = read_u16("Timeout"); | ||
cond_warning(opts.verbose >= 2 && num < 0, | ||
"Could not read variable 'Timeout'"); | ||
if (num >= 0) { | ||
value = json_integer(num); | ||
json_object_set_new(root, "Timeout", value); | ||
} | ||
} | ||
|
||
static json_t * | ||
bootorder_json_array(uint16_t *order, int length) | ||
{ | ||
json_t *value, *array; | ||
char s[5] = {}; | ||
int i; | ||
|
||
array = json_array(); | ||
if (!array) | ||
return NULL; | ||
|
||
for (i = 0; i < length; i++) { | ||
snprintf(s, sizeof(s), "%04X", order[i]); | ||
value = json_string(s); | ||
json_array_append_new(array, value); | ||
} | ||
|
||
return array; | ||
} | ||
|
||
static void | ||
json_fill_order(json_t *root, const char *name) | ||
{ | ||
var_entry_t *order = NULL; | ||
uint16_t *data; | ||
json_t *array; | ||
int rc; | ||
|
||
rc = read_order(name, &order); | ||
cond_warning(opts.verbose >= 2 && rc < 0, | ||
"Could not read variable '%s'", name); | ||
|
||
if (rc < 0) { | ||
if (errno == ENOENT) { | ||
if (!strcmp(name, "BootOrder")) | ||
printf("No BootOrder is set; firmware will attempt recovery\n"); | ||
else | ||
printf("No %s is set\n", name); | ||
} else | ||
perror("json_fill_order()"); | ||
return; | ||
} | ||
|
||
data = (uint16_t *)order->data; | ||
if (order->data_size) { | ||
array = bootorder_json_array(data, | ||
order->data_size / sizeof(uint16_t)); | ||
if (array != NULL) | ||
json_object_set_new(root, name, array); | ||
free(order->data); | ||
} | ||
free(order); | ||
} | ||
|
||
static void | ||
json_fill_vars(json_t *root, const char *prefix, list_t *entry_list) | ||
{ | ||
const unsigned char *description; | ||
json_t *boot_json, *vars_json; | ||
efi_load_option *load_option; | ||
char name[16] = {'\0'}; | ||
var_entry_t *boot; | ||
list_t *pos; | ||
int active; | ||
|
||
vars_json = json_array(); | ||
if (!vars_json) | ||
return; | ||
|
||
list_for_each(pos, entry_list) { | ||
boot_json = json_object(); | ||
boot = list_entry(pos, var_entry_t, list); | ||
load_option = (efi_load_option *)boot->data; | ||
description = efi_loadopt_desc(load_option, boot->data_size); | ||
if (boot->name) | ||
json_object_set_new(boot_json, "name", json_string(boot->name)); | ||
else { | ||
snprintf(name, sizeof(name), "%s%04X", prefix, boot->num); | ||
json_object_set_new(boot_json, "name", json_string(boot->name)); | ||
} | ||
|
||
active = efi_loadopt_attrs(load_option) & LOAD_OPTION_ACTIVE ? 1 : 0; | ||
json_object_set_new(boot_json, "active", json_boolean(active)); | ||
json_object_set_new(boot_json, "description", | ||
json_string((char *)description)); | ||
json_array_append_new(vars_json, boot_json); | ||
} | ||
|
||
json_object_set_new(root, "vars", vars_json); | ||
} | ||
|
||
void | ||
__print_json(list_t *entry_list, ebm_mode mode, char **prefices, char **order_name) | ||
{ | ||
json_t *root = json_object(); | ||
char *json_str = NULL; | ||
|
||
switch (mode) { | ||
case boot: | ||
json_fill_bootnext(root); | ||
json_fill_bootcurrent(root); | ||
json_fill_timeout(root); | ||
json_fill_order(root, order_name[mode]); | ||
json_fill_vars(root, prefices[mode], entry_list); | ||
break; | ||
case driver: | ||
case sysprep: | ||
json_fill_order(root, order_name[mode]); | ||
json_fill_vars(root, prefices[mode], entry_list); | ||
break; | ||
} | ||
json_str = json_dumps(root, JSON_COMPACT); | ||
printf("%s\n", json_str); | ||
free(json_str); | ||
json_decref(root); | ||
} |