mrdump_mpart.c 13 KB

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