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