blob: 6168c4276f9f30e57185c71df56ac507a6a4931f [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <asm/arch/bl31_apis.h>
8#include <asm/arch/secure_apb.h>
9#include <ramdump.h>
10#include <emmc_partitions.h>
11#include <usb.h>
12#include <asm/arch/regs.h>
13
14#define DEBUG_RAMDUMP 0
15#define AMLOGIC_KERNEL_PANIC 0x0c
16#define AMLOGIC_WATCHDOG_REBOOT 0x0d
17
18#ifdef CONFIG_DUMP_COMPRESS_HEAD
19static void dump_info(unsigned int addr, unsigned int size, const char *info)
20{
21 int i = 0;
22
23 printf("\nDUMP %s 0X%08x :", info, addr);
24 for (i = 0; i < size; i += 4) {
25 if (0 == (i % 32))
26 printf("\n[0x%08x] ", addr + i);
27 printf("%08x ", readl(addr + i));
28 }
29 printf("\n\n");
30}
31#endif
32
33unsigned long ramdump_base = 0;
34unsigned long ramdump_size = 0;
35unsigned int get_reboot_mode(void)
36{
37 uint32_t reboot_mode_val = ((readl(REG_MDUMP_REBOOT_MODE) >> 12) & 0xf);
38 return reboot_mode_val;
39}
40
41void ramdump_init(void)
42{
43 unsigned int data;
44 printf("%s, base reg:0x%08x, size reg:0x%08x\n", __func__,
45 REG_MDUMP_COMPRESS_BASE, REG_MDUMP_COMPRESS_SIZE);
46 ramdump_base = readl(REG_MDUMP_COMPRESS_BASE);
47 ramdump_size = readl(REG_MDUMP_COMPRESS_SIZE);
48 if (ramdump_base & 0x80) {
49 /* 0x80: The flag indicates that the addr exceeds 4G. */
50 /* real size = size[31:0] + addr[6:0]<<32 */
51 ramdump_size += (ramdump_base & 0x7f) << 32;
52 /* real addr = addr[31:8] << 8 */
53 ramdump_base = (ramdump_base & 0xffffff00) << 8;
54 }
55
56 data = readl(PREG_STICKY_REG6);
57 writel(data & ~RAMDUMP_STICKY_DATA_MASK, PREG_STICKY_REG6);
58 printf("%s, add:%lx, size:%lx\n", __func__, ramdump_base, ramdump_size);
59
60#ifdef CONFIG_DUMP_COMPRESS_HEAD
61 dump_info((unsigned int)ramdump_base, 0x80, "bl33 check COMPRESS DATA 1");
62#endif
63}
64
65static void wait_usb_dev(void)
66{
67 int print_cnt = 0, ret;
68
69 while (1) {
70 run_command("usb start", 1);
71 mdelay(2000);
72 run_command("usb reset", 1);
73 ret = usb_stor_scan(1);
74 if (ret) {
75 if (!(print_cnt & 0x3f)) {
76 print_cnt++;
77 printf("ramdump: can't find usb device, please insert Udisk.\n\n");
78 }
79 mdelay(10000);
80 continue;
81 } else {
82 run_command("usb dev", 1);
83 break;
84 }
85 }
86}
87
88/*
89 * NOTE: this is a default implementation for writing compressed ramdump data
90 * to /data/ partition for Android platform. You can read out dumpfile in
91 * path /data/crashdump-1.bin when enter Android for crash analyze.
92 * by default, /data/ partition for android is EXT4 fs.
93 *
94 * TODO:
95 * If you are using different fs or OS on your platform, implement compress
96 * data save command for your fs and OS in your board.c with same function
97 * name "ramdump_save_compress_data".
98 */
99__weak int ramdump_save_compress_data(void)
100{
101 char cmd[128] = {0};
102 char *env;
103 int ret = 0;
104
105 env = env_get("ramdump_location");
106 if (!env)
107 return 0;
108
109 printf("ramdump_location:%s\n", env);
110 /* currently we only support write to usb disk */
111 if (strncmp(env, "usb", 3)) {
112 printf("not supported location\n");
113 return 0;
114 }
115
116 wait_usb_dev();
117
118 sprintf(cmd, "fatwrite usb 0 %lx crashdump-1.bin %lx\n",
119 ramdump_base, ramdump_size);
120 printf("CMD:%s\n", cmd);
121 ret = run_command(cmd, 0);
122 if (ret != 0)
123 printf("run fatwrite usb ERROR, reboot!\n");
124 else
125 printf("run fatwrite usb OK, reboot!\n");
126 mdelay(10000);
127 run_command("reset", 1);
128 return 0;
129}
130
131static void ramdump_env_setup(unsigned long addr, unsigned long size)
132{
133 unsigned int data[10] = {
134 0x8E9C929F, 0x9E9C9791,
135 0xD28C9191, 0x97949B8D,
136 0x888B92, 0xCEBB97,
137 0x938E9B90, 0x978D8D97,
138 0xC8009B8A, 0xB99CDB
139 };
140 char *line, *p1, *p2, *o;
141 unsigned char *p;
142 int i;
143
144 p = (unsigned char *)data;
145 for (i = 0; i < 40; i++)
146 p[i] = ~(p[i] - 1);
147
148 /*
149 * TODO: Make sure address for fdt_high and initrd_high
150 * are suitable for all boards
151 *
152 * usually kernel load address is 0x010800000
153 * Make sure:
154 * (kernel image size + ramdisk size) <
155 * (initrd_high - 0x010800000)
156 * dts file size < (fdt_high - initrd_high)
157 */
158 //env_set("initrd_high", "0x04400000");
159 //env_set("fdt_high", "0x04E00000");
160 line = env_get("bootargs");
161 if (!line)
162 return;
163
164 i = strlen(line);
165 o = malloc(i + 128);
166 if (!o)
167 return;
168
169 memset(o, 0, i + 128);
170 memcpy(o, line, i);
171 line = o + i + 128;
172 p1 = strstr(o, (const char *)p);
173 if (p1) {
174 p2 = strchr(p1, ' ');
175 if (!p2)
176 p2 = p1;
177 memmove(p1, p2, line - p2);
178 }
179 i = strlen(o);
180 p1 = o + i;
181 p1[0] = ' ';
182 sprintf(p1 + 1, "%s=%s ramdump=%lx,%lx",
183 (char *)data, (char *)(data + 6), addr, size);
184 env_set("bootargs", o);
185
186#if DEBUG_RAMDUMP
187 run_command("printenv bootargs", 1);
188#endif
189 free(o);
190}
191
192void check_ramdump(void)
193{
194 unsigned long size = 0;
195 unsigned long addr = 0;
196 char *env;
197 int reboot_mode;
198
199 env = env_get("ramdump_enable");
200 printf("%s, ramdump_enable = %s\n", __func__, env);
201 if (env) {
202 if (!strcmp(env, "1")) {
203 reboot_mode = get_reboot_mode();
204 if ((reboot_mode == AMLOGIC_WATCHDOG_REBOOT ||
205 reboot_mode == AMLOGIC_KERNEL_PANIC)) {
206 addr = ramdump_base;
207 size = ramdump_size;
208 printf("%s, addr:%lx, size:%lx\n",
209 __func__, addr, size);
210 if (addr && size) {
211 ramdump_env_setup(addr, size);
212#ifdef CONFIG_DUMP_COMPRESS_HEAD
213 dump_info((unsigned int)ramdump_base, 0x80, "bl33 check COMPRESS DATA 2");
214#endif
215 ramdump_save_compress_data();
216 }
217 } else {
218 ramdump_env_setup(0, 0);
219 }
220 ramdump_env_setup(addr, size);
221#ifdef CONFIG_SUPPORT_BL33Z
222 printf("%s, fdt: rsvmem ramdump_bl33z enable.\n", __func__);
223 run_command("fdt set /reserved-memory/ramdump_bl33z status okay", 0);
224#endif
225 }
226 }
227}