diff options
Diffstat (limited to 'target/linux/mpc85xx/image/spi-loader/loader.c')
-rw-r--r-- | target/linux/mpc85xx/image/spi-loader/loader.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/target/linux/mpc85xx/image/spi-loader/loader.c b/target/linux/mpc85xx/image/spi-loader/loader.c new file mode 100644 index 0000000000..145a723033 --- /dev/null +++ b/target/linux/mpc85xx/image/spi-loader/loader.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Matthias Schiffer <mschiffer@universe-factory.net> + */ + +#include <image.h> +#include <init.h> +#include <spi.h> +#include <spi-nor.h> +#include <stdio.h> +#include <string.h> + +static bool check_image_header(const image_header_t *header) +{ + if (header->ih_magic != cpu_to_be32(IH_MAGIC_OKLI)) { + puts("Invalid image magic\n"); + return false; + } + + if (header->ih_comp != cpu_to_be32(IH_COMP_NONE)) { + puts("Unsupported compressed image\n"); + return false; + } + + return true; +} + +static uint32_t do_load(void) +{ + image_header_t header; + uint32_t ih_size, ih_load, ih_ep; + + if (spi_nor_read_id()) + return UINT32_MAX; + + puts("Reading image header...\n"); + if (spi_nor_read_data(&header, CONFIG_IMAGE_OFFSET, sizeof(header))) + return UINT32_MAX; + + if (!check_image_header(&header)) + return UINT32_MAX; + + header.ih_name[sizeof(header.ih_name) - 1] = 0; + ih_size = be32_to_cpu(header.ih_size); + ih_load = be32_to_cpu(header.ih_load); + ih_ep = be32_to_cpu(header.ih_ep); + + put_with_label("Image Name: ", puts, (const char *)header.ih_name); + put_with_label("Data Size: ", put_u32, ih_size); + put_with_label("Load Address: ", put_u32, ih_load); + put_with_label("Entry Point: ", put_u32, ih_ep); + + puts("Reading image data...\n"); + void *loadaddr = (void *)ih_load; + if (spi_nor_read_data(loadaddr, CONFIG_IMAGE_OFFSET + sizeof(header), + ih_size)) + return false; + + flush_cache(loadaddr, ih_size); + + return ih_ep; +} + +static void enter_image(uint32_t addr) +{ + typedef void (*entry_t)(void); + entry_t entry = (entry_t)addr; + + puts("Starting image...\n"); + entry(); +} + +static void load(void) +{ + uint32_t addr; + int ret; + + ret = spi_init(0, CONFIG_SPI_MAX_HZ, SPI_MODE_0); + if (ret) { + puts("Failed to initialize SPI controller\n"); + return; + } + + ret = spi_claim_bus(); + if (ret) { + puts("Failed to enable SPI controller\n"); + return; + } + + addr = do_load(); + + spi_release_bus(); + + if (addr != UINT32_MAX) + enter_image(addr); +} + +void start(void) +{ + serial_console_init(); + puts("=== " CONFIG_PROGRAM_NAME " ===\n"); + + load(); + + puts("Halting execution.\n"); + while (true) {} +} |