Commit 2db1c3fc673c2ddfa1f8dbb41326d9763ea0ae64
Committed by
Tom Rini
1 parent
1fd1e2f69f
Exists in
master
and in
53 other branches
tools/Makefile: Move _GNU_SOURCE to Makefile
Commit 669dfc2e adds libfdt_env.h to HOSTCPPFLAGS. It causes stdio.h to be included before _GNU_SOURCE is defined in C files. On some old hosts some prototypes are protected by #ifdef __USE_GNU, which is set when _GNU_SOURCE is defined. Signed-off-by: York Sun <yorksun@freescale.com> Acked-by: Simon Glass <sjg@chromium.org>
Showing 8 changed files with 3 additions and 21 deletions Inline Diff
tools/Makefile
1 | # | 1 | # |
2 | # (C) Copyright 2000-2006 | 2 | # (C) Copyright 2000-2006 |
3 | # Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 3 | # Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | # | 4 | # |
5 | # SPDX-License-Identifier: GPL-2.0+ | 5 | # SPDX-License-Identifier: GPL-2.0+ |
6 | # | 6 | # |
7 | 7 | ||
8 | TOOLSUBDIRS = kernel-doc | 8 | TOOLSUBDIRS = kernel-doc |
9 | 9 | ||
10 | # | 10 | # |
11 | # Include this after HOSTOS HOSTARCH check | 11 | # Include this after HOSTOS HOSTARCH check |
12 | # so that we can act intelligently. | 12 | # so that we can act intelligently. |
13 | # | 13 | # |
14 | include $(TOPDIR)/config.mk | 14 | include $(TOPDIR)/config.mk |
15 | 15 | ||
16 | # | 16 | # |
17 | # toolchains targeting win32 generate .exe files | 17 | # toolchains targeting win32 generate .exe files |
18 | # | 18 | # |
19 | ifneq (,$(findstring WIN32 ,$(shell $(HOSTCC) -E -dM -xc /dev/null))) | 19 | ifneq (,$(findstring WIN32 ,$(shell $(HOSTCC) -E -dM -xc /dev/null))) |
20 | SFX = .exe | 20 | SFX = .exe |
21 | else | 21 | else |
22 | SFX = | 22 | SFX = |
23 | endif | 23 | endif |
24 | 24 | ||
25 | # Enable all the config-independent tools | 25 | # Enable all the config-independent tools |
26 | ifneq ($(HOST_TOOLS_ALL),) | 26 | ifneq ($(HOST_TOOLS_ALL),) |
27 | CONFIG_LCD_LOGO = y | 27 | CONFIG_LCD_LOGO = y |
28 | CONFIG_CMD_LOADS = y | 28 | CONFIG_CMD_LOADS = y |
29 | CONFIG_CMD_NET = y | 29 | CONFIG_CMD_NET = y |
30 | CONFIG_XWAY_SWAP_BYTES = y | 30 | CONFIG_XWAY_SWAP_BYTES = y |
31 | CONFIG_NETCONSOLE = y | 31 | CONFIG_NETCONSOLE = y |
32 | CONFIG_SHA1_CHECK_UB_IMG = y | 32 | CONFIG_SHA1_CHECK_UB_IMG = y |
33 | endif | 33 | endif |
34 | 34 | ||
35 | # Merge all the different vars for envcrc into one | 35 | # Merge all the different vars for envcrc into one |
36 | ENVCRC-$(CONFIG_ENV_IS_EMBEDDED) = y | 36 | ENVCRC-$(CONFIG_ENV_IS_EMBEDDED) = y |
37 | ENVCRC-$(CONFIG_ENV_IS_IN_DATAFLASH) = y | 37 | ENVCRC-$(CONFIG_ENV_IS_IN_DATAFLASH) = y |
38 | ENVCRC-$(CONFIG_ENV_IS_IN_EEPROM) = y | 38 | ENVCRC-$(CONFIG_ENV_IS_IN_EEPROM) = y |
39 | ENVCRC-$(CONFIG_ENV_IS_IN_FLASH) = y | 39 | ENVCRC-$(CONFIG_ENV_IS_IN_FLASH) = y |
40 | ENVCRC-$(CONFIG_ENV_IS_IN_ONENAND) = y | 40 | ENVCRC-$(CONFIG_ENV_IS_IN_ONENAND) = y |
41 | ENVCRC-$(CONFIG_ENV_IS_IN_NAND) = y | 41 | ENVCRC-$(CONFIG_ENV_IS_IN_NAND) = y |
42 | ENVCRC-$(CONFIG_ENV_IS_IN_NVRAM) = y | 42 | ENVCRC-$(CONFIG_ENV_IS_IN_NVRAM) = y |
43 | ENVCRC-$(CONFIG_ENV_IS_IN_SPI_FLASH) = y | 43 | ENVCRC-$(CONFIG_ENV_IS_IN_SPI_FLASH) = y |
44 | CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y) | 44 | CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y) |
45 | 45 | ||
46 | # Generated executable files | 46 | # Generated executable files |
47 | BIN_FILES-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX) | 47 | BIN_FILES-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX) |
48 | BIN_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX) | 48 | BIN_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX) |
49 | BIN_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc$(SFX) | 49 | BIN_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc$(SFX) |
50 | BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX) | 50 | BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX) |
51 | BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX) | 51 | BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX) |
52 | BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) | 52 | BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) |
53 | BIN_FILES-y += mkenvimage$(SFX) | 53 | BIN_FILES-y += mkenvimage$(SFX) |
54 | BIN_FILES-y += mkimage$(SFX) | 54 | BIN_FILES-y += mkimage$(SFX) |
55 | BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) | 55 | BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) |
56 | BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) | 56 | BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) |
57 | BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) | 57 | BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) |
58 | BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) | 58 | BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) |
59 | BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX) | 59 | BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX) |
60 | BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX) | 60 | BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX) |
61 | BIN_FILES-y += proftool(SFX) | 61 | BIN_FILES-y += proftool(SFX) |
62 | 62 | ||
63 | # Source files which exist outside the tools directory | 63 | # Source files which exist outside the tools directory |
64 | EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o | 64 | EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o |
65 | EXT_OBJ_FILES-y += common/image.o | 65 | EXT_OBJ_FILES-y += common/image.o |
66 | EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o | 66 | EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o |
67 | EXT_OBJ_FILES-y += common/image-sig.o | 67 | EXT_OBJ_FILES-y += common/image-sig.o |
68 | EXT_OBJ_FILES-y += lib/crc32.o | 68 | EXT_OBJ_FILES-y += lib/crc32.o |
69 | EXT_OBJ_FILES-y += lib/md5.o | 69 | EXT_OBJ_FILES-y += lib/md5.o |
70 | EXT_OBJ_FILES-y += lib/sha1.o | 70 | EXT_OBJ_FILES-y += lib/sha1.o |
71 | 71 | ||
72 | # Source files located in the tools directory | 72 | # Source files located in the tools directory |
73 | OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o | 73 | OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o |
74 | OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o | 74 | OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o |
75 | NOPED_OBJ_FILES-y += default_image.o | 75 | NOPED_OBJ_FILES-y += default_image.o |
76 | NOPED_OBJ_FILES-y += proftool.o | 76 | NOPED_OBJ_FILES-y += proftool.o |
77 | OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o | 77 | OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o |
78 | NOPED_OBJ_FILES-y += fit_image.o | 78 | NOPED_OBJ_FILES-y += fit_image.o |
79 | OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o | 79 | OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o |
80 | OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o | 80 | OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o |
81 | OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o | 81 | OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o |
82 | NOPED_OBJ_FILES-y += aisimage.o | 82 | NOPED_OBJ_FILES-y += aisimage.o |
83 | NOPED_OBJ_FILES-y += kwbimage.o | 83 | NOPED_OBJ_FILES-y += kwbimage.o |
84 | NOPED_OBJ_FILES-y += pblimage.o | 84 | NOPED_OBJ_FILES-y += pblimage.o |
85 | NOPED_OBJ_FILES-y += imximage.o | 85 | NOPED_OBJ_FILES-y += imximage.o |
86 | NOPED_OBJ_FILES-y += image-host.o | 86 | NOPED_OBJ_FILES-y += image-host.o |
87 | NOPED_OBJ_FILES-y += omapimage.o | 87 | NOPED_OBJ_FILES-y += omapimage.o |
88 | NOPED_OBJ_FILES-y += mkenvimage.o | 88 | NOPED_OBJ_FILES-y += mkenvimage.o |
89 | NOPED_OBJ_FILES-y += mkimage.o | 89 | NOPED_OBJ_FILES-y += mkimage.o |
90 | OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o | 90 | OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o |
91 | OBJ_FILES-$(CONFIG_MX23) += mxsboot.o | 91 | OBJ_FILES-$(CONFIG_MX23) += mxsboot.o |
92 | OBJ_FILES-$(CONFIG_MX28) += mxsboot.o | 92 | OBJ_FILES-$(CONFIG_MX28) += mxsboot.o |
93 | OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o | 93 | OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o |
94 | NOPED_OBJ_FILES-y += os_support.o | 94 | NOPED_OBJ_FILES-y += os_support.o |
95 | OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o | 95 | OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o |
96 | NOPED_OBJ_FILES-y += ublimage.o | 96 | NOPED_OBJ_FILES-y += ublimage.o |
97 | OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o | 97 | OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o |
98 | 98 | ||
99 | # Don't build by default | 99 | # Don't build by default |
100 | #ifeq ($(ARCH),ppc) | 100 | #ifeq ($(ARCH),ppc) |
101 | #BIN_FILES-y += mpc86x_clk$(SFX) | 101 | #BIN_FILES-y += mpc86x_clk$(SFX) |
102 | #OBJ_FILES-y += mpc86x_clk.o | 102 | #OBJ_FILES-y += mpc86x_clk.o |
103 | #endif | 103 | #endif |
104 | 104 | ||
105 | # Flattened device tree objects | 105 | # Flattened device tree objects |
106 | LIBFDT_OBJ_FILES-y += fdt.o | 106 | LIBFDT_OBJ_FILES-y += fdt.o |
107 | LIBFDT_OBJ_FILES-y += fdt_ro.o | 107 | LIBFDT_OBJ_FILES-y += fdt_ro.o |
108 | LIBFDT_OBJ_FILES-y += fdt_rw.o | 108 | LIBFDT_OBJ_FILES-y += fdt_rw.o |
109 | LIBFDT_OBJ_FILES-y += fdt_strerror.o | 109 | LIBFDT_OBJ_FILES-y += fdt_strerror.o |
110 | LIBFDT_OBJ_FILES-y += fdt_wip.o | 110 | LIBFDT_OBJ_FILES-y += fdt_wip.o |
111 | 111 | ||
112 | # RSA objects | 112 | # RSA objects |
113 | RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o | 113 | RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o |
114 | 114 | ||
115 | # Generated LCD/video logo | 115 | # Generated LCD/video logo |
116 | LOGO_H = $(OBJTREE)/include/bmp_logo.h | 116 | LOGO_H = $(OBJTREE)/include/bmp_logo.h |
117 | LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h | 117 | LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h |
118 | LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H) | 118 | LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H) |
119 | LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_DATA_H) | 119 | LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_DATA_H) |
120 | LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H) | 120 | LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H) |
121 | LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_DATA_H) | 121 | LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_DATA_H) |
122 | 122 | ||
123 | # Generic logo | 123 | # Generic logo |
124 | ifeq ($(LOGO_BMP),) | 124 | ifeq ($(LOGO_BMP),) |
125 | LOGO_BMP= logos/denx.bmp | 125 | LOGO_BMP= logos/denx.bmp |
126 | 126 | ||
127 | # Use board logo and fallback to vendor | 127 | # Use board logo and fallback to vendor |
128 | ifneq ($(wildcard logos/$(BOARD).bmp),) | 128 | ifneq ($(wildcard logos/$(BOARD).bmp),) |
129 | LOGO_BMP= logos/$(BOARD).bmp | 129 | LOGO_BMP= logos/$(BOARD).bmp |
130 | else | 130 | else |
131 | ifneq ($(wildcard logos/$(VENDOR).bmp),) | 131 | ifneq ($(wildcard logos/$(VENDOR).bmp),) |
132 | LOGO_BMP= logos/$(VENDOR).bmp | 132 | LOGO_BMP= logos/$(VENDOR).bmp |
133 | endif | 133 | endif |
134 | endif | 134 | endif |
135 | 135 | ||
136 | endif # !LOGO_BMP | 136 | endif # !LOGO_BMP |
137 | 137 | ||
138 | # now $(obj) is defined | 138 | # now $(obj) is defined |
139 | HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) | 139 | HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) |
140 | HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) | 140 | HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) |
141 | HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) | 141 | HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) |
142 | HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(RSA_OBJ_FILES-y:.o=.c)) | 142 | HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(RSA_OBJ_FILES-y:.o=.c)) |
143 | BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) | 143 | BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) |
144 | LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) | 144 | LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) |
145 | RSA_OBJS := $(addprefix $(obj),$(RSA_OBJ_FILES-y)) | 145 | RSA_OBJS := $(addprefix $(obj),$(RSA_OBJ_FILES-y)) |
146 | 146 | ||
147 | # We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host | 147 | # We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host |
148 | FIT_SIG_OBJ_FILES := image-sig.o | 148 | FIT_SIG_OBJ_FILES := image-sig.o |
149 | FIT_SIG_OBJS := $(addprefix $(obj),$(FIT_SIG_OBJ_FILES)) | 149 | FIT_SIG_OBJS := $(addprefix $(obj),$(FIT_SIG_OBJ_FILES)) |
150 | 150 | ||
151 | HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y)) | 151 | HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y)) |
152 | NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y)) | 152 | NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y)) |
153 | 153 | ||
154 | # | 154 | # |
155 | # Use native tools and options | 155 | # Use native tools and options |
156 | # Define __KERNEL_STRICT_NAMES to prevent typedef overlaps | 156 | # Define __KERNEL_STRICT_NAMES to prevent typedef overlaps |
157 | # Define _GNU_SOURCE to obtain the getline prototype from stdio.h | ||
157 | # | 158 | # |
158 | HOSTCPPFLAGS = -include $(SRCTREE)/include/libfdt_env.h \ | 159 | HOSTCPPFLAGS = -include $(SRCTREE)/include/libfdt_env.h \ |
159 | -idirafter $(SRCTREE)/include \ | 160 | -idirafter $(SRCTREE)/include \ |
160 | -idirafter $(OBJTREE)/include2 \ | 161 | -idirafter $(OBJTREE)/include2 \ |
161 | -idirafter $(OBJTREE)/include \ | 162 | -idirafter $(OBJTREE)/include \ |
162 | -I $(SRCTREE)/lib/libfdt \ | 163 | -I $(SRCTREE)/lib/libfdt \ |
163 | -I $(SRCTREE)/tools \ | 164 | -I $(SRCTREE)/tools \ |
164 | -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \ | 165 | -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \ |
165 | -DUSE_HOSTCC \ | 166 | -DUSE_HOSTCC \ |
166 | -D__KERNEL_STRICT_NAMES | 167 | -D__KERNEL_STRICT_NAMES \ |
168 | -D_GNU_SOURCE | ||
167 | 169 | ||
168 | 170 | ||
169 | all: $(obj).depend $(BINS) $(LOGO-y) subdirs | 171 | all: $(obj).depend $(BINS) $(LOGO-y) subdirs |
170 | 172 | ||
171 | $(obj)bin2header$(SFX): $(obj)bin2header.o | 173 | $(obj)bin2header$(SFX): $(obj)bin2header.o |
172 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 174 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
173 | $(HOSTSTRIP) $@ | 175 | $(HOSTSTRIP) $@ |
174 | 176 | ||
175 | $(obj)bmp_logo$(SFX): $(obj)bmp_logo.o | 177 | $(obj)bmp_logo$(SFX): $(obj)bmp_logo.o |
176 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 178 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
177 | $(HOSTSTRIP) $@ | 179 | $(HOSTSTRIP) $@ |
178 | 180 | ||
179 | $(obj)proftool(SFX): $(obj)proftool.o | 181 | $(obj)proftool(SFX): $(obj)proftool.o |
180 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 182 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
181 | $(HOSTSTRIP) $@ | 183 | $(HOSTSTRIP) $@ |
182 | 184 | ||
183 | $(obj)envcrc$(SFX): $(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o | 185 | $(obj)envcrc$(SFX): $(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o |
184 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 186 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
185 | 187 | ||
186 | $(obj)gen_eth_addr$(SFX): $(obj)gen_eth_addr.o | 188 | $(obj)gen_eth_addr$(SFX): $(obj)gen_eth_addr.o |
187 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 189 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
188 | $(HOSTSTRIP) $@ | 190 | $(HOSTSTRIP) $@ |
189 | 191 | ||
190 | $(obj)img2srec$(SFX): $(obj)img2srec.o | 192 | $(obj)img2srec$(SFX): $(obj)img2srec.o |
191 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 193 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
192 | $(HOSTSTRIP) $@ | 194 | $(HOSTSTRIP) $@ |
193 | 195 | ||
194 | $(obj)xway-swap-bytes$(SFX): $(obj)xway-swap-bytes.o | 196 | $(obj)xway-swap-bytes$(SFX): $(obj)xway-swap-bytes.o |
195 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 197 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
196 | $(HOSTSTRIP) $@ | 198 | $(HOSTSTRIP) $@ |
197 | 199 | ||
198 | $(obj)mkenvimage$(SFX): $(obj)crc32.o $(obj)mkenvimage.o \ | 200 | $(obj)mkenvimage$(SFX): $(obj)crc32.o $(obj)mkenvimage.o \ |
199 | $(obj)os_support.o | 201 | $(obj)os_support.o |
200 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 202 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
201 | $(HOSTSTRIP) $@ | 203 | $(HOSTSTRIP) $@ |
202 | 204 | ||
203 | $(obj)mkimage$(SFX): $(obj)aisimage.o \ | 205 | $(obj)mkimage$(SFX): $(obj)aisimage.o \ |
204 | $(obj)crc32.o \ | 206 | $(obj)crc32.o \ |
205 | $(obj)default_image.o \ | 207 | $(obj)default_image.o \ |
206 | $(obj)fit_image.o \ | 208 | $(obj)fit_image.o \ |
207 | $(obj)image-fit.o \ | 209 | $(obj)image-fit.o \ |
208 | $(obj)image.o \ | 210 | $(obj)image.o \ |
209 | $(obj)image-host.o \ | 211 | $(obj)image-host.o \ |
210 | $(FIT_SIG_OBJS) \ | 212 | $(FIT_SIG_OBJS) \ |
211 | $(obj)imximage.o \ | 213 | $(obj)imximage.o \ |
212 | $(obj)kwbimage.o \ | 214 | $(obj)kwbimage.o \ |
213 | $(obj)pblimage.o \ | 215 | $(obj)pblimage.o \ |
214 | $(obj)md5.o \ | 216 | $(obj)md5.o \ |
215 | $(obj)mkimage.o \ | 217 | $(obj)mkimage.o \ |
216 | $(obj)os_support.o \ | 218 | $(obj)os_support.o \ |
217 | $(obj)omapimage.o \ | 219 | $(obj)omapimage.o \ |
218 | $(obj)sha1.o \ | 220 | $(obj)sha1.o \ |
219 | $(obj)ublimage.o \ | 221 | $(obj)ublimage.o \ |
220 | $(LIBFDT_OBJS) \ | 222 | $(LIBFDT_OBJS) \ |
221 | $(RSA_OBJS) | 223 | $(RSA_OBJS) |
222 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) | 224 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) |
223 | $(HOSTSTRIP) $@ | 225 | $(HOSTSTRIP) $@ |
224 | 226 | ||
225 | $(obj)mk$(BOARD)spl$(SFX): $(obj)mkexynosspl.o | 227 | $(obj)mk$(BOARD)spl$(SFX): $(obj)mkexynosspl.o |
226 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 228 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
227 | $(HOSTSTRIP) $@ | 229 | $(HOSTSTRIP) $@ |
228 | 230 | ||
229 | $(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o | 231 | $(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o |
230 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 232 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
231 | $(HOSTSTRIP) $@ | 233 | $(HOSTSTRIP) $@ |
232 | 234 | ||
233 | $(obj)mxsboot$(SFX): $(obj)mxsboot.o | 235 | $(obj)mxsboot$(SFX): $(obj)mxsboot.o |
234 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 236 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
235 | $(HOSTSTRIP) $@ | 237 | $(HOSTSTRIP) $@ |
236 | 238 | ||
237 | $(obj)ncb$(SFX): $(obj)ncb.o | 239 | $(obj)ncb$(SFX): $(obj)ncb.o |
238 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 240 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
239 | $(HOSTSTRIP) $@ | 241 | $(HOSTSTRIP) $@ |
240 | 242 | ||
241 | $(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o | 243 | $(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o |
242 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 244 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
243 | 245 | ||
244 | $(obj)kwboot$(SFX): $(obj)kwboot.o | 246 | $(obj)kwboot$(SFX): $(obj)kwboot.o |
245 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ | 247 | $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ |
246 | $(HOSTSTRIP) $@ | 248 | $(HOSTSTRIP) $@ |
247 | 249 | ||
248 | # Some of the tool objects need to be accessed from outside the tools directory | 250 | # Some of the tool objects need to be accessed from outside the tools directory |
249 | $(obj)%.o: $(SRCTREE)/common/%.c | 251 | $(obj)%.o: $(SRCTREE)/common/%.c |
250 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< | 252 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< |
251 | 253 | ||
252 | $(obj)%.o: $(SRCTREE)/lib/%.c | 254 | $(obj)%.o: $(SRCTREE)/lib/%.c |
253 | $(HOSTCC) -g $(HOSTCFLAGS) -c -o $@ $< | 255 | $(HOSTCC) -g $(HOSTCFLAGS) -c -o $@ $< |
254 | 256 | ||
255 | $(obj)%.o: $(SRCTREE)/lib/libfdt/%.c | 257 | $(obj)%.o: $(SRCTREE)/lib/libfdt/%.c |
256 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< | 258 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< |
257 | 259 | ||
258 | $(obj)%.o: $(SRCTREE)/lib/rsa/%.c | 260 | $(obj)%.o: $(SRCTREE)/lib/rsa/%.c |
259 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< | 261 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< |
260 | 262 | ||
261 | subdirs: | 263 | subdirs: |
262 | ifeq ($(TOOLSUBDIRS),) | 264 | ifeq ($(TOOLSUBDIRS),) |
263 | @: | 265 | @: |
264 | else | 266 | else |
265 | @for dir in $(TOOLSUBDIRS) ; do \ | 267 | @for dir in $(TOOLSUBDIRS) ; do \ |
266 | $(MAKE) \ | 268 | $(MAKE) \ |
267 | HOSTOS=$(HOSTOS) \ | 269 | HOSTOS=$(HOSTOS) \ |
268 | HOSTARCH=$(HOSTARCH) \ | 270 | HOSTARCH=$(HOSTARCH) \ |
269 | -C $$dir || exit 1 ; \ | 271 | -C $$dir || exit 1 ; \ |
270 | done | 272 | done |
271 | endif | 273 | endif |
272 | 274 | ||
273 | $(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) | 275 | $(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) |
274 | $(obj)./bmp_logo --gen-info $(LOGO_BMP) > $@ | 276 | $(obj)./bmp_logo --gen-info $(LOGO_BMP) > $@ |
275 | 277 | ||
276 | $(LOGO_DATA_H): $(obj)bmp_logo $(LOGO_BMP) | 278 | $(LOGO_DATA_H): $(obj)bmp_logo $(LOGO_BMP) |
277 | $(obj)./bmp_logo --gen-data $(LOGO_BMP) > $@ | 279 | $(obj)./bmp_logo --gen-data $(LOGO_BMP) > $@ |
278 | 280 | ||
279 | ######################################################################### | 281 | ######################################################################### |
280 | 282 | ||
281 | # defines $(obj).depend target | 283 | # defines $(obj).depend target |
282 | include $(SRCTREE)/rules.mk | 284 | include $(SRCTREE)/rules.mk |
283 | 285 | ||
284 | sinclude $(obj).depend | 286 | sinclude $(obj).depend |
285 | 287 | ||
286 | ######################################################################### | 288 | ######################################################################### |
287 | 289 |
tools/aisimage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 | 2 | * (C) Copyright 2011 |
3 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. | 3 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | /* Required to obtain the getline prototype from stdio.h */ | ||
9 | #define _GNU_SOURCE | ||
10 | |||
11 | #include "mkimage.h" | 8 | #include "mkimage.h" |
12 | #include "aisimage.h" | 9 | #include "aisimage.h" |
13 | #include <image.h> | 10 | #include <image.h> |
14 | 11 | ||
15 | #define IS_FNC_EXEC(c) (cmd_table[c].AIS_cmd == AIS_CMD_FNLOAD) | 12 | #define IS_FNC_EXEC(c) (cmd_table[c].AIS_cmd == AIS_CMD_FNLOAD) |
16 | #define WORD_ALIGN0 4 | 13 | #define WORD_ALIGN0 4 |
17 | #define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1)) | 14 | #define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1)) |
18 | #define MAX_CMD_BUFFER 4096 | 15 | #define MAX_CMD_BUFFER 4096 |
19 | 16 | ||
20 | static uint32_t ais_img_size; | 17 | static uint32_t ais_img_size; |
21 | 18 | ||
22 | /* | 19 | /* |
23 | * Supported commands for configuration file | 20 | * Supported commands for configuration file |
24 | */ | 21 | */ |
25 | static table_entry_t aisimage_cmds[] = { | 22 | static table_entry_t aisimage_cmds[] = { |
26 | {CMD_DATA, "DATA", "Reg Write Data"}, | 23 | {CMD_DATA, "DATA", "Reg Write Data"}, |
27 | {CMD_FILL, "FILL", "Fill range with pattern"}, | 24 | {CMD_FILL, "FILL", "Fill range with pattern"}, |
28 | {CMD_CRCON, "CRCON", "CRC Enable"}, | 25 | {CMD_CRCON, "CRCON", "CRC Enable"}, |
29 | {CMD_CRCOFF, "CRCOFF", "CRC Disable"}, | 26 | {CMD_CRCOFF, "CRCOFF", "CRC Disable"}, |
30 | {CMD_CRCCHECK, "CRCCHECK", "CRC Validate"}, | 27 | {CMD_CRCCHECK, "CRCCHECK", "CRC Validate"}, |
31 | {CMD_JMPCLOSE, "JMPCLOSE", "Jump & Close"}, | 28 | {CMD_JMPCLOSE, "JMPCLOSE", "Jump & Close"}, |
32 | {CMD_JMP, "JMP", "Jump"}, | 29 | {CMD_JMP, "JMP", "Jump"}, |
33 | {CMD_SEQREAD, "SEQREAD", "Sequential read"}, | 30 | {CMD_SEQREAD, "SEQREAD", "Sequential read"}, |
34 | {CMD_PLL0, "PLL0", "PLL0"}, | 31 | {CMD_PLL0, "PLL0", "PLL0"}, |
35 | {CMD_PLL1, "PLL1", "PLL1"}, | 32 | {CMD_PLL1, "PLL1", "PLL1"}, |
36 | {CMD_CLK, "CLK", "Clock configuration"}, | 33 | {CMD_CLK, "CLK", "Clock configuration"}, |
37 | {CMD_DDR2, "DDR2", "DDR2 Configuration"}, | 34 | {CMD_DDR2, "DDR2", "DDR2 Configuration"}, |
38 | {CMD_EMIFA, "EMIFA", "EMIFA"}, | 35 | {CMD_EMIFA, "EMIFA", "EMIFA"}, |
39 | {CMD_EMIFA_ASYNC, "EMIFA_ASYNC", "EMIFA Async"}, | 36 | {CMD_EMIFA_ASYNC, "EMIFA_ASYNC", "EMIFA Async"}, |
40 | {CMD_PLL, "PLL", "PLL & Clock configuration"}, | 37 | {CMD_PLL, "PLL", "PLL & Clock configuration"}, |
41 | {CMD_PSC, "PSC", "PSC setup"}, | 38 | {CMD_PSC, "PSC", "PSC setup"}, |
42 | {CMD_PINMUX, "PINMUX", "Pinmux setup"}, | 39 | {CMD_PINMUX, "PINMUX", "Pinmux setup"}, |
43 | {CMD_BOOTTABLE, "BOOT_TABLE", "Boot table command"}, | 40 | {CMD_BOOTTABLE, "BOOT_TABLE", "Boot table command"}, |
44 | {-1, "", ""}, | 41 | {-1, "", ""}, |
45 | }; | 42 | }; |
46 | 43 | ||
47 | static struct ais_func_exec { | 44 | static struct ais_func_exec { |
48 | uint32_t index; | 45 | uint32_t index; |
49 | uint32_t argcnt; | 46 | uint32_t argcnt; |
50 | } ais_func_table[] = { | 47 | } ais_func_table[] = { |
51 | [CMD_PLL0] = {0, 2}, | 48 | [CMD_PLL0] = {0, 2}, |
52 | [CMD_PLL1] = {1, 2}, | 49 | [CMD_PLL1] = {1, 2}, |
53 | [CMD_CLK] = {2, 1}, | 50 | [CMD_CLK] = {2, 1}, |
54 | [CMD_DDR2] = {3, 8}, | 51 | [CMD_DDR2] = {3, 8}, |
55 | [CMD_EMIFA] = {4, 5}, | 52 | [CMD_EMIFA] = {4, 5}, |
56 | [CMD_EMIFA_ASYNC] = {5, 5}, | 53 | [CMD_EMIFA_ASYNC] = {5, 5}, |
57 | [CMD_PLL] = {6, 3}, | 54 | [CMD_PLL] = {6, 3}, |
58 | [CMD_PSC] = {7, 1}, | 55 | [CMD_PSC] = {7, 1}, |
59 | [CMD_PINMUX] = {8, 3} | 56 | [CMD_PINMUX] = {8, 3} |
60 | }; | 57 | }; |
61 | 58 | ||
62 | static struct cmd_table_t { | 59 | static struct cmd_table_t { |
63 | uint32_t nargs; | 60 | uint32_t nargs; |
64 | uint32_t AIS_cmd; | 61 | uint32_t AIS_cmd; |
65 | } cmd_table[] = { | 62 | } cmd_table[] = { |
66 | [CMD_FILL] = { 4, AIS_CMD_FILL}, | 63 | [CMD_FILL] = { 4, AIS_CMD_FILL}, |
67 | [CMD_CRCON] = { 0, AIS_CMD_ENCRC}, | 64 | [CMD_CRCON] = { 0, AIS_CMD_ENCRC}, |
68 | [CMD_CRCOFF] = { 0, AIS_CMD_DISCRC}, | 65 | [CMD_CRCOFF] = { 0, AIS_CMD_DISCRC}, |
69 | [CMD_CRCCHECK] = { 2, AIS_CMD_ENCRC}, | 66 | [CMD_CRCCHECK] = { 2, AIS_CMD_ENCRC}, |
70 | [CMD_JMPCLOSE] = { 1, AIS_CMD_JMPCLOSE}, | 67 | [CMD_JMPCLOSE] = { 1, AIS_CMD_JMPCLOSE}, |
71 | [CMD_JMP] = { 1, AIS_CMD_JMP}, | 68 | [CMD_JMP] = { 1, AIS_CMD_JMP}, |
72 | [CMD_SEQREAD] = { 0, AIS_CMD_SEQREAD}, | 69 | [CMD_SEQREAD] = { 0, AIS_CMD_SEQREAD}, |
73 | [CMD_PLL0] = { 2, AIS_CMD_FNLOAD}, | 70 | [CMD_PLL0] = { 2, AIS_CMD_FNLOAD}, |
74 | [CMD_PLL1] = { 2, AIS_CMD_FNLOAD}, | 71 | [CMD_PLL1] = { 2, AIS_CMD_FNLOAD}, |
75 | [CMD_CLK] = { 1, AIS_CMD_FNLOAD}, | 72 | [CMD_CLK] = { 1, AIS_CMD_FNLOAD}, |
76 | [CMD_DDR2] = { 8, AIS_CMD_FNLOAD}, | 73 | [CMD_DDR2] = { 8, AIS_CMD_FNLOAD}, |
77 | [CMD_EMIFA] = { 5, AIS_CMD_FNLOAD}, | 74 | [CMD_EMIFA] = { 5, AIS_CMD_FNLOAD}, |
78 | [CMD_EMIFA_ASYNC] = { 5, AIS_CMD_FNLOAD}, | 75 | [CMD_EMIFA_ASYNC] = { 5, AIS_CMD_FNLOAD}, |
79 | [CMD_PLL] = { 3, AIS_CMD_FNLOAD}, | 76 | [CMD_PLL] = { 3, AIS_CMD_FNLOAD}, |
80 | [CMD_PSC] = { 1, AIS_CMD_FNLOAD}, | 77 | [CMD_PSC] = { 1, AIS_CMD_FNLOAD}, |
81 | [CMD_PINMUX] = { 3, AIS_CMD_FNLOAD}, | 78 | [CMD_PINMUX] = { 3, AIS_CMD_FNLOAD}, |
82 | [CMD_BOOTTABLE] = { 4, AIS_CMD_BOOTTBL}, | 79 | [CMD_BOOTTABLE] = { 4, AIS_CMD_BOOTTBL}, |
83 | }; | 80 | }; |
84 | 81 | ||
85 | static uint32_t get_cfg_value(char *token, char *name, int linenr) | 82 | static uint32_t get_cfg_value(char *token, char *name, int linenr) |
86 | { | 83 | { |
87 | char *endptr; | 84 | char *endptr; |
88 | uint32_t value; | 85 | uint32_t value; |
89 | 86 | ||
90 | errno = 0; | 87 | errno = 0; |
91 | value = strtoul(token, &endptr, 16); | 88 | value = strtoul(token, &endptr, 16); |
92 | if (errno || (token == endptr)) { | 89 | if (errno || (token == endptr)) { |
93 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", | 90 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", |
94 | name, linenr, token); | 91 | name, linenr, token); |
95 | exit(EXIT_FAILURE); | 92 | exit(EXIT_FAILURE); |
96 | } | 93 | } |
97 | return value; | 94 | return value; |
98 | } | 95 | } |
99 | 96 | ||
100 | static int get_ais_table_id(uint32_t *ptr) | 97 | static int get_ais_table_id(uint32_t *ptr) |
101 | { | 98 | { |
102 | 99 | ||
103 | int i; | 100 | int i; |
104 | int func_no; | 101 | int func_no; |
105 | 102 | ||
106 | for (i = 0; i < ARRAY_SIZE(cmd_table); i++) { | 103 | for (i = 0; i < ARRAY_SIZE(cmd_table); i++) { |
107 | if (*ptr == cmd_table[i].AIS_cmd) { | 104 | if (*ptr == cmd_table[i].AIS_cmd) { |
108 | if (cmd_table[i].AIS_cmd != AIS_CMD_FNLOAD) | 105 | if (cmd_table[i].AIS_cmd != AIS_CMD_FNLOAD) |
109 | return i; | 106 | return i; |
110 | 107 | ||
111 | func_no = ((struct ais_cmd_func *)ptr)->func_args | 108 | func_no = ((struct ais_cmd_func *)ptr)->func_args |
112 | & 0xFFFF; | 109 | & 0xFFFF; |
113 | if (func_no == ais_func_table[i].index) | 110 | if (func_no == ais_func_table[i].index) |
114 | return i; | 111 | return i; |
115 | } | 112 | } |
116 | } | 113 | } |
117 | 114 | ||
118 | return -1; | 115 | return -1; |
119 | } | 116 | } |
120 | 117 | ||
121 | static void aisimage_print_header(const void *hdr) | 118 | static void aisimage_print_header(const void *hdr) |
122 | { | 119 | { |
123 | struct ais_header *ais_hdr = (struct ais_header *)hdr; | 120 | struct ais_header *ais_hdr = (struct ais_header *)hdr; |
124 | uint32_t *ptr; | 121 | uint32_t *ptr; |
125 | struct ais_cmd_load *ais_load; | 122 | struct ais_cmd_load *ais_load; |
126 | int id; | 123 | int id; |
127 | 124 | ||
128 | if (ais_hdr->magic != AIS_MAGIC_WORD) { | 125 | if (ais_hdr->magic != AIS_MAGIC_WORD) { |
129 | fprintf(stderr, "Error: - AIS Magic Number not found\n"); | 126 | fprintf(stderr, "Error: - AIS Magic Number not found\n"); |
130 | return; | 127 | return; |
131 | } | 128 | } |
132 | fprintf(stdout, "Image Type: TI Davinci AIS Boot Image\n"); | 129 | fprintf(stdout, "Image Type: TI Davinci AIS Boot Image\n"); |
133 | fprintf(stdout, "AIS magic : %08x\n", ais_hdr->magic); | 130 | fprintf(stdout, "AIS magic : %08x\n", ais_hdr->magic); |
134 | ptr = (uint32_t *)&ais_hdr->magic; | 131 | ptr = (uint32_t *)&ais_hdr->magic; |
135 | ptr++; | 132 | ptr++; |
136 | 133 | ||
137 | while (*ptr != AIS_CMD_JMPCLOSE) { | 134 | while (*ptr != AIS_CMD_JMPCLOSE) { |
138 | /* Check if we find the image */ | 135 | /* Check if we find the image */ |
139 | if (*ptr == AIS_CMD_LOAD) { | 136 | if (*ptr == AIS_CMD_LOAD) { |
140 | ais_load = (struct ais_cmd_load *)ptr; | 137 | ais_load = (struct ais_cmd_load *)ptr; |
141 | fprintf(stdout, "Image at : 0x%08x size 0x%08x\n", | 138 | fprintf(stdout, "Image at : 0x%08x size 0x%08x\n", |
142 | ais_load->addr, | 139 | ais_load->addr, |
143 | ais_load->size); | 140 | ais_load->size); |
144 | ptr = ais_load->data + ais_load->size / sizeof(*ptr); | 141 | ptr = ais_load->data + ais_load->size / sizeof(*ptr); |
145 | continue; | 142 | continue; |
146 | } | 143 | } |
147 | 144 | ||
148 | id = get_ais_table_id(ptr); | 145 | id = get_ais_table_id(ptr); |
149 | if (id < 0) { | 146 | if (id < 0) { |
150 | fprintf(stderr, "Error: - AIS Image corrupted\n"); | 147 | fprintf(stderr, "Error: - AIS Image corrupted\n"); |
151 | return; | 148 | return; |
152 | } | 149 | } |
153 | fprintf(stdout, "AIS cmd : %s\n", | 150 | fprintf(stdout, "AIS cmd : %s\n", |
154 | get_table_entry_name(aisimage_cmds, NULL, id)); | 151 | get_table_entry_name(aisimage_cmds, NULL, id)); |
155 | ptr += cmd_table[id].nargs + IS_FNC_EXEC(id) + 1; | 152 | ptr += cmd_table[id].nargs + IS_FNC_EXEC(id) + 1; |
156 | if (((void *)ptr - hdr) > ais_img_size) { | 153 | if (((void *)ptr - hdr) > ais_img_size) { |
157 | fprintf(stderr, | 154 | fprintf(stderr, |
158 | "AIS Image not terminated by JMPCLOSE\n"); | 155 | "AIS Image not terminated by JMPCLOSE\n"); |
159 | return; | 156 | return; |
160 | } | 157 | } |
161 | } | 158 | } |
162 | } | 159 | } |
163 | 160 | ||
164 | static uint32_t *ais_insert_cmd_header(uint32_t cmd, uint32_t nargs, | 161 | static uint32_t *ais_insert_cmd_header(uint32_t cmd, uint32_t nargs, |
165 | uint32_t *parms, struct image_type_params *tparams, | 162 | uint32_t *parms, struct image_type_params *tparams, |
166 | uint32_t *ptr) | 163 | uint32_t *ptr) |
167 | { | 164 | { |
168 | int i; | 165 | int i; |
169 | 166 | ||
170 | *ptr++ = cmd_table[cmd].AIS_cmd; | 167 | *ptr++ = cmd_table[cmd].AIS_cmd; |
171 | if (IS_FNC_EXEC(cmd)) | 168 | if (IS_FNC_EXEC(cmd)) |
172 | *ptr++ = ((nargs & 0xFFFF) << 16) + ais_func_table[cmd].index; | 169 | *ptr++ = ((nargs & 0xFFFF) << 16) + ais_func_table[cmd].index; |
173 | 170 | ||
174 | /* Copy parameters */ | 171 | /* Copy parameters */ |
175 | for (i = 0; i < nargs; i++) | 172 | for (i = 0; i < nargs; i++) |
176 | *ptr++ = cpu_to_le32(parms[i]); | 173 | *ptr++ = cpu_to_le32(parms[i]); |
177 | 174 | ||
178 | return ptr; | 175 | return ptr; |
179 | 176 | ||
180 | } | 177 | } |
181 | 178 | ||
182 | static uint32_t *ais_alloc_buffer(struct mkimage_params *params) | 179 | static uint32_t *ais_alloc_buffer(struct mkimage_params *params) |
183 | { | 180 | { |
184 | int dfd; | 181 | int dfd; |
185 | struct stat sbuf; | 182 | struct stat sbuf; |
186 | char *datafile = params->datafile; | 183 | char *datafile = params->datafile; |
187 | uint32_t *ptr; | 184 | uint32_t *ptr; |
188 | 185 | ||
189 | dfd = open(datafile, O_RDONLY|O_BINARY); | 186 | dfd = open(datafile, O_RDONLY|O_BINARY); |
190 | if (dfd < 0) { | 187 | if (dfd < 0) { |
191 | fprintf(stderr, "%s: Can't open %s: %s\n", | 188 | fprintf(stderr, "%s: Can't open %s: %s\n", |
192 | params->cmdname, datafile, strerror(errno)); | 189 | params->cmdname, datafile, strerror(errno)); |
193 | exit(EXIT_FAILURE); | 190 | exit(EXIT_FAILURE); |
194 | } | 191 | } |
195 | 192 | ||
196 | if (fstat(dfd, &sbuf) < 0) { | 193 | if (fstat(dfd, &sbuf) < 0) { |
197 | fprintf(stderr, "%s: Can't stat %s: %s\n", | 194 | fprintf(stderr, "%s: Can't stat %s: %s\n", |
198 | params->cmdname, datafile, strerror(errno)); | 195 | params->cmdname, datafile, strerror(errno)); |
199 | exit(EXIT_FAILURE); | 196 | exit(EXIT_FAILURE); |
200 | } | 197 | } |
201 | 198 | ||
202 | /* | 199 | /* |
203 | * Place for header is allocated. The size is taken from | 200 | * Place for header is allocated. The size is taken from |
204 | * the size of the datafile, that the ais_image_generate() | 201 | * the size of the datafile, that the ais_image_generate() |
205 | * will copy into the header. Copying the datafile | 202 | * will copy into the header. Copying the datafile |
206 | * is not left to the main program, because after the datafile | 203 | * is not left to the main program, because after the datafile |
207 | * the header must be terminated with the Jump & Close command. | 204 | * the header must be terminated with the Jump & Close command. |
208 | */ | 205 | */ |
209 | ais_img_size = WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER; | 206 | ais_img_size = WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER; |
210 | ptr = (uint32_t *)malloc(WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER); | 207 | ptr = (uint32_t *)malloc(WORD_ALIGN(sbuf.st_size) + MAX_CMD_BUFFER); |
211 | if (!ptr) { | 208 | if (!ptr) { |
212 | fprintf(stderr, "%s: malloc return failure: %s\n", | 209 | fprintf(stderr, "%s: malloc return failure: %s\n", |
213 | params->cmdname, strerror(errno)); | 210 | params->cmdname, strerror(errno)); |
214 | exit(EXIT_FAILURE); | 211 | exit(EXIT_FAILURE); |
215 | } | 212 | } |
216 | 213 | ||
217 | close(dfd); | 214 | close(dfd); |
218 | 215 | ||
219 | return ptr; | 216 | return ptr; |
220 | } | 217 | } |
221 | 218 | ||
222 | static uint32_t *ais_copy_image(struct mkimage_params *params, | 219 | static uint32_t *ais_copy_image(struct mkimage_params *params, |
223 | uint32_t *aisptr) | 220 | uint32_t *aisptr) |
224 | 221 | ||
225 | { | 222 | { |
226 | int dfd; | 223 | int dfd; |
227 | struct stat sbuf; | 224 | struct stat sbuf; |
228 | char *datafile = params->datafile; | 225 | char *datafile = params->datafile; |
229 | void *ptr; | 226 | void *ptr; |
230 | 227 | ||
231 | dfd = open(datafile, O_RDONLY|O_BINARY); | 228 | dfd = open(datafile, O_RDONLY|O_BINARY); |
232 | if (dfd < 0) { | 229 | if (dfd < 0) { |
233 | fprintf(stderr, "%s: Can't open %s: %s\n", | 230 | fprintf(stderr, "%s: Can't open %s: %s\n", |
234 | params->cmdname, datafile, strerror(errno)); | 231 | params->cmdname, datafile, strerror(errno)); |
235 | exit(EXIT_FAILURE); | 232 | exit(EXIT_FAILURE); |
236 | } | 233 | } |
237 | 234 | ||
238 | if (fstat(dfd, &sbuf) < 0) { | 235 | if (fstat(dfd, &sbuf) < 0) { |
239 | fprintf(stderr, "%s: Can't stat %s: %s\n", | 236 | fprintf(stderr, "%s: Can't stat %s: %s\n", |
240 | params->cmdname, datafile, strerror(errno)); | 237 | params->cmdname, datafile, strerror(errno)); |
241 | exit(EXIT_FAILURE); | 238 | exit(EXIT_FAILURE); |
242 | } | 239 | } |
243 | 240 | ||
244 | ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); | 241 | ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); |
245 | *aisptr++ = AIS_CMD_LOAD; | 242 | *aisptr++ = AIS_CMD_LOAD; |
246 | *aisptr++ = params->ep; | 243 | *aisptr++ = params->ep; |
247 | *aisptr++ = sbuf.st_size; | 244 | *aisptr++ = sbuf.st_size; |
248 | memcpy((void *)aisptr, ptr, sbuf.st_size); | 245 | memcpy((void *)aisptr, ptr, sbuf.st_size); |
249 | aisptr += WORD_ALIGN(sbuf.st_size) / sizeof(uint32_t); | 246 | aisptr += WORD_ALIGN(sbuf.st_size) / sizeof(uint32_t); |
250 | 247 | ||
251 | (void) munmap((void *)ptr, sbuf.st_size); | 248 | (void) munmap((void *)ptr, sbuf.st_size); |
252 | (void) close(dfd); | 249 | (void) close(dfd); |
253 | 250 | ||
254 | return aisptr; | 251 | return aisptr; |
255 | 252 | ||
256 | } | 253 | } |
257 | 254 | ||
258 | static int aisimage_generate(struct mkimage_params *params, | 255 | static int aisimage_generate(struct mkimage_params *params, |
259 | struct image_type_params *tparams) | 256 | struct image_type_params *tparams) |
260 | { | 257 | { |
261 | FILE *fd = NULL; | 258 | FILE *fd = NULL; |
262 | char *line = NULL; | 259 | char *line = NULL; |
263 | char *token, *saveptr1, *saveptr2; | 260 | char *token, *saveptr1, *saveptr2; |
264 | int lineno = 0; | 261 | int lineno = 0; |
265 | int fld; | 262 | int fld; |
266 | size_t len; | 263 | size_t len; |
267 | int32_t cmd; | 264 | int32_t cmd; |
268 | uint32_t nargs, cmd_parms[10]; | 265 | uint32_t nargs, cmd_parms[10]; |
269 | uint32_t value, size; | 266 | uint32_t value, size; |
270 | char *name = params->imagename; | 267 | char *name = params->imagename; |
271 | uint32_t *aishdr; | 268 | uint32_t *aishdr; |
272 | 269 | ||
273 | fd = fopen(name, "r"); | 270 | fd = fopen(name, "r"); |
274 | if (fd == 0) { | 271 | if (fd == 0) { |
275 | fprintf(stderr, | 272 | fprintf(stderr, |
276 | "Error: %s - Can't open AIS configuration\n", name); | 273 | "Error: %s - Can't open AIS configuration\n", name); |
277 | exit(EXIT_FAILURE); | 274 | exit(EXIT_FAILURE); |
278 | } | 275 | } |
279 | 276 | ||
280 | /* | 277 | /* |
281 | * the size of the header is variable and is computed | 278 | * the size of the header is variable and is computed |
282 | * scanning the configuration file. | 279 | * scanning the configuration file. |
283 | */ | 280 | */ |
284 | tparams->header_size = 0; | 281 | tparams->header_size = 0; |
285 | 282 | ||
286 | /* | 283 | /* |
287 | * Start allocating a buffer suitable for most command | 284 | * Start allocating a buffer suitable for most command |
288 | * The buffer is then reallocated if it is too small | 285 | * The buffer is then reallocated if it is too small |
289 | */ | 286 | */ |
290 | aishdr = ais_alloc_buffer(params); | 287 | aishdr = ais_alloc_buffer(params); |
291 | tparams->hdr = aishdr; | 288 | tparams->hdr = aishdr; |
292 | *aishdr++ = AIS_MAGIC_WORD; | 289 | *aishdr++ = AIS_MAGIC_WORD; |
293 | 290 | ||
294 | /* Very simple parsing, line starting with # are comments | 291 | /* Very simple parsing, line starting with # are comments |
295 | * and are dropped | 292 | * and are dropped |
296 | */ | 293 | */ |
297 | while ((getline(&line, &len, fd)) > 0) { | 294 | while ((getline(&line, &len, fd)) > 0) { |
298 | lineno++; | 295 | lineno++; |
299 | 296 | ||
300 | token = strtok_r(line, "\r\n", &saveptr1); | 297 | token = strtok_r(line, "\r\n", &saveptr1); |
301 | if (token == NULL) | 298 | if (token == NULL) |
302 | continue; | 299 | continue; |
303 | 300 | ||
304 | /* Check inside the single line */ | 301 | /* Check inside the single line */ |
305 | line = token; | 302 | line = token; |
306 | fld = CFG_COMMAND; | 303 | fld = CFG_COMMAND; |
307 | cmd = CMD_INVALID; | 304 | cmd = CMD_INVALID; |
308 | nargs = 0; | 305 | nargs = 0; |
309 | while (token != NULL) { | 306 | while (token != NULL) { |
310 | token = strtok_r(line, " \t", &saveptr2); | 307 | token = strtok_r(line, " \t", &saveptr2); |
311 | if (token == NULL) | 308 | if (token == NULL) |
312 | break; | 309 | break; |
313 | 310 | ||
314 | /* Drop all text starting with '#' as comments */ | 311 | /* Drop all text starting with '#' as comments */ |
315 | if (token[0] == '#') | 312 | if (token[0] == '#') |
316 | break; | 313 | break; |
317 | 314 | ||
318 | switch (fld) { | 315 | switch (fld) { |
319 | case CFG_COMMAND: | 316 | case CFG_COMMAND: |
320 | cmd = get_table_entry_id(aisimage_cmds, | 317 | cmd = get_table_entry_id(aisimage_cmds, |
321 | "aisimage commands", token); | 318 | "aisimage commands", token); |
322 | if (cmd < 0) { | 319 | if (cmd < 0) { |
323 | fprintf(stderr, | 320 | fprintf(stderr, |
324 | "Error: %s[%d] - Invalid command" | 321 | "Error: %s[%d] - Invalid command" |
325 | "(%s)\n", name, lineno, token); | 322 | "(%s)\n", name, lineno, token); |
326 | 323 | ||
327 | exit(EXIT_FAILURE); | 324 | exit(EXIT_FAILURE); |
328 | } | 325 | } |
329 | break; | 326 | break; |
330 | case CFG_VALUE: | 327 | case CFG_VALUE: |
331 | value = get_cfg_value(token, name, lineno); | 328 | value = get_cfg_value(token, name, lineno); |
332 | cmd_parms[nargs++] = value; | 329 | cmd_parms[nargs++] = value; |
333 | if (nargs > cmd_table[cmd].nargs) { | 330 | if (nargs > cmd_table[cmd].nargs) { |
334 | fprintf(stderr, | 331 | fprintf(stderr, |
335 | "Error: %s[%d] - too much arguments:" | 332 | "Error: %s[%d] - too much arguments:" |
336 | "(%s) for command %s\n", name, | 333 | "(%s) for command %s\n", name, |
337 | lineno, token, | 334 | lineno, token, |
338 | aisimage_cmds[cmd].sname); | 335 | aisimage_cmds[cmd].sname); |
339 | exit(EXIT_FAILURE); | 336 | exit(EXIT_FAILURE); |
340 | } | 337 | } |
341 | break; | 338 | break; |
342 | } | 339 | } |
343 | line = NULL; | 340 | line = NULL; |
344 | fld = CFG_VALUE; | 341 | fld = CFG_VALUE; |
345 | } | 342 | } |
346 | if (cmd != CMD_INVALID) { | 343 | if (cmd != CMD_INVALID) { |
347 | /* Now insert the command into the header */ | 344 | /* Now insert the command into the header */ |
348 | aishdr = ais_insert_cmd_header(cmd, nargs, cmd_parms, | 345 | aishdr = ais_insert_cmd_header(cmd, nargs, cmd_parms, |
349 | tparams, aishdr); | 346 | tparams, aishdr); |
350 | } | 347 | } |
351 | 348 | ||
352 | } | 349 | } |
353 | fclose(fd); | 350 | fclose(fd); |
354 | 351 | ||
355 | aishdr = ais_copy_image(params, aishdr); | 352 | aishdr = ais_copy_image(params, aishdr); |
356 | 353 | ||
357 | /* Add Jmp & Close */ | 354 | /* Add Jmp & Close */ |
358 | *aishdr++ = AIS_CMD_JMPCLOSE; | 355 | *aishdr++ = AIS_CMD_JMPCLOSE; |
359 | *aishdr++ = params->ep; | 356 | *aishdr++ = params->ep; |
360 | 357 | ||
361 | size = (aishdr - (uint32_t *)tparams->hdr) * sizeof(uint32_t); | 358 | size = (aishdr - (uint32_t *)tparams->hdr) * sizeof(uint32_t); |
362 | tparams->header_size = size; | 359 | tparams->header_size = size; |
363 | 360 | ||
364 | return 0; | 361 | return 0; |
365 | } | 362 | } |
366 | 363 | ||
367 | static int aisimage_check_image_types(uint8_t type) | 364 | static int aisimage_check_image_types(uint8_t type) |
368 | { | 365 | { |
369 | if (type == IH_TYPE_AISIMAGE) | 366 | if (type == IH_TYPE_AISIMAGE) |
370 | return EXIT_SUCCESS; | 367 | return EXIT_SUCCESS; |
371 | else | 368 | else |
372 | return EXIT_FAILURE; | 369 | return EXIT_FAILURE; |
373 | } | 370 | } |
374 | 371 | ||
375 | static int aisimage_verify_header(unsigned char *ptr, int image_size, | 372 | static int aisimage_verify_header(unsigned char *ptr, int image_size, |
376 | struct mkimage_params *params) | 373 | struct mkimage_params *params) |
377 | { | 374 | { |
378 | struct ais_header *ais_hdr = (struct ais_header *)ptr; | 375 | struct ais_header *ais_hdr = (struct ais_header *)ptr; |
379 | 376 | ||
380 | if (ais_hdr->magic != AIS_MAGIC_WORD) | 377 | if (ais_hdr->magic != AIS_MAGIC_WORD) |
381 | return -FDT_ERR_BADSTRUCTURE; | 378 | return -FDT_ERR_BADSTRUCTURE; |
382 | 379 | ||
383 | /* Store the total size to remember in print_hdr */ | 380 | /* Store the total size to remember in print_hdr */ |
384 | ais_img_size = image_size; | 381 | ais_img_size = image_size; |
385 | 382 | ||
386 | return 0; | 383 | return 0; |
387 | } | 384 | } |
388 | 385 | ||
389 | static void aisimage_set_header(void *ptr, struct stat *sbuf, int ifd, | 386 | static void aisimage_set_header(void *ptr, struct stat *sbuf, int ifd, |
390 | struct mkimage_params *params) | 387 | struct mkimage_params *params) |
391 | { | 388 | { |
392 | } | 389 | } |
393 | 390 | ||
394 | int aisimage_check_params(struct mkimage_params *params) | 391 | int aisimage_check_params(struct mkimage_params *params) |
395 | { | 392 | { |
396 | if (!params) | 393 | if (!params) |
397 | return CFG_INVALID; | 394 | return CFG_INVALID; |
398 | if (!strlen(params->imagename)) { | 395 | if (!strlen(params->imagename)) { |
399 | fprintf(stderr, "Error: %s - Configuration file not specified, " | 396 | fprintf(stderr, "Error: %s - Configuration file not specified, " |
400 | "it is needed for aisimage generation\n", | 397 | "it is needed for aisimage generation\n", |
401 | params->cmdname); | 398 | params->cmdname); |
402 | return CFG_INVALID; | 399 | return CFG_INVALID; |
403 | } | 400 | } |
404 | /* | 401 | /* |
405 | * Check parameters: | 402 | * Check parameters: |
406 | * XIP is not allowed and verify that incompatible | 403 | * XIP is not allowed and verify that incompatible |
407 | * parameters are not sent at the same time | 404 | * parameters are not sent at the same time |
408 | * For example, if list is required a data image must not be provided | 405 | * For example, if list is required a data image must not be provided |
409 | */ | 406 | */ |
410 | return (params->dflag && (params->fflag || params->lflag)) || | 407 | return (params->dflag && (params->fflag || params->lflag)) || |
411 | (params->fflag && (params->dflag || params->lflag)) || | 408 | (params->fflag && (params->dflag || params->lflag)) || |
412 | (params->lflag && (params->dflag || params->fflag)) || | 409 | (params->lflag && (params->dflag || params->fflag)) || |
413 | (params->xflag) || !(strlen(params->imagename)); | 410 | (params->xflag) || !(strlen(params->imagename)); |
414 | } | 411 | } |
415 | 412 | ||
416 | /* | 413 | /* |
417 | * aisimage parameters | 414 | * aisimage parameters |
418 | */ | 415 | */ |
419 | static struct image_type_params aisimage_params = { | 416 | static struct image_type_params aisimage_params = { |
420 | .name = "TI Davinci AIS Boot Image support", | 417 | .name = "TI Davinci AIS Boot Image support", |
421 | .header_size = 0, | 418 | .header_size = 0, |
422 | .hdr = NULL, | 419 | .hdr = NULL, |
423 | .check_image_type = aisimage_check_image_types, | 420 | .check_image_type = aisimage_check_image_types, |
424 | .verify_header = aisimage_verify_header, | 421 | .verify_header = aisimage_verify_header, |
425 | .print_header = aisimage_print_header, | 422 | .print_header = aisimage_print_header, |
426 | .set_header = aisimage_set_header, | 423 | .set_header = aisimage_set_header, |
427 | .check_params = aisimage_check_params, | 424 | .check_params = aisimage_check_params, |
428 | .vrec_header = aisimage_generate, | 425 | .vrec_header = aisimage_generate, |
429 | }; | 426 | }; |
430 | 427 | ||
431 | void init_ais_image_type(void) | 428 | void init_ais_image_type(void) |
432 | { | 429 | { |
433 | mkimage_register(&aisimage_params); | 430 | mkimage_register(&aisimage_params); |
434 | } | 431 | } |
435 | 432 |
tools/imximage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2009 | 2 | * (C) Copyright 2009 |
3 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. | 3 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. |
4 | * | 4 | * |
5 | * (C) Copyright 2008 | 5 | * (C) Copyright 2008 |
6 | * Marvell Semiconductor <www.marvell.com> | 6 | * Marvell Semiconductor <www.marvell.com> |
7 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> | 7 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> |
8 | * | 8 | * |
9 | * SPDX-License-Identifier: GPL-2.0+ | 9 | * SPDX-License-Identifier: GPL-2.0+ |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* Required to obtain the getline prototype from stdio.h */ | ||
13 | #define _GNU_SOURCE | ||
14 | |||
15 | #include "mkimage.h" | 12 | #include "mkimage.h" |
16 | #include <image.h> | 13 | #include <image.h> |
17 | #include "imximage.h" | 14 | #include "imximage.h" |
18 | 15 | ||
19 | /* | 16 | /* |
20 | * Supported commands for configuration file | 17 | * Supported commands for configuration file |
21 | */ | 18 | */ |
22 | static table_entry_t imximage_cmds[] = { | 19 | static table_entry_t imximage_cmds[] = { |
23 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, | 20 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, |
24 | {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, | 21 | {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, |
25 | {CMD_DATA, "DATA", "Reg Write Data", }, | 22 | {CMD_DATA, "DATA", "Reg Write Data", }, |
26 | {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, | 23 | {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, |
27 | {-1, "", "", }, | 24 | {-1, "", "", }, |
28 | }; | 25 | }; |
29 | 26 | ||
30 | /* | 27 | /* |
31 | * Supported Boot options for configuration file | 28 | * Supported Boot options for configuration file |
32 | * this is needed to set the correct flash offset | 29 | * this is needed to set the correct flash offset |
33 | */ | 30 | */ |
34 | static table_entry_t imximage_bootops[] = { | 31 | static table_entry_t imximage_bootops[] = { |
35 | {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, | 32 | {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, |
36 | {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, | 33 | {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, |
37 | {FLASH_OFFSET_NOR, "nor", "NOR Flash", }, | 34 | {FLASH_OFFSET_NOR, "nor", "NOR Flash", }, |
38 | {FLASH_OFFSET_SATA, "sata", "SATA Disk", }, | 35 | {FLASH_OFFSET_SATA, "sata", "SATA Disk", }, |
39 | {FLASH_OFFSET_SD, "sd", "SD Card", }, | 36 | {FLASH_OFFSET_SD, "sd", "SD Card", }, |
40 | {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, | 37 | {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, |
41 | {-1, "", "Invalid", }, | 38 | {-1, "", "Invalid", }, |
42 | }; | 39 | }; |
43 | 40 | ||
44 | /* | 41 | /* |
45 | * IMXIMAGE version definition for i.MX chips | 42 | * IMXIMAGE version definition for i.MX chips |
46 | */ | 43 | */ |
47 | static table_entry_t imximage_versions[] = { | 44 | static table_entry_t imximage_versions[] = { |
48 | {IMXIMAGE_V1, "", " (i.MX25/35/51 compatible)", }, | 45 | {IMXIMAGE_V1, "", " (i.MX25/35/51 compatible)", }, |
49 | {IMXIMAGE_V2, "", " (i.MX53/6 compatible)", }, | 46 | {IMXIMAGE_V2, "", " (i.MX53/6 compatible)", }, |
50 | {-1, "", " (Invalid)", }, | 47 | {-1, "", " (Invalid)", }, |
51 | }; | 48 | }; |
52 | 49 | ||
53 | static struct imx_header imximage_header; | 50 | static struct imx_header imximage_header; |
54 | static uint32_t imximage_version; | 51 | static uint32_t imximage_version; |
55 | 52 | ||
56 | static set_dcd_val_t set_dcd_val; | 53 | static set_dcd_val_t set_dcd_val; |
57 | static set_dcd_rst_t set_dcd_rst; | 54 | static set_dcd_rst_t set_dcd_rst; |
58 | static set_imx_hdr_t set_imx_hdr; | 55 | static set_imx_hdr_t set_imx_hdr; |
59 | static uint32_t max_dcd_entries; | 56 | static uint32_t max_dcd_entries; |
60 | static uint32_t *header_size_ptr; | 57 | static uint32_t *header_size_ptr; |
61 | 58 | ||
62 | static uint32_t get_cfg_value(char *token, char *name, int linenr) | 59 | static uint32_t get_cfg_value(char *token, char *name, int linenr) |
63 | { | 60 | { |
64 | char *endptr; | 61 | char *endptr; |
65 | uint32_t value; | 62 | uint32_t value; |
66 | 63 | ||
67 | errno = 0; | 64 | errno = 0; |
68 | value = strtoul(token, &endptr, 16); | 65 | value = strtoul(token, &endptr, 16); |
69 | if (errno || (token == endptr)) { | 66 | if (errno || (token == endptr)) { |
70 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", | 67 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", |
71 | name, linenr, token); | 68 | name, linenr, token); |
72 | exit(EXIT_FAILURE); | 69 | exit(EXIT_FAILURE); |
73 | } | 70 | } |
74 | return value; | 71 | return value; |
75 | } | 72 | } |
76 | 73 | ||
77 | static uint32_t detect_imximage_version(struct imx_header *imx_hdr) | 74 | static uint32_t detect_imximage_version(struct imx_header *imx_hdr) |
78 | { | 75 | { |
79 | imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; | 76 | imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; |
80 | imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; | 77 | imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; |
81 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; | 78 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; |
82 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; | 79 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; |
83 | 80 | ||
84 | /* Try to detect V1 */ | 81 | /* Try to detect V1 */ |
85 | if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) && | 82 | if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) && |
86 | (hdr_v1->dcd_table.preamble.barker == DCD_BARKER)) | 83 | (hdr_v1->dcd_table.preamble.barker == DCD_BARKER)) |
87 | return IMXIMAGE_V1; | 84 | return IMXIMAGE_V1; |
88 | 85 | ||
89 | /* Try to detect V2 */ | 86 | /* Try to detect V2 */ |
90 | if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && | 87 | if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && |
91 | (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) | 88 | (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) |
92 | return IMXIMAGE_V2; | 89 | return IMXIMAGE_V2; |
93 | 90 | ||
94 | return IMXIMAGE_VER_INVALID; | 91 | return IMXIMAGE_VER_INVALID; |
95 | } | 92 | } |
96 | 93 | ||
97 | static void err_imximage_version(int version) | 94 | static void err_imximage_version(int version) |
98 | { | 95 | { |
99 | fprintf(stderr, | 96 | fprintf(stderr, |
100 | "Error: Unsupported imximage version:%d\n", version); | 97 | "Error: Unsupported imximage version:%d\n", version); |
101 | 98 | ||
102 | exit(EXIT_FAILURE); | 99 | exit(EXIT_FAILURE); |
103 | } | 100 | } |
104 | 101 | ||
105 | static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, | 102 | static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, |
106 | int fld, uint32_t value, uint32_t off) | 103 | int fld, uint32_t value, uint32_t off) |
107 | { | 104 | { |
108 | dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; | 105 | dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; |
109 | 106 | ||
110 | switch (fld) { | 107 | switch (fld) { |
111 | case CFG_REG_SIZE: | 108 | case CFG_REG_SIZE: |
112 | /* Byte, halfword, word */ | 109 | /* Byte, halfword, word */ |
113 | if ((value != 1) && (value != 2) && (value != 4)) { | 110 | if ((value != 1) && (value != 2) && (value != 4)) { |
114 | fprintf(stderr, "Error: %s[%d] - " | 111 | fprintf(stderr, "Error: %s[%d] - " |
115 | "Invalid register size " "(%d)\n", | 112 | "Invalid register size " "(%d)\n", |
116 | name, lineno, value); | 113 | name, lineno, value); |
117 | exit(EXIT_FAILURE); | 114 | exit(EXIT_FAILURE); |
118 | } | 115 | } |
119 | dcd_v1->addr_data[off].type = value; | 116 | dcd_v1->addr_data[off].type = value; |
120 | break; | 117 | break; |
121 | case CFG_REG_ADDRESS: | 118 | case CFG_REG_ADDRESS: |
122 | dcd_v1->addr_data[off].addr = value; | 119 | dcd_v1->addr_data[off].addr = value; |
123 | break; | 120 | break; |
124 | case CFG_REG_VALUE: | 121 | case CFG_REG_VALUE: |
125 | dcd_v1->addr_data[off].value = value; | 122 | dcd_v1->addr_data[off].value = value; |
126 | break; | 123 | break; |
127 | default: | 124 | default: |
128 | break; | 125 | break; |
129 | 126 | ||
130 | } | 127 | } |
131 | } | 128 | } |
132 | 129 | ||
133 | static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, | 130 | static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, |
134 | int fld, uint32_t value, uint32_t off) | 131 | int fld, uint32_t value, uint32_t off) |
135 | { | 132 | { |
136 | dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; | 133 | dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; |
137 | 134 | ||
138 | switch (fld) { | 135 | switch (fld) { |
139 | case CFG_REG_ADDRESS: | 136 | case CFG_REG_ADDRESS: |
140 | dcd_v2->addr_data[off].addr = cpu_to_be32(value); | 137 | dcd_v2->addr_data[off].addr = cpu_to_be32(value); |
141 | break; | 138 | break; |
142 | case CFG_REG_VALUE: | 139 | case CFG_REG_VALUE: |
143 | dcd_v2->addr_data[off].value = cpu_to_be32(value); | 140 | dcd_v2->addr_data[off].value = cpu_to_be32(value); |
144 | break; | 141 | break; |
145 | default: | 142 | default: |
146 | break; | 143 | break; |
147 | 144 | ||
148 | } | 145 | } |
149 | } | 146 | } |
150 | 147 | ||
151 | /* | 148 | /* |
152 | * Complete setting up the rest field of DCD of V1 | 149 | * Complete setting up the rest field of DCD of V1 |
153 | * such as barker code and DCD data length. | 150 | * such as barker code and DCD data length. |
154 | */ | 151 | */ |
155 | static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, | 152 | static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, |
156 | char *name, int lineno) | 153 | char *name, int lineno) |
157 | { | 154 | { |
158 | dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; | 155 | dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; |
159 | 156 | ||
160 | dcd_v1->preamble.barker = DCD_BARKER; | 157 | dcd_v1->preamble.barker = DCD_BARKER; |
161 | dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); | 158 | dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); |
162 | } | 159 | } |
163 | 160 | ||
164 | /* | 161 | /* |
165 | * Complete setting up the reset field of DCD of V2 | 162 | * Complete setting up the reset field of DCD of V2 |
166 | * such as DCD tag, version, length, etc. | 163 | * such as DCD tag, version, length, etc. |
167 | */ | 164 | */ |
168 | static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, | 165 | static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, |
169 | char *name, int lineno) | 166 | char *name, int lineno) |
170 | { | 167 | { |
171 | dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; | 168 | dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; |
172 | 169 | ||
173 | dcd_v2->header.tag = DCD_HEADER_TAG; | 170 | dcd_v2->header.tag = DCD_HEADER_TAG; |
174 | dcd_v2->header.length = cpu_to_be16( | 171 | dcd_v2->header.length = cpu_to_be16( |
175 | dcd_len * sizeof(dcd_addr_data_t) + 8); | 172 | dcd_len * sizeof(dcd_addr_data_t) + 8); |
176 | dcd_v2->header.version = DCD_VERSION; | 173 | dcd_v2->header.version = DCD_VERSION; |
177 | dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; | 174 | dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; |
178 | dcd_v2->write_dcd_command.length = cpu_to_be16( | 175 | dcd_v2->write_dcd_command.length = cpu_to_be16( |
179 | dcd_len * sizeof(dcd_addr_data_t) + 4); | 176 | dcd_len * sizeof(dcd_addr_data_t) + 4); |
180 | dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; | 177 | dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; |
181 | } | 178 | } |
182 | 179 | ||
183 | static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, | 180 | static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, |
184 | uint32_t entry_point, uint32_t flash_offset) | 181 | uint32_t entry_point, uint32_t flash_offset) |
185 | { | 182 | { |
186 | imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; | 183 | imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; |
187 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; | 184 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; |
188 | dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; | 185 | dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; |
189 | uint32_t hdr_base; | 186 | uint32_t hdr_base; |
190 | uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr) | 187 | uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr) |
191 | - ((char *)imxhdr)); | 188 | - ((char *)imxhdr)); |
192 | 189 | ||
193 | /* Set magic number */ | 190 | /* Set magic number */ |
194 | fhdr_v1->app_code_barker = APP_CODE_BARKER; | 191 | fhdr_v1->app_code_barker = APP_CODE_BARKER; |
195 | 192 | ||
196 | hdr_base = entry_point - sizeof(struct imx_header); | 193 | hdr_base = entry_point - sizeof(struct imx_header); |
197 | fhdr_v1->app_dest_ptr = hdr_base - flash_offset; | 194 | fhdr_v1->app_dest_ptr = hdr_base - flash_offset; |
198 | fhdr_v1->app_code_jump_vector = entry_point; | 195 | fhdr_v1->app_code_jump_vector = entry_point; |
199 | 196 | ||
200 | fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr); | 197 | fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr); |
201 | fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table); | 198 | fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table); |
202 | 199 | ||
203 | /* Security feature are not supported */ | 200 | /* Security feature are not supported */ |
204 | fhdr_v1->app_code_csf = 0; | 201 | fhdr_v1->app_code_csf = 0; |
205 | fhdr_v1->super_root_key = 0; | 202 | fhdr_v1->super_root_key = 0; |
206 | header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4); | 203 | header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4); |
207 | } | 204 | } |
208 | 205 | ||
209 | static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, | 206 | static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, |
210 | uint32_t entry_point, uint32_t flash_offset) | 207 | uint32_t entry_point, uint32_t flash_offset) |
211 | { | 208 | { |
212 | imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; | 209 | imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; |
213 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; | 210 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; |
214 | uint32_t hdr_base; | 211 | uint32_t hdr_base; |
215 | 212 | ||
216 | /* Set magic number */ | 213 | /* Set magic number */ |
217 | fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ | 214 | fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ |
218 | fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); | 215 | fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); |
219 | fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ | 216 | fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ |
220 | 217 | ||
221 | fhdr_v2->entry = entry_point; | 218 | fhdr_v2->entry = entry_point; |
222 | fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; | 219 | fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; |
223 | fhdr_v2->self = hdr_base = entry_point - sizeof(struct imx_header); | 220 | fhdr_v2->self = hdr_base = entry_point - sizeof(struct imx_header); |
224 | 221 | ||
225 | fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table); | 222 | fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table); |
226 | fhdr_v2->boot_data_ptr = hdr_base | 223 | fhdr_v2->boot_data_ptr = hdr_base |
227 | + offsetof(imx_header_v2_t, boot_data); | 224 | + offsetof(imx_header_v2_t, boot_data); |
228 | hdr_v2->boot_data.start = hdr_base - flash_offset; | 225 | hdr_v2->boot_data.start = hdr_base - flash_offset; |
229 | 226 | ||
230 | /* Security feature are not supported */ | 227 | /* Security feature are not supported */ |
231 | fhdr_v2->csf = 0; | 228 | fhdr_v2->csf = 0; |
232 | header_size_ptr = &hdr_v2->boot_data.size; | 229 | header_size_ptr = &hdr_v2->boot_data.size; |
233 | } | 230 | } |
234 | 231 | ||
235 | static void set_hdr_func(struct imx_header *imxhdr) | 232 | static void set_hdr_func(struct imx_header *imxhdr) |
236 | { | 233 | { |
237 | switch (imximage_version) { | 234 | switch (imximage_version) { |
238 | case IMXIMAGE_V1: | 235 | case IMXIMAGE_V1: |
239 | set_dcd_val = set_dcd_val_v1; | 236 | set_dcd_val = set_dcd_val_v1; |
240 | set_dcd_rst = set_dcd_rst_v1; | 237 | set_dcd_rst = set_dcd_rst_v1; |
241 | set_imx_hdr = set_imx_hdr_v1; | 238 | set_imx_hdr = set_imx_hdr_v1; |
242 | max_dcd_entries = MAX_HW_CFG_SIZE_V1; | 239 | max_dcd_entries = MAX_HW_CFG_SIZE_V1; |
243 | break; | 240 | break; |
244 | case IMXIMAGE_V2: | 241 | case IMXIMAGE_V2: |
245 | set_dcd_val = set_dcd_val_v2; | 242 | set_dcd_val = set_dcd_val_v2; |
246 | set_dcd_rst = set_dcd_rst_v2; | 243 | set_dcd_rst = set_dcd_rst_v2; |
247 | set_imx_hdr = set_imx_hdr_v2; | 244 | set_imx_hdr = set_imx_hdr_v2; |
248 | max_dcd_entries = MAX_HW_CFG_SIZE_V2; | 245 | max_dcd_entries = MAX_HW_CFG_SIZE_V2; |
249 | break; | 246 | break; |
250 | default: | 247 | default: |
251 | err_imximage_version(imximage_version); | 248 | err_imximage_version(imximage_version); |
252 | break; | 249 | break; |
253 | } | 250 | } |
254 | } | 251 | } |
255 | 252 | ||
256 | static void print_hdr_v1(struct imx_header *imx_hdr) | 253 | static void print_hdr_v1(struct imx_header *imx_hdr) |
257 | { | 254 | { |
258 | imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; | 255 | imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; |
259 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; | 256 | flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; |
260 | dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; | 257 | dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; |
261 | uint32_t size, length, ver; | 258 | uint32_t size, length, ver; |
262 | 259 | ||
263 | size = dcd_v1->preamble.length; | 260 | size = dcd_v1->preamble.length; |
264 | if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) { | 261 | if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) { |
265 | fprintf(stderr, | 262 | fprintf(stderr, |
266 | "Error: Image corrupt DCD size %d exceed maximum %d\n", | 263 | "Error: Image corrupt DCD size %d exceed maximum %d\n", |
267 | (uint32_t)(size / sizeof(dcd_type_addr_data_t)), | 264 | (uint32_t)(size / sizeof(dcd_type_addr_data_t)), |
268 | MAX_HW_CFG_SIZE_V1); | 265 | MAX_HW_CFG_SIZE_V1); |
269 | exit(EXIT_FAILURE); | 266 | exit(EXIT_FAILURE); |
270 | } | 267 | } |
271 | 268 | ||
272 | length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t); | 269 | length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t); |
273 | ver = detect_imximage_version(imx_hdr); | 270 | ver = detect_imximage_version(imx_hdr); |
274 | 271 | ||
275 | printf("Image Type: Freescale IMX Boot Image\n"); | 272 | printf("Image Type: Freescale IMX Boot Image\n"); |
276 | printf("Image Ver: %x", ver); | 273 | printf("Image Ver: %x", ver); |
277 | printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver)); | 274 | printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver)); |
278 | printf("Data Size: "); | 275 | printf("Data Size: "); |
279 | genimg_print_size(dcd_v1->addr_data[length].type); | 276 | genimg_print_size(dcd_v1->addr_data[length].type); |
280 | printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr); | 277 | printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr); |
281 | printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); | 278 | printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); |
282 | } | 279 | } |
283 | 280 | ||
284 | static void print_hdr_v2(struct imx_header *imx_hdr) | 281 | static void print_hdr_v2(struct imx_header *imx_hdr) |
285 | { | 282 | { |
286 | imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; | 283 | imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; |
287 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; | 284 | flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; |
288 | dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; | 285 | dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; |
289 | uint32_t size, version; | 286 | uint32_t size, version; |
290 | 287 | ||
291 | size = be16_to_cpu(dcd_v2->header.length) - 8; | 288 | size = be16_to_cpu(dcd_v2->header.length) - 8; |
292 | if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { | 289 | if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { |
293 | fprintf(stderr, | 290 | fprintf(stderr, |
294 | "Error: Image corrupt DCD size %d exceed maximum %d\n", | 291 | "Error: Image corrupt DCD size %d exceed maximum %d\n", |
295 | (uint32_t)(size / sizeof(dcd_addr_data_t)), | 292 | (uint32_t)(size / sizeof(dcd_addr_data_t)), |
296 | MAX_HW_CFG_SIZE_V2); | 293 | MAX_HW_CFG_SIZE_V2); |
297 | exit(EXIT_FAILURE); | 294 | exit(EXIT_FAILURE); |
298 | } | 295 | } |
299 | 296 | ||
300 | version = detect_imximage_version(imx_hdr); | 297 | version = detect_imximage_version(imx_hdr); |
301 | 298 | ||
302 | printf("Image Type: Freescale IMX Boot Image\n"); | 299 | printf("Image Type: Freescale IMX Boot Image\n"); |
303 | printf("Image Ver: %x", version); | 300 | printf("Image Ver: %x", version); |
304 | printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); | 301 | printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); |
305 | printf("Data Size: "); | 302 | printf("Data Size: "); |
306 | genimg_print_size(hdr_v2->boot_data.size); | 303 | genimg_print_size(hdr_v2->boot_data.size); |
307 | printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); | 304 | printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); |
308 | printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); | 305 | printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); |
309 | } | 306 | } |
310 | 307 | ||
311 | static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, | 308 | static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, |
312 | char *name, int lineno, int fld, int dcd_len) | 309 | char *name, int lineno, int fld, int dcd_len) |
313 | { | 310 | { |
314 | int value; | 311 | int value; |
315 | static int cmd_ver_first = ~0; | 312 | static int cmd_ver_first = ~0; |
316 | 313 | ||
317 | switch (cmd) { | 314 | switch (cmd) { |
318 | case CMD_IMAGE_VERSION: | 315 | case CMD_IMAGE_VERSION: |
319 | imximage_version = get_cfg_value(token, name, lineno); | 316 | imximage_version = get_cfg_value(token, name, lineno); |
320 | if (cmd_ver_first == 0) { | 317 | if (cmd_ver_first == 0) { |
321 | fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " | 318 | fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " |
322 | "command need be the first before other " | 319 | "command need be the first before other " |
323 | "valid command in the file\n", name, lineno); | 320 | "valid command in the file\n", name, lineno); |
324 | exit(EXIT_FAILURE); | 321 | exit(EXIT_FAILURE); |
325 | } | 322 | } |
326 | cmd_ver_first = 1; | 323 | cmd_ver_first = 1; |
327 | set_hdr_func(imxhdr); | 324 | set_hdr_func(imxhdr); |
328 | break; | 325 | break; |
329 | case CMD_BOOT_FROM: | 326 | case CMD_BOOT_FROM: |
330 | imxhdr->flash_offset = get_table_entry_id(imximage_bootops, | 327 | imxhdr->flash_offset = get_table_entry_id(imximage_bootops, |
331 | "imximage boot option", token); | 328 | "imximage boot option", token); |
332 | if (imxhdr->flash_offset == -1) { | 329 | if (imxhdr->flash_offset == -1) { |
333 | fprintf(stderr, "Error: %s[%d] -Invalid boot device" | 330 | fprintf(stderr, "Error: %s[%d] -Invalid boot device" |
334 | "(%s)\n", name, lineno, token); | 331 | "(%s)\n", name, lineno, token); |
335 | exit(EXIT_FAILURE); | 332 | exit(EXIT_FAILURE); |
336 | } | 333 | } |
337 | if (unlikely(cmd_ver_first != 1)) | 334 | if (unlikely(cmd_ver_first != 1)) |
338 | cmd_ver_first = 0; | 335 | cmd_ver_first = 0; |
339 | break; | 336 | break; |
340 | case CMD_BOOT_OFFSET: | 337 | case CMD_BOOT_OFFSET: |
341 | imxhdr->flash_offset = get_cfg_value(token, name, lineno); | 338 | imxhdr->flash_offset = get_cfg_value(token, name, lineno); |
342 | if (unlikely(cmd_ver_first != 1)) | 339 | if (unlikely(cmd_ver_first != 1)) |
343 | cmd_ver_first = 0; | 340 | cmd_ver_first = 0; |
344 | break; | 341 | break; |
345 | case CMD_DATA: | 342 | case CMD_DATA: |
346 | value = get_cfg_value(token, name, lineno); | 343 | value = get_cfg_value(token, name, lineno); |
347 | (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len); | 344 | (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len); |
348 | if (unlikely(cmd_ver_first != 1)) | 345 | if (unlikely(cmd_ver_first != 1)) |
349 | cmd_ver_first = 0; | 346 | cmd_ver_first = 0; |
350 | break; | 347 | break; |
351 | } | 348 | } |
352 | } | 349 | } |
353 | 350 | ||
354 | static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, | 351 | static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, |
355 | char *token, char *name, int lineno, int fld, int *dcd_len) | 352 | char *token, char *name, int lineno, int fld, int *dcd_len) |
356 | { | 353 | { |
357 | int value; | 354 | int value; |
358 | 355 | ||
359 | switch (fld) { | 356 | switch (fld) { |
360 | case CFG_COMMAND: | 357 | case CFG_COMMAND: |
361 | *cmd = get_table_entry_id(imximage_cmds, | 358 | *cmd = get_table_entry_id(imximage_cmds, |
362 | "imximage commands", token); | 359 | "imximage commands", token); |
363 | if (*cmd < 0) { | 360 | if (*cmd < 0) { |
364 | fprintf(stderr, "Error: %s[%d] - Invalid command" | 361 | fprintf(stderr, "Error: %s[%d] - Invalid command" |
365 | "(%s)\n", name, lineno, token); | 362 | "(%s)\n", name, lineno, token); |
366 | exit(EXIT_FAILURE); | 363 | exit(EXIT_FAILURE); |
367 | } | 364 | } |
368 | break; | 365 | break; |
369 | case CFG_REG_SIZE: | 366 | case CFG_REG_SIZE: |
370 | parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len); | 367 | parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len); |
371 | break; | 368 | break; |
372 | case CFG_REG_ADDRESS: | 369 | case CFG_REG_ADDRESS: |
373 | case CFG_REG_VALUE: | 370 | case CFG_REG_VALUE: |
374 | if (*cmd != CMD_DATA) | 371 | if (*cmd != CMD_DATA) |
375 | return; | 372 | return; |
376 | 373 | ||
377 | value = get_cfg_value(token, name, lineno); | 374 | value = get_cfg_value(token, name, lineno); |
378 | (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); | 375 | (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); |
379 | 376 | ||
380 | if (fld == CFG_REG_VALUE) { | 377 | if (fld == CFG_REG_VALUE) { |
381 | (*dcd_len)++; | 378 | (*dcd_len)++; |
382 | if (*dcd_len > max_dcd_entries) { | 379 | if (*dcd_len > max_dcd_entries) { |
383 | fprintf(stderr, "Error: %s[%d] -" | 380 | fprintf(stderr, "Error: %s[%d] -" |
384 | "DCD table exceeds maximum size(%d)\n", | 381 | "DCD table exceeds maximum size(%d)\n", |
385 | name, lineno, max_dcd_entries); | 382 | name, lineno, max_dcd_entries); |
386 | exit(EXIT_FAILURE); | 383 | exit(EXIT_FAILURE); |
387 | } | 384 | } |
388 | } | 385 | } |
389 | break; | 386 | break; |
390 | default: | 387 | default: |
391 | break; | 388 | break; |
392 | } | 389 | } |
393 | } | 390 | } |
394 | static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name) | 391 | static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name) |
395 | { | 392 | { |
396 | FILE *fd = NULL; | 393 | FILE *fd = NULL; |
397 | char *line = NULL; | 394 | char *line = NULL; |
398 | char *token, *saveptr1, *saveptr2; | 395 | char *token, *saveptr1, *saveptr2; |
399 | int lineno = 0; | 396 | int lineno = 0; |
400 | int fld; | 397 | int fld; |
401 | size_t len; | 398 | size_t len; |
402 | int dcd_len = 0; | 399 | int dcd_len = 0; |
403 | int32_t cmd; | 400 | int32_t cmd; |
404 | 401 | ||
405 | fd = fopen(name, "r"); | 402 | fd = fopen(name, "r"); |
406 | if (fd == 0) { | 403 | if (fd == 0) { |
407 | fprintf(stderr, "Error: %s - Can't open DCD file\n", name); | 404 | fprintf(stderr, "Error: %s - Can't open DCD file\n", name); |
408 | exit(EXIT_FAILURE); | 405 | exit(EXIT_FAILURE); |
409 | } | 406 | } |
410 | 407 | ||
411 | /* Very simple parsing, line starting with # are comments | 408 | /* Very simple parsing, line starting with # are comments |
412 | * and are dropped | 409 | * and are dropped |
413 | */ | 410 | */ |
414 | while ((getline(&line, &len, fd)) > 0) { | 411 | while ((getline(&line, &len, fd)) > 0) { |
415 | lineno++; | 412 | lineno++; |
416 | 413 | ||
417 | token = strtok_r(line, "\r\n", &saveptr1); | 414 | token = strtok_r(line, "\r\n", &saveptr1); |
418 | if (token == NULL) | 415 | if (token == NULL) |
419 | continue; | 416 | continue; |
420 | 417 | ||
421 | /* Check inside the single line */ | 418 | /* Check inside the single line */ |
422 | for (fld = CFG_COMMAND, cmd = CMD_INVALID, | 419 | for (fld = CFG_COMMAND, cmd = CMD_INVALID, |
423 | line = token; ; line = NULL, fld++) { | 420 | line = token; ; line = NULL, fld++) { |
424 | token = strtok_r(line, " \t", &saveptr2); | 421 | token = strtok_r(line, " \t", &saveptr2); |
425 | if (token == NULL) | 422 | if (token == NULL) |
426 | break; | 423 | break; |
427 | 424 | ||
428 | /* Drop all text starting with '#' as comments */ | 425 | /* Drop all text starting with '#' as comments */ |
429 | if (token[0] == '#') | 426 | if (token[0] == '#') |
430 | break; | 427 | break; |
431 | 428 | ||
432 | parse_cfg_fld(imxhdr, &cmd, token, name, | 429 | parse_cfg_fld(imxhdr, &cmd, token, name, |
433 | lineno, fld, &dcd_len); | 430 | lineno, fld, &dcd_len); |
434 | } | 431 | } |
435 | 432 | ||
436 | } | 433 | } |
437 | 434 | ||
438 | (*set_dcd_rst)(imxhdr, dcd_len, name, lineno); | 435 | (*set_dcd_rst)(imxhdr, dcd_len, name, lineno); |
439 | fclose(fd); | 436 | fclose(fd); |
440 | 437 | ||
441 | /* Exit if there is no BOOT_FROM field specifying the flash_offset */ | 438 | /* Exit if there is no BOOT_FROM field specifying the flash_offset */ |
442 | if (imxhdr->flash_offset == FLASH_OFFSET_UNDEFINED) { | 439 | if (imxhdr->flash_offset == FLASH_OFFSET_UNDEFINED) { |
443 | fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name); | 440 | fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name); |
444 | exit(EXIT_FAILURE); | 441 | exit(EXIT_FAILURE); |
445 | } | 442 | } |
446 | return dcd_len; | 443 | return dcd_len; |
447 | } | 444 | } |
448 | 445 | ||
449 | 446 | ||
450 | static int imximage_check_image_types(uint8_t type) | 447 | static int imximage_check_image_types(uint8_t type) |
451 | { | 448 | { |
452 | if (type == IH_TYPE_IMXIMAGE) | 449 | if (type == IH_TYPE_IMXIMAGE) |
453 | return EXIT_SUCCESS; | 450 | return EXIT_SUCCESS; |
454 | else | 451 | else |
455 | return EXIT_FAILURE; | 452 | return EXIT_FAILURE; |
456 | } | 453 | } |
457 | 454 | ||
458 | static int imximage_verify_header(unsigned char *ptr, int image_size, | 455 | static int imximage_verify_header(unsigned char *ptr, int image_size, |
459 | struct mkimage_params *params) | 456 | struct mkimage_params *params) |
460 | { | 457 | { |
461 | struct imx_header *imx_hdr = (struct imx_header *) ptr; | 458 | struct imx_header *imx_hdr = (struct imx_header *) ptr; |
462 | 459 | ||
463 | if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID) | 460 | if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID) |
464 | return -FDT_ERR_BADSTRUCTURE; | 461 | return -FDT_ERR_BADSTRUCTURE; |
465 | 462 | ||
466 | return 0; | 463 | return 0; |
467 | } | 464 | } |
468 | 465 | ||
469 | static void imximage_print_header(const void *ptr) | 466 | static void imximage_print_header(const void *ptr) |
470 | { | 467 | { |
471 | struct imx_header *imx_hdr = (struct imx_header *) ptr; | 468 | struct imx_header *imx_hdr = (struct imx_header *) ptr; |
472 | uint32_t version = detect_imximage_version(imx_hdr); | 469 | uint32_t version = detect_imximage_version(imx_hdr); |
473 | 470 | ||
474 | switch (version) { | 471 | switch (version) { |
475 | case IMXIMAGE_V1: | 472 | case IMXIMAGE_V1: |
476 | print_hdr_v1(imx_hdr); | 473 | print_hdr_v1(imx_hdr); |
477 | break; | 474 | break; |
478 | case IMXIMAGE_V2: | 475 | case IMXIMAGE_V2: |
479 | print_hdr_v2(imx_hdr); | 476 | print_hdr_v2(imx_hdr); |
480 | break; | 477 | break; |
481 | default: | 478 | default: |
482 | err_imximage_version(version); | 479 | err_imximage_version(version); |
483 | break; | 480 | break; |
484 | } | 481 | } |
485 | } | 482 | } |
486 | 483 | ||
487 | static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, | 484 | static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, |
488 | struct mkimage_params *params) | 485 | struct mkimage_params *params) |
489 | { | 486 | { |
490 | struct imx_header *imxhdr = (struct imx_header *)ptr; | 487 | struct imx_header *imxhdr = (struct imx_header *)ptr; |
491 | uint32_t dcd_len; | 488 | uint32_t dcd_len; |
492 | 489 | ||
493 | /* | 490 | /* |
494 | * In order to not change the old imx cfg file | 491 | * In order to not change the old imx cfg file |
495 | * by adding VERSION command into it, here need | 492 | * by adding VERSION command into it, here need |
496 | * set up function ptr group to V1 by default. | 493 | * set up function ptr group to V1 by default. |
497 | */ | 494 | */ |
498 | imximage_version = IMXIMAGE_V1; | 495 | imximage_version = IMXIMAGE_V1; |
499 | /* Be able to detect if the cfg file has no BOOT_FROM tag */ | 496 | /* Be able to detect if the cfg file has no BOOT_FROM tag */ |
500 | imxhdr->flash_offset = FLASH_OFFSET_UNDEFINED; | 497 | imxhdr->flash_offset = FLASH_OFFSET_UNDEFINED; |
501 | set_hdr_func(imxhdr); | 498 | set_hdr_func(imxhdr); |
502 | 499 | ||
503 | /* Parse dcd configuration file */ | 500 | /* Parse dcd configuration file */ |
504 | dcd_len = parse_cfg_file(imxhdr, params->imagename); | 501 | dcd_len = parse_cfg_file(imxhdr, params->imagename); |
505 | 502 | ||
506 | /* Set the imx header */ | 503 | /* Set the imx header */ |
507 | (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imxhdr->flash_offset); | 504 | (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imxhdr->flash_offset); |
508 | 505 | ||
509 | /* | 506 | /* |
510 | * ROM bug alert | 507 | * ROM bug alert |
511 | * | 508 | * |
512 | * MX53 only loads 512 byte multiples in case of SD boot. | 509 | * MX53 only loads 512 byte multiples in case of SD boot. |
513 | * MX53 only loads NAND page multiples in case of NAND boot and | 510 | * MX53 only loads NAND page multiples in case of NAND boot and |
514 | * supports up to 4096 byte large pages, thus align to 4096. | 511 | * supports up to 4096 byte large pages, thus align to 4096. |
515 | * | 512 | * |
516 | * The remaining fraction of a block bytes would not be loaded! | 513 | * The remaining fraction of a block bytes would not be loaded! |
517 | */ | 514 | */ |
518 | *header_size_ptr = ROUND(sbuf->st_size + imxhdr->flash_offset, 4096); | 515 | *header_size_ptr = ROUND(sbuf->st_size + imxhdr->flash_offset, 4096); |
519 | } | 516 | } |
520 | 517 | ||
521 | int imximage_check_params(struct mkimage_params *params) | 518 | int imximage_check_params(struct mkimage_params *params) |
522 | { | 519 | { |
523 | if (!params) | 520 | if (!params) |
524 | return CFG_INVALID; | 521 | return CFG_INVALID; |
525 | if (!strlen(params->imagename)) { | 522 | if (!strlen(params->imagename)) { |
526 | fprintf(stderr, "Error: %s - Configuration file not specified, " | 523 | fprintf(stderr, "Error: %s - Configuration file not specified, " |
527 | "it is needed for imximage generation\n", | 524 | "it is needed for imximage generation\n", |
528 | params->cmdname); | 525 | params->cmdname); |
529 | return CFG_INVALID; | 526 | return CFG_INVALID; |
530 | } | 527 | } |
531 | /* | 528 | /* |
532 | * Check parameters: | 529 | * Check parameters: |
533 | * XIP is not allowed and verify that incompatible | 530 | * XIP is not allowed and verify that incompatible |
534 | * parameters are not sent at the same time | 531 | * parameters are not sent at the same time |
535 | * For example, if list is required a data image must not be provided | 532 | * For example, if list is required a data image must not be provided |
536 | */ | 533 | */ |
537 | return (params->dflag && (params->fflag || params->lflag)) || | 534 | return (params->dflag && (params->fflag || params->lflag)) || |
538 | (params->fflag && (params->dflag || params->lflag)) || | 535 | (params->fflag && (params->dflag || params->lflag)) || |
539 | (params->lflag && (params->dflag || params->fflag)) || | 536 | (params->lflag && (params->dflag || params->fflag)) || |
540 | (params->xflag) || !(strlen(params->imagename)); | 537 | (params->xflag) || !(strlen(params->imagename)); |
541 | } | 538 | } |
542 | 539 | ||
543 | /* | 540 | /* |
544 | * imximage parameters | 541 | * imximage parameters |
545 | */ | 542 | */ |
546 | static struct image_type_params imximage_params = { | 543 | static struct image_type_params imximage_params = { |
547 | .name = "Freescale i.MX Boot Image support", | 544 | .name = "Freescale i.MX Boot Image support", |
548 | .header_size = sizeof(struct imx_header), | 545 | .header_size = sizeof(struct imx_header), |
549 | .hdr = (void *)&imximage_header, | 546 | .hdr = (void *)&imximage_header, |
550 | .check_image_type = imximage_check_image_types, | 547 | .check_image_type = imximage_check_image_types, |
551 | .verify_header = imximage_verify_header, | 548 | .verify_header = imximage_verify_header, |
552 | .print_header = imximage_print_header, | 549 | .print_header = imximage_print_header, |
553 | .set_header = imximage_set_header, | 550 | .set_header = imximage_set_header, |
554 | .check_params = imximage_check_params, | 551 | .check_params = imximage_check_params, |
555 | }; | 552 | }; |
556 | 553 | ||
557 | void init_imx_image_type(void) | 554 | void init_imx_image_type(void) |
558 | { | 555 | { |
559 | mkimage_register(&imximage_params); | 556 | mkimage_register(&imximage_params); |
560 | } | 557 | } |
561 | 558 |
tools/kwbimage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2008 | 2 | * (C) Copyright 2008 |
3 | * Marvell Semiconductor <www.marvell.com> | 3 | * Marvell Semiconductor <www.marvell.com> |
4 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> | 4 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* Required to obtain the getline prototype from stdio.h */ | ||
10 | #define _GNU_SOURCE | ||
11 | |||
12 | #include "mkimage.h" | 9 | #include "mkimage.h" |
13 | #include <image.h> | 10 | #include <image.h> |
14 | #include "kwbimage.h" | 11 | #include "kwbimage.h" |
15 | 12 | ||
16 | /* | 13 | /* |
17 | * Supported commands for configuration file | 14 | * Supported commands for configuration file |
18 | */ | 15 | */ |
19 | static table_entry_t kwbimage_cmds[] = { | 16 | static table_entry_t kwbimage_cmds[] = { |
20 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, | 17 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, |
21 | {CMD_NAND_ECC_MODE, "NAND_ECC_MODE", "NAND mode", }, | 18 | {CMD_NAND_ECC_MODE, "NAND_ECC_MODE", "NAND mode", }, |
22 | {CMD_NAND_PAGE_SIZE, "NAND_PAGE_SIZE", "NAND size", }, | 19 | {CMD_NAND_PAGE_SIZE, "NAND_PAGE_SIZE", "NAND size", }, |
23 | {CMD_SATA_PIO_MODE, "SATA_PIO_MODE", "SATA mode", }, | 20 | {CMD_SATA_PIO_MODE, "SATA_PIO_MODE", "SATA mode", }, |
24 | {CMD_DDR_INIT_DELAY, "DDR_INIT_DELAY", "DDR init dly", }, | 21 | {CMD_DDR_INIT_DELAY, "DDR_INIT_DELAY", "DDR init dly", }, |
25 | {CMD_DATA, "DATA", "Reg Write Data", }, | 22 | {CMD_DATA, "DATA", "Reg Write Data", }, |
26 | {CMD_INVALID, "", "", }, | 23 | {CMD_INVALID, "", "", }, |
27 | }; | 24 | }; |
28 | 25 | ||
29 | /* | 26 | /* |
30 | * Supported Boot options for configuration file | 27 | * Supported Boot options for configuration file |
31 | */ | 28 | */ |
32 | static table_entry_t kwbimage_bootops[] = { | 29 | static table_entry_t kwbimage_bootops[] = { |
33 | {IBR_HDR_SPI_ID, "spi", "SPI Flash", }, | 30 | {IBR_HDR_SPI_ID, "spi", "SPI Flash", }, |
34 | {IBR_HDR_NAND_ID, "nand", "NAND Flash", }, | 31 | {IBR_HDR_NAND_ID, "nand", "NAND Flash", }, |
35 | {IBR_HDR_SATA_ID, "sata", "Sata port", }, | 32 | {IBR_HDR_SATA_ID, "sata", "Sata port", }, |
36 | {IBR_HDR_PEX_ID, "pex", "PCIe port", }, | 33 | {IBR_HDR_PEX_ID, "pex", "PCIe port", }, |
37 | {IBR_HDR_UART_ID, "uart", "Serial port", }, | 34 | {IBR_HDR_UART_ID, "uart", "Serial port", }, |
38 | {-1, "", "Invalid", }, | 35 | {-1, "", "Invalid", }, |
39 | }; | 36 | }; |
40 | 37 | ||
41 | /* | 38 | /* |
42 | * Supported NAND ecc options configuration file | 39 | * Supported NAND ecc options configuration file |
43 | */ | 40 | */ |
44 | static table_entry_t kwbimage_eccmodes[] = { | 41 | static table_entry_t kwbimage_eccmodes[] = { |
45 | {IBR_HDR_ECC_DEFAULT, "default", "Default mode", }, | 42 | {IBR_HDR_ECC_DEFAULT, "default", "Default mode", }, |
46 | {IBR_HDR_ECC_FORCED_HAMMING, "hamming", "Hamming mode", }, | 43 | {IBR_HDR_ECC_FORCED_HAMMING, "hamming", "Hamming mode", }, |
47 | {IBR_HDR_ECC_FORCED_RS, "rs", "RS mode", }, | 44 | {IBR_HDR_ECC_FORCED_RS, "rs", "RS mode", }, |
48 | {IBR_HDR_ECC_DISABLED, "disabled", "ECC Disabled", }, | 45 | {IBR_HDR_ECC_DISABLED, "disabled", "ECC Disabled", }, |
49 | {-1, "", "", }, | 46 | {-1, "", "", }, |
50 | }; | 47 | }; |
51 | 48 | ||
52 | static struct kwb_header kwbimage_header; | 49 | static struct kwb_header kwbimage_header; |
53 | static int datacmd_cnt = 0; | 50 | static int datacmd_cnt = 0; |
54 | static char * fname = "Unknown"; | 51 | static char * fname = "Unknown"; |
55 | static int lineno = -1; | 52 | static int lineno = -1; |
56 | 53 | ||
57 | /* | 54 | /* |
58 | * Report Error if xflag is set in addition to default | 55 | * Report Error if xflag is set in addition to default |
59 | */ | 56 | */ |
60 | static int kwbimage_check_params (struct mkimage_params *params) | 57 | static int kwbimage_check_params (struct mkimage_params *params) |
61 | { | 58 | { |
62 | if (!strlen (params->imagename)) { | 59 | if (!strlen (params->imagename)) { |
63 | printf ("Error:%s - Configuration file not specified, " | 60 | printf ("Error:%s - Configuration file not specified, " |
64 | "it is needed for kwbimage generation\n", | 61 | "it is needed for kwbimage generation\n", |
65 | params->cmdname); | 62 | params->cmdname); |
66 | return CFG_INVALID; | 63 | return CFG_INVALID; |
67 | } | 64 | } |
68 | return ((params->dflag && (params->fflag || params->lflag)) || | 65 | return ((params->dflag && (params->fflag || params->lflag)) || |
69 | (params->fflag && (params->dflag || params->lflag)) || | 66 | (params->fflag && (params->dflag || params->lflag)) || |
70 | (params->lflag && (params->dflag || params->fflag)) || | 67 | (params->lflag && (params->dflag || params->fflag)) || |
71 | (params->xflag) || !(strlen (params->imagename))); | 68 | (params->xflag) || !(strlen (params->imagename))); |
72 | } | 69 | } |
73 | 70 | ||
74 | static uint32_t check_get_hexval (char *token) | 71 | static uint32_t check_get_hexval (char *token) |
75 | { | 72 | { |
76 | uint32_t hexval; | 73 | uint32_t hexval; |
77 | 74 | ||
78 | if (!sscanf (token, "%x", &hexval)) { | 75 | if (!sscanf (token, "%x", &hexval)) { |
79 | printf ("Error:%s[%d] - Invalid hex data(%s)\n", fname, | 76 | printf ("Error:%s[%d] - Invalid hex data(%s)\n", fname, |
80 | lineno, token); | 77 | lineno, token); |
81 | exit (EXIT_FAILURE); | 78 | exit (EXIT_FAILURE); |
82 | } | 79 | } |
83 | return hexval; | 80 | return hexval; |
84 | } | 81 | } |
85 | 82 | ||
86 | /* | 83 | /* |
87 | * Generates 8 bit checksum | 84 | * Generates 8 bit checksum |
88 | */ | 85 | */ |
89 | static uint8_t kwbimage_checksum8 (void *start, uint32_t len, uint8_t csum) | 86 | static uint8_t kwbimage_checksum8 (void *start, uint32_t len, uint8_t csum) |
90 | { | 87 | { |
91 | register uint8_t sum = csum; | 88 | register uint8_t sum = csum; |
92 | volatile uint8_t *p = (volatile uint8_t *)start; | 89 | volatile uint8_t *p = (volatile uint8_t *)start; |
93 | 90 | ||
94 | /* check len and return zero checksum if invalid */ | 91 | /* check len and return zero checksum if invalid */ |
95 | if (!len) | 92 | if (!len) |
96 | return 0; | 93 | return 0; |
97 | 94 | ||
98 | do { | 95 | do { |
99 | sum += *p; | 96 | sum += *p; |
100 | p++; | 97 | p++; |
101 | } while (--len); | 98 | } while (--len); |
102 | return (sum); | 99 | return (sum); |
103 | } | 100 | } |
104 | 101 | ||
105 | /* | 102 | /* |
106 | * Generates 32 bit checksum | 103 | * Generates 32 bit checksum |
107 | */ | 104 | */ |
108 | static uint32_t kwbimage_checksum32 (uint32_t *start, uint32_t len, uint32_t csum) | 105 | static uint32_t kwbimage_checksum32 (uint32_t *start, uint32_t len, uint32_t csum) |
109 | { | 106 | { |
110 | register uint32_t sum = csum; | 107 | register uint32_t sum = csum; |
111 | volatile uint32_t *p = start; | 108 | volatile uint32_t *p = start; |
112 | 109 | ||
113 | /* check len and return zero checksum if invalid */ | 110 | /* check len and return zero checksum if invalid */ |
114 | if (!len) | 111 | if (!len) |
115 | return 0; | 112 | return 0; |
116 | 113 | ||
117 | if (len % sizeof(uint32_t)) { | 114 | if (len % sizeof(uint32_t)) { |
118 | printf ("Error:%s[%d] - length is not in multiple of %zu\n", | 115 | printf ("Error:%s[%d] - length is not in multiple of %zu\n", |
119 | __FUNCTION__, len, sizeof(uint32_t)); | 116 | __FUNCTION__, len, sizeof(uint32_t)); |
120 | return 0; | 117 | return 0; |
121 | } | 118 | } |
122 | 119 | ||
123 | do { | 120 | do { |
124 | sum += *p; | 121 | sum += *p; |
125 | p++; | 122 | p++; |
126 | len -= sizeof(uint32_t); | 123 | len -= sizeof(uint32_t); |
127 | } while (len > 0); | 124 | } while (len > 0); |
128 | return (sum); | 125 | return (sum); |
129 | } | 126 | } |
130 | 127 | ||
131 | static void kwbimage_check_cfgdata (char *token, enum kwbimage_cmd cmdsw, | 128 | static void kwbimage_check_cfgdata (char *token, enum kwbimage_cmd cmdsw, |
132 | struct kwb_header *kwbhdr) | 129 | struct kwb_header *kwbhdr) |
133 | { | 130 | { |
134 | bhr_t *mhdr = &kwbhdr->kwb_hdr; | 131 | bhr_t *mhdr = &kwbhdr->kwb_hdr; |
135 | extbhr_t *exthdr = &kwbhdr->kwb_exthdr; | 132 | extbhr_t *exthdr = &kwbhdr->kwb_exthdr; |
136 | int i; | 133 | int i; |
137 | 134 | ||
138 | switch (cmdsw) { | 135 | switch (cmdsw) { |
139 | case CMD_BOOT_FROM: | 136 | case CMD_BOOT_FROM: |
140 | i = get_table_entry_id (kwbimage_bootops, | 137 | i = get_table_entry_id (kwbimage_bootops, |
141 | "Kwbimage boot option", token); | 138 | "Kwbimage boot option", token); |
142 | 139 | ||
143 | if (i < 0) | 140 | if (i < 0) |
144 | goto INVL_DATA; | 141 | goto INVL_DATA; |
145 | 142 | ||
146 | mhdr->blockid = i; | 143 | mhdr->blockid = i; |
147 | printf ("Preparing kirkwood boot image to boot " | 144 | printf ("Preparing kirkwood boot image to boot " |
148 | "from %s\n", token); | 145 | "from %s\n", token); |
149 | break; | 146 | break; |
150 | case CMD_NAND_ECC_MODE: | 147 | case CMD_NAND_ECC_MODE: |
151 | i = get_table_entry_id (kwbimage_eccmodes, | 148 | i = get_table_entry_id (kwbimage_eccmodes, |
152 | "NAND ecc mode", token); | 149 | "NAND ecc mode", token); |
153 | 150 | ||
154 | if (i < 0) | 151 | if (i < 0) |
155 | goto INVL_DATA; | 152 | goto INVL_DATA; |
156 | 153 | ||
157 | mhdr->nandeccmode = i; | 154 | mhdr->nandeccmode = i; |
158 | printf ("Nand ECC mode = %s\n", token); | 155 | printf ("Nand ECC mode = %s\n", token); |
159 | break; | 156 | break; |
160 | case CMD_NAND_PAGE_SIZE: | 157 | case CMD_NAND_PAGE_SIZE: |
161 | mhdr->nandpagesize = | 158 | mhdr->nandpagesize = |
162 | (uint16_t) check_get_hexval (token); | 159 | (uint16_t) check_get_hexval (token); |
163 | printf ("Nand page size = 0x%x\n", mhdr->nandpagesize); | 160 | printf ("Nand page size = 0x%x\n", mhdr->nandpagesize); |
164 | break; | 161 | break; |
165 | case CMD_SATA_PIO_MODE: | 162 | case CMD_SATA_PIO_MODE: |
166 | mhdr->satapiomode = | 163 | mhdr->satapiomode = |
167 | (uint8_t) check_get_hexval (token); | 164 | (uint8_t) check_get_hexval (token); |
168 | printf ("Sata PIO mode = 0x%x\n", | 165 | printf ("Sata PIO mode = 0x%x\n", |
169 | mhdr->satapiomode); | 166 | mhdr->satapiomode); |
170 | break; | 167 | break; |
171 | case CMD_DDR_INIT_DELAY: | 168 | case CMD_DDR_INIT_DELAY: |
172 | mhdr->ddrinitdelay = | 169 | mhdr->ddrinitdelay = |
173 | (uint16_t) check_get_hexval (token); | 170 | (uint16_t) check_get_hexval (token); |
174 | printf ("DDR init delay = %d msec\n", mhdr->ddrinitdelay); | 171 | printf ("DDR init delay = %d msec\n", mhdr->ddrinitdelay); |
175 | break; | 172 | break; |
176 | case CMD_DATA: | 173 | case CMD_DATA: |
177 | exthdr->rcfg[datacmd_cnt].raddr = | 174 | exthdr->rcfg[datacmd_cnt].raddr = |
178 | check_get_hexval (token); | 175 | check_get_hexval (token); |
179 | 176 | ||
180 | break; | 177 | break; |
181 | case CMD_INVALID: | 178 | case CMD_INVALID: |
182 | goto INVL_DATA; | 179 | goto INVL_DATA; |
183 | default: | 180 | default: |
184 | goto INVL_DATA; | 181 | goto INVL_DATA; |
185 | } | 182 | } |
186 | return; | 183 | return; |
187 | 184 | ||
188 | INVL_DATA: | 185 | INVL_DATA: |
189 | printf ("Error:%s[%d] - Invalid data\n", fname, lineno); | 186 | printf ("Error:%s[%d] - Invalid data\n", fname, lineno); |
190 | exit (EXIT_FAILURE); | 187 | exit (EXIT_FAILURE); |
191 | } | 188 | } |
192 | 189 | ||
193 | /* | 190 | /* |
194 | * this function sets the kwbimage header by- | 191 | * this function sets the kwbimage header by- |
195 | * 1. Abstracting input command line arguments data | 192 | * 1. Abstracting input command line arguments data |
196 | * 2. parses the kwbimage configuration file and update extebded header data | 193 | * 2. parses the kwbimage configuration file and update extebded header data |
197 | * 3. calculates header, extended header and image checksums | 194 | * 3. calculates header, extended header and image checksums |
198 | */ | 195 | */ |
199 | static void kwdimage_set_ext_header (struct kwb_header *kwbhdr, char* name) { | 196 | static void kwdimage_set_ext_header (struct kwb_header *kwbhdr, char* name) { |
200 | bhr_t *mhdr = &kwbhdr->kwb_hdr; | 197 | bhr_t *mhdr = &kwbhdr->kwb_hdr; |
201 | extbhr_t *exthdr = &kwbhdr->kwb_exthdr; | 198 | extbhr_t *exthdr = &kwbhdr->kwb_exthdr; |
202 | FILE *fd = NULL; | 199 | FILE *fd = NULL; |
203 | int j; | 200 | int j; |
204 | char *line = NULL; | 201 | char *line = NULL; |
205 | char * token, *saveptr1, *saveptr2; | 202 | char * token, *saveptr1, *saveptr2; |
206 | size_t len = 0; | 203 | size_t len = 0; |
207 | enum kwbimage_cmd cmd; | 204 | enum kwbimage_cmd cmd; |
208 | 205 | ||
209 | fname = name; | 206 | fname = name; |
210 | /* set dram register offset */ | 207 | /* set dram register offset */ |
211 | exthdr->dramregsoffs = (intptr_t)&exthdr->rcfg - (intptr_t)mhdr; | 208 | exthdr->dramregsoffs = (intptr_t)&exthdr->rcfg - (intptr_t)mhdr; |
212 | 209 | ||
213 | if ((fd = fopen (name, "r")) == 0) { | 210 | if ((fd = fopen (name, "r")) == 0) { |
214 | printf ("Error:%s - Can't open\n", fname); | 211 | printf ("Error:%s - Can't open\n", fname); |
215 | exit (EXIT_FAILURE); | 212 | exit (EXIT_FAILURE); |
216 | } | 213 | } |
217 | 214 | ||
218 | /* Simple kwimage.cfg file parser */ | 215 | /* Simple kwimage.cfg file parser */ |
219 | lineno=0; | 216 | lineno=0; |
220 | while ((getline (&line, &len, fd)) > 0) { | 217 | while ((getline (&line, &len, fd)) > 0) { |
221 | lineno++; | 218 | lineno++; |
222 | token = strtok_r (line, "\r\n", &saveptr1); | 219 | token = strtok_r (line, "\r\n", &saveptr1); |
223 | /* drop all lines with zero tokens (= empty lines) */ | 220 | /* drop all lines with zero tokens (= empty lines) */ |
224 | if (token == NULL) | 221 | if (token == NULL) |
225 | continue; | 222 | continue; |
226 | 223 | ||
227 | for (j = 0, cmd = CMD_INVALID, line = token; ; line = NULL) { | 224 | for (j = 0, cmd = CMD_INVALID, line = token; ; line = NULL) { |
228 | token = strtok_r (line, " \t", &saveptr2); | 225 | token = strtok_r (line, " \t", &saveptr2); |
229 | if (token == NULL) | 226 | if (token == NULL) |
230 | break; | 227 | break; |
231 | /* Drop all text starting with '#' as comments */ | 228 | /* Drop all text starting with '#' as comments */ |
232 | if (token[0] == '#') | 229 | if (token[0] == '#') |
233 | break; | 230 | break; |
234 | 231 | ||
235 | /* Process rest as valid config command line */ | 232 | /* Process rest as valid config command line */ |
236 | switch (j) { | 233 | switch (j) { |
237 | case CFG_COMMAND: | 234 | case CFG_COMMAND: |
238 | cmd = get_table_entry_id (kwbimage_cmds, | 235 | cmd = get_table_entry_id (kwbimage_cmds, |
239 | "Kwbimage command", token); | 236 | "Kwbimage command", token); |
240 | 237 | ||
241 | if (cmd == CMD_INVALID) | 238 | if (cmd == CMD_INVALID) |
242 | goto INVL_CMD; | 239 | goto INVL_CMD; |
243 | break; | 240 | break; |
244 | 241 | ||
245 | case CFG_DATA0: | 242 | case CFG_DATA0: |
246 | kwbimage_check_cfgdata (token, cmd, kwbhdr); | 243 | kwbimage_check_cfgdata (token, cmd, kwbhdr); |
247 | break; | 244 | break; |
248 | 245 | ||
249 | case CFG_DATA1: | 246 | case CFG_DATA1: |
250 | if (cmd != CMD_DATA) | 247 | if (cmd != CMD_DATA) |
251 | goto INVL_CMD; | 248 | goto INVL_CMD; |
252 | 249 | ||
253 | exthdr->rcfg[datacmd_cnt].rdata = | 250 | exthdr->rcfg[datacmd_cnt].rdata = |
254 | check_get_hexval (token); | 251 | check_get_hexval (token); |
255 | 252 | ||
256 | if (datacmd_cnt > KWBIMAGE_MAX_CONFIG ) { | 253 | if (datacmd_cnt > KWBIMAGE_MAX_CONFIG ) { |
257 | printf ("Error:%s[%d] - Found more " | 254 | printf ("Error:%s[%d] - Found more " |
258 | "than max(%zd) allowed " | 255 | "than max(%zd) allowed " |
259 | "data configurations\n", | 256 | "data configurations\n", |
260 | fname, lineno, | 257 | fname, lineno, |
261 | KWBIMAGE_MAX_CONFIG); | 258 | KWBIMAGE_MAX_CONFIG); |
262 | exit (EXIT_FAILURE); | 259 | exit (EXIT_FAILURE); |
263 | } else | 260 | } else |
264 | datacmd_cnt++; | 261 | datacmd_cnt++; |
265 | break; | 262 | break; |
266 | 263 | ||
267 | default: | 264 | default: |
268 | goto INVL_CMD; | 265 | goto INVL_CMD; |
269 | } | 266 | } |
270 | j++; | 267 | j++; |
271 | } | 268 | } |
272 | } | 269 | } |
273 | if (line) | 270 | if (line) |
274 | free (line); | 271 | free (line); |
275 | 272 | ||
276 | fclose (fd); | 273 | fclose (fd); |
277 | return; | 274 | return; |
278 | 275 | ||
279 | /* | 276 | /* |
280 | * Invalid Command error reporring | 277 | * Invalid Command error reporring |
281 | * | 278 | * |
282 | * command CMD_DATA needs three strings on a line | 279 | * command CMD_DATA needs three strings on a line |
283 | * whereas other commands need only two. | 280 | * whereas other commands need only two. |
284 | * | 281 | * |
285 | * if more than two/three (as per command type) are observed, | 282 | * if more than two/three (as per command type) are observed, |
286 | * then error will be reported | 283 | * then error will be reported |
287 | */ | 284 | */ |
288 | INVL_CMD: | 285 | INVL_CMD: |
289 | printf ("Error:%s[%d] - Invalid command\n", fname, lineno); | 286 | printf ("Error:%s[%d] - Invalid command\n", fname, lineno); |
290 | exit (EXIT_FAILURE); | 287 | exit (EXIT_FAILURE); |
291 | } | 288 | } |
292 | 289 | ||
293 | static void kwbimage_set_header (void *ptr, struct stat *sbuf, int ifd, | 290 | static void kwbimage_set_header (void *ptr, struct stat *sbuf, int ifd, |
294 | struct mkimage_params *params) | 291 | struct mkimage_params *params) |
295 | { | 292 | { |
296 | struct kwb_header *hdr = (struct kwb_header *)ptr; | 293 | struct kwb_header *hdr = (struct kwb_header *)ptr; |
297 | bhr_t *mhdr = &hdr->kwb_hdr; | 294 | bhr_t *mhdr = &hdr->kwb_hdr; |
298 | extbhr_t *exthdr = &hdr->kwb_exthdr; | 295 | extbhr_t *exthdr = &hdr->kwb_exthdr; |
299 | uint32_t checksum; | 296 | uint32_t checksum; |
300 | int size; | 297 | int size; |
301 | 298 | ||
302 | /* Build and add image checksum header */ | 299 | /* Build and add image checksum header */ |
303 | checksum = kwbimage_checksum32 ((uint32_t *)ptr, sbuf->st_size, 0); | 300 | checksum = kwbimage_checksum32 ((uint32_t *)ptr, sbuf->st_size, 0); |
304 | 301 | ||
305 | size = write (ifd, &checksum, sizeof(uint32_t)); | 302 | size = write (ifd, &checksum, sizeof(uint32_t)); |
306 | if (size != sizeof(uint32_t)) { | 303 | if (size != sizeof(uint32_t)) { |
307 | printf ("Error:%s - Checksum write %d bytes %s\n", | 304 | printf ("Error:%s - Checksum write %d bytes %s\n", |
308 | params->cmdname, size, params->imagefile); | 305 | params->cmdname, size, params->imagefile); |
309 | exit (EXIT_FAILURE); | 306 | exit (EXIT_FAILURE); |
310 | } | 307 | } |
311 | 308 | ||
312 | sbuf->st_size += sizeof(uint32_t); | 309 | sbuf->st_size += sizeof(uint32_t); |
313 | 310 | ||
314 | mhdr->blocksize = sbuf->st_size - sizeof(struct kwb_header); | 311 | mhdr->blocksize = sbuf->st_size - sizeof(struct kwb_header); |
315 | mhdr->srcaddr = sizeof(struct kwb_header); | 312 | mhdr->srcaddr = sizeof(struct kwb_header); |
316 | mhdr->destaddr= params->addr; | 313 | mhdr->destaddr= params->addr; |
317 | mhdr->execaddr =params->ep; | 314 | mhdr->execaddr =params->ep; |
318 | mhdr->ext = 0x1; /* header extension appended */ | 315 | mhdr->ext = 0x1; /* header extension appended */ |
319 | 316 | ||
320 | kwdimage_set_ext_header (hdr, params->imagename); | 317 | kwdimage_set_ext_header (hdr, params->imagename); |
321 | /* calculate checksums */ | 318 | /* calculate checksums */ |
322 | mhdr->checkSum = kwbimage_checksum8 ((void *)mhdr, sizeof(bhr_t), 0); | 319 | mhdr->checkSum = kwbimage_checksum8 ((void *)mhdr, sizeof(bhr_t), 0); |
323 | exthdr->checkSum = kwbimage_checksum8 ((void *)exthdr, | 320 | exthdr->checkSum = kwbimage_checksum8 ((void *)exthdr, |
324 | sizeof(extbhr_t), 0); | 321 | sizeof(extbhr_t), 0); |
325 | } | 322 | } |
326 | 323 | ||
327 | static int kwbimage_verify_header (unsigned char *ptr, int image_size, | 324 | static int kwbimage_verify_header (unsigned char *ptr, int image_size, |
328 | struct mkimage_params *params) | 325 | struct mkimage_params *params) |
329 | { | 326 | { |
330 | struct kwb_header *hdr = (struct kwb_header *)ptr; | 327 | struct kwb_header *hdr = (struct kwb_header *)ptr; |
331 | bhr_t *mhdr = &hdr->kwb_hdr; | 328 | bhr_t *mhdr = &hdr->kwb_hdr; |
332 | extbhr_t *exthdr = &hdr->kwb_exthdr; | 329 | extbhr_t *exthdr = &hdr->kwb_exthdr; |
333 | uint8_t calc_hdrcsum; | 330 | uint8_t calc_hdrcsum; |
334 | uint8_t calc_exthdrcsum; | 331 | uint8_t calc_exthdrcsum; |
335 | 332 | ||
336 | calc_hdrcsum = kwbimage_checksum8 ((void *)mhdr, | 333 | calc_hdrcsum = kwbimage_checksum8 ((void *)mhdr, |
337 | sizeof(bhr_t) - sizeof(uint8_t), 0); | 334 | sizeof(bhr_t) - sizeof(uint8_t), 0); |
338 | if (calc_hdrcsum != mhdr->checkSum) | 335 | if (calc_hdrcsum != mhdr->checkSum) |
339 | return -FDT_ERR_BADSTRUCTURE; /* mhdr csum not matched */ | 336 | return -FDT_ERR_BADSTRUCTURE; /* mhdr csum not matched */ |
340 | 337 | ||
341 | calc_exthdrcsum = kwbimage_checksum8 ((void *)exthdr, | 338 | calc_exthdrcsum = kwbimage_checksum8 ((void *)exthdr, |
342 | sizeof(extbhr_t) - sizeof(uint8_t), 0); | 339 | sizeof(extbhr_t) - sizeof(uint8_t), 0); |
343 | if (calc_exthdrcsum != exthdr->checkSum) | 340 | if (calc_exthdrcsum != exthdr->checkSum) |
344 | return -FDT_ERR_BADSTRUCTURE; /* exthdr csum not matched */ | 341 | return -FDT_ERR_BADSTRUCTURE; /* exthdr csum not matched */ |
345 | 342 | ||
346 | return 0; | 343 | return 0; |
347 | } | 344 | } |
348 | 345 | ||
349 | static void kwbimage_print_header (const void *ptr) | 346 | static void kwbimage_print_header (const void *ptr) |
350 | { | 347 | { |
351 | struct kwb_header *hdr = (struct kwb_header *) ptr; | 348 | struct kwb_header *hdr = (struct kwb_header *) ptr; |
352 | bhr_t *mhdr = &hdr->kwb_hdr; | 349 | bhr_t *mhdr = &hdr->kwb_hdr; |
353 | char *name = get_table_entry_name (kwbimage_bootops, | 350 | char *name = get_table_entry_name (kwbimage_bootops, |
354 | "Kwbimage boot option", | 351 | "Kwbimage boot option", |
355 | (int) mhdr->blockid); | 352 | (int) mhdr->blockid); |
356 | 353 | ||
357 | printf ("Image Type: Kirkwood Boot from %s Image\n", name); | 354 | printf ("Image Type: Kirkwood Boot from %s Image\n", name); |
358 | printf ("Data Size: "); | 355 | printf ("Data Size: "); |
359 | genimg_print_size (mhdr->blocksize - sizeof(uint32_t)); | 356 | genimg_print_size (mhdr->blocksize - sizeof(uint32_t)); |
360 | printf ("Load Address: %08x\n", mhdr->destaddr); | 357 | printf ("Load Address: %08x\n", mhdr->destaddr); |
361 | printf ("Entry Point: %08x\n", mhdr->execaddr); | 358 | printf ("Entry Point: %08x\n", mhdr->execaddr); |
362 | } | 359 | } |
363 | 360 | ||
364 | static int kwbimage_check_image_types (uint8_t type) | 361 | static int kwbimage_check_image_types (uint8_t type) |
365 | { | 362 | { |
366 | if (type == IH_TYPE_KWBIMAGE) | 363 | if (type == IH_TYPE_KWBIMAGE) |
367 | return EXIT_SUCCESS; | 364 | return EXIT_SUCCESS; |
368 | else | 365 | else |
369 | return EXIT_FAILURE; | 366 | return EXIT_FAILURE; |
370 | } | 367 | } |
371 | 368 | ||
372 | /* | 369 | /* |
373 | * kwbimage type parameters definition | 370 | * kwbimage type parameters definition |
374 | */ | 371 | */ |
375 | static struct image_type_params kwbimage_params = { | 372 | static struct image_type_params kwbimage_params = { |
376 | .name = "Kirkwood Boot Image support", | 373 | .name = "Kirkwood Boot Image support", |
377 | .header_size = sizeof(struct kwb_header), | 374 | .header_size = sizeof(struct kwb_header), |
378 | .hdr = (void*)&kwbimage_header, | 375 | .hdr = (void*)&kwbimage_header, |
379 | .check_image_type = kwbimage_check_image_types, | 376 | .check_image_type = kwbimage_check_image_types, |
380 | .verify_header = kwbimage_verify_header, | 377 | .verify_header = kwbimage_verify_header, |
381 | .print_header = kwbimage_print_header, | 378 | .print_header = kwbimage_print_header, |
382 | .set_header = kwbimage_set_header, | 379 | .set_header = kwbimage_set_header, |
383 | .check_params = kwbimage_check_params, | 380 | .check_params = kwbimage_check_params, |
384 | }; | 381 | }; |
385 | 382 | ||
386 | void init_kwb_image_type (void) | 383 | void init_kwb_image_type (void) |
387 | { | 384 | { |
388 | mkimage_register (&kwbimage_params); | 385 | mkimage_register (&kwbimage_params); |
389 | } | 386 | } |
390 | 387 |
tools/mkenvimage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 Free Electrons | 2 | * (C) Copyright 2011 Free Electrons |
3 | * David Wagner <david.wagner@free-electrons.com> | 3 | * David Wagner <david.wagner@free-electrons.com> |
4 | * | 4 | * |
5 | * Inspired from envcrc.c: | 5 | * Inspired from envcrc.c: |
6 | * (C) Copyright 2001 | 6 | * (C) Copyright 2001 |
7 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it | 7 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it |
8 | * | 8 | * |
9 | * SPDX-License-Identifier: GPL-2.0+ | 9 | * SPDX-License-Identifier: GPL-2.0+ |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* We want the GNU version of basename() */ | ||
13 | #define _GNU_SOURCE | ||
14 | |||
15 | #include <errno.h> | 12 | #include <errno.h> |
16 | #include <fcntl.h> | 13 | #include <fcntl.h> |
17 | #include <stdio.h> | 14 | #include <stdio.h> |
18 | #include <stdlib.h> | 15 | #include <stdlib.h> |
19 | #include <stdint.h> | 16 | #include <stdint.h> |
20 | #include <string.h> | 17 | #include <string.h> |
21 | #include <unistd.h> | 18 | #include <unistd.h> |
22 | #include <libgen.h> | 19 | #include <libgen.h> |
23 | #include <sys/types.h> | 20 | #include <sys/types.h> |
24 | #include <sys/stat.h> | 21 | #include <sys/stat.h> |
25 | #include <sys/mman.h> | 22 | #include <sys/mman.h> |
26 | 23 | ||
27 | #include "compiler.h" | 24 | #include "compiler.h" |
28 | #include <u-boot/crc.h> | 25 | #include <u-boot/crc.h> |
29 | #include <version.h> | 26 | #include <version.h> |
30 | 27 | ||
31 | #define CRC_SIZE sizeof(uint32_t) | 28 | #define CRC_SIZE sizeof(uint32_t) |
32 | 29 | ||
33 | static void usage(const char *exec_name) | 30 | static void usage(const char *exec_name) |
34 | { | 31 | { |
35 | fprintf(stderr, "%s [-h] [-r] [-b] [-p <byte>] -s <environment partition size> -o <output> <input file>\n" | 32 | fprintf(stderr, "%s [-h] [-r] [-b] [-p <byte>] -s <environment partition size> -o <output> <input file>\n" |
36 | "\n" | 33 | "\n" |
37 | "This tool takes a key=value input file (same as would a `printenv' show) and generates the corresponding environment image, ready to be flashed.\n" | 34 | "This tool takes a key=value input file (same as would a `printenv' show) and generates the corresponding environment image, ready to be flashed.\n" |
38 | "\n" | 35 | "\n" |
39 | "\tThe input file is in format:\n" | 36 | "\tThe input file is in format:\n" |
40 | "\t\tkey1=value1\n" | 37 | "\t\tkey1=value1\n" |
41 | "\t\tkey2=value2\n" | 38 | "\t\tkey2=value2\n" |
42 | "\t\t...\n" | 39 | "\t\t...\n" |
43 | "\t-r : the environment has multiple copies in flash\n" | 40 | "\t-r : the environment has multiple copies in flash\n" |
44 | "\t-b : the target is big endian (default is little endian)\n" | 41 | "\t-b : the target is big endian (default is little endian)\n" |
45 | "\t-p <byte> : fill the image with <byte> bytes instead of 0xff bytes\n" | 42 | "\t-p <byte> : fill the image with <byte> bytes instead of 0xff bytes\n" |
46 | "\t-V : print version information and exit\n" | 43 | "\t-V : print version information and exit\n" |
47 | "\n" | 44 | "\n" |
48 | "If the input file is \"-\", data is read from standard input\n", | 45 | "If the input file is \"-\", data is read from standard input\n", |
49 | exec_name); | 46 | exec_name); |
50 | } | 47 | } |
51 | 48 | ||
52 | long int xstrtol(const char *s) | 49 | long int xstrtol(const char *s) |
53 | { | 50 | { |
54 | long int tmp; | 51 | long int tmp; |
55 | 52 | ||
56 | errno = 0; | 53 | errno = 0; |
57 | tmp = strtol(s, NULL, 0); | 54 | tmp = strtol(s, NULL, 0); |
58 | if (!errno) | 55 | if (!errno) |
59 | return tmp; | 56 | return tmp; |
60 | 57 | ||
61 | if (errno == ERANGE) | 58 | if (errno == ERANGE) |
62 | fprintf(stderr, "Bad integer format: %s\n", s); | 59 | fprintf(stderr, "Bad integer format: %s\n", s); |
63 | else | 60 | else |
64 | fprintf(stderr, "Error while parsing %s: %s\n", s, | 61 | fprintf(stderr, "Error while parsing %s: %s\n", s, |
65 | strerror(errno)); | 62 | strerror(errno)); |
66 | 63 | ||
67 | exit(EXIT_FAILURE); | 64 | exit(EXIT_FAILURE); |
68 | } | 65 | } |
69 | 66 | ||
70 | int main(int argc, char **argv) | 67 | int main(int argc, char **argv) |
71 | { | 68 | { |
72 | uint32_t crc, targetendian_crc; | 69 | uint32_t crc, targetendian_crc; |
73 | const char *txt_filename = NULL, *bin_filename = NULL; | 70 | const char *txt_filename = NULL, *bin_filename = NULL; |
74 | int txt_fd, bin_fd; | 71 | int txt_fd, bin_fd; |
75 | unsigned char *dataptr, *envptr; | 72 | unsigned char *dataptr, *envptr; |
76 | unsigned char *filebuf = NULL; | 73 | unsigned char *filebuf = NULL; |
77 | unsigned int filesize = 0, envsize = 0, datasize = 0; | 74 | unsigned int filesize = 0, envsize = 0, datasize = 0; |
78 | int bigendian = 0; | 75 | int bigendian = 0; |
79 | int redundant = 0; | 76 | int redundant = 0; |
80 | unsigned char padbyte = 0xff; | 77 | unsigned char padbyte = 0xff; |
81 | 78 | ||
82 | int option; | 79 | int option; |
83 | int ret = EXIT_SUCCESS; | 80 | int ret = EXIT_SUCCESS; |
84 | 81 | ||
85 | struct stat txt_file_stat; | 82 | struct stat txt_file_stat; |
86 | 83 | ||
87 | int fp, ep; | 84 | int fp, ep; |
88 | const char *prg; | 85 | const char *prg; |
89 | 86 | ||
90 | prg = basename(argv[0]); | 87 | prg = basename(argv[0]); |
91 | 88 | ||
92 | /* Turn off getopt()'s internal error message */ | 89 | /* Turn off getopt()'s internal error message */ |
93 | opterr = 0; | 90 | opterr = 0; |
94 | 91 | ||
95 | /* Parse the cmdline */ | 92 | /* Parse the cmdline */ |
96 | while ((option = getopt(argc, argv, ":s:o:rbp:hV")) != -1) { | 93 | while ((option = getopt(argc, argv, ":s:o:rbp:hV")) != -1) { |
97 | switch (option) { | 94 | switch (option) { |
98 | case 's': | 95 | case 's': |
99 | datasize = xstrtol(optarg); | 96 | datasize = xstrtol(optarg); |
100 | break; | 97 | break; |
101 | case 'o': | 98 | case 'o': |
102 | bin_filename = strdup(optarg); | 99 | bin_filename = strdup(optarg); |
103 | if (!bin_filename) { | 100 | if (!bin_filename) { |
104 | fprintf(stderr, "Can't strdup() the output filename\n"); | 101 | fprintf(stderr, "Can't strdup() the output filename\n"); |
105 | return EXIT_FAILURE; | 102 | return EXIT_FAILURE; |
106 | } | 103 | } |
107 | break; | 104 | break; |
108 | case 'r': | 105 | case 'r': |
109 | redundant = 1; | 106 | redundant = 1; |
110 | break; | 107 | break; |
111 | case 'b': | 108 | case 'b': |
112 | bigendian = 1; | 109 | bigendian = 1; |
113 | break; | 110 | break; |
114 | case 'p': | 111 | case 'p': |
115 | padbyte = xstrtol(optarg); | 112 | padbyte = xstrtol(optarg); |
116 | break; | 113 | break; |
117 | case 'h': | 114 | case 'h': |
118 | usage(prg); | 115 | usage(prg); |
119 | return EXIT_SUCCESS; | 116 | return EXIT_SUCCESS; |
120 | case 'V': | 117 | case 'V': |
121 | printf("%s version %s\n", prg, PLAIN_VERSION); | 118 | printf("%s version %s\n", prg, PLAIN_VERSION); |
122 | return EXIT_SUCCESS; | 119 | return EXIT_SUCCESS; |
123 | case ':': | 120 | case ':': |
124 | fprintf(stderr, "Missing argument for option -%c\n", | 121 | fprintf(stderr, "Missing argument for option -%c\n", |
125 | optopt); | 122 | optopt); |
126 | usage(prg); | 123 | usage(prg); |
127 | return EXIT_FAILURE; | 124 | return EXIT_FAILURE; |
128 | default: | 125 | default: |
129 | fprintf(stderr, "Wrong option -%c\n", optopt); | 126 | fprintf(stderr, "Wrong option -%c\n", optopt); |
130 | usage(prg); | 127 | usage(prg); |
131 | return EXIT_FAILURE; | 128 | return EXIT_FAILURE; |
132 | } | 129 | } |
133 | } | 130 | } |
134 | 131 | ||
135 | /* Check datasize and allocate the data */ | 132 | /* Check datasize and allocate the data */ |
136 | if (datasize == 0) { | 133 | if (datasize == 0) { |
137 | fprintf(stderr, "Please specify the size of the environment partition.\n"); | 134 | fprintf(stderr, "Please specify the size of the environment partition.\n"); |
138 | usage(prg); | 135 | usage(prg); |
139 | return EXIT_FAILURE; | 136 | return EXIT_FAILURE; |
140 | } | 137 | } |
141 | 138 | ||
142 | dataptr = malloc(datasize * sizeof(*dataptr)); | 139 | dataptr = malloc(datasize * sizeof(*dataptr)); |
143 | if (!dataptr) { | 140 | if (!dataptr) { |
144 | fprintf(stderr, "Can't alloc %d bytes for dataptr.\n", | 141 | fprintf(stderr, "Can't alloc %d bytes for dataptr.\n", |
145 | datasize); | 142 | datasize); |
146 | return EXIT_FAILURE; | 143 | return EXIT_FAILURE; |
147 | } | 144 | } |
148 | 145 | ||
149 | /* | 146 | /* |
150 | * envptr points to the beginning of the actual environment (after the | 147 | * envptr points to the beginning of the actual environment (after the |
151 | * crc and possible `redundant' byte | 148 | * crc and possible `redundant' byte |
152 | */ | 149 | */ |
153 | envsize = datasize - (CRC_SIZE + redundant); | 150 | envsize = datasize - (CRC_SIZE + redundant); |
154 | envptr = dataptr + CRC_SIZE + redundant; | 151 | envptr = dataptr + CRC_SIZE + redundant; |
155 | 152 | ||
156 | /* Pad the environment with the padding byte */ | 153 | /* Pad the environment with the padding byte */ |
157 | memset(envptr, padbyte, envsize); | 154 | memset(envptr, padbyte, envsize); |
158 | 155 | ||
159 | /* Open the input file ... */ | 156 | /* Open the input file ... */ |
160 | if (optind >= argc || strcmp(argv[optind], "-") == 0) { | 157 | if (optind >= argc || strcmp(argv[optind], "-") == 0) { |
161 | int readbytes = 0; | 158 | int readbytes = 0; |
162 | int readlen = sizeof(*envptr) * 4096; | 159 | int readlen = sizeof(*envptr) * 4096; |
163 | txt_fd = STDIN_FILENO; | 160 | txt_fd = STDIN_FILENO; |
164 | 161 | ||
165 | do { | 162 | do { |
166 | filebuf = realloc(filebuf, readlen); | 163 | filebuf = realloc(filebuf, readlen); |
167 | if (!filebuf) { | 164 | if (!filebuf) { |
168 | fprintf(stderr, "Can't realloc memory for the input file buffer\n"); | 165 | fprintf(stderr, "Can't realloc memory for the input file buffer\n"); |
169 | return EXIT_FAILURE; | 166 | return EXIT_FAILURE; |
170 | } | 167 | } |
171 | readbytes = read(txt_fd, filebuf + filesize, readlen); | 168 | readbytes = read(txt_fd, filebuf + filesize, readlen); |
172 | if (errno) { | 169 | if (errno) { |
173 | fprintf(stderr, "Error while reading stdin: %s\n", | 170 | fprintf(stderr, "Error while reading stdin: %s\n", |
174 | strerror(errno)); | 171 | strerror(errno)); |
175 | return EXIT_FAILURE; | 172 | return EXIT_FAILURE; |
176 | } | 173 | } |
177 | filesize += readbytes; | 174 | filesize += readbytes; |
178 | } while (readbytes == readlen); | 175 | } while (readbytes == readlen); |
179 | 176 | ||
180 | } else { | 177 | } else { |
181 | txt_filename = argv[optind]; | 178 | txt_filename = argv[optind]; |
182 | txt_fd = open(txt_filename, O_RDONLY); | 179 | txt_fd = open(txt_filename, O_RDONLY); |
183 | if (txt_fd == -1) { | 180 | if (txt_fd == -1) { |
184 | fprintf(stderr, "Can't open \"%s\": %s\n", | 181 | fprintf(stderr, "Can't open \"%s\": %s\n", |
185 | txt_filename, strerror(errno)); | 182 | txt_filename, strerror(errno)); |
186 | return EXIT_FAILURE; | 183 | return EXIT_FAILURE; |
187 | } | 184 | } |
188 | /* ... and check it */ | 185 | /* ... and check it */ |
189 | ret = fstat(txt_fd, &txt_file_stat); | 186 | ret = fstat(txt_fd, &txt_file_stat); |
190 | if (ret == -1) { | 187 | if (ret == -1) { |
191 | fprintf(stderr, "Can't stat() on \"%s\": %s\n", | 188 | fprintf(stderr, "Can't stat() on \"%s\": %s\n", |
192 | txt_filename, strerror(errno)); | 189 | txt_filename, strerror(errno)); |
193 | return EXIT_FAILURE; | 190 | return EXIT_FAILURE; |
194 | } | 191 | } |
195 | 192 | ||
196 | filesize = txt_file_stat.st_size; | 193 | filesize = txt_file_stat.st_size; |
197 | 194 | ||
198 | filebuf = mmap(NULL, sizeof(*envptr) * filesize, PROT_READ, | 195 | filebuf = mmap(NULL, sizeof(*envptr) * filesize, PROT_READ, |
199 | MAP_PRIVATE, txt_fd, 0); | 196 | MAP_PRIVATE, txt_fd, 0); |
200 | if (filebuf == MAP_FAILED) { | 197 | if (filebuf == MAP_FAILED) { |
201 | fprintf(stderr, "mmap (%zu bytes) failed: %s\n", | 198 | fprintf(stderr, "mmap (%zu bytes) failed: %s\n", |
202 | sizeof(*envptr) * filesize, | 199 | sizeof(*envptr) * filesize, |
203 | strerror(errno)); | 200 | strerror(errno)); |
204 | fprintf(stderr, "Falling back to read()\n"); | 201 | fprintf(stderr, "Falling back to read()\n"); |
205 | 202 | ||
206 | filebuf = malloc(sizeof(*envptr) * filesize); | 203 | filebuf = malloc(sizeof(*envptr) * filesize); |
207 | ret = read(txt_fd, filebuf, sizeof(*envptr) * filesize); | 204 | ret = read(txt_fd, filebuf, sizeof(*envptr) * filesize); |
208 | if (ret != sizeof(*envptr) * filesize) { | 205 | if (ret != sizeof(*envptr) * filesize) { |
209 | fprintf(stderr, "Can't read the whole input file (%zu bytes): %s\n", | 206 | fprintf(stderr, "Can't read the whole input file (%zu bytes): %s\n", |
210 | sizeof(*envptr) * filesize, | 207 | sizeof(*envptr) * filesize, |
211 | strerror(errno)); | 208 | strerror(errno)); |
212 | 209 | ||
213 | return EXIT_FAILURE; | 210 | return EXIT_FAILURE; |
214 | } | 211 | } |
215 | } | 212 | } |
216 | ret = close(txt_fd); | 213 | ret = close(txt_fd); |
217 | } | 214 | } |
218 | /* The +1 is for the additionnal ending \0. See below. */ | 215 | /* The +1 is for the additionnal ending \0. See below. */ |
219 | if (filesize + 1 > envsize) { | 216 | if (filesize + 1 > envsize) { |
220 | fprintf(stderr, "The input file is larger than the environment partition size\n"); | 217 | fprintf(stderr, "The input file is larger than the environment partition size\n"); |
221 | return EXIT_FAILURE; | 218 | return EXIT_FAILURE; |
222 | } | 219 | } |
223 | 220 | ||
224 | /* Replace newlines separating variables with \0 */ | 221 | /* Replace newlines separating variables with \0 */ |
225 | for (fp = 0, ep = 0 ; fp < filesize ; fp++) { | 222 | for (fp = 0, ep = 0 ; fp < filesize ; fp++) { |
226 | if (filebuf[fp] == '\n') { | 223 | if (filebuf[fp] == '\n') { |
227 | if (ep == 0) { | 224 | if (ep == 0) { |
228 | /* | 225 | /* |
229 | * Newlines at the beginning of the file ? | 226 | * Newlines at the beginning of the file ? |
230 | * Ignore them. | 227 | * Ignore them. |
231 | */ | 228 | */ |
232 | continue; | 229 | continue; |
233 | } else if (filebuf[fp-1] == '\\') { | 230 | } else if (filebuf[fp-1] == '\\') { |
234 | /* | 231 | /* |
235 | * Embedded newline in a variable. | 232 | * Embedded newline in a variable. |
236 | * | 233 | * |
237 | * The backslash was added to the envptr; rewind | 234 | * The backslash was added to the envptr; rewind |
238 | * and replace it with a newline | 235 | * and replace it with a newline |
239 | */ | 236 | */ |
240 | ep--; | 237 | ep--; |
241 | envptr[ep++] = '\n'; | 238 | envptr[ep++] = '\n'; |
242 | } else { | 239 | } else { |
243 | /* End of a variable */ | 240 | /* End of a variable */ |
244 | envptr[ep++] = '\0'; | 241 | envptr[ep++] = '\0'; |
245 | } | 242 | } |
246 | } else { | 243 | } else { |
247 | envptr[ep++] = filebuf[fp]; | 244 | envptr[ep++] = filebuf[fp]; |
248 | } | 245 | } |
249 | } | 246 | } |
250 | /* | 247 | /* |
251 | * Make sure there is a final '\0' | 248 | * Make sure there is a final '\0' |
252 | * And do it again on the next byte to mark the end of the environment. | 249 | * And do it again on the next byte to mark the end of the environment. |
253 | */ | 250 | */ |
254 | if (envptr[ep-1] != '\0') { | 251 | if (envptr[ep-1] != '\0') { |
255 | envptr[ep++] = '\0'; | 252 | envptr[ep++] = '\0'; |
256 | /* | 253 | /* |
257 | * The text file doesn't have an ending newline. We need to | 254 | * The text file doesn't have an ending newline. We need to |
258 | * check the env size again to make sure we have room for two \0 | 255 | * check the env size again to make sure we have room for two \0 |
259 | */ | 256 | */ |
260 | if (ep >= envsize) { | 257 | if (ep >= envsize) { |
261 | fprintf(stderr, "The environment file is too large for the target environment storage\n"); | 258 | fprintf(stderr, "The environment file is too large for the target environment storage\n"); |
262 | return EXIT_FAILURE; | 259 | return EXIT_FAILURE; |
263 | } | 260 | } |
264 | envptr[ep] = '\0'; | 261 | envptr[ep] = '\0'; |
265 | } else { | 262 | } else { |
266 | envptr[ep] = '\0'; | 263 | envptr[ep] = '\0'; |
267 | } | 264 | } |
268 | 265 | ||
269 | /* Computes the CRC and put it at the beginning of the data */ | 266 | /* Computes the CRC and put it at the beginning of the data */ |
270 | crc = crc32(0, envptr, envsize); | 267 | crc = crc32(0, envptr, envsize); |
271 | targetendian_crc = bigendian ? cpu_to_be32(crc) : cpu_to_le32(crc); | 268 | targetendian_crc = bigendian ? cpu_to_be32(crc) : cpu_to_le32(crc); |
272 | 269 | ||
273 | memcpy(dataptr, &targetendian_crc, sizeof(targetendian_crc)); | 270 | memcpy(dataptr, &targetendian_crc, sizeof(targetendian_crc)); |
274 | if (redundant) | 271 | if (redundant) |
275 | dataptr[sizeof(targetendian_crc)] = 1; | 272 | dataptr[sizeof(targetendian_crc)] = 1; |
276 | 273 | ||
277 | if (!bin_filename || strcmp(bin_filename, "-") == 0) { | 274 | if (!bin_filename || strcmp(bin_filename, "-") == 0) { |
278 | bin_fd = STDOUT_FILENO; | 275 | bin_fd = STDOUT_FILENO; |
279 | } else { | 276 | } else { |
280 | bin_fd = creat(bin_filename, S_IRUSR | S_IWUSR | S_IRGRP | | 277 | bin_fd = creat(bin_filename, S_IRUSR | S_IWUSR | S_IRGRP | |
281 | S_IWGRP); | 278 | S_IWGRP); |
282 | if (bin_fd == -1) { | 279 | if (bin_fd == -1) { |
283 | fprintf(stderr, "Can't open output file \"%s\": %s\n", | 280 | fprintf(stderr, "Can't open output file \"%s\": %s\n", |
284 | bin_filename, strerror(errno)); | 281 | bin_filename, strerror(errno)); |
285 | return EXIT_FAILURE; | 282 | return EXIT_FAILURE; |
286 | } | 283 | } |
287 | } | 284 | } |
288 | 285 | ||
289 | if (write(bin_fd, dataptr, sizeof(*dataptr) * datasize) != | 286 | if (write(bin_fd, dataptr, sizeof(*dataptr) * datasize) != |
290 | sizeof(*dataptr) * datasize) { | 287 | sizeof(*dataptr) * datasize) { |
291 | fprintf(stderr, "write() failed: %s\n", strerror(errno)); | 288 | fprintf(stderr, "write() failed: %s\n", strerror(errno)); |
292 | return EXIT_FAILURE; | 289 | return EXIT_FAILURE; |
293 | } | 290 | } |
294 | 291 | ||
295 | ret = close(bin_fd); | 292 | ret = close(bin_fd); |
296 | 293 | ||
297 | return ret; | 294 | return ret; |
298 | } | 295 | } |
299 | 296 |
tools/omapimage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2010 | 2 | * (C) Copyright 2010 |
3 | * Linaro LTD, www.linaro.org | 3 | * Linaro LTD, www.linaro.org |
4 | * Author: John Rigby <john.rigby@linaro.org> | 4 | * Author: John Rigby <john.rigby@linaro.org> |
5 | * Based on TI's signGP.c | 5 | * Based on TI's signGP.c |
6 | * | 6 | * |
7 | * (C) Copyright 2009 | 7 | * (C) Copyright 2009 |
8 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. | 8 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. |
9 | * | 9 | * |
10 | * (C) Copyright 2008 | 10 | * (C) Copyright 2008 |
11 | * Marvell Semiconductor <www.marvell.com> | 11 | * Marvell Semiconductor <www.marvell.com> |
12 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> | 12 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> |
13 | * | 13 | * |
14 | * SPDX-License-Identifier: GPL-2.0+ | 14 | * SPDX-License-Identifier: GPL-2.0+ |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* Required to obtain the getline prototype from stdio.h */ | ||
18 | #define _GNU_SOURCE | ||
19 | |||
20 | #include "mkimage.h" | 17 | #include "mkimage.h" |
21 | #include <image.h> | 18 | #include <image.h> |
22 | #include "omapimage.h" | 19 | #include "omapimage.h" |
23 | 20 | ||
24 | /* Header size is CH header rounded up to 512 bytes plus GP header */ | 21 | /* Header size is CH header rounded up to 512 bytes plus GP header */ |
25 | #define OMAP_CH_HDR_SIZE 512 | 22 | #define OMAP_CH_HDR_SIZE 512 |
26 | #define OMAP_GP_HDR_SIZE (sizeof(struct gp_header)) | 23 | #define OMAP_GP_HDR_SIZE (sizeof(struct gp_header)) |
27 | #define OMAP_FILE_HDR_SIZE (OMAP_CH_HDR_SIZE+OMAP_GP_HDR_SIZE) | 24 | #define OMAP_FILE_HDR_SIZE (OMAP_CH_HDR_SIZE+OMAP_GP_HDR_SIZE) |
28 | 25 | ||
29 | static int do_swap32 = 0; | 26 | static int do_swap32 = 0; |
30 | 27 | ||
31 | static uint32_t omapimage_swap32(uint32_t data) | 28 | static uint32_t omapimage_swap32(uint32_t data) |
32 | { | 29 | { |
33 | uint32_t result = 0; | 30 | uint32_t result = 0; |
34 | result = (data & 0xFF000000) >> 24; | 31 | result = (data & 0xFF000000) >> 24; |
35 | result |= (data & 0x00FF0000) >> 8; | 32 | result |= (data & 0x00FF0000) >> 8; |
36 | result |= (data & 0x0000FF00) << 8; | 33 | result |= (data & 0x0000FF00) << 8; |
37 | result |= (data & 0x000000FF) << 24; | 34 | result |= (data & 0x000000FF) << 24; |
38 | return result; | 35 | return result; |
39 | } | 36 | } |
40 | 37 | ||
41 | static uint8_t omapimage_header[OMAP_FILE_HDR_SIZE]; | 38 | static uint8_t omapimage_header[OMAP_FILE_HDR_SIZE]; |
42 | 39 | ||
43 | static int omapimage_check_image_types(uint8_t type) | 40 | static int omapimage_check_image_types(uint8_t type) |
44 | { | 41 | { |
45 | if (type == IH_TYPE_OMAPIMAGE) | 42 | if (type == IH_TYPE_OMAPIMAGE) |
46 | return EXIT_SUCCESS; | 43 | return EXIT_SUCCESS; |
47 | else { | 44 | else { |
48 | return EXIT_FAILURE; | 45 | return EXIT_FAILURE; |
49 | } | 46 | } |
50 | } | 47 | } |
51 | 48 | ||
52 | /* | 49 | /* |
53 | * Only the simplest image type is currently supported: | 50 | * Only the simplest image type is currently supported: |
54 | * TOC pointing to CHSETTINGS | 51 | * TOC pointing to CHSETTINGS |
55 | * TOC terminator | 52 | * TOC terminator |
56 | * CHSETTINGS | 53 | * CHSETTINGS |
57 | * | 54 | * |
58 | * padding to OMAP_CH_HDR_SIZE bytes | 55 | * padding to OMAP_CH_HDR_SIZE bytes |
59 | * | 56 | * |
60 | * gp header | 57 | * gp header |
61 | * size | 58 | * size |
62 | * load_addr | 59 | * load_addr |
63 | */ | 60 | */ |
64 | static int valid_gph_size(uint32_t size) | 61 | static int valid_gph_size(uint32_t size) |
65 | { | 62 | { |
66 | return size; | 63 | return size; |
67 | } | 64 | } |
68 | 65 | ||
69 | static int valid_gph_load_addr(uint32_t load_addr) | 66 | static int valid_gph_load_addr(uint32_t load_addr) |
70 | { | 67 | { |
71 | return load_addr; | 68 | return load_addr; |
72 | } | 69 | } |
73 | 70 | ||
74 | static int omapimage_verify_header(unsigned char *ptr, int image_size, | 71 | static int omapimage_verify_header(unsigned char *ptr, int image_size, |
75 | struct mkimage_params *params) | 72 | struct mkimage_params *params) |
76 | { | 73 | { |
77 | struct ch_toc *toc = (struct ch_toc *)ptr; | 74 | struct ch_toc *toc = (struct ch_toc *)ptr; |
78 | struct gp_header *gph = (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); | 75 | struct gp_header *gph = (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); |
79 | uint32_t offset, size, gph_size, gph_load_addr; | 76 | uint32_t offset, size, gph_size, gph_load_addr; |
80 | 77 | ||
81 | while (toc->section_offset != 0xffffffff | 78 | while (toc->section_offset != 0xffffffff |
82 | && toc->section_size != 0xffffffff) { | 79 | && toc->section_size != 0xffffffff) { |
83 | if (do_swap32) { | 80 | if (do_swap32) { |
84 | offset = omapimage_swap32(toc->section_offset); | 81 | offset = omapimage_swap32(toc->section_offset); |
85 | size = omapimage_swap32(toc->section_size); | 82 | size = omapimage_swap32(toc->section_size); |
86 | } else { | 83 | } else { |
87 | offset = toc->section_offset; | 84 | offset = toc->section_offset; |
88 | size = toc->section_size; | 85 | size = toc->section_size; |
89 | } | 86 | } |
90 | if (!offset || !size) | 87 | if (!offset || !size) |
91 | return -1; | 88 | return -1; |
92 | if (offset >= OMAP_CH_HDR_SIZE || | 89 | if (offset >= OMAP_CH_HDR_SIZE || |
93 | offset+size >= OMAP_CH_HDR_SIZE) | 90 | offset+size >= OMAP_CH_HDR_SIZE) |
94 | return -1; | 91 | return -1; |
95 | toc++; | 92 | toc++; |
96 | } | 93 | } |
97 | 94 | ||
98 | if (do_swap32) { | 95 | if (do_swap32) { |
99 | gph_size = omapimage_swap32(gph->size); | 96 | gph_size = omapimage_swap32(gph->size); |
100 | gph_load_addr = omapimage_swap32(gph->load_addr); | 97 | gph_load_addr = omapimage_swap32(gph->load_addr); |
101 | } else { | 98 | } else { |
102 | gph_size = gph->size; | 99 | gph_size = gph->size; |
103 | gph_load_addr = gph->load_addr; | 100 | gph_load_addr = gph->load_addr; |
104 | } | 101 | } |
105 | 102 | ||
106 | if (!valid_gph_size(gph_size)) | 103 | if (!valid_gph_size(gph_size)) |
107 | return -1; | 104 | return -1; |
108 | if (!valid_gph_load_addr(gph_load_addr)) | 105 | if (!valid_gph_load_addr(gph_load_addr)) |
109 | return -1; | 106 | return -1; |
110 | 107 | ||
111 | return 0; | 108 | return 0; |
112 | } | 109 | } |
113 | 110 | ||
114 | static void omapimage_print_section(struct ch_settings *chs) | 111 | static void omapimage_print_section(struct ch_settings *chs) |
115 | { | 112 | { |
116 | const char *section_name; | 113 | const char *section_name; |
117 | 114 | ||
118 | if (chs->section_key) | 115 | if (chs->section_key) |
119 | section_name = "CHSETTINGS"; | 116 | section_name = "CHSETTINGS"; |
120 | else | 117 | else |
121 | section_name = "UNKNOWNKEY"; | 118 | section_name = "UNKNOWNKEY"; |
122 | 119 | ||
123 | printf("%s (%x) " | 120 | printf("%s (%x) " |
124 | "valid:%x " | 121 | "valid:%x " |
125 | "version:%x " | 122 | "version:%x " |
126 | "reserved:%x " | 123 | "reserved:%x " |
127 | "flags:%x\n", | 124 | "flags:%x\n", |
128 | section_name, | 125 | section_name, |
129 | chs->section_key, | 126 | chs->section_key, |
130 | chs->valid, | 127 | chs->valid, |
131 | chs->version, | 128 | chs->version, |
132 | chs->reserved, | 129 | chs->reserved, |
133 | chs->flags); | 130 | chs->flags); |
134 | } | 131 | } |
135 | 132 | ||
136 | static void omapimage_print_header(const void *ptr) | 133 | static void omapimage_print_header(const void *ptr) |
137 | { | 134 | { |
138 | const struct ch_toc *toc = (struct ch_toc *)ptr; | 135 | const struct ch_toc *toc = (struct ch_toc *)ptr; |
139 | const struct gp_header *gph = | 136 | const struct gp_header *gph = |
140 | (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); | 137 | (struct gp_header *)(ptr+OMAP_CH_HDR_SIZE); |
141 | uint32_t offset, size, gph_size, gph_load_addr; | 138 | uint32_t offset, size, gph_size, gph_load_addr; |
142 | 139 | ||
143 | while (toc->section_offset != 0xffffffff | 140 | while (toc->section_offset != 0xffffffff |
144 | && toc->section_size != 0xffffffff) { | 141 | && toc->section_size != 0xffffffff) { |
145 | if (do_swap32) { | 142 | if (do_swap32) { |
146 | offset = omapimage_swap32(toc->section_offset); | 143 | offset = omapimage_swap32(toc->section_offset); |
147 | size = omapimage_swap32(toc->section_size); | 144 | size = omapimage_swap32(toc->section_size); |
148 | } else { | 145 | } else { |
149 | offset = toc->section_offset; | 146 | offset = toc->section_offset; |
150 | size = toc->section_size; | 147 | size = toc->section_size; |
151 | } | 148 | } |
152 | 149 | ||
153 | if (offset >= OMAP_CH_HDR_SIZE || | 150 | if (offset >= OMAP_CH_HDR_SIZE || |
154 | offset+size >= OMAP_CH_HDR_SIZE) | 151 | offset+size >= OMAP_CH_HDR_SIZE) |
155 | exit(EXIT_FAILURE); | 152 | exit(EXIT_FAILURE); |
156 | 153 | ||
157 | printf("Section %s offset %x length %x\n", | 154 | printf("Section %s offset %x length %x\n", |
158 | toc->section_name, | 155 | toc->section_name, |
159 | toc->section_offset, | 156 | toc->section_offset, |
160 | toc->section_size); | 157 | toc->section_size); |
161 | 158 | ||
162 | omapimage_print_section((struct ch_settings *)(ptr+offset)); | 159 | omapimage_print_section((struct ch_settings *)(ptr+offset)); |
163 | toc++; | 160 | toc++; |
164 | } | 161 | } |
165 | 162 | ||
166 | if (do_swap32) { | 163 | if (do_swap32) { |
167 | gph_size = omapimage_swap32(gph->size); | 164 | gph_size = omapimage_swap32(gph->size); |
168 | gph_load_addr = omapimage_swap32(gph->load_addr); | 165 | gph_load_addr = omapimage_swap32(gph->load_addr); |
169 | } else { | 166 | } else { |
170 | gph_size = gph->size; | 167 | gph_size = gph->size; |
171 | gph_load_addr = gph->load_addr; | 168 | gph_load_addr = gph->load_addr; |
172 | } | 169 | } |
173 | 170 | ||
174 | if (!valid_gph_size(gph_size)) { | 171 | if (!valid_gph_size(gph_size)) { |
175 | fprintf(stderr, "Error: invalid image size %x\n", gph_size); | 172 | fprintf(stderr, "Error: invalid image size %x\n", gph_size); |
176 | exit(EXIT_FAILURE); | 173 | exit(EXIT_FAILURE); |
177 | } | 174 | } |
178 | 175 | ||
179 | if (!valid_gph_load_addr(gph_load_addr)) { | 176 | if (!valid_gph_load_addr(gph_load_addr)) { |
180 | fprintf(stderr, "Error: invalid image load address %x\n", | 177 | fprintf(stderr, "Error: invalid image load address %x\n", |
181 | gph_load_addr); | 178 | gph_load_addr); |
182 | exit(EXIT_FAILURE); | 179 | exit(EXIT_FAILURE); |
183 | } | 180 | } |
184 | 181 | ||
185 | printf("GP Header: Size %x LoadAddr %x\n", gph_size, gph_load_addr); | 182 | printf("GP Header: Size %x LoadAddr %x\n", gph_size, gph_load_addr); |
186 | } | 183 | } |
187 | 184 | ||
188 | static int toc_offset(void *hdr, void *member) | 185 | static int toc_offset(void *hdr, void *member) |
189 | { | 186 | { |
190 | return member - hdr; | 187 | return member - hdr; |
191 | } | 188 | } |
192 | 189 | ||
193 | static void omapimage_set_header(void *ptr, struct stat *sbuf, int ifd, | 190 | static void omapimage_set_header(void *ptr, struct stat *sbuf, int ifd, |
194 | struct mkimage_params *params) | 191 | struct mkimage_params *params) |
195 | { | 192 | { |
196 | struct ch_toc *toc = (struct ch_toc *)ptr; | 193 | struct ch_toc *toc = (struct ch_toc *)ptr; |
197 | struct ch_settings *chs = (struct ch_settings *) | 194 | struct ch_settings *chs = (struct ch_settings *) |
198 | (ptr + 2 * sizeof(*toc)); | 195 | (ptr + 2 * sizeof(*toc)); |
199 | struct gp_header *gph = (struct gp_header *)(ptr + OMAP_CH_HDR_SIZE); | 196 | struct gp_header *gph = (struct gp_header *)(ptr + OMAP_CH_HDR_SIZE); |
200 | 197 | ||
201 | toc->section_offset = toc_offset(ptr, chs); | 198 | toc->section_offset = toc_offset(ptr, chs); |
202 | toc->section_size = sizeof(struct ch_settings); | 199 | toc->section_size = sizeof(struct ch_settings); |
203 | strcpy((char *)toc->section_name, "CHSETTINGS"); | 200 | strcpy((char *)toc->section_name, "CHSETTINGS"); |
204 | 201 | ||
205 | chs->section_key = KEY_CHSETTINGS; | 202 | chs->section_key = KEY_CHSETTINGS; |
206 | chs->valid = 0; | 203 | chs->valid = 0; |
207 | chs->version = 1; | 204 | chs->version = 1; |
208 | chs->reserved = 0; | 205 | chs->reserved = 0; |
209 | chs->flags = 0; | 206 | chs->flags = 0; |
210 | 207 | ||
211 | toc++; | 208 | toc++; |
212 | memset(toc, 0xff, sizeof(*toc)); | 209 | memset(toc, 0xff, sizeof(*toc)); |
213 | 210 | ||
214 | gph->size = sbuf->st_size - OMAP_FILE_HDR_SIZE; | 211 | gph->size = sbuf->st_size - OMAP_FILE_HDR_SIZE; |
215 | gph->load_addr = params->addr; | 212 | gph->load_addr = params->addr; |
216 | 213 | ||
217 | if (strncmp(params->imagename, "byteswap", 8) == 0) { | 214 | if (strncmp(params->imagename, "byteswap", 8) == 0) { |
218 | do_swap32 = 1; | 215 | do_swap32 = 1; |
219 | int swapped = 0; | 216 | int swapped = 0; |
220 | uint32_t *data = (uint32_t *)ptr; | 217 | uint32_t *data = (uint32_t *)ptr; |
221 | 218 | ||
222 | while (swapped <= (sbuf->st_size / sizeof(uint32_t))) { | 219 | while (swapped <= (sbuf->st_size / sizeof(uint32_t))) { |
223 | *data = omapimage_swap32(*data); | 220 | *data = omapimage_swap32(*data); |
224 | swapped++; | 221 | swapped++; |
225 | data++; | 222 | data++; |
226 | } | 223 | } |
227 | } | 224 | } |
228 | } | 225 | } |
229 | 226 | ||
230 | int omapimage_check_params(struct mkimage_params *params) | 227 | int omapimage_check_params(struct mkimage_params *params) |
231 | { | 228 | { |
232 | return (params->dflag && (params->fflag || params->lflag)) || | 229 | return (params->dflag && (params->fflag || params->lflag)) || |
233 | (params->fflag && (params->dflag || params->lflag)) || | 230 | (params->fflag && (params->dflag || params->lflag)) || |
234 | (params->lflag && (params->dflag || params->fflag)); | 231 | (params->lflag && (params->dflag || params->fflag)); |
235 | } | 232 | } |
236 | 233 | ||
237 | /* | 234 | /* |
238 | * omapimage parameters | 235 | * omapimage parameters |
239 | */ | 236 | */ |
240 | static struct image_type_params omapimage_params = { | 237 | static struct image_type_params omapimage_params = { |
241 | .name = "TI OMAP CH/GP Boot Image support", | 238 | .name = "TI OMAP CH/GP Boot Image support", |
242 | .header_size = OMAP_FILE_HDR_SIZE, | 239 | .header_size = OMAP_FILE_HDR_SIZE, |
243 | .hdr = (void *)&omapimage_header, | 240 | .hdr = (void *)&omapimage_header, |
244 | .check_image_type = omapimage_check_image_types, | 241 | .check_image_type = omapimage_check_image_types, |
245 | .verify_header = omapimage_verify_header, | 242 | .verify_header = omapimage_verify_header, |
246 | .print_header = omapimage_print_header, | 243 | .print_header = omapimage_print_header, |
247 | .set_header = omapimage_set_header, | 244 | .set_header = omapimage_set_header, |
248 | .check_params = omapimage_check_params, | 245 | .check_params = omapimage_check_params, |
249 | }; | 246 | }; |
250 | 247 | ||
251 | void init_omap_image_type(void) | 248 | void init_omap_image_type(void) |
252 | { | 249 | { |
253 | mkimage_register(&omapimage_params); | 250 | mkimage_register(&omapimage_params); |
254 | } | 251 | } |
255 | 252 |
tools/pblimage.c
1 | /* | 1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | 2 | * Copyright 2012 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | */ | 5 | */ |
6 | #define _GNU_SOURCE | ||
7 | |||
8 | #include "mkimage.h" | 6 | #include "mkimage.h" |
9 | #include <image.h> | 7 | #include <image.h> |
10 | #include "pblimage.h" | 8 | #include "pblimage.h" |
11 | 9 | ||
12 | /* | 10 | /* |
13 | * Initialize to an invalid value. | 11 | * Initialize to an invalid value. |
14 | */ | 12 | */ |
15 | static uint32_t next_pbl_cmd = 0x82000000; | 13 | static uint32_t next_pbl_cmd = 0x82000000; |
16 | /* | 14 | /* |
17 | * need to store all bytes in memory for calculating crc32, then write the | 15 | * need to store all bytes in memory for calculating crc32, then write the |
18 | * bytes to image file for PBL boot. | 16 | * bytes to image file for PBL boot. |
19 | */ | 17 | */ |
20 | static unsigned char mem_buf[1000000]; | 18 | static unsigned char mem_buf[1000000]; |
21 | static unsigned char *pmem_buf = mem_buf; | 19 | static unsigned char *pmem_buf = mem_buf; |
22 | static int pbl_size; | 20 | static int pbl_size; |
23 | static char *fname = "Unknown"; | 21 | static char *fname = "Unknown"; |
24 | static int lineno = -1; | 22 | static int lineno = -1; |
25 | static struct pbl_header pblimage_header; | 23 | static struct pbl_header pblimage_header; |
26 | 24 | ||
27 | static union | 25 | static union |
28 | { | 26 | { |
29 | char c[4]; | 27 | char c[4]; |
30 | unsigned char l; | 28 | unsigned char l; |
31 | } endian_test = { {'l', '?', '?', 'b'} }; | 29 | } endian_test = { {'l', '?', '?', 'b'} }; |
32 | 30 | ||
33 | #define ENDIANNESS ((char)endian_test.l) | 31 | #define ENDIANNESS ((char)endian_test.l) |
34 | 32 | ||
35 | /* | 33 | /* |
36 | * The PBL can load up to 64 bytes at a time, so we split the U-Boot | 34 | * The PBL can load up to 64 bytes at a time, so we split the U-Boot |
37 | * image into 64 byte chunks. PBL needs a command for each piece, of | 35 | * image into 64 byte chunks. PBL needs a command for each piece, of |
38 | * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the | 36 | * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the |
39 | * start offset by subtracting the size of the u-boot image from the | 37 | * start offset by subtracting the size of the u-boot image from the |
40 | * top of the allowable 24-bit range. | 38 | * top of the allowable 24-bit range. |
41 | */ | 39 | */ |
42 | static void init_next_pbl_cmd(FILE *fp_uboot) | 40 | static void init_next_pbl_cmd(FILE *fp_uboot) |
43 | { | 41 | { |
44 | struct stat st; | 42 | struct stat st; |
45 | int fd = fileno(fp_uboot); | 43 | int fd = fileno(fp_uboot); |
46 | 44 | ||
47 | if (fstat(fd, &st) == -1) { | 45 | if (fstat(fd, &st) == -1) { |
48 | printf("Error: Could not determine u-boot image size. %s\n", | 46 | printf("Error: Could not determine u-boot image size. %s\n", |
49 | strerror(errno)); | 47 | strerror(errno)); |
50 | exit(EXIT_FAILURE); | 48 | exit(EXIT_FAILURE); |
51 | } | 49 | } |
52 | 50 | ||
53 | next_pbl_cmd = 0x82000000 - st.st_size; | 51 | next_pbl_cmd = 0x82000000 - st.st_size; |
54 | } | 52 | } |
55 | 53 | ||
56 | static void generate_pbl_cmd(void) | 54 | static void generate_pbl_cmd(void) |
57 | { | 55 | { |
58 | uint32_t val = next_pbl_cmd; | 56 | uint32_t val = next_pbl_cmd; |
59 | next_pbl_cmd += 0x40; | 57 | next_pbl_cmd += 0x40; |
60 | int i; | 58 | int i; |
61 | 59 | ||
62 | for (i = 3; i >= 0; i--) { | 60 | for (i = 3; i >= 0; i--) { |
63 | *pmem_buf++ = (val >> (i * 8)) & 0xff; | 61 | *pmem_buf++ = (val >> (i * 8)) & 0xff; |
64 | pbl_size++; | 62 | pbl_size++; |
65 | } | 63 | } |
66 | } | 64 | } |
67 | 65 | ||
68 | static void pbl_fget(size_t size, FILE *stream) | 66 | static void pbl_fget(size_t size, FILE *stream) |
69 | { | 67 | { |
70 | unsigned char c; | 68 | unsigned char c; |
71 | int c_temp; | 69 | int c_temp; |
72 | 70 | ||
73 | while (size && (c_temp = fgetc(stream)) != EOF) { | 71 | while (size && (c_temp = fgetc(stream)) != EOF) { |
74 | c = (unsigned char)c_temp; | 72 | c = (unsigned char)c_temp; |
75 | *pmem_buf++ = c; | 73 | *pmem_buf++ = c; |
76 | pbl_size++; | 74 | pbl_size++; |
77 | size--; | 75 | size--; |
78 | } | 76 | } |
79 | } | 77 | } |
80 | 78 | ||
81 | /* load split u-boot with PBI command 81xxxxxx. */ | 79 | /* load split u-boot with PBI command 81xxxxxx. */ |
82 | static void load_uboot(FILE *fp_uboot) | 80 | static void load_uboot(FILE *fp_uboot) |
83 | { | 81 | { |
84 | init_next_pbl_cmd(fp_uboot); | 82 | init_next_pbl_cmd(fp_uboot); |
85 | while (next_pbl_cmd < 0x82000000) { | 83 | while (next_pbl_cmd < 0x82000000) { |
86 | generate_pbl_cmd(); | 84 | generate_pbl_cmd(); |
87 | pbl_fget(64, fp_uboot); | 85 | pbl_fget(64, fp_uboot); |
88 | } | 86 | } |
89 | } | 87 | } |
90 | 88 | ||
91 | static void check_get_hexval(char *token) | 89 | static void check_get_hexval(char *token) |
92 | { | 90 | { |
93 | uint32_t hexval; | 91 | uint32_t hexval; |
94 | int i; | 92 | int i; |
95 | 93 | ||
96 | if (!sscanf(token, "%x", &hexval)) { | 94 | if (!sscanf(token, "%x", &hexval)) { |
97 | printf("Error:%s[%d] - Invalid hex data(%s)\n", fname, | 95 | printf("Error:%s[%d] - Invalid hex data(%s)\n", fname, |
98 | lineno, token); | 96 | lineno, token); |
99 | exit(EXIT_FAILURE); | 97 | exit(EXIT_FAILURE); |
100 | } | 98 | } |
101 | for (i = 3; i >= 0; i--) { | 99 | for (i = 3; i >= 0; i--) { |
102 | *pmem_buf++ = (hexval >> (i * 8)) & 0xff; | 100 | *pmem_buf++ = (hexval >> (i * 8)) & 0xff; |
103 | pbl_size++; | 101 | pbl_size++; |
104 | } | 102 | } |
105 | } | 103 | } |
106 | 104 | ||
107 | static void pbl_parser(char *name) | 105 | static void pbl_parser(char *name) |
108 | { | 106 | { |
109 | FILE *fd = NULL; | 107 | FILE *fd = NULL; |
110 | char *line = NULL; | 108 | char *line = NULL; |
111 | char *token, *saveptr1, *saveptr2; | 109 | char *token, *saveptr1, *saveptr2; |
112 | size_t len = 0; | 110 | size_t len = 0; |
113 | 111 | ||
114 | fname = name; | 112 | fname = name; |
115 | fd = fopen(name, "r"); | 113 | fd = fopen(name, "r"); |
116 | if (fd == NULL) { | 114 | if (fd == NULL) { |
117 | printf("Error:%s - Can't open\n", fname); | 115 | printf("Error:%s - Can't open\n", fname); |
118 | exit(EXIT_FAILURE); | 116 | exit(EXIT_FAILURE); |
119 | } | 117 | } |
120 | 118 | ||
121 | while ((getline(&line, &len, fd)) > 0) { | 119 | while ((getline(&line, &len, fd)) > 0) { |
122 | lineno++; | 120 | lineno++; |
123 | token = strtok_r(line, "\r\n", &saveptr1); | 121 | token = strtok_r(line, "\r\n", &saveptr1); |
124 | /* drop all lines with zero tokens (= empty lines) */ | 122 | /* drop all lines with zero tokens (= empty lines) */ |
125 | if (token == NULL) | 123 | if (token == NULL) |
126 | continue; | 124 | continue; |
127 | for (line = token;; line = NULL) { | 125 | for (line = token;; line = NULL) { |
128 | token = strtok_r(line, " \t", &saveptr2); | 126 | token = strtok_r(line, " \t", &saveptr2); |
129 | if (token == NULL) | 127 | if (token == NULL) |
130 | break; | 128 | break; |
131 | /* Drop all text starting with '#' as comments */ | 129 | /* Drop all text starting with '#' as comments */ |
132 | if (token[0] == '#') | 130 | if (token[0] == '#') |
133 | break; | 131 | break; |
134 | check_get_hexval(token); | 132 | check_get_hexval(token); |
135 | } | 133 | } |
136 | } | 134 | } |
137 | if (line) | 135 | if (line) |
138 | free(line); | 136 | free(line); |
139 | fclose(fd); | 137 | fclose(fd); |
140 | } | 138 | } |
141 | 139 | ||
142 | static uint32_t crc_table[256]; | 140 | static uint32_t crc_table[256]; |
143 | 141 | ||
144 | static void make_crc_table(void) | 142 | static void make_crc_table(void) |
145 | { | 143 | { |
146 | uint32_t mask; | 144 | uint32_t mask; |
147 | int i, j; | 145 | int i, j; |
148 | uint32_t poly; /* polynomial exclusive-or pattern */ | 146 | uint32_t poly; /* polynomial exclusive-or pattern */ |
149 | 147 | ||
150 | /* | 148 | /* |
151 | * the polynomial used by PBL is 1 + x1 + x2 + x4 + x5 + x7 + x8 + x10 | 149 | * the polynomial used by PBL is 1 + x1 + x2 + x4 + x5 + x7 + x8 + x10 |
152 | * + x11 + x12 + x16 + x22 + x23 + x26 + x32. | 150 | * + x11 + x12 + x16 + x22 + x23 + x26 + x32. |
153 | */ | 151 | */ |
154 | poly = 0x04c11db7; | 152 | poly = 0x04c11db7; |
155 | 153 | ||
156 | for (i = 0; i < 256; i++) { | 154 | for (i = 0; i < 256; i++) { |
157 | mask = i << 24; | 155 | mask = i << 24; |
158 | for (j = 0; j < 8; j++) { | 156 | for (j = 0; j < 8; j++) { |
159 | if (mask & 0x80000000) | 157 | if (mask & 0x80000000) |
160 | mask = (mask << 1) ^ poly; | 158 | mask = (mask << 1) ^ poly; |
161 | else | 159 | else |
162 | mask <<= 1; | 160 | mask <<= 1; |
163 | } | 161 | } |
164 | crc_table[i] = mask; | 162 | crc_table[i] = mask; |
165 | } | 163 | } |
166 | } | 164 | } |
167 | 165 | ||
168 | unsigned long pbl_crc32(unsigned long crc, const char *buf, uint32_t len) | 166 | unsigned long pbl_crc32(unsigned long crc, const char *buf, uint32_t len) |
169 | { | 167 | { |
170 | uint32_t crc32_val = 0xffffffff; | 168 | uint32_t crc32_val = 0xffffffff; |
171 | uint32_t xor = 0x0; | 169 | uint32_t xor = 0x0; |
172 | int i; | 170 | int i; |
173 | 171 | ||
174 | make_crc_table(); | 172 | make_crc_table(); |
175 | 173 | ||
176 | for (i = 0; i < len; i++) | 174 | for (i = 0; i < len; i++) |
177 | crc32_val = (crc32_val << 8) ^ | 175 | crc32_val = (crc32_val << 8) ^ |
178 | crc_table[(crc32_val >> 24) ^ (*buf++ & 0xff)]; | 176 | crc_table[(crc32_val >> 24) ^ (*buf++ & 0xff)]; |
179 | 177 | ||
180 | crc32_val = crc32_val ^ xor; | 178 | crc32_val = crc32_val ^ xor; |
181 | if (crc32_val < 0) { | 179 | if (crc32_val < 0) { |
182 | crc32_val += 0xffffffff; | 180 | crc32_val += 0xffffffff; |
183 | crc32_val += 1; | 181 | crc32_val += 1; |
184 | } | 182 | } |
185 | return crc32_val; | 183 | return crc32_val; |
186 | } | 184 | } |
187 | 185 | ||
188 | static uint32_t reverse_byte(uint32_t val) | 186 | static uint32_t reverse_byte(uint32_t val) |
189 | { | 187 | { |
190 | uint32_t temp; | 188 | uint32_t temp; |
191 | unsigned char *p1; | 189 | unsigned char *p1; |
192 | int j; | 190 | int j; |
193 | 191 | ||
194 | temp = val; | 192 | temp = val; |
195 | p1 = (unsigned char *)&temp; | 193 | p1 = (unsigned char *)&temp; |
196 | for (j = 3; j >= 0; j--) | 194 | for (j = 3; j >= 0; j--) |
197 | *p1++ = (val >> (j * 8)) & 0xff; | 195 | *p1++ = (val >> (j * 8)) & 0xff; |
198 | return temp; | 196 | return temp; |
199 | } | 197 | } |
200 | 198 | ||
201 | /* write end command and crc command to memory. */ | 199 | /* write end command and crc command to memory. */ |
202 | static void add_end_cmd(void) | 200 | static void add_end_cmd(void) |
203 | { | 201 | { |
204 | uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000, | 202 | uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000, |
205 | 0x091380c0, 0x00000000}; | 203 | 0x091380c0, 0x00000000}; |
206 | uint32_t crc32_pbl; | 204 | uint32_t crc32_pbl; |
207 | int i; | 205 | int i; |
208 | unsigned char *p = (unsigned char *)&pbl_end_cmd; | 206 | unsigned char *p = (unsigned char *)&pbl_end_cmd; |
209 | 207 | ||
210 | if (ENDIANNESS == 'l') { | 208 | if (ENDIANNESS == 'l') { |
211 | for (i = 0; i < 4; i++) | 209 | for (i = 0; i < 4; i++) |
212 | pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]); | 210 | pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]); |
213 | } | 211 | } |
214 | 212 | ||
215 | for (i = 0; i < 16; i++) { | 213 | for (i = 0; i < 16; i++) { |
216 | *pmem_buf++ = *p++; | 214 | *pmem_buf++ = *p++; |
217 | pbl_size++; | 215 | pbl_size++; |
218 | } | 216 | } |
219 | 217 | ||
220 | /* Add PBI CRC command. */ | 218 | /* Add PBI CRC command. */ |
221 | *pmem_buf++ = 0x08; | 219 | *pmem_buf++ = 0x08; |
222 | *pmem_buf++ = 0x13; | 220 | *pmem_buf++ = 0x13; |
223 | *pmem_buf++ = 0x80; | 221 | *pmem_buf++ = 0x80; |
224 | *pmem_buf++ = 0x40; | 222 | *pmem_buf++ = 0x40; |
225 | pbl_size += 4; | 223 | pbl_size += 4; |
226 | 224 | ||
227 | /* calculated CRC32 and write it to memory. */ | 225 | /* calculated CRC32 and write it to memory. */ |
228 | crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size); | 226 | crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size); |
229 | *pmem_buf++ = (crc32_pbl >> 24) & 0xff; | 227 | *pmem_buf++ = (crc32_pbl >> 24) & 0xff; |
230 | *pmem_buf++ = (crc32_pbl >> 16) & 0xff; | 228 | *pmem_buf++ = (crc32_pbl >> 16) & 0xff; |
231 | *pmem_buf++ = (crc32_pbl >> 8) & 0xff; | 229 | *pmem_buf++ = (crc32_pbl >> 8) & 0xff; |
232 | *pmem_buf++ = (crc32_pbl) & 0xff; | 230 | *pmem_buf++ = (crc32_pbl) & 0xff; |
233 | pbl_size += 4; | 231 | pbl_size += 4; |
234 | 232 | ||
235 | if ((pbl_size % 16) != 0) { | 233 | if ((pbl_size % 16) != 0) { |
236 | for (i = 0; i < 8; i++) { | 234 | for (i = 0; i < 8; i++) { |
237 | *pmem_buf++ = 0x0; | 235 | *pmem_buf++ = 0x0; |
238 | pbl_size++; | 236 | pbl_size++; |
239 | } | 237 | } |
240 | } | 238 | } |
241 | if ((pbl_size % 16 != 0)) { | 239 | if ((pbl_size % 16 != 0)) { |
242 | printf("Error: Bad size of image file\n"); | 240 | printf("Error: Bad size of image file\n"); |
243 | exit(EXIT_FAILURE); | 241 | exit(EXIT_FAILURE); |
244 | } | 242 | } |
245 | } | 243 | } |
246 | 244 | ||
247 | void pbl_load_uboot(int ifd, struct mkimage_params *params) | 245 | void pbl_load_uboot(int ifd, struct mkimage_params *params) |
248 | { | 246 | { |
249 | FILE *fp_uboot; | 247 | FILE *fp_uboot; |
250 | int size; | 248 | int size; |
251 | 249 | ||
252 | /* parse the rcw.cfg file. */ | 250 | /* parse the rcw.cfg file. */ |
253 | pbl_parser(params->imagename); | 251 | pbl_parser(params->imagename); |
254 | 252 | ||
255 | /* parse the pbi.cfg file. */ | 253 | /* parse the pbi.cfg file. */ |
256 | pbl_parser(params->imagename2); | 254 | pbl_parser(params->imagename2); |
257 | 255 | ||
258 | fp_uboot = fopen(params->datafile, "r"); | 256 | fp_uboot = fopen(params->datafile, "r"); |
259 | if (fp_uboot == NULL) { | 257 | if (fp_uboot == NULL) { |
260 | printf("Error: %s open failed\n", params->datafile); | 258 | printf("Error: %s open failed\n", params->datafile); |
261 | exit(EXIT_FAILURE); | 259 | exit(EXIT_FAILURE); |
262 | } | 260 | } |
263 | 261 | ||
264 | load_uboot(fp_uboot); | 262 | load_uboot(fp_uboot); |
265 | add_end_cmd(); | 263 | add_end_cmd(); |
266 | fclose(fp_uboot); | 264 | fclose(fp_uboot); |
267 | lseek(ifd, 0, SEEK_SET); | 265 | lseek(ifd, 0, SEEK_SET); |
268 | 266 | ||
269 | size = pbl_size; | 267 | size = pbl_size; |
270 | if (write(ifd, (const void *)&mem_buf, size) != size) { | 268 | if (write(ifd, (const void *)&mem_buf, size) != size) { |
271 | fprintf(stderr, "Write error on %s: %s\n", | 269 | fprintf(stderr, "Write error on %s: %s\n", |
272 | params->imagefile, strerror(errno)); | 270 | params->imagefile, strerror(errno)); |
273 | exit(EXIT_FAILURE); | 271 | exit(EXIT_FAILURE); |
274 | } | 272 | } |
275 | } | 273 | } |
276 | 274 | ||
277 | static int pblimage_check_image_types(uint8_t type) | 275 | static int pblimage_check_image_types(uint8_t type) |
278 | { | 276 | { |
279 | if (type == IH_TYPE_PBLIMAGE) | 277 | if (type == IH_TYPE_PBLIMAGE) |
280 | return EXIT_SUCCESS; | 278 | return EXIT_SUCCESS; |
281 | else | 279 | else |
282 | return EXIT_FAILURE; | 280 | return EXIT_FAILURE; |
283 | } | 281 | } |
284 | 282 | ||
285 | static int pblimage_verify_header(unsigned char *ptr, int image_size, | 283 | static int pblimage_verify_header(unsigned char *ptr, int image_size, |
286 | struct mkimage_params *params) | 284 | struct mkimage_params *params) |
287 | { | 285 | { |
288 | struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; | 286 | struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; |
289 | 287 | ||
290 | /* Only a few checks can be done: search for magic numbers */ | 288 | /* Only a few checks can be done: search for magic numbers */ |
291 | if (ENDIANNESS == 'l') { | 289 | if (ENDIANNESS == 'l') { |
292 | if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) | 290 | if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) |
293 | return -FDT_ERR_BADSTRUCTURE; | 291 | return -FDT_ERR_BADSTRUCTURE; |
294 | 292 | ||
295 | if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER)) | 293 | if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER)) |
296 | return -FDT_ERR_BADSTRUCTURE; | 294 | return -FDT_ERR_BADSTRUCTURE; |
297 | } else { | 295 | } else { |
298 | if (pbl_hdr->preamble != RCW_PREAMBLE) | 296 | if (pbl_hdr->preamble != RCW_PREAMBLE) |
299 | return -FDT_ERR_BADSTRUCTURE; | 297 | return -FDT_ERR_BADSTRUCTURE; |
300 | 298 | ||
301 | if (pbl_hdr->rcwheader != RCW_HEADER) | 299 | if (pbl_hdr->rcwheader != RCW_HEADER) |
302 | return -FDT_ERR_BADSTRUCTURE; | 300 | return -FDT_ERR_BADSTRUCTURE; |
303 | } | 301 | } |
304 | return 0; | 302 | return 0; |
305 | } | 303 | } |
306 | 304 | ||
307 | static void pblimage_print_header(const void *ptr) | 305 | static void pblimage_print_header(const void *ptr) |
308 | { | 306 | { |
309 | printf("Image Type: Freescale PBL Boot Image\n"); | 307 | printf("Image Type: Freescale PBL Boot Image\n"); |
310 | } | 308 | } |
311 | 309 | ||
312 | static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd, | 310 | static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd, |
313 | struct mkimage_params *params) | 311 | struct mkimage_params *params) |
314 | { | 312 | { |
315 | /*nothing need to do, pbl_load_uboot takes care of whole file. */ | 313 | /*nothing need to do, pbl_load_uboot takes care of whole file. */ |
316 | } | 314 | } |
317 | 315 | ||
318 | /* pblimage parameters */ | 316 | /* pblimage parameters */ |
319 | static struct image_type_params pblimage_params = { | 317 | static struct image_type_params pblimage_params = { |
320 | .name = "Freescale PBL Boot Image support", | 318 | .name = "Freescale PBL Boot Image support", |
321 | .header_size = sizeof(struct pbl_header), | 319 | .header_size = sizeof(struct pbl_header), |
322 | .hdr = (void *)&pblimage_header, | 320 | .hdr = (void *)&pblimage_header, |
323 | .check_image_type = pblimage_check_image_types, | 321 | .check_image_type = pblimage_check_image_types, |
324 | .verify_header = pblimage_verify_header, | 322 | .verify_header = pblimage_verify_header, |
325 | .print_header = pblimage_print_header, | 323 | .print_header = pblimage_print_header, |
326 | .set_header = pblimage_set_header, | 324 | .set_header = pblimage_set_header, |
327 | }; | 325 | }; |
328 | 326 | ||
329 | void init_pbl_image_type(void) | 327 | void init_pbl_image_type(void) |
330 | { | 328 | { |
331 | pbl_size = 0; | 329 | pbl_size = 0; |
332 | mkimage_register(&pblimage_params); | 330 | mkimage_register(&pblimage_params); |
333 | } | 331 | } |
334 | 332 |
tools/ublimage.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 | 2 | * (C) Copyright 2011 |
3 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. | 3 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. |
4 | * | 4 | * |
5 | * Based on: | 5 | * Based on: |
6 | * (C) Copyright 2009 | 6 | * (C) Copyright 2009 |
7 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. | 7 | * Stefano Babic, DENX Software Engineering, sbabic@denx.de. |
8 | * | 8 | * |
9 | * (C) Copyright 2008 | 9 | * (C) Copyright 2008 |
10 | * Marvell Semiconductor <www.marvell.com> | 10 | * Marvell Semiconductor <www.marvell.com> |
11 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> | 11 | * Written-by: Prafulla Wadaskar <prafulla@marvell.com> |
12 | * | 12 | * |
13 | * SPDX-License-Identifier: GPL-2.0+ | 13 | * SPDX-License-Identifier: GPL-2.0+ |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* Required to obtain the getline prototype from stdio.h */ | ||
17 | #define _GNU_SOURCE | ||
18 | |||
19 | #include "mkimage.h" | 16 | #include "mkimage.h" |
20 | #include <image.h> | 17 | #include <image.h> |
21 | #include "ublimage.h" | 18 | #include "ublimage.h" |
22 | 19 | ||
23 | /* | 20 | /* |
24 | * Supported commands for configuration file | 21 | * Supported commands for configuration file |
25 | */ | 22 | */ |
26 | static table_entry_t ublimage_cmds[] = { | 23 | static table_entry_t ublimage_cmds[] = { |
27 | {CMD_BOOT_MODE, "MODE", "UBL special modes", }, | 24 | {CMD_BOOT_MODE, "MODE", "UBL special modes", }, |
28 | {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", }, | 25 | {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", }, |
29 | {CMD_PAGE, "PAGES", | 26 | {CMD_PAGE, "PAGES", |
30 | "number of pages (size of bootloader)", }, | 27 | "number of pages (size of bootloader)", }, |
31 | {CMD_ST_BLOCK, "START_BLOCK", | 28 | {CMD_ST_BLOCK, "START_BLOCK", |
32 | "block number where bootloader is present", }, | 29 | "block number where bootloader is present", }, |
33 | {CMD_ST_PAGE, "START_PAGE", | 30 | {CMD_ST_PAGE, "START_PAGE", |
34 | "page number where bootloader is present", }, | 31 | "page number where bootloader is present", }, |
35 | {CMD_LD_ADDR, "LD_ADDR", | 32 | {CMD_LD_ADDR, "LD_ADDR", |
36 | "load addr", }, | 33 | "load addr", }, |
37 | {-1, "", "", }, | 34 | {-1, "", "", }, |
38 | }; | 35 | }; |
39 | 36 | ||
40 | /* | 37 | /* |
41 | * Supported Boot options for configuration file | 38 | * Supported Boot options for configuration file |
42 | * this is needed to set the correct flash offset | 39 | * this is needed to set the correct flash offset |
43 | */ | 40 | */ |
44 | static table_entry_t ublimage_bootops[] = { | 41 | static table_entry_t ublimage_bootops[] = { |
45 | {UBL_MAGIC_SAFE, "safe", "Safe boot mode", }, | 42 | {UBL_MAGIC_SAFE, "safe", "Safe boot mode", }, |
46 | {-1, "", "Invalid", }, | 43 | {-1, "", "Invalid", }, |
47 | }; | 44 | }; |
48 | 45 | ||
49 | static struct ubl_header ublimage_header; | 46 | static struct ubl_header ublimage_header; |
50 | 47 | ||
51 | static uint32_t get_cfg_value(char *token, char *name, int linenr) | 48 | static uint32_t get_cfg_value(char *token, char *name, int linenr) |
52 | { | 49 | { |
53 | char *endptr; | 50 | char *endptr; |
54 | uint32_t value; | 51 | uint32_t value; |
55 | 52 | ||
56 | errno = 0; | 53 | errno = 0; |
57 | value = strtoul(token, &endptr, 16); | 54 | value = strtoul(token, &endptr, 16); |
58 | if (errno || (token == endptr)) { | 55 | if (errno || (token == endptr)) { |
59 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", | 56 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", |
60 | name, linenr, token); | 57 | name, linenr, token); |
61 | exit(EXIT_FAILURE); | 58 | exit(EXIT_FAILURE); |
62 | } | 59 | } |
63 | return value; | 60 | return value; |
64 | } | 61 | } |
65 | 62 | ||
66 | static void print_hdr(struct ubl_header *ubl_hdr) | 63 | static void print_hdr(struct ubl_header *ubl_hdr) |
67 | { | 64 | { |
68 | printf("Image Type : Davinci UBL Boot Image\n"); | 65 | printf("Image Type : Davinci UBL Boot Image\n"); |
69 | printf("UBL magic : %08x\n", ubl_hdr->magic); | 66 | printf("UBL magic : %08x\n", ubl_hdr->magic); |
70 | printf("Entry Point: %08x\n", ubl_hdr->entry); | 67 | printf("Entry Point: %08x\n", ubl_hdr->entry); |
71 | printf("nr of pages: %08x\n", ubl_hdr->pages); | 68 | printf("nr of pages: %08x\n", ubl_hdr->pages); |
72 | printf("start block: %08x\n", ubl_hdr->block); | 69 | printf("start block: %08x\n", ubl_hdr->block); |
73 | printf("start page : %08x\n", ubl_hdr->page); | 70 | printf("start page : %08x\n", ubl_hdr->page); |
74 | } | 71 | } |
75 | 72 | ||
76 | static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token, | 73 | static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token, |
77 | char *name, int lineno, int fld, int dcd_len) | 74 | char *name, int lineno, int fld, int dcd_len) |
78 | { | 75 | { |
79 | static int cmd_ver_first = ~0; | 76 | static int cmd_ver_first = ~0; |
80 | 77 | ||
81 | switch (cmd) { | 78 | switch (cmd) { |
82 | case CMD_BOOT_MODE: | 79 | case CMD_BOOT_MODE: |
83 | ublhdr->magic = get_table_entry_id(ublimage_bootops, | 80 | ublhdr->magic = get_table_entry_id(ublimage_bootops, |
84 | "ublimage special boot mode", token); | 81 | "ublimage special boot mode", token); |
85 | if (ublhdr->magic == -1) { | 82 | if (ublhdr->magic == -1) { |
86 | fprintf(stderr, "Error: %s[%d] -Invalid boot mode" | 83 | fprintf(stderr, "Error: %s[%d] -Invalid boot mode" |
87 | "(%s)\n", name, lineno, token); | 84 | "(%s)\n", name, lineno, token); |
88 | exit(EXIT_FAILURE); | 85 | exit(EXIT_FAILURE); |
89 | } | 86 | } |
90 | ublhdr->magic += UBL_MAGIC_BASE; | 87 | ublhdr->magic += UBL_MAGIC_BASE; |
91 | if (unlikely(cmd_ver_first != 1)) | 88 | if (unlikely(cmd_ver_first != 1)) |
92 | cmd_ver_first = 0; | 89 | cmd_ver_first = 0; |
93 | break; | 90 | break; |
94 | case CMD_ENTRY: | 91 | case CMD_ENTRY: |
95 | ublhdr->entry = get_cfg_value(token, name, lineno); | 92 | ublhdr->entry = get_cfg_value(token, name, lineno); |
96 | break; | 93 | break; |
97 | case CMD_PAGE: | 94 | case CMD_PAGE: |
98 | ublhdr->pages = get_cfg_value(token, name, lineno); | 95 | ublhdr->pages = get_cfg_value(token, name, lineno); |
99 | break; | 96 | break; |
100 | case CMD_ST_BLOCK: | 97 | case CMD_ST_BLOCK: |
101 | ublhdr->block = get_cfg_value(token, name, lineno); | 98 | ublhdr->block = get_cfg_value(token, name, lineno); |
102 | break; | 99 | break; |
103 | case CMD_ST_PAGE: | 100 | case CMD_ST_PAGE: |
104 | ublhdr->page = get_cfg_value(token, name, lineno); | 101 | ublhdr->page = get_cfg_value(token, name, lineno); |
105 | break; | 102 | break; |
106 | case CMD_LD_ADDR: | 103 | case CMD_LD_ADDR: |
107 | ublhdr->pll_m = get_cfg_value(token, name, lineno); | 104 | ublhdr->pll_m = get_cfg_value(token, name, lineno); |
108 | break; | 105 | break; |
109 | } | 106 | } |
110 | } | 107 | } |
111 | 108 | ||
112 | static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd, | 109 | static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd, |
113 | char *token, char *name, int lineno, int fld, int *dcd_len) | 110 | char *token, char *name, int lineno, int fld, int *dcd_len) |
114 | { | 111 | { |
115 | 112 | ||
116 | switch (fld) { | 113 | switch (fld) { |
117 | case CFG_COMMAND: | 114 | case CFG_COMMAND: |
118 | *cmd = get_table_entry_id(ublimage_cmds, | 115 | *cmd = get_table_entry_id(ublimage_cmds, |
119 | "ublimage commands", token); | 116 | "ublimage commands", token); |
120 | if (*cmd < 0) { | 117 | if (*cmd < 0) { |
121 | fprintf(stderr, "Error: %s[%d] - Invalid command" | 118 | fprintf(stderr, "Error: %s[%d] - Invalid command" |
122 | "(%s)\n", name, lineno, token); | 119 | "(%s)\n", name, lineno, token); |
123 | exit(EXIT_FAILURE); | 120 | exit(EXIT_FAILURE); |
124 | } | 121 | } |
125 | break; | 122 | break; |
126 | case CFG_REG_VALUE: | 123 | case CFG_REG_VALUE: |
127 | parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len); | 124 | parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len); |
128 | break; | 125 | break; |
129 | default: | 126 | default: |
130 | break; | 127 | break; |
131 | } | 128 | } |
132 | } | 129 | } |
133 | static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name) | 130 | static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name) |
134 | { | 131 | { |
135 | FILE *fd = NULL; | 132 | FILE *fd = NULL; |
136 | char *line = NULL; | 133 | char *line = NULL; |
137 | char *token, *saveptr1, *saveptr2; | 134 | char *token, *saveptr1, *saveptr2; |
138 | int lineno = 0; | 135 | int lineno = 0; |
139 | int i; | 136 | int i; |
140 | char *ptr = (char *)ublhdr; | 137 | char *ptr = (char *)ublhdr; |
141 | int fld; | 138 | int fld; |
142 | size_t len; | 139 | size_t len; |
143 | int dcd_len = 0; | 140 | int dcd_len = 0; |
144 | int32_t cmd; | 141 | int32_t cmd; |
145 | int ublhdrlen = sizeof(struct ubl_header); | 142 | int ublhdrlen = sizeof(struct ubl_header); |
146 | 143 | ||
147 | fd = fopen(name, "r"); | 144 | fd = fopen(name, "r"); |
148 | if (fd == 0) { | 145 | if (fd == 0) { |
149 | fprintf(stderr, "Error: %s - Can't open DCD file\n", name); | 146 | fprintf(stderr, "Error: %s - Can't open DCD file\n", name); |
150 | exit(EXIT_FAILURE); | 147 | exit(EXIT_FAILURE); |
151 | } | 148 | } |
152 | 149 | ||
153 | /* Fill header with 0xff */ | 150 | /* Fill header with 0xff */ |
154 | for (i = 0; i < ublhdrlen; i++) { | 151 | for (i = 0; i < ublhdrlen; i++) { |
155 | *ptr = 0xff; | 152 | *ptr = 0xff; |
156 | ptr++; | 153 | ptr++; |
157 | } | 154 | } |
158 | 155 | ||
159 | /* | 156 | /* |
160 | * Very simple parsing, line starting with # are comments | 157 | * Very simple parsing, line starting with # are comments |
161 | * and are dropped | 158 | * and are dropped |
162 | */ | 159 | */ |
163 | while ((getline(&line, &len, fd)) > 0) { | 160 | while ((getline(&line, &len, fd)) > 0) { |
164 | lineno++; | 161 | lineno++; |
165 | 162 | ||
166 | token = strtok_r(line, "\r\n", &saveptr1); | 163 | token = strtok_r(line, "\r\n", &saveptr1); |
167 | if (token == NULL) | 164 | if (token == NULL) |
168 | continue; | 165 | continue; |
169 | 166 | ||
170 | /* Check inside the single line */ | 167 | /* Check inside the single line */ |
171 | for (fld = CFG_COMMAND, cmd = CMD_INVALID, | 168 | for (fld = CFG_COMMAND, cmd = CMD_INVALID, |
172 | line = token; ; line = NULL, fld++) { | 169 | line = token; ; line = NULL, fld++) { |
173 | token = strtok_r(line, " \t", &saveptr2); | 170 | token = strtok_r(line, " \t", &saveptr2); |
174 | if (token == NULL) | 171 | if (token == NULL) |
175 | break; | 172 | break; |
176 | 173 | ||
177 | /* Drop all text starting with '#' as comments */ | 174 | /* Drop all text starting with '#' as comments */ |
178 | if (token[0] == '#') | 175 | if (token[0] == '#') |
179 | break; | 176 | break; |
180 | 177 | ||
181 | parse_cfg_fld(ublhdr, &cmd, token, name, | 178 | parse_cfg_fld(ublhdr, &cmd, token, name, |
182 | lineno, fld, &dcd_len); | 179 | lineno, fld, &dcd_len); |
183 | } | 180 | } |
184 | } | 181 | } |
185 | fclose(fd); | 182 | fclose(fd); |
186 | 183 | ||
187 | return dcd_len; | 184 | return dcd_len; |
188 | } | 185 | } |
189 | 186 | ||
190 | static int ublimage_check_image_types(uint8_t type) | 187 | static int ublimage_check_image_types(uint8_t type) |
191 | { | 188 | { |
192 | if (type == IH_TYPE_UBLIMAGE) | 189 | if (type == IH_TYPE_UBLIMAGE) |
193 | return EXIT_SUCCESS; | 190 | return EXIT_SUCCESS; |
194 | else | 191 | else |
195 | return EXIT_FAILURE; | 192 | return EXIT_FAILURE; |
196 | } | 193 | } |
197 | 194 | ||
198 | static int ublimage_verify_header(unsigned char *ptr, int image_size, | 195 | static int ublimage_verify_header(unsigned char *ptr, int image_size, |
199 | struct mkimage_params *params) | 196 | struct mkimage_params *params) |
200 | { | 197 | { |
201 | struct ubl_header *ubl_hdr = (struct ubl_header *)ptr; | 198 | struct ubl_header *ubl_hdr = (struct ubl_header *)ptr; |
202 | 199 | ||
203 | if ((ubl_hdr->magic & 0xFFFFFF00) != UBL_MAGIC_BASE) | 200 | if ((ubl_hdr->magic & 0xFFFFFF00) != UBL_MAGIC_BASE) |
204 | return -1; | 201 | return -1; |
205 | 202 | ||
206 | return 0; | 203 | return 0; |
207 | } | 204 | } |
208 | 205 | ||
209 | static void ublimage_print_header(const void *ptr) | 206 | static void ublimage_print_header(const void *ptr) |
210 | { | 207 | { |
211 | struct ubl_header *ubl_hdr = (struct ubl_header *) ptr; | 208 | struct ubl_header *ubl_hdr = (struct ubl_header *) ptr; |
212 | 209 | ||
213 | print_hdr(ubl_hdr); | 210 | print_hdr(ubl_hdr); |
214 | } | 211 | } |
215 | 212 | ||
216 | static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd, | 213 | static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd, |
217 | struct mkimage_params *params) | 214 | struct mkimage_params *params) |
218 | { | 215 | { |
219 | struct ubl_header *ublhdr = (struct ubl_header *)ptr; | 216 | struct ubl_header *ublhdr = (struct ubl_header *)ptr; |
220 | 217 | ||
221 | /* Parse configuration file */ | 218 | /* Parse configuration file */ |
222 | parse_cfg_file(ublhdr, params->imagename); | 219 | parse_cfg_file(ublhdr, params->imagename); |
223 | } | 220 | } |
224 | 221 | ||
225 | int ublimage_check_params(struct mkimage_params *params) | 222 | int ublimage_check_params(struct mkimage_params *params) |
226 | { | 223 | { |
227 | if (!params) | 224 | if (!params) |
228 | return CFG_INVALID; | 225 | return CFG_INVALID; |
229 | if (!strlen(params->imagename)) { | 226 | if (!strlen(params->imagename)) { |
230 | fprintf(stderr, "Error: %s - Configuration file not" | 227 | fprintf(stderr, "Error: %s - Configuration file not" |
231 | "specified, it is needed for ublimage generation\n", | 228 | "specified, it is needed for ublimage generation\n", |
232 | params->cmdname); | 229 | params->cmdname); |
233 | return CFG_INVALID; | 230 | return CFG_INVALID; |
234 | } | 231 | } |
235 | /* | 232 | /* |
236 | * Check parameters: | 233 | * Check parameters: |
237 | * XIP is not allowed and verify that incompatible | 234 | * XIP is not allowed and verify that incompatible |
238 | * parameters are not sent at the same time | 235 | * parameters are not sent at the same time |
239 | * For example, if list is required a data image must not be provided | 236 | * For example, if list is required a data image must not be provided |
240 | */ | 237 | */ |
241 | return (params->dflag && (params->fflag || params->lflag)) || | 238 | return (params->dflag && (params->fflag || params->lflag)) || |
242 | (params->fflag && (params->dflag || params->lflag)) || | 239 | (params->fflag && (params->dflag || params->lflag)) || |
243 | (params->lflag && (params->dflag || params->fflag)) || | 240 | (params->lflag && (params->dflag || params->fflag)) || |
244 | (params->xflag) || !(strlen(params->imagename)); | 241 | (params->xflag) || !(strlen(params->imagename)); |
245 | } | 242 | } |
246 | 243 | ||
247 | /* | 244 | /* |
248 | * ublimage parameters | 245 | * ublimage parameters |
249 | */ | 246 | */ |
250 | static struct image_type_params ublimage_params = { | 247 | static struct image_type_params ublimage_params = { |
251 | .name = "Davinci UBL boot support", | 248 | .name = "Davinci UBL boot support", |
252 | .header_size = sizeof(struct ubl_header), | 249 | .header_size = sizeof(struct ubl_header), |
253 | .hdr = (void *)&ublimage_header, | 250 | .hdr = (void *)&ublimage_header, |
254 | .check_image_type = ublimage_check_image_types, | 251 | .check_image_type = ublimage_check_image_types, |
255 | .verify_header = ublimage_verify_header, | 252 | .verify_header = ublimage_verify_header, |
256 | .print_header = ublimage_print_header, | 253 | .print_header = ublimage_print_header, |
257 | .set_header = ublimage_set_header, | 254 | .set_header = ublimage_set_header, |
258 | .check_params = ublimage_check_params, | 255 | .check_params = ublimage_check_params, |
259 | }; | 256 | }; |
260 | 257 | ||
261 | void init_ubl_image_type(void) | 258 | void init_ubl_image_type(void) |
262 | { | 259 | { |
263 | mkimage_register(&ublimage_params); | 260 | mkimage_register(&ublimage_params); |
264 | } | 261 | } |
265 | 262 |