Blame view
common/image.c
33.2 KB
b97a2a0a2
|
1 2 3 4 5 6 |
/* * (C) Copyright 2008 Semihalf * * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * |
1a4596601
|
7 |
* SPDX-License-Identifier: GPL-2.0+ |
b97a2a0a2
|
8 |
*/ |
ceaed2b1e
|
9 |
|
b97a2a0a2
|
10 |
#ifndef USE_HOSTCC |
5ad03eb38
|
11 12 13 14 15 16 17 18 19 20 |
#include <common.h> #include <watchdog.h> #ifdef CONFIG_SHOW_BOOT_PROGRESS #include <status_led.h> #endif #ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif |
95d449ad4
|
21 22 23 |
#ifdef CONFIG_LOGBUFFER #include <logbuff.h> #endif |
2242f5369
|
24 |
#include <rtc.h> |
2242f5369
|
25 |
|
1cf0a8b2f
|
26 |
#include <environment.h> |
5dfb52138
|
27 |
#include <image.h> |
712fbcf38
|
28 |
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) |
fff888a19
|
29 30 |
#include <libfdt.h> #include <fdt_support.h> |
c87796483
|
31 |
#endif |
20a14a42a
|
32 |
#include <u-boot/md5.h> |
2b9912e6a
|
33 |
#include <u-boot/sha1.h> |
a51ec63b8
|
34 |
#include <asm/errno.h> |
35e7b0f17
|
35 |
#include <asm/io.h> |
c87796483
|
36 |
|
b6b0fe646
|
37 |
#ifdef CONFIG_CMD_BDI |
54841ab50
|
38 |
extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); |
b6b0fe646
|
39 40 41 |
#endif DECLARE_GLOBAL_DATA_PTR; |
8a5ea3e61
|
42 |
|
21d29f7f9
|
43 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
712fbcf38
|
44 |
static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, |
d985c8498
|
45 |
int verify); |
21d29f7f9
|
46 |
#endif |
b97a2a0a2
|
47 |
#else |
5ad03eb38
|
48 |
#include "mkimage.h" |
20a14a42a
|
49 |
#include <u-boot/md5.h> |
5dfb52138
|
50 |
#include <time.h> |
b97a2a0a2
|
51 |
#include <image.h> |
5dfb52138
|
52 |
#endif /* !USE_HOSTCC*/ |
b97a2a0a2
|
53 |
|
0ccff500c
|
54 |
#include <u-boot/crc.h> |
13d06981a
|
55 56 57 |
#ifndef CONFIG_SYS_BARGSIZE #define CONFIG_SYS_BARGSIZE 512 #endif |
7edb186fc
|
58 |
static const table_entry_t uimage_arch[] = { |
570abb0ad
|
59 60 61 62 63 64 65 66 67 |
{ IH_ARCH_INVALID, NULL, "Invalid ARCH", }, { IH_ARCH_ALPHA, "alpha", "Alpha", }, { IH_ARCH_ARM, "arm", "ARM", }, { IH_ARCH_I386, "x86", "Intel x86", }, { IH_ARCH_IA64, "ia64", "IA64", }, { IH_ARCH_M68K, "m68k", "M68K", }, { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, { IH_ARCH_MIPS, "mips", "MIPS", }, { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, |
570abb0ad
|
68 |
{ IH_ARCH_NIOS2, "nios2", "NIOS II", }, |
e419e12d0
|
69 |
{ IH_ARCH_PPC, "powerpc", "PowerPC", }, |
570abb0ad
|
70 71 72 73 74 75 76 |
{ IH_ARCH_PPC, "ppc", "PowerPC", }, { IH_ARCH_S390, "s390", "IBM S390", }, { IH_ARCH_SH, "sh", "SuperH", }, { IH_ARCH_SPARC, "sparc", "SPARC", }, { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, { IH_ARCH_AVR32, "avr32", "AVR32", }, |
64d614617
|
77 |
{ IH_ARCH_NDS32, "nds32", "NDS32", }, |
3ddcaccda
|
78 |
{ IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",}, |
35e7b0f17
|
79 |
{ IH_ARCH_SANDBOX, "sandbox", "Sandbox", }, |
0ae765312
|
80 |
{ IH_ARCH_ARM64, "arm64", "AArch64", }, |
bc5d54288
|
81 |
{ IH_ARCH_ARC, "arc", "ARC", }, |
570abb0ad
|
82 83 |
{ -1, "", "", }, }; |
7edb186fc
|
84 |
static const table_entry_t uimage_os[] = { |
570abb0ad
|
85 |
{ IH_OS_INVALID, NULL, "Invalid OS", }, |
570abb0ad
|
86 87 88 89 90 |
{ IH_OS_LINUX, "linux", "Linux", }, #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) { IH_OS_LYNXOS, "lynxos", "LynxOS", }, #endif { IH_OS_NETBSD, "netbsd", "NetBSD", }, |
3df619579
|
91 |
{ IH_OS_OSE, "ose", "Enea OSE", }, |
04d414090
|
92 |
{ IH_OS_PLAN9, "plan9", "Plan 9", }, |
570abb0ad
|
93 94 |
{ IH_OS_RTEMS, "rtems", "RTEMS", }, { IH_OS_U_BOOT, "u-boot", "U-Boot", }, |
68b15e831
|
95 |
{ IH_OS_VXWORKS, "vxworks", "VxWorks", }, |
570abb0ad
|
96 97 |
#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) { IH_OS_QNX, "qnx", "QNX", }, |
570abb0ad
|
98 |
#endif |
f5ed9e390
|
99 100 101 |
#if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC) { IH_OS_INTEGRITY,"integrity", "INTEGRITY", }, #endif |
570abb0ad
|
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
#ifdef USE_HOSTCC { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, { IH_OS_DELL, "dell", "Dell", }, { IH_OS_ESIX, "esix", "Esix", }, { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, { IH_OS_IRIX, "irix", "Irix", }, { IH_OS_NCR, "ncr", "NCR", }, { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, { IH_OS_PSOS, "psos", "pSOS", }, { IH_OS_SCO, "sco", "SCO", }, { IH_OS_SOLARIS, "solaris", "Solaris", }, { IH_OS_SVR4, "svr4", "SVR4", }, #endif { -1, "", "", }, }; |
7edb186fc
|
117 |
static const table_entry_t uimage_type[] = { |
4962e38e9
|
118 |
{ IH_TYPE_AISIMAGE, "aisimage", "Davinci AIS image",}, |
570abb0ad
|
119 120 |
{ IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, |
3decb14ab
|
121 |
{ IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, |
bf411ea9f
|
122 |
{ IH_TYPE_GPIMAGE, "gpimage", "TI Keystone SPL Image",}, |
570abb0ad
|
123 |
{ IH_TYPE_KERNEL, "kernel", "Kernel Image", }, |
b9b50e89d
|
124 |
{ IH_TYPE_KERNEL_NOLOAD, "kernel_noload", "Kernel Image (no loading done)", }, |
4962e38e9
|
125 126 127 |
{ IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, { IH_TYPE_INVALID, NULL, "Invalid Image", }, |
570abb0ad
|
128 |
{ IH_TYPE_MULTI, "multi", "Multi-File Image", }, |
4962e38e9
|
129 |
{ IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, |
5d898a00f
|
130 |
{ IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, |
570abb0ad
|
131 132 |
{ IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", }, |
832472a94
|
133 |
{ IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SOCFPGA preloader",}, |
570abb0ad
|
134 |
{ IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, |
7816f2cf8
|
135 |
{ IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",}, |
bce883707
|
136 |
{ IH_TYPE_MXSIMAGE, "mxsimage", "Freescale MXS Boot Image",}, |
7b1a41174
|
137 |
{ IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",}, |
570abb0ad
|
138 139 |
{ -1, "", "", }, }; |
7edb186fc
|
140 |
static const table_entry_t uimage_comp[] = { |
570abb0ad
|
141 142 143 |
{ IH_COMP_NONE, "none", "uncompressed", }, { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, { IH_COMP_GZIP, "gzip", "gzip compressed", }, |
fc9c1727b
|
144 |
{ IH_COMP_LZMA, "lzma", "lzma compressed", }, |
20dde48bc
|
145 |
{ IH_COMP_LZO, "lzo", "lzo compressed", }, |
570abb0ad
|
146 147 |
{ -1, "", "", }, }; |
9a4daad0a
|
148 149 150 |
/*****************************************************************************/ /* Legacy format routines */ /*****************************************************************************/ |
712fbcf38
|
151 |
int image_check_hcrc(const image_header_t *hdr) |
b97a2a0a2
|
152 153 |
{ ulong hcrc; |
712fbcf38
|
154 |
ulong len = image_get_header_size(); |
b97a2a0a2
|
155 156 157 |
image_header_t header; /* Copy header so we can blank CRC field for re-calculation */ |
712fbcf38
|
158 159 |
memmove(&header, (char *)hdr, image_get_header_size()); image_set_hcrc(&header, 0); |
b97a2a0a2
|
160 |
|
712fbcf38
|
161 |
hcrc = crc32(0, (unsigned char *)&header, len); |
b97a2a0a2
|
162 |
|
712fbcf38
|
163 |
return (hcrc == image_get_hcrc(hdr)); |
b97a2a0a2
|
164 |
} |
712fbcf38
|
165 |
int image_check_dcrc(const image_header_t *hdr) |
b97a2a0a2
|
166 |
{ |
712fbcf38
|
167 168 169 |
ulong data = image_get_data(hdr); ulong len = image_get_data_size(hdr); ulong dcrc = crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32); |
b97a2a0a2
|
170 |
|
712fbcf38
|
171 |
return (dcrc == image_get_dcrc(hdr)); |
b97a2a0a2
|
172 |
} |
f13e7b2e9
|
173 174 175 176 177 178 179 180 181 182 183 184 185 |
/** * image_multi_count - get component (sub-image) count * @hdr: pointer to the header of the multi component image * * image_multi_count() returns number of components in a multi * component image. * * Note: no checking of the image type is done, caller must pass * a valid multi component image. * * returns: * number of components */ |
712fbcf38
|
186 |
ulong image_multi_count(const image_header_t *hdr) |
f13e7b2e9
|
187 188 |
{ ulong i, count = 0; |
df6f1b895
|
189 |
uint32_t *size; |
f13e7b2e9
|
190 191 192 |
/* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ |
712fbcf38
|
193 |
size = (uint32_t *)image_get_data(hdr); |
f13e7b2e9
|
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
/* count non empty slots */ for (i = 0; size[i]; ++i) count++; return count; } /** * image_multi_getimg - get component data address and size * @hdr: pointer to the header of the multi component image * @idx: index of the requested component * @data: pointer to a ulong variable, will hold component data address * @len: pointer to a ulong variable, will hold component size * * image_multi_getimg() returns size and data address for the requested * component in a multi component image. * * Note: no checking of the image type is done, caller must pass * a valid multi component image. * * returns: * data address and size of the component, if idx is valid * 0 in data and len, if idx is out of range */ |
712fbcf38
|
219 |
void image_multi_getimg(const image_header_t *hdr, ulong idx, |
f13e7b2e9
|
220 221 222 |
ulong *data, ulong *len) { int i; |
df6f1b895
|
223 |
uint32_t *size; |
02b9b2244
|
224 |
ulong offset, count, img_data; |
f13e7b2e9
|
225 226 |
/* get number of component */ |
712fbcf38
|
227 |
count = image_multi_count(hdr); |
f13e7b2e9
|
228 229 230 |
/* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ |
712fbcf38
|
231 |
size = (uint32_t *)image_get_data(hdr); |
f13e7b2e9
|
232 233 234 |
/* get address of the proper component data start, which means * skipping sizes table (add 1 for last, null entry) */ |
712fbcf38
|
235 |
img_data = image_get_data(hdr) + (count + 1) * sizeof(uint32_t); |
f13e7b2e9
|
236 237 |
if (idx < count) { |
712fbcf38
|
238 |
*len = uimage_to_cpu(size[idx]); |
f13e7b2e9
|
239 |
offset = 0; |
f13e7b2e9
|
240 241 242 |
/* go over all indices preceding requested component idx */ for (i = 0; i < idx; i++) { |
02b9b2244
|
243 |
/* add up i-th component size, rounding up to 4 bytes */ |
712fbcf38
|
244 |
offset += (uimage_to_cpu(size[i]) + 3) & ~3 ; |
f13e7b2e9
|
245 246 247 |
} /* calculate idx-th component data address */ |
02b9b2244
|
248 |
*data = img_data + offset; |
f13e7b2e9
|
249 250 251 252 253 |
} else { *len = 0; *data = 0; } } |
42b73e8ee
|
254 |
|
712fbcf38
|
255 |
static void image_print_type(const image_header_t *hdr) |
9a4daad0a
|
256 257 |
{ const char *os, *arch, *type, *comp; |
712fbcf38
|
258 259 260 261 |
os = genimg_get_os_name(image_get_os(hdr)); arch = genimg_get_arch_name(image_get_arch(hdr)); type = genimg_get_type_name(image_get_type(hdr)); comp = genimg_get_comp_name(image_get_comp(hdr)); |
9a4daad0a
|
262 |
|
712fbcf38
|
263 264 |
printf("%s %s %s (%s) ", arch, os, type, comp); |
9a4daad0a
|
265 |
} |
5dfb52138
|
266 |
/** |
edbed247a
|
267 |
* image_print_contents - prints out the contents of the legacy format image |
3a2003f61
|
268 |
* @ptr: pointer to the legacy format image header |
5dfb52138
|
269 270 |
* @p: pointer to prefix string * |
edbed247a
|
271 |
* image_print_contents() formats a multi line legacy image contents description. |
5dfb52138
|
272 273 274 275 276 277 |
* The routine prints out all header fields followed by the size/offset data * for MULTI/SCRIPT images. * * returns: * no returned results */ |
712fbcf38
|
278 |
void image_print_contents(const void *ptr) |
9a4daad0a
|
279 |
{ |
3a2003f61
|
280 |
const image_header_t *hdr = (const image_header_t *)ptr; |
edbed247a
|
281 |
const char *p; |
1fe7d9389
|
282 |
p = IMAGE_INDENT_STRING; |
712fbcf38
|
283 284 |
printf("%sImage Name: %.*s ", p, IH_NMLEN, image_get_name(hdr)); |
859e92b77
|
285 286 287 288 |
if (IMAGE_ENABLE_TIMESTAMP) { printf("%sCreated: ", p); genimg_print_time((time_t)image_get_time(hdr)); } |
712fbcf38
|
289 290 291 292 293 294 295 296 297 298 299 |
printf("%sImage Type: ", p); image_print_type(hdr); printf("%sData Size: ", p); genimg_print_size(image_get_data_size(hdr)); printf("%sLoad Address: %08x ", p, image_get_load(hdr)); printf("%sEntry Point: %08x ", p, image_get_ep(hdr)); if (image_check_type(hdr, IH_TYPE_MULTI) || image_check_type(hdr, IH_TYPE_SCRIPT)) { |
9a4daad0a
|
300 301 |
int i; ulong data, len; |
712fbcf38
|
302 |
ulong count = image_multi_count(hdr); |
9a4daad0a
|
303 |
|
712fbcf38
|
304 305 |
printf("%sContents: ", p); |
9a4daad0a
|
306 |
for (i = 0; i < count; i++) { |
712fbcf38
|
307 |
image_multi_getimg(hdr, i, &data, &len); |
570abb0ad
|
308 |
|
712fbcf38
|
309 310 |
printf("%s Image %d: ", p, i); genimg_print_size(len); |
570abb0ad
|
311 |
|
712fbcf38
|
312 |
if (image_check_type(hdr, IH_TYPE_SCRIPT) && i > 0) { |
570abb0ad
|
313 314 315 316 317 |
/* * the user may need to know offsets * if planning to do something with * multiple files */ |
712fbcf38
|
318 319 |
printf("%s Offset = 0x%08lx ", p, data); |
570abb0ad
|
320 |
} |
9a4daad0a
|
321 322 323 |
} } } |
570abb0ad
|
324 325 |
#ifndef USE_HOSTCC |
21d29f7f9
|
326 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
9a4daad0a
|
327 328 |
/** * image_get_ramdisk - get and verify ramdisk image |
9a4daad0a
|
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
* @rd_addr: ramdisk image start address * @arch: expected ramdisk architecture * @verify: checksum verification flag * * image_get_ramdisk() returns a pointer to the verified ramdisk image * header. Routine receives image start address and expected architecture * flag. Verification done covers data and header integrity and os/type/arch * fields checking. * * If dataflash support is enabled routine checks for dataflash addresses * and handles required dataflash reads. * * returns: * pointer to a ramdisk image header, if image was found and valid * otherwise, return NULL */ |
712fbcf38
|
345 |
static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, |
d985c8498
|
346 |
int verify) |
9a4daad0a
|
347 |
{ |
3a2003f61
|
348 |
const image_header_t *rd_hdr = (const image_header_t *)rd_addr; |
9a4daad0a
|
349 |
|
712fbcf38
|
350 351 352 |
if (!image_check_magic(rd_hdr)) { puts("Bad Magic Number "); |
770605e4f
|
353 |
bootstage_error(BOOTSTAGE_ID_RD_MAGIC); |
9a4daad0a
|
354 355 |
return NULL; } |
712fbcf38
|
356 357 358 |
if (!image_check_hcrc(rd_hdr)) { puts("Bad Header Checksum "); |
770605e4f
|
359 |
bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM); |
9a4daad0a
|
360 361 |
return NULL; } |
770605e4f
|
362 |
bootstage_mark(BOOTSTAGE_ID_RD_MAGIC); |
712fbcf38
|
363 |
image_print_contents(rd_hdr); |
9a4daad0a
|
364 365 366 |
if (verify) { puts(" Verifying Checksum ... "); |
712fbcf38
|
367 368 369 |
if (!image_check_dcrc(rd_hdr)) { puts("Bad Data CRC "); |
770605e4f
|
370 |
bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM); |
9a4daad0a
|
371 372 373 374 375 |
return NULL; } puts("OK "); } |
770605e4f
|
376 |
bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM); |
9a4daad0a
|
377 |
|
712fbcf38
|
378 379 380 381 382 |
if (!image_check_os(rd_hdr, IH_OS_LINUX) || !image_check_arch(rd_hdr, arch) || !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { printf("No Linux %s Ramdisk Image ", |
9a4daad0a
|
383 |
genimg_get_arch_name(arch)); |
770605e4f
|
384 |
bootstage_error(BOOTSTAGE_ID_RAMDISK); |
9a4daad0a
|
385 386 387 388 389 |
return NULL; } return rd_hdr; } |
21d29f7f9
|
390 |
#endif |
570abb0ad
|
391 |
#endif /* !USE_HOSTCC */ |
9a4daad0a
|
392 393 394 395 |
/*****************************************************************************/ /* Shared dual-format routines */ /*****************************************************************************/ |
570abb0ad
|
396 |
#ifndef USE_HOSTCC |
1cf0a8b2f
|
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ ulong save_addr; /* Default Save Address */ ulong save_size; /* Default Save Size (in bytes) */ static int on_loadaddr(const char *name, const char *value, enum env_op op, int flags) { switch (op) { case env_op_create: case env_op_overwrite: load_addr = simple_strtoul(value, NULL, 16); break; default: break; } return 0; } U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); |
9a4daad0a
|
416 417 |
ulong getenv_bootm_low(void) { |
712fbcf38
|
418 |
char *s = getenv("bootm_low"); |
9a4daad0a
|
419 |
if (s) { |
712fbcf38
|
420 |
ulong tmp = simple_strtoul(s, NULL, 16); |
9a4daad0a
|
421 422 |
return tmp; } |
6d0f6bcf3
|
423 424 |
#if defined(CONFIG_SYS_SDRAM_BASE) return CONFIG_SYS_SDRAM_BASE; |
afe45c87e
|
425 426 |
#elif defined(CONFIG_ARM) return gd->bd->bi_dram[0].start; |
9a4daad0a
|
427 428 429 430 |
#else return 0; #endif } |
391fd93ab
|
431 |
phys_size_t getenv_bootm_size(void) |
9a4daad0a
|
432 |
{ |
c519facc6
|
433 |
phys_size_t tmp; |
712fbcf38
|
434 |
char *s = getenv("bootm_size"); |
9a4daad0a
|
435 |
if (s) { |
712fbcf38
|
436 |
tmp = (phys_size_t)simple_strtoull(s, NULL, 16); |
9a4daad0a
|
437 438 |
return tmp; } |
c519facc6
|
439 440 |
s = getenv("bootm_low"); if (s) |
712fbcf38
|
441 |
tmp = (phys_size_t)simple_strtoull(s, NULL, 16); |
c519facc6
|
442 443 |
else tmp = 0; |
9a4daad0a
|
444 |
|
afe45c87e
|
445 |
#if defined(CONFIG_ARM) |
c519facc6
|
446 |
return gd->bd->bi_dram[0].size - tmp; |
afe45c87e
|
447 |
#else |
c519facc6
|
448 |
return gd->bd->bi_memsize - tmp; |
afe45c87e
|
449 |
#endif |
9a4daad0a
|
450 |
} |
c3624e6ed
|
451 452 453 |
phys_size_t getenv_bootm_mapsize(void) { phys_size_t tmp; |
712fbcf38
|
454 |
char *s = getenv("bootm_mapsize"); |
c3624e6ed
|
455 |
if (s) { |
712fbcf38
|
456 |
tmp = (phys_size_t)simple_strtoull(s, NULL, 16); |
c3624e6ed
|
457 458 459 460 461 462 463 464 465 |
return tmp; } #if defined(CONFIG_SYS_BOOTMAPSZ) return CONFIG_SYS_BOOTMAPSZ; #else return getenv_bootm_size(); #endif } |
712fbcf38
|
466 |
void memmove_wd(void *to, void *from, size_t len, ulong chunksz) |
9a4daad0a
|
467 |
{ |
54fa2c5b5
|
468 469 |
if (to == from) return; |
9a4daad0a
|
470 471 472 |
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) while (len > 0) { size_t tail = (len > chunksz) ? chunksz : len; |
712fbcf38
|
473 474 |
WATCHDOG_RESET(); memmove(to, from, tail); |
9a4daad0a
|
475 476 477 478 479 |
to += tail; from += tail; len -= tail; } #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ |
712fbcf38
|
480 |
memmove(to, from, len); |
9a4daad0a
|
481 482 |
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ } |
570abb0ad
|
483 |
#endif /* !USE_HOSTCC */ |
9a4daad0a
|
484 |
|
712fbcf38
|
485 |
void genimg_print_size(uint32_t size) |
42b73e8ee
|
486 |
{ |
570abb0ad
|
487 |
#ifndef USE_HOSTCC |
712fbcf38
|
488 489 490 |
printf("%d Bytes = ", size); print_size(size, " "); |
570abb0ad
|
491 |
#else |
712fbcf38
|
492 493 |
printf("%d Bytes = %.2f kB = %.2f MB ", |
570abb0ad
|
494 495 |
size, (double)size / 1.024e3, (double)size / 1.048576e6); |
42b73e8ee
|
496 |
#endif |
570abb0ad
|
497 |
} |
859e92b77
|
498 499 |
#if IMAGE_ENABLE_TIMESTAMP void genimg_print_time(time_t timestamp) |
570abb0ad
|
500 501 502 |
{ #ifndef USE_HOSTCC struct rtc_time tm; |
712fbcf38
|
503 504 505 |
to_tm(timestamp, &tm); printf("%4d-%02d-%02d %2d:%02d:%02d UTC ", |
570abb0ad
|
506 507 508 |
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); #else |
712fbcf38
|
509 |
printf("%s", ctime(×tamp)); |
42b73e8ee
|
510 |
#endif |
570abb0ad
|
511 |
} |
859e92b77
|
512 |
#endif |
42b73e8ee
|
513 |
|
570abb0ad
|
514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
/** * get_table_entry_name - translate entry id to long name * @table: pointer to a translation table for entries of a specific type * @msg: message to be returned when translation fails * @id: entry id to be translated * * get_table_entry_name() will go over translation table trying to find * entry that matches given id. If matching entry is found, its long * name is returned to the caller. * * returns: * long entry name if translation succeeds * msg otherwise */ |
7edb186fc
|
528 |
char *get_table_entry_name(const table_entry_t *table, char *msg, int id) |
570abb0ad
|
529 530 531 |
{ for (; table->id >= 0; ++table) { if (table->id == id) |
2e5167cca
|
532 |
#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) |
e3d1ac7bb
|
533 534 535 536 |
return table->lname; #else return table->lname + gd->reloc_off; #endif |
42b73e8ee
|
537 |
} |
570abb0ad
|
538 539 |
return (msg); } |
42b73e8ee
|
540 |
|
712fbcf38
|
541 |
const char *genimg_get_os_name(uint8_t os) |
570abb0ad
|
542 |
{ |
712fbcf38
|
543 |
return (get_table_entry_name(uimage_os, "Unknown OS", os)); |
42b73e8ee
|
544 |
} |
712fbcf38
|
545 |
const char *genimg_get_arch_name(uint8_t arch) |
42b73e8ee
|
546 |
{ |
712fbcf38
|
547 548 |
return (get_table_entry_name(uimage_arch, "Unknown Architecture", arch)); |
570abb0ad
|
549 |
} |
42b73e8ee
|
550 |
|
712fbcf38
|
551 |
const char *genimg_get_type_name(uint8_t type) |
570abb0ad
|
552 |
{ |
712fbcf38
|
553 |
return (get_table_entry_name(uimage_type, "Unknown Image", type)); |
570abb0ad
|
554 |
} |
42b73e8ee
|
555 |
|
712fbcf38
|
556 |
const char *genimg_get_comp_name(uint8_t comp) |
570abb0ad
|
557 |
{ |
712fbcf38
|
558 559 |
return (get_table_entry_name(uimage_comp, "Unknown Compression", comp)); |
42b73e8ee
|
560 |
} |
570abb0ad
|
561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
/** * get_table_entry_id - translate short entry name to id * @table: pointer to a translation table for entries of a specific type * @table_name: to be used in case of error * @name: entry short name to be translated * * get_table_entry_id() will go over translation table trying to find * entry that matches given short name. If matching entry is found, * its id returned to the caller. * * returns: * entry id if translation succeeds * -1 otherwise */ |
7edb186fc
|
575 |
int get_table_entry_id(const table_entry_t *table, |
570abb0ad
|
576 |
const char *table_name, const char *name) |
42b73e8ee
|
577 |
{ |
7edb186fc
|
578 |
const table_entry_t *t; |
570abb0ad
|
579 580 |
#ifdef USE_HOSTCC int first = 1; |
42b73e8ee
|
581 |
|
570abb0ad
|
582 583 |
for (t = table; t->id >= 0; ++t) { if (t->sname && strcasecmp(t->sname, name) == 0) |
712fbcf38
|
584 |
return(t->id); |
42b73e8ee
|
585 |
} |
712fbcf38
|
586 587 |
fprintf(stderr, " Invalid %s Type - valid names are", table_name); |
570abb0ad
|
588 589 590 |
for (t = table; t->id >= 0; ++t) { if (t->sname == NULL) continue; |
712fbcf38
|
591 |
fprintf(stderr, "%c %s", (first) ? ':' : ',', t->sname); |
570abb0ad
|
592 593 |
first = 0; } |
712fbcf38
|
594 595 |
fprintf(stderr, " "); |
570abb0ad
|
596 597 |
#else for (t = table; t->id >= 0; ++t) { |
2e5167cca
|
598 |
#ifdef CONFIG_NEEDS_MANUAL_RELOC |
e3d1ac7bb
|
599 |
if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0) |
2e5167cca
|
600 601 |
#else if (t->sname && strcmp(t->sname, name) == 0) |
521af04d8
|
602 |
#endif |
570abb0ad
|
603 604 |
return (t->id); } |
712fbcf38
|
605 606 |
debug("Invalid %s Type: %s ", table_name, name); |
570abb0ad
|
607 608 609 |
#endif /* USE_HOSTCC */ return (-1); } |
712fbcf38
|
610 |
int genimg_get_os_id(const char *name) |
570abb0ad
|
611 |
{ |
712fbcf38
|
612 |
return (get_table_entry_id(uimage_os, "OS", name)); |
570abb0ad
|
613 |
} |
712fbcf38
|
614 |
int genimg_get_arch_id(const char *name) |
570abb0ad
|
615 |
{ |
712fbcf38
|
616 |
return (get_table_entry_id(uimage_arch, "CPU", name)); |
42b73e8ee
|
617 |
} |
5ad03eb38
|
618 |
|
712fbcf38
|
619 |
int genimg_get_type_id(const char *name) |
570abb0ad
|
620 |
{ |
712fbcf38
|
621 |
return (get_table_entry_id(uimage_type, "Image", name)); |
570abb0ad
|
622 |
} |
712fbcf38
|
623 |
int genimg_get_comp_id(const char *name) |
570abb0ad
|
624 |
{ |
712fbcf38
|
625 |
return (get_table_entry_id(uimage_comp, "Compression", name)); |
570abb0ad
|
626 627 628 |
} #ifndef USE_HOSTCC |
5ad03eb38
|
629 |
/** |
6c454fedf
|
630 631 |
* genimg_get_kernel_addr_fit - get the real kernel address and return 2 * FIT strings |
0f64140b6
|
632 |
* @img_addr: a string might contain real image address |
6c454fedf
|
633 634 635 636 |
* @fit_uname_config: double pointer to a char, will hold pointer to a * configuration unit name * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage * name |
0f64140b6
|
637 |
* |
6c454fedf
|
638 |
* genimg_get_kernel_addr_fit get the real kernel start address from a string |
0f64140b6
|
639 640 641 642 643 |
* which is normally the first argv of bootm/bootz * * returns: * kernel start address */ |
6c454fedf
|
644 645 646 |
ulong genimg_get_kernel_addr_fit(char * const img_addr, const char **fit_uname_config, const char **fit_uname_kernel) |
0f64140b6
|
647 |
{ |
0f64140b6
|
648 649 650 651 652 653 654 655 656 657 |
ulong kernel_addr; /* find out kernel image address */ if (!img_addr) { kernel_addr = load_addr; debug("* kernel: default image load address = 0x%08lx ", load_addr); #if defined(CONFIG_FIT) } else if (fit_parse_conf(img_addr, load_addr, &kernel_addr, |
6c454fedf
|
658 |
fit_uname_config)) { |
0f64140b6
|
659 660 |
debug("* kernel: config '%s' from image at 0x%08lx ", |
6c454fedf
|
661 |
*fit_uname_config, kernel_addr); |
0f64140b6
|
662 |
} else if (fit_parse_subimage(img_addr, load_addr, &kernel_addr, |
6c454fedf
|
663 |
fit_uname_kernel)) { |
0f64140b6
|
664 665 |
debug("* kernel: subimage '%s' from image at 0x%08lx ", |
6c454fedf
|
666 |
*fit_uname_kernel, kernel_addr); |
0f64140b6
|
667 668 669 670 671 672 673 674 675 676 677 678 |
#endif } else { kernel_addr = simple_strtoul(img_addr, NULL, 16); debug("* kernel: cmdline image address = 0x%08lx ", kernel_addr); } return kernel_addr; } /** |
6c454fedf
|
679 680 681 682 683 684 685 686 687 688 689 690 691 |
* genimg_get_kernel_addr() is the simple version of * genimg_get_kernel_addr_fit(). It ignores those return FIT strings */ ulong genimg_get_kernel_addr(char * const img_addr) { const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config, &fit_uname_kernel); } /** |
9a4daad0a
|
692 |
* genimg_get_format - get image format type |
fff888a19
|
693 694 |
* @img_addr: image start address * |
9a4daad0a
|
695 |
* genimg_get_format() checks whether provided address points to a valid |
fff888a19
|
696 697 |
* legacy or FIT image. * |
4efbe9dbb
|
698 699 |
* New uImage format and FDT blob are based on a libfdt. FDT blob * may be passed directly or embedded in a FIT image. In both situations |
9a4daad0a
|
700 |
* genimg_get_format() must be able to dectect libfdt header. |
4efbe9dbb
|
701 |
* |
fff888a19
|
702 703 704 |
* returns: * image format type or IMAGE_FORMAT_INVALID if no image is present */ |
35e7b0f17
|
705 |
int genimg_get_format(const void *img_addr) |
fff888a19
|
706 |
{ |
21d29f7f9
|
707 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
3a2003f61
|
708 |
const image_header_t *hdr; |
fff888a19
|
709 |
|
3a2003f61
|
710 |
hdr = (const image_header_t *)img_addr; |
fff888a19
|
711 |
if (image_check_magic(hdr)) |
21d29f7f9
|
712 713 |
return IMAGE_FORMAT_LEGACY; #endif |
4efbe9dbb
|
714 |
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) |
21d29f7f9
|
715 716 |
if (fdt_check_header(img_addr) == 0) return IMAGE_FORMAT_FIT; |
9ace3fc81
|
717 718 |
#endif #ifdef CONFIG_ANDROID_BOOT_IMAGE |
21d29f7f9
|
719 720 |
if (android_image_check_header(img_addr) == 0) return IMAGE_FORMAT_ANDROID; |
fff888a19
|
721 |
#endif |
21d29f7f9
|
722 |
return IMAGE_FORMAT_INVALID; |
fff888a19
|
723 724 725 |
} /** |
9a4daad0a
|
726 |
* genimg_get_image - get image from special storage (if necessary) |
fff888a19
|
727 728 |
* @img_addr: image start address * |
9a4daad0a
|
729 |
* genimg_get_image() checks if provided image start adddress is located |
fff888a19
|
730 731 732 733 734 |
* in a dataflash storage. If so, image is moved to a system RAM memory. * * returns: * image start address after possible relocation from special storage */ |
712fbcf38
|
735 |
ulong genimg_get_image(ulong img_addr) |
fff888a19
|
736 |
{ |
6f0f9dfc4
|
737 |
ulong ram_addr = img_addr; |
fff888a19
|
738 739 |
#ifdef CONFIG_HAS_DATAFLASH |
6f0f9dfc4
|
740 |
ulong h_size, d_size; |
712fbcf38
|
741 |
if (addr_dataflash(img_addr)) { |
35e7b0f17
|
742 |
void *buf; |
6f0f9dfc4
|
743 |
/* ger RAM address */ |
6d0f6bcf3
|
744 |
ram_addr = CONFIG_SYS_LOAD_ADDR; |
6f0f9dfc4
|
745 746 |
/* get header size */ |
712fbcf38
|
747 |
h_size = image_get_header_size(); |
6f0f9dfc4
|
748 749 750 751 752 753 |
#if defined(CONFIG_FIT) if (sizeof(struct fdt_header) > h_size) h_size = sizeof(struct fdt_header); #endif /* read in header */ |
712fbcf38
|
754 |
debug(" Reading image header from dataflash address " |
fff888a19
|
755 756 |
"%08lx to RAM address %08lx ", img_addr, ram_addr); |
fff888a19
|
757 |
|
35e7b0f17
|
758 759 |
buf = map_sysmem(ram_addr, 0); read_dataflash(img_addr, h_size, buf); |
fff888a19
|
760 |
|
6f0f9dfc4
|
761 |
/* get data size */ |
35e7b0f17
|
762 |
switch (genimg_get_format(buf)) { |
21d29f7f9
|
763 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
6f0f9dfc4
|
764 |
case IMAGE_FORMAT_LEGACY: |
35e7b0f17
|
765 |
d_size = image_get_data_size(buf); |
712fbcf38
|
766 767 768 |
debug(" Legacy format image found at 0x%08lx, " "size 0x%08lx ", |
6f0f9dfc4
|
769 770 |
ram_addr, d_size); break; |
21d29f7f9
|
771 |
#endif |
fff888a19
|
772 |
#if defined(CONFIG_FIT) |
6f0f9dfc4
|
773 |
case IMAGE_FORMAT_FIT: |
35e7b0f17
|
774 |
d_size = fit_get_size(buf) - h_size; |
712fbcf38
|
775 776 777 |
debug(" FIT/FDT format image found at 0x%08lx, " "size 0x%08lx ", |
6f0f9dfc4
|
778 779 |
ram_addr, d_size); break; |
fff888a19
|
780 |
#endif |
6f0f9dfc4
|
781 |
default: |
712fbcf38
|
782 783 784 |
printf(" No valid image found at 0x%08lx ", img_addr); |
6f0f9dfc4
|
785 786 |
return ram_addr; } |
fff888a19
|
787 |
|
6f0f9dfc4
|
788 |
/* read in image data */ |
712fbcf38
|
789 |
debug(" Reading image remaining data from dataflash address " |
fff888a19
|
790 791 792 |
"%08lx to RAM address %08lx ", img_addr + h_size, ram_addr + h_size); |
712fbcf38
|
793 |
read_dataflash(img_addr + h_size, d_size, |
35e7b0f17
|
794 |
(char *)(buf + h_size)); |
6f0f9dfc4
|
795 |
|
fff888a19
|
796 |
} |
6f0f9dfc4
|
797 |
#endif /* CONFIG_HAS_DATAFLASH */ |
fff888a19
|
798 799 800 801 802 |
return ram_addr; } /** |
f773bea8e
|
803 804 805 806 807 808 809 810 811 812 |
* fit_has_config - check if there is a valid FIT configuration * @images: pointer to the bootm command headers structure * * fit_has_config() checks if there is a FIT configuration in use * (if FTI support is present). * * returns: * 0, no FIT support or no configuration found * 1, configuration found */ |
712fbcf38
|
813 |
int genimg_has_config(bootm_headers_t *images) |
f773bea8e
|
814 815 816 817 818 819 820 821 822 |
{ #if defined(CONFIG_FIT) if (images->fit_uname_cfg) return 1; #endif return 0; } /** |
9a4daad0a
|
823 |
* boot_get_ramdisk - main ramdisk handling routine |
5ad03eb38
|
824 825 |
* @argc: command argument count * @argv: command argument list |
8a5ea3e61
|
826 |
* @images: pointer to the bootm images structure |
5ad03eb38
|
827 828 829 830 |
* @arch: expected ramdisk architecture * @rd_start: pointer to a ulong variable, will hold ramdisk start address * @rd_end: pointer to a ulong variable, will hold ramdisk end * |
9a4daad0a
|
831 |
* boot_get_ramdisk() is responsible for finding a valid ramdisk image. |
5ad03eb38
|
832 833 834 835 836 |
* Curently supported are the following ramdisk sources: * - multicomponent kernel/ramdisk image, * - commandline provided address of decicated ramdisk image. * * returns: |
d985c8498
|
837 |
* 0, if ramdisk image was found and valid, or skiped |
5ad03eb38
|
838 839 |
* rd_start and rd_end are set to ramdisk start/end addresses if * ramdisk image is found and valid |
d985c8498
|
840 |
* |
ea86b9e64
|
841 |
* 1, if ramdisk image is found but corrupted, or invalid |
5ad03eb38
|
842 |
* rd_start and rd_end are set to 0 if no ramdisk exists |
5ad03eb38
|
843 |
*/ |
712fbcf38
|
844 |
int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, |
d985c8498
|
845 |
uint8_t arch, ulong *rd_start, ulong *rd_end) |
5ad03eb38
|
846 |
{ |
d5934ad77
|
847 |
ulong rd_addr, rd_load; |
5ad03eb38
|
848 |
ulong rd_data, rd_len; |
21d29f7f9
|
849 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
3a2003f61
|
850 |
const image_header_t *rd_hdr; |
21d29f7f9
|
851 |
#endif |
35e7b0f17
|
852 |
void *buf; |
57d40ab70
|
853 |
#ifdef CONFIG_SUPPORT_RAW_INITRD |
017e1f3f9
|
854 |
char *end; |
57d40ab70
|
855 |
#endif |
d5934ad77
|
856 |
#if defined(CONFIG_FIT) |
f320a4d84
|
857 |
const char *fit_uname_config = images->fit_uname_cfg; |
d5934ad77
|
858 859 |
const char *fit_uname_ramdisk = NULL; ulong default_addr; |
c87796483
|
860 |
int rd_noffset; |
d5934ad77
|
861 |
#endif |
983c72f47
|
862 |
const char *select = NULL; |
5ad03eb38
|
863 |
|
c87796483
|
864 865 |
*rd_start = 0; *rd_end = 0; |
983c72f47
|
866 867 |
if (argc >= 2) select = argv[1]; |
d5934ad77
|
868 869 870 871 |
/* * Look for a '-' which indicates to ignore the * ramdisk argument */ |
983c72f47
|
872 |
if (select && strcmp(select, "-") == 0) { |
712fbcf38
|
873 874 |
debug("## Skipping init Ramdisk "); |
d5934ad77
|
875 |
rd_len = rd_data = 0; |
983c72f47
|
876 |
} else if (select || genimg_has_config(images)) { |
d5934ad77
|
877 |
#if defined(CONFIG_FIT) |
983c72f47
|
878 |
if (select) { |
f773bea8e
|
879 880 881 882 883 884 885 886 887 888 |
/* * If the init ramdisk comes from the FIT image and * the FIT image address is omitted in the command * line argument, try to use os FIT image address or * default load address. */ if (images->fit_uname_os) default_addr = (ulong)images->fit_hdr_os; else default_addr = load_addr; |
983c72f47
|
889 890 |
if (fit_parse_conf(select, default_addr, &rd_addr, &fit_uname_config)) { |
712fbcf38
|
891 892 893 |
debug("* ramdisk: config '%s' from image at " "0x%08lx ", |
f773bea8e
|
894 |
fit_uname_config, rd_addr); |
983c72f47
|
895 |
} else if (fit_parse_subimage(select, default_addr, |
f773bea8e
|
896 |
&rd_addr, &fit_uname_ramdisk)) { |
712fbcf38
|
897 898 899 |
debug("* ramdisk: subimage '%s' from image at " "0x%08lx ", |
f773bea8e
|
900 901 |
fit_uname_ramdisk, rd_addr); } else |
d5934ad77
|
902 |
#endif |
f773bea8e
|
903 |
{ |
983c72f47
|
904 |
rd_addr = simple_strtoul(select, NULL, 16); |
712fbcf38
|
905 906 907 |
debug("* ramdisk: cmdline image address = " "0x%08lx ", |
f773bea8e
|
908 909 910 911 912 |
rd_addr); } #if defined(CONFIG_FIT) } else { /* use FIT configuration provided in first bootm |
a51ec63b8
|
913 914 |
* command argument. If the property is not defined, * quit silently. |
f773bea8e
|
915 |
*/ |
35e7b0f17
|
916 |
rd_addr = map_to_sysmem(images->fit_hdr_os); |
a51ec63b8
|
917 918 919 |
rd_noffset = fit_get_node_from_config(images, FIT_RAMDISK_PROP, rd_addr); if (rd_noffset == -ENOLINK) |
41266c9b5
|
920 |
return 0; |
a51ec63b8
|
921 922 |
else if (rd_noffset < 0) return 1; |
d5934ad77
|
923 |
} |
f773bea8e
|
924 |
#endif |
d5934ad77
|
925 926 |
/* copy from dataflash if needed */ |
712fbcf38
|
927 |
rd_addr = genimg_get_image(rd_addr); |
d5934ad77
|
928 929 930 931 932 933 |
/* * Check if there is an initrd image at the * address provided in the second bootm argument * check image type, for FIT images get FIT node. */ |
35e7b0f17
|
934 935 |
buf = map_sysmem(rd_addr, 0); switch (genimg_get_format(buf)) { |
21d29f7f9
|
936 |
#if defined(CONFIG_IMAGE_FORMAT_LEGACY) |
d5934ad77
|
937 |
case IMAGE_FORMAT_LEGACY: |
712fbcf38
|
938 |
printf("## Loading init Ramdisk from Legacy " |
c87796483
|
939 940 |
"Image at %08lx ... ", rd_addr); |
5ad03eb38
|
941 |
|
770605e4f
|
942 |
bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); |
712fbcf38
|
943 |
rd_hdr = image_get_ramdisk(rd_addr, arch, |
d985c8498
|
944 |
images->verify); |
5ad03eb38
|
945 |
|
c87796483
|
946 |
if (rd_hdr == NULL) |
274cea2bd
|
947 |
return 1; |
274cea2bd
|
948 |
|
712fbcf38
|
949 950 951 |
rd_data = image_get_data(rd_hdr); rd_len = image_get_data_size(rd_hdr); rd_load = image_get_load(rd_hdr); |
d5934ad77
|
952 |
break; |
21d29f7f9
|
953 |
#endif |
d5934ad77
|
954 955 |
#if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: |
126cc8642
|
956 |
rd_noffset = fit_image_load(images, |
a51ec63b8
|
957 |
rd_addr, &fit_uname_ramdisk, |
f320a4d84
|
958 |
&fit_uname_config, arch, |
a51ec63b8
|
959 960 |
IH_TYPE_RAMDISK, BOOTSTAGE_ID_FIT_RD_START, |
fe20a81a6
|
961 962 |
FIT_LOAD_OPTIONAL_NON_ZERO, &rd_data, &rd_len); |
a51ec63b8
|
963 |
if (rd_noffset < 0) |
c78fce699
|
964 |
return 1; |
c87796483
|
965 |
|
a51ec63b8
|
966 |
images->fit_hdr_rd = map_sysmem(rd_addr, 0); |
c87796483
|
967 |
images->fit_uname_rd = fit_uname_ramdisk; |
3dfe11014
|
968 |
images->fit_noffset_rd = rd_noffset; |
c87796483
|
969 |
break; |
d5934ad77
|
970 971 |
#endif default: |
017e1f3f9
|
972 |
#ifdef CONFIG_SUPPORT_RAW_INITRD |
983c72f47
|
973 974 975 976 |
end = NULL; if (select) end = strchr(select, ':'); if (end) { |
017e1f3f9
|
977 978 979 980 981 982 983 984 985 986 |
rd_len = simple_strtoul(++end, NULL, 16); rd_data = rd_addr; } else #endif { puts("Wrong Ramdisk Image Format "); rd_data = rd_len = rd_load = 0; return 1; } |
d5934ad77
|
987 |
} |
d5934ad77
|
988 |
} else if (images->legacy_hdr_valid && |
712fbcf38
|
989 990 |
image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { |
5ad03eb38
|
991 |
/* |
d5934ad77
|
992 993 |
* Now check if we have a legacy mult-component image, * get second entry data start address and len. |
5ad03eb38
|
994 |
*/ |
770605e4f
|
995 |
bootstage_mark(BOOTSTAGE_ID_RAMDISK); |
712fbcf38
|
996 |
printf("## Loading init Ramdisk from multi component " |
c87796483
|
997 998 |
"Legacy Image at %08lx ... ", |
d5934ad77
|
999 |
(ulong)images->legacy_hdr_os); |
712fbcf38
|
1000 |
image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); |
9ace3fc81
|
1001 1002 1003 1004 1005 1006 1007 1008 1009 |
} #ifdef CONFIG_ANDROID_BOOT_IMAGE else if ((genimg_get_format(images) == IMAGE_FORMAT_ANDROID) && (!android_image_get_ramdisk((void *)images->os.start, &rd_data, &rd_len))) { /* empty */ } #endif else { |
5ad03eb38
|
1010 1011 1012 |
/* * no initrd image */ |
770605e4f
|
1013 |
bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); |
5ad03eb38
|
1014 1015 1016 1017 |
rd_len = rd_data = 0; } if (!rd_data) { |
712fbcf38
|
1018 1019 |
debug("## No init Ramdisk "); |
5ad03eb38
|
1020 1021 1022 1023 |
} else { *rd_start = rd_data; *rd_end = rd_data + rd_len; } |
712fbcf38
|
1024 1025 |
debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx ", |
5ad03eb38
|
1026 |
*rd_start, *rd_end); |
274cea2bd
|
1027 1028 |
return 0; |
5ad03eb38
|
1029 |
} |
ceaed2b1e
|
1030 |
|
fca43cc80
|
1031 |
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH |
ceaed2b1e
|
1032 |
/** |
9a4daad0a
|
1033 |
* boot_ramdisk_high - relocate init ramdisk |
e822d7fc4
|
1034 |
* @lmb: pointer to lmb handle, will be used for memory mgmt |
ceaed2b1e
|
1035 1036 |
* @rd_data: ramdisk data start address * @rd_len: ramdisk data length |
ceaed2b1e
|
1037 1038 1039 1040 1041 |
* @initrd_start: pointer to a ulong variable, will hold final init ramdisk * start address (after possible relocation) * @initrd_end: pointer to a ulong variable, will hold final init ramdisk * end address (after possible relocation) * |
1bce2aeb6
|
1042 |
* boot_ramdisk_high() takes a relocation hint from "initrd_high" environment |
ceaed2b1e
|
1043 1044 |
* variable and if requested ramdisk data is moved to a specified location. * |
9a4daad0a
|
1045 1046 1047 1048 |
* Initrd_start and initrd_end are set to final (after relocation) ramdisk * start/end addresses if ramdisk image start and len were provided, * otherwise set initrd_start and initrd_end set to zeros. * |
ceaed2b1e
|
1049 |
* returns: |
9a4daad0a
|
1050 1051 |
* 0 - success * -1 - failure |
ceaed2b1e
|
1052 |
*/ |
712fbcf38
|
1053 |
int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, |
e822d7fc4
|
1054 |
ulong *initrd_start, ulong *initrd_end) |
ceaed2b1e
|
1055 1056 1057 1058 |
{ char *s; ulong initrd_high; int initrd_copy_to_ram = 1; |
712fbcf38
|
1059 |
if ((s = getenv("initrd_high")) != NULL) { |
ceaed2b1e
|
1060 1061 1062 |
/* a value of "no" or a similar string will act like 0, * turning the "load high" feature off. This is intentional. */ |
712fbcf38
|
1063 |
initrd_high = simple_strtoul(s, NULL, 16); |
ceaed2b1e
|
1064 1065 1066 1067 1068 1069 |
if (initrd_high == ~0) initrd_copy_to_ram = 0; } else { /* not set, no restrictions to load high */ initrd_high = ~0; } |
95d449ad4
|
1070 1071 1072 1073 1074 |
#ifdef CONFIG_LOGBUFFER /* Prevent initrd from overwriting logbuffer */ lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE); #endif |
712fbcf38
|
1075 1076 |
debug("## initrd_high = 0x%08lx, copy_to_ram = %d ", |
ceaed2b1e
|
1077 1078 1079 1080 |
initrd_high, initrd_copy_to_ram); if (rd_data) { if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ |
712fbcf38
|
1081 1082 |
debug(" in-place initrd "); |
ceaed2b1e
|
1083 1084 |
*initrd_start = rd_data; *initrd_end = rd_data + rd_len; |
e822d7fc4
|
1085 |
lmb_reserve(lmb, rd_data, rd_len); |
ceaed2b1e
|
1086 |
} else { |
e822d7fc4
|
1087 |
if (initrd_high) |
712fbcf38
|
1088 1089 |
*initrd_start = (ulong)lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); |
e822d7fc4
|
1090 |
else |
712fbcf38
|
1091 1092 |
*initrd_start = (ulong)lmb_alloc(lmb, rd_len, 0x1000); |
e822d7fc4
|
1093 1094 |
if (*initrd_start == 0) { |
712fbcf38
|
1095 1096 |
puts("ramdisk - allocation error "); |
e822d7fc4
|
1097 |
goto error; |
ceaed2b1e
|
1098 |
} |
770605e4f
|
1099 |
bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); |
ceaed2b1e
|
1100 1101 |
*initrd_end = *initrd_start + rd_len; |
712fbcf38
|
1102 |
printf(" Loading Ramdisk to %08lx, end %08lx ... ", |
ceaed2b1e
|
1103 |
*initrd_start, *initrd_end); |
712fbcf38
|
1104 |
memmove_wd((void *)*initrd_start, |
ceaed2b1e
|
1105 |
(void *)rd_data, rd_len, CHUNKSZ); |
3b2001105
|
1106 1107 1108 1109 1110 1111 1112 1113 |
#ifdef CONFIG_MP /* * Ensure the image is flushed to memory to handle * AMP boot scenarios in which we might not be * HW cache coherent */ flush_cache((unsigned long)*initrd_start, rd_len); #endif |
712fbcf38
|
1114 1115 |
puts("OK "); |
ceaed2b1e
|
1116 1117 1118 1119 1120 |
} } else { *initrd_start = 0; *initrd_end = 0; } |
712fbcf38
|
1121 1122 |
debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx ", |
ceaed2b1e
|
1123 |
*initrd_start, *initrd_end); |
9a4daad0a
|
1124 |
|
e822d7fc4
|
1125 |
return 0; |
b6b0fe646
|
1126 |
|
e822d7fc4
|
1127 1128 |
error: return -1; |
b6b0fe646
|
1129 |
} |
fca43cc80
|
1130 |
#endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */ |
b6b0fe646
|
1131 |
|
fca43cc80
|
1132 |
#ifdef CONFIG_SYS_BOOT_GET_CMDLINE |
b6b0fe646
|
1133 |
/** |
9a4daad0a
|
1134 |
* boot_get_cmdline - allocate and initialize kernel cmdline |
e822d7fc4
|
1135 |
* @lmb: pointer to lmb handle, will be used for memory mgmt |
b6b0fe646
|
1136 1137 1138 |
* @cmd_start: pointer to a ulong variable, will hold cmdline start * @cmd_end: pointer to a ulong variable, will hold cmdline end * |
9a4daad0a
|
1139 |
* boot_get_cmdline() allocates space for kernel command line below |
590d3cacb
|
1140 |
* BOOTMAPSZ + getenv_bootm_low() address. If "bootargs" U-boot environemnt |
b6b0fe646
|
1141 1142 1143 1144 |
* variable is present its contents is copied to allocated kernel * command line. * * returns: |
e822d7fc4
|
1145 1146 |
* 0 - success * -1 - failure |
b6b0fe646
|
1147 |
*/ |
712fbcf38
|
1148 |
int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) |
b6b0fe646
|
1149 1150 1151 |
{ char *cmdline; char *s; |
6d0f6bcf3
|
1152 |
cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, |
c3624e6ed
|
1153 |
getenv_bootm_mapsize() + getenv_bootm_low()); |
e822d7fc4
|
1154 1155 1156 |
if (cmdline == NULL) return -1; |
b6b0fe646
|
1157 1158 1159 1160 1161 1162 1163 1164 |
if ((s = getenv("bootargs")) == NULL) s = ""; strcpy(cmdline, s); *cmd_start = (ulong) & cmdline[0]; *cmd_end = *cmd_start + strlen(cmdline); |
712fbcf38
|
1165 1166 |
debug("## cmdline at 0x%08lx ... 0x%08lx ", *cmd_start, *cmd_end); |
b6b0fe646
|
1167 |
|
e822d7fc4
|
1168 |
return 0; |
b6b0fe646
|
1169 |
} |
fca43cc80
|
1170 |
#endif /* CONFIG_SYS_BOOT_GET_CMDLINE */ |
b6b0fe646
|
1171 |
|
fca43cc80
|
1172 |
#ifdef CONFIG_SYS_BOOT_GET_KBD |
b6b0fe646
|
1173 |
/** |
9a4daad0a
|
1174 |
* boot_get_kbd - allocate and initialize kernel copy of board info |
e822d7fc4
|
1175 |
* @lmb: pointer to lmb handle, will be used for memory mgmt |
b6b0fe646
|
1176 1177 |
* @kbd: double pointer to board info data * |
9a4daad0a
|
1178 |
* boot_get_kbd() allocates space for kernel copy of board info data below |
590d3cacb
|
1179 1180 |
* BOOTMAPSZ + getenv_bootm_low() address and kernel board info is initialized * with the current u-boot board info data. |
b6b0fe646
|
1181 1182 |
* * returns: |
e822d7fc4
|
1183 1184 |
* 0 - success * -1 - failure |
b6b0fe646
|
1185 |
*/ |
712fbcf38
|
1186 |
int boot_get_kbd(struct lmb *lmb, bd_t **kbd) |
b6b0fe646
|
1187 |
{ |
391fd93ab
|
1188 |
*kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, |
c3624e6ed
|
1189 |
getenv_bootm_mapsize() + getenv_bootm_low()); |
e822d7fc4
|
1190 1191 |
if (*kbd == NULL) return -1; |
b6b0fe646
|
1192 |
**kbd = *(gd->bd); |
712fbcf38
|
1193 1194 |
debug("## kernel board info at 0x%08lx ", (ulong)*kbd); |
b6b0fe646
|
1195 1196 1197 1198 |
#if defined(DEBUG) && defined(CONFIG_CMD_BDI) do_bdinfo(NULL, 0, 0, NULL); #endif |
e822d7fc4
|
1199 |
return 0; |
ceaed2b1e
|
1200 |
} |
fca43cc80
|
1201 |
#endif /* CONFIG_SYS_BOOT_GET_KBD */ |
13d06981a
|
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 |
#ifdef CONFIG_LMB int image_setup_linux(bootm_headers_t *images) { ulong of_size = images->ft_len; char **of_flat_tree = &images->ft_addr; ulong *initrd_start = &images->initrd_start; ulong *initrd_end = &images->initrd_end; struct lmb *lmb = &images->lmb; ulong rd_len; int ret; if (IMAGE_ENABLE_OF_LIBFDT) boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); if (IMAGE_BOOT_GET_CMDLINE) { ret = boot_get_cmdline(lmb, &images->cmdline_start, &images->cmdline_end); if (ret) { puts("ERROR with allocation of cmdline "); return ret; } } if (IMAGE_ENABLE_RAMDISK_HIGH) { rd_len = images->rd_end - images->rd_start; ret = boot_ramdisk_high(lmb, images->rd_start, rd_len, initrd_start, initrd_end); if (ret) return ret; } if (IMAGE_ENABLE_OF_LIBFDT) { ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); if (ret) return ret; } if (IMAGE_ENABLE_OF_LIBFDT && of_size) { ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb); if (ret) return ret; } return 0; } #endif /* CONFIG_LMB */ |
5dfb52138
|
1249 |
#endif /* !USE_HOSTCC */ |