xref: /openbmc/u-boot/tools/rkspi.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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