1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
210b84fe1SSimon Glass /*
310b84fe1SSimon Glass * (C) Copyright 2015 Google, Inc
410b84fe1SSimon Glass * Written by Simon Glass <sjg@chromium.org>
510b84fe1SSimon Glass *
610b84fe1SSimon Glass * See README.rockchip for details of the rkspi format
710b84fe1SSimon Glass */
810b84fe1SSimon Glass
910b84fe1SSimon Glass #include "imagetool.h"
1010b84fe1SSimon Glass #include <image.h>
1110b84fe1SSimon Glass #include <rc4.h>
1210b84fe1SSimon Glass #include "mkimage.h"
1310b84fe1SSimon Glass #include "rkcommon.h"
1410b84fe1SSimon Glass
1510b84fe1SSimon Glass enum {
1610b84fe1SSimon Glass RKSPI_SECT_LEN = RK_BLK_SIZE * 4,
1710b84fe1SSimon Glass };
1810b84fe1SSimon Glass
rkspi_set_header(void * buf,struct stat * sbuf,int ifd,struct image_tool_params * params)1910b84fe1SSimon Glass static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
2010b84fe1SSimon Glass struct image_tool_params *params)
2110b84fe1SSimon Glass {
2210b84fe1SSimon Glass int sector;
2310b84fe1SSimon Glass unsigned int size;
2410b84fe1SSimon Glass int ret;
2510b84fe1SSimon Glass
2610b84fe1SSimon Glass size = params->orig_file_size;
277bf274b9SJeffy Chen ret = rkcommon_set_header(buf, size, params);
2810b84fe1SSimon Glass debug("size %x\n", size);
2910b84fe1SSimon Glass if (ret) {
3010b84fe1SSimon Glass /* TODO(sjg@chromium.org): This method should return an error */
31366aad4dSPhilipp Tomsich printf("Warning: SPL image is too large (size %#x) and will "
32366aad4dSPhilipp Tomsich "not boot\n", size);
3310b84fe1SSimon Glass }
3410b84fe1SSimon Glass
3510b84fe1SSimon Glass /*
3610b84fe1SSimon Glass * Spread the image out so we only use the first 2KB of each 4KB
3710b84fe1SSimon Glass * region. This is a feature of the SPI format required by the Rockchip
3810b84fe1SSimon Glass * boot ROM. Its rationale is unknown.
3910b84fe1SSimon Glass */
4010b84fe1SSimon Glass for (sector = size / RKSPI_SECT_LEN - 1; sector >= 0; sector--) {
4125525ebeSSimon Glass debug("sector %u\n", sector);
4210b84fe1SSimon Glass memmove(buf + sector * RKSPI_SECT_LEN * 2,
4310b84fe1SSimon Glass buf + sector * RKSPI_SECT_LEN,
4410b84fe1SSimon Glass RKSPI_SECT_LEN);
4510b84fe1SSimon Glass memset(buf + sector * RKSPI_SECT_LEN * 2 + RKSPI_SECT_LEN,
4610b84fe1SSimon Glass '\0', RKSPI_SECT_LEN);
4710b84fe1SSimon Glass }
4810b84fe1SSimon Glass }
4910b84fe1SSimon Glass
rkspi_check_image_type(uint8_t type)5010b84fe1SSimon Glass static int rkspi_check_image_type(uint8_t type)
5110b84fe1SSimon Glass {
5210b84fe1SSimon Glass if (type == IH_TYPE_RKSPI)
5310b84fe1SSimon Glass return EXIT_SUCCESS;
5410b84fe1SSimon Glass else
5510b84fe1SSimon Glass return EXIT_FAILURE;
5610b84fe1SSimon Glass }
5710b84fe1SSimon Glass
58366aad4dSPhilipp Tomsich /*
59366aad4dSPhilipp Tomsich * The SPI payload needs to be padded out to make space for odd half-sector
60366aad4dSPhilipp Tomsich * layout used in flash (i.e. only the first 2K of each 4K sector is used).
61366aad4dSPhilipp Tomsich */
rkspi_vrec_header(struct image_tool_params * params,struct image_type_params * tparams)6210b84fe1SSimon Glass static int rkspi_vrec_header(struct image_tool_params *params,
6310b84fe1SSimon Glass struct image_type_params *tparams)
6410b84fe1SSimon Glass {
65ad972ac3SPhilipp Tomsich int padding = rkcommon_vrec_header(params, tparams, RK_INIT_SIZE_ALIGN);
66366aad4dSPhilipp Tomsich /*
67366aad4dSPhilipp Tomsich * The file size has not been adjusted at this point (our caller will
68366aad4dSPhilipp Tomsich * eventually add the header/padding to the file_size), so we need to
69366aad4dSPhilipp Tomsich * add up the header_size, file_size and padding ourselves.
70366aad4dSPhilipp Tomsich */
71366aad4dSPhilipp Tomsich int padded_size = tparams->header_size + params->file_size + padding;
7210b84fe1SSimon Glass
73366aad4dSPhilipp Tomsich /*
74366aad4dSPhilipp Tomsich * We need to store the original file-size (i.e. before padding), as
75366aad4dSPhilipp Tomsich * imagetool does not set this during its adjustment of file_size.
76366aad4dSPhilipp Tomsich */
77366aad4dSPhilipp Tomsich params->orig_file_size = padded_size;
78111bcc4fSPhilipp Tomsich
79366aad4dSPhilipp Tomsich /*
80366aad4dSPhilipp Tomsich * Converting to the SPI format (i.e. splitting each 4K page into two
81366aad4dSPhilipp Tomsich * 2K subpages and then padding these 2K pages up to take a complete
82366aad4dSPhilipp Tomsich * 4K sector again) will will double the image size.
83366aad4dSPhilipp Tomsich *
84366aad4dSPhilipp Tomsich * Thus we return the padded_size as an additional padding requirement
85366aad4dSPhilipp Tomsich * (be sure to add this to the padding returned from the common code).
86366aad4dSPhilipp Tomsich */
87366aad4dSPhilipp Tomsich return padded_size + padding;
8810b84fe1SSimon Glass }
8910b84fe1SSimon Glass
9010b84fe1SSimon Glass /*
9110b84fe1SSimon Glass * rk_spi parameters
9210b84fe1SSimon Glass */
9310b84fe1SSimon Glass U_BOOT_IMAGE_TYPE(
9410b84fe1SSimon Glass rkspi,
9510b84fe1SSimon Glass "Rockchip SPI Boot Image support",
96111bcc4fSPhilipp Tomsich 0,
97111bcc4fSPhilipp Tomsich NULL,
987bf274b9SJeffy Chen rkcommon_check_params,
992fb371ffSPhilipp Tomsich rkcommon_verify_header,
1002fb371ffSPhilipp Tomsich rkcommon_print_header,
10110b84fe1SSimon Glass rkspi_set_header,
1022fb371ffSPhilipp Tomsich NULL,
10310b84fe1SSimon Glass rkspi_check_image_type,
10410b84fe1SSimon Glass NULL,
10510b84fe1SSimon Glass rkspi_vrec_header
10610b84fe1SSimon Glass );
107