mrdump_mpart.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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) 2018. 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 <stdint.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <malloc.h>
  36. #ifdef MTK_GPT_SCHEME_SUPPORT
  37. #include <platform/partition.h>
  38. #else
  39. #include <mt_partition.h>
  40. #endif
  41. #ifdef MTK_PARTITION_COMMON
  42. #include <env.h>
  43. #else
  44. #include <platform/env.h>
  45. #endif
  46. #include <platform/mtk_wdt.h>
  47. #include "aee.h"
  48. #include "mrdump_private.h"
  49. #include <efi.h>
  50. #include <pal_log.h>
  51. #include <lib/crc.h>
  52. #include <part_interface.h>
  53. #include <dev/aee_platform_debug.h>
  54. #ifndef min
  55. #define min(x, y) (x < y ? x : y)
  56. #endif
  57. #define BLKSIZE 4096
  58. #define MAX_CONTINUE 16 // only 1MB memory for lk
  59. #define EXSPACE (BLKSIZE*MAX_CONTINUE) // Expect continue space
  60. #define DATA_SIZE_MIN 5368709120 // 5GB
  61. #define BYTE_SIZE_16MB 16777216
  62. /*For gpt update*/
  63. extern part_t *partition;
  64. extern int gpt_partition_table_update(const char *arg, void *data, unsigned sz);
  65. extern int read_gpt(part_t *part);
  66. struct mrdump_part_handle {
  67. struct mrdump_dev *dumpdev;
  68. uint64_t filesize;
  69. uint64_t woffset;
  70. int midx;
  71. uint8_t data[EXSPACE];
  72. };
  73. // Store data and write when buffer(handle's data) full
  74. // return left length to avoid recursive call. --> turn to for loop
  75. static int Do_Store_or_Write(struct mrdump_part_handle *handle, uint8_t *buf, uint32_t Length)
  76. {
  77. unsigned int leftspace, mylen, reval;
  78. leftspace = EXSPACE - handle->midx;
  79. // Check Length
  80. if (Length > leftspace) {
  81. mylen = leftspace;
  82. reval = Length - leftspace;
  83. } else {
  84. mylen = Length;
  85. reval = 0;
  86. }
  87. // Store
  88. while (mylen > 0) {
  89. handle->data[handle->midx] = *buf;
  90. handle->midx++;
  91. buf++;
  92. mylen--;
  93. }
  94. // Write
  95. if (handle->midx == EXSPACE) {
  96. if (!handle->dumpdev->write(handle->dumpdev, handle->woffset, handle->data, EXSPACE)) {
  97. voprintf_error(" SDCard: Write dump data failed.\n");
  98. return -1;
  99. }
  100. handle->woffset = handle->woffset + EXSPACE;
  101. handle->midx = 0;
  102. }
  103. return reval;
  104. }
  105. static int lba_write_cb(void *opaque_handle, void *buf, int size)
  106. {
  107. unsigned int len, moves;
  108. int ret;
  109. uint8_t *Ptr;
  110. struct mrdump_part_handle *handle = opaque_handle;
  111. handle->filesize += size;
  112. // End of File, write the left Data in handle data buffer...
  113. if ((buf == NULL) && (size == 0)) {
  114. if (!handle->dumpdev->write(handle->dumpdev, handle->woffset, handle->data, handle->midx)) {
  115. voprintf_error(" SDCard: Write dump data failed.\n");
  116. return -1;
  117. }
  118. return 0;
  119. }
  120. // buf should not be NULL if not EOF
  121. if (buf == NULL)
  122. return -1;
  123. // process of Store and write
  124. len = size;
  125. ret = len;
  126. Ptr = (uint8_t *)buf;
  127. while (1) {
  128. ret = Do_Store_or_Write(handle, Ptr, len);
  129. if (ret < 0) {
  130. voprintf_error(" SDCard: Store and Write failed.\n");
  131. return -1;
  132. } else if (ret==0) {
  133. break;
  134. } else {
  135. moves = len - ret;
  136. Ptr += moves;
  137. len = ret;
  138. }
  139. }
  140. return size;
  141. }
  142. int mrdump_partition_output(const struct mrdump_control_block *mrdump_cb, const struct kzip_addlist *memlist, struct mrdump_dev *mrdump_dev)
  143. {
  144. uint8_t InfoHeader[MRDUMP_PAF_TOTAL_SIZE];
  145. unsigned int mycrc;
  146. u64 mrdump_total_sect;
  147. part_dev_t *dev = mt_part_get_device();
  148. if (mrdump_dev == NULL) {
  149. return -1;
  150. }
  151. voprintf_info("Output to dynmaic Partition %s\n", mrdump_dev->name);
  152. mrdump_total_sect = partition_get_size_by_name("mrdump") / dev->blkdev->blksz;
  153. if (mrdump_total_sect == (BYTE_SIZE_16MB / dev->blkdev->blksz)) {
  154. voprintf_error("mrdump partition only 16MB\n");
  155. return -1;
  156. }
  157. // pre-work for dynamic partition header
  158. bzero(InfoHeader, sizeof(InfoHeader));
  159. if (!mrdump_dev->read(mrdump_dev, 0ULL, (uint8_t *)InfoHeader, sizeof(InfoHeader))) {
  160. voprintf_error(" SDCard: Reading InfoHeader failed.\n");
  161. return -1;
  162. }
  163. struct mrdump_part_handle *handle = memalign(16, sizeof(struct mrdump_part_handle));
  164. if (handle == NULL) {
  165. voprintf_error("No enough memory.\n");
  166. return -1;
  167. }
  168. memset(handle, 0, sizeof(struct mrdump_part_handle));
  169. handle->dumpdev = mrdump_dev;
  170. // Mark coredump as ULLONG_MAX to verify the unknown interrupt case during dumping data
  171. *(uint64_t *)(InfoHeader + MRDUMP_PAF_COREDUMPSIZE) = ULLONG_MAX;
  172. //calculate the CRC
  173. mycrc = crc32(0L, NULL, 0);
  174. *(uint32_t *)(InfoHeader + MRDUMP_PAF_CRC32) = crc32(mycrc, (const unsigned char*)InfoHeader, MRDUMP_LBA_DATAONLY);
  175. //update the coredump size and CRC
  176. if (!handle->dumpdev->write(handle->dumpdev, 0ULL, (uint8_t *)InfoHeader, sizeof(InfoHeader))) {
  177. voprintf_error(" SDCard: Write InfoHeader error.\n");
  178. free(handle);
  179. return -1;
  180. }
  181. // Starting Dumping Data
  182. handle->woffset = BLKSIZE;
  183. mtk_wdt_restart();
  184. bool ok = true;
  185. mtk_wdt_restart();
  186. struct kzip_file *zf = kzip_open(handle, lba_write_cb);
  187. if (zf != NULL) {
  188. if (!kzip_add_file(zf, memlist, "SYS_COREDUMP")) {
  189. ok = false;
  190. }
  191. mtk_wdt_restart();
  192. kzip_close(zf);
  193. lba_write_cb(handle, NULL, 0); /* really write onto emmc of the last part */
  194. } else {
  195. ok = false;
  196. }
  197. if (!ok) {
  198. free(handle);
  199. return -1;
  200. }
  201. voprintf_info(" Zip COREDUMP size is: %lld\n", handle->filesize);
  202. // Record File Size...
  203. *(uint64_t *)(InfoHeader + MRDUMP_PAF_COREDUMPSIZE) = handle->filesize;
  204. mycrc = crc32(0L, NULL, 0);
  205. *(uint32_t *)(InfoHeader + MRDUMP_PAF_CRC32) = crc32(mycrc, (const unsigned char*)InfoHeader, MRDUMP_LBA_DATAONLY);
  206. if (!handle->dumpdev->write(handle->dumpdev, 0ULL, (uint8_t *)InfoHeader, sizeof(InfoHeader))) {
  207. voprintf_error(" SDCard: Write InfoHeader error.\n");
  208. free(handle);
  209. return -1;
  210. }
  211. free(handle);
  212. mtk_wdt_restart();
  213. mrdump_status_ok("OUTPUT:%s\nMODE:%s\n", "PARTITION_DATA", mrdump_mode2string(mrdump_cb->crash_record.reboot_mode));
  214. return 0;
  215. }
  216. /*
  217. ********** Definition of GPT buffer **********
  218. */
  219. static void w2s(u8 *dst, int dst_max, u16 *src, int src_max)
  220. {
  221. int i = 0;
  222. int len = min(src_max, dst_max - 1);
  223. while (i < len) {
  224. if (!src[i]) {
  225. break;
  226. }
  227. dst[i] = src[i] & 0xFF;
  228. i++;
  229. }
  230. dst[i] = 0;
  231. return;
  232. }
  233. static int read_data(u8 *buf, u32 part_id, u64 lba, u64 size)
  234. {
  235. int err;
  236. part_dev_t *dev;
  237. dev = mt_part_get_device();
  238. if (!dev) {
  239. pal_log_err("%s: read data, err(no dev)\n", __func__);
  240. return 1;
  241. }
  242. err = dev->read(dev, lba * dev->blkdev->blksz, buf, (int)size, part_id);
  243. if (err != (int)size) {
  244. pal_log_err("%s: read data, err(%d)\n", __func__, err);
  245. return err;
  246. }
  247. return 0;
  248. }
  249. static int write_data(u64 lba, u8 *buf, u64 size, u32 part_id)
  250. {
  251. int err;
  252. part_dev_t *dev;
  253. dev = mt_part_get_device();
  254. if (!dev) {
  255. pal_log_err("%s: write data, err(no dev)\n", __func__);
  256. return 1;
  257. }
  258. err = dev->write(dev, buf, lba * dev->blkdev->blksz, (int)size, part_id);
  259. if (err != (int)size) {
  260. pal_log_err("%s: write data, err(%d)\n", __func__, err);
  261. return err;
  262. }
  263. return 0;
  264. }
  265. static int mrdump_get_part_index(const char *part_name)
  266. {
  267. int index;
  268. #ifdef MTK_AB_OTA_UPDATER
  269. int predef_part_num = 3; // preloader, preloader_a, preloader_b
  270. #else
  271. int predef_part_num = 1; // preloader
  272. #endif
  273. index = partition_get_index_by_name(part_name) - predef_part_num;
  274. if (index < 0)
  275. return -1;
  276. else
  277. return index;
  278. }
  279. /*
  280. * method=0 : mean reduce mrdump patition to SIZE_16MB
  281. * method=1 : mean extend mrdump partition to DRAM_SIZE + SIZE_16MB
  282. */
  283. int mrdump_gpt_resize(int method)
  284. {
  285. int err;
  286. uint8_t data_name[PART_META_INFO_NAMELEN];
  287. uint8_t mrdump_name[PART_META_INFO_NAMELEN];
  288. u32 part_id, gpt_entries_size;
  289. int data_index, mrdump_index;
  290. part_dev_t *dev = mt_part_get_device();
  291. gpt_entry *entries;
  292. u64 total_dump_size = physical_memory_size();
  293. u64 dram_total_sect = total_dump_size / dev->blkdev->blksz;
  294. u64 data_total_sect, mrdump_total_sect;
  295. u64 sz;
  296. u8 *data;
  297. part_id = dev->blkdev->part_user;
  298. gpt_entries_size = sizeof(gpt_entry) * PART_MAX_COUNT;
  299. sz = dev->blkdev->blksz + gpt_entries_size;
  300. data = (u8 *)malloc(sz);
  301. if (data == NULL) {
  302. voprintf_error("%s: malloc return NULL\n", __func__);
  303. return -1;
  304. }
  305. /* get gpt header + entries */
  306. err = read_data(data, part_id, 1, sz);
  307. if (err) {
  308. voprintf_error("%s: read entries(part_id=%d), err(%d)\n",
  309. __func__, part_id, err);
  310. free(data);
  311. return err;
  312. }
  313. /* parse pgpt entries */
  314. entries = (gpt_entry *)(data + dev->blkdev->blksz);
  315. mrdump_index = mrdump_get_part_index("mrdump");
  316. if (mrdump_index < 0) {
  317. voprintf_error("%s: Can't get mrdump partition index\n", __func__);
  318. goto fail;
  319. }
  320. w2s(mrdump_name, PART_META_INFO_NAMELEN, entries[mrdump_index].partition_name, GPT_ENTRY_NAME_LEN);
  321. data_index = mrdump_get_part_index("userdata");
  322. if (data_index < 0) {
  323. voprintf_error("%s: Can't get userdata partition index\n", __func__);
  324. goto fail;
  325. }
  326. w2s(data_name, PART_META_INFO_NAMELEN, entries[data_index].partition_name, GPT_ENTRY_NAME_LEN);
  327. /* resize policy
  328. * method = 0
  329. * 1. set mrdump partition to 16MB when it's size !=16MB
  330. and extend data partition
  331. * method = 1
  332. * 1. data total size should be large or equal to DATA_SIZE_MIN
  333. * 2. only do extend when mrdump total size less than DRAM size + 16MB
  334. * 3. must meet 1. and 2. requirement
  335. */
  336. data_total_sect = partition_get_size_by_name("userdata") / dev->blkdev->blksz;
  337. mrdump_total_sect = partition_get_size_by_name("mrdump") / dev->blkdev->blksz;
  338. if (method == 0) {
  339. if (mrdump_total_sect == (BYTE_SIZE_16MB / dev->blkdev->blksz)) {
  340. voprintf_error("mrdump partition already resized to 16MB\n");
  341. goto fail;
  342. }
  343. if (mrdump_total_sect != dram_total_sect + (BYTE_SIZE_16MB / dev->blkdev->blksz)) {
  344. voprintf_error("Unknown mrdump partition size (0x%llx)\n", mrdump_total_sect);
  345. goto fail;
  346. }
  347. entries[data_index].ending_lba = entries[data_index].ending_lba + dram_total_sect;
  348. entries[mrdump_index].starting_lba = entries[mrdump_index].starting_lba + dram_total_sect;
  349. }
  350. else if (method == 1) {
  351. if ((data_total_sect - dram_total_sect) < (DATA_SIZE_MIN / dev->blkdev->blksz)) {
  352. voprintf_error("mrdump partition can't do resize (0x%llx < 0x%lx)\n",(data_total_sect - dram_total_sect), (DATA_SIZE_MIN / dev->blkdev->blksz));
  353. goto fail;
  354. }
  355. if (mrdump_total_sect >= dram_total_sect + (BYTE_SIZE_16MB / dev->blkdev->blksz)) {
  356. voprintf_error("mrdump partition already resized\n");
  357. goto fail;
  358. }
  359. /* Update data.ending_lba and mrdump.starting_lba */
  360. entries[data_index].ending_lba = entries[data_index].ending_lba - dram_total_sect;
  361. entries[mrdump_index].starting_lba = entries[mrdump_index].starting_lba - dram_total_sect;
  362. }
  363. else {
  364. voprintf_error("unknown mrdump partition resize method (%d)\n", method);
  365. goto fail;
  366. }
  367. /* Update primary and secondary gpt */
  368. err = gpt_partition_table_update("gpt", data, sz);
  369. if (err) {
  370. voprintf_error("gpt_partition_table_update failed\n");
  371. goto fail;
  372. }
  373. /* re-init partition table afster update pmbor, pgpt and sgpt */
  374. read_gpt(partition);
  375. /* erase data partition */
  376. if (method == 1)
  377. partition_erase("userdata");
  378. fail:
  379. /* Free data buffers after using it */
  380. free(data);
  381. return 0;
  382. }
  383. void mrdump_partition_resize(void)
  384. {
  385. if (mrdump_get_part_index("mrdump") != -1) {
  386. pal_log_err("mrdump_partition_resize: start resize mrdump partition\n");
  387. if (mrdump_get_default_output_device() == MRDUMP_DEV_PARTITION)
  388. mrdump_gpt_resize(1);
  389. else
  390. mrdump_gpt_resize(0);
  391. }
  392. else
  393. pal_log_err("%s: mrdump doesn't exist\n", __func__);
  394. }