]>
Commit | Line | Data |
---|---|---|
c1108172 SR |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2020 Stefan Roese <[email protected]> | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
4d72caa5 | 7 | #include <image.h> |
f7ae49fc | 8 | #include <log.h> |
aba6e77a | 9 | #include <malloc.h> |
b02c4e94 | 10 | #include <mapmem.h> |
77aed22b | 11 | #include <asm/sections.h> |
c1108172 SR |
12 | #include <spl.h> |
13 | ||
aba6e77a WG |
14 | #include <lzma/LzmaTypes.h> |
15 | #include <lzma/LzmaDec.h> | |
16 | #include <lzma/LzmaTools.h> | |
17 | ||
18 | #define LZMA_LEN (1 << 20) | |
19 | ||
77aed22b MV |
20 | static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) |
21 | { | |
22 | uintptr_t spl_start = (uintptr_t)_start; | |
301ae618 | 23 | uintptr_t spl_end = (uintptr_t)&_image_binary_end; |
77aed22b MV |
24 | uintptr_t end = start + size; |
25 | ||
26 | if ((start >= spl_start && start < spl_end) || | |
27 | (end > spl_start && end <= spl_end) || | |
28 | (start < spl_start && end >= spl_end) || | |
29 | (start > end && end > spl_start)) | |
30 | panic("SPL: Image overlaps SPL\n"); | |
31 | ||
32 | if (size > CONFIG_SYS_BOOTM_LEN) | |
33 | panic("SPL: Image too large\n"); | |
34 | } | |
35 | ||
c1108172 | 36 | int spl_parse_legacy_header(struct spl_image_info *spl_image, |
f3543e69 | 37 | const struct legacy_img_hdr *header) |
c1108172 | 38 | { |
f3543e69 | 39 | u32 header_size = sizeof(struct legacy_img_hdr); |
c1108172 | 40 | |
c1108172 | 41 | /* check uImage header CRC */ |
5ae526b6 SR |
42 | if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK) && |
43 | !image_check_hcrc(header)) { | |
c1108172 SR |
44 | puts("SPL: Image header CRC check failed!\n"); |
45 | return -EINVAL; | |
46 | } | |
c1108172 SR |
47 | |
48 | if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { | |
49 | /* | |
50 | * On some system (e.g. powerpc), the load-address and | |
51 | * entry-point is located at address 0. We can't load | |
52 | * to 0-0x40. So skip header in this case. | |
53 | */ | |
54 | spl_image->load_addr = image_get_load(header); | |
55 | spl_image->entry_point = image_get_ep(header); | |
56 | spl_image->size = image_get_data_size(header); | |
57 | } else { | |
58 | spl_image->entry_point = image_get_ep(header); | |
59 | /* Load including the header */ | |
60 | spl_image->load_addr = image_get_load(header) - | |
61 | header_size; | |
62 | spl_image->size = image_get_data_size(header) + | |
63 | header_size; | |
64 | } | |
65 | ||
66 | #ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK | |
67 | /* store uImage data length and CRC to check later */ | |
68 | spl_image->dcrc_data = image_get_load(header); | |
69 | spl_image->dcrc_length = image_get_data_size(header); | |
70 | spl_image->dcrc = image_get_dcrc(header); | |
71 | #endif | |
72 | ||
73 | spl_image->os = image_get_os(header); | |
74 | spl_image->name = image_get_name(header); | |
75 | debug(SPL_TPL_PROMPT | |
76 | "payload image: %32s load addr: 0x%lx size: %d\n", | |
77 | spl_image->name, spl_image->load_addr, spl_image->size); | |
78 | ||
77aed22b MV |
79 | spl_parse_legacy_validate(spl_image->load_addr, spl_image->size); |
80 | spl_parse_legacy_validate(spl_image->entry_point, 0); | |
81 | ||
c1108172 SR |
82 | return 0; |
83 | } | |
2fc91ed3 | 84 | |
efe92cd2 SA |
85 | int spl_load_legacy_lzma(struct spl_image_info *spl_image, |
86 | struct spl_load_info *load, ulong offset) | |
87 | { | |
88 | SizeT lzma_len = LZMA_LEN; | |
89 | void *src; | |
90 | ulong dataptr, overhead, size; | |
91 | int ret; | |
92 | ||
93 | /* dataptr points to compressed payload */ | |
94 | dataptr = ALIGN_DOWN(sizeof(struct legacy_img_hdr), | |
95 | spl_get_bl_len(load)); | |
96 | overhead = sizeof(struct legacy_img_hdr) - dataptr; | |
97 | size = ALIGN(spl_image->size + overhead, spl_get_bl_len(load)); | |
98 | dataptr += offset; | |
99 | ||
100 | debug("LZMA: Decompressing %08lx to %08lx\n", | |
101 | dataptr, spl_image->load_addr); | |
102 | src = malloc(size); | |
103 | if (!src) { | |
104 | printf("Unable to allocate %d bytes for LZMA\n", | |
105 | spl_image->size); | |
106 | return -ENOMEM; | |
107 | } | |
108 | ||
109 | load->read(load, dataptr, size, src); | |
110 | ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr, | |
111 | spl_image->size), &lzma_len, | |
112 | src + overhead, spl_image->size); | |
113 | if (ret) { | |
114 | printf("LZMA decompression error: %d\n", ret); | |
115 | return ret; | |
116 | } | |
117 | ||
118 | spl_image->size = lzma_len; | |
119 | return 0; | |
120 | } |