mirror of https://github.com/wolfSSL/wolfBoot.git
F-7985: enter legacy uImage at ih_ep when it differs from ih_load
wolfBoot_start() parsed both ih_load and ih_ep from the U-Boot legacy uImage header, relocated the payload to ih_load, then discarded ih_ep and passed the load address to do_boot(). An image built with the entry point ahead of the load address (a preamble before the entry, as U-Boot bootm handles by copying to ih_load and jumping to ih_ep) was staged correctly but entered at the wrong address. Keep ih_load as the relocation destination and remember ih_ep as the entry point when the two differ, then override load_address just before do_boot(). The override is skipped when a later stage (ELF/FIT) re-derived the load address, since that stage supplies its own entry point. Extend unit-update-ram-uboot with a case where ih_ep = ih_load + 0x40: it asserts the payload lands at ih_load and do_boot() is entered at ih_ep. Fails before this change (jumps to ih_load).pull/851/head
parent
5dfdec31b1
commit
93edc29082
|
|
@ -273,6 +273,10 @@ void RAMFUNCTION wolfBoot_start(void)
|
|||
BENCHMARK_DECLARE();
|
||||
#ifdef WOLFBOOT_UBOOT_LEGACY
|
||||
uint8_t *image_ptr;
|
||||
/* uImage ih_load/ih_ep, kept only when the entry point differs from the
|
||||
* load address (see the do_boot() entry override below). */
|
||||
uint32_t *uboot_load = NULL;
|
||||
uint32_t *uboot_entry = NULL;
|
||||
#endif
|
||||
uint32_t *load_address = NULL;
|
||||
uint32_t *source_address = NULL;
|
||||
|
|
@ -506,6 +510,14 @@ backup_on_failure:
|
|||
os_image.fw_size);
|
||||
}
|
||||
#endif
|
||||
/* bootm relocates to ih_load but enters at ih_ep: kernels built
|
||||
* with a preamble ahead of the entry point set the two to
|
||||
* different addresses. Remember the entry point; ih_load remains
|
||||
* the relocation destination. */
|
||||
if ((ih_ep != 0) && (ih_ep != ih_load)) {
|
||||
uboot_load = load_address;
|
||||
uboot_entry = (uint32_t*)(uintptr_t)ih_ep;
|
||||
}
|
||||
} else {
|
||||
/* Linux PPC path: leave load_address alone, just advance it
|
||||
* past the header to match upstream behaviour. load_address is
|
||||
|
|
@ -513,7 +525,6 @@ backup_on_failure:
|
|||
load_address = (uint32_t*)((uint8_t*)load_address +
|
||||
UBOOT_IMG_HDR_SZ);
|
||||
}
|
||||
(void)ih_ep; /* TODO: pass through to do_boot when ih_ep != ih_load */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -650,6 +661,14 @@ backup_on_failure:
|
|||
}
|
||||
#endif /* MMU */
|
||||
|
||||
#ifdef WOLFBOOT_UBOOT_LEGACY
|
||||
/* Enter the uImage at ih_ep. Skipped if a later stage (ELF/FIT) re-derived
|
||||
* the load address, since that stage provides its own entry point. */
|
||||
if ((uboot_entry != NULL) && (load_address == uboot_load)) {
|
||||
load_address = uboot_entry;
|
||||
}
|
||||
#endif
|
||||
|
||||
wolfBoot_printf("Booting at %p\n", load_address);
|
||||
|
||||
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
|
||||
|
|
|
|||
|
|
@ -170,11 +170,11 @@ static void cleanup_ram(void)
|
|||
|
||||
#define DIGEST_TLV_OFF_IN_HDR 28
|
||||
/* Write a wolfBoot image to the BOOT partition whose firmware payload is a
|
||||
* uImage: [64-byte uImage header][KERNEL_LEN kernel bytes]. ih_load is set to
|
||||
* the caller-provided value; the uImage magic/size/header-CRC are made valid so
|
||||
* uboot_legacy_header_valid() accepts it. Fills expected_kernel[] with the
|
||||
* kernel pattern for later comparison. Returns 0 on success. */
|
||||
static int add_uimage_payload(uint32_t version, uint32_t ih_load)
|
||||
* uImage: [64-byte uImage header][KERNEL_LEN kernel bytes]. ih_load/ih_ep are
|
||||
* set to the caller-provided values; the uImage magic/size/header-CRC are made
|
||||
* valid so uboot_legacy_header_valid() accepts it. Fills expected_kernel[] with
|
||||
* the kernel pattern for later comparison. Returns 0 on success. */
|
||||
static int add_uimage_payload(uint32_t version, uint32_t ih_load, uint32_t ih_ep)
|
||||
{
|
||||
uint8_t *base = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
uint8_t uimg[UBOOT_IMG_HDR_SZ + KERNEL_LEN];
|
||||
|
|
@ -194,7 +194,7 @@ static int add_uimage_payload(uint32_t version, uint32_t ih_load)
|
|||
/* uimg[4..8] = ih_hcrc, left 0 while computing the header CRC. */
|
||||
store_be32(uimg + 0x0C, KERNEL_LEN); /* ih_size */
|
||||
store_be32(uimg + 0x10, ih_load); /* ih_load */
|
||||
store_be32(uimg + 0x14, ih_load); /* ih_ep (unused by wolfBoot) */
|
||||
store_be32(uimg + 0x14, ih_ep); /* ih_ep */
|
||||
for (i = 0; i < KERNEL_LEN; i++) {
|
||||
uint8_t b = (uint8_t)(0xA5u ^ (uint8_t)i);
|
||||
uimg[UBOOT_IMG_HDR_SZ + i] = b;
|
||||
|
|
@ -265,21 +265,28 @@ static void fixture_teardown(void)
|
|||
cleanup_flash();
|
||||
}
|
||||
|
||||
/* Run the full wolfBoot_start() flow for a given uImage ih_load and check that
|
||||
* do_boot() was reached with expect_addr and the kernel payload is present
|
||||
* there. (mmap setup/teardown is handled by the checked fixture.) */
|
||||
static void run_and_check(uint32_t ih_load, uintptr_t expect_addr)
|
||||
/* Run the full wolfBoot_start() flow for a given uImage ih_load/ih_ep and check
|
||||
* that the kernel payload landed at expect_load and that do_boot() was reached
|
||||
* with expect_boot. (mmap setup/teardown is handled by the checked fixture.) */
|
||||
static void run_and_check_ep(uint32_t ih_load, uint32_t ih_ep,
|
||||
uintptr_t expect_load, uintptr_t expect_boot)
|
||||
{
|
||||
ck_assert_int_eq(add_uimage_payload(1, ih_load), 0);
|
||||
ck_assert_int_eq(add_uimage_payload(1, ih_load, ih_ep), 0);
|
||||
|
||||
wolfBoot_start();
|
||||
|
||||
ck_assert_int_eq(g_boot_called, 1);
|
||||
ck_assert_uint_eq((uintptr_t)g_boot_addr, expect_addr);
|
||||
ck_assert_int_eq(memcmp((void *)expect_addr, expected_kernel, KERNEL_LEN),
|
||||
ck_assert_uint_eq((uintptr_t)g_boot_addr, expect_boot);
|
||||
ck_assert_int_eq(memcmp((void *)expect_load, expected_kernel, KERNEL_LEN),
|
||||
0);
|
||||
}
|
||||
|
||||
/* Common case: entry point == load address. */
|
||||
static void run_and_check(uint32_t ih_load, uintptr_t expect_addr)
|
||||
{
|
||||
run_and_check_ep(ih_load, ih_load, expect_addr, expect_addr);
|
||||
}
|
||||
|
||||
/* Case 1: ih_load coincides with the staged kernel address -> no relocation
|
||||
* needed; the payload is already there. */
|
||||
START_TEST (test_uboot_ihload_coincident)
|
||||
|
|
@ -306,7 +313,21 @@ START_TEST (test_uboot_ihload_lower_overlap)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
/* Case 4: ih_load == 0 (Linux/PPC convention) -> load_address is only advanced
|
||||
/* Case 4: ih_ep distinct from ih_load (kernels built with a preamble ahead of
|
||||
* the entry point). U-Boot bootm copies the payload to ih_load and jumps to
|
||||
* ih_ep: the payload must land at ih_load, but do_boot() must be entered at
|
||||
* ih_ep. */
|
||||
#define UIMAGE_EP_OFFSET 0x40
|
||||
START_TEST (test_uboot_ihep_distinct)
|
||||
{
|
||||
run_and_check_ep((uint32_t)IHLOAD_HI_BASE,
|
||||
(uint32_t)(IHLOAD_HI_BASE + UIMAGE_EP_OFFSET),
|
||||
(uintptr_t)IHLOAD_HI_BASE,
|
||||
(uintptr_t)(IHLOAD_HI_BASE + UIMAGE_EP_OFFSET));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Case 5: ih_load == 0 (Linux/PPC convention) -> load_address is only advanced
|
||||
* past the 64-byte header; behavior is unchanged by the fix. */
|
||||
START_TEST (test_uboot_ihload_zero)
|
||||
{
|
||||
|
|
@ -320,26 +341,31 @@ Suite *wolfboot_suite(void)
|
|||
TCase *coincident = tcase_create("uImage ih_load coincident");
|
||||
TCase *higher = tcase_create("uImage ih_load higher");
|
||||
TCase *lower = tcase_create("uImage ih_load lower overlap");
|
||||
TCase *ep = tcase_create("uImage ih_ep distinct");
|
||||
TCase *zero = tcase_create("uImage ih_load zero");
|
||||
|
||||
tcase_add_checked_fixture(coincident, fixture_setup, fixture_teardown);
|
||||
tcase_add_checked_fixture(higher, fixture_setup, fixture_teardown);
|
||||
tcase_add_checked_fixture(lower, fixture_setup, fixture_teardown);
|
||||
tcase_add_checked_fixture(ep, fixture_setup, fixture_teardown);
|
||||
tcase_add_checked_fixture(zero, fixture_setup, fixture_teardown);
|
||||
|
||||
tcase_add_test(coincident, test_uboot_ihload_coincident);
|
||||
tcase_add_test(higher, test_uboot_ihload_higher);
|
||||
tcase_add_test(lower, test_uboot_ihload_lower_overlap);
|
||||
tcase_add_test(ep, test_uboot_ihep_distinct);
|
||||
tcase_add_test(zero, test_uboot_ihload_zero);
|
||||
|
||||
suite_add_tcase(s, coincident);
|
||||
suite_add_tcase(s, higher);
|
||||
suite_add_tcase(s, lower);
|
||||
suite_add_tcase(s, ep);
|
||||
suite_add_tcase(s, zero);
|
||||
|
||||
tcase_set_timeout(coincident, 5);
|
||||
tcase_set_timeout(higher, 5);
|
||||
tcase_set_timeout(lower, 5);
|
||||
tcase_set_timeout(ep, 5);
|
||||
tcase_set_timeout(zero, 5);
|
||||
|
||||
return s;
|
||||
|
|
|
|||
Loading…
Reference in New Issue