1 /*
2 * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include "imagetool.h"
8 #include <image.h>
9 #include <rc4.h>
10 #include "mkimage.h"
11 #include "rkcommon.h"
12
13 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
14
15 enum {
16 RKNAND_SECT_LEN = RK_BLK_SIZE * 4,
17 };
18
19 struct rknand_info {
20 uint32_t pagesize;
21 uint32_t itersize;
22 uint32_t tplsplsize;
23 };
24
25 struct rknand_info ninfo;
26
rknand_set_header(void * buf,struct stat * sbuf,int ifd,struct image_tool_params * params)27 static void rknand_set_header(void *buf, struct stat *sbuf, int ifd,
28 struct image_tool_params *params)
29 {
30 int sector;
31 unsigned int size;
32
33 size = params->orig_file_size;
34
35 rkcommon_set_header(buf, sbuf, ifd, params);
36
37 /*
38 * Spread the image out so we only use the first 2KB of each pagesize
39 * region. This is a feature of the NAND format required by the Rockchip
40 * boot ROM.
41 */
42 if (params->vflag)
43 fprintf(stderr, "Spreading nand image from %u to %u\n",
44 size, params->file_size);
45
46 for (sector = ninfo.tplsplsize / ninfo.itersize - 1; sector >= 0;
47 sector--) {
48 memmove(buf + ninfo.pagesize + sector * ninfo.itersize,
49 buf + RK_SPL_HDR_START + sector * RKNAND_SECT_LEN,
50 RKNAND_SECT_LEN);
51
52 memset(buf + ninfo.pagesize + sector * ninfo.itersize +
53 RKNAND_SECT_LEN, 0xFF,
54 ninfo.itersize - RKNAND_SECT_LEN);
55 }
56
57 /* Fill up padded area of the header. */
58 memset(buf + RK_SPL_HDR_START, 0xFF, ninfo.pagesize - RK_SPL_HDR_START);
59 }
60
rknand_check_image_type(uint8_t type)61 static int rknand_check_image_type(uint8_t type)
62 {
63 if (type == IH_TYPE_RKNAND)
64 return EXIT_SUCCESS;
65 else
66 return EXIT_FAILURE;
67 }
68
rknand_vrec_header(struct image_tool_params * params,struct image_type_params * tparams)69 static int rknand_vrec_header(struct image_tool_params *params,
70 struct image_type_params *tparams)
71 {
72 int tplsplsize;
73 uint32_t skippages;
74 int ret;
75
76 rkcommon_vrec_header(params, tparams);
77
78 ret = sscanf(params->extraparams, "%u,%u", &ninfo.pagesize, &skippages);
79 if (ret != 2 || (ninfo.pagesize % RKNAND_SECT_LEN)) {
80 fprintf(stderr, "%s: Wrong nand params\n", params->cmdname);
81 exit(EXIT_FAILURE);
82 }
83
84 ninfo.itersize = ninfo.pagesize * (skippages + 1);
85
86 tplsplsize = params->file_size - RK_SPL_HDR_START;
87 ninfo.tplsplsize =
88 DIV_ROUND_UP(tplsplsize, RKNAND_SECT_LEN) * ninfo.itersize;
89
90 /* Padded file size = padded header + padded tpl & spl. */
91 params->file_size = ninfo.pagesize + ninfo.tplsplsize;
92
93 return 0;
94 }
95
96 /*
97 * rknand parameters
98 */
99 U_BOOT_IMAGE_TYPE(
100 rknand,
101 "Rockchip NAND Boot Image support",
102 0,
103 NULL,
104 rkcommon_check_params,
105 /* TODO: Support rknand in there helpers */
106 NULL, //rkcommon_verify_header,
107 NULL, //rkcommon_print_header,
108 rknand_set_header,
109 NULL,
110 rknand_check_image_type,
111 NULL,
112 rknand_vrec_header
113 );
114