]>
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> |
c1108172 SR |
10 | #include <spl.h> |
11 | ||
aba6e77a WG |
12 | #include <lzma/LzmaTypes.h> |
13 | #include <lzma/LzmaDec.h> | |
14 | #include <lzma/LzmaTools.h> | |
15 | ||
16 | #define LZMA_LEN (1 << 20) | |
17 | ||
c1108172 SR |
18 | int spl_parse_legacy_header(struct spl_image_info *spl_image, |
19 | const struct image_header *header) | |
20 | { | |
21 | u32 header_size = sizeof(struct image_header); | |
22 | ||
c1108172 | 23 | /* check uImage header CRC */ |
5ae526b6 SR |
24 | if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK) && |
25 | !image_check_hcrc(header)) { | |
c1108172 SR |
26 | puts("SPL: Image header CRC check failed!\n"); |
27 | return -EINVAL; | |
28 | } | |
c1108172 SR |
29 | |
30 | if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { | |
31 | /* | |
32 | * On some system (e.g. powerpc), the load-address and | |
33 | * entry-point is located at address 0. We can't load | |
34 | * to 0-0x40. So skip header in this case. | |
35 | */ | |
36 | spl_image->load_addr = image_get_load(header); | |
37 | spl_image->entry_point = image_get_ep(header); | |
38 | spl_image->size = image_get_data_size(header); | |
39 | } else { | |
40 | spl_image->entry_point = image_get_ep(header); | |
41 | /* Load including the header */ | |
42 | spl_image->load_addr = image_get_load(header) - | |
43 | header_size; | |
44 | spl_image->size = image_get_data_size(header) + | |
45 | header_size; | |
46 | } | |
47 | ||
48 | #ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK | |
49 | /* store uImage data length and CRC to check later */ | |
50 | spl_image->dcrc_data = image_get_load(header); | |
51 | spl_image->dcrc_length = image_get_data_size(header); | |
52 | spl_image->dcrc = image_get_dcrc(header); | |
53 | #endif | |
54 | ||
55 | spl_image->os = image_get_os(header); | |
56 | spl_image->name = image_get_name(header); | |
57 | debug(SPL_TPL_PROMPT | |
58 | "payload image: %32s load addr: 0x%lx size: %d\n", | |
59 | spl_image->name, spl_image->load_addr, spl_image->size); | |
60 | ||
61 | return 0; | |
62 | } | |
2fc91ed3 | 63 | |
aba6e77a WG |
64 | /* |
65 | * This function is added explicitly to avoid code size increase, when | |
66 | * no compression method is enabled. The compiler will optimize the | |
67 | * following switch/case statement in spl_load_legacy_img() away due to | |
68 | * Dead Code Elimination. | |
69 | */ | |
70 | static inline int spl_image_get_comp(const struct image_header *hdr) | |
71 | { | |
72 | if (IS_ENABLED(CONFIG_SPL_LZMA)) | |
73 | return image_get_comp(hdr); | |
74 | ||
75 | return IH_COMP_NONE; | |
76 | } | |
77 | ||
2fc91ed3 SR |
78 | int spl_load_legacy_img(struct spl_image_info *spl_image, |
79 | struct spl_load_info *load, ulong header) | |
80 | { | |
aba6e77a WG |
81 | __maybe_unused SizeT lzma_len; |
82 | __maybe_unused void *src; | |
2fc91ed3 | 83 | struct image_header hdr; |
aba6e77a | 84 | ulong dataptr; |
2fc91ed3 SR |
85 | int ret; |
86 | ||
87 | /* Read header into local struct */ | |
88 | load->read(load, header, sizeof(hdr), &hdr); | |
89 | ||
90 | ret = spl_parse_image_header(spl_image, &hdr); | |
91 | if (ret) | |
92 | return ret; | |
93 | ||
aba6e77a WG |
94 | dataptr = header + sizeof(hdr); |
95 | ||
2fc91ed3 | 96 | /* Read image */ |
aba6e77a WG |
97 | switch (spl_image_get_comp(&hdr)) { |
98 | case IH_COMP_NONE: | |
99 | load->read(load, dataptr, spl_image->size, | |
100 | (void *)(unsigned long)spl_image->load_addr); | |
101 | break; | |
102 | ||
103 | case IH_COMP_LZMA: | |
104 | lzma_len = LZMA_LEN; | |
105 | ||
106 | debug("LZMA: Decompressing %08lx to %08lx\n", | |
107 | dataptr, spl_image->load_addr); | |
108 | src = malloc(spl_image->size); | |
109 | if (!src) { | |
110 | printf("Unable to allocate %d bytes for LZMA\n", | |
111 | spl_image->size); | |
112 | return -ENOMEM; | |
113 | } | |
114 | ||
115 | load->read(load, dataptr, spl_image->size, src); | |
116 | ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr, | |
117 | &lzma_len, src, spl_image->size); | |
118 | if (ret) { | |
119 | printf("LZMA decompression error: %d\n", ret); | |
120 | return ret; | |
121 | } | |
122 | ||
123 | spl_image->size = lzma_len; | |
124 | break; | |
125 | ||
126 | default: | |
127 | debug("Compression method %s is not supported\n", | |
128 | genimg_get_comp_short_name(image_get_comp(&hdr))); | |
129 | return -EINVAL; | |
130 | } | |
2fc91ed3 SR |
131 | |
132 | return 0; | |
133 | } |