blob: c7dc25c6d0d94e1a97594d7a7644578e97fccee1 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2020 MediaTek Inc.
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9#include <arch/ops.h>
10#include <assert.h>
11#include <errno.h>
12#include <lib/android_bootimg.h>
13#include <lib/bio.h>
14#include <lib/boot_info.h>
15#include <lib/decompress.h>
16#include <lib/mempool.h>
17#include <kernel/vm.h>
18#include <string.h>
19#include <trace.h>
20
21#define LOCAL_TRACE 0
22
23static int get_decompress_algo(unsigned char *src)
24{
25 int ret = NO_DECOMPRESS;
26 uint16_t gzip_magic;
27 uint32_t lz4_magic;
28
29 /* lz4 magic stores to 32-bits little-endian */
30 lz4_magic = src[0];
31 lz4_magic |= (src[1] << 8);
32 lz4_magic |= (src[2] << 16);
33 lz4_magic |= (src[3] << 24);
34
35 /* gzip magic stores to 16-bits big-endian */
36 gzip_magic = (src[0] << 8);
37 gzip_magic |= src[1];
38
39 if (lz4_magic == LZ4_LEGACY_MAGIC)
40 ret = LZ4_DECOMPRESS;
41 else if (gzip_magic == GZIP_MAGIC)
42 ret = GZIP_DECOMPRESS;
43
44 return ret;
45}
46
47int android_get_image(const char *label, void **load_buf)
48{
49 bdev_t *bdev;
50 struct bootimg_hdr bootimg;
51 size_t totalsize;
52 int hdr_len, ret = 0;
53 void *buf = NULL;
54
55 bdev = bio_open_by_label(label) ? : bio_open(label);
56 if (!bdev) {
57 LTRACEF_LEVEL(CRITICAL, "Partition [%s] is not exist.\n", label);
58 return -ENODEV;
59 }
60
61 hdr_len = sizeof(struct bootimg_hdr);
62 if (bio_read(bdev, &bootimg, 0, hdr_len) < hdr_len ) {
63 ret = -EIO;
64 goto closebdev;
65 }
66
67 ret = load_bootinfo_bootimg_hdr(&bootimg);
68 if (ret)
69 goto closebdev;
70
71 totalsize = get_page_sz() + get_ramdisk_sz() + get_dtb_size()
72 + get_kernel_sz();
73 buf = mempool_alloc(totalsize, MEMPOOL_ANY);
74 if (!buf) {
75 ret = -ENOMEM;
76 goto closebdev;
77 }
78
79 if ((size_t)bio_read(bdev, buf, 0, totalsize) < totalsize) {
80 ret = -EIO;
81 goto closebdev;
82 }
83
84 *load_buf = buf;
85
86closebdev:
87 bio_close(bdev);
88 if (ret && buf)
89 mempool_free(buf);
90
91 return ret;
92}
93
94int android_processing_data(const char *image_name, vaddr_t load_data,
95 addr_t target_addr, size_t size)
96{
97 int ret;
98 int algo;
99 vaddr_t load_addr;
100
101 if (size == 0) {
102 LTRACEF_LEVEL(CRITICAL, "%s is NULL\n", image_name);
103 return -EINVAL;
104 }
105
106#if WITH_KERNEL_VM
107 load_addr = (vaddr_t)paddr_to_kvaddr(target_addr);
108#endif
109
110 algo = get_decompress_algo((unsigned char *)load_data);
111 switch(algo) {
112 case LZ4_DECOMPRESS:
113 ret = unlz4((void *)load_data, size - 4, (void *)load_addr);
114 if (ret != LZ4_OK) {
115 LTRACEF_LEVEL(ALWAYS, "[%s] lz4 decompress failure\n",
116 image_name);
117 return -LZ4_FAIL;
118 }
119 /* In lz4 kernel image, the last 4 bytes are the uncompressed
120 * kernel image size.
121 */
122 size = *(uint32_t *)(load_data + size - 4);
123 break;
124 case GZIP_DECOMPRESS:
125 if (strcmp(image_name, "ramdisk")) {
126 LTRACEF_LEVEL(ALWAYS, "[%s] gzip is not suppport\n",
127 image_name);
128 return -EINVAL;
129 }
130 default:
131 memmove((void *)load_addr, (void *)load_data, size);
132 break;
133 }
134
135#if WITH_KERNEL_VM
136 /* always flush cache to PoC */
137 arch_clean_cache_range(load_addr, size);
138#endif
139
140 LTRACEF("[%s] load_addr = 0x%lx\n", image_name, load_addr);
141 LTRACEF("[%s] data = 0x%lx\n", image_name, load_data);
142 LTRACEF("[%s] size = %zu\n", image_name, size);
143
144 return 0;
145}