Compare commits

...

26 Commits

Author SHA1 Message Date
Simon Glass
87ff7df6a6 fit: Use the libfdt subnode iterator
Replace fdt_next_node() with depth tracking with fdt_for_each_subnode()
which has been available for some time.

This also fixes a latent bug where the default configuration was being
read from the wrong node offset. It happened to work before because
noffset ended up at the right value after the images loop.

Series-to: concept
Series-cc: heinrich
Cover-letter:
fit: Improve and test the code to print FIT info
The code for printing information about FITs is fairly old and not that
easy to maintain. It also lacks tests.

This series adds some tests, moves the code into its own file and then
adds a series of helpers to deal with the intricacies of printing each
item.

This provides a binary-size reduction of about 320 bytes on aarch64.
END

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:47:59 -07:00
Simon Glass
38f96198de fit: Add a helper to iterate through hash/signature nodes
The pattern for iterating through and processing hash/signature subnodes
is repeated in two places. Add a new process_subnodes() helper to reduce
code duplication.

Drop the now-unused ndepth and noffset local variables.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:43:07 -07:00
Simon Glass
a56029dca7 fit: Use a boolean to simplify type checks
Add a boolean variable 'loadable' that combines the common type check
for kernel, standalone, and ramdisk images.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:42:29 -07:00
Simon Glass
db9df43e39 fit: Add a helper for address printing
Add emit_addr() to handle printing load an entry addresses.

The helper takes a 'valid' boolean parameter to determine whether to
print the address value or 'unavailable'.

Combine the two separate if() blocks for the load address.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:41:15 -07:00
Simon Glass
a02307aaab fit: Add a helper for printing descriptions
Add emit_desc() which handles getting and printing descriptions from FIT
nodes. Handle the "unavailable" case when a description is missing.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:40:29 -07:00
Simon Glass
013d05ff79 fit: Add a helper for stringlist properties
Add a emit_stringlist() helper function to simplify printing stringlist
properties in FIT configurations.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:39:59 -07:00
Simon Glass
b1f69b13ca fit: Add a helper for timestamp printing
Add a new emit_timestamp() helper function to handle printing timestamps
in FITs.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:39:26 -07:00
Simon Glass
313a765e97 fit: Add a helper to output optional properties
Add a new emit_prop() helper function to simplify printing optional
properties in FIT configurations.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:38:52 -07:00
Simon Glass
1004d2bf1f fit: Use emit_label_val() where possible
Refactor the printing of multi-line properties to use the
emit_label_val() helper function instead of custom formatting.

Update emit_label() to deal with an empty label and not show a colon in
that case.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:38:38 -07:00
Simon Glass
4facf75881 fit: Move values one column to the right
Line up the values witht the FIT Description and Created items at the
top. This looks a little nicer.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:35:06 -07:00
Simon Glass
a2d18c32af fit: Change indent from string to int
Change the indent field in fit_print_ctx from a string pointer to an int
number of spaces to indent.

Set the initial indent value to 3 to match IMAGE_INDENT_STRING

Drop indentation from the debug() calls since these are not visible to
users.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:35:03 -07:00
Simon Glass
f8bcbbf43c fit: Add a a function to print labels with values
Add a new emit_label_val() helper function that combines emit_label()
and printf() for simple label-value pairs.

Make use of it where appropriate.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:33:10 -07:00
Simon Glass
796610f8d8 fit: Use emit_label() helper in fit_conf_print()
Update fit_conf_print() to use the emit_label() helper function for
printing labels.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:32:46 -07:00
Simon Glass
653a7864bd fit: Use emit_label() helper in fit_image_print()
Update fit_image_print() to use the emit_label() helper function for
printing labels. This avoids various manual printf() calls and spacing
logic.

Set ctx->tab to 19 to align values at the correct column position.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:31:43 -07:00
Simon Glass
900fcec548 fit: Create some helpers for printing
The current code is quite fiddly with manually spaced labels. Add helper
functions for printing labels (with or without a type prefix) with a
cofigurable tab width for the value that folows.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:29:43 -07:00
Simon Glass
0f7ec21254 fit: Put the indent string into print context
Move the indent string into struct fit_print_ctx so it is available to
the printing functions. This avoids having to pass it as a separate
parameter.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:29:22 -07:00
Simon Glass
a682393bc0 fit: Add a context struct for FIT-printing
Create a struct fit_print_ctx to hold the FIT pointer and pass it to all
printing functions instead of passing the FIT pointer directly. This
provides a foundation for adding additional context in the future.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:29:22 -07:00
Simon Glass
fb7bd18c21 fit: Drop showing an unused 'required' property
This is actually not defined by the spec. The 'required' property is for
use by the verifying code. Having it in the FIT does not help size an
attacker could potentially remove it.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:29:22 -07:00
Simon Glass
0fe2fb8bbc fit: Move printing code to its own file
There is enough code here that it makes sense to put it in its own file.
Create a new fit_print.c file, before undertaking future refactoring.

Printing is only included in the build if CONFIG_FIT_PRINT is enabled.

Make a few small code-style adjustments.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:29:21 -07:00
Simon Glass
4e10991148 fit: Refactor fit_print_contents() to use new fit_print()
Create a new fit_print() function containing the logic from
fit_print_contents(), and make fit_print_contents() call it.
This allows future callers to use fit_print() directly as we add more
features.

Tidy up the function comments so that they are in the header.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:39 -07:00
Simon Glass
ffd5339e9e test: fit: Add test for missing FIT description
Add a test to verify that fit_print_contents() correctly handles a FIT
image with a missing description property.

To handle this a new FIT created with the description removed after
mkimage has processed it, since mkimage will fail if the description is
missing.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:39 -07:00
Simon Glass
08cd4b94f0 test: fit: Test the remaining features and edge cases
Add support for testing the loadables, fpga, compatible properties and
unavailable/error conditions in FIT configurations.

With this, most of the FIT-printing code is covered by tests.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:39 -07:00
Simon Glass
ac06e52d77 test: fit: Test printing a FIT with multiple FDTs
Update the FDT fdt to include two separate FDT images, referenced by the
two configurations.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:39 -07:00
Simon Glass
24da9b60d5 test: Add signature-testing to the FIT-printing test
Add a signature node to the FIT configuration in the ITS template, using
a fixed RSA-2048 private key for reproducible signatures. Use the default
'pkcs-1.5' padding.

Use mkimage to sign it.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:38 -07:00
Simon Glass
c01d679c78 test: Add a test for FIT image printing
The code for printing FITs is quite messy, with lots of separate
printf() calls, an indentation string, etc.

It also has no tests.

In preparation for refactoring this code, add a test. Use Python code
to create the test image and C code to test it.

The test covers FIT description, image details (type, architecture, OS,
addresses), and configuration details.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-11-18 17:18:38 -07:00
Simon Glass
8e90172e19 fit: Remove unused len parameter from fit_get_name()
Remove the unused third parameter (len) from fit_get_name(). All 54
call sites in the codebase pass NULL for this parameter, and the
returned length is never used.

This simplifies the API and makes it clearer that the function only
returns the node name string, not its length.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 17:18:37 -07:00
16 changed files with 1087 additions and 476 deletions

View File

@@ -48,6 +48,7 @@ obj-$(CONFIG_$(PHASE_)UPL_WRITE) += upl_write.o
obj-$(CONFIG_$(PHASE_)OF_LIBFDT) += image-fdt.o
obj-$(CONFIG_$(PHASE_)FIT_SIGNATURE) += fdt_region.o
obj-$(CONFIG_$(PHASE_)FIT) += image-fit.o
obj-$(CONFIG_$(PHASE_)FIT_PRINT) += fit_print.o
obj-$(CONFIG_$(PHASE_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
obj-$(CONFIG_$(PHASE_)IMAGE_PRE_LOAD) += image-pre-load.o
obj-$(CONFIG_$(PHASE_)IMAGE_SIGN_INFO) += image-sig.o

494
boot/fit_print.c Normal file
View File

@@ -0,0 +1,494 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2013, Google Inc.
*
* (C) Copyright 2008 Semihalf
*
* (C) Copyright 2000-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#define LOG_CATEGORY LOGC_BOOT
#ifdef USE_HOSTCC
#include "mkimage.h"
#include <time.h>
#include <linux/libfdt.h>
#else
#include <linux/compiler.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#endif
#include <image.h>
#include <u-boot/crc.h>
/**
* fit_print_init() - initialize FIT print context
* @ctx: pointer to FIT print context to initialize
* @fit: pointer to the FIT format image header
*
* This initializes a fit_print_ctx structure with the given FIT image.
*/
void fit_print_init(struct fit_print_ctx *ctx, const void *fit)
{
ctx->fit = fit;
ctx->indent = IMAGE_INDENT;
ctx->tab = 20;
}
/**
* emit_type() - print a label with indentation and padding
* @ctx: pointer to FIT print context
* @type: type prefix (e.g., "Hash" or "Sign")
* @label: label suffix (e.g., "algo" or "value")
*
* Prints the indentation from the context, followed by two spaces, the type,
* a space, the label, a colon, and padding to align values to ctx->tab.
*/
static void emit_type(struct fit_print_ctx *ctx, const char *type,
const char *label)
{
int len;
len = printf("%*s%s %s:", ctx->indent, "", type, label);
printf("%*s", ctx->tab - len, "");
}
/**
* emit_label() - print a label with indentation and padding
* @ctx: pointer to FIT print context
* @type: type prefix (e.g., "Hash" or "Sign")
* @label: label suffix (e.g., "algo" or "value")
*
* Prints the indentation from the context, followed by two spaces, a space,
* the label, a colon, and padding to align values to ctx->tab.
*/
static void emit_label(struct fit_print_ctx *ctx, const char *label)
{
int len;
len = printf("%*s%s%c", ctx->indent, "", label, *label ? ':' : ' ');
printf("%*s", ctx->tab - len, "");
}
/**
* emit_label_val() - print a label with value
* @ctx: pointer to FIT print context
* @label: label string (e.g., "Type" or "OS")
* @val: value string to print after the label
*
* Prints the indentation, label with padding to ctx->tab, and the value
* followed by a newline. This is a convenience function that combines
* emit_label() and printf() for simple label-value pairs.
*/
static void emit_label_val(struct fit_print_ctx *ctx, const char *label,
const char *val)
{
emit_label(ctx, label);
printf("%s\n", val);
}
/**
* emit_prop() - print a property if it exists
* @ctx: pointer to FIT print context
* @noffset: offset of the node containing the property
* @prop: property name to get and print
* @label: label string to use when printing
*
* Gets a property from the specified node and prints it with the given label
* only if the property exists. This is a convenience function for optional
* properties that should only be printed when present.
*/
static void emit_prop(struct fit_print_ctx *ctx, int noffset,
const char *prop, const char *label)
{
const char *val;
val = fdt_getprop(ctx->fit, noffset, prop, NULL);
if (val)
emit_label_val(ctx, label, val);
}
/**
* emit_timestamp() - print a timestamp
* @ctx: pointer to FIT print context
* @noffset: offset of the node containing the timestamp
* @label: label string to use when printing
*
* Gets the timestamp from the specified node and prints it with the given
* label. If the timestamp is not available, prints "unavailable" instead.
* This is a convenience function for printing FIT timestamps.
*/
static void emit_timestamp(struct fit_print_ctx *ctx, int noffset,
const char *label)
{
time_t timestamp;
if (!IMAGE_ENABLE_TIMESTAMP)
return;
emit_label(ctx, label);
if (fit_get_timestamp(ctx->fit, noffset, &timestamp))
printf("unavailable\n");
else
genimg_print_time(timestamp);
}
/**
* emit_stringlist() - print a stringlist property
* @ctx: pointer to FIT print context
* @noffset: offset of the node containing the property
* @prop: property name to get and print
* @label: label string to use when printing
*
* Gets a stringlist property from the specified node and prints each string
* with the given label. The first string shows the label, subsequent strings
* are indented to align with the first value. If the property doesn't exist,
* nothing is printed.
*/
static void emit_stringlist(struct fit_print_ctx *ctx, int noffset,
const char *prop, const char *label)
{
const char *val;
int i;
for (i = 0;
val = fdt_stringlist_get(ctx->fit, noffset, prop, i, NULL), val;
i++)
emit_label_val(ctx, i ? "" : label, val);
}
/**
* emit_desc() - print a description
* @ctx: pointer to FIT print context
* @noffset: offset of the node containing the description
* @label: label string to use when printing
*
* Gets the description from the specified node and prints it with the given
* label. If the description is not available, prints "unavailable" instead.
* This is a convenience function for printing FIT descriptions.
*/
static void emit_desc(struct fit_print_ctx *ctx, int noffset,
const char *label)
{
const char *desc;
int ret;
ret = fit_get_desc(ctx->fit, noffset, &desc);
emit_label_val(ctx, label, ret ? "unavailable" : desc);
}
/**
* emit_addr() - print an address property
* @ctx: pointer to FIT print context
* @label: label string to use when printing
* @addr: address value to print
* @valid: true if the address is valid, false to print "unavailable"
*
* Prints an address with the given label. If valid is false, prints
* "unavailable" instead of the address value.
*/
static void emit_addr(struct fit_print_ctx *ctx, const char *label, ulong addr,
bool valid)
{
emit_label(ctx, label);
if (valid)
printf("0x%08lx\n", addr);
else
printf("unavailable\n");
}
/**
* fit_image_print_data() - prints out the hash node details
* @ctx: pointer to FIT print context
* @noffset: offset of the hash node
* @type: Type of information to print ("hash" or "sign")
*
* fit_image_print_data() lists properties for the processed hash node
*
* This function avoid using puts() since it prints a newline on the host
* but does not in U-Boot.
*
* returns:
* no returned results
*/
static void fit_image_print_data(struct fit_print_ctx *ctx, int noffset,
const char *type)
{
const char *keyname, *padding, *algo;
int p = ctx->indent;
const void *fit = ctx->fit;
int value_len, ret, i;
uint8_t *value;
debug("%s node: '%s'\n", type, fit_get_name(fit, noffset));
emit_type(ctx, type, "algo");
if (fit_image_hash_get_algo(fit, noffset, &algo)) {
printf("invalid/unsupported\n");
return;
}
printf("%s", algo);
keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
if (keyname)
printf(":%s", keyname);
printf("\n");
padding = fdt_getprop(fit, noffset, "padding", NULL);
if (padding)
printf("%*s%s padding: %s\n", p, "", type, padding);
ret = fit_image_hash_get_value(fit, noffset, &value, &value_len);
emit_type(ctx, type, "value");
if (ret) {
printf("unavailable\n");
} else {
for (i = 0; i < value_len; i++)
printf("%02x", value[i]);
printf("\n");
}
debug("%s len: %d\n", type, value_len);
/* Signatures have a time stamp */
if (IMAGE_ENABLE_TIMESTAMP && keyname)
emit_timestamp(ctx, noffset, "Timestamp");
}
/**
* fit_image_print_verification_data() - prints out the hash/signature details
* @ctx: pointer to FIT print context
* @noffset: offset of the hash or signature node
*
* This lists properties for the processed hash node
*
* returns:
* no returned results
*/
static void fit_image_print_verification_data(struct fit_print_ctx *ctx,
int noffset)
{
const void *fit = ctx->fit;
const char *name;
/*
* Check subnode name, must be equal to "hash" or "signature".
* Multiple hash/signature nodes require unique unit node
* names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
*/
name = fit_get_name(fit, noffset);
if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
fit_image_print_data(ctx, noffset, "Hash");
else if (!strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME)))
fit_image_print_data(ctx, noffset, "Sign");
}
/**
* process_subnodes() - process and print verification data for all subnodes
* @ctx: pointer to FIT print context
* @parent: parent node offset
*
* Iterates through all direct child nodes of the parent and prints their
* verification data (hash/signature information).
*/
static void process_subnodes(struct fit_print_ctx *ctx, int parent)
{
const void *fit = ctx->fit;
int noffset;
fdt_for_each_subnode(noffset, fit, parent)
fit_image_print_verification_data(ctx, noffset);
}
/**
* fit_image_print - prints out the FIT component image details
* @ctx: pointer to FIT print context
* @image_noffset: offset of the component image node
* @p: pointer to prefix string
*
* fit_image_print() lists all mandatory properties for the processed component
* image. If present, hash nodes are printed out as well. Load
* address for images of type firmware is also printed out. Since the load
* address is not mandatory for firmware images, it will be output as
* "unavailable" when not present.
*
* returns:
* no returned results
*/
void fit_image_print(struct fit_print_ctx *ctx, int image_noffset)
{
const void *fit = ctx->fit;
uint8_t type, arch, os, comp = IH_COMP_NONE;
size_t size;
ulong load, entry;
const void *data;
int ret;
/* Mandatory properties */
emit_desc(ctx, image_noffset, "Description");
emit_timestamp(ctx, 0, "Created");
fit_image_get_type(fit, image_noffset, &type);
emit_label_val(ctx, "Type", genimg_get_type_name(type));
fit_image_get_comp(fit, image_noffset, &comp);
emit_label_val(ctx, "Compression", genimg_get_comp_name(comp));
ret = fit_image_get_data(fit, image_noffset, &data, &size);
if (!tools_build()) {
emit_label(ctx, "Data Start");
if (ret) {
printf("unavailable\n");
} else {
void *vdata = (void *)data;
printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
}
}
emit_label(ctx, "Data Size");
if (ret)
printf("unavailable\n");
else
genimg_print_size(size);
/* Remaining, type dependent properties */
bool loadable = type == IH_TYPE_KERNEL || type == IH_TYPE_STANDALONE ||
type == IH_TYPE_RAMDISK;
if (loadable || type == IH_TYPE_FIRMWARE || type == IH_TYPE_FLATDT) {
fit_image_get_arch(fit, image_noffset, &arch);
emit_label_val(ctx, "Architecture", genimg_get_arch_name(arch));
}
if (loadable || type == IH_TYPE_FIRMWARE) {
fit_image_get_os(fit, image_noffset, &os);
emit_label_val(ctx, "OS", genimg_get_os_name(os));
}
if (loadable || type == IH_TYPE_FIRMWARE || type == IH_TYPE_FPGA ||
type == IH_TYPE_FLATDT) {
ret = fit_image_get_load(fit, image_noffset, &load);
if (type != IH_TYPE_FLATDT || !ret)
emit_addr(ctx, "Load Address", load, !ret);
}
if (loadable) {
ret = fit_image_get_entry(fit, image_noffset, &entry);
emit_addr(ctx, "Entry Point", entry, !ret);
}
/* Process all hash subnodes of the component image node */
process_subnodes(ctx, image_noffset);
}
/**
* fit_conf_print - prints out the FIT configuration details
* @ctx: pointer to FIT print context
* @noffset: offset of the configuration node
*
* fit_conf_print() lists all mandatory properties for the processed
* configuration node.
*
* returns:
* no returned results
*/
static void fit_conf_print(struct fit_print_ctx *ctx, int noffset)
{
const void *fit = ctx->fit;
const char *uname;
/* Mandatory properties */
emit_desc(ctx, noffset, "Description");
uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
emit_label_val(ctx, "Kernel", uname ?: "unavailable");
/* Optional properties */
emit_prop(ctx, noffset, FIT_RAMDISK_PROP, "Init Ramdisk");
emit_prop(ctx, noffset, FIT_FIRMWARE_PROP, "Firmware");
emit_stringlist(ctx, noffset, FIT_FDT_PROP, "FDT");
emit_prop(ctx, noffset, FIT_FPGA_PROP, "FPGA");
emit_stringlist(ctx, noffset, FIT_LOADABLE_PROP, "Loadables");
emit_stringlist(ctx, noffset, FIT_COMPATIBLE_PROP, "Compatible");
/* Process all hash subnodes of the component configuration node */
process_subnodes(ctx, noffset);
}
void fit_print(struct fit_print_ctx *ctx)
{
const void *fit = ctx->fit;
int p = ctx->indent;
char *uname;
int images_noffset;
int confs_noffset;
int noffset;
int count;
/* Root node properties */
emit_desc(ctx, 0, "FIT description");
emit_timestamp(ctx, 0, "Created");
/* Find images parent node offset */
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images_noffset < 0) {
printf("Can't find images parent node '%s' (%s)\n",
FIT_IMAGES_PATH, fdt_strerror(images_noffset));
return;
}
/* Process its subnodes, print out component images details */
count = 0;
fdt_for_each_subnode(noffset, fit, images_noffset) {
/*
* Direct child node of the images parent node,
* i.e. component image node.
*/
printf("%*s Image %u (%s)\n", p, "", count++,
fit_get_name(fit, noffset));
ctx->indent += 2;
fit_image_print(ctx, noffset);
ctx->indent -= 2;
}
/* Find configurations parent node offset */
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
if (confs_noffset < 0) {
debug("Can't get configurations parent node '%s' (%s)\n",
FIT_CONFS_PATH, fdt_strerror(confs_noffset));
return;
}
/* get default configuration unit name from default property */
uname = (char *)fdt_getprop(fit, confs_noffset, FIT_DEFAULT_PROP, NULL);
if (uname)
printf("%*s Default Configuration: '%s'\n", p, "", uname);
/* Process its subnodes, print out configurations details */
count = 0;
fdt_for_each_subnode(noffset, fit, confs_noffset) {
/*
* Direct child node of the configurations parent node,
* i.e. configuration node.
*/
printf("%*s Configuration %u (%s)\n", p, "", count++,
fit_get_name(fit, noffset));
ctx->indent += 2;
fit_conf_print(ctx, noffset);
ctx->indent -= 2;
}
}
void fit_print_contents(const void *fit)
{
struct fit_print_ctx ctx;
fit_print_init(&ctx, fit);
fit_print(&ctx);
}

View File

@@ -76,7 +76,7 @@ static int fit_image_setup_decrypt(struct image_cipher_info *info,
char *algo_name;
int ret;
node_name = fit_get_name(fit, image_noffset, NULL);
node_name = fit_get_name(fit, image_noffset);
if (!node_name) {
printf("Can't get node name\n");
return -1;

View File

@@ -145,7 +145,7 @@ static int fit_image_verify_sig(const void *fit, int image_noffset,
/* Process all hash subnodes of the component image node */
fdt_for_each_subnode(noffset, fit, image_noffset) {
const char *name = fit_get_name(fit, noffset, NULL);
const char *name = fit_get_name(fit, noffset);
/*
* We don't support this since libfdt considers names with the
@@ -178,8 +178,8 @@ static int fit_image_verify_sig(const void *fit, int image_noffset,
error:
printf(" error!\n%s for '%s' hash node in '%s' image node\n",
err_msg, fit_get_name(fit, noffset, NULL),
fit_get_name(fit, image_noffset, NULL));
err_msg, fit_get_name(fit, noffset),
fit_get_name(fit, image_noffset));
return -1;
}
@@ -212,7 +212,7 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset,
key_blob, noffset);
if (ret) {
printf("Failed to verify required signature '%s'\n",
fit_get_name(key_blob, noffset, NULL));
fit_get_name(key_blob, noffset));
return ret;
}
verify_count++;
@@ -277,10 +277,10 @@ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset,
char path[200];
int count;
config_name = fit_get_name(fit, conf_noffset, NULL);
config_name = fit_get_name(fit, conf_noffset);
debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob,
fit_get_name(fit, noffset, NULL),
fit_get_name(key_blob, required_keynode, NULL));
fit_get_name(fit, noffset),
fit_get_name(key_blob, required_keynode));
*err_msgp = NULL;
if (fit_image_setup_verify(&info, fit, noffset, key_blob,
required_keynode, err_msgp))
@@ -421,7 +421,7 @@ static int fit_config_verify_key(const void *fit, int conf_noffset,
/* Process all hash subnodes of the component conf node */
fdt_for_each_subnode(noffset, fit, conf_noffset) {
const char *name = fit_get_name(fit, noffset, NULL);
const char *name = fit_get_name(fit, noffset);
if (!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
@@ -448,8 +448,8 @@ static int fit_config_verify_key(const void *fit, int conf_noffset,
error:
printf(" error!\n%s for '%s' hash node in '%s' config node\n",
err_msg, fit_get_name(fit, noffset, NULL),
fit_get_name(fit, conf_noffset, NULL));
err_msg, fit_get_name(fit, noffset),
fit_get_name(fit, conf_noffset));
return -EPERM;
}
@@ -469,7 +469,7 @@ error:
static int fit_config_verify_required_keys(const void *fit, int conf_noffset,
const void *key_blob)
{
const char *name = fit_get_name(fit, conf_noffset, NULL);
const char *name = fit_get_name(fit, conf_noffset);
int noffset;
int key_node;
int verified = 0;
@@ -525,7 +525,7 @@ static int fit_config_verify_required_keys(const void *fit, int conf_noffset,
if (ret) {
if (reqd_policy_all) {
printf("Failed to verify required signature '%s'\n",
fit_get_name(key_blob, noffset, NULL));
fit_get_name(key_blob, noffset));
return ret;
}
} else {

View File

@@ -148,7 +148,7 @@ static void fit_get_debug(const void *fit, int noffset,
char *prop_name, int err)
{
debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset),
fdt_strerror(err));
}
@@ -179,423 +179,6 @@ int fit_get_subimage_count(const void *fit, int images_noffset)
return count;
}
/**
* fit_image_print_data() - prints out the hash node details
* @fit: pointer to the FIT format image header
* @noffset: offset of the hash node
* @p: pointer to prefix string
* @type: Type of information to print ("hash" or "sign")
*
* fit_image_print_data() lists properties for the processed hash node
*
* This function avoid using puts() since it prints a newline on the host
* but does not in U-Boot.
*
* returns:
* no returned results
*/
static void fit_image_print_data(const void *fit, int noffset, const char *p,
const char *type)
{
const char *keyname;
uint8_t *value;
int value_len;
const char *algo;
const char *padding;
bool required;
int ret, i;
debug("%s %s node: '%s'\n", p, type,
fit_get_name(fit, noffset, NULL));
printf("%s %s algo: ", p, type);
if (fit_image_hash_get_algo(fit, noffset, &algo)) {
printf("invalid/unsupported\n");
return;
}
printf("%s", algo);
keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
required = fdt_getprop(fit, noffset, FIT_KEY_REQUIRED, NULL) != NULL;
if (keyname)
printf(":%s", keyname);
if (required)
printf(" (required)");
printf("\n");
padding = fdt_getprop(fit, noffset, "padding", NULL);
if (padding)
printf("%s %s padding: %s\n", p, type, padding);
ret = fit_image_hash_get_value(fit, noffset, &value,
&value_len);
printf("%s %s value: ", p, type);
if (ret) {
printf("unavailable\n");
} else {
for (i = 0; i < value_len; i++)
printf("%02x", value[i]);
printf("\n");
}
debug("%s %s len: %d\n", p, type, value_len);
/* Signatures have a time stamp */
if (IMAGE_ENABLE_TIMESTAMP && keyname) {
time_t timestamp;
printf("%s Timestamp: ", p);
if (fit_get_timestamp(fit, noffset, &timestamp))
printf("unavailable\n");
else
genimg_print_time(timestamp);
}
}
/**
* fit_image_print_verification_data() - prints out the hash/signature details
* @fit: pointer to the FIT format image header
* @noffset: offset of the hash or signature node
* @p: pointer to prefix string
*
* This lists properties for the processed hash node
*
* returns:
* no returned results
*/
static void fit_image_print_verification_data(const void *fit, int noffset,
const char *p)
{
const char *name;
/*
* Check subnode name, must be equal to "hash" or "signature".
* Multiple hash/signature nodes require unique unit node
* names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
*/
name = fit_get_name(fit, noffset, NULL);
if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
fit_image_print_data(fit, noffset, p, "Hash");
} else if (!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
fit_image_print_data(fit, noffset, p, "Sign");
}
}
/**
* fit_conf_print - prints out the FIT configuration details
* @fit: pointer to the FIT format image header
* @noffset: offset of the configuration node
* @p: pointer to prefix string
*
* fit_conf_print() lists all mandatory properties for the processed
* configuration node.
*
* returns:
* no returned results
*/
static void fit_conf_print(const void *fit, int noffset, const char *p)
{
const char *uname, *desc;
int ret, ndepth, i;
/* Mandatory properties */
ret = fit_get_desc(fit, noffset, &desc);
printf("%s Description: ", p);
if (ret)
printf("unavailable\n");
else
printf("%s\n", desc);
uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
printf("%s Kernel: ", p);
if (!uname)
printf("unavailable\n");
else
printf("%s\n", uname);
/* Optional properties */
uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
if (uname)
printf("%s Init Ramdisk: %s\n", p, uname);
uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL);
if (uname)
printf("%s Firmware: %s\n", p, uname);
for (i = 0;
uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
i, NULL), uname;
i++) {
if (!i)
printf("%s FDT: ", p);
else
printf("%s ", p);
printf("%s\n", uname);
}
uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
if (uname)
printf("%s FPGA: %s\n", p, uname);
/* Print out all of the specified loadables */
for (i = 0;
uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
i, NULL), uname;
i++) {
if (!i)
printf("%s Loadables: ", p);
else
printf("%s ", p);
printf("%s\n", uname);
}
/* Show the list of compatible strings */
for (i = 0; uname = fdt_stringlist_get(fit, noffset,
FIT_COMPATIBLE_PROP, i, NULL), uname; i++) {
if (!i)
printf("%s Compatible: ", p);
else
printf("%s ", p);
printf("%s\n", uname);
}
/* Process all hash subnodes of the component configuration node */
for (ndepth = 0, noffset = fdt_next_node(fit, noffset, &ndepth);
(noffset >= 0) && (ndepth > 0);
noffset = fdt_next_node(fit, noffset, &ndepth)) {
if (ndepth == 1) {
/* Direct child node of the component configuration node */
fit_image_print_verification_data(fit, noffset, p);
}
}
}
/**
* fit_print_contents - prints out the contents of the FIT format image
* @fit: pointer to the FIT format image header
* @p: pointer to prefix string
*
* fit_print_contents() formats a multi line FIT image contents description.
* The routine prints out FIT image properties (root node level) followed by
* the details of each component image.
*
* returns:
* no returned results
*/
void fit_print_contents(const void *fit)
{
const char *desc;
char *uname;
int images_noffset;
int confs_noffset;
int noffset;
int ndepth;
int count = 0;
int ret;
const char *p;
time_t timestamp;
if (!CONFIG_IS_ENABLED(FIT_PRINT))
return;
/* Indent string is defined in header image.h */
p = IMAGE_INDENT_STRING;
/* Root node properties */
ret = fit_get_desc(fit, 0, &desc);
printf("%sFIT description: ", p);
if (ret)
printf("unavailable\n");
else
printf("%s\n", desc);
if (IMAGE_ENABLE_TIMESTAMP) {
ret = fit_get_timestamp(fit, 0, &timestamp);
printf("%sCreated: ", p);
if (ret)
printf("unavailable\n");
else
genimg_print_time(timestamp);
}
/* Find images parent node offset */
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images_noffset < 0) {
printf("Can't find images parent node '%s' (%s)\n",
FIT_IMAGES_PATH, fdt_strerror(images_noffset));
return;
}
/* Process its subnodes, print out component images details */
for (ndepth = 0, count = 0,
noffset = fdt_next_node(fit, images_noffset, &ndepth);
(noffset >= 0) && (ndepth > 0);
noffset = fdt_next_node(fit, noffset, &ndepth)) {
if (ndepth == 1) {
/*
* Direct child node of the images parent node,
* i.e. component image node.
*/
printf("%s Image %u (%s)\n", p, count++,
fit_get_name(fit, noffset, NULL));
fit_image_print(fit, noffset, p);
}
}
/* Find configurations parent node offset */
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
if (confs_noffset < 0) {
debug("Can't get configurations parent node '%s' (%s)\n",
FIT_CONFS_PATH, fdt_strerror(confs_noffset));
return;
}
/* get default configuration unit name from default property */
uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
if (uname)
printf("%s Default Configuration: '%s'\n", p, uname);
/* Process its subnodes, print out configurations details */
for (ndepth = 0, count = 0,
noffset = fdt_next_node(fit, confs_noffset, &ndepth);
(noffset >= 0) && (ndepth > 0);
noffset = fdt_next_node(fit, noffset, &ndepth)) {
if (ndepth == 1) {
/*
* Direct child node of the configurations parent node,
* i.e. configuration node.
*/
printf("%s Configuration %u (%s)\n", p, count++,
fit_get_name(fit, noffset, NULL));
fit_conf_print(fit, noffset, p);
}
}
}
/**
* fit_image_print - prints out the FIT component image details
* @fit: pointer to the FIT format image header
* @image_noffset: offset of the component image node
* @p: pointer to prefix string
*
* fit_image_print() lists all mandatory properties for the processed component
* image. If present, hash nodes are printed out as well. Load
* address for images of type firmware is also printed out. Since the load
* address is not mandatory for firmware images, it will be output as
* "unavailable" when not present.
*
* returns:
* no returned results
*/
void fit_image_print(const void *fit, int image_noffset, const char *p)
{
uint8_t type, arch, os, comp = IH_COMP_NONE;
const char *desc;
size_t size;
ulong load, entry;
const void *data;
int noffset;
int ndepth;
int ret;
if (!CONFIG_IS_ENABLED(FIT_PRINT))
return;
/* Mandatory properties */
ret = fit_get_desc(fit, image_noffset, &desc);
printf("%s Description: ", p);
if (ret)
printf("unavailable\n");
else
printf("%s\n", desc);
if (IMAGE_ENABLE_TIMESTAMP) {
time_t timestamp;
ret = fit_get_timestamp(fit, 0, &timestamp);
printf("%s Created: ", p);
if (ret)
printf("unavailable\n");
else
genimg_print_time(timestamp);
}
fit_image_get_type(fit, image_noffset, &type);
printf("%s Type: %s\n", p, genimg_get_type_name(type));
fit_image_get_comp(fit, image_noffset, &comp);
printf("%s Compression: %s\n", p, genimg_get_comp_name(comp));
ret = fit_image_get_data(fit, image_noffset, &data, &size);
if (!tools_build()) {
printf("%s Data Start: ", p);
if (ret) {
printf("unavailable\n");
} else {
void *vdata = (void *)data;
printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
}
}
printf("%s Data Size: ", p);
if (ret)
printf("unavailable\n");
else
genimg_print_size(size);
/* Remaining, type dependent properties */
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
(type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
(type == IH_TYPE_FLATDT)) {
fit_image_get_arch(fit, image_noffset, &arch);
printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch));
}
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) ||
(type == IH_TYPE_FIRMWARE)) {
fit_image_get_os(fit, image_noffset, &os);
printf("%s OS: %s\n", p, genimg_get_os_name(os));
}
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
(type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) ||
(type == IH_TYPE_FPGA)) {
ret = fit_image_get_load(fit, image_noffset, &load);
printf("%s Load Address: ", p);
if (ret)
printf("unavailable\n");
else
printf("0x%08lx\n", load);
}
/* optional load address for FDT */
if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load))
printf("%s Load Address: 0x%08lx\n", p, load);
if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
(type == IH_TYPE_RAMDISK)) {
ret = fit_image_get_entry(fit, image_noffset, &entry);
printf("%s Entry Point: ", p);
if (ret)
printf("unavailable\n");
else
printf("0x%08lx\n", entry);
}
/* Process all hash subnodes of the component image node */
for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
(noffset >= 0) && (ndepth > 0);
noffset = fdt_next_node(fit, noffset, &ndepth)) {
if (ndepth == 1) {
/* Direct child node of the component image node */
fit_image_print_verification_data(fit, noffset, p);
}
}
}
int fit_get_desc(const void *fit, int noffset, const char **descp)
{
const char *desc;
@@ -1215,7 +798,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
sizeof(uint32_t));
if (ret) {
debug("Can't set '%s' property for '%s' node (%s)\n",
FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset),
fdt_strerror(ret));
return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
}
@@ -1352,7 +935,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
/* Process all hash subnodes of the component image node */
fdt_for_each_subnode(noffset, fit, image_noffset) {
const char *name = fit_get_name(fit, noffset, NULL);
const char *name = fit_get_name(fit, noffset);
/*
* Check subnode name, must be equal to "hash".
@@ -1393,8 +976,8 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
error:
printf(" error!\n%s for '%s' hash node in '%s' image node\n",
err_msg, fit_get_name(fit, noffset, NULL),
fit_get_name(fit, image_noffset, NULL));
err_msg, fit_get_name(fit, noffset),
fit_get_name(fit, image_noffset));
return 0;
}
@@ -1413,7 +996,7 @@ error:
*/
int fit_image_verify(const void *fit, int image_noffset)
{
const char *name = fit_get_name(fit, image_noffset, NULL);
const char *name = fit_get_name(fit, image_noffset);
const void *data;
size_t size;
char *err_msg = "";
@@ -1437,7 +1020,7 @@ int fit_image_verify(const void *fit, int image_noffset)
err:
printf("error!\n%s in '%s' image node\n", err_msg,
fit_get_name(fit, image_noffset, NULL));
fit_get_name(fit, image_noffset));
return 0;
}
@@ -1480,7 +1063,7 @@ int fit_all_image_verify(const void *fit)
* i.e. component image node.
*/
printf(" Hash(es) for Image %u (%s): ", count,
fit_get_name(fit, noffset, NULL));
fit_get_name(fit, noffset));
count++;
if (!fit_image_verify(fit, noffset))
@@ -1972,7 +1555,10 @@ int fit_get_data_conf_prop(const void *fit, const char *prop_name,
static int print_and_verify(const void *fit, int rd_noffset, int verify)
{
fit_image_print(fit, rd_noffset, " ");
struct fit_print_ctx ctx;
fit_print_init(&ctx, fit);
fit_image_print(&ctx, rd_noffset);
if (verify) {
puts(" Verifying Hash Integrity ... ");
@@ -2127,7 +1713,7 @@ static int select_from_config(const void *fit, struct bootm_headers *images,
return -ENOPKG;
}
*fit_unamep = fit_get_name(fit, noffset, NULL);
*fit_unamep = fit_get_name(fit, noffset);
return noffset;
}
@@ -2639,7 +2225,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
if (i < count) {
noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
FIT_FDT_PROP, i);
uname = fit_get_name(fit, noffset, NULL);
uname = fit_get_name(fit, noffset);
uconfig = NULL;
} else {
if (!next_config)

View File

@@ -255,7 +255,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
if (fit_image_get_load(fit, node, &load_addr)) {
if (!image_info->load_addr) {
printf("Can't load %s: No load address and no buffer\n",
fit_get_name(fit, node, NULL));
fit_get_name(fit, node));
return -ENOBUFS;
}
load_addr = image_info->load_addr;
@@ -281,7 +281,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
/* Dont bother to copy 0 byte data, but warn, though */
if (!len) {
log_warning("%s: Skip load '%s': image size is 0!\n",
__func__, fit_get_name(fit, node, NULL));
__func__, fit_get_name(fit, node));
return 0;
}
@@ -318,7 +318,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
printf("## Checking hash(es) for Image %s ... ",
fit_get_name(fit, node, NULL));
fit_get_name(fit, node));
if (!fit_image_verify_with_data(fit, node, gd_fdt_blob(), src,
length))
return -EPERM;
@@ -489,12 +489,12 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
(void *)image_info.load_addr);
if (ret) {
pr_err("failed to apply DT overlay %s\n",
fit_get_name(ctx->fit, node, NULL));
fit_get_name(ctx->fit, node));
break;
}
debug("%s: DT overlay %s applied\n", __func__,
fit_get_name(ctx->fit, node, NULL));
fit_get_name(ctx->fit, node));
}
free(tmpbuffer);
if (ret)
@@ -720,7 +720,7 @@ static int spl_simple_fit_parse(struct spl_fit_info *ctx)
if (IS_ENABLED(CONFIG_SPL_FIT_SIGNATURE)) {
printf("## Checking hash(es) for config %s ... ",
fit_get_name(ctx->fit, ctx->conf_node, NULL));
fit_get_name(ctx->fit, ctx->conf_node));
if (fit_config_verify(ctx->fit, ctx->conf_node))
return -EPERM;
puts("OK\n");

View File

@@ -278,7 +278,7 @@ got_update_file:
if (ndepth != 1)
goto next_node;
fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
fit_image_name = (char *)fit_get_name(fit, noffset);
printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) {
@@ -354,7 +354,7 @@ int fit_update(const void *fit)
if (ndepth != 1)
goto next_node;
fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
fit_image_name = (char *)fit_get_name(fit, noffset);
printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) {

View File

@@ -613,7 +613,7 @@ static int first_loading_rbf_to_buffer(struct udevice *dev,
images_noffset = fit_conf_get_prop_node_index(buffer_p,
confs_noffset,
FIT_FPGA_PROP, i);
uname = fit_get_name(buffer_p, images_noffset, NULL);
uname = fit_get_name(buffer_p, images_noffset);
if (uname) {
debug("FPGA: %s\n", uname);

View File

@@ -26,6 +26,7 @@ struct fdt_region;
#include <sys/types.h>
#include <linux/kconfig.h>
#define IMAGE_INDENT 0
#define IMAGE_INDENT_STRING ""
#define BIT(nr) (1UL << (nr))
@@ -37,6 +38,7 @@ struct fdt_region;
#include <linker_lists.h>
#include <linux/bitops.h>
#define IMAGE_INDENT 3
#define IMAGE_INDENT_STRING " "
#endif /* USE_HOSTCC */
@@ -1198,8 +1200,70 @@ int fit_parse_subimage(const char *spec, ulong addr_curr,
ulong *addr, const char **image_name);
int fit_get_subimage_count(const void *fit, int images_noffset);
/**
* struct fit_print_ctx - context for FIT printing
* @fit: pointer to the FIT format image header
* @indent: indentation level for printing
* @tab: amount of space to tab out for the label
*/
struct fit_print_ctx {
const void *fit;
int indent;
int tab;
};
/**
* fit_print_init() - initialize FIT print context
* @ctx: pointer to FIT print context to initialize
* @fit: pointer to the FIT format image header
*
* This initializes a fit_print_ctx structure with the given FIT image.
*/
void fit_print_init(struct fit_print_ctx *ctx, const void *fit);
/**
* fit_print() - prints out the contents of the FIT format image
* @ctx: pointer to FIT print context
*
* fit_print() formats a multi line FIT image contents description.
* The routine prints out FIT image properties (root node level) followed by
* the details of each component image.
*
* returns:
* no returned results
*/
void fit_print(struct fit_print_ctx *ctx);
/**
* fit_print_contents() - prints out the contents of the FIT format image
* @fit: pointer to the FIT format image header
* @p: pointer to prefix string
*
* fit_print_contents() formats a multi line FIT image contents description.
* The routine prints out FIT image properties (root node level) followed by
* the details of each component image.
*
* returns:
* no returned results
*/
void fit_print_contents(const void *fit);
void fit_image_print(const void *fit, int noffset, const char *p);
/**
* fit_image_print - prints out the FIT component image details
* @ctx: pointer to FIT print context
* @image_noffset: offset of the component image node
*
* fit_image_print() lists all mandatory properties for the processed component
* image. If present, hash nodes are printed out as well. Load
* address for images of type firmware is also printed out. Since the load
* address is not mandatory for firmware images, it will be output as
* "unavailable" when not present.
*
* returns:
* no returned results
*/
void fit_image_print(struct fit_print_ctx *ctx, int noffset);
/**
* fit_get_end - get FIT image size
@@ -1225,15 +1289,15 @@ ulong fit_get_end(const void *fit);
/**
* fit_get_name - get FIT node name
* @fit: pointer to the FIT format image header
* @noffset: node offset
*
* returns:
* NULL, on error
* pointer to node name, on success
*/
static inline const char *fit_get_name(const void *fit_hdr,
int noffset, int *len)
static inline const char *fit_get_name(const void *fit_hdr, int noffset)
{
return fdt_get_name(fit_hdr, noffset, len);
return fdt_get_name(fit_hdr, noffset, NULL);
}
/**

View File

@@ -5,6 +5,7 @@
ifdef CONFIG_UT_BOOTSTD
obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
obj-$(CONFIG_FIT) += image.o
obj-$(CONFIG_$(PHASE_)FIT_PRINT) += fit_print.o
obj-$(CONFIG_BLK_LUKS) += luks.o
obj-$(CONFIG_EXPO) += expo.o expo_common.o

191
test/boot/fit_print.c Normal file
View File

@@ -0,0 +1,191 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Test for FIT image printing
*
* Copyright 2025 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <image.h>
#include <mapmem.h>
#include <os.h>
#include <test/ut.h>
#include <linux/libfdt.h>
#include "bootstd_common.h"
/* Test fit_print_contents() output */
static int test_fit_print(struct unit_test_state *uts)
{
char fname[256];
void *fit;
void *buf;
ulong addr;
int size;
/* Load the FIT created by the Python test */
ut_assertok(os_persistent_file(fname, sizeof(fname), "test-fit.fit"));
ut_assertok(os_read_file(fname, &buf, &size));
/* Copy to address 0x10000 and print from there */
addr = 0x10000;
fit = map_sysmem(addr, size);
memcpy(fit, buf, size);
/* Print it and check output line by line */
console_record_reset_enable();
fit_print_contents(fit);
/* Check every line of output */
ut_assert_nextline(" FIT description: Test FIT image for printing");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Image 0 (kernel)");
ut_assert_nextline(" Description: Test kernel");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Kernel Image");
ut_assert_nextline(" Compression: gzip compressed");
ut_assert_nextline(" Data Start: 0x000100c4");
ut_assert_nextline(" Data Size: 327 Bytes = 327 Bytes");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" OS: Linux");
ut_assert_nextline(" Load Address: 0x01000000");
ut_assert_nextline(" Entry Point: 0x01000000");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: fad998b94ef12fdac0c347915d8b9b6069a4011399e1a2097638a2cb33244cee");
ut_assert_nextline(" Image 1 (ramdisk)");
ut_assert_nextline(" Description: Test ramdisk");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: RAMDisk Image");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x00010304");
ut_assert_nextline(" Data Size: 301 Bytes = 301 Bytes");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" OS: Linux");
ut_assert_nextline(" Load Address: 0x02000000");
ut_assert_nextline(" Entry Point: unavailable");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 53e2a65d92ad890dcd89d83a1f95ad6b8206e0e4889548b035062fc494e7f655");
ut_assert_nextline(" Image 2 (fdt-1)");
ut_assert_nextline(" Description: Test FDT 1");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Flat Device Tree");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x00010518");
ut_assert_nextline(" Data Size: 161 Bytes = 161 Bytes");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 1264bc4619a1162736fdca8e63e44a1b009fbeaaa259c356b555b91186257ffb");
ut_assert_nextline(" Image 3 (fdt-2)");
ut_assert_nextline(" Description: Test FDT 2");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Flat Device Tree");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x0001067c");
ut_assert_nextline(" Data Size: 161 Bytes = 161 Bytes");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 3a07e37c76dd48c2a17927981f0959758ac6fd0d649e2032143c5afeea9a98a4");
ut_assert_nextline(" Image 4 (firmware-1)");
ut_assert_nextline(" Description: Test Firmware 1");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Firmware");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x000107e8");
ut_assert_nextline(" Data Size: 3891 Bytes = 3.8 KiB");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" OS: Unknown OS");
ut_assert_nextline(" Load Address: unavailable");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 53f1358540a556282764ceaf2912e701d2e25902a6b069b329e57e3c59148414");
ut_assert_nextline(" Image 5 (firmware-2)");
ut_assert_nextline(" Description: Test Firmware 2");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Firmware");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x000117e8");
ut_assert_nextline(" Data Size: 3891 Bytes = 3.8 KiB");
ut_assert_nextline(" Architecture: Sandbox");
ut_assert_nextline(" OS: Unknown OS");
ut_assert_nextline(" Load Address: unavailable");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 6a12ac2283f3c9605113b5c2287e983da5671d8d0015381009d75169526676f1");
ut_assert_nextline(" Image 6 (fpga)");
ut_assert_nextline(" Description: Test FPGA");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: FPGA Image");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x000127e0");
ut_assert_nextline(" Data Size: 4291 Bytes = 4.2 KiB");
ut_assert_nextline(" Load Address: unavailable");
ut_assert_nextline(" Hash algo: sha256");
ut_assert_nextline(" Hash value: 2f588e50e95abc7f9d6afd1d5b3f2bf285cccd55efcf52f47a975dbff3265622");
ut_assert_nextline(" Image 7 (script)");
ut_assert_nextline(" Description: unavailable");
ut_assert_nextline(" Created: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Type: Script");
ut_assert_nextline(" Compression: uncompressed");
ut_assert_nextline(" Data Start: 0x0001394c");
ut_assert_nextline(" Data Size: 3791 Bytes = 3.7 KiB");
ut_assert_nextline(" Hash algo: invalid/unsupported");
ut_assert_nextline(" Default Configuration: 'conf-1'");
ut_assert_nextline(" Configuration 0 (conf-1)");
ut_assert_nextline(" Description: Test configuration");
ut_assert_nextline(" Kernel: kernel");
ut_assert_nextline(" Init Ramdisk: ramdisk");
ut_assert_nextline(" FDT: fdt-1");
ut_assert_nextline(" Compatible: vendor,board-1.0");
ut_assert_nextline(" vendor,board");
ut_assert_nextline(" Sign algo: sha256,rsa2048:test-key");
ut_assert_nextline(" Sign padding: pkcs-1.5");
ut_assert_nextlinen(" Sign value: c20f64d9bf79ddb0b1a6");
ut_assert_nextline(" Timestamp: 2009-02-13 23:31:30 UTC");
ut_assert_nextline(" Configuration 1 (conf-2)");
ut_assert_nextline(" Description: Alternate configuration");
ut_assert_nextline(" Kernel: kernel");
ut_assert_nextline(" FDT: fdt-1");
ut_assert_nextline(" fdt-2");
ut_assert_nextline(" FPGA: fpga");
ut_assert_nextline(" Loadables: firmware-1");
ut_assert_nextline(" firmware-2");
ut_assert_nextline(" Compatible: vendor,board-2.0");
ut_assert_nextline(" Configuration 2 (conf-3)");
ut_assert_nextline(" Description: unavailable");
ut_assert_nextline(" Kernel: unavailable");
ut_assert_nextline(" Loadables: script");
ut_assert_console_end();
os_free(buf);
return 0;
}
BOOTSTD_TEST(test_fit_print, UTF_CONSOLE);
/* Test fit_print_contents() with missing FIT description */
static int test_fit_print_no_desc(struct unit_test_state *uts)
{
char fname[256];
void *fit;
void *buf;
ulong addr;
int size;
/* Load the FIT created by the Python test (which deleted description) */
ut_assertok(os_persistent_file(fname, sizeof(fname), "test-fit-nodesc.fit"));
ut_assertok(os_read_file(fname, &buf, &size));
/* Copy to address 0x10000 and print from there */
addr = 0x10000;
fit = map_sysmem(addr, size);
memcpy(fit, buf, size);
/* Print it and check just the first line */
console_record_reset_enable();
fit_print_contents(fit);
/* Check the first line shows unavailable */
ut_assert_nextline(" FIT description: unavailable");
os_free(buf);
return 0;
}
BOOTSTD_TEST(test_fit_print_no_desc, UTF_CONSOLE);

View File

@@ -0,0 +1,270 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2025, Google Inc.
"""Test for FIT image printing"""
import os
import pytest
import shutil
import utils
import fit_util
# ITS for testing FIT printing with hashes, ramdisk, and multiple configs
PRINT_ITS = '''
/dts-v1/;
/ {
description = "Test FIT image for printing";
#address-cells = <1>;
images {
kernel {
description = "Test kernel";
data = /incbin/("%(kernel)s");
type = "kernel";
arch = "sandbox";
os = "linux";
compression = "gzip";
load = <0x1000000>;
entry = <0x1000000>;
hash-1 {
algo = "sha256";
};
};
ramdisk {
description = "Test ramdisk";
data = /incbin/("%(ramdisk)s");
type = "ramdisk";
arch = "sandbox";
os = "linux";
compression = "none";
load = <0x2000000>;
hash-1 {
algo = "sha256";
};
};
fdt-1 {
description = "Test FDT 1";
data = /incbin/("%(fdt1)s");
type = "flat_dt";
arch = "sandbox";
compression = "none";
hash-1 {
algo = "sha256";
};
};
fdt-2 {
description = "Test FDT 2";
data = /incbin/("%(fdt2)s");
type = "flat_dt";
arch = "sandbox";
compression = "none";
hash-1 {
algo = "sha256";
};
};
firmware-1 {
description = "Test Firmware 1";
data = /incbin/("%(firmware1)s");
type = "firmware";
arch = "sandbox";
compression = "none";
hash-1 {
algo = "sha256";
};
};
firmware-2 {
description = "Test Firmware 2";
data = /incbin/("%(firmware2)s");
type = "firmware";
arch = "sandbox";
compression = "none";
hash-1 {
algo = "sha256";
};
};
fpga {
description = "Test FPGA";
data = /incbin/("%(fpga)s");
type = "fpga";
arch = "sandbox";
compression = "none";
hash-1 {
algo = "sha256";
};
};
script {
data = /incbin/("%(script)s");
type = "script";
compression = "none";
hash-1 {
algo = "sha256";
};
};
};
configurations {
default = "conf-1";
conf-1 {
description = "Test configuration";
kernel = "kernel";
fdt = "fdt-1";
ramdisk = "ramdisk";
compatible = "vendor,board-1.0", "vendor,board";
signature {
algo = "sha256,rsa2048";
padding = "pkcs-1.5";
key-name-hint = "test-key";
sign-images = "fdt-1", "kernel", "ramdisk";
};
};
conf-2 {
description = "Alternate configuration";
kernel = "kernel";
fdt = "fdt-1", "fdt-2";
fpga = "fpga";
loadables = "firmware-1", "firmware-2";
compatible = "vendor,board-2.0";
};
conf-3 {
loadables = "script";
};
};
};
'''
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('fit')
@pytest.mark.buildconfigspec('fit_print')
@pytest.mark.requiredtool('dtc')
@pytest.mark.requiredtool('openssl')
def test_fit_print(ubman):
"""Test fit_print_contents() via C unit test"""
mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage')
# Create test files (make kernel ~6.3K)
kernel = fit_util.make_kernel(ubman, 'test-kernel.bin',
'kernel with some extra test data')
# Compress the kernel (with -n to avoid timestamps for reproducibility)
kernel_gz = kernel + '.gz'
utils.run_and_log(ubman, ['gzip', '-f', '-n', '-k', kernel])
fdt1 = fit_util.make_dtb(ubman, '''
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <0>;
model = "Test FDT 1";
};
''', 'test-fdt-1')
fdt2 = fit_util.make_dtb(ubman, '''
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <0>;
model = "Test FDT 2";
};
''', 'test-fdt-2')
firmware1 = fit_util.make_kernel(ubman, 'test-firmware-1.bin', 'firmware 1')
firmware2 = fit_util.make_kernel(ubman, 'test-firmware-2.bin', 'firmware 2')
fpga = fit_util.make_kernel(ubman, 'test-fpga.bin', 'fpga bitstream')
ramdisk = fit_util.make_kernel(ubman, 'test-ramdisk.bin', 'ramdisk')
script = fit_util.make_kernel(ubman, 'test-script.bin', 'echo test')
# Compress the ramdisk (with -n to avoid timestamps for reproducibility)
ramdisk_gz = ramdisk + '.gz'
utils.run_and_log(ubman, ['gzip', '-f', '-n', '-k', ramdisk])
# Create FIT image with fixed timestamp for reproducible output
params = {
'kernel': kernel_gz,
'fdt1': fdt1,
'fdt2': fdt2,
'firmware1': firmware1,
'firmware2': firmware2,
'fpga': fpga,
'ramdisk': ramdisk_gz,
'script': script,
}
env = os.environ.copy()
env['SOURCE_DATE_EPOCH'] = '1234567890' # 2009-02-13 23:31:30 UTC
fit = fit_util.make_fname(ubman, 'test-fit.fit')
its = fit_util.make_its(ubman, PRINT_ITS, params)
utils.run_and_log(ubman, [mkimage, '-f', its, fit], env=env)
# Use a fixed RSA key pair for reproducible signatures
tmpdir = ubman.config.result_dir + '/'
# Fixed 2048-bit RSA private key for testing (for reproducible signatures)
key_pem = '''-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDU18AB+xpQw+GX
mywzH4nsEIECgLVnBTNaAnE4XSIqbiviZetumBP6Ib2W+0OIOn8/hIh3UnzzyWIP
aRus94CVfFQPqwhi6/M9ptL7N7lCXq9DwQ0EY55GquwoO9jZnnDsCSU76jgKg+Nc
dsbvprfFDxBjkrLBfdEgzJtNUaJnUCd58RG8sII7EOP4JTGnXn2wVTsKYcTmr8y6
bOZTUQfsYj9BGFTbskkLYj1RJ6Dpzk4yBqyUn4fUYhfqsAHwlJs/64Byx2m7J7Ia
rfp49NkqgOFlTvDzKnecxGt4pmgEA+4MtRxUFDliZ/bG3TvG/xNlXvWaHp9DG05u
4h9jy2NPAgMBAAECggEAAMZKOheeWGXmF8WmSwdV2qiSt54dSuMvdSfmHpTkL3BY
M4o4aZ4fEH138ak3bTL9TI9gacLAlqiIdVLmGWKLMsARlD8EmEuQhoxpXyWsRGwQ
yjfVIst0A4DSvDC/kMctVQaRfp7TFmK1fJwoDC44o/xyjFI32VFqZeqotAbUhvi3
gIYvP5Q4Kvbaq9aZNURqazJHuEVD9LpwbnroUd4cBrcorstJzaDmTIyb5swLX+IX
FjMOVtHtBDKOG9Ce1wlEOXZtSsoZtAEgkd1IQYBCTBUDkxPdx+ZKPdfT4aKWX3S4
WQ65lDEGAnplMmetFRV+k9NNJvEia9JoX/SJqhUWGQKBgQD1/rffQZnFWqGM2dD1
CEkXpCN23xAEaZjQtuIhPMBWEWufAPZhyZSbq3eLjcqSS5mzU8B+n1c9Zxw6r0qM
BXlcUftreFPKvEXeyp1YWh7loxHiVVuasp2lEDx4arwUrI61XtAaixUb9Opxxj/x
UDrY5cj7BIRhrkDZtnor/EbRaQKBgQDdf9pymbbxRmHHFGERSzo6/gbr1GRK9fUA
ZNrzfBM5Sdvmm2aKgYd7hIKhOgeKIkS858gEOsRw75x6nvlrjZvFZGIfetXXxaN9
c6Uqq/f6rTRUTB9/SqvMgKZMuJ2SFms8I1nbxSE/PMD0T6TRbhjaFoZwZP42HVsM
wAN2Oiq/9wKBgQC7sQHyYkdFgYVJxtfcXdoHI8G7bS73buqeNSwMWCIYiWooA7/5
lKjCre2kmSc6wFwhq4FwG3ug6g9r51tlwrd6bUL8GO81/LkC6G1tgDWa2PVIUAB4
5FfMHbtF1Ypz68VnNVRrLDuK/S/0Z2NaZ/C+lXTnseaf8Sih9Mz6yp3uIQKBgBc4
61cuhH6hSWkM2uxsPaunrGQXPXiadthWupnifUV5V+PCkSqeT+0ERInQwq+Zzikc
B91hp+zLQlWcyzuaeiVk0+DHCRp5Lx3c/QkPRI10kVLxNDAtTPvA1S6gAG0rioyg
jDA9Z7Hwla5Hl1kZuONMj0XDYN+djkk07Gf9yzObAoGAbiS3mRID0pLFhWR1L64h
NlRJpZjsHNRPd0WFVxXnJRzZxkStoTwL2BhPtG3Xx1ReIkNVCxlu1Dk0rLLKl1nj
4B/X9Qu6aejXnOsbqp1/JBXYxD8l5B2yg5//wz18um/SOSagpAPeH4i/V3NxOup5
S0n8gbs0Ht/ZckLk8mPclbk=
-----END PRIVATE KEY-----'''
with open(tmpdir + 'test-key.key', 'w') as f:
f.write(key_pem)
utils.run_and_log(ubman,
f'openssl req -batch -new -x509 -key {tmpdir}test-key.key '
f'-out {tmpdir}test-key.crt')
# Create a dummy DTB for the public key
dtb = fit_util.make_fname(ubman, 'test-key.dtb')
utils.run_and_log(ubman, ['dtc', '-I', 'dts', '-O', 'dtb', '-o', dtb],
stdin=b'/dts-v1/; / { };')
# Sign the FIT configuration (use env for reproducible timestamp)
utils.run_and_log(ubman, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
'-r', fit, '-c', 'Configuration signing'], env=env)
# Delete the algo property from script's hash-1 node to test invalid/unsupported algo
utils.run_and_log(ubman, ['fdtput', '-t', 's', fit, '/images/script/hash-1', 'algo', ''])
utils.run_and_log(ubman, ['fdtput', '-d', fit, '/images/script/hash-1', 'algo'])
# Copy to persistent directory with known name
persistent_fit = os.path.join(ubman.config.persistent_data_dir,
'test-fit.fit')
shutil.copy(fit, persistent_fit)
# Run the C test which will load and verify this FIT
ubman.run_command('ut -f bootstd test_fit_print')
result = ubman.run_command('echo $?')
assert '0' == result
# Test missing FIT description by deleting it and checking the output
fit_no_desc = fit_util.make_fname(ubman, 'test-fit-nodesc.fit')
shutil.copy(fit, fit_no_desc)
utils.run_and_log(ubman, ['fdtput', '-d', fit_no_desc, '/', 'description'])
persistent_fit_no_desc = os.path.join(ubman.config.persistent_data_dir,
'test-fit-nodesc.fit')
shutil.copy(fit_no_desc, persistent_fit_no_desc)
# Run a second C test to check the missing description
ubman.run_command('ut -f bootstd test_fit_print_no_desc')
result = ubman.run_command('echo $?')
assert '0' == result

View File

@@ -72,6 +72,7 @@ hostprogs-y += file2include
endif
FIT_OBJS-y := fit_common.o fit_image.o image-host.o generated/boot/image-fit.o
FIT_OBJS-$(CONFIG_FIT_PRINT) += generated/boot/fit_print.o
FIT_SIG_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := image-sig-host.o generated/boot/image-fit-sig.o
FIT_CIPHER_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := generated/boot/image-cipher.o

View File

@@ -940,10 +940,10 @@ static int fit_extract_contents(void *ptr, struct imgtool *itl)
int ndepth;
const void *fit = ptr;
int count = 0;
const char *p;
int p;
/* Indent string is defined in header image.h */
p = IMAGE_INDENT_STRING;
/* Indent value is defined in header image.h */
p = 5;
/* Find images parent node offset */
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
@@ -971,10 +971,13 @@ static int fit_extract_contents(void *ptr, struct imgtool *itl)
* i.e. component image node.
*/
if (itl->pflag == count) {
printf("Extracted:\n%s Image %u (%s)\n", p,
count, fit_get_name(fit, noffset, NULL));
struct fit_print_ctx ctx;
fit_image_print(fit, noffset, p);
printf("Extracted:\n%*s Image %u (%s)\n", p, "",
count, fit_get_name(fit, noffset));
fit_print_init(&ctx, fit);
fit_image_print(&ctx, noffset);
return fit_image_extract(fit, noffset,
itl->outfile);

View File

@@ -98,7 +98,7 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
printf("NAME: %s\n", fit_get_name(fit_blob, nodeoffset, NULL));
printf("NAME: %s\n", fit_get_name(fit_blob, nodeoffset));
printf("LEN: %d\n", len);
printf("OFF: %d\n", (int)(nodep - fit_blob));
(void) munmap((void *)fit_blob, fsbuf.st_size);

View File

@@ -46,7 +46,7 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value,
ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
if (ret) {
fprintf(stderr, "Can't set hash '%s' property for '%s' node(%s)\n",
FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
FIT_VALUE_PROP, fit_get_name(fit, noffset),
fdt_strerror(ret));
return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
}
@@ -76,7 +76,7 @@ static int fit_image_process_hash(void *fit, const char *image_name,
const char *algo;
int ret;
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
if (fit_image_hash_get_algo(fit, noffset, &algo)) {
fprintf(stderr,
@@ -176,7 +176,7 @@ static int fit_image_setup_sig(struct image_sign_info *info,
const char *node_name;
const char *padding_name;
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
if (!algo_name) {
if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
fprintf(stderr,
@@ -247,7 +247,7 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile,
engine_id, algo_name))
return -1;
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
region.data = data;
region.size = size;
ret = info.crypto->sign(&info, &region, 1, &value, &value_len);
@@ -585,7 +585,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest,
int cipher_node_offset, len;
/* Get image name */
image_name = fit_get_name(fit, image_noffset, NULL);
image_name = fit_get_name(fit, image_noffset);
if (!image_name) {
fprintf(stderr, "Can't get image name\n");
return -1;
@@ -677,7 +677,7 @@ int fit_image_add_verification_data(const char *keydir, const char *keyfile,
return -1;
}
image_name = fit_get_name(fit, image_noffset, NULL);
image_name = fit_get_name(fit, image_noffset);
/* Process all hash subnodes of the component image node */
for (noffset = fdt_first_subnode(fit, image_noffset);
@@ -691,7 +691,7 @@ int fit_image_add_verification_data(const char *keydir, const char *keyfile,
* Multiple hash nodes require unique unit node
* names, e.g. hash-1, hash-2, signature-1, etc.
*/
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
if (!strncmp(node_name, FIT_HASH_NODENAME,
strlen(FIT_HASH_NODENAME))) {
ret = fit_image_process_hash(fit, image_name, noffset,
@@ -809,7 +809,7 @@ static int fit_config_add_hash(const void *fit, int image_noffset,
for (noffset = fdt_first_subnode(fit, image_noffset);
noffset >= 0;
noffset = fdt_next_subnode(fit, noffset)) {
const char *name = fit_get_name(fit, noffset, NULL);
const char *name = fit_get_name(fit, noffset);
if (strncmp(name, FIT_HASH_NODENAME,
strlen(FIT_HASH_NODENAME)))
@@ -884,8 +884,8 @@ static int fit_config_get_hash_list(const void *fit, int conf_noffset,
int image_count;
int ret, len;
conf_name = fit_get_name(fit, conf_noffset, NULL);
sig_name = fit_get_name(fit, sig_offset, NULL);
conf_name = fit_get_name(fit, conf_noffset);
sig_name = fit_get_name(fit, sig_offset);
/*
* Build a list of nodes we need to hash. We always need the root
@@ -991,8 +991,8 @@ static int fit_config_get_regions(const void *fit, int conf_noffset,
char *region_prop;
int ret, len;
conf_name = fit_get_name(fit, conf_noffset, NULL);
sig_name = fit_get_name(fit, sig_offset, NULL);
conf_name = fit_get_name(fit, conf_noffset);
sig_name = fit_get_name(fit, sig_offset);
debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
/* Get a list of nodes we want to hash */
@@ -1084,7 +1084,7 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile,
uint value_len;
int ret;
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
if (fit_config_get_regions(fit, conf_noffset, noffset, &region,
&region_count, &region_prop,
&region_proplen))
@@ -1148,7 +1148,7 @@ static int fit_config_add_verification_data(const char *keydir,
const char *conf_name;
int noffset;
conf_name = fit_get_name(fit, conf_noffset, NULL);
conf_name = fit_get_name(fit, conf_noffset);
/* Process all hash subnodes of the configuration node */
for (noffset = fdt_first_subnode(fit, conf_noffset);
@@ -1157,7 +1157,7 @@ static int fit_config_add_verification_data(const char *keydir,
const char *node_name;
int ret = 0;
node_name = fit_get_name(fit, noffset, NULL);
node_name = fit_get_name(fit, noffset);
if (!strncmp(node_name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
ret = fit_config_process_sig(keydir, keyfile, keydest,