blob: 4a9d10fab7764a23fadfea13369a51bae1316d34 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2016 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 <arch/ops.h>
26#include <ctype.h>
27#include <debug.h>
28#include <dev/timer/arm_generic.h>
29#include <dev/udc.h>
30#include <errno.h>
31#include <fit.h>
32#include <kernel/event.h>
33#include <kernel/thread.h>
34#include <lib/bio.h>
35#include <lib/dl_commands.h>
36#include <lib/fastboot.h>
37#include <lib/mempool.h>
38#include <lib/partition.h>
39#include <lib/sparse_format.h>
40#include <libfdt.h>
41#include <platform.h>
42#include <platform/mmc_rpmb.h>
43#include <platform/mt_reg_base.h>
44#include <platform/mtk_wdt.h>
45#include <stdlib.h>
46#include <string.h>
47#include <target.h>
48#include <trace.h>
49
50#define LOCAL_TRACE 0
51
52#define MODULE_NAME "FASTBOOT_DOWNLOAD"
53
54extern void *download_base;
55extern unsigned download_max;
56extern unsigned download_size;
57extern unsigned fastboot_state;
58
59/*LXO: !Download related command*/
60
61#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
62#define INVALID_PTN -1
63
64lk_bigtime_t start_time_ms;
65#define TIME_STAMP current_time_hires()
66#define TIME_START {start_time_ms = current_time_hires();}
67#define TIME_ELAPSE (current_time_hires() - start_time_ms)
68
69extern int usb_write(void *buf, unsigned len);
70extern int usb_read(void *buf, unsigned len);
71
72static int create_download_membdev(const char *arg, unsigned sz);
73
74extern struct fastboot_var *varlist;
75void cmd_getvar(const char *arg, void *data, unsigned sz)
76{
77 struct fastboot_var *var;
78 char response[MAX_RSP_SIZE];
79
80 if (!strcmp(arg, "all")) {
81 for (var = varlist; var; var = var->next) {
82 snprintf(response, MAX_RSP_SIZE,"\t%s: %s", var->name, var->value);
83 fastboot_info(response);
84 }
85 fastboot_okay("Done!!");
86 return;
87 }
88 for (var = varlist; var; var = var->next) {
89 if (!strcmp(var->name, arg)) {
90 fastboot_okay(var->value);
91 return;
92 }
93 }
94 fastboot_okay("");
95}
96
97void cmd_reboot(const char *arg, void *data, unsigned sz)
98{
99 dprintf(ALWAYS, "rebooting the device\n");
100 fastboot_okay("");
101 set_clr_fastboot_mode(false);
102 mtk_arch_reset(1); /* bypass pwr key when reboot */
103}
104
105void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
106{
107 dprintf(ALWAYS, "rebooting the device to bootloader\n");
108 fastboot_okay("");
109 set_clr_fastboot_mode(true);
110 mtk_arch_reset(1); /* bypass pwr key when reboot */
111}
112
113__WEAK void set_clr_fastbootd_mode(bool flag)
114{
115 dprintf(ALWAYS, "not support rebooting the device to fastbootd\n");
116}
117
118void cmd_reboot_fastbootd(const char *arg, void *data, unsigned sz)
119{
120 dprintf(ALWAYS, "rebooting the device to fastbootd\n");
121 fastboot_okay("");
122 set_clr_fastboot_mode(false);
123 set_clr_recovery_mode(false);
124 set_clr_fastbootd_mode(true);
125 mtk_arch_reset(1); /* bypass pwr key when reboot */
126}
127
128void cmd_reboot_recovery(const char *arg, void *data, unsigned sz)
129{
130 dprintf(ALWAYS, "rebooting the device to recovery\n");
131 fastboot_okay("");
132 set_clr_recovery_mode(true);
133 mtk_arch_reset(1); /* bypass pwr key when reboot */
134}
135
136static void fastboot_fail_wrapper(const char *msg)
137{
138 fastboot_fail(msg);
139}
140
141static void fastboot_ok_wrapper(const char *msg, unsigned data_size)
142{
143 fastboot_okay("");
144}
145
146void cmd_download(const char *arg, void *data, unsigned sz)
147{
148 char *response;
149 char *endptr;
150 unsigned len = strtoul(arg, &endptr, 16);
151 int r;
152
153 download_size = 0;
154 if (len > download_max) {
155 fastboot_fail_wrapper("data is too large");
156 return;
157 }
158 response = (char *)memalign(CACHE_LINE, MAX_RSP_SIZE);
159 if (!response) {
160 fastboot_fail_wrapper("buffer allocation fail");
161 return;
162 }
163
164 snprintf(response, MAX_RSP_SIZE, "DATA%08x", len);
165 r = usb_write(response, strlen(response));
166 free(response);
167 if (r < 0) {
168 return;
169 }
170
171
172 TIME_START;
173 r = usb_read(download_base, len);
174 if ((r < 0) || ((unsigned) r != len)) {
175 fastboot_fail_wrapper("Read USB error");
176 fastboot_state = STATE_ERROR;
177 return;
178 }
179 download_size = len;
180
181 fastboot_ok_wrapper("USB Transmission OK", len);
182}
183
184void cmd_flash_img(const char *arg, void *data, unsigned sz)
185{
186 bdev_t *bdev;
187 int ret = 0;
188 off_t round_size;
189
190 if (!strncmp(arg, "download:", strlen("download:"))) {
191 if (create_download_membdev(arg, sz)) {
192 fastboot_fail_wrapper("create memdev fail.");
193 return;
194 }
195 }
196
197 bdev = bio_open_by_label(arg) ? : bio_open(arg);
198 if (!bdev) {
199 fastboot_fail_wrapper("Partition is not exist.");
200 return;
201 }
202
203 round_size = (off_t)ROUND_TO_PAGE(sz, bdev->block_size - 1);
204 LTRACEF("src size is %lld, dst size is %lld\n",
205 round_size, bdev->total_size);
206 if (bdev->total_size && (round_size > bdev->total_size)) {
207 fastboot_fail_wrapper("Image size is too large.");
208 goto closebdev;
209 }
210
211 ret = partition_update(bdev->name, 0x0, data, sz);
212 if (ret < 0) {
213 fastboot_fail_wrapper("Flash write failure.");
214 goto closebdev;
215 }
216
217 ret = partition_publish(bdev->name, 0x0);
218 if (ret > 0)
219 bio_dump_devices();
220
221 fastboot_okay("");
222
223closebdev:
224 bio_close(bdev);
225
226 return;
227}
228
229void cmd_flash_sparse_img(const char *arg, void *data, unsigned sz)
230{
231 bdev_t *bdev;
232 size_t ret = 0;
233 unsigned int chunk;
234 unsigned int chunk_data_sz;
235 uint32_t *fill_buf = NULL;
236 uint32_t fill_val, pre_fill_val, erase_val;
237 uint32_t chunk_blk_cnt = 0;
238 uint32_t i;
239 sparse_header_t *sparse_header;
240 chunk_header_t *chunk_header;
241 uint32_t total_blocks = 0;
242 unsigned long long size = 0;
243
244 bdev = bio_open_by_label(arg);
245 if (!bdev) {
246 fastboot_fail_wrapper("Partition is not exist.");
247 return;
248 }
249
250 size = bdev->total_size;
251 if (!size) {
252 fastboot_fail_wrapper("Size is uncorrect.");
253 goto closebdev;
254 }
255
256 /* Read and skip over sparse image header */
257 sparse_header = (sparse_header_t *) data;
258 dprintf(ALWAYS, "Image size span 0x%llx, partition size 0x%llx\n", (unsigned long long)sparse_header->total_blks*sparse_header->blk_sz, size);
259 if ((unsigned long long)sparse_header->total_blks*sparse_header->blk_sz > size) {
260 fastboot_fail("sparse image size span overflow.");
261 goto closebdev;
262 }
263
264 data += sparse_header->file_hdr_sz;
265 if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) {
266 /* Skip the remaining bytes in a header that is longer than
267 * we expected.
268 */
269 data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
270 }
271
272 /* sparse_header->blk_sz is used as denominator later, ensure it's not 0 */
273 if (sparse_header->blk_sz == 0) {
274 fastboot_fail("wrong blk_sz in sparse header.");
275 goto closebdev;
276 }
277
278 LTRACEF("=== Sparse Image Header ===\n");
279 LTRACEF("magic: 0x%x\n", sparse_header->magic);
280 LTRACEF("major_version: 0x%x\n", sparse_header->major_version);
281 LTRACEF("minor_version: 0x%x\n", sparse_header->minor_version);
282 LTRACEF("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
283 LTRACEF("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
284 LTRACEF("blk_sz: %d\n", sparse_header->blk_sz);
285 LTRACEF("total_blks: %d\n", sparse_header->total_blks);
286 LTRACEF("total_chunks: %d\n", sparse_header->total_chunks);
287
288 fill_buf = (uint32_t *)memalign(CACHE_LINE, ROUNDUP(sparse_header->blk_sz, CACHE_LINE));
289 if (!fill_buf) {
290 fastboot_fail_wrapper("Malloc failed for: CHUNK_TYPE_FILL");
291 goto closebdev;
292 }
293 erase_val = (int)bdev->erase_byte|bdev->erase_byte<<8|bdev->erase_byte<<16|bdev->erase_byte<<24;
294 pre_fill_val = erase_val;
295 LTRACEF("Init previous fill value to 0x%08x\n", pre_fill_val);
296
297 /* Start processing chunks */
298 for (chunk=0; chunk<sparse_header->total_chunks; chunk++) {
299 /* Read and skip over chunk header */
300 chunk_header = (chunk_header_t *)data;
301 data += sizeof(chunk_header_t);
302
303 LTRACEF("=== Chunk Header ===\n");
304 LTRACEF("chunk_type: 0x%x\n", chunk_header->chunk_type);
305 LTRACEF("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
306 LTRACEF("total_size: 0x%x\n", chunk_header->total_sz);
307
308 if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) {
309 /* Skip the remaining bytes in a header that is longer than
310 * we expected.
311 */
312 data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
313 }
314
315 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
316 switch (chunk_header->chunk_type) {
317 case CHUNK_TYPE_RAW:
318 if (chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
319 chunk_data_sz)) {
320 fastboot_fail("Bogus chunk size for chunk type Raw");
321 goto error;
322 }
323
324 LTRACEF("Raw: start block addr: 0x%x\n", total_blocks);
325
326 LTRACEF("addr 0x%llx, partsz 0x%x\n", ((unsigned long long)total_blocks*sparse_header->blk_sz) , chunk_data_sz);
327 ret = (size_t)bio_write(bdev, data, ((unsigned long long)total_blocks*sparse_header->blk_sz), chunk_data_sz);
328 if (ret != chunk_data_sz) {
329 fastboot_fail_wrapper("flash write failure");
330 goto error;
331 }
332
333 total_blocks += chunk_header->chunk_sz;
334 data += chunk_data_sz;
335 break;
336
337 case CHUNK_TYPE_DONT_CARE:
338 LTRACEF("!!Blank: start: 0x%x offset: 0x%x\n",
339 total_blocks, chunk_header->chunk_sz);
340 total_blocks += chunk_header->chunk_sz;
341 break;
342
343 case CHUNK_TYPE_FILL:
344 LTRACEF("CHUNK_TYPE_FILL=0x%x size=%d chunk_data_sz=%d\n",
345 *(uint32_t *)data,
346 ROUNDUP(sparse_header->blk_sz, CACHE_LINE),
347 chunk_data_sz);
348 if (chunk_header->total_sz != (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
349 fastboot_fail_wrapper("Bogus chunk size for chunk type FILL");
350 goto error;
351 }
352
353 fill_val = *(uint32_t *)data;
354 data = (char *) data + sizeof(uint32_t);
355 chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
356
357 if (fill_val != pre_fill_val) {
358 pre_fill_val = fill_val;
359 for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
360 fill_buf[i] = fill_val;
361 }
362
363 for (i = 0; i < chunk_blk_cnt; i++) {
364 if (fill_val == erase_val) {
365 /* To assume partition already erased */
366 /* skip fill value as same as erase_byte */
367 LTRACEF("skip CHUNK_TYPE_FILL with value '%x'\n", fill_val);
368 } else {
369 ret = (size_t)bio_write(bdev, fill_buf, ((uint64_t)total_blocks*sparse_header->blk_sz), sparse_header->blk_sz);
370 if (ret != sparse_header->blk_sz) {
371 fastboot_fail_wrapper("CHUNK_TYPE_FILL flash write failure");
372 goto error;
373 }
374 }
375 total_blocks++;
376 }
377 break;
378
379 case CHUNK_TYPE_CRC:
380 if (chunk_header->total_sz != sparse_header->chunk_hdr_sz) {
381 fastboot_fail_wrapper("Bogus chunk size for chunk type Dont Care");
382 goto error;
383 }
384 total_blocks += chunk_header->chunk_sz;
385 data += chunk_data_sz;
386 break;
387
388 default:
389 fastboot_fail_wrapper("Unknown chunk type");
390 goto error;
391 }
392 }
393
394 dprintf(ALWAYS, "Wrote %d blocks, expected to write %d blocks\n",
395 total_blocks, sparse_header->total_blks);
396
397 if (total_blocks != sparse_header->total_blks) {
398 fastboot_fail_wrapper("sparse image write failure");
399 } else {
400 fastboot_okay("");
401 }
402
403error:
404 free(fill_buf);
405closebdev:
406 bio_close(bdev);
407
408 return;
409}
410
411void cmd_flash(const char *arg, void *data, unsigned sz)
412{
413 sparse_header_t *sparse_header;
414
415 dprintf(ALWAYS, "cmd_flash: %s, %d\n", arg, (u32)sz);
416
417 if (sz == 0) {
418 fastboot_okay("");
419 return;
420 }
421
422 TIME_START;
423
424// security check, only unlocked device can flash partitions
425#if !(defined FORCE_DISABLE_FLASH_CHECK)
426 int ret=-1;
427 unsigned char blk[256]={0};
428
429 ret=mmc_rpmb_block_read(INDEX_RPMB_UNLOCK,&blk[0]);
430 if(ret != 0){
431 dprintf(CRITICAL, "mmc_rpmb_block_read fail %d.\n", ret);
432 return;
433 }
434
435 if(blk[0] != AVB_DEVICE_UNLOCK){
436 dprintf(ALWAYS, "Device not unlocked, cmd_flash refused \n");
437 return;
438 }
439#endif
440
441 sparse_header = (sparse_header_t *) data;
442 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
443 cmd_flash_img(arg, data, sz);
444 else {
445 cmd_flash_sparse_img(arg, data, sz);
446 }
447
448 return;
449}
450
451void cmd_erase(const char *arg, void *data, unsigned sz)
452{
453#define MAX_ERASE_SIZE (INT_MAX & ~(bdev->block_size - 1))
454 bdev_t *bdev;
455 ssize_t ret = 0, erase_len = 0;
456 char response[MAX_RSP_SIZE];
457
458 dprintf(ALWAYS, "cmd_erase\n");
459 bdev = bio_open_by_label(arg);
460 if (!bdev) {
461 bdev = bio_open(arg);
462 if (!bdev) {
463 fastboot_fail_wrapper("Partition is not exist.");
464 return;
465 }
466 }
467
468 if (!bdev->total_size) {
469 fastboot_fail_wrapper("Size is uncorrect.");
470 goto closebdev;
471 }
472
473 LTRACEF("%s %s %lld %d\n",
474 bdev->name, bdev->label, bdev->total_size, bdev->block_count);
475 if (bdev->total_size > (off_t)MAX_ERASE_SIZE) {
476 off_t offset = 0LL, size = bdev->total_size;
477 size_t len;
478 do {
479 len = (size_t)MIN(size, (off_t)MAX_ERASE_SIZE);
480 ret = bio_erase(bdev, offset, len);
481 if (ret < 0) {
482 fastboot_fail_wrapper("Erase failure.");
483 goto closebdev;
484 }
485 erase_len += ret;
486 size -= len;
487 offset += len;
488 } while (size);
489 } else {
490 ret = bio_erase(bdev, 0, bdev->total_size);
491 if (ret < 0) {
492 fastboot_fail_wrapper("Erase failure.");
493 goto closebdev;
494 }
495 erase_len = ret;
496 }
497
498 ret = partition_unpublish(bdev->name);
499 if (ret > 0)
500 bio_dump_devices();
501
502 snprintf(response, MAX_RSP_SIZE, "request sz: 0x%llx, real erase len: 0x%lx",
503 bdev->total_size, erase_len);
504 fastboot_info(response);
505
506 fastboot_okay("");
507
508closebdev:
509 bio_close(bdev);
510
511 return;
512}
513
514//to support AVB2.0 cmd: fastboot flashing [lock | unlock]
515#ifdef AVB_ENABLE_DEVICE_STATE_CHANGE
516int cmd_flash_lock_state(const char *arg)
517{
518 unsigned char blk[256]={0};
519 int ret=-1;
520
521 LTRACEF("start to flash device state [%s] \n",arg);
522
523 if (!strcmp(arg, " lock")) {
524 blk[0]=0;
525 LTRACEF("start to flash lock state \n");
526 ret=mmc_rpmb_block_write(INDEX_RPMB_UNLOCK,&blk[0]);
527 LTRACEF("end to flash lock state %d \n",ret);
528 }
529 else if (!strcmp(arg, " unlock")){
530 blk[0]=AVB_DEVICE_UNLOCK;
531 ret=mmc_rpmb_block_write(INDEX_RPMB_UNLOCK,&blk[0]);
532 LTRACEF("end to flash unlock state %d \n",ret);
533 }
534 else{
535 dprintf(ALWAYS, "cmd %s not supported \n",arg);
536 }
537
538 dprintf(ALWAYS, "cmd %s finish %d \n",arg,ret);
539
540 return ret;
541}
542
543void cmd_flashing(const char *arg, void *data, unsigned sz)
544{
545 char response[MAX_RSP_SIZE];
546 int ret=-1;
547
548 if(arg == NULL){
549 dprintf(ALWAYS, "invalid parameter \n");
550 return ;
551 }
552
553 dprintf(ALWAYS, "cmd_flashing: %s, \n", arg);
554
555 ret=cmd_flash_lock_state(arg);
556
557 snprintf(response, MAX_RSP_SIZE, "flashing state %s", (ret==0)?"sucessful":"fail");
558 fastboot_info(response);
559
560 fastboot_okay("");
561
562 return;
563}
564#endif
565
566extern unsigned fastboot_state;
567void cmd_continue_boot(const char *arg, void *data, unsigned sz)
568{
569 fastboot_okay("");
570 /* set state to leave fastboot command loop and handler */
571 fastboot_state = STATE_RETURN;
572 mtk_wdt_init();
573}
574
575static int create_download_membdev(const char *arg, unsigned sz)
576{
577 size_t membdev_size;
578 void *membdev_buf;
579 int rc;
580
581 /* destroy the membdev if previously created */
582 membdev_buf = destroy_membdev(arg);
583 if (membdev_buf) {
584 mempool_free(membdev_buf);
585 membdev_buf = NULL;
586 }
587
588 /* membdev size should be aligned to 512 bytes */
589 membdev_size = ROUNDUP(sz, 512);
590 membdev_buf = mempool_alloc(membdev_size, MEMPOOL_ANY);
591 if (membdev_buf == NULL) {
592 fastboot_fail_wrapper("size is too large");
593 return -1;
594 }
595
596 rc = create_membdev(arg, membdev_buf, membdev_size);
597 if (rc) {
598 fastboot_fail_wrapper("fail to create membdev");
599 mempool_free(membdev_buf);
600 return -1;
601 }
602 fastboot_okay("");
603
604 return 0;
605}