mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 07:04:28 +00:00
tools: mkeficapsule: Add support to print capsule headers
Add support to dump the contents of capsule headers. This is useful as a debug feature for checking the contents of the capsule headers, and can also be used in capsule verification. Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
5fecea171d
commit
6984077de0
2 changed files with 228 additions and 1 deletions
|
@ -22,6 +22,8 @@
|
|||
#define __aligned(x) __attribute__((__aligned__(x)))
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
typedef struct {
|
||||
uint8_t b[16];
|
||||
} efi_guid_t __aligned(8);
|
||||
|
|
|
@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
|
|||
efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
|
||||
efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
|
||||
|
||||
static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
|
||||
static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD";
|
||||
|
||||
enum {
|
||||
CAPSULE_NORMAL_BLOB = 0,
|
||||
|
@ -49,6 +49,7 @@ static struct option options[] = {
|
|||
{"fw-accept", no_argument, NULL, 'A'},
|
||||
{"fw-revert", no_argument, NULL, 'R'},
|
||||
{"capoemflag", required_argument, NULL, 'o'},
|
||||
{"dump-capsule", no_argument, NULL, 'D'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
@ -69,6 +70,7 @@ static void print_usage(void)
|
|||
"\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n"
|
||||
"\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n"
|
||||
"\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-h, --help print a help message\n",
|
||||
tool_name);
|
||||
}
|
||||
|
@ -647,6 +649,215 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
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]]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static uint32_t dump_fmp_payload_header(
|
||||
struct fmp_payload_header *fmp_payload_hdr)
|
||||
{
|
||||
if (fmp_payload_hdr->signature == FMP_PAYLOAD_HDR_SIGNATURE) {
|
||||
printf("--------\n");
|
||||
printf("FMP_PAYLOAD_HDR.SIGNATURE\t\t\t: %08X\n",
|
||||
FMP_PAYLOAD_HDR_SIGNATURE);
|
||||
printf("FMP_PAYLOAD_HDR.HEADER_SIZE\t\t\t: %08X\n",
|
||||
fmp_payload_hdr->header_size);
|
||||
printf("FMP_PAYLOAD_HDR.FW_VERSION\t\t\t: %08X\n",
|
||||
fmp_payload_hdr->fw_version);
|
||||
printf("FMP_PAYLOAD_HDR.LOWEST_SUPPORTED_VERSION\t: %08X\n",
|
||||
fmp_payload_hdr->lowest_supported_version);
|
||||
return fmp_payload_hdr->header_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_capsule_auth_header(
|
||||
struct efi_firmware_image_authentication *capsule_auth_hdr)
|
||||
{
|
||||
printf("EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT\t\t: %08lX\n",
|
||||
capsule_auth_hdr->monotonic_count);
|
||||
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.dwLENGTH\t: %08X\n",
|
||||
capsule_auth_hdr->auth_info.hdr.dwLength);
|
||||
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION\t: %08X\n",
|
||||
capsule_auth_hdr->auth_info.hdr.wRevision);
|
||||
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE\t: %08X\n",
|
||||
capsule_auth_hdr->auth_info.hdr.wCertificateType);
|
||||
printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE\t: ");
|
||||
print_guid(&capsule_auth_hdr->auth_info.cert_type);
|
||||
}
|
||||
|
||||
static void dump_fmp_capsule_image_header(
|
||||
struct efi_firmware_management_capsule_image_header *image_hdr)
|
||||
{
|
||||
void *capsule_auth_hdr;
|
||||
void *fmp_payload_hdr;
|
||||
uint64_t signature_size = 0;
|
||||
uint32_t payload_size = 0;
|
||||
uint32_t fmp_payload_hdr_size = 0;
|
||||
struct efi_firmware_image_authentication *auth_hdr;
|
||||
|
||||
printf("--------\n");
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n",
|
||||
image_hdr->version);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID\t: ");
|
||||
print_guid(&image_hdr->update_image_type_id);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX\t: %08X\n",
|
||||
image_hdr->update_image_index);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_SIZE\t\t: %08X\n",
|
||||
image_hdr->update_image_size);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_VENDOR_CODE_SIZE\t: %08X\n",
|
||||
image_hdr->update_vendor_code_size);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_HARDWARE_INSTANCE\t: %08lX\n",
|
||||
image_hdr->update_hardware_instance);
|
||||
printf("FMP_CAPSULE_IMAGE_HDR.IMAGE_CAPSULE_SUPPORT\t: %08lX\n",
|
||||
image_hdr->image_capsule_support);
|
||||
|
||||
printf("--------\n");
|
||||
if (image_hdr->image_capsule_support & CAPSULE_SUPPORT_AUTHENTICATION) {
|
||||
capsule_auth_hdr = (char *)image_hdr + sizeof(*image_hdr);
|
||||
dump_capsule_auth_header(capsule_auth_hdr);
|
||||
|
||||
auth_hdr = capsule_auth_hdr;
|
||||
signature_size = sizeof(auth_hdr->monotonic_count) +
|
||||
auth_hdr->auth_info.hdr.dwLength;
|
||||
fmp_payload_hdr = (char *)capsule_auth_hdr + signature_size;
|
||||
} else {
|
||||
printf("Capsule Authentication Not Enabled\n");
|
||||
fmp_payload_hdr = (char *)image_hdr + sizeof(*image_hdr);
|
||||
}
|
||||
|
||||
fmp_payload_hdr_size = dump_fmp_payload_header(fmp_payload_hdr);
|
||||
|
||||
payload_size = image_hdr->update_image_size - signature_size -
|
||||
fmp_payload_hdr_size;
|
||||
printf("--------\n");
|
||||
printf("Payload Image Size\t\t\t\t: %08X\n", payload_size);
|
||||
}
|
||||
|
||||
static void dump_fmp_header(
|
||||
struct efi_firmware_management_capsule_header *fmp_hdr)
|
||||
{
|
||||
int i;
|
||||
void *capsule_image_hdr;
|
||||
|
||||
printf("EFI_FMP_HDR.VERSION\t\t\t\t: %08X\n", fmp_hdr->version);
|
||||
printf("EFI_FMP_HDR.EMBEDDED_DRIVER_COUNT\t\t: %08X\n",
|
||||
fmp_hdr->embedded_driver_count);
|
||||
printf("EFI_FMP_HDR.PAYLOAD_ITEM_COUNT\t\t\t: %08X\n",
|
||||
fmp_hdr->payload_item_count);
|
||||
|
||||
/*
|
||||
* We currently don't support Embedded Drivers.
|
||||
* Only worry about the payload items.
|
||||
*/
|
||||
for (i = 0; i < fmp_hdr->payload_item_count; i++) {
|
||||
capsule_image_hdr = (char *)fmp_hdr +
|
||||
fmp_hdr->item_offset_list[i];
|
||||
dump_fmp_capsule_image_header(capsule_image_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_capsule_header(struct efi_capsule_header *capsule_hdr)
|
||||
{
|
||||
printf("EFI_CAPSULE_HDR.CAPSULE_GUID\t\t\t: ");
|
||||
print_guid((void *)&capsule_hdr->capsule_guid);
|
||||
printf("EFI_CAPSULE_HDR.HEADER_SIZE\t\t\t: %08X\n",
|
||||
capsule_hdr->header_size);
|
||||
printf("EFI_CAPSULE_HDR.FLAGS\t\t\t\t: %08X\n", capsule_hdr->flags);
|
||||
printf("EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE\t\t: %08X\n",
|
||||
capsule_hdr->capsule_image_size);
|
||||
}
|
||||
|
||||
static void normal_capsule_dump(void *capsule_buf)
|
||||
{
|
||||
void *fmp_hdr;
|
||||
struct efi_capsule_header *hdr = capsule_buf;
|
||||
|
||||
dump_capsule_header(hdr);
|
||||
printf("--------\n");
|
||||
|
||||
fmp_hdr = (char *)capsule_buf + sizeof(*hdr);
|
||||
dump_fmp_header(fmp_hdr);
|
||||
}
|
||||
|
||||
static void empty_capsule_dump(void *capsule_buf)
|
||||
{
|
||||
efi_guid_t *accept_image_guid;
|
||||
struct efi_capsule_header *hdr = capsule_buf;
|
||||
efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
|
||||
|
||||
dump_capsule_header(hdr);
|
||||
|
||||
if (!memcmp(&efi_empty_accept_capsule, &hdr->capsule_guid,
|
||||
sizeof(efi_guid_t))) {
|
||||
accept_image_guid = (void *)(char *)capsule_buf +
|
||||
sizeof(struct efi_capsule_header);
|
||||
printf("--------\n");
|
||||
printf("ACCEPT_IMAGE_GUID\t\t\t\t: ");
|
||||
print_guid(accept_image_guid);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_capsule_contents(char *capsule_file)
|
||||
{
|
||||
int fd;
|
||||
char *ptr;
|
||||
efi_guid_t efi_fmp_guid = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
|
||||
efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID;
|
||||
efi_guid_t efi_empty_revert_capsule = FW_REVERT_OS_GUID;
|
||||
struct stat sbuf;
|
||||
|
||||
if (!capsule_file) {
|
||||
fprintf(stderr, "No capsule file provided\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((fd = open(capsule_file, O_RDONLY)) < 0) {
|
||||
fprintf(stderr, "Error opening capsule file: %s\n",
|
||||
capsule_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fstat(fd, &sbuf) < 0) {
|
||||
fprintf(stderr, "Can't stat capsule file: %s\n", capsule_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0))
|
||||
== MAP_FAILED) {
|
||||
fprintf(stderr, "Can't mmap capsule file: %s\n", capsule_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!memcmp(&efi_fmp_guid, ptr, sizeof(efi_guid_t))) {
|
||||
normal_capsule_dump(ptr);
|
||||
} else if (!memcmp(&efi_empty_accept_capsule, ptr,
|
||||
sizeof(efi_guid_t)) ||
|
||||
!memcmp(&efi_empty_revert_capsule, ptr,
|
||||
sizeof(efi_guid_t))) {
|
||||
empty_capsule_dump(ptr);
|
||||
} else {
|
||||
fprintf(stderr, "Unable to decode the capsule file: %s\n",
|
||||
capsule_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* main - main entry function of mkeficapsule
|
||||
* @argc: Number of arguments
|
||||
|
@ -666,6 +877,7 @@ int main(int argc, char **argv)
|
|||
unsigned long index, instance;
|
||||
uint64_t mcount;
|
||||
unsigned long oemflags;
|
||||
bool capsule_dump;
|
||||
char *privkey_file, *cert_file;
|
||||
int c, idx;
|
||||
struct fmp_payload_header_params fmp_ph_params = { 0 };
|
||||
|
@ -676,6 +888,7 @@ int main(int argc, char **argv)
|
|||
mcount = 0;
|
||||
privkey_file = NULL;
|
||||
cert_file = NULL;
|
||||
capsule_dump = false;
|
||||
dump_sig = 0;
|
||||
capsule_type = CAPSULE_NORMAL_BLOB;
|
||||
oemflags = 0;
|
||||
|
@ -754,12 +967,24 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
capsule_dump = true;
|
||||
break;
|
||||
default:
|
||||
print_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (capsule_dump) {
|
||||
if (argc != optind + 1) {
|
||||
fprintf(stderr, "Must provide the capsule file to parse\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
dump_capsule_contents(argv[argc - 1]);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* check necessary parameters */
|
||||
if ((capsule_type == CAPSULE_NORMAL_BLOB &&
|
||||
((argc != optind + 2) || !guid ||
|
||||
|
|
Loading…
Reference in a new issue