1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2011
3*4882a593Smuzhiyun * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Based on:
6*4882a593Smuzhiyun * (C) Copyright 2009
7*4882a593Smuzhiyun * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * (C) Copyright 2008
10*4882a593Smuzhiyun * Marvell Semiconductor <www.marvell.com>
11*4882a593Smuzhiyun * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "imagetool.h"
17*4882a593Smuzhiyun #include <image.h>
18*4882a593Smuzhiyun #include "ublimage.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun * Supported commands for configuration file
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun static table_entry_t ublimage_cmds[] = {
24*4882a593Smuzhiyun {CMD_BOOT_MODE, "MODE", "UBL special modes", },
25*4882a593Smuzhiyun {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", },
26*4882a593Smuzhiyun {CMD_PAGE, "PAGES",
27*4882a593Smuzhiyun "number of pages (size of bootloader)", },
28*4882a593Smuzhiyun {CMD_ST_BLOCK, "START_BLOCK",
29*4882a593Smuzhiyun "block number where bootloader is present", },
30*4882a593Smuzhiyun {CMD_ST_PAGE, "START_PAGE",
31*4882a593Smuzhiyun "page number where bootloader is present", },
32*4882a593Smuzhiyun {CMD_LD_ADDR, "LD_ADDR",
33*4882a593Smuzhiyun "load addr", },
34*4882a593Smuzhiyun {-1, "", "", },
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun * Supported Boot options for configuration file
39*4882a593Smuzhiyun * this is needed to set the correct flash offset
40*4882a593Smuzhiyun */
41*4882a593Smuzhiyun static table_entry_t ublimage_bootops[] = {
42*4882a593Smuzhiyun {UBL_MAGIC_SAFE, "safe", "Safe boot mode", },
43*4882a593Smuzhiyun {-1, "", "Invalid", },
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun static struct ubl_header ublimage_header;
47*4882a593Smuzhiyun
get_cfg_value(char * token,char * name,int linenr)48*4882a593Smuzhiyun static uint32_t get_cfg_value(char *token, char *name, int linenr)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun char *endptr;
51*4882a593Smuzhiyun uint32_t value;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun errno = 0;
54*4882a593Smuzhiyun value = strtoul(token, &endptr, 16);
55*4882a593Smuzhiyun if (errno || (token == endptr)) {
56*4882a593Smuzhiyun fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n",
57*4882a593Smuzhiyun name, linenr, token);
58*4882a593Smuzhiyun exit(EXIT_FAILURE);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun return value;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
print_hdr(struct ubl_header * ubl_hdr)63*4882a593Smuzhiyun static void print_hdr(struct ubl_header *ubl_hdr)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun printf("Image Type : Davinci UBL Boot Image\n");
66*4882a593Smuzhiyun printf("UBL magic : %08x\n", ubl_hdr->magic);
67*4882a593Smuzhiyun printf("Entry Point: %08x\n", ubl_hdr->entry);
68*4882a593Smuzhiyun printf("nr of pages: %08x\n", ubl_hdr->pages);
69*4882a593Smuzhiyun printf("start block: %08x\n", ubl_hdr->block);
70*4882a593Smuzhiyun printf("start page : %08x\n", ubl_hdr->page);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
parse_cfg_cmd(struct ubl_header * ublhdr,int32_t cmd,char * token,char * name,int lineno,int fld,int dcd_len)73*4882a593Smuzhiyun static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token,
74*4882a593Smuzhiyun char *name, int lineno, int fld, int dcd_len)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun static int cmd_ver_first = ~0;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun switch (cmd) {
79*4882a593Smuzhiyun case CMD_BOOT_MODE:
80*4882a593Smuzhiyun ublhdr->magic = get_table_entry_id(ublimage_bootops,
81*4882a593Smuzhiyun "ublimage special boot mode", token);
82*4882a593Smuzhiyun if (ublhdr->magic == -1) {
83*4882a593Smuzhiyun fprintf(stderr, "Error: %s[%d] -Invalid boot mode"
84*4882a593Smuzhiyun "(%s)\n", name, lineno, token);
85*4882a593Smuzhiyun exit(EXIT_FAILURE);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun ublhdr->magic += UBL_MAGIC_BASE;
88*4882a593Smuzhiyun if (unlikely(cmd_ver_first != 1))
89*4882a593Smuzhiyun cmd_ver_first = 0;
90*4882a593Smuzhiyun break;
91*4882a593Smuzhiyun case CMD_ENTRY:
92*4882a593Smuzhiyun ublhdr->entry = get_cfg_value(token, name, lineno);
93*4882a593Smuzhiyun break;
94*4882a593Smuzhiyun case CMD_PAGE:
95*4882a593Smuzhiyun ublhdr->pages = get_cfg_value(token, name, lineno);
96*4882a593Smuzhiyun break;
97*4882a593Smuzhiyun case CMD_ST_BLOCK:
98*4882a593Smuzhiyun ublhdr->block = get_cfg_value(token, name, lineno);
99*4882a593Smuzhiyun break;
100*4882a593Smuzhiyun case CMD_ST_PAGE:
101*4882a593Smuzhiyun ublhdr->page = get_cfg_value(token, name, lineno);
102*4882a593Smuzhiyun break;
103*4882a593Smuzhiyun case CMD_LD_ADDR:
104*4882a593Smuzhiyun ublhdr->pll_m = get_cfg_value(token, name, lineno);
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
parse_cfg_fld(struct ubl_header * ublhdr,int32_t * cmd,char * token,char * name,int lineno,int fld,int * dcd_len)109*4882a593Smuzhiyun static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd,
110*4882a593Smuzhiyun char *token, char *name, int lineno, int fld, int *dcd_len)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun switch (fld) {
114*4882a593Smuzhiyun case CFG_COMMAND:
115*4882a593Smuzhiyun *cmd = get_table_entry_id(ublimage_cmds,
116*4882a593Smuzhiyun "ublimage commands", token);
117*4882a593Smuzhiyun if (*cmd < 0) {
118*4882a593Smuzhiyun fprintf(stderr, "Error: %s[%d] - Invalid command"
119*4882a593Smuzhiyun "(%s)\n", name, lineno, token);
120*4882a593Smuzhiyun exit(EXIT_FAILURE);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun break;
123*4882a593Smuzhiyun case CFG_REG_VALUE:
124*4882a593Smuzhiyun parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len);
125*4882a593Smuzhiyun break;
126*4882a593Smuzhiyun default:
127*4882a593Smuzhiyun break;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun }
parse_cfg_file(struct ubl_header * ublhdr,char * name)130*4882a593Smuzhiyun static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun FILE *fd = NULL;
133*4882a593Smuzhiyun char *line = NULL;
134*4882a593Smuzhiyun char *token, *saveptr1, *saveptr2;
135*4882a593Smuzhiyun int lineno = 0;
136*4882a593Smuzhiyun int i;
137*4882a593Smuzhiyun char *ptr = (char *)ublhdr;
138*4882a593Smuzhiyun int fld;
139*4882a593Smuzhiyun size_t len;
140*4882a593Smuzhiyun int dcd_len = 0;
141*4882a593Smuzhiyun int32_t cmd;
142*4882a593Smuzhiyun int ublhdrlen = sizeof(struct ubl_header);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun fd = fopen(name, "r");
145*4882a593Smuzhiyun if (fd == 0) {
146*4882a593Smuzhiyun fprintf(stderr, "Error: %s - Can't open DCD file\n", name);
147*4882a593Smuzhiyun exit(EXIT_FAILURE);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* Fill header with 0xff */
151*4882a593Smuzhiyun for (i = 0; i < ublhdrlen; i++) {
152*4882a593Smuzhiyun *ptr = 0xff;
153*4882a593Smuzhiyun ptr++;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun * Very simple parsing, line starting with # are comments
158*4882a593Smuzhiyun * and are dropped
159*4882a593Smuzhiyun */
160*4882a593Smuzhiyun while ((getline(&line, &len, fd)) > 0) {
161*4882a593Smuzhiyun lineno++;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun token = strtok_r(line, "\r\n", &saveptr1);
164*4882a593Smuzhiyun if (token == NULL)
165*4882a593Smuzhiyun continue;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* Check inside the single line */
168*4882a593Smuzhiyun for (fld = CFG_COMMAND, cmd = CMD_INVALID,
169*4882a593Smuzhiyun line = token; ; line = NULL, fld++) {
170*4882a593Smuzhiyun token = strtok_r(line, " \t", &saveptr2);
171*4882a593Smuzhiyun if (token == NULL)
172*4882a593Smuzhiyun break;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /* Drop all text starting with '#' as comments */
175*4882a593Smuzhiyun if (token[0] == '#')
176*4882a593Smuzhiyun break;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun parse_cfg_fld(ublhdr, &cmd, token, name,
179*4882a593Smuzhiyun lineno, fld, &dcd_len);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun fclose(fd);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun return dcd_len;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
ublimage_check_image_types(uint8_t type)187*4882a593Smuzhiyun static int ublimage_check_image_types(uint8_t type)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun if (type == IH_TYPE_UBLIMAGE)
190*4882a593Smuzhiyun return EXIT_SUCCESS;
191*4882a593Smuzhiyun else
192*4882a593Smuzhiyun return EXIT_FAILURE;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
ublimage_verify_header(unsigned char * ptr,int image_size,struct image_tool_params * params)195*4882a593Smuzhiyun static int ublimage_verify_header(unsigned char *ptr, int image_size,
196*4882a593Smuzhiyun struct image_tool_params *params)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct ubl_header *ubl_hdr = (struct ubl_header *)ptr;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if ((ubl_hdr->magic & 0xFFFFFF00) != UBL_MAGIC_BASE)
201*4882a593Smuzhiyun return -1;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return 0;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
ublimage_print_header(const void * ptr)206*4882a593Smuzhiyun static void ublimage_print_header(const void *ptr)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct ubl_header *ubl_hdr = (struct ubl_header *) ptr;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun print_hdr(ubl_hdr);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
ublimage_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)213*4882a593Smuzhiyun static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd,
214*4882a593Smuzhiyun struct image_tool_params *params)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun struct ubl_header *ublhdr = (struct ubl_header *)ptr;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* Parse configuration file */
219*4882a593Smuzhiyun parse_cfg_file(ublhdr, params->imagename);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
ublimage_check_params(struct image_tool_params * params)222*4882a593Smuzhiyun int ublimage_check_params(struct image_tool_params *params)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun if (!params)
225*4882a593Smuzhiyun return CFG_INVALID;
226*4882a593Smuzhiyun if (!strlen(params->imagename)) {
227*4882a593Smuzhiyun fprintf(stderr, "Error: %s - Configuration file not"
228*4882a593Smuzhiyun "specified, it is needed for ublimage generation\n",
229*4882a593Smuzhiyun params->cmdname);
230*4882a593Smuzhiyun return CFG_INVALID;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun /*
233*4882a593Smuzhiyun * Check parameters:
234*4882a593Smuzhiyun * XIP is not allowed and verify that incompatible
235*4882a593Smuzhiyun * parameters are not sent at the same time
236*4882a593Smuzhiyun * For example, if list is required a data image must not be provided
237*4882a593Smuzhiyun */
238*4882a593Smuzhiyun return (params->dflag && (params->fflag || params->lflag)) ||
239*4882a593Smuzhiyun (params->fflag && (params->dflag || params->lflag)) ||
240*4882a593Smuzhiyun (params->lflag && (params->dflag || params->fflag)) ||
241*4882a593Smuzhiyun (params->xflag) || !(strlen(params->imagename));
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /*
245*4882a593Smuzhiyun * ublimage parameters
246*4882a593Smuzhiyun */
247*4882a593Smuzhiyun U_BOOT_IMAGE_TYPE(
248*4882a593Smuzhiyun ublimage,
249*4882a593Smuzhiyun "Davinci UBL boot support",
250*4882a593Smuzhiyun sizeof(struct ubl_header),
251*4882a593Smuzhiyun (void *)&ublimage_header,
252*4882a593Smuzhiyun ublimage_check_params,
253*4882a593Smuzhiyun ublimage_verify_header,
254*4882a593Smuzhiyun ublimage_print_header,
255*4882a593Smuzhiyun ublimage_set_header,
256*4882a593Smuzhiyun NULL,
257*4882a593Smuzhiyun ublimage_check_image_types,
258*4882a593Smuzhiyun NULL,
259*4882a593Smuzhiyun NULL
260*4882a593Smuzhiyun );
261