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 enum { 14 RKNAND_SECT_LEN = RK_BLK_SIZE * 4, 15 }; 16 17 struct rknand_info { 18 uint32_t pagesize; 19 uint32_t skippages; 20 uint32_t tplsize; 21 uint32_t splsize; 22 uint32_t tplpaddedsize; 23 uint32_t splpaddedsize; 24 uint32_t itersize; 25 uint32_t tplsplsize; 26 char *tplfile; 27 char *splfile; 28 }; 29 30 struct rknand_info ninfo; 31 32 static uint32_t rknand_get_file_size(char *filename) 33 { 34 int dfd; 35 struct stat sbuf; 36 37 dfd = open(filename, O_RDONLY | O_BINARY); 38 if (dfd < 0) { 39 fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno)); 40 exit(EXIT_FAILURE); 41 } 42 43 if (fstat(dfd, &sbuf) < 0) { 44 fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno)); 45 exit(EXIT_FAILURE); 46 } 47 48 close(dfd); 49 50 return sbuf.st_size; 51 } 52 53 static void rknand_fill_ninfo(struct image_tool_params *params) 54 { 55 sscanf(params->extraparams, "%u,%u", &ninfo.pagesize, &ninfo.skippages); 56 57 ninfo.tplfile = params->datafile; 58 if ((ninfo.splfile = strchr(params->datafile, ':')) != NULL) { 59 *ninfo.splfile = '\0'; 60 ninfo.splfile += 1; 61 } 62 63 ninfo.tplsize = rknand_get_file_size(ninfo.tplfile); 64 ninfo.splsize = rknand_get_file_size(ninfo.splfile); 65 66 ninfo.tplpaddedsize = ROUND(ninfo.tplsize, RKNAND_SECT_LEN); 67 68 ninfo.splpaddedsize = ROUND(ninfo.splsize, RKNAND_SECT_LEN); 69 70 ninfo.itersize = ninfo.pagesize * (ninfo.skippages + 1); 71 ninfo.tplsplsize = ((ninfo.tplpaddedsize + ninfo.splpaddedsize) / 72 RKNAND_SECT_LEN) * ninfo.itersize; 73 } 74 75 static void rknand_set_header(void *buf, struct stat *sbuf, int ifd, 76 struct image_tool_params *params) 77 { 78 int sector, sploffset, splfd, ret; 79 80 ret = rkcommon_set_header(buf, ninfo.tplsize, ninfo.splsize, params); 81 if (ret) { 82 printf("Warning: TPL image is too large (size %#x) and will " 83 "not boot\n", ninfo.tplsize); 84 } 85 86 if ((splfd = open(ninfo.splfile, O_RDONLY | O_BINARY)) < 0) { 87 fprintf (stderr, "%s: Can't open %s: %s\n", 88 params->cmdname, ninfo.splfile, strerror(errno)); 89 exit (EXIT_FAILURE); 90 } 91 92 sploffset = RKNAND_SECT_LEN + ninfo.tplpaddedsize; 93 if (read(splfd, buf + sploffset, ninfo.splsize) != ninfo.splsize) { 94 fprintf (stderr, "%s: Read error on %s: %s\n", 95 params->cmdname, ninfo.splfile, strerror(errno)); 96 exit (EXIT_FAILURE); 97 } 98 close(splfd); 99 100 if (rkcommon_need_rc4_spl(params)) 101 rkcommon_rc4_encode_spl(buf, sploffset, ninfo.splpaddedsize); 102 103 /* 104 * Spread the image out so we only use the first 2KB of each pagesize 105 * region. This is a feature of the NAND format required by the Rockchip 106 * boot ROM. 107 */ 108 for (sector = ninfo.tplsplsize / ninfo.itersize - 1; sector >= 0; sector--) { 109 memmove(buf + sector * ninfo.itersize + ninfo.pagesize, 110 buf + (sector + 1) * RKNAND_SECT_LEN, RKNAND_SECT_LEN); 111 112 if (sector < (ninfo.tplsplsize / ninfo.itersize - 1)) 113 memset(buf + sector * ninfo.itersize + ninfo.pagesize + 114 RKNAND_SECT_LEN, 0xFF, ninfo.itersize - 115 RKNAND_SECT_LEN); 116 } 117 memset(buf + RKNAND_SECT_LEN, 0xFF, ninfo.pagesize - RKNAND_SECT_LEN); 118 memset(buf + ninfo.tplsplsize - ninfo.pagesize + RKNAND_SECT_LEN, 0xFF, 119 ninfo.pagesize - RKNAND_SECT_LEN); 120 } 121 122 static int rknand_check_image_type(uint8_t type) 123 { 124 if (type == IH_TYPE_RKNAND) 125 return EXIT_SUCCESS; 126 else 127 return EXIT_FAILURE; 128 } 129 130 static int rknand_vrec_header(struct image_tool_params *params, 131 struct image_type_params *tparams) 132 { 133 rknand_fill_ninfo(params); 134 rkcommon_vrec_header(params, tparams, RKNAND_SECT_LEN); 135 136 return ninfo.tplsplsize - tparams->header_size - ninfo.tplsize; 137 } 138 139 /* 140 * rknand parameters 141 */ 142 U_BOOT_IMAGE_TYPE( 143 rknand, 144 "Rockchip NAND Boot Image support", 145 0, 146 NULL, 147 rkcommon_check_params, 148 rkcommon_verify_header, 149 rkcommon_print_header, 150 rknand_set_header, 151 NULL, 152 rknand_check_image_type, 153 NULL, 154 rknand_vrec_header 155 ); 156