blob: 9a489f32d642b404474fbdcce7a0aa8f8e6104f2 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001/*
2 * Copyright (c) 2018 MediaTek Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <app.h>
25#include <assert.h>
26#include <boot_mode.h>
27#include <err.h>
28#include <errno.h>
29#include <fit.h>
30#include <kernel/event.h>
31#include <kernel/thread.h>
32#include <kernel/vm.h>
33#include <libfdt.h>
34#include <lib/dl_commands.h> /* [TODO] separate rpmb define from fastboot */
35#include <lib/mempool.h>
36#include <platform.h>
37#include <rpmb/include/rpmb_mac.h> /* [TODO] #include <lib/rpmb_mac.h> */
38#include <trace.h>
39
40#include "blx_common.h"
41#include "blxboot_ab.h"
42#include "blxboot_plat.h"
43#include "dto.h"
44#include "imageinfo.h"
45
46#define LOCAL_TRACE 0
47
48extern void ext_boot(void);
49extern struct imageinfo_t imagelist[];
50
51static int load_all_images(struct blxboot *obj)
52{
53 int rc;
54 int load_idx;
55 struct imageinfo_t *img;
56 const char *part_name[3];
57 uint32_t *boot_mode = &(obj->bootcfg.boot_mode);
58
59 img = &imagelist[0];
60 while (img->type != IMGTYPE_NONE) {
61 LTRACEF("image load: %s\n", img->imgdata->part_name);
62
63 ASSERT((img->load != NULL) && (img->imgdata != NULL));
64
65 /* setup the load retry sequence: fastboot -> normal -> recovery */
66 if (*boot_mode == NORMAL_BOOT)
67 load_idx = 1;
68 else if (*boot_mode == RECOVERY_BOOT)
69 load_idx = 0;
70 else /* FASTBOOT_BOOT */
71 load_idx = 2;
72
73 part_name[2] = img->imgdata->membdev_name;
74 part_name[1] = img->imgdata->part_name;
75 part_name[0] = img->imgdata->recovery_part_name;
76
77 /* for non recovery boot partition, no need to try recovery partition
78 * if its name is the same with normal boot partition */
79 if (*boot_mode != RECOVERY_BOOT) {
80 if ((part_name[0] != NULL) && (part_name[1] != NULL) &&
81 (!strcmp(part_name[0], part_name[1])))
82 part_name[0] = NULL;
83 }
84
85 rc = -ENODEV;
86 while (load_idx >= 0) {
87 if (part_name[load_idx] != NULL) {
88 rc = img->load(part_name[load_idx], img);
89 if (rc == 0)
90 break;
91 }
92
93 load_idx--;
94 }
95
96 if (rc == 0) {
97 if (obj->ops.notify)
98 obj->ops.notify(obj, img);
99 } else {
100 LTRACEF("load part: %s, type=%d failed\n",
101 img->imgdata->part_name, img->type);
102 if ((img->type != IMGTYPE_DTBO) && (img->type != IMGTYPE_VPD))
103 return -1;
104
105 /* dtbo/vpd image: allow partition not exist or no valid data.
106 * Other cases, boot fail */
107 if ((rc != -ENODEV) && (rc != -ENOTSUP))
108 return -1;
109 }
110 img++;
111 }
112
113 return 0;
114}
115
116static void append_suffix(const char **name, const char *suffix, int suffix_len)
117{
118 char *new_name;
119 int n, len;
120
121 len = strlen(*name) + suffix_len + 1;
122 new_name = mempool_alloc(len, MEMPOOL_ANY);
123 ASSERT(new_name != NULL);
124
125 n = snprintf(new_name, len, "%s%s", *name, suffix);
126 ASSERT(!((n < 0) || (n >= len)));
127
128 *name = new_name;
129}
130
131static void update_image_partition_name(const char *suffix)
132{
133 struct imageinfo_t *img;
134 struct image_load_data *imgdata;
135 int suffix_len;
136
137 suffix_len = strlen(suffix);
138 for (img = &imagelist[0]; img->type != IMGTYPE_NONE; img++) {
139 ASSERT((img != NULL) && (img->imgdata != NULL));
140 imgdata = img->imgdata;
141 if (!imgdata->has_slot)
142 continue;
143
144 append_suffix(&imgdata->part_name, suffix, suffix_len);
145 if (imgdata->recovery_part_name)
146 append_suffix(&imgdata->recovery_part_name, suffix, suffix_len);
147 }
148}
149
150static void blxboot_task(const struct app_descriptor *app, void *args)
151{
152 struct blxboot *blxobj;
153 struct boot_param bprm = { .arg0 = 0, .arg1 = 0, .arg2 = 0, .arg3 = 0 };
154 bool fastboot_on_fail;
155 uint32_t *boot_mode;
156 void *fdt_dtb, *dtbo, *vpd;
157 int rc;
158
159#if (defined AVB_ENABLE_ANTIROLLBACK) || (defined AVB_ENABLE_DEVICE_STATE_CHANGE)
160 rpmb_init();
161#endif
162
163 if (plat_fixup_init() != NO_ERROR)
164 return;
165
166 blxobj = blxboot_create();
167 if (!blxobj)
168 return;
169
170 boot_mode = &(blxobj->bootcfg.boot_mode);
171 *boot_mode = get_boot_mode();
172 assert(*boot_mode <= FASTBOOT_BOOT);
173
174 if (blxobj->ops.init) {
175 rc = blxobj->ops.init();
176 /*
177 * if init fails, and boot mode is
178 * - fastboot mode: enter fastboot mode
179 * - non fastboot mode:
180 * . AB OTA updater enabled: reboot,
181 * . non AB OTA updater: enter fastboot mode
182 */
183 if (rc && (*boot_mode != FASTBOOT_BOOT)) {
184 if (is_enabled_ab_ota_updater())
185 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
186 else
187 *boot_mode = FASTBOOT_BOOT;
188 }
189 }
190
191#if defined(AB_OTA_UPDATER)
192 plat_check_update_anti_rollback_bl_ver();
193#endif
194
195 blxobj->bootcfg.ab_suffix = get_suffix();
196 if (blxobj->bootcfg.ab_suffix != NULL)
197 update_image_partition_name(blxobj->bootcfg.ab_suffix);
198
199 if (is_enabled_ab_ota_updater())
200 fastboot_on_fail = false;
201 else
202 fastboot_on_fail = true; /* enter fastboot mode if load fail */
203
204 do {
205 if (*boot_mode == FASTBOOT_BOOT) {
206 ext_boot();
207 fastboot_on_fail = false;
208 }
209
210 if ((rc = load_all_images(blxobj)) == 0)
211 break;
212
213 if (fastboot_on_fail)
214 *boot_mode = FASTBOOT_BOOT;
215 } while (fastboot_on_fail);
216
217 if (rc != 0) {
218 if (is_enabled_ab_ota_updater())
219 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
220
221 return;
222 }
223
224 /* dtbo may contains kernel bootargs, do overlay_fdt before fixup_image */
225 blxobj->ops.get_overlay_image(blxobj, &fdt_dtb, &dtbo, &vpd);
226 if (fdt_dtb && (dtbo || vpd)) {
227 rc = overlay_fdt(fdt_dtb, dtbo, vpd);
228 if (rc) {
229 LTRACEF_LEVEL(CRITICAL, "dtbo overlay failed\n");
230 return;
231 }
232 }
233
234 if (blxobj->ops.fixup_image)
235 blxobj->ops.fixup_image(blxobj, fdt_dtb);
236
237 plat_fixup_hook(*boot_mode, blxobj->bootcfg.ab_suffix,
238 fdt_dtb, MAX_DTB_SIZE);
239
240 if (blxobj->ops.setup_boot_param) {
241 blxobj->ops.setup_boot_param(blxobj, &bprm);
242 }
243
244 dprintf(ALWAYS, "LK run time: %lld (us)\n", current_time_hires());
245 dprintf(ALWAYS, "jump to next ep %p, arg (0x%lx)\n",
246 (void *)bprm.arg1, bprm.arg2);
247
248 arch_chain_load((void *)blxobj->ops.exit,
249 bprm.arg0, bprm.arg1, bprm.arg2, bprm.arg3);
250}
251
252APP_START(blxboot)
253.entry = blxboot_task,
254 .flags = 0,
255 APP_END