blob: 8aa4a8cdfa3b4fac2654d6fe3dd886199e85cc0e [file] [log] [blame]
Parth Dixit75b16812016-04-05 19:17:17 +05301/* Copyright (c) 2010-2016, 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>
Shashank Mittal024c0332010-02-03 11:44:00 -080046
47#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
53#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Shashank Mittal024c0332010-02-03 11:44:00 -080054
55static const int MISC_PAGES = 3; // number of pages to save
56static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
57static char buf[4096];
Pavel Nedeva1e62322013-04-05 15:21:36 +030058
Shashank Mittal024c0332010-02-03 11:44:00 -080059unsigned boot_into_recovery = 0;
60
Deepa Dinamani41fa8d62013-05-23 13:25:36 -070061extern uint32_t get_page_size();
Shashank Mittal162244e2011-08-08 19:01:25 -070062extern void reset_device_info();
63extern void set_device_root();
Shashank Mittal024c0332010-02-03 11:44:00 -080064
65int get_recovery_message(struct recovery_message *out)
66{
67 struct ptentry *ptn;
68 struct ptable *ptable;
69 unsigned offset = 0;
70 unsigned pagesize = flash_page_size();
71
72 ptable = flash_get_ptable();
73
74 if (ptable == NULL) {
75 dprintf(CRITICAL, "ERROR: Partition table not found\n");
76 return -1;
77 }
78 ptn = ptable_find(ptable, "misc");
79
80 if (ptn == NULL) {
81 dprintf(CRITICAL, "ERROR: No misc partition found\n");
82 return -1;
83 }
84
85 offset += (pagesize * MISC_COMMAND_PAGE);
Greg Griscod6250552011-06-29 14:40:23 -070086 if (flash_read(ptn, offset, (void *) buf, pagesize)) {
Shashank Mittal024c0332010-02-03 11:44:00 -080087 dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
88 return -1;
89 }
90 memcpy(out, buf, sizeof(*out));
91 return 0;
92}
93
94int set_recovery_message(const struct recovery_message *in)
95{
96 struct ptentry *ptn;
97 struct ptable *ptable;
98 unsigned offset = 0;
99 unsigned pagesize = flash_page_size();
100 unsigned n = 0;
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300101 void *scratch_addr = target_get_scratch_address();
Shashank Mittal024c0332010-02-03 11:44:00 -0800102
103 ptable = flash_get_ptable();
104
105 if (ptable == NULL) {
106 dprintf(CRITICAL, "ERROR: Partition table not found\n");
107 return -1;
108 }
109 ptn = ptable_find(ptable, "misc");
110
111 if (ptn == NULL) {
112 dprintf(CRITICAL, "ERROR: No misc partition found\n");
113 return -1;
114 }
115
116 n = pagesize * (MISC_COMMAND_PAGE + 1);
117
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300118 if (flash_read(ptn, offset, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800119 dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
120 return -1;
121 }
122
123 offset += (pagesize * MISC_COMMAND_PAGE);
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300124 offset += (unsigned) scratch_addr;
Greg Griscod6250552011-06-29 14:40:23 -0700125 memcpy((void *) offset, in, sizeof(*in));
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300126 if (flash_write(ptn, 0, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800127 dprintf(CRITICAL, "ERROR: flash write fail!\n");
128 return -1;
129 }
Greg Griscod6250552011-06-29 14:40:23 -0700130 return 0;
Shashank Mittal024c0332010-02-03 11:44:00 -0800131}
132
133int read_update_header_for_bootloader(struct update_header *header)
134{
135 struct ptentry *ptn;
136 struct ptable *ptable;
137 unsigned offset = 0;
138 unsigned pagesize = flash_page_size();
139
140 ptable = flash_get_ptable();
141 if (ptable == NULL) {
142 dprintf(CRITICAL, "ERROR: Partition table not found\n");
143 return -1;
144 }
145 ptn = ptable_find(ptable, "cache");
146
147 if (ptn == NULL) {
148 dprintf(CRITICAL, "ERROR: No cache partition found\n");
149 return -1;
150 }
151 if (flash_read(ptn, offset, buf, pagesize)) {
152 dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
153 return -1;
154 }
155 memcpy(header, buf, sizeof(*header));
156
Greg Griscod6250552011-06-29 14:40:23 -0700157 if (strncmp((char *) header->MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE))
Shashank Mittal024c0332010-02-03 11:44:00 -0800158 {
159 return -1;
160 }
161 return 0;
162}
163
164int update_firmware_image (struct update_header *header, char *name)
165{
166 struct ptentry *ptn;
167 struct ptable *ptable;
168 unsigned offset = 0;
169 unsigned pagesize = flash_page_size();
170 unsigned pagemask = pagesize -1;
171 unsigned n = 0;
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300172 void *scratch_addr = target_get_scratch_address();
Shashank Mittal024c0332010-02-03 11:44:00 -0800173
174 ptable = flash_get_ptable();
175 if (ptable == NULL) {
176 dprintf(CRITICAL, "ERROR: Partition table not found\n");
177 return -1;
178 }
179
180 ptn = ptable_find(ptable, "cache");
181 if (ptn == NULL) {
182 dprintf(CRITICAL, "ERROR: No cache partition found\n");
183 return -1;
184 }
185
186 offset += header->image_offset;
187 n = (header->image_length + pagemask) & (~pagemask);
188
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300189 if (flash_read(ptn, offset, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800190 dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
191 return -1;
192 }
193
194 ptn = ptable_find(ptable, name);
195 if (ptn == NULL) {
196 dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
197 return -1;
198 }
199
Pavel Nedev5d4a7052013-05-13 15:14:45 +0300200 if (flash_write(ptn, 0, scratch_addr, n)) {
Shashank Mittal024c0332010-02-03 11:44:00 -0800201 dprintf(CRITICAL, "ERROR: flash write fail!\n");
202 return -1;
203 }
204
205 dprintf(INFO, "Partition writen successfully!");
206 return 0;
207}
208
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700209static int set_ssd_radio_update (char *name)
210{
211 struct ptentry *ptn;
212 struct ptable *ptable;
213 unsigned int ssd_cookie[2] = {0x53534443, 0x4F4F4B49};
214 unsigned pagesize = flash_page_size();
215 unsigned pagemask = pagesize -1;
216 unsigned n = 0;
217
218 ptable = flash_get_ptable();
219 if (ptable == NULL) {
220 dprintf(CRITICAL, "ERROR: Partition table not found\n");
221 return -1;
222 }
223
224 n = (sizeof(ssd_cookie) + pagemask) & (~pagemask);
225
226 ptn = ptable_find(ptable, name);
227 if (ptn == NULL) {
228 dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
229 return -1;
230 }
231
232 if (flash_write(ptn, 0, ssd_cookie, n)) {
233 dprintf(CRITICAL, "ERROR: flash write fail!\n");
234 return -1;
235 }
236
237 dprintf(INFO, "FOTA partition written successfully!");
238 return 0;
239}
240
241int get_boot_info_apps (char type, unsigned int *status)
242{
243 boot_info_for_apps apps_boot_info;
244 int ret = 0;
245
246 ret = smem_read_alloc_entry(SMEM_BOOT_INFO_FOR_APPS,
247 &apps_boot_info, sizeof(apps_boot_info));
248 if (ret)
249 {
250 dprintf(CRITICAL, "ERROR: unable to read shared memory for apps boot info %d\n",ret);
251 return ret;
252 }
253
254 dprintf(INFO,"boot flag %x update status %x\n",apps_boot_info.boot_flags,
255 apps_boot_info.status.update_status);
256
257 if(type == BOOT_FLAGS)
258 *status = apps_boot_info.boot_flags;
259 else if(type == UPDATE_STATUS)
260 *status = apps_boot_info.status.update_status;
261
262 return ret;
263}
264
Shashank Mittal024c0332010-02-03 11:44:00 -0800265/* Bootloader / Recovery Flow
266 *
267 * On every boot, the bootloader will read the recovery_message
268 * from flash and check the command field. The bootloader should
269 * deal with the command field not having a 0 terminator correctly
270 * (so as to not crash if the block is invalid or corrupt).
271 *
272 * The bootloader will have to publish the partition that contains
273 * the recovery_message to the linux kernel so it can update it.
274 *
275 * if command == "boot-recovery" -> boot recovery.img
276 * else if command == "update-radio" -> update radio image (below)
277 * else -> boot boot.img (normal boot)
278 *
279 * Radio Update Flow
280 * 1. the bootloader will attempt to load and validate the header
281 * 2. if the header is invalid, status="invalid-update", goto #8
282 * 3. display the busy image on-screen
283 * 4. if the update image is invalid, status="invalid-radio-image", goto #8
284 * 5. attempt to update the firmware (depending on the command)
285 * 6. if successful, status="okay", goto #8
286 * 7. if failed, and the old image can still boot, status="failed-update"
287 * 8. write the recovery_message, leaving the recovery field
288 * unchanged, updating status, and setting command to
289 * "boot-recovery"
290 * 9. reboot
291 *
292 * The bootloader will not modify or erase the cache partition.
293 * It is recovery's responsibility to clean up the mess afterwards.
294 */
295
296int recovery_init (void)
297{
298 struct recovery_message msg;
Shashank Mittal024c0332010-02-03 11:44:00 -0800299 char partition_name[32];
300 unsigned valid_command = 0;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700301 int update_status = 0;
Shashank Mittal024c0332010-02-03 11:44:00 -0800302
303 // get recovery message
Greg Griscod6250552011-06-29 14:40:23 -0700304 if (get_recovery_message(&msg))
Shashank Mittal024c0332010-02-03 11:44:00 -0800305 return -1;
Shashank Mittal024c0332010-02-03 11:44:00 -0800306 msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
Pavel Nedev96a9aea2013-02-26 15:16:26 -0800307 if (msg.command[0] != 0 && msg.command[0] != 255) {
308 dprintf(INFO,"Recovery command: %d %s\n",
309 sizeof(msg.command), msg.command);
310 }
Shashank Mittal024c0332010-02-03 11:44:00 -0800311
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700312 if (!strcmp("boot-recovery",msg.command))
313 {
314 if(!strcmp("RADIO",msg.status))
315 {
316 /* We're now here due to radio update, so check for update status */
Greg Griscod2471ef2011-07-14 13:00:42 -0700317 int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700318
319 if(!ret && (update_status & 0x01))
320 {
321 dprintf(INFO,"radio update success\n");
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700322 strlcpy(msg.status, "OKAY", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700323 }
324 else
325 {
326 dprintf(INFO,"radio update failed\n");
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700327 strlcpy(msg.status, "failed-update", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700328 }
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700329 strlcpy(msg.command, "", sizeof(msg.command)); // clearing recovery command
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700330 set_recovery_message(&msg); // send recovery message
331 boot_into_recovery = 1; // Boot in recovery mode
332 return 0;
333 }
334
Shashank Mittal024c0332010-02-03 11:44:00 -0800335 valid_command = 1;
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700336 strlcpy(msg.command, "", sizeof(msg.command)); // to safe against multiple reboot into recovery
337 strlcpy(msg.status, "OKAY", sizeof(msg.status));
Shashank Mittal024c0332010-02-03 11:44:00 -0800338 set_recovery_message(&msg); // send recovery message
339 boot_into_recovery = 1; // Boot in recovery mode
340 return 0;
341 }
342
343 if (!strcmp("update-radio",msg.command)) {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700344 dprintf(INFO,"start radio update\n");
Shashank Mittal024c0332010-02-03 11:44:00 -0800345 valid_command = 1;
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700346 strlcpy(partition_name, "FOTA", sizeof(partition_name));
Shashank Mittal024c0332010-02-03 11:44:00 -0800347 }
348
349 //Todo: Add support for bootloader update too.
350
351 if(!valid_command) {
352 //We need not to do anything
353 return 0; // Boot in normal mode
354 }
355
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700356#ifdef OLD_FOTA_UPGRADE
Shashank Mittal024c0332010-02-03 11:44:00 -0800357 if (read_update_header_for_bootloader(&header)) {
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700358 strlcpy(msg.status, "invalid-update", sizeof(msg.status));
Shashank Mittal024c0332010-02-03 11:44:00 -0800359 goto SEND_RECOVERY_MSG;
360 }
361
362 if (update_firmware_image (&header, partition_name)) {
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700363 strlcpy(msg.status, "failed-update", sizeof(msg.status));
Shashank Mittal024c0332010-02-03 11:44:00 -0800364 goto SEND_RECOVERY_MSG;
365 }
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700366#else
367 if (set_ssd_radio_update(partition_name)) {
368 /* If writing to FOTA partition fails */
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700369 strlcpy(msg.command, "", sizeof(msg.command));
370 strlcpy(msg.status, "failed-update", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700371 goto SEND_RECOVERY_MSG;
372 }
373 else {
374 /* Setting this to check the radio update status */
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700375 strlcpy(msg.command, "boot-recovery", sizeof(msg.command));
Ajay Dudanif4caa942011-10-02 08:57:15 -0700376 strlcpy(msg.status, "RADIO", sizeof(msg.status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700377 goto SEND_RECOVERY_MSG;
378 }
379#endif
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700380 strlcpy(msg.status, "OKAY", sizeof(msg.status));
Shashank Mittal024c0332010-02-03 11:44:00 -0800381
382SEND_RECOVERY_MSG:
Shashank Mittal024c0332010-02-03 11:44:00 -0800383 set_recovery_message(&msg); // send recovery message
384 boot_into_recovery = 1; // Boot in recovery mode
385 reboot_device(0);
386 return 0;
387}
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700388
389static int emmc_set_recovery_msg(struct recovery_message *out)
390{
391 char *ptn_name = "misc";
392 unsigned long long ptn = 0;
393 unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
394 unsigned char data[size];
Kinson Chikf1a43512011-07-14 11:28:39 -0700395 int index = INVALID_PTN;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700396
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530397 index = partition_get_index((const char *) ptn_name);
Kinson Chikf1a43512011-07-14 11:28:39 -0700398 ptn = partition_get_offset(index);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700399 mmc_set_lun(partition_get_lun(index));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700400 if(ptn == 0) {
401 dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
402 return -1;
403 }
404 memcpy(data, out, sizeof(*out));
405 if (mmc_write(ptn , size, (unsigned int*)data)) {
406 dprintf(CRITICAL,"mmc write failure %s %d\n",ptn_name, sizeof(*out));
407 return -1;
408 }
409 return 0;
410}
411
412static int emmc_get_recovery_msg(struct recovery_message *in)
413{
414 char *ptn_name = "misc";
415 unsigned long long ptn = 0;
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700416 unsigned int size;
Kinson Chikf1a43512011-07-14 11:28:39 -0700417 int index = INVALID_PTN;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700418
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700419 size = mmc_get_device_blocksize();
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530420 index = partition_get_index((const char *) ptn_name);
Channagoud Kadabif2805632015-01-07 16:46:50 -0800421 if (index < 0)
422 {
423 dprintf(CRITICAL, "%s: Partition not found\n", ptn_name);
424 return -1;
425 }
426
Kinson Chikf1a43512011-07-14 11:28:39 -0700427 ptn = partition_get_offset(index);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700428 mmc_set_lun(partition_get_lun(index));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700429 if(ptn == 0) {
430 dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
431 return -1;
432 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700433 if (mmc_read(ptn , (unsigned int*)in, size)) {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700434 dprintf(CRITICAL,"mmc read failure %s %d\n",ptn_name, size);
435 return -1;
436 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700437
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700438 return 0;
439}
440
441int _emmc_recovery_init(void)
442{
443 int update_status = 0;
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700444 struct recovery_message *msg;
445 uint32_t block_size = 0;
446
447 block_size = mmc_get_device_blocksize();
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700448
449 // get recovery message
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700450 msg = (struct recovery_message *)memalign(CACHE_LINE, block_size);
451 ASSERT(msg);
452
453 if(emmc_get_recovery_msg(msg))
454 {
455 if(msg)
456 free(msg);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700457 return -1;
Pavel Nedev96a9aea2013-02-26 15:16:26 -0800458 }
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700459
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700460 msg->command[sizeof(msg->command)-1] = '\0'; //Ensure termination
461 if (msg->command[0] != 0 && msg->command[0] != 255) {
462 dprintf(INFO,"Recovery command: %d %s\n",
463 sizeof(msg->command), msg->command);
464 }
465
vijay kumar32e2e3c2014-08-01 21:10:28 +0530466 if (!strcmp(msg->command, "boot-recovery")) {
Stanimir Varbanovbe041992013-04-26 14:29:21 +0300467 boot_into_recovery = 1;
468 }
469
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700470 if (!strcmp("update-radio",msg->command))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700471 {
472 /* We're now here due to radio update, so check for update status */
Greg Griscod2471ef2011-07-14 13:00:42 -0700473 int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700474
475 if(!ret && (update_status & 0x01))
476 {
477 dprintf(INFO,"radio update success\n");
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700478 strlcpy(msg->status, "OKAY", sizeof(msg->status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700479 }
480 else
481 {
482 dprintf(INFO,"radio update failed\n");
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700483 strlcpy(msg->status, "failed-update", sizeof(msg->status));
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700484 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700485 boot_into_recovery = 1; // Boot in recovery mode
486 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700487 if (!strcmp("reset-device-info",msg->command))
Shashank Mittal162244e2011-08-08 19:01:25 -0700488 {
489 reset_device_info();
490 }
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700491 if (!strcmp("root-detect",msg->command))
Shashank Mittal162244e2011-08-08 19:01:25 -0700492 {
493 set_device_root();
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700494 }
495 else
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700496 goto out;// do nothing
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700497
Sundarajan Srinivasan151c04d2014-07-17 15:52:12 -0700498 strlcpy(msg->command, "", sizeof(msg->command)); // clearing recovery command
499 emmc_set_recovery_msg(msg); // send recovery message
500
501out:
502 if(msg)
503 free(msg);
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700504 return 0;
505}
Pavel Nedeva1e62322013-04-05 15:21:36 +0300506
507static int read_misc(unsigned page_offset, void *buf, unsigned size)
508{
509 const char *ptn_name = "misc";
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700510 uint32_t pagesize = get_page_size();
Pavel Nedeva1e62322013-04-05 15:21:36 +0300511 unsigned offset;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300512
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700513 if (size == 0 || buf == NULL)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300514 return -1;
515
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700516 offset = page_offset * pagesize;
517
Pavel Nedeva1e62322013-04-05 15:21:36 +0300518 if (target_is_emmc_boot())
519 {
520 int index;
521 unsigned long long ptn;
522 unsigned long long ptn_size;
523
524 index = partition_get_index(ptn_name);
525 if (index == INVALID_PTN)
526 {
527 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
528 return -1;
529 }
530
531 ptn = partition_get_offset(index);
532 ptn_size = partition_get_size(index);
533
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700534 mmc_set_lun(partition_get_lun(index));
535
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700536 if (ptn_size < offset + size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300537 {
538 dprintf(CRITICAL, "Read request out of '%s' boundaries\n",
539 ptn_name);
540 return -1;
541 }
542
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700543 if (mmc_read(ptn + offset, (unsigned int *)buf, size))
Pavel Nedeva1e62322013-04-05 15:21:36 +0300544 {
545 dprintf(CRITICAL, "Reading MMC failed\n");
546 return -1;
547 }
548 }
549 else
550 {
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700551 dprintf(CRITICAL, "Misc partition not supported for NAND targets.\n");
552 return -1;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300553 }
554
Pavel Nedeva1e62322013-04-05 15:21:36 +0300555 return 0;
556}
557
Pavel Nedevc728bb32013-04-05 16:58:05 +0300558int write_misc(unsigned page_offset, void *buf, unsigned size)
559{
560 const char *ptn_name = "misc";
561 void *scratch_addr = target_get_scratch_address();
562 unsigned offset;
563 unsigned aligned_size;
564
565 if (size == 0 || buf == NULL || scratch_addr == NULL)
566 return -1;
567
568 if (target_is_emmc_boot())
569 {
570 int index;
571 unsigned long long ptn;
572 unsigned long long ptn_size;
573
574 index = partition_get_index(ptn_name);
575 if (index == INVALID_PTN)
576 {
577 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
578 return -1;
579 }
580
581 ptn = partition_get_offset(index);
582 ptn_size = partition_get_size(index);
583
584 offset = page_offset * BLOCK_SIZE;
585 aligned_size = ROUND_TO_PAGE(size, (unsigned)BLOCK_SIZE - 1);
586 if (ptn_size < offset + aligned_size)
587 {
588 dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
589 ptn_name);
590 return -1;
591 }
592
593 if (scratch_addr != buf)
594 memcpy(scratch_addr, buf, size);
Channagoud Kadabi2776b652015-08-28 15:41:26 -0700595
596 /* Set Lun for misc partition */
597 mmc_set_lun(partition_get_lun(index));
598
Pavel Nedevc728bb32013-04-05 16:58:05 +0300599 if (mmc_write(ptn + offset, aligned_size, (unsigned int *)scratch_addr))
600 {
601 dprintf(CRITICAL, "Writing MMC failed\n");
602 return -1;
603 }
604 }
605 else
606 {
607 struct ptentry *ptn;
608 struct ptable *ptable;
609 unsigned pagesize = flash_page_size();
610
611 ptable = flash_get_ptable();
612 if (ptable == NULL)
613 {
614 dprintf(CRITICAL, "Partition table not found\n");
615 return -1;
616 }
617
618 ptn = ptable_find(ptable, ptn_name);
619 if (ptn == NULL)
620 {
621 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
622 return -1;
623 }
624
625 offset = page_offset * pagesize;
626 aligned_size = ROUND_TO_PAGE(size, pagesize - 1);
627 if (ptn->length < offset + aligned_size)
628 {
629 dprintf(CRITICAL, "Write request out of '%s' boundaries\n",
630 ptn_name);
631 return -1;
632 }
633
634 if (scratch_addr != buf)
635 memcpy(scratch_addr, buf, size);
636 if (flash_write(ptn, offset, scratch_addr, aligned_size)) {
637 dprintf(CRITICAL, "Writing flash failed\n");
638 return -1;
639 }
640 }
641
642 return 0;
643}
644
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700645int get_ffbm(char *ffbm, unsigned size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300646{
647 const char *ffbm_cmd = "ffbm-";
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700648 uint32_t page_size = get_page_size();
649 char *ffbm_page_buffer = NULL;
650 int retval = 0;
651 if (size < FFBM_MODE_BUF_SIZE || size >= page_size)
Pavel Nedeva1e62322013-04-05 15:21:36 +0300652 {
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700653 dprintf(CRITICAL, "Invalid size argument passed to get_ffbm\n");
654 retval = -1;
655 goto cleanup;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300656 }
Parth Dixit75b16812016-04-05 19:17:17 +0530657 ffbm_page_buffer = (char*)memalign(CACHE_LINE, page_size);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700658 if (!ffbm_page_buffer)
659 {
660 dprintf(CRITICAL, "Failed to alloc buffer for ffbm cookie\n");
661 retval = -1;
662 goto cleanup;
663 }
664 if (read_misc(0, ffbm_page_buffer, page_size))
Pavel Nedeva1e62322013-04-05 15:21:36 +0300665 {
666 dprintf(CRITICAL, "Error reading MISC partition\n");
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700667 retval = -1;
668 goto cleanup;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300669 }
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700670 ffbm_page_buffer[size] = '\0';
671 if (strncmp(ffbm_cmd, ffbm_page_buffer, strlen(ffbm_cmd)))
672 {
673 retval = 0;
674 goto cleanup;
675 }
676 else
677 {
678 if (strlcpy(ffbm, ffbm_page_buffer, size) <
679 FFBM_MODE_BUF_SIZE -1)
680 {
681 dprintf(CRITICAL, "Invalid string in misc partition\n");
682 retval = -1;
683 }
684 else
685 retval = 1;
686 }
687cleanup:
688 if(ffbm_page_buffer)
689 free(ffbm_page_buffer);
690 return retval;
Pavel Nedeva1e62322013-04-05 15:21:36 +0300691}
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700692
693