blob: 9dfb8658edb15223d43f4e18d7d7f0d9a03e62e5 [file] [log] [blame]
Rahul Shaharee7baede2021-02-02 13:23:57 +05301/* Copyright (c) 2010-2017,2019,2021 The Linux Foundation. All rights reserved.
Shashank Mittal024c0332010-02-03 11:44:00 -08002
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
Duy Truongf3ac7b32013-02-13 01:07:28 -080012 * * Neither the name of The Linux Foundation nor the names of its
Shashank Mittal024c0332010-02-03 11:44:00 -080013 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <arch/arm.h>
31#include <dev/udc.h>
32#include <string.h>
33#include <kernel/thread.h>
34#include <arch/ops.h>
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -070035#include <arch/defines.h>
36#include <malloc.h>
Shashank Mittal024c0332010-02-03 11:44:00 -080037
38#include <dev/flash.h>
39#include <lib/ptable.h>
40#include <dev/keys.h>
Greg Griscod6250552011-06-29 14:40:23 -070041#include <platform.h>
Pavel Nedeva1e62322013-04-05 15:21:36 +030042#include <target.h>
Kinson Chikf1a43512011-07-14 11:28:39 -070043#include <partition_parser.h>
Greg Griscod2471ef2011-07-14 13:00:42 -070044#include <mmc.h>
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +053045#include <malloc.h>
Mayank Grover7e40ad22017-11-13 17:17:53 +053046#include <stdlib.h>
Shashank Mittal024c0332010-02-03 11:44:00 -080047#include "recovery.h"
48#include "bootimg.h"
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -070049#include "smem.h"
50
51#define BOOT_FLAGS 1
52#define UPDATE_STATUS 2
Shashank Mittal024c0332010-02-03 11:44:00 -080053
54static const int MISC_PAGES = 3; // number of pages to save
55static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
56static char buf[4096];
Pavel Nedeva1e62322013-04-05 15:21:36 +030057
Shashank Mittal024c0332010-02-03 11:44:00 -080058unsigned boot_into_recovery = 0;
59
Deepa Dinamani41fa8d62013-05-23 13:25:36 -070060extern uint32_t get_page_size();
Shashank Mittal162244e2011-08-08 19:01:25 -070061extern void reset_device_info();
62extern void set_device_root();
Shashank Mittal024c0332010-02-03 11:44:00 -080063
64int get_recovery_message(struct recovery_message *out)
65{
66 struct ptentry *ptn;
67 struct ptable *ptable;
68 unsigned offset = 0;
69 unsigned pagesize = flash_page_size();
70
71 ptable = flash_get_ptable();
72
73 if (ptable == NULL) {
74 dprintf(CRITICAL, "ERROR: Partition table not found\n");
75 return -1;
76 }
77 ptn = ptable_find(ptable, "misc");
78
79 if (ptn == NULL) {
80 dprintf(CRITICAL, "ERROR: No misc partition found\n");
81 return -1;
82 }
83
84 offset += (pagesize * MISC_COMMAND_PAGE);
Greg Griscod6250552011-06-29 14:40:23 -070085 if (flash_read(ptn, offset, (void *) buf, pagesize)) {
Shashank Mittal024c0332010-02-03 11:44:00 -080086 dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
87 return -1;
88 }
89 memcpy(out, buf, sizeof(*out));
90 return 0;
91}
92
93int set_recovery_message(const struct recovery_message *in)
94{
95 struct ptentry *ptn;
96 struct ptable *ptable;
97 unsigned offset = 0;
98 unsigned pagesize = flash_page_size();
99 unsigned n = 0;
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300100 void *scratch_addr = target_get_scratch_address();
Shashank Mittal024c0332010-02-03 11:44:00 -0800101
102 ptable = flash_get_ptable();
103
104 if (ptable == NULL) {
105 dprintf(CRITICAL, "ERROR: Partition table not found\n");
106 return -1;
107 }
108 ptn = ptable_find(ptable, "misc");
109
110 if (ptn == NULL) {
111 dprintf(CRITICAL, "ERROR: No misc partition found\n");
112 return -1;
113 }
114
115 n = pagesize * (MISC_COMMAND_PAGE + 1);
116
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300117 if (flash_read(ptn, offset, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800118 dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
119 return -1;
120 }
121
122 offset += (pagesize * MISC_COMMAND_PAGE);
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300123 offset += (unsigned) scratch_addr;
Greg Griscod6250552011-06-29 14:40:23 -0700124 memcpy((void *) offset, in, sizeof(*in));
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300125 if (flash_write(ptn, 0, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800126 dprintf(CRITICAL, "ERROR: flash write fail!\n");
127 return -1;
128 }
Greg Griscod6250552011-06-29 14:40:23 -0700129 return 0;
Shashank Mittal024c0332010-02-03 11:44:00 -0800130}
131
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700132static int set_ssd_radio_update (char *name)
133{
134 struct ptentry *ptn;
135 struct ptable *ptable;
Mayank Groverba853de2017-06-15 16:20:18 +0530136 unsigned int *ssd_cookie;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700137 unsigned pagesize = flash_page_size();
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700138
139 ptable = flash_get_ptable();
140 if (ptable == NULL) {
141 dprintf(CRITICAL, "ERROR: Partition table not found\n");
142 return -1;
143 }
144
Mayank Groverba853de2017-06-15 16:20:18 +0530145 ssd_cookie = malloc(pagesize);
146 if (!ssd_cookie){
147 dprintf(CRITICAL, "ERROR: Memory allocation failure\n");
148 return -1;
149 }
150 memset(ssd_cookie, 0, pagesize);
151 ssd_cookie[0] = 0x53534443;
152 ssd_cookie[1] = 0x4F4F4B49;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700153
154 ptn = ptable_find(ptable, name);
155 if (ptn == NULL) {
156 dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
Mayank Groverba853de2017-06-15 16:20:18 +0530157 goto out;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700158 }
159
Mayank Groverba853de2017-06-15 16:20:18 +0530160 if (flash_write(ptn, 0, ssd_cookie, pagesize)) {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700161 dprintf(CRITICAL, "ERROR: flash write fail!\n");
Mayank Groverba853de2017-06-15 16:20:18 +0530162 goto out;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700163 }
164
Mayank Groverba853de2017-06-15 16:20:18 +0530165 free(ssd_cookie);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700166 dprintf(INFO, "FOTA partition written successfully!");
167 return 0;
Mayank Groverba853de2017-06-15 16:20:18 +0530168out:
169 free(ssd_cookie);
170 return -1;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700171}
172
173int get_boot_info_apps (char type, unsigned int *status)
174{
175 boot_info_for_apps apps_boot_info;
176 int ret = 0;
177
178 ret = smem_read_alloc_entry(SMEM_BOOT_INFO_FOR_APPS,
179 &apps_boot_info, sizeof(apps_boot_info));
180 if (ret)
181 {
182 dprintf(CRITICAL, "ERROR: unable to read shared memory for apps boot info %d\n",ret);
183 return ret;
184 }
185
186 dprintf(INFO,"boot flag %x update status %x\n",apps_boot_info.boot_flags,
187 apps_boot_info.status.update_status);
188
189 if(type == BOOT_FLAGS)
190 *status = apps_boot_info.boot_flags;
191 else if(type == UPDATE_STATUS)
192 *status = apps_boot_info.status.update_status;
193
194 return ret;
195}
196
Shashank Mittal024c0332010-02-03 11:44:00 -0800197/* Bootloader / Recovery Flow
198 *
199 * On every boot, the bootloader will read the recovery_message
200 * from flash and check the command field. The bootloader should
201 * deal with the command field not having a 0 terminator correctly
202 * (so as to not crash if the block is invalid or corrupt).
203 *
204 * The bootloader will have to publish the partition that contains
205 * the recovery_message to the linux kernel so it can update it.
206 *
207 * if command == "boot-recovery" -> boot recovery.img
208 * else if command == "update-radio" -> update radio image (below)
209 * else -> boot boot.img (normal boot)
210 *
211 * Radio Update Flow
212 * 1. the bootloader will attempt to load and validate the header
213 * 2. if the header is invalid, status="invalid-update", goto #8
214 * 3. display the busy image on-screen
215 * 4. if the update image is invalid, status="invalid-radio-image", goto #8
216 * 5. attempt to update the firmware (depending on the command)
217 * 6. if successful, status="okay", goto #8
218 * 7. if failed, and the old image can still boot, status="failed-update"
219 * 8. write the recovery_message, leaving the recovery field
220 * unchanged, updating status, and setting command to
221 * "boot-recovery"
222 * 9. reboot
223 *
224 * The bootloader will not modify or erase the cache partition.
225 * It is recovery's responsibility to clean up the mess afterwards.
226 */
227
228int recovery_init (void)
229{
230 struct recovery_message msg;
Shashank Mittal024c0332010-02-03 11:44:00 -0800231 char partition_name[32];
232 unsigned valid_command = 0;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700233 int update_status = 0;
Shashank Mittal024c0332010-02-03 11:44:00 -0800234
235 // get recovery message
Greg Griscod6250552011-06-29 14:40:23 -0700236 if (get_recovery_message(&msg))
Shashank Mittal024c0332010-02-03 11:44:00 -0800237 return -1;
Shashank Mittal024c0332010-02-03 11:44:00 -0800238 msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
Pavel Nedev96a9aea2013-02-26 15:16:26 -0800239 if (msg.command[0] != 0 && msg.command[0] != 255) {
240 dprintf(INFO,"Recovery command: %d %s\n",
241 sizeof(msg.command), msg.command);
242 }
Shashank Mittal024c0332010-02-03 11:44:00 -0800243
Mayank Grover98c4c742019-04-25 17:21:37 +0530244 if (!strcmp(RECOVERY_BOOT_RECOVERY_CMD, msg.command))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700245 {
246 if(!strcmp("RADIO",msg.status))
247 {
248 /* We're now here due to radio update, so check for update status */
Greg Griscod2471ef2011-07-14 13:00:42 -0700249 int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700250
251 if(!ret && (update_status & 0x01))
252 {
253 dprintf(INFO,"radio update success\n");
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700254 strlcpy(msg.status, "OKAY", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700255 }
256 else
257 {
258 dprintf(INFO,"radio update failed\n");
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700259 strlcpy(msg.status, "failed-update", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700260 }
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700261 strlcpy(msg.command, "", sizeof(msg.command)); // clearing recovery command
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700262 set_recovery_message(&msg); // send recovery message
263 boot_into_recovery = 1; // Boot in recovery mode
264 return 0;
265 }
Shashank Mittal024c0332010-02-03 11:44:00 -0800266 boot_into_recovery = 1; // Boot in recovery mode
267 return 0;
268 }
269
Luca Weiss7f063f12022-04-14 11:06:43 +0200270 if (!strcmp(RECOVERY_BOOT_FASTBOOT_CMD, msg.command)) {
Mayank Grover98c4c742019-04-25 17:21:37 +0530271 boot_into_recovery = 1; // Boot in userspace fastboot mode
272 return 0;
273 }
274
Shashank Mittal024c0332010-02-03 11:44:00 -0800275 if (!strcmp("update-radio",msg.command)) {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700276 dprintf(INFO,"start radio update\n");
Shashank Mittal024c0332010-02-03 11:44:00 -0800277 valid_command = 1;
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700278 strlcpy(partition_name, "FOTA", sizeof(partition_name));
Shashank Mittal024c0332010-02-03 11:44:00 -0800279 }
280
281 //Todo: Add support for bootloader update too.
282
283 if(!valid_command) {
284 //We need not to do anything
285 return 0; // Boot in normal mode
286 }
287
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700288 if (set_ssd_radio_update(partition_name)) {
289 /* If writing to FOTA partition fails */
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700290 strlcpy(msg.command, "", sizeof(msg.command));
291 strlcpy(msg.status, "failed-update", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700292 goto SEND_RECOVERY_MSG;
293 }
294 else {
295 /* Setting this to check the radio update status */
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700296 strlcpy(msg.command, "boot-recovery", sizeof(msg.command));
Ajay Dudanif4caa942011-10-02 08:57:15 -0700297 strlcpy(msg.status, "RADIO", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700298 goto SEND_RECOVERY_MSG;
299 }
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700300 strlcpy(msg.status, "OKAY", sizeof(msg.status));
Shashank Mittal024c0332010-02-03 11:44:00 -0800301
302SEND_RECOVERY_MSG:
Shashank Mittal024c0332010-02-03 11:44:00 -0800303 set_recovery_message(&msg); // send recovery message
304 boot_into_recovery = 1; // Boot in recovery mode
305 reboot_device(0);
306 return 0;
307}
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700308
309static int emmc_set_recovery_msg(struct recovery_message *out)
310{
311 char *ptn_name = "misc";
312 unsigned long long ptn = 0;
Mayank Grover9db97242017-06-16 12:41:56 +0530313 unsigned blocksize = mmc_get_device_blocksize();
314 unsigned int size = ROUND_TO_PAGE(sizeof(*out), (unsigned)blocksize - 1);
315 unsigned char *data = NULL;
316 int ret = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700317 int index = INVALID_PTN;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700318
Mayank Grover9db97242017-06-16 12:41:56 +0530319 data = malloc(size);
320 if(!data)
321 {
322 dprintf(CRITICAL,"memory allocation error \n");
323 ret = -1;
324 goto out;
325 }
326
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530327 index = partition_get_index((const char *) ptn_name);
Kinson Chikf1a43512011-07-14 11:28:39 -0700328 ptn = partition_get_offset(index);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700329 mmc_set_lun(partition_get_lun(index));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700330 if(ptn == 0) {
331 dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
Mayank Grover9db97242017-06-16 12:41:56 +0530332 ret = -1;
333 goto out;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700334 }
Mayank Grover9db97242017-06-16 12:41:56 +0530335 memset(data, 0, size);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700336 memcpy(data, out, sizeof(*out));
337 if (mmc_write(ptn , size, (unsigned int*)data)) {
338 dprintf(CRITICAL,"mmc write failure %s %d\n",ptn_name, sizeof(*out));
Mayank Grover9db97242017-06-16 12:41:56 +0530339 ret = -1;
340 goto out;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700341 }
Mayank Grover9db97242017-06-16 12:41:56 +0530342out:
343 if (data)
344 free(data);
345 return ret;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700346}
347
348static int emmc_get_recovery_msg(struct recovery_message *in)
349{
350 char *ptn_name = "misc";
351 unsigned long long ptn = 0;
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700352 unsigned int size;
Kinson Chikf1a43512011-07-14 11:28:39 -0700353 int index = INVALID_PTN;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700354
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700355 size = mmc_get_device_blocksize();
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530356 index = partition_get_index((const char *) ptn_name);
Channagoud Kadabif2805632015-01-07 16:46:50 -0800357 if (index < 0)
358 {
359 dprintf(CRITICAL, "%s: Partition not found\n", ptn_name);
360 return -1;
361 }
362
Kinson Chikf1a43512011-07-14 11:28:39 -0700363 ptn = partition_get_offset(index);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700364 mmc_set_lun(partition_get_lun(index));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700365 if(ptn == 0) {
366 dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
367 return -1;
368 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700369 if (mmc_read(ptn , (unsigned int*)in, size)) {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700370 dprintf(CRITICAL,"mmc read failure %s %d\n",ptn_name, size);
371 return -1;
372 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700373
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700374 return 0;
375}
376
Mayank Grover98c4c742019-04-25 17:21:37 +0530377/* Generic funcition to write misc commands. */
378int send_recovery_cmd(const char *command)
379{
380 struct recovery_message msg;
381 int status = 0;
382 memset(&msg, 0, sizeof(msg));
383
384 /* Populate command to msg */
385 snprintf(msg.command,
386 sizeof(msg.command),
387 command);
388
389 dprintf(INFO,"Recovery command: %s\n", msg.command);
390 if (target_is_emmc_boot())
391 /* Update emmc partition */
392 status = emmc_set_recovery_msg(&msg);
393 else
394 status = set_recovery_message(&msg);
395
396 return status;
397}
398
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700399int _emmc_recovery_init(void)
400{
401 int update_status = 0;
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700402 struct recovery_message *msg;
403 uint32_t block_size = 0;
404
405 block_size = mmc_get_device_blocksize();
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700406
407 // get recovery message
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700408 msg = (struct recovery_message *)memalign(CACHE_LINE, block_size);
409 ASSERT(msg);
410
411 if(emmc_get_recovery_msg(msg))
412 {
413 if(msg)
414 free(msg);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700415 return -1;
Pavel Nedev96a9aea2013-02-26 15:16:26 -0800416 }
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700417
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700418 msg->command[sizeof(msg->command)-1] = '\0'; //Ensure termination
419 if (msg->command[0] != 0 && msg->command[0] != 255) {
420 dprintf(INFO,"Recovery command: %d %s\n",
421 sizeof(msg->command), msg->command);
422 }
423
Mayank Grover98c4c742019-04-25 17:21:37 +0530424 if (!strcmp(msg->command, RECOVERY_BOOT_RECOVERY_CMD)) {
425 boot_into_recovery = 1;
426 }
427
Luca Weiss7f063f12022-04-14 11:06:43 +0200428 if (!strcmp(msg->command, RECOVERY_BOOT_FASTBOOT_CMD)) {
Stanimir Varbanovbe041992013-04-26 14:29:21 +0300429 boot_into_recovery = 1;
430 }
431
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700432 if (!strcmp("update-radio",msg->command))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700433 {
434 /* We're now here due to radio update, so check for update status */
Greg Griscod2471ef2011-07-14 13:00:42 -0700435 int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700436
437 if(!ret && (update_status & 0x01))
438 {
439 dprintf(INFO,"radio update success\n");
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700440 strlcpy(msg->status, "OKAY", sizeof(msg->status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700441 }
442 else
443 {
444 dprintf(INFO,"radio update failed\n");
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700445 strlcpy(msg->status, "failed-update", sizeof(msg->status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700446 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700447 boot_into_recovery = 1; // Boot in recovery mode
448 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700449 if (!strcmp("reset-device-info",msg->command))
Shashank Mittal162244e2011-08-08 19:01:25 -0700450 {
451 reset_device_info();
452 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700453 if (!strcmp("root-detect",msg->command))
Shashank Mittal162244e2011-08-08 19:01:25 -0700454 {
455 set_device_root();
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700456 }
457 else
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700458 goto out;// do nothing
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700459
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700460 strlcpy(msg->command, "", sizeof(msg->command)); // clearing recovery command
461 emmc_set_recovery_msg(msg); // send recovery message
462
463out:
464 if(msg)
465 free(msg);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700466 return 0;
467}
Pavel Nedeva1e62322013-04-05 15:21:36 +0300468
469static int read_misc(unsigned page_offset, void *buf, unsigned size)
470{
471 const char *ptn_name = "misc";
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700472 uint32_t pagesize = get_page_size();
Pavel Nedeva1e62322013-04-05 15:21:36 +0300473 unsigned offset;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300474
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700475 if (size == 0 || buf == NULL)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300476 return -1;
477
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700478 offset = page_offset * pagesize;
479
Pavel Nedeva1e62322013-04-05 15:21:36 +0300480 if (target_is_emmc_boot())
481 {
482 int index;
483 unsigned long long ptn;
484 unsigned long long ptn_size;
485
486 index = partition_get_index(ptn_name);
487 if (index == INVALID_PTN)
488 {
489 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
490 return -1;
491 }
492
493 ptn = partition_get_offset(index);
494 ptn_size = partition_get_size(index);
495
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700496 mmc_set_lun(partition_get_lun(index));
497
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700498 if (ptn_size < offset + size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300499 {
500 dprintf(CRITICAL, "Read request out of '%s' boundaries\n",
501 ptn_name);
502 return -1;
503 }
504
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700505 if (mmc_read(ptn + offset, (unsigned int *)buf, size))
Pavel Nedeva1e62322013-04-05 15:21:36 +0300506 {
507 dprintf(CRITICAL, "Reading MMC failed\n");
508 return -1;
509 }
510 }
511 else
512 {
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700513 dprintf(CRITICAL, "Misc partition not supported for NAND targets.\n");
514 return -1;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300515 }
516
Pavel Nedeva1e62322013-04-05 15:21:36 +0300517 return 0;
518}
519
Pavel Nedevc728bb32013-04-05 16:58:05 +0300520int write_misc(unsigned page_offset, void *buf, unsigned size)
521{
522 const char *ptn_name = "misc";
523 void *scratch_addr = target_get_scratch_address();
524 unsigned offset;
525 unsigned aligned_size;
526
527 if (size == 0 || buf == NULL || scratch_addr == NULL)
528 return -1;
529
530 if (target_is_emmc_boot())
531 {
532 int index;
533 unsigned long long ptn;
534 unsigned long long ptn_size;
535
536 index = partition_get_index(ptn_name);
537 if (index == INVALID_PTN)
538 {
539 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
540 return -1;
541 }
542
543 ptn = partition_get_offset(index);
544 ptn_size = partition_get_size(index);
Rahul Shaharef7a5f8b2021-02-04 16:51:36 +0530545#if VIRTUAL_AB_OTA
546 offset = page_offset;
547#else
Pavel Nedevc728bb32013-04-05 16:58:05 +0300548 offset = page_offset * BLOCK_SIZE;
Rahul Shaharef7a5f8b2021-02-04 16:51:36 +0530549#endif
Pavel Nedevc728bb32013-04-05 16:58:05 +0300550 aligned_size = ROUND_TO_PAGE(size, (unsigned)BLOCK_SIZE - 1);
551 if (ptn_size < offset + aligned_size)
552 {
553 dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
554 ptn_name);
555 return -1;
556 }
557
Mayank Grover467bf492017-10-24 12:27:53 +0530558 /* This will ensure, we zeored out any extra bytes
559 we will push to emmc, to prevent information leak */
560 if (aligned_size > size)
561 memset((scratch_addr + size), 0, (aligned_size-size));
562
Pavel Nedevc728bb32013-04-05 16:58:05 +0300563 if (scratch_addr != buf)
564 memcpy(scratch_addr, buf, size);
Channagoud Kadabi2776b652015-08-28 15:41:26 -0700565
566 /* Set Lun for misc partition */
567 mmc_set_lun(partition_get_lun(index));
568
Pavel Nedevc728bb32013-04-05 16:58:05 +0300569 if (mmc_write(ptn + offset, aligned_size, (unsigned int *)scratch_addr))
570 {
571 dprintf(CRITICAL, "Writing MMC failed\n");
572 return -1;
573 }
574 }
575 else
576 {
577 struct ptentry *ptn;
578 struct ptable *ptable;
579 unsigned pagesize = flash_page_size();
580
581 ptable = flash_get_ptable();
582 if (ptable == NULL)
583 {
584 dprintf(CRITICAL, "Partition table not found\n");
585 return -1;
586 }
587
588 ptn = ptable_find(ptable, ptn_name);
589 if (ptn == NULL)
590 {
591 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
592 return -1;
593 }
594
595 offset = page_offset * pagesize;
596 aligned_size = ROUND_TO_PAGE(size, pagesize - 1);
597 if (ptn->length < offset + aligned_size)
598 {
599 dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
600 ptn_name);
601 return -1;
602 }
603
Mayank Grover467bf492017-10-24 12:27:53 +0530604 /* This will ensure, we zeored out any extra bytes
605 we will push, to prevent information leak */
606 if (aligned_size > size)
607 memset((scratch_addr + size), 0, (aligned_size-size));
608
Pavel Nedevc728bb32013-04-05 16:58:05 +0300609 if (scratch_addr != buf)
610 memcpy(scratch_addr, buf, size);
Mayank Grover467bf492017-10-24 12:27:53 +0530611
Pavel Nedevc728bb32013-04-05 16:58:05 +0300612 if (flash_write(ptn, offset, scratch_addr, aligned_size)) {
613 dprintf(CRITICAL, "Writing flash failed\n");
614 return -1;
615 }
616 }
617
618 return 0;
619}
620
Rahul Shaharee7baede2021-02-02 13:23:57 +0530621static MiscVirtualABMessage *VirtualAbMsg = NULL;
622
Rahul Shaharef7a5f8b2021-02-04 16:51:36 +0530623int SetSnapshotMergeStatus (VirtualAbMergeStatus MergeStatus)
624{
625 int Status = 1;
626 VirtualAbMergeStatus OldMergeStatus;
627
628 if (target_is_emmc_boot())
629 {
630 OldMergeStatus = VirtualAbMsg->MergeStatus;
631 VirtualAbMsg->MergeStatus = MergeStatus;
632
633 Status = write_misc(MISC_VIRTUALAB_OFFSET, &VirtualAbMsg, sizeof(VirtualAbMsg));
634 if (Status != 0) {
635 dprintf(CRITICAL, "Write the VirtualAbMsg failed\n");
636 VirtualAbMsg->MergeStatus = OldMergeStatus;
637 }
638 }
639 return Status;
640}
641
Rahul Shaharee7baede2021-02-02 13:23:57 +0530642VirtualAbMergeStatus GetSnapshotMergeStatus (void)
643{
644 VirtualAbMergeStatus MergeStatus = NONE_MERGE_STATUS;
645 uint32_t pagesize = get_page_size();
646
647 if (target_is_emmc_boot())
648 {
649 if (VirtualAbMsg == NULL) {
650 if(read_misc(MISC_VIRTUALAB_OFFSET, (void *)&VirtualAbMsg,
651 pagesize))
652 {
653 dprintf(CRITICAL,"Error reading virtualab msg from misc partition\n");
654 return MergeStatus;
655 }
656
657 if (VirtualAbMsg->Magic != MISC_VIRTUAL_AB_MAGIC_HEADER ||
658 VirtualAbMsg->Version != MISC_VIRTUAL_AB_MESSAGE_VERSION) {
659
660 dprintf(CRITICAL,"Error read virtualab msg version:%u magic:%u not valid\n",
661 VirtualAbMsg->Version,VirtualAbMsg->Magic);
662
663 free(VirtualAbMsg);
664 VirtualAbMsg = NULL;
665 }
666 else
667 {
668 dprintf(CRITICAL,"read virtualab MergeStatus:%x\n", VirtualAbMsg->MergeStatus);
669 }
670 }
671
672 if (VirtualAbMsg)
673 MergeStatus = VirtualAbMsg->MergeStatus;
674 }
675 return MergeStatus;
676}
677
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700678int get_ffbm(char *ffbm, unsigned size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300679{
680 const char *ffbm_cmd = "ffbm-";
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700681 uint32_t page_size = get_page_size();
682 char *ffbm_page_buffer = NULL;
683 int retval = 0;
684 if (size < FFBM_MODE_BUF_SIZE || size >= page_size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300685 {
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700686 dprintf(CRITICAL, "Invalid size argument passed to get_ffbm\n");
687 retval = -1;
688 goto cleanup;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300689 }
Parth Dixit75b16812016-04-05 19:17:17 +0530690 ffbm_page_buffer = (char*)memalign(CACHE_LINE, page_size);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700691 if (!ffbm_page_buffer)
692 {
693 dprintf(CRITICAL, "Failed to alloc buffer for ffbm cookie\n");
694 retval = -1;
695 goto cleanup;
696 }
697 if (read_misc(0, ffbm_page_buffer, page_size))
Pavel Nedeva1e62322013-04-05 15:21:36 +0300698 {
699 dprintf(CRITICAL, "Error reading MISC partition\n");
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700700 retval = -1;
701 goto cleanup;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300702 }
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700703 ffbm_page_buffer[size] = '\0';
704 if (strncmp(ffbm_cmd, ffbm_page_buffer, strlen(ffbm_cmd)))
705 {
706 retval = 0;
707 goto cleanup;
708 }
709 else
710 {
711 if (strlcpy(ffbm, ffbm_page_buffer, size) <
712 FFBM_MODE_BUF_SIZE -1)
713 {
714 dprintf(CRITICAL, "Invalid string in misc partition\n");
715 retval = -1;
716 }
717 else
718 retval = 1;
719 }
720cleanup:
721 if(ffbm_page_buffer)
722 free(ffbm_page_buffer);
723 return retval;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300724}
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700725
726