blob: 5b154ef526bd8c17b346fc3c0c43ca28b0c3a280 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +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 len;
120
121 len = strlen(*name) + suffix_len + 1;
122 new_name = mempool_alloc(len, MEMPOOL_ANY);
123 ASSERT(new_name != NULL);
124 sprintf(new_name, "%s%s", *name, suffix);
125 *name = new_name;
126}
127
128static void update_image_partition_name(const char *suffix)
129{
130 struct imageinfo_t *img;
131 struct image_load_data *imgdata;
132 int suffix_len;
133
134 suffix_len = strlen(suffix);
135 for (img = &imagelist[0]; img->type != IMGTYPE_NONE; img++) {
136 ASSERT((img != NULL) && (img->imgdata != NULL));
137 imgdata = img->imgdata;
138 if (!imgdata->has_slot)
139 continue;
140
141 append_suffix(&imgdata->part_name, suffix, suffix_len);
142 if (imgdata->recovery_part_name)
143 append_suffix(&imgdata->recovery_part_name, suffix, suffix_len);
144 }
145}
146
147static void blxboot_task(const struct app_descriptor *app, void *args)
148{
149 struct blxboot *blxobj;
150 struct boot_param bprm;
151 bool fastboot_on_fail;
152 uint32_t *boot_mode;
153 void *fdt_dtb, *dtbo, *vpd;
154 int rc;
155
156#if (defined AVB_ENABLE_ANTIROLLBACK) || (defined AVB_ENABLE_DEVICE_STATE_CHANGE)
157 rpmb_init();
158#endif
159
160 if (plat_fixup_init() != NO_ERROR)
161 return;
162
163 blxobj = blxboot_create();
164 if (!blxobj)
165 return;
166
167 boot_mode = &(blxobj->bootcfg.boot_mode);
168 *boot_mode = get_boot_mode();
169 assert(*boot_mode <= FASTBOOT_BOOT);
170
171 if (blxobj->ops.init) {
172 rc = blxobj->ops.init();
173 /*
174 * if init fails, and boot mode is
175 * - fastboot mode: enter fastboot mode
176 * - non fastboot mode:
177 * . AB OTA updater enabled: reboot,
178 * . non AB OTA updater: enter fastboot mode
179 */
180 if (rc && (*boot_mode != FASTBOOT_BOOT)) {
181 if (is_enabled_ab_ota_updater())
182 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
183 else
184 *boot_mode = FASTBOOT_BOOT;
185 }
186 }
187
188 blxobj->bootcfg.ab_suffix = get_suffix();
189 if (blxobj->bootcfg.ab_suffix != NULL)
190 update_image_partition_name(blxobj->bootcfg.ab_suffix);
191
192 if (is_enabled_ab_ota_updater())
193 fastboot_on_fail = false;
194 else
195 fastboot_on_fail = true; /* enter fastboot mode if load fail */
196
197 do {
198 if (*boot_mode == FASTBOOT_BOOT) {
199 ext_boot();
200 fastboot_on_fail = false;
201 }
202
203 if ((rc = load_all_images(blxobj)) == 0)
204 break;
205
206 if (fastboot_on_fail)
207 *boot_mode = FASTBOOT_BOOT;
208 } while (fastboot_on_fail);
209
210 if (rc != 0) {
211 if (is_enabled_ab_ota_updater())
212 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
213
214 return;
215 }
216
217 /* dtbo may contains kernel bootargs, do overlay_fdt before fixup_image */
218 blxobj->ops.get_overlay_image(blxobj, &fdt_dtb, &dtbo, &vpd);
219 if (fdt_dtb && (dtbo || vpd)) {
220 rc = overlay_fdt(fdt_dtb, dtbo, vpd);
221 if (rc) {
222 LTRACEF_LEVEL(CRITICAL, "dtbo overlay failed\n");
223 return;
224 }
225 }
226
227 if (blxobj->ops.fixup_image)
228 blxobj->ops.fixup_image(blxobj, fdt_dtb);
229
230 plat_fixup_hook(*boot_mode, blxobj->bootcfg.ab_suffix,
231 fdt_dtb, MAX_DTB_SIZE);
232
233 if (blxobj->ops.setup_boot_param) {
234 blxobj->ops.setup_boot_param(blxobj, &bprm);
235 }
236
237 dprintf(ALWAYS, "LK run time: %lld (us)\n", current_time_hires());
238 dprintf(ALWAYS, "jump to next ep %p, arg (0x%lx)\n",
239 (void *)bprm.arg1, bprm.arg2);
240
241 arch_chain_load((void *)blxobj->ops.exit,
242 bprm.arg0, bprm.arg1, bprm.arg2, bprm.arg3);
243}
244
245APP_START(blxboot)
246.entry = blxboot_task,
247 .flags = 0,
248 APP_END