mrdump_datafs.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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 <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <malloc.h>
  35. #include <stdint.h>
  36. #include <string.h>
  37. #include <platform/mt_typedefs.h>
  38. #include <platform/mtk_wdt.h>
  39. #include <lib/zlib.h>
  40. #include "aee.h"
  41. #include "mrdump_private.h"
  42. #define BLKSIZE 4096
  43. #define MAX_CONTINUE 16 // only 1MB memory for lk
  44. #define EXSPACE (BLKSIZE*MAX_CONTINUE) // Expect continue space
  45. uint64_t lba_marker_time;
  46. struct __attribute__((__packed__)) marked_block_data {
  47. uint32_t lba;
  48. uint64_t zero_padding[510];
  49. uint64_t timestamp;
  50. uint32_t crc;
  51. } bdata;
  52. struct mrdump_lba_handle {
  53. struct mrdump_dev *dumpdev;
  54. uint64_t allocsize;
  55. uint64_t filesize;
  56. unsigned int wlba;
  57. unsigned int rlba;
  58. int bidx;
  59. int midx;
  60. unsigned int blknum;
  61. unsigned int block_lba[1024];
  62. uint8_t data[EXSPACE];
  63. };
  64. static uint64_t ext4_lba_to_block_offset(uint32_t lba)
  65. {
  66. return (uint64_t)lba * (uint64_t)BLKSIZE;
  67. }
  68. #ifdef MTK_USERIMAGES_USE_F2FS
  69. static bool check_block_valid(const struct mrdump_lba_handle *handle, uint32_t lba)
  70. {
  71. mtk_wdt_restart();
  72. if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(lba), (uint8_t *)&bdata, BLKSIZE)) {
  73. voprintf_error(" Read BlockData failed\n");
  74. return false;
  75. }
  76. if (bdata.lba != lba) {
  77. voprintf_error(" Read BlockData LBA failed (c:%08x, v:%08x)\n", bdata.lba, lba);
  78. return false;
  79. }
  80. if (bdata.timestamp != lba_marker_time) {
  81. voprintf_error(" Read BlockData timestamp failed (c:%016x, v:%016x)\n", bdata.timestamp, lba_marker_time);
  82. return false;
  83. }
  84. unsigned int crcval = crc32(0, Z_NULL, 0);
  85. crcval = crc32(crcval, (void *)&bdata, (BLKSIZE - 4));
  86. if (bdata.crc != crcval) {
  87. voprintf_error("%s: Get BlockData crc32 error (c:%08x, v:%08x)\n", __func__, crcval, bdata.crc);
  88. return false;
  89. }
  90. return true;
  91. }
  92. #endif
  93. static int Get_Next_bidx(struct mrdump_lba_handle *handle, unsigned int moves)
  94. {
  95. unsigned int mycrc;
  96. if (handle->bidx == 1022) {
  97. handle->rlba = handle->block_lba[handle->bidx];
  98. if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(handle->rlba), (uint8_t *)handle->block_lba, BLKSIZE)) {
  99. voprintf_error(" SDCard: Reading BlockLBA failed.\n");
  100. return -1;
  101. }
  102. // check crc32
  103. mycrc = crc32(0, Z_NULL, 0);
  104. mycrc = crc32(mycrc, (void *)handle->block_lba, (BLKSIZE-4));
  105. if (mycrc != handle->block_lba[1023]) {
  106. voprintf_error(" Get next index crc32 error!\n");
  107. return -1;
  108. }
  109. handle->bidx = 0;
  110. } else {
  111. handle->bidx+=moves;
  112. }
  113. return handle->bidx;
  114. }
  115. unsigned int Num_to_Join(const struct mrdump_lba_handle *handle, unsigned int idx)
  116. {
  117. unsigned int i, j;
  118. uint32_t lba;
  119. for (i=0, j=0; i<MAX_CONTINUE; i++) {
  120. lba = handle->block_lba[idx+i];
  121. if ((lba - handle->block_lba[idx]) == i) {
  122. mtk_wdt_restart();
  123. #ifdef MTK_USERIMAGES_USE_F2FS
  124. if (!check_block_valid(handle, lba)) {
  125. voprintf_error(" BlockData Verification failed\n");
  126. return 0;
  127. }
  128. #endif
  129. j++;
  130. continue;
  131. }
  132. break;
  133. }
  134. return j;
  135. }
  136. // Store data and write when buffer(handle's data) full
  137. // return left length to avoid recursive call. --> turn to for loop
  138. static int Do_Store_or_Write(struct mrdump_lba_handle *handle, uint8_t *buf, uint32_t Length)
  139. {
  140. int total;
  141. unsigned int leftspace, mylen, reval;
  142. total = BLKSIZE * handle->blknum;
  143. leftspace = total - handle->midx;
  144. // Check Length
  145. if (Length > leftspace) {
  146. mylen = leftspace;
  147. reval = Length - leftspace;
  148. } else {
  149. mylen = Length;
  150. reval = 0;
  151. }
  152. // Store
  153. while (mylen > 0) {
  154. handle->data[handle->midx] = *buf;
  155. handle->midx++;
  156. buf++;
  157. mylen--;
  158. }
  159. // Write
  160. if (handle->midx == total) {
  161. if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(handle->wlba), handle->data, total)) {
  162. voprintf_error(" SDCard: Write dump data failed.\n");
  163. return -1;
  164. }
  165. handle->bidx = Get_Next_bidx(handle, handle->blknum);
  166. if (handle->bidx < 0) {
  167. voprintf_error(" SDCard: Reading bidx failed.\n");
  168. return -1;
  169. }
  170. if (handle->bidx == 1022) {
  171. handle->bidx = Get_Next_bidx(handle, handle->blknum);
  172. if (handle->bidx < 0) {
  173. voprintf_error(" SDCard: Reading 1022 bidx failed.\n");
  174. return -1;
  175. }
  176. }
  177. handle->blknum = Num_to_Join(handle, handle->bidx);
  178. if (handle->blknum == 0)
  179. return -1;
  180. handle->wlba = handle->block_lba[handle->bidx];
  181. handle->midx = 0;
  182. }
  183. return reval;
  184. }
  185. static int lba_write_cb(void *opaque_handle, void *buf, int size)
  186. {
  187. unsigned int len, moves;
  188. int ret;
  189. uint8_t *Ptr;
  190. struct mrdump_lba_handle *handle = opaque_handle;
  191. if ((handle->filesize + size) > handle->allocsize) {
  192. voprintf_error(" dump size > allocated size. file-size %lld allocate-size %lld\n", handle->filesize + size, handle->allocsize);
  193. return -1;
  194. }
  195. handle->filesize += size;
  196. // End of File, write the left Data in handle data buffer...
  197. if ((buf == NULL) && (size == 0)) {
  198. if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(handle->wlba), handle->data, handle->midx)) {
  199. voprintf_error(" SDCard: Write dump data failed.\n");
  200. return -1;
  201. }
  202. return 0;
  203. }
  204. // buf should not be NULL if not EOF
  205. if (buf == NULL)
  206. return -1;
  207. // process of Store and write
  208. len = size;
  209. ret = len;
  210. Ptr = (uint8_t *)buf;
  211. while (1) {
  212. ret = Do_Store_or_Write(handle, Ptr, len);
  213. if (ret < 0) {
  214. voprintf_error(" SDCard: Store and Write failed.\n");
  215. return -1;
  216. } else if (ret==0) {
  217. break;
  218. } else {
  219. moves = len - ret;
  220. Ptr += moves;
  221. len = ret;
  222. }
  223. }
  224. return size;
  225. }
  226. static inline uint16_t paf_version_extract(uint8_t pafinfo[MRDUMP_PAF_TOTAL_SIZE])
  227. {
  228. return pafinfo[0] + (pafinfo[1] << 8);
  229. }
  230. static void dump_paf_info(uint8_t InfoLBA[MRDUMP_PAF_TOTAL_SIZE], const char *msg, ...)
  231. {
  232. va_list ap;
  233. va_start(ap, msg);
  234. voprintf('E', msg, ap);
  235. va_end(ap);
  236. uint32_t paf_version = paf_version_extract(InfoLBA);
  237. uint32_t paf_info_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_INFO_LBA);
  238. uint32_t paf_addr_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_ADDR_LBA);
  239. uint64_t paf_alloc_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_ALLOCSIZE);
  240. uint64_t paf_coredump_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE);
  241. uint64_t paf_timestamp = *(uint64_t *)(InfoLBA + MRDUMP_PAF_TIMESTAMP);
  242. uint32_t paf_crc32 = *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32);
  243. voprintf_info(" pafile ver %u info-lba %u addr-lba %u alloc-size %llu coredump-size %llu timestamp %llx crc %x\n",
  244. paf_version, paf_info_lba, paf_addr_lba, paf_alloc_size, paf_coredump_size, paf_timestamp, paf_crc32);
  245. }
  246. int mrdump_ext4_output(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev)
  247. {
  248. uint8_t InfoLBA[MRDUMP_PAF_TOTAL_SIZE];
  249. unsigned int mycrc;
  250. if (mrdump_dev == NULL) {
  251. return -1;
  252. }
  253. voprintf_info("Output to DATA FS Partition %s\n", mrdump_dev->name);
  254. // pre-work for ext4 LBA
  255. bzero(InfoLBA, sizeof(InfoLBA));
  256. // Error 1. InfoLBA starting address not available
  257. if (mrdump_cb->output_fs_lbaooo == 0) {
  258. voprintf_error(" Pre-Allocate has no LBA markers(lbaooo=%u). RAM-Dump stop!\n", mrdump_cb->output_fs_lbaooo);
  259. return -1;
  260. }
  261. if (!mrdump_dev->read(mrdump_dev, ext4_lba_to_block_offset(mrdump_cb->output_fs_lbaooo), (uint8_t *)InfoLBA, sizeof(InfoLBA))) {
  262. voprintf_error(" SDCard: Reading InfoLBA failed.\n");
  263. return -1;
  264. }
  265. uint32_t paf_version = paf_version_extract(InfoLBA);
  266. uint32_t paf_info_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_INFO_LBA);
  267. uint32_t paf_addr_lba = *(uint32_t *)(InfoLBA + MRDUMP_PAF_ADDR_LBA);
  268. uint64_t paf_alloc_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_ALLOCSIZE);
  269. uint64_t paf_coredump_size = *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE);
  270. uint64_t paf_timestamp = *(uint64_t *)(InfoLBA + MRDUMP_PAF_TIMESTAMP);
  271. uint32_t paf_info_crc32 = *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32);
  272. if (paf_version != MRDUMP_PAF_VERSION) {
  273. dump_paf_info(InfoLBA, " Unsupport PAF version %d (expected: %d)\n", paf_version, MRDUMP_PAF_VERSION);
  274. return -1;
  275. }
  276. // Error 3. InfoLBA[EXT4_1ST_LBA] should be mrdump_cb->output_fs_lbaooo
  277. if (mrdump_cb->output_fs_lbaooo != paf_info_lba) {
  278. dump_paf_info(InfoLBA, " LBA Starting Address Error(LBA0=%u)! Abort!\n", paf_info_lba);
  279. return -1;
  280. }
  281. // Error 4. EXT4_CORE_DUMP_SIZE is not zero --> want to hold 1st dump
  282. if (paf_coredump_size != 0) {
  283. dump_paf_info(InfoLBA, " CORE DUMP SIZE is not Zero! Abort!(coresize=%llu)\n", paf_coredump_size);
  284. return -1;
  285. }
  286. // Error 5. EXT4_USER_FILESIZE is zero
  287. if (paf_alloc_size == 0) {
  288. dump_paf_info(InfoLBA, " Allocate file with zero size. Abort!(filesize=%llu)\n", paf_alloc_size);
  289. return -1;
  290. }
  291. // get lba_marker_time as timestamp
  292. lba_marker_time = paf_timestamp;
  293. // Error 2. CRC not matched
  294. mycrc = crc32(0L, Z_NULL, 0);
  295. mycrc = crc32(mycrc, (const unsigned char*)InfoLBA, sizeof(InfoLBA) - 4);
  296. if (mycrc != paf_info_crc32) {
  297. dump_paf_info(InfoLBA, " InfoLBA CRC32 Error! Abort! (CRC1=0x%08x, CRC2=0x%08x)\n", mycrc, paf_info_crc32);
  298. return -1;
  299. }
  300. struct mrdump_lba_handle *handle = memalign(16, sizeof(struct mrdump_lba_handle));
  301. if (handle == NULL) {
  302. voprintf_error("No enough memory.\n");
  303. return -1;
  304. }
  305. memset(handle, 0, sizeof(struct mrdump_lba_handle));
  306. handle->dumpdev = mrdump_dev;
  307. handle->rlba = mrdump_cb->output_fs_lbaooo;
  308. handle->allocsize = paf_alloc_size;
  309. // Mark coredump as ULLONG_MAX to verify the unknown interrupt case during dumping data
  310. *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE) = ULLONG_MAX;
  311. //calculate the CRC
  312. mycrc = crc32(0L, Z_NULL, 0);
  313. *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32) = crc32(mycrc, (const unsigned char*)InfoLBA, MRDUMP_LBA_DATAONLY);
  314. //update the coredump sizeand CRC
  315. if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(paf_info_lba), (uint8_t *)InfoLBA, sizeof(InfoLBA))) {
  316. voprintf_error(" SDCard: Write InfoLBA error.\n");
  317. free(handle);
  318. return -1;
  319. }
  320. // Starting Dumping Data
  321. handle->rlba = paf_addr_lba;
  322. if (!handle->dumpdev->read(handle->dumpdev, ext4_lba_to_block_offset(handle->rlba), (uint8_t *)handle->block_lba, BLKSIZE)) {
  323. dump_paf_info(InfoLBA, " SDCard: Reading BlockLBA error.\n");
  324. free(handle);
  325. return -1;
  326. }
  327. handle->wlba = handle->block_lba[handle->midx];
  328. handle->blknum = Num_to_Join(handle, handle->bidx);
  329. if (handle->blknum == 0) {
  330. voprintf_error("No continuous space.\n");
  331. free(handle);
  332. return -1;
  333. }
  334. voprintf_info(" Pre-Allocate starts at LBA: %u\n", paf_info_lba);
  335. voprintf_info(" SYS_COREDUMP starts at LBA: %u\n", handle->wlba);
  336. mtk_wdt_restart();
  337. bool ok = true;
  338. mtk_wdt_restart();
  339. struct kzip_file *zf = kzip_open(handle, lba_write_cb);
  340. if (zf != NULL) {
  341. if (!kzip_add_file(zf, memlist, "SYS_COREDUMP")) {
  342. ok = false;
  343. }
  344. mtk_wdt_restart();
  345. kzip_close(zf);
  346. lba_write_cb(handle, NULL, 0); /* really write onto emmc of the last part */
  347. zf = NULL;
  348. } else {
  349. ok = false;
  350. }
  351. if (!ok) {
  352. free(handle);
  353. return -1;
  354. }
  355. voprintf_info(" SYS_COREDUMP ends at LBA: %u\n", handle->wlba);
  356. voprintf_info(" Zip COREDUMP size is: %llu\n", handle->filesize);
  357. // Record File Size...
  358. *(uint64_t *)(InfoLBA + MRDUMP_PAF_COREDUMPSIZE) = handle->filesize;
  359. mycrc = crc32(0L, Z_NULL, 0);
  360. *(uint32_t *)(InfoLBA + MRDUMP_PAF_CRC32) = crc32(mycrc, (const unsigned char*)InfoLBA, MRDUMP_LBA_DATAONLY);
  361. if (!handle->dumpdev->write(handle->dumpdev, ext4_lba_to_block_offset(paf_info_lba), (uint8_t *)InfoLBA, sizeof(InfoLBA))) {
  362. voprintf_error(" SDCard: Write InfoLBA error.\n");
  363. free(handle);
  364. return -1;
  365. }
  366. free(handle);
  367. mtk_wdt_restart();
  368. mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "DATA_FS", mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
  369. return 0;
  370. }