summaryrefslogtreecommitdiff
path: root/tools/mkeficapsule.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mkeficapsule.c')
-rw-r--r--tools/mkeficapsule.c208
1 files changed, 156 insertions, 52 deletions
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 1b53151d41a..49f5b7849e4 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -16,16 +16,20 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <uuid/uuid.h>
#include <gnutls/gnutls.h>
#include <gnutls/pkcs7.h>
#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, "Usage: %s [options] <image blob> <output file>\n"
+ 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:\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();
}
/**
@@ -578,37 +594,6 @@ err:
return ret;
}
-/**
- * convert_uuid_to_guid() - convert UUID to GUID
- * @buf: UUID binary
- *
- * UUID and GUID have the same data structure, but their binary
- * formats are different due to the endianness. See lib/uuid.c.
- * Since uuid_parse() can handle only UUID, this function must
- * be called to get correct data for GUID when parsing a string.
- *
- * The correct data will be returned in @buf.
- */
-void convert_uuid_to_guid(unsigned char *buf)
-{
- unsigned char c;
-
- c = buf[0];
- buf[0] = buf[3];
- buf[3] = c;
- c = buf[1];
- buf[1] = buf[2];
- buf[2] = c;
-
- c = buf[4];
- buf[4] = buf[5];
- buf[5] = c;
-
- c = buf[6];
- buf[6] = buf[7];
- buf[7] = c;
-}
-
static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
{
struct efi_capsule_header header = { 0 };
@@ -654,20 +639,10 @@ err:
static void print_guid(void *ptr)
{
- int i;
- efi_guid_t *guid = ptr;
- const uint8_t seq[] = {
- 3, 2, 1, 0, '-', 5, 4, '-', 7, 6,
- '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
-
- for (i = 0; i < ARRAY_SIZE(seq); i++) {
- if (seq[i] == '-')
- putchar(seq[i]);
- else
- printf("%02X", guid->b[seq[i]]);
- }
+ static char buf[37] = { 0 };
- printf("\n");
+ uuid_bin_to_str(ptr, buf, UUID_STR_FORMAT_GUID | UUID_STR_UPPER_CASE);
+ printf("%s\n", buf);
}
static uint32_t dump_fmp_payload_header(
@@ -861,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
@@ -885,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;
@@ -907,11 +1012,10 @@ int main(int argc, char **argv)
"Image type already specified\n");
exit(EXIT_FAILURE);
}
- if (uuid_parse(optarg, uuid_buf)) {
+ if (uuid_str_to_bin(optarg, uuid_buf, UUID_STR_FORMAT_GUID)) {
fprintf(stderr, "Wrong guid format\n");
exit(EXIT_FAILURE);
}
- convert_uuid_to_guid(uuid_buf);
guid = (efi_guid_t *)uuid_buf;
break;
case 'i':
@@ -977,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);
}
}
@@ -1000,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);
}