diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/mkeficapsule.c | 156 |
1 files changed, 151 insertions, 5 deletions
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index ede9de2bef7..49f5b7849e4 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -22,10 +22,14 @@ #include <gnutls/abstract.h> #include <version.h> +#include <libfdt.h> #include <u-boot/uuid.h> #include "eficapsule.h" +// Matches CONFIG_EFI_CAPSULE_NAMESPACE_GUID +#define DEFAULT_NAMESPACE_GUID "8c9f137e-91dc-427b-b2d6-b420faebaf2a" + static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; @@ -56,9 +60,20 @@ static struct option options[] = { {NULL, 0, NULL, 0}, }; -static void print_usage(void) +static void print_usage_guidgen(void) +{ + fprintf(stderr, "%s guidgen [GUID] DTB IMAGE_NAME...\n" + "Options:\n" + + "\tGUID Namespace GUID (default: %s)\n" + "\tDTB Device Tree Blob\n" + "\tIMAGE_NAME... One or more names of fw_images to generate GUIDs for\n", + tool_name, DEFAULT_NAMESPACE_GUID); +} + +static void print_usage_mkeficapsule(void) { - fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n" + fprintf(stderr, "Usage:\n\n%s [options] <image blob> <output file>\n" "Options:\n" "\t-g, --guid <guid string> guid for image blob type\n" @@ -74,8 +89,9 @@ static void print_usage(void) "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n" "\t-D, --dump-capsule dump the contents of the capsule headers\n" "\t-V, --version show version number\n" - "\t-h, --help print a help message\n", + "\t-h, --help print a help message\n\n", tool_name); + print_usage_guidgen(); } /** @@ -820,6 +836,129 @@ static void dump_capsule_contents(char *capsule_file) } } +static struct fdt_header *load_dtb(const char *path) +{ + struct fdt_header *dtb; + ssize_t dtb_size; + FILE *f; + + /* Open and parse DTB */ + f = fopen(path, "r"); + if (!f) { + fprintf(stderr, "Cannot open %s\n", path); + return NULL; + } + + if (fseek(f, 0, SEEK_END)) { + fprintf(stderr, "Cannot seek to the end of %s: %s\n", + path, strerror(errno)); + return NULL; + } + + dtb_size = ftell(f); + if (dtb_size < 0) { + fprintf(stderr, "Cannot ftell %s: %s\n", + path, strerror(errno)); + return NULL; + } + + fseek(f, 0, SEEK_SET); + + dtb = malloc(dtb_size); + if (!dtb) { + fprintf(stderr, "Can't allocated %ld\n", dtb_size); + return NULL; + } + + if (fread(dtb, dtb_size, 1, f) != 1) { + fprintf(stderr, "Can't read %ld bytes from %s\n", + dtb_size, path); + free(dtb); + return NULL; + } + + fclose(f); + + return dtb; +} + +#define MAX_IMAGE_NAME_LEN 128 +static int genguid(int argc, char **argv) +{ + int idx = 2, ret; + unsigned char namespace[16]; + struct efi_guid image_type_id; + const char *dtb_path; + struct fdt_header *dtb; + const char *compatible; + int compatlen, namelen; + uint16_t fw_image[MAX_IMAGE_NAME_LEN]; + + if (argc < 2) { + fprintf(stderr, "Usage: "); + print_usage_guidgen(); + return -1; + } + + if (uuid_str_to_bin(argv[1], namespace, UUID_STR_FORMAT_GUID)) { + uuid_str_to_bin(DEFAULT_NAMESPACE_GUID, namespace, UUID_STR_FORMAT_GUID); + dtb_path = argv[1]; + } else { + dtb_path = argv[2]; + idx = 3; + } + + if (idx == argc) { + fprintf(stderr, "Usage: "); + print_usage_guidgen(); + return -1; + } + + dtb = load_dtb(dtb_path); + if (!dtb) + return -1; + + ret = fdt_check_header(dtb); + if (ret) { + fprintf(stderr, "Invalid DTB header: %d\n", ret); + return -1; + } + + compatible = fdt_getprop(dtb, 0, "compatible", &compatlen); + if (!compatible) { + fprintf(stderr, "No compatible string found in DTB\n"); + return -1; + } + if (strnlen(compatible, compatlen) >= compatlen) { + fprintf(stderr, "Compatible string not null-terminated\n"); + return -1; + } + + printf("Generating GUIDs for %s with namespace %s:\n", + compatible, DEFAULT_NAMESPACE_GUID); + for (; idx < argc; idx++) { + memset(fw_image, 0, sizeof(fw_image)); + namelen = strlen(argv[idx]); + if (namelen > MAX_IMAGE_NAME_LEN) { + fprintf(stderr, "Image name too long: %s\n", argv[idx]); + return -1; + } + + for (int i = 0; i < namelen; i++) + fw_image[i] = (uint16_t)argv[idx][i]; + + gen_v5_guid((struct uuid *)&namespace, &image_type_id, + compatible, strlen(compatible), + fw_image, namelen * sizeof(uint16_t), + NULL); + + printf("%s: ", argv[idx]); + print_guid(&image_type_id); + } + + return 0; +} + /** * main - main entry function of mkeficapsule * @argc: Number of arguments @@ -844,6 +983,13 @@ int main(int argc, char **argv) int c, idx; struct fmp_payload_header_params fmp_ph_params = { 0 }; + /* Generate dynamic GUIDs */ + if (argc > 1 && !strcmp(argv[1], "guidgen")) { + if (genguid(argc - 1, argv + 1)) + exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); + } + guid = NULL; index = 0; instance = 0; @@ -935,7 +1081,7 @@ int main(int argc, char **argv) printf("mkeficapsule version %s\n", PLAIN_VERSION); exit(EXIT_SUCCESS); default: - print_usage(); + print_usage_mkeficapsule(); exit(EXIT_FAILURE); } } @@ -958,7 +1104,7 @@ int main(int argc, char **argv) ((argc != optind + 1) || ((capsule_type == CAPSULE_ACCEPT) && !guid) || ((capsule_type == CAPSULE_REVERT) && guid)))) { - print_usage(); + print_usage_mkeficapsule(); exit(EXIT_FAILURE); } |