aee.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2016. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <malloc.h>
  32. #include <printf.h>
  33. #include <stdarg.h>
  34. #include <stdint.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <lib/zlib.h>
  38. #include <video.h>
  39. #include <part_interface.h>
  40. #include <platform/mt_typedefs.h>
  41. #include <dev/mrdump.h>
  42. #include <platform/mtk_key.h>
  43. #include <platform/mtk_wdt.h>
  44. #include <platform/mt_gpt.h>
  45. #include <target/board.h>
  46. #include <target/cust_key.h>
  47. #include <platform/boot_mode.h>
  48. #include <bootimg.h>
  49. #include <platform/ram_console.h>
  50. #include <arch/ops.h>
  51. #include <platform.h>
  52. #include <mt_boot.h>
  53. #include <platform/errno.h>
  54. #include "aee.h"
  55. #include "mrdump_private.h"
  56. #ifdef MTK_3LEVEL_PAGETABLE
  57. #include <target.h>
  58. #endif
  59. #define MRDUMP_DELAY_TIME 10
  60. extern BOOT_ARGUMENT *g_boot_arg;
  61. extern BOOTMODE g_boot_mode;
  62. static struct mrdump_control_block *mrdump_cb = NULL;
  63. static struct mrdump_cblock_result cblock_result;
  64. static unsigned int log_size;
  65. static int output_device;
  66. int mrdump_get_env(const char *name, char *out, int out_len)
  67. {
  68. struct mrdump_expdb_config mrdump_config;
  69. struct mrdump_dev *blkpart = mrdump_dev_blkpart(AEE_IPANIC_LABEL);
  70. if (blkpart == NULL) {
  71. dprintf(CRITICAL, "%s partition does not exist\n", AEE_IPANIC_LABEL);
  72. return -ENODEV;
  73. }
  74. off_t part_total_size = partition_get_size_by_name(AEE_IPANIC_LABEL);
  75. off_t offset;
  76. bool status;
  77. offset = part_total_size - MRDUMP_CONFIG_EXPDB_OFFSET;
  78. status = blkpart->read(blkpart, offset, (uint8_t *)&mrdump_config, sizeof(struct mrdump_expdb_config));
  79. free(blkpart);
  80. if (!status) {
  81. dprintf(CRITICAL, "%s: bio_read fail\n", __func__);
  82. return -EIO;
  83. }
  84. if (!strncmp(name, MRDUMP_OUTPUT, sizeof(MRDUMP_OUTPUT))) {
  85. if (strlcpy(out, mrdump_config.output_dev, out_len) >= out_len) {
  86. dprintf(CRITICAL, "%s: mrdump_config.output_dev too long\n", __func__);
  87. return -1;
  88. }
  89. dprintf(CRITICAL, "%s: %s\n", MRDUMP_OUTPUT, out);
  90. } else if (!strncmp(name, MRDUMP_ALLOCATE_SIZE, 20)) {
  91. if (strlcpy(out, mrdump_config.allocate_size, out_len) >= out_len) {
  92. dprintf(CRITICAL, "%s: mrdump_config.allocate_size too long\n", __func__);
  93. return -1;
  94. }
  95. dprintf(CRITICAL, "%s: %s\n", MRDUMP_ALLOCATE_SIZE, out);
  96. } else if (!strncmp(name, MRDUMP_MEM_SIZE, sizeof(MRDUMP_MEM_SIZE))) {
  97. if (strlcpy(out, mrdump_config.mem_size, out_len) >= out_len) {
  98. dprintf(CRITICAL, "%s: mrdump_config.mem_size too long\n", __func__);
  99. return -1;
  100. }
  101. } else if (!strncmp(name, MRDUMP_LBAOOO, sizeof(MRDUMP_LBAOOO))) {
  102. if (strlcpy(out, mrdump_config.lbaooo, out_len) >= out_len) {
  103. dprintf(CRITICAL, "%s: mrdump_config.lbaooo too long\n", __func__);
  104. return -1;
  105. }
  106. } else if (!strncmp(name, MRDUMP_DUMP_TYPE, sizeof(MRDUMP_DUMP_TYPE))) {
  107. if (strlcpy(out, mrdump_config.dump_type, out_len) >= out_len) {
  108. dprintf(CRITICAL, "%s: mrdump_config.dump_type too long\n", __func__);
  109. return -1;
  110. }
  111. } else {
  112. dprintf(CRITICAL, "unknown mrdump config %s\n", name);
  113. return -1;
  114. }
  115. dprintf(CRITICAL, "%s: %s\n", name, out);
  116. return 0;
  117. }
  118. int mrdump_set_env(const char *name, const char *value)
  119. {
  120. struct mrdump_expdb_config mrdump_config;
  121. off_t part_total_size;
  122. off_t offset;
  123. bool status;
  124. memset(&mrdump_config, 0, sizeof(mrdump_config));
  125. struct mrdump_dev *blkpart = mrdump_dev_blkpart(AEE_IPANIC_LABEL);
  126. if (blkpart == NULL) {
  127. dprintf(CRITICAL, "%s partition does not exist\n", AEE_IPANIC_LABEL);
  128. return -ENODEV;
  129. }
  130. part_total_size = partition_get_size_by_name(AEE_IPANIC_LABEL);
  131. offset = part_total_size - MRDUMP_CONFIG_EXPDB_OFFSET;
  132. status = blkpart->read(blkpart, offset, (uint8_t *)&mrdump_config, sizeof(struct mrdump_expdb_config));
  133. if (!status) {
  134. dprintf(CRITICAL, "%s: bio_read fail\n", __func__);
  135. free(blkpart);
  136. return -EIO;
  137. }
  138. if (mrdump_config.sig != MRDUMP_CONFIG_SIG) {
  139. memset(&mrdump_config, 0, sizeof(struct mrdump_expdb_config));
  140. mrdump_config.sig = MRDUMP_CONFIG_SIG;
  141. }
  142. if (!strncmp(name, MRDUMP_OUTPUT, sizeof(MRDUMP_OUTPUT))) {
  143. memcpy(&mrdump_config.output_dev, value, sizeof(mrdump_config.output_dev));
  144. } else if (!strncmp(name, MRDUMP_ALLOCATE_SIZE, sizeof(MRDUMP_ALLOCATE_SIZE))) {
  145. memcpy(&mrdump_config.allocate_size, value, sizeof(mrdump_config.allocate_size));
  146. } else if (!strncmp(name, MRDUMP_MEM_SIZE, sizeof(MRDUMP_MEM_SIZE))) {
  147. memcpy(&mrdump_config.mem_size, value, sizeof(mrdump_config.mem_size));
  148. } else if (!strncmp(name, MRDUMP_LBAOOO, sizeof(MRDUMP_LBAOOO))) {
  149. memcpy(&mrdump_config.lbaooo, value, sizeof(mrdump_config.lbaooo));
  150. } else if (!strncmp(name, MRDUMP_DUMP_TYPE, sizeof(MRDUMP_DUMP_TYPE))) {
  151. memcpy(&mrdump_config.dump_type, value, sizeof(mrdump_config.dump_type));
  152. } else {
  153. dprintf(CRITICAL, "unknown mrdump config\n");
  154. free(blkpart);
  155. return -1;
  156. }
  157. dprintf(CRITICAL, "%s update to %s\n", name, value);
  158. status = blkpart->write(blkpart, offset, (uint8_t *)&mrdump_config, sizeof(struct mrdump_expdb_config));
  159. if (!status) {
  160. dprintf(CRITICAL, "%s: bio_write fail\n", __func__);
  161. free(blkpart);
  162. return -EIO;
  163. }
  164. free(blkpart);
  165. return 0;
  166. }
  167. void voprintf(char type, const char *msg, va_list ap)
  168. {
  169. char msgbuf[128], *p;
  170. p = msgbuf;
  171. if (msg[0] == '\r') {
  172. *p++ = msg[0];
  173. msg++;
  174. }
  175. *p++ = type;
  176. *p++ = ':';
  177. if (vsnprintf(p, sizeof(msgbuf) - (p - msgbuf), msg, ap) < 0) {
  178. strlcpy(p, "<Message format error>\n", p - msgbuf);
  179. }
  180. switch (type) {
  181. case 'I':
  182. case 'W':
  183. case 'E':
  184. video_printf("%s", msgbuf);
  185. break;
  186. }
  187. dprintf(CRITICAL,"[%s] %s", MRDUMP_GO_DUMP, msgbuf);
  188. /* Write log buffer */
  189. p = msgbuf;
  190. while ((*p != 0) && (log_size < sizeof(cblock_result.log_buf))) {
  191. cblock_result.log_buf[log_size] = *p++;
  192. log_size++;
  193. }
  194. }
  195. void voprintf_verbose(const char *msg, ...)
  196. {
  197. va_list ap;
  198. va_start(ap, msg);
  199. voprintf('V', msg, ap);
  200. va_end(ap);
  201. }
  202. void voprintf_debug(const char *msg, ...)
  203. {
  204. va_list ap;
  205. va_start(ap, msg);
  206. voprintf('D', msg, ap);
  207. va_end(ap);
  208. }
  209. void voprintf_info(const char *msg, ...)
  210. {
  211. va_list ap;
  212. va_start(ap, msg);
  213. voprintf('I', msg, ap);
  214. va_end(ap);
  215. }
  216. void voprintf_warning(const char *msg, ...)
  217. {
  218. va_list ap;
  219. va_start(ap, msg);
  220. voprintf('W', msg, ap);
  221. va_end(ap);
  222. }
  223. void voprintf_error(const char *msg, ...)
  224. {
  225. va_list ap;
  226. va_start(ap, msg);
  227. voprintf('E', msg, ap);
  228. va_end(ap);
  229. }
  230. void vo_show_progress(int sizeM)
  231. {
  232. video_set_cursor((video_get_rows() / 4) * 3, (video_get_colums() - 22)/ 2);
  233. video_printf("=====================\n");
  234. video_set_cursor((video_get_rows() / 4) * 3 + 1, (video_get_colums() - 22)/ 2);
  235. video_printf(">>> Written %4dM <<<\n", sizeM);
  236. video_set_cursor((video_get_rows() / 4) * 3 + 2, (video_get_colums() - 22)/ 2);
  237. video_printf("=====================\n");
  238. video_set_cursor(video_get_rows() - 1, 0);
  239. dprintf(CRITICAL,"... Written %dM\n", sizeM);
  240. }
  241. static void mrdump_status(const char *status, const char *fmt, va_list ap)
  242. {
  243. char *dest = cblock_result.status;
  244. dest += strlcpy(dest, status, sizeof(cblock_result.status));
  245. *dest++ = '\n';
  246. vsnprintf(dest, sizeof(cblock_result.status) - (dest - cblock_result.status), fmt, ap);
  247. }
  248. void mrdump_status_ok(const char *fmt, ...)
  249. {
  250. va_list ap;
  251. va_start(ap, fmt);
  252. mrdump_status("OK", fmt, ap);
  253. va_end(ap);
  254. }
  255. void mrdump_status_none(const char *fmt, ...)
  256. {
  257. va_list ap;
  258. va_start(ap, fmt);
  259. mrdump_status("NONE", fmt, ap);
  260. va_end(ap);
  261. }
  262. void mrdump_status_error(const char *fmt, ...)
  263. {
  264. va_list ap;
  265. va_start(ap, fmt);
  266. mrdump_status("FAILED", fmt, ap);
  267. va_end(ap);
  268. }
  269. const const char *mrdump_mode2string(uint8_t mode)
  270. {
  271. switch (mode) {
  272. case AEE_REBOOT_MODE_NORMAL:
  273. return "NORMAL-BOOT";
  274. case AEE_REBOOT_MODE_KERNEL_OOPS:
  275. return "KERNEL-OOPS";
  276. case AEE_REBOOT_MODE_KERNEL_PANIC:
  277. return "KERNEL-PANIC";
  278. case AEE_REBOOT_MODE_NESTED_EXCEPTION:
  279. return "NESTED-CPU-EXCEPTION";
  280. case AEE_REBOOT_MODE_WDT:
  281. return "HWT";
  282. case AEE_REBOOT_MODE_EXCEPTION_KDUMP:
  283. return "MANUALDUMP";
  284. case AEE_REBOOT_MODE_MRDUMP_KEY:
  285. return "MRDUMP_KEY";
  286. case AEE_REBOOT_MODE_HANG_DETECT:
  287. return "KERNEL-HANG-DETECT";
  288. default:
  289. return "UNKNOWN-BOOT";
  290. }
  291. }
  292. #define MRDUMP_EXPDB_OFFSET 3145728
  293. static void mrdump_write_result(void)
  294. {
  295. struct mrdump_dev *blkpart = mrdump_dev_blkpart("expdb");
  296. if (blkpart != NULL) {
  297. u64 part_size = blkpart->get_size(blkpart);
  298. if (part_size < MRDUMP_EXPDB_OFFSET + sizeof(cblock_result)) {
  299. dprintf(CRITICAL, "%s: partition size(%llx) is less then reserved (%x)\n",
  300. __func__, part_size, MRDUMP_EXPDB_OFFSET);
  301. free(blkpart);
  302. return;
  303. }
  304. blkpart->write(blkpart, part_size - MRDUMP_EXPDB_OFFSET,
  305. (uint8_t *) &cblock_result, sizeof(cblock_result));
  306. free(blkpart);
  307. }
  308. else {
  309. dprintf(CRITICAL, "%s: Cannot find expdb partition\n", __func__);
  310. }
  311. }
  312. #define SIZE_1MB 1048576ULL
  313. #define SIZE_64MB 67108864ULL
  314. static uint64_t mrdump_mem_size(void)
  315. {
  316. uint64_t total_dump_size = physical_memory_size();
  317. char mem_size_param[8] = {0};
  318. if (mrdump_get_env("mrdump_mem_size", mem_size_param, sizeof(mem_size_param)))
  319. dprintf(CRITICAL, "%s: mrdump_get_env fail\n", __func__);
  320. if (strcmp(mem_size_param, "")) {
  321. uint64_t mem_size = atoi(mem_size_param) * SIZE_1MB;
  322. voprintf_info("Memory dump size set to %uM\n", (unsigned int) (mem_size / SIZE_1MB));
  323. if (mem_size >= SIZE_64MB) {
  324. /* minimum 64m */
  325. total_dump_size = MIN(total_dump_size, mem_size);
  326. }
  327. }
  328. return total_dump_size;
  329. }
  330. int mrdump_set_output_device(const char *output_dev)
  331. {
  332. int retval = MRDUMP_DEV_UNKNOWN;
  333. if (strcmp(output_dev, "none") == 0) {
  334. retval = MRDUMP_DEV_NONE;
  335. }
  336. else if (strcmp(output_dev, "null") == 0) {
  337. retval = MRDUMP_DEV_NULL;
  338. }
  339. else if (strcmp(output_dev, "usb") == 0) {
  340. retval = MRDUMP_DEV_USB;
  341. }
  342. else if (strcmp(output_dev, "partition") == 0) {
  343. retval = MRDUMP_DEV_PARTITION;
  344. }
  345. else if (strcmp(output_dev, "internal-storage") == 0) {
  346. retval = MRDUMP_DEV_ISTORAGE;
  347. }
  348. if (retval != MRDUMP_DEV_UNKNOWN) {
  349. if (mrdump_set_env("mrdump_output", (char *)output_dev) == 0) {
  350. dprintf(CRITICAL, "%s: defaults: %s\n",__func__, output_dev);
  351. }
  352. else {
  353. dprintf(CRITICAL, "%s: fail to set default mrdump output device\n", __func__);
  354. }
  355. }
  356. else {
  357. dprintf(CRITICAL, "%s: unknown output device %s\n",__func__, output_dev);
  358. }
  359. return retval;
  360. }
  361. int mrdump_get_default_output_device(void)
  362. {
  363. char output_device_param[64] = "";
  364. if (mrdump_get_env("mrdump_output", output_device_param, sizeof(output_device_param)))
  365. dprintf(CRITICAL, "%s: mrdump_get_env fail\n", __func__);
  366. if (strcmp(output_device_param, "")) {
  367. if (strcmp(output_device_param, "none") == 0)
  368. return MRDUMP_DEV_NONE;
  369. if (strcmp(output_device_param, "null") == 0)
  370. return MRDUMP_DEV_NULL;
  371. if (strcmp(output_device_param, "internal-storage") == 0)
  372. return MRDUMP_DEV_ISTORAGE;
  373. if (strcmp(output_device_param, "usb") == 0)
  374. return MRDUMP_DEV_USB;
  375. if (strcmp(output_device_param, "partition") == 0)
  376. return MRDUMP_DEV_PARTITION;
  377. dprintf(CRITICAL, "%s: unknown output device %s\n",__func__,
  378. output_device_param);
  379. return MRDUMP_DEV_UNKNOWN;
  380. }
  381. #if defined(MRDUMP_DEFAULT_NONE)
  382. return mrdump_set_output_device("none");
  383. #elif defined(MRDUMP_DEFAULT_NULL)
  384. return mrdump_set_output_device("null");
  385. #elif defined(MRDUMP_DEFAULT_USB_DUMP)
  386. return mrdump_set_output_device("usb");
  387. #elif defined(MRDUMP_DEFAULT_MRDUMP_PARTITION)
  388. return mrdump_set_output_device("partition");
  389. #elif defined(MRDUMP_DEFAULT_DATA_PARTITION)
  390. return mrdump_set_output_device("internal-storage");
  391. #else
  392. #ifdef MRDUMP_PARTITION_ENABLE
  393. return mrdump_set_output_device("partition");
  394. #else
  395. return mrdump_set_output_device("internal-storage");
  396. #endif
  397. #endif
  398. }
  399. static struct kzip_addlist *mrdump_memlist_fill(struct mrdump_control_block *mrdump_cblock)
  400. {
  401. struct kzip_addlist *memlist = malloc(sizeof(struct kzip_addlist) * 4);
  402. if (memlist == NULL) {
  403. return NULL;
  404. }
  405. void *bufp = malloc(MRDUMP_CORE_HEADER_SIZE);
  406. if (bufp == NULL) {
  407. free(memlist);
  408. return NULL;
  409. }
  410. memset(bufp, 0, MRDUMP_CORE_HEADER_SIZE);
  411. memlist[0].address = (uint64_t)(uintptr_t) bufp;
  412. memlist[0].size = MRDUMP_CORE_HEADER_SIZE;
  413. memlist[0].type = MEM_NO_MAP;
  414. memlist[0].memmap = 0;
  415. memlist[0].pageflags = 0;
  416. memlist[0].struct_page_size = 0;
  417. memlist[1].address = (uint64_t)(uintptr_t) mrdump_cb_addr();
  418. memlist[1].size = mrdump_cb_size();
  419. memlist[1].type = MEM_NO_MAP;
  420. memlist[1].memmap = 0;
  421. memlist[1].pageflags = 0;
  422. memlist[1].struct_page_size = 0;
  423. memlist[2].address = DRAM_PHY_ADDR;
  424. memlist[2].size = mrdump_mem_size();
  425. memlist[2].type = MEM_DO_MAP;
  426. memlist[2].memmap = mrdump_cblock->machdesc.memmap;
  427. memlist[2].pageflags = mrdump_cblock->machdesc.pageflags;
  428. memlist[2].struct_page_size = mrdump_cblock->machdesc.struct_page_size;
  429. memlist[3].address = 0;
  430. memlist[3].size = 0;
  431. memlist[3].type = MEM_NO_MAP;
  432. memlist[3].memmap = 0;
  433. memlist[3].pageflags = 0;
  434. memlist[3].struct_page_size = 0;
  435. return memlist;
  436. }
  437. static void mrdump_memlist_free(struct kzip_addlist *memlist)
  438. {
  439. free((void *)(uintptr_t)memlist[0].address);
  440. free(memlist);
  441. }
  442. static void kdump_ui(struct mrdump_control_block *mrdump_cblock)
  443. {
  444. video_clear_image_by_color(0xFFFF7F00, 0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
  445. video_set_bgcolor(0xFFFF7F00);
  446. video_set_fgcolor(0xFFFF0000);
  447. video_set_cursor(0, 0);
  448. mrdump_status_error("Unknown error\n");
  449. voprintf_info("Kdump triggerd by '%s' (address:%x, size:%lluM)\n",
  450. mrdump_mode2string(mrdump_cblock->crash_record.reboot_mode),
  451. DRAM_PHY_ADDR, mrdump_mem_size() / 0x100000UL);
  452. /* check machdesc crc */
  453. uint32_t mcrc = crc32(0xffffffff, (const unsigned char*)&mrdump_cblock->machdesc,
  454. sizeof(struct mrdump_machdesc)) ^ 0xffffffff;
  455. if (mcrc != mrdump_cblock->machdesc_crc) {
  456. voprintf_error("Control block machdesc field CRC error (%08x, %08x).\n",
  457. mcrc, mrdump_cblock->machdesc_crc);
  458. return;
  459. }
  460. struct kzip_addlist *memlist_cmm = mrdump_memlist_fill_cmm(mrdump_cblock);
  461. struct kzip_addlist *memlist = mrdump_memlist_fill(mrdump_cblock);
  462. if (memlist == NULL) {
  463. voprintf_error("Cannot allcate memlist memory.\n");
  464. return;
  465. }
  466. mrdump_core_header_init(mrdump_cblock, memlist);
  467. struct aee_timer elapse_time;
  468. aee_timer_init(&elapse_time);
  469. aee_timer_start(&elapse_time);
  470. int dump_ok;
  471. switch (output_device) {
  472. case MRDUMP_DEV_NONE:
  473. mrdump_status_none("Output to None (disabled)\n");
  474. voprintf_info("Output to None (disabled)\n");
  475. dump_ok = 0;
  476. break;
  477. case MRDUMP_DEV_NULL:
  478. dump_ok = mrdump_null_output(mrdump_cblock, memlist, memlist_cmm);
  479. break;
  480. case MRDUMP_DEV_ISTORAGE:
  481. dump_ok = mrdump_ext4_output(mrdump_cblock, memlist, memlist_cmm, mrdump_dev_blkpart("userdata"));
  482. break;
  483. case MRDUMP_DEV_USB:
  484. dump_ok = mrdump_usb_output(mrdump_cblock, memlist, memlist_cmm);
  485. break;
  486. case MRDUMP_DEV_PARTITION:
  487. dump_ok = mrdump_partition_output(mrdump_cblock, memlist, memlist_cmm, mrdump_dev_blkpart("mrdump"));
  488. break;
  489. default:
  490. voprintf_error("Unsupport device id %d\n", output_device);
  491. dump_ok = -1;
  492. }
  493. mrdump_memlist_free(memlist);
  494. mrdump_memlist_free_cmm(memlist_cmm);
  495. aee_mrdump_flush_cblock(mrdump_cblock);
  496. aee_timer_stop(&elapse_time);
  497. voprintf_info("Dump finished.(%s, %d sec)\n", dump_ok == 0 ? "ok" : "failed", elapse_time.acc_ms / 1000);
  498. mtk_wdt_restart();
  499. video_clean_screen();
  500. video_set_cursor(0, 0);
  501. }
  502. int mrdump_detection(void)
  503. {
  504. if (mrdump_check_enable() > MRDUMP_ALWAYS_ENABLE)
  505. return 0;
  506. mrdump_key_secure_enable();
  507. output_device = mrdump_get_default_output_device();
  508. if (output_device == MRDUMP_DEV_UNKNOWN) {
  509. return 0;
  510. }
  511. if (!ram_console_is_abnormal_boot()) {
  512. dprintf(CRITICAL, "MT-RAMDUMP: No exception detected, skipped\n");
  513. return 0;
  514. }
  515. mrdump_cb = aee_mrdump_get_params();
  516. if (mrdump_cb == NULL) {
  517. dprintf(CRITICAL, "MT-RAMDUMP control block not found\n");
  518. return 0;
  519. }
  520. memset(&cblock_result, 0, sizeof(struct mrdump_cblock_result));
  521. log_size = 0;
  522. strlcpy(cblock_result.sig, MRDUMP_GO_DUMP, sizeof(cblock_result.sig));
  523. uint8_t reboot_mode = mrdump_cb->crash_record.reboot_mode;
  524. if (!g_boot_arg->ddr_reserve_enable) {
  525. voprintf_debug("DDR reserve mode disabled\n");
  526. mrdump_status_none("DDR reserve mode disabled\n");
  527. goto error;
  528. }
  529. if (!g_boot_arg->ddr_reserve_success) {
  530. voprintf_debug("DDR reserve mode failed\n");
  531. mrdump_status_none("DDR reserve mode failed\n");
  532. goto error;
  533. }
  534. if (mrdump_cb->enabled != MRDUMP_ENABLE_COOKIE) {
  535. voprintf_debug("Runtime disabled %x\n", mrdump_cb->enabled);
  536. mrdump_status_none("Runtime disabled\n");
  537. goto error;
  538. }
  539. voprintf_debug("sram record with mode %d\n", reboot_mode);
  540. switch (reboot_mode) {
  541. case AEE_REBOOT_MODE_GZ_WDT:
  542. case AEE_REBOOT_MODE_WDT: {
  543. goto end;
  544. }
  545. case AEE_REBOOT_MODE_NORMAL: {
  546. /* MRDUMP_KEY reboot*/
  547. if (ram_console_reboot_by_mrdump_key && ram_console_reboot_by_mrdump_key()) {
  548. mrdump_cb->crash_record.reboot_mode = AEE_REBOOT_MODE_MRDUMP_KEY;
  549. mrdump_status_none("set reboot_mode to MRDUMP_KEY\n");
  550. goto end;
  551. } else
  552. return 0;
  553. }
  554. case AEE_REBOOT_MODE_KERNEL_OOPS:
  555. case AEE_REBOOT_MODE_KERNEL_PANIC:
  556. case AEE_REBOOT_MODE_NESTED_EXCEPTION:
  557. case AEE_REBOOT_MODE_EXCEPTION_KDUMP:
  558. case AEE_REBOOT_MODE_MRDUMP_KEY:
  559. case AEE_REBOOT_MODE_GZ_KE:
  560. case AEE_REBOOT_MODE_HANG_DETECT:
  561. goto end;
  562. }
  563. voprintf_debug("Unsupport exception type\n");
  564. mrdump_status_none("Unsupport exception type\n");
  565. error:
  566. mrdump_write_result();
  567. return 0;
  568. end:
  569. if (output_device == MRDUMP_DEV_USB) {
  570. g_boot_mode = FASTBOOT;
  571. if (mrdump_set_env("mrdump_output", "usb")) {
  572. dprintf(CRITICAL, "%s: default usb dump\n",__func__);
  573. }
  574. else {
  575. dprintf(CRITICAL, "%s: fail to set default usb mrdump\n", __func__);
  576. }
  577. }
  578. return 1;
  579. }
  580. void mrdump_reboot(void)
  581. {
  582. #ifdef MTK_PMIC_FULL_RESET
  583. voprintf_debug("Ready for full pmic reset\n");
  584. mrdump_write_result();
  585. mtk_arch_full_reset();
  586. #else
  587. voprintf_debug("Ready for reset\n");
  588. mrdump_write_result();
  589. mtk_arch_reset(1);
  590. #endif
  591. }
  592. int mrdump_run2(void)
  593. {
  594. if (mrdump_cb != NULL) {
  595. kdump_ui(mrdump_cb);
  596. if (output_device != MRDUMP_DEV_USB) {
  597. mrdump_reboot();
  598. }
  599. mrdump_write_result();
  600. return 1;
  601. }
  602. return 0;
  603. }
  604. void aee_timer_init(struct aee_timer *t)
  605. {
  606. memset(t, 0, sizeof(struct aee_timer));
  607. }
  608. void aee_timer_start(struct aee_timer *t)
  609. {
  610. t->start_ms = get_timer_masked();
  611. }
  612. void aee_timer_stop(struct aee_timer *t)
  613. {
  614. t->acc_ms += (get_timer_masked() - t->start_ms);
  615. t->start_ms = 0;
  616. }
  617. #ifdef MTK_3LEVEL_PAGETABLE
  618. vaddr_t scratch_addr(void)
  619. {
  620. return (vaddr_t)target_get_scratch_address();
  621. }
  622. #endif