More tests and fixes for fdt command
binman signing feature fix buildman -A bug introduced recently -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmQQ8KIRHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIreYRmwgA1XAHafEOfhaya54nalUgW9qYZe5Ntfqd 4Tg7zj3gadZuv82LuyskEyBKptwRCzgX0Tyx62V3Oop9vJ/cCwjIB4AGhCsMKERf NqcMd8fbGbJ9jJzOp7gNTHzV4vSmwKM0lRkxbClMFcvMsfVdKcBRPswLLghk5/xL Uu4Ww4yfe7UCqgBm9uouVaIbcNNcl8p0QnSJT9HvwjGKawPT6uSHOHK9Wpkud0q1 ZyrPpCMA29mifhIU8aH5CJH5G61UbGcVSDhm9lIKwqZg+KJGuYf64JbZoY9JI2/z pOUHLZx7fVHoFyWKWfVkA9l6HRjZTRc0nJhYFx5HyNUOU50hMENeTQ== =ko2P -----END PGP SIGNATURE----- Merge tag 'dm-next-12mar23a' of git://git.denx.de/u-boot-dm into next More tests and fixes for fdt command binman signing feature fix buildman -A bug introduced recently Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
commit
cb90ddb2a6
25 changed files with 1155 additions and 84 deletions
|
@ -478,7 +478,7 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|||
/* Get address */
|
||||
char buf[19];
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%lx",
|
||||
snprintf(buf, sizeof(buf), "%lx",
|
||||
(ulong)map_to_sysmem(nodep));
|
||||
env_set(var, buf);
|
||||
} else if (subcmd[0] == 's') {
|
||||
|
|
|
@ -842,7 +842,7 @@ int console_record_readline(char *str, int maxlen)
|
|||
return -ENOSPC;
|
||||
|
||||
return membuff_readline((struct membuff *)&gd->console_out, str,
|
||||
maxlen, ' ');
|
||||
maxlen, '\0');
|
||||
}
|
||||
|
||||
int console_record_avail(void)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <command.h>
|
||||
#include <console.h>
|
||||
#include <env.h>
|
||||
#include <fdtdec.h>
|
||||
#include <init.h>
|
||||
#include <net.h>
|
||||
#include <version_string.h>
|
||||
|
|
|
@ -125,36 +125,47 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes);
|
|||
fmt, ##args)
|
||||
|
||||
/* Assert that a condition is non-zero */
|
||||
#define ut_assert(cond) \
|
||||
#define ut_assert(cond) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (!(cond)) { \
|
||||
ut_fail(uts, __FILE__, __LINE__, __func__, #cond); \
|
||||
return CMD_RET_FAILURE; \
|
||||
}
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that a condition is non-zero, with printf() string */
|
||||
#define ut_assertf(cond, fmt, args...) \
|
||||
#define ut_assertf(cond, fmt, args...) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (!(cond)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, #cond, \
|
||||
fmt, ##args); \
|
||||
return CMD_RET_FAILURE; \
|
||||
}
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two int expressions are equal */
|
||||
#define ut_asserteq(expr1, expr2) { \
|
||||
#define ut_asserteq(expr1, expr2) ({ \
|
||||
unsigned int _val1 = (expr1), _val2 = (expr2); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (_val1 != _val2) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr1 " == " #expr2, \
|
||||
"Expected %#x (%d), got %#x (%d)", \
|
||||
_val1, _val1, _val2, _val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two 64 int expressions are equal */
|
||||
#define ut_asserteq_64(expr1, expr2) { \
|
||||
#define ut_asserteq_64(expr1, expr2) ({ \
|
||||
u64 _val1 = (expr1), _val2 = (expr2); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (_val1 != _val2) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
|
@ -164,43 +175,49 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes);
|
|||
(unsigned long long)_val1, \
|
||||
(unsigned long long)_val2, \
|
||||
(unsigned long long)_val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two string expressions are equal */
|
||||
#define ut_asserteq_str(expr1, expr2) { \
|
||||
#define ut_asserteq_str(expr1, expr2) ({ \
|
||||
const char *_val1 = (expr1), *_val2 = (expr2); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (strcmp(_val1, _val2)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr1 " = " #expr2, \
|
||||
"Expected \"%s\", got \"%s\"", _val1, _val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Assert that two string expressions are equal, up to length of the
|
||||
* first
|
||||
*/
|
||||
#define ut_asserteq_strn(expr1, expr2) { \
|
||||
#define ut_asserteq_strn(expr1, expr2) ({ \
|
||||
const char *_val1 = (expr1), *_val2 = (expr2); \
|
||||
int _len = strlen(_val1); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (memcmp(_val1, _val2, _len)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr1 " = " #expr2, \
|
||||
"Expected \"%.*s\", got \"%.*s\"", \
|
||||
_len, _val1, _len, _val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two memory areas are equal */
|
||||
#define ut_asserteq_mem(expr1, expr2, len) { \
|
||||
#define ut_asserteq_mem(expr1, expr2, len) ({ \
|
||||
const u8 *_val1 = (u8 *)(expr1), *_val2 = (u8 *)(expr2); \
|
||||
const uint __len = len; \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (memcmp(_val1, _val2, __len)) { \
|
||||
char __buf1[64 + 1] = "\0"; \
|
||||
|
@ -211,128 +228,163 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes);
|
|||
#expr1 " = " #expr2, \
|
||||
"Expected \"%s\", got \"%s\"", \
|
||||
__buf1, __buf2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two pointers are equal */
|
||||
#define ut_asserteq_ptr(expr1, expr2) { \
|
||||
#define ut_asserteq_ptr(expr1, expr2) ({ \
|
||||
const void *_val1 = (expr1), *_val2 = (expr2); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (_val1 != _val2) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr1 " = " #expr2, \
|
||||
"Expected %p, got %p", _val1, _val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that two addresses (converted from pointers) are equal */
|
||||
#define ut_asserteq_addr(expr1, expr2) { \
|
||||
#define ut_asserteq_addr(expr1, expr2) ({ \
|
||||
ulong _val1 = map_to_sysmem(expr1); \
|
||||
ulong _val2 = map_to_sysmem(expr2); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (_val1 != _val2) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr1 " = " #expr2, \
|
||||
"Expected %lx, got %lx", _val1, _val2); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that a pointer is NULL */
|
||||
#define ut_assertnull(expr) { \
|
||||
#define ut_assertnull(expr) ({ \
|
||||
const void *_val = (expr); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (_val) { \
|
||||
if (_val) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr " != NULL", \
|
||||
"Expected NULL, got %p", _val); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that a pointer is not NULL */
|
||||
#define ut_assertnonnull(expr) { \
|
||||
#define ut_assertnonnull(expr) ({ \
|
||||
const void *_val = (expr); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (!_val) { \
|
||||
if (!_val) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr " = NULL", \
|
||||
"Expected non-null, got NULL"); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that a pointer is not an error pointer */
|
||||
#define ut_assertok_ptr(expr) { \
|
||||
#define ut_assertok_ptr(expr) ({ \
|
||||
const void *_val = (expr); \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (IS_ERR(_val)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
#expr " = NULL", \
|
||||
"Expected pointer, got error %ld", \
|
||||
PTR_ERR(_val)); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
}
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that an operation succeeds (returns 0) */
|
||||
#define ut_assertok(cond) ut_asserteq(0, cond)
|
||||
|
||||
/* Assert that the next console output line matches */
|
||||
#define ut_assert_nextline(fmt, args...) \
|
||||
#define ut_assert_nextline(fmt, args...) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_console_line(uts, fmt, ##args)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", "\nExpected '%s',\n got '%s'", \
|
||||
uts->expect_str, uts->actual_str); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that the next console output line matches up to the length */
|
||||
#define ut_assert_nextlinen(fmt, args...) \
|
||||
#define ut_assert_nextlinen(fmt, args...) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_console_linen(uts, fmt, ##args)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", "\nExpected '%s',\n got '%s'", \
|
||||
uts->expect_str, uts->actual_str); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that there is a 'next' console output line, and skip it */
|
||||
#define ut_assert_skipline() \
|
||||
#define ut_assert_skipline() ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_skipline(uts)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", "\nExpected a line, got end"); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that a following console output line matches */
|
||||
#define ut_assert_skip_to_line(fmt, args...) \
|
||||
#define ut_assert_skip_to_line(fmt, args...) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_skip_to_line(uts, fmt, ##args)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", "\nExpected '%s',\n got to '%s'", \
|
||||
uts->expect_str, uts->actual_str); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that there is no more console output */
|
||||
#define ut_assert_console_end() \
|
||||
#define ut_assert_console_end() ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_console_end(uts)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", "Expected no more output, got '%s'",\
|
||||
uts->actual_str); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that the next lines are print_buffer() dump at an address */
|
||||
#define ut_assert_nextlines_are_dump(total_bytes) \
|
||||
#define ut_assert_nextlines_are_dump(total_bytes) ({ \
|
||||
int __ret = 0; \
|
||||
\
|
||||
if (ut_check_console_dump(uts, total_bytes)) { \
|
||||
ut_failf(uts, __FILE__, __LINE__, __func__, \
|
||||
"console", \
|
||||
"Expected dump of length %x bytes, got '%s'", \
|
||||
total_bytes, uts->actual_str); \
|
||||
return CMD_RET_FAILURE; \
|
||||
__ret = CMD_RET_FAILURE; \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/* Assert that the next console output line is empty */
|
||||
#define ut_assert_nextline_empty() \
|
||||
|
|
562
test/cmd/fdt.c
562
test/cmd/fdt.c
|
@ -303,6 +303,149 @@ static int fdt_test_resize(struct unit_test_state *uts)
|
|||
}
|
||||
FDT_TEST(fdt_test_resize, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_print_list_common(struct unit_test_state *uts,
|
||||
const char *opc, const char *node)
|
||||
{
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* subnode $node/subnode
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s/subnode", opc, node));
|
||||
ut_assert_nextline("subnode {");
|
||||
ut_assert_nextline("\t#address-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\t#size-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\tcompatible = \"u-boot,fdt-subnode-test-device\";");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path / string property model
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s / model", opc));
|
||||
ut_assert_nextline("model = \"U-Boot FDT test\"");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path $node string property compatible
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s compatible", opc, node));
|
||||
ut_assert_nextline("compatible = \"u-boot,fdt-test-device1\"");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path $node stringlist property clock-names
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s clock-names", opc, node));
|
||||
ut_assert_nextline("clock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\"");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path $node u32 property clock-frequency
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s clock-frequency", opc, node));
|
||||
ut_assert_nextline("clock-frequency = <0x00fde800>");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path $node empty property u-boot,empty-property
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s u-boot,empty-property", opc, node));
|
||||
/*
|
||||
* This is the only 'fdt print' / 'fdt list' incantation which
|
||||
* prefixes the property with node path. This has been in U-Boot
|
||||
* since the beginning of the command 'fdt', keep it.
|
||||
*/
|
||||
ut_assert_nextline("%s u-boot,empty-property", node);
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Test printing/listing the working FDT
|
||||
* path $node prop-encoded array property regs
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s %s regs", opc, node));
|
||||
ut_assert_nextline("regs = <0x00001234 0x00001000>");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_test_print_list(struct unit_test_state *uts, bool print)
|
||||
{
|
||||
const char *opc = print ? "print" : "list";
|
||||
char fdt[4096];
|
||||
ulong addr;
|
||||
int ret;
|
||||
|
||||
/* Original source DT */
|
||||
ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt)));
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Test printing/listing the working FDT -- node / */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt %s", opc));
|
||||
ut_assert_nextline("/ {");
|
||||
ut_assert_nextline("\t#address-cells = <0x00000001>;");
|
||||
ut_assert_nextline("\t#size-cells = <0x00000001>;");
|
||||
ut_assert_nextline("\tcompatible = \"u-boot,fdt-test\";");
|
||||
ut_assert_nextline("\tmodel = \"U-Boot FDT test\";");
|
||||
ut_assert_nextline("\taliases {");
|
||||
if (print) {
|
||||
ut_assert_nextline("\t\tbadalias = \"/bad/alias\";");
|
||||
ut_assert_nextline("\t\tsubnodealias = \"/test-node@1234/subnode\";");
|
||||
ut_assert_nextline("\t\ttestnodealias = \"/test-node@1234\";");
|
||||
}
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("\ttest-node@1234 {");
|
||||
if (print) {
|
||||
ut_assert_nextline("\t\t#address-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\t\t#size-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\t\tcompatible = \"u-boot,fdt-test-device1\";");
|
||||
ut_assert_nextline("\t\tclock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\";");
|
||||
ut_assert_nextline("\t\tu-boot,empty-property;");
|
||||
ut_assert_nextline("\t\tclock-frequency = <0x00fde800>;");
|
||||
ut_assert_nextline("\t\tregs = <0x00001234 0x00001000>;");
|
||||
ut_assert_nextline("\t\tsubnode {");
|
||||
ut_assert_nextline("\t\t\t#address-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\t\t\t#size-cells = <0x00000000>;");
|
||||
ut_assert_nextline("\t\t\tcompatible = \"u-boot,fdt-subnode-test-device\";");
|
||||
ut_assert_nextline("\t\t};");
|
||||
}
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
ret = fdt_test_print_list_common(uts, opc, "/test-node@1234");
|
||||
if (!ret)
|
||||
ret = fdt_test_print_list_common(uts, opc, "testnodealias");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_test_print(struct unit_test_state *uts)
|
||||
{
|
||||
return fdt_test_print_list(uts, true);
|
||||
}
|
||||
FDT_TEST(fdt_test_print, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_list(struct unit_test_state *uts)
|
||||
{
|
||||
return fdt_test_print_list(uts, false);
|
||||
}
|
||||
FDT_TEST(fdt_test_list, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
/* Test 'fdt get value' reading an fdt */
|
||||
static int fdt_test_get_value_string(struct unit_test_state *uts,
|
||||
const char *node, const char *prop,
|
||||
|
@ -653,23 +796,21 @@ static int fdt_test_set_single(struct unit_test_state *uts,
|
|||
* => fdt set /path property
|
||||
*/
|
||||
ut_assertok(console_record_reset_enable());
|
||||
if (sval) {
|
||||
if (sval)
|
||||
ut_assertok(run_commandf("fdt set %s %s %s", path, prop, sval));
|
||||
} else if (integer) {
|
||||
else if (integer)
|
||||
ut_assertok(run_commandf("fdt set %s %s <%d>", path, prop, ival));
|
||||
} else {
|
||||
else
|
||||
ut_assertok(run_commandf("fdt set %s %s", path, prop));
|
||||
}
|
||||
|
||||
/* Validate the property is present and has correct value. */
|
||||
ut_assertok(run_commandf("fdt get value svar %s %s", path, prop));
|
||||
if (sval) {
|
||||
if (sval)
|
||||
ut_asserteq_str(sval, env_get("svar"));
|
||||
} else if (integer) {
|
||||
else if (integer)
|
||||
ut_asserteq(ival, env_get_hex("svar", 0x1234));
|
||||
} else {
|
||||
else
|
||||
ut_assertnull(env_get("svar"));
|
||||
}
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
|
@ -971,6 +1112,411 @@ static int fdt_test_bootcpu(struct unit_test_state *uts)
|
|||
}
|
||||
FDT_TEST(fdt_test_bootcpu, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_header_get(struct unit_test_state *uts,
|
||||
const char *field, const unsigned long val)
|
||||
{
|
||||
/* Test getting valid header entry */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt header get fvar %s", field));
|
||||
ut_asserteq(val, env_get_hex("fvar", 0x1234));
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test getting malformed header entry */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_asserteq(1, run_commandf("fdt header get fvar typo%stypo", field));
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_test_header(struct unit_test_state *uts)
|
||||
{
|
||||
char fdt[256];
|
||||
ulong addr;
|
||||
|
||||
ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt)));
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Test header print */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt header"));
|
||||
ut_assert_nextline("magic:\t\t\t0x%x", fdt_magic(fdt));
|
||||
ut_assert_nextline("totalsize:\t\t0x%x (%d)", fdt_totalsize(fdt), fdt_totalsize(fdt));
|
||||
ut_assert_nextline("off_dt_struct:\t\t0x%x", fdt_off_dt_struct(fdt));
|
||||
ut_assert_nextline("off_dt_strings:\t\t0x%x", fdt_off_dt_strings(fdt));
|
||||
ut_assert_nextline("off_mem_rsvmap:\t\t0x%x", fdt_off_mem_rsvmap(fdt));
|
||||
ut_assert_nextline("version:\t\t%d", fdt_version(fdt));
|
||||
ut_assert_nextline("last_comp_version:\t%d", fdt_last_comp_version(fdt));
|
||||
ut_assert_nextline("boot_cpuid_phys:\t0x%x", fdt_boot_cpuid_phys(fdt));
|
||||
ut_assert_nextline("size_dt_strings:\t0x%x", fdt_size_dt_strings(fdt));
|
||||
ut_assert_nextline("size_dt_struct:\t\t0x%x", fdt_size_dt_struct(fdt));
|
||||
ut_assert_nextline("number mem_rsv:\t\t0x%x", fdt_num_mem_rsv(fdt));
|
||||
ut_assert_nextline_empty();
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test header get */
|
||||
fdt_test_header_get(uts, "magic", fdt_magic(fdt));
|
||||
fdt_test_header_get(uts, "totalsize", fdt_totalsize(fdt));
|
||||
fdt_test_header_get(uts, "off_dt_struct", fdt_off_dt_struct(fdt));
|
||||
fdt_test_header_get(uts, "off_dt_strings", fdt_off_dt_strings(fdt));
|
||||
fdt_test_header_get(uts, "off_mem_rsvmap", fdt_off_mem_rsvmap(fdt));
|
||||
fdt_test_header_get(uts, "version", fdt_version(fdt));
|
||||
fdt_test_header_get(uts, "last_comp_version", fdt_last_comp_version(fdt));
|
||||
fdt_test_header_get(uts, "boot_cpuid_phys", fdt_boot_cpuid_phys(fdt));
|
||||
fdt_test_header_get(uts, "size_dt_strings", fdt_size_dt_strings(fdt));
|
||||
fdt_test_header_get(uts, "size_dt_struct", fdt_size_dt_struct(fdt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
FDT_TEST(fdt_test_header, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_memory_cells(struct unit_test_state *uts,
|
||||
const unsigned int cells)
|
||||
{
|
||||
unsigned char *pada, *pads;
|
||||
unsigned char *seta, *sets;
|
||||
char fdt[8192];
|
||||
const int size = sizeof(fdt);
|
||||
fdt32_t *regs;
|
||||
ulong addr;
|
||||
char *spc;
|
||||
int i;
|
||||
|
||||
/* Create DT with node /memory { regs = <0x100 0x200>; } and #*cells */
|
||||
ut_assertnonnull(regs = calloc(2 * cells, sizeof(*regs)));
|
||||
ut_assertnonnull(pada = calloc(12, cells));
|
||||
ut_assertnonnull(pads = calloc(12, cells));
|
||||
ut_assertnonnull(seta = calloc(12, cells));
|
||||
ut_assertnonnull(sets = calloc(12, cells));
|
||||
for (i = cells; i >= 1; i--) {
|
||||
regs[cells - 1] = cpu_to_fdt32(i * 0x10000);
|
||||
regs[(cells * 2) - 1] = cpu_to_fdt32(~i);
|
||||
snprintf(seta + (8 * (cells - i)), 9, "%08x", i * 0x10000);
|
||||
snprintf(sets + (8 * (cells - i)), 9, "%08x", ~i);
|
||||
spc = (i != 1) ? " " : "";
|
||||
snprintf(pada + (11 * (cells - i)), 12, "0x%08x%s", i * 0x10000, spc);
|
||||
snprintf(pads + (11 * (cells - i)), 12, "0x%08x%s", ~i, spc);
|
||||
}
|
||||
|
||||
ut_assertok(fdt_create(fdt, size));
|
||||
ut_assertok(fdt_finish_reservemap(fdt));
|
||||
ut_assert(fdt_begin_node(fdt, "") >= 0);
|
||||
ut_assertok(fdt_property_u32(fdt, "#address-cells", cells));
|
||||
ut_assertok(fdt_property_u32(fdt, "#size-cells", cells));
|
||||
ut_assert(fdt_begin_node(fdt, "memory") >= 0);
|
||||
ut_assertok(fdt_property_string(fdt, "device_type", "memory"));
|
||||
ut_assertok(fdt_property(fdt, "reg", ®s, cells * 2));
|
||||
ut_assertok(fdt_end_node(fdt));
|
||||
ut_assertok(fdt_end_node(fdt));
|
||||
ut_assertok(fdt_finish(fdt));
|
||||
fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Test updating the memory node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt memory 0x%s 0x%s", seta, sets));
|
||||
ut_assertok(run_commandf("fdt print /memory"));
|
||||
ut_assert_nextline("memory {");
|
||||
ut_assert_nextline("\tdevice_type = \"memory\";");
|
||||
ut_assert_nextline("\treg = <%s %s>;", pada, pads);
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
free(sets);
|
||||
free(seta);
|
||||
free(pads);
|
||||
free(pada);
|
||||
free(regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_test_memory(struct unit_test_state *uts)
|
||||
{
|
||||
/*
|
||||
* Test memory fixup for 32 and 64 bit systems, anything bigger is
|
||||
* so far unsupported and fails because of simple_stroull() being
|
||||
* 64bit tops in the 'fdt memory' command implementation.
|
||||
*/
|
||||
fdt_test_memory_cells(uts, 1);
|
||||
fdt_test_memory_cells(uts, 2);
|
||||
|
||||
/*
|
||||
* The 'fdt memory' command is limited to /memory node, it does
|
||||
* not support any other valid DT memory node format, which is
|
||||
* either one or multiple /memory@adresss nodes. Therefore, this
|
||||
* DT variant is not tested here.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
FDT_TEST(fdt_test_memory, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_rsvmem(struct unit_test_state *uts)
|
||||
{
|
||||
char fdt[8192];
|
||||
ulong addr;
|
||||
|
||||
ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt)));
|
||||
fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
|
||||
fdt_add_mem_rsv(fdt, 0x42, 0x1701);
|
||||
fdt_add_mem_rsv(fdt, 0x74656, 0x9);
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Test default reserved memory node presence */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt rsvmem print"));
|
||||
ut_assert_nextline("index\t\t start\t\t size");
|
||||
ut_assert_nextline("------------------------------------------------");
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x42, 0x1701);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x74656, 0x9);
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test add new reserved memory node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt rsvmem add 0x1234 0x5678"));
|
||||
ut_assertok(run_commandf("fdt rsvmem print"));
|
||||
ut_assert_nextline("index\t\t start\t\t size");
|
||||
ut_assert_nextline("------------------------------------------------");
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x42, 0x1701);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x74656, 0x9);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 2, 0x1234, 0x5678);
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test delete reserved memory node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt rsvmem delete 0"));
|
||||
ut_assertok(run_commandf("fdt rsvmem print"));
|
||||
ut_assert_nextline("index\t\t start\t\t size");
|
||||
ut_assert_nextline("------------------------------------------------");
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x74656, 0x9);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x1234, 0x5678);
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test re-add new reserved memory node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt rsvmem add 0x42 0x1701"));
|
||||
ut_assertok(run_commandf("fdt rsvmem print"));
|
||||
ut_assert_nextline("index\t\t start\t\t size");
|
||||
ut_assert_nextline("------------------------------------------------");
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x74656, 0x9);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x1234, 0x5678);
|
||||
ut_assert_nextline(" %x\t%016x\t%016x", 2, 0x42, 0x1701);
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test delete nonexistent reserved memory node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_asserteq(1, run_commandf("fdt rsvmem delete 10"));
|
||||
ut_assert_nextline("libfdt fdt_del_mem_rsv(): FDT_ERR_NOTFOUND");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
}
|
||||
FDT_TEST(fdt_test_rsvmem, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_chosen(struct unit_test_state *uts)
|
||||
{
|
||||
const char *env_bootargs = env_get("bootargs");
|
||||
char fdt[8192];
|
||||
ulong addr;
|
||||
|
||||
ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt)));
|
||||
fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Test default chosen node presence, fail as there is no /chosen node */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_asserteq(1, run_commandf("fdt print /chosen"));
|
||||
ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test add new chosen node without initrd */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt chosen"));
|
||||
ut_assertok(run_commandf("fdt print /chosen"));
|
||||
ut_assert_nextline("chosen {");
|
||||
ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
|
||||
if (env_bootargs)
|
||||
ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test add new chosen node with initrd */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt chosen 0x1234 0x5678"));
|
||||
ut_assertok(run_commandf("fdt print /chosen"));
|
||||
ut_assert_nextline("chosen {");
|
||||
ut_assert_nextline("\tlinux,initrd-end = <0x%08x 0x%08x>;",
|
||||
upper_32_bits(0x1234 + 0x5678 - 1),
|
||||
lower_32_bits(0x1234 + 0x5678 - 1));
|
||||
ut_assert_nextline("\tlinux,initrd-start = <0x%08x 0x%08x>;",
|
||||
upper_32_bits(0x1234), lower_32_bits(0x1234));
|
||||
ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
|
||||
if (env_bootargs)
|
||||
ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
}
|
||||
FDT_TEST(fdt_test_chosen, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
static int fdt_test_apply(struct unit_test_state *uts)
|
||||
{
|
||||
char fdt[8192], fdto[8192];
|
||||
ulong addr, addro;
|
||||
|
||||
/* Create base DT with __symbols__ node */
|
||||
ut_assertok(fdt_create(fdt, sizeof(fdt)));
|
||||
ut_assertok(fdt_finish_reservemap(fdt));
|
||||
ut_assert(fdt_begin_node(fdt, "") >= 0);
|
||||
ut_assert(fdt_begin_node(fdt, "__symbols__") >= 0);
|
||||
ut_assertok(fdt_end_node(fdt));
|
||||
ut_assertok(fdt_end_node(fdt));
|
||||
ut_assertok(fdt_finish(fdt));
|
||||
fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
|
||||
addr = map_to_sysmem(fdt);
|
||||
set_working_fdt_addr(addr);
|
||||
|
||||
/* Create DTO which adds single property to root node / */
|
||||
ut_assertok(fdt_create(fdto, sizeof(fdto)));
|
||||
ut_assertok(fdt_finish_reservemap(fdto));
|
||||
ut_assert(fdt_begin_node(fdto, "") >= 0);
|
||||
ut_assert(fdt_begin_node(fdto, "fragment") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "target-path", "/"));
|
||||
ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "newstring", "newvalue"));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_finish(fdto));
|
||||
addro = map_to_sysmem(fdto);
|
||||
|
||||
/* Test default DT print */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt print /"));
|
||||
ut_assert_nextline("/ {");
|
||||
ut_assert_nextline("\t__symbols__ {");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/* Test simple DTO application */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt apply 0x%08x", addro));
|
||||
ut_assertok(run_commandf("fdt print /"));
|
||||
ut_assert_nextline("/ {");
|
||||
ut_assert_nextline("\tnewstring = \"newvalue\";");
|
||||
ut_assert_nextline("\t__symbols__ {");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Create complex DTO which:
|
||||
* - modifies newstring property in root node /
|
||||
* - adds new properties to root node /
|
||||
* - adds new subnode with properties to root node /
|
||||
* - adds phandle to the subnode and therefore __symbols__ node
|
||||
*/
|
||||
ut_assertok(fdt_create(fdto, sizeof(fdto)));
|
||||
ut_assertok(fdt_finish_reservemap(fdto));
|
||||
ut_assert(fdt_begin_node(fdto, "") >= 0);
|
||||
ut_assertok(fdt_property_cell(fdto, "#address-cells", 1));
|
||||
ut_assertok(fdt_property_cell(fdto, "#size-cells", 0));
|
||||
|
||||
ut_assert(fdt_begin_node(fdto, "fragment@0") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "target-path", "/"));
|
||||
ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "newstring", "newervalue"));
|
||||
ut_assertok(fdt_property_u32(fdto, "newu32", 0x12345678));
|
||||
ut_assertok(fdt_property(fdto, "empty-property", NULL, 0));
|
||||
ut_assert(fdt_begin_node(fdto, "subnode") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "subnewstring", "newervalue"));
|
||||
ut_assertok(fdt_property_u32(fdto, "subnewu32", 0x12345678));
|
||||
ut_assertok(fdt_property(fdto, "subempty-property", NULL, 0));
|
||||
ut_assertok(fdt_property_u32(fdto, "phandle", 0x01));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
|
||||
ut_assert(fdt_begin_node(fdto, "__symbols__") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "subnodephandle", "/fragment@0/__overlay__/subnode"));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_finish(fdto));
|
||||
addro = map_to_sysmem(fdto);
|
||||
|
||||
/* Test complex DTO application */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt apply 0x%08x", addro));
|
||||
ut_assertok(run_commandf("fdt print /"));
|
||||
ut_assert_nextline("/ {");
|
||||
ut_assert_nextline("\tempty-property;");
|
||||
ut_assert_nextline("\tnewu32 = <0x12345678>;");
|
||||
ut_assert_nextline("\tnewstring = \"newervalue\";");
|
||||
ut_assert_nextline("\tsubnode {");
|
||||
ut_assert_nextline("\t\tphandle = <0x00000001>;");
|
||||
ut_assert_nextline("\t\tsubempty-property;");
|
||||
ut_assert_nextline("\t\tsubnewu32 = <0x12345678>;");
|
||||
ut_assert_nextline("\t\tsubnewstring = \"newervalue\";");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("\t__symbols__ {");
|
||||
ut_assert_nextline("\t\tsubnodephandle = \"/subnode\";");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
/*
|
||||
* Create complex DTO which:
|
||||
* - modifies subnewu32 property in subnode via phandle and uses __fixups__ node
|
||||
*/
|
||||
ut_assertok(fdt_create(fdto, sizeof(fdto)));
|
||||
ut_assertok(fdt_finish_reservemap(fdto));
|
||||
ut_assert(fdt_begin_node(fdto, "") >= 0);
|
||||
ut_assertok(fdt_property_cell(fdto, "#address-cells", 1));
|
||||
ut_assertok(fdt_property_cell(fdto, "#size-cells", 0));
|
||||
|
||||
ut_assert(fdt_begin_node(fdto, "fragment@0") >= 0);
|
||||
ut_assertok(fdt_property_u32(fdto, "target", 0xffffffff));
|
||||
ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
|
||||
ut_assertok(fdt_property_u32(fdto, "subnewu32", 0xabcdef01));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
|
||||
ut_assert(fdt_begin_node(fdto, "__fixups__") >= 0);
|
||||
ut_assertok(fdt_property_string(fdto, "subnodephandle", "/fragment@0:target:0"));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_end_node(fdto));
|
||||
ut_assertok(fdt_finish(fdto));
|
||||
addro = map_to_sysmem(fdto);
|
||||
|
||||
/* Test complex DTO application */
|
||||
ut_assertok(console_record_reset_enable());
|
||||
ut_assertok(run_commandf("fdt apply 0x%08x", addro));
|
||||
ut_assertok(run_commandf("fdt print /"));
|
||||
ut_assert_nextline("/ {");
|
||||
ut_assert_nextline("\tempty-property;");
|
||||
ut_assert_nextline("\tnewu32 = <0x12345678>;");
|
||||
ut_assert_nextline("\tnewstring = \"newervalue\";");
|
||||
ut_assert_nextline("\tsubnode {");
|
||||
ut_assert_nextline("\t\tphandle = <0x00000001>;");
|
||||
ut_assert_nextline("\t\tsubempty-property;");
|
||||
ut_assert_nextline("\t\tsubnewu32 = <0xabcdef01>;");
|
||||
ut_assert_nextline("\t\tsubnewstring = \"newervalue\";");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("\t__symbols__ {");
|
||||
ut_assert_nextline("\t\tsubnodephandle = \"/subnode\";");
|
||||
ut_assert_nextline("\t};");
|
||||
ut_assert_nextline("};");
|
||||
ut_assertok(ut_check_console_end(uts));
|
||||
|
||||
return 0;
|
||||
}
|
||||
FDT_TEST(fdt_test_apply, UT_TESTF_CONSOLE_REC);
|
||||
|
||||
int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test);
|
||||
|
|
|
@ -27,11 +27,11 @@ static int dm_test_pwm_cmd(struct unit_test_state *uts)
|
|||
/* pwm <invert> <pwm_dev_num> <channel> <polarity> */
|
||||
/* cros-ec-pwm doesn't support invert */
|
||||
ut_asserteq(1, run_command("pwm invert 0 0 1", 0));
|
||||
ut_assert_nextline("error(-38)")
|
||||
ut_assert_nextline("error(-38)");
|
||||
ut_assert_console_end();
|
||||
|
||||
ut_asserteq(1, run_command("pwm invert 0 0 0", 0));
|
||||
ut_assert_nextline("error(-38)")
|
||||
ut_assert_nextline("error(-38)");
|
||||
ut_assert_console_end();
|
||||
|
||||
/* pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns> */
|
||||
|
|
|
@ -1083,7 +1083,7 @@ static int dm_test_acpi_write_name(struct unit_test_state *uts)
|
|||
ut_asserteq(NAME_OP, *ptr++);
|
||||
ptr += 10;
|
||||
ut_asserteq(STRING_PREFIX, *ptr++);
|
||||
ut_asserteq_str("baldrick", (char *)ptr)
|
||||
ut_asserteq_str("baldrick", (char *)ptr);
|
||||
ptr += 9;
|
||||
|
||||
ut_asserteq(NAME_OP, *ptr++);
|
||||
|
|
|
@ -51,13 +51,13 @@ static int dm_test_misc(struct unit_test_state *uts)
|
|||
/* Read back last issued ioctl */
|
||||
ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl,
|
||||
sizeof(last_ioctl)));
|
||||
ut_asserteq(6, last_ioctl)
|
||||
ut_asserteq(6, last_ioctl);
|
||||
|
||||
ut_assertok(misc_ioctl(dev, 23, NULL));
|
||||
/* Read back last issued ioctl */
|
||||
ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl,
|
||||
sizeof(last_ioctl)));
|
||||
ut_asserteq(23, last_ioctl)
|
||||
ut_asserteq(23, last_ioctl);
|
||||
|
||||
/* Enable / disable tests */
|
||||
|
||||
|
|
|
@ -28,22 +28,22 @@ static int dm_test_phy_base(struct unit_test_state *uts)
|
|||
/*
|
||||
* Get the same phy port in 2 different ways and compare.
|
||||
*/
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method1))
|
||||
ut_assertok(generic_phy_get_by_index(parent, 0, &phy1_method2))
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method1));
|
||||
ut_assertok(generic_phy_get_by_index(parent, 0, &phy1_method2));
|
||||
ut_asserteq(phy1_method1.id, phy1_method2.id);
|
||||
|
||||
/*
|
||||
* Get the second phy port. Check that the same phy provider (device)
|
||||
* provides this 2nd phy port, but that the IDs are different
|
||||
*/
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2))
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2));
|
||||
ut_asserteq_ptr(phy1_method2.dev, phy2.dev);
|
||||
ut_assert(phy1_method1.id != phy2.id);
|
||||
|
||||
/*
|
||||
* Get the third phy port. Check that the phy provider is different
|
||||
*/
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3))
|
||||
ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3));
|
||||
ut_assert(phy2.dev != phy3.dev);
|
||||
|
||||
/* Try to get a non-existing phy */
|
||||
|
|
|
@ -187,10 +187,10 @@ static int dm_test_scmi_resets(struct unit_test_state *uts)
|
|||
ut_assertnonnull(agent);
|
||||
|
||||
/* Test SCMI resect controller manipulation */
|
||||
ut_assert(!agent->reset[0].asserted)
|
||||
ut_assert(!agent->reset[0].asserted);
|
||||
|
||||
ut_assertok(reset_assert(&scmi_devices->reset[0]));
|
||||
ut_assert(agent->reset[0].asserted)
|
||||
ut_assert(agent->reset[0].asserted);
|
||||
|
||||
ut_assertok(reset_deassert(&scmi_devices->reset[0]));
|
||||
ut_assert(!agent->reset[0].asserted);
|
||||
|
|
|
@ -15,12 +15,12 @@ static int lib_test_is_enabled(struct unit_test_state *uts)
|
|||
{
|
||||
ulong val;
|
||||
|
||||
ut_asserteq(1, IS_ENABLED(CONFIG_CMDLINE))
|
||||
ut_asserteq(0, IS_ENABLED(CONFIG__UNDEFINED))
|
||||
ut_asserteq(1, IS_ENABLED(CONFIG_CMDLINE));
|
||||
ut_asserteq(0, IS_ENABLED(CONFIG__UNDEFINED));
|
||||
|
||||
ut_asserteq(1, CONFIG_IS_ENABLED(CMDLINE))
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED))
|
||||
ut_asserteq(1, CONFIG_IS_ENABLED(CMDLINE));
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(OF_PLATDATA));
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED));
|
||||
|
||||
ut_asserteq(0xc000,
|
||||
IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, CONFIG_BLOBLIST_ADDR));
|
||||
|
|
|
@ -15,9 +15,9 @@ static int lib_test_spl_is_enabled(struct unit_test_state *uts)
|
|||
{
|
||||
ulong val;
|
||||
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(CMDLINE))
|
||||
ut_asserteq(1, CONFIG_IS_ENABLED(OF_PLATDATA))
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED))
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(CMDLINE));
|
||||
ut_asserteq(1, CONFIG_IS_ENABLED(OF_PLATDATA));
|
||||
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED));
|
||||
|
||||
/*
|
||||
* This fails if CONFIG_TEST_KCONFIG_ENABLE is not enabled, since the
|
||||
|
|
|
@ -192,7 +192,7 @@ static int unicode_test_utf8_get(struct unit_test_state *uts)
|
|||
if (!code)
|
||||
break;
|
||||
}
|
||||
ut_asserteq_ptr(s, d2 + 9)
|
||||
ut_asserteq_ptr(s, d2 + 9);
|
||||
|
||||
/* Check characters less than 0x10000 */
|
||||
s = d3;
|
||||
|
@ -203,7 +203,7 @@ static int unicode_test_utf8_get(struct unit_test_state *uts)
|
|||
if (!code)
|
||||
break;
|
||||
}
|
||||
ut_asserteq_ptr(s, d3 + 9)
|
||||
ut_asserteq_ptr(s, d3 + 9);
|
||||
|
||||
/* Check character greater 0xffff */
|
||||
s = d4;
|
||||
|
@ -228,7 +228,7 @@ static int unicode_test_utf8_put(struct unit_test_state *uts)
|
|||
|
||||
/* Commercial at, translates to one character */
|
||||
pos = buffer;
|
||||
ut_assert(!utf8_put('@', &pos))
|
||||
ut_assert(!utf8_put('@', &pos));
|
||||
ut_asserteq(1, pos - buffer);
|
||||
ut_asserteq('@', buffer[0]);
|
||||
ut_assert(!buffer[1]);
|
||||
|
|
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
|
@ -6,6 +6,7 @@
|
|||
/dumpimage
|
||||
/easylogo/easylogo
|
||||
/envcrc
|
||||
/fdt_add_pubkey
|
||||
/fdtgrep
|
||||
/file2include
|
||||
/fit_check_sign
|
||||
|
|
|
@ -65,6 +65,7 @@ mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
|
|||
|
||||
hostprogs-y += dumpimage mkimage
|
||||
hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fit_info fit_check_sign
|
||||
hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fdt_add_pubkey
|
||||
|
||||
ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_FWU_MDATA_GPT_BLK),)
|
||||
hostprogs-y += file2include
|
||||
|
@ -150,6 +151,7 @@ dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
|
|||
mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
|
||||
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
||||
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||
fdt_add_pubkey-objs := $(dumpimage-mkimage-objs) fdt_add_pubkey.o
|
||||
file2include-objs := file2include.o
|
||||
|
||||
ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_TOOLS_LIBCRYPTO),)
|
||||
|
@ -187,6 +189,7 @@ HOSTCFLAGS_fit_image.o += -DMKIMAGE_DTC=\"$(CONFIG_MKIMAGE_DTC_PATH)\"
|
|||
HOSTLDLIBS_dumpimage := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_fit_info := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_fit_check_sign := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_fdt_add_pubkey := $(HOSTLDLIBS_mkimage)
|
||||
|
||||
hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl
|
||||
hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
|
||||
|
|
|
@ -1366,6 +1366,24 @@ when it was created.
|
|||
|
||||
.. _`BinmanLogging`:
|
||||
|
||||
Signing FIT container with private key in an image
|
||||
--------------------------------------------------
|
||||
|
||||
You can sign FIT container with private key in your image.
|
||||
For example::
|
||||
|
||||
$ binman sign -i image.bin -k privatekey -a sha256,rsa4096 fit
|
||||
|
||||
binman will extract FIT container, sign and replace it immediately.
|
||||
|
||||
If you want to sign and replace FIT container in place::
|
||||
|
||||
$ binman sign -i image.bin -k privatekey -a sha256,rsa4096 -f fit.fit fit
|
||||
|
||||
which will sign FIT container with private key and replace it immediately
|
||||
inside your image.
|
||||
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
|
@ -1751,6 +1769,35 @@ Options:
|
|||
output directory if a single test is run (pass test name at the end of the
|
||||
command line
|
||||
|
||||
binman sign
|
||||
-----------
|
||||
|
||||
Usage::
|
||||
|
||||
binman sign [-h] -a ALGO [-f FILE] -i IMAGE -k KEY [paths ...]
|
||||
|
||||
positional arguments:
|
||||
|
||||
paths
|
||||
Paths within file to sign (wildcard)
|
||||
|
||||
options:
|
||||
|
||||
-h, --help
|
||||
show this help message and exit
|
||||
|
||||
-a ALGO, --algo ALGO
|
||||
Hash algorithm e.g. sha256,rsa4096
|
||||
|
||||
-f FILE, --file FILE
|
||||
Input filename to sign
|
||||
|
||||
-i IMAGE, --image IMAGE
|
||||
Image filename to update
|
||||
|
||||
-k KEY, --key KEY
|
||||
Private key file for signing
|
||||
|
||||
binman tool
|
||||
-----------
|
||||
|
||||
|
|
|
@ -176,6 +176,19 @@ controlled by a description in the board device tree.'''
|
|||
replace_parser.add_argument('paths', type=str, nargs='*',
|
||||
help='Paths within file to replace (wildcard)')
|
||||
|
||||
sign_parser = subparsers.add_parser('sign',
|
||||
help='Sign entries in image')
|
||||
sign_parser.add_argument('-a', '--algo', type=str, required=True,
|
||||
help='Hash algorithm e.g. sha256,rsa4096')
|
||||
sign_parser.add_argument('-f', '--file', type=str, required=False,
|
||||
help='Input filename to sign')
|
||||
sign_parser.add_argument('-i', '--image', type=str, required=True,
|
||||
help='Image filename to update')
|
||||
sign_parser.add_argument('-k', '--key', type=str, required=True,
|
||||
help='Private key file for signing')
|
||||
sign_parser.add_argument('paths', type=str, nargs='*',
|
||||
help='Paths within file to sign (wildcard)')
|
||||
|
||||
if HAS_TESTS:
|
||||
test_parser = subparsers.add_parser('test', help='Run tests')
|
||||
test_parser.add_argument('-P', '--processes', type=int,
|
||||
|
|
|
@ -448,6 +448,31 @@ def ReplaceEntries(image_fname, input_fname, indir, entry_paths,
|
|||
AfterReplace(image, allow_resize=allow_resize, write_map=write_map)
|
||||
return image
|
||||
|
||||
def SignEntries(image_fname, input_fname, privatekey_fname, algo, entry_paths,
|
||||
write_map=False):
|
||||
"""Sign and replace the data from one or more entries from input files
|
||||
|
||||
Args:
|
||||
image_fname: Image filename to process
|
||||
input_fname: Single input filename to use if replacing one file, None
|
||||
otherwise
|
||||
algo: Hashing algorithm
|
||||
entry_paths: List of entry paths to sign
|
||||
privatekey_fname: Private key filename
|
||||
write_map (bool): True to write the map file
|
||||
"""
|
||||
image_fname = os.path.abspath(image_fname)
|
||||
image = Image.FromFile(image_fname)
|
||||
|
||||
image.mark_build_done()
|
||||
|
||||
BeforeReplace(image, allow_resize=True)
|
||||
|
||||
for entry_path in entry_paths:
|
||||
entry = image.FindEntryPath(entry_path)
|
||||
entry.UpdateSignatures(privatekey_fname, algo, input_fname)
|
||||
|
||||
AfterReplace(image, allow_resize=True, write_map=write_map)
|
||||
|
||||
def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
|
||||
"""Prepare the images to be processed and select the device tree
|
||||
|
@ -660,7 +685,7 @@ def Binman(args):
|
|||
tools.set_tool_paths(tool_paths or None)
|
||||
bintool.Bintool.set_tool_dir(args.tooldir)
|
||||
|
||||
if args.cmd in ['ls', 'extract', 'replace', 'tool']:
|
||||
if args.cmd in ['ls', 'extract', 'replace', 'tool', 'sign']:
|
||||
try:
|
||||
tout.init(args.verbosity)
|
||||
if args.cmd == 'replace':
|
||||
|
@ -679,6 +704,9 @@ def Binman(args):
|
|||
do_compress=not args.compressed,
|
||||
allow_resize=not args.fix_size, write_map=args.map)
|
||||
|
||||
if args.cmd == 'sign':
|
||||
SignEntries(args.image, args.file, args.key, args.algo, args.paths)
|
||||
|
||||
if args.cmd == 'tool':
|
||||
if args.list:
|
||||
bintool.Bintool.list_all()
|
||||
|
|
|
@ -1378,3 +1378,6 @@ features to produce new behaviours.
|
|||
if entries:
|
||||
for entry in entries.values():
|
||||
entry.mark_build_done()
|
||||
|
||||
def UpdateSignatures(self, privatekey_fname, algo, input_fname):
|
||||
self.Raise('Updating signatures is not supported with this entry type')
|
||||
|
|
|
@ -835,3 +835,19 @@ class Entry_fit(Entry_section):
|
|||
|
||||
def CheckEntries(self):
|
||||
pass
|
||||
|
||||
def UpdateSignatures(self, privatekey_fname, algo, input_fname):
|
||||
uniq = self.GetUniqueName()
|
||||
args = [ '-G', privatekey_fname, '-r', '-o', algo, '-F' ]
|
||||
if input_fname:
|
||||
fname = input_fname
|
||||
else:
|
||||
fname = tools.get_output_filename('%s.fit' % uniq)
|
||||
tools.write_file(fname, self.GetData())
|
||||
args.append(fname)
|
||||
|
||||
if self.mkimage.run_cmd(*args) is None:
|
||||
self.Raise("Missing tool: 'mkimage'")
|
||||
|
||||
data = tools.read_file(fname)
|
||||
self.WriteData(data)
|
||||
|
|
|
@ -709,6 +709,14 @@ class TestFunctional(unittest.TestCase):
|
|||
AddNode(dtb.GetRoot(), '')
|
||||
return tree
|
||||
|
||||
def _CheckSign(self, fit, key):
|
||||
try:
|
||||
tools.run('fit_check_sign', '-k', key, '-f', fit)
|
||||
except:
|
||||
self.fail('Expected signed FIT container')
|
||||
return False
|
||||
return True
|
||||
|
||||
def testRun(self):
|
||||
"""Test a basic run with valid args"""
|
||||
result = self._RunBinman('-h')
|
||||
|
@ -6583,6 +6591,91 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
|||
self._DoTestFile('278_mkimage_missing_multiple.dts', allow_missing=False)
|
||||
self.assertIn("not found in input path", str(e.exception))
|
||||
|
||||
def _PrepareSignEnv(self, dts='280_fit_sign.dts'):
|
||||
"""Prepare sign environment
|
||||
|
||||
Create private and public keys, add pubkey into dtb.
|
||||
|
||||
Returns:
|
||||
Tuple:
|
||||
FIT container
|
||||
Image name
|
||||
Private key
|
||||
DTB
|
||||
"""
|
||||
|
||||
data = self._DoReadFileRealDtb(dts)
|
||||
updated_fname = tools.get_output_filename('image-updated.bin')
|
||||
tools.write_file(updated_fname, data)
|
||||
dtb = tools.get_output_filename('source.dtb')
|
||||
private_key = tools.get_output_filename('test_key.key')
|
||||
public_key = tools.get_output_filename('test_key.crt')
|
||||
fit = tools.get_output_filename('fit.fit')
|
||||
key_dir = tools.get_output_dir()
|
||||
|
||||
tools.run('openssl', 'req', '-batch' , '-newkey', 'rsa:4096',
|
||||
'-sha256', '-new', '-nodes', '-x509', '-keyout',
|
||||
private_key, '-out', public_key)
|
||||
tools.run('fdt_add_pubkey', '-a', 'sha256,rsa4096', '-k', key_dir,
|
||||
'-n', 'test_key', '-r', 'conf', dtb)
|
||||
|
||||
return fit, updated_fname, private_key, dtb
|
||||
|
||||
def testSignSimple(self):
|
||||
"""Test that a FIT container can be signed in image"""
|
||||
is_signed = False
|
||||
fit, fname, private_key, dtb = self._PrepareSignEnv()
|
||||
|
||||
# do sign with private key
|
||||
control.SignEntries(fname, None, private_key, 'sha256,rsa4096',
|
||||
['fit'])
|
||||
is_signed = self._CheckSign(fit, dtb)
|
||||
|
||||
self.assertEqual(is_signed, True)
|
||||
|
||||
def testSignExactFIT(self):
|
||||
"""Test that a FIT container can be signed and replaced in image"""
|
||||
is_signed = False
|
||||
fit, fname, private_key, dtb = self._PrepareSignEnv()
|
||||
|
||||
# Make sure we propagate the toolpath, since mkimage may not be on PATH
|
||||
args = []
|
||||
if self.toolpath:
|
||||
for path in self.toolpath:
|
||||
args += ['--toolpath', path]
|
||||
|
||||
# do sign with private key
|
||||
self._DoBinman(*args, 'sign', '-i', fname, '-k', private_key, '-a',
|
||||
'sha256,rsa4096', '-f', fit, 'fit')
|
||||
is_signed = self._CheckSign(fit, dtb)
|
||||
|
||||
self.assertEqual(is_signed, True)
|
||||
|
||||
def testSignNonFit(self):
|
||||
"""Test a non-FIT entry cannot be signed"""
|
||||
is_signed = False
|
||||
fit, fname, private_key, _ = self._PrepareSignEnv(
|
||||
'281_sign_non_fit.dts')
|
||||
|
||||
# do sign with private key
|
||||
with self.assertRaises(ValueError) as e:
|
||||
self._DoBinman('sign', '-i', fname, '-k', private_key, '-a',
|
||||
'sha256,rsa4096', '-f', fit, 'u-boot')
|
||||
self.assertIn(
|
||||
"Node '/u-boot': Updating signatures is not supported with this entry type",
|
||||
str(e.exception))
|
||||
|
||||
def testSignMissingMkimage(self):
|
||||
"""Test that FIT signing handles a missing mkimage tool"""
|
||||
fit, fname, private_key, _ = self._PrepareSignEnv()
|
||||
|
||||
# try to sign with a missing mkimage tool
|
||||
bintool.Bintool.set_missing_list(['mkimage'])
|
||||
with self.assertRaises(ValueError) as e:
|
||||
control.SignEntries(fname, None, private_key, 'sha256,rsa4096',
|
||||
['fit'])
|
||||
self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
63
tools/binman/test/280_fit_sign.dts
Normal file
63
tools/binman/test/280_fit_sign.dts
Normal file
|
@ -0,0 +1,63 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
size = <0x100000>;
|
||||
allow-repack;
|
||||
|
||||
fit {
|
||||
description = "U-Boot";
|
||||
offset = <0x10000>;
|
||||
images {
|
||||
u-boot-1 {
|
||||
description = "U-Boot";
|
||||
type = "standalone";
|
||||
arch = "arm64";
|
||||
os = "u-boot";
|
||||
compression = "none";
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
|
||||
fdt-1 {
|
||||
description = "test.dtb";
|
||||
type = "flat_dt";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
u-boot-spl-dtb {
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
description = "u-boot with fdt";
|
||||
firmware = "u-boot-1";
|
||||
fdt = "fdt-1";
|
||||
signature-1 {
|
||||
algo = "sha256,rsa4096";
|
||||
key-name-hint = "test_key";
|
||||
sign-images = "firmware", "fdt";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fdtmap {
|
||||
};
|
||||
};
|
||||
};
|
65
tools/binman/test/281_sign_non_fit.dts
Normal file
65
tools/binman/test/281_sign_non_fit.dts
Normal file
|
@ -0,0 +1,65 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
size = <0x100000>;
|
||||
allow-repack;
|
||||
|
||||
u-boot {
|
||||
};
|
||||
fit {
|
||||
description = "U-Boot";
|
||||
offset = <0x10000>;
|
||||
images {
|
||||
u-boot-1 {
|
||||
description = "U-Boot";
|
||||
type = "standalone";
|
||||
arch = "arm64";
|
||||
os = "u-boot";
|
||||
compression = "none";
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
|
||||
fdt-1 {
|
||||
description = "test.dtb";
|
||||
type = "flat_dt";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
u-boot-spl-dtb {
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
description = "u-boot with fdt";
|
||||
firmware = "u-boot-1";
|
||||
fdt = "fdt-1";
|
||||
signature-1 {
|
||||
algo = "sha256,rsa4096";
|
||||
key-name-hint = "test_key";
|
||||
sign-images = "firmware", "fdt";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fdtmap {
|
||||
};
|
||||
};
|
||||
};
|
|
@ -157,7 +157,9 @@ class Toolchain:
|
|||
Value of that environment variable or arguments
|
||||
"""
|
||||
if which == VAR_CROSS_COMPILE:
|
||||
return self.GetWrapper() + self.cross
|
||||
wrapper = self.GetWrapper()
|
||||
base = '' if self.arch == 'sandbox' else self.path
|
||||
return wrapper + os.path.join(base, self.cross)
|
||||
elif which == VAR_PATH:
|
||||
return self.path
|
||||
elif which == VAR_ARCH:
|
||||
|
|
138
tools/fdt_add_pubkey.c
Normal file
138
tools/fdt_add_pubkey.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
#include <image.h>
|
||||
#include "fit_common.h"
|
||||
|
||||
static const char *cmdname;
|
||||
|
||||
static const char *algo_name = "sha1,rsa2048"; /* -a <algo> */
|
||||
static const char *keydir = "."; /* -k <keydir> */
|
||||
static const char *keyname = "key"; /* -n <keyname> */
|
||||
static const char *require_keys; /* -r <conf|image> */
|
||||
static const char *keydest; /* argv[n] */
|
||||
|
||||
static void print_usage(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", msg);
|
||||
fprintf(stderr, "Usage: %s [-a <algo>] [-k <keydir>] [-n <keyname>] [-r <conf|image>]"
|
||||
" <fdt blob>\n", cmdname);
|
||||
fprintf(stderr, "Help information: %s [-h]\n", cmdname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void print_help(void)
|
||||
{
|
||||
fprintf(stderr, "Options:\n"
|
||||
"\t-a <algo> Cryptographic algorithm. Optional parameter, default value: sha1,rsa2048\n"
|
||||
"\t-k <keydir> Directory with public key. Optional parameter, default value: .\n"
|
||||
"\t-n <keyname> Public key name. Optional parameter, default value: key\n"
|
||||
"\t-r <conf|image> Required: If present this indicates that the key must be verified for the image / configuration to be considered valid.\n"
|
||||
"\t<fdt blob> FDT blob file for adding of the public key. Required parameter.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void process_args(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "a:k:n:r:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 'k':
|
||||
keydir = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
algo_name = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
keyname = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
require_keys = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
default:
|
||||
print_usage("Invalid option");
|
||||
}
|
||||
}
|
||||
/* The last parameter is expected to be the .dtb to add the public key to */
|
||||
if (optind < argc)
|
||||
keydest = argv[optind];
|
||||
|
||||
if (!keydest)
|
||||
print_usage("Missing dtb file to update");
|
||||
}
|
||||
|
||||
static void reset_info(struct image_sign_info *info)
|
||||
{
|
||||
if (!info)
|
||||
fprintf(stderr, "Error: info is NULL in %s\n", __func__);
|
||||
|
||||
memset(info, 0, sizeof(struct image_sign_info));
|
||||
|
||||
info->keydir = keydir;
|
||||
info->keyname = keyname;
|
||||
info->name = algo_name;
|
||||
info->require_keys = require_keys;
|
||||
info->crypto = image_get_crypto_algo(algo_name);
|
||||
|
||||
if (!info->crypto) {
|
||||
fprintf(stderr, "Unsupported signature algorithm '%s'\n",
|
||||
algo_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static int add_pubkey(struct image_sign_info *info)
|
||||
{
|
||||
int destfd = -1, ret;
|
||||
void *dest_blob = NULL;
|
||||
struct stat dest_sbuf;
|
||||
size_t size_inc = 0;
|
||||
|
||||
if (!info)
|
||||
fprintf(stderr, "Error: info is NULL in %s\n", __func__);
|
||||
|
||||
do {
|
||||
if (destfd >= 0) {
|
||||
munmap(dest_blob, dest_sbuf.st_size);
|
||||
close(destfd);
|
||||
|
||||
fprintf(stderr, ".dtb too small, increasing size by 1024 bytes\n");
|
||||
size_inc = 1024;
|
||||
}
|
||||
|
||||
destfd = mmap_fdt(cmdname, keydest, size_inc, &dest_blob,
|
||||
&dest_sbuf, false, false);
|
||||
if (destfd < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ret = info->crypto->add_verify_data(info, dest_blob);
|
||||
if (ret == -ENOSPC)
|
||||
continue;
|
||||
else if (ret < 0)
|
||||
break;
|
||||
} while (ret == -ENOSPC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct image_sign_info info;
|
||||
int ret;
|
||||
|
||||
cmdname = argv[0];
|
||||
|
||||
process_args(argc, argv);
|
||||
reset_info(&info);
|
||||
ret = add_pubkey(&info);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Cannot add public key to FIT blob: %s\n",
|
||||
cmdname, strerror(ret));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in a new issue