bootctrl_api.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein is
  5. * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
  6. * the prior written permission of MediaTek inc. and/or its licensors, any
  7. * reproduction, modification, use or disclosure of MediaTek Software, and
  8. * information contained herein, in whole or in part, shall be strictly
  9. * prohibited.
  10. *
  11. * MediaTek Inc. (C) 2016. All rights reserved.
  12. *
  13. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  14. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  15. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
  16. * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
  17. * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  19. * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
  20. * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
  21. * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
  22. * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
  23. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
  24. * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
  25. * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
  26. * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  27. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
  28. * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
  29. * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
  30. * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
  31. * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  32. *
  33. * The following software/firmware and/or related documentation ("MediaTek
  34. * Software") have been modified by MediaTek Inc. All revisions are subject to
  35. * any receiver's applicable license agreements with MediaTek Inc.
  36. */
  37. #include <stdint.h>
  38. #include <pal_typedefs.h>
  39. #include <pal_log.h>
  40. #include <part_interface.h>
  41. #include <string.h>
  42. #include <platform/mt_typedefs.h>
  43. #include <block_generic_interface.h>
  44. #include "part_dev.h"
  45. #include "avb_util.h"
  46. #include "bootctrl.h"
  47. #include "debug.h"
  48. #include "mmc_core.h"
  49. #include "mmc_common_inter.h"
  50. #include "ufs_aio_hcd.h"
  51. #define BOOTCTR_PARTITION "misc"
  52. static const char *suffix[2] = {BOOTCTRL_SUFFIX_A, BOOTCTRL_SUFFIX_B};
  53. static struct bootloader_control boot_control;
  54. static int bootctl_exists = 0;
  55. int check_suffix_with_slot(const char *suffix)
  56. {
  57. int slot = -1;
  58. if (suffix == NULL) {
  59. pal_log_err("[LK] input suffix is NULL\n");
  60. return -1;
  61. }
  62. if (!strcmp(suffix, BOOTCTRL_SUFFIX_A))
  63. slot = 0;
  64. else if (!strcmp(suffix, BOOTCTRL_SUFFIX_B))
  65. slot = 1;
  66. else
  67. pal_log_err("[LK] unknow slot suffix\n");
  68. return slot;
  69. }
  70. static void initDefaultBootControl(struct bootloader_control *bctrl) {
  71. int slot = 0;
  72. struct slot_metadata *slotp;
  73. bctrl->magic = BOOTCTRL_MAGIC;
  74. bctrl->version = BOOTCTRL_VERSION;
  75. bctrl->nb_slot = BOOTCTRL_NUM_SLOTS;
  76. /* Set highest priority and reset retry count */
  77. for (slot = 0; slot < BOOTCTRL_NUM_SLOTS; slot++) {
  78. slotp = &bctrl->slot_info[slot];
  79. slotp->successful_boot = 0;
  80. slotp->priority = BOOT_CONTROL_MAX_PRI;
  81. slotp->tries_remaining = BOOT_CONTROL_MAX_RETRY;
  82. }
  83. bctrl->crc32_le = avb_crc32((const uint8_t*)bctrl, sizeof(struct bootloader_control) - sizeof(uint32_t));
  84. }
  85. static int read_write_partition_info(struct bootloader_control *bctrl, int mode)
  86. {
  87. int ret = -1;
  88. if (bctrl == NULL) {
  89. pal_log_err("[LK] read_write_partition_info failed, bctrl is NULL\n");
  90. return ret;
  91. }
  92. if (mode == READ_PARTITION) {
  93. if (boot_control.magic != BOOTCTRL_MAGIC) {
  94. if (partition_read(BOOTCTR_PARTITION, (off_t) OFFSETOF_SLOT_SUFFIX, (uint8_t *) &boot_control, (size_t) sizeof(struct bootloader_control)) <= 0) {
  95. pal_log_err("[LK] read boot_control fail\n");
  96. return ret;
  97. }
  98. bootctl_exists = 0;
  99. if (boot_control.magic != BOOTCTRL_MAGIC) {
  100. initDefaultBootControl(&boot_control);
  101. bootctl_exists = 0;
  102. } else {
  103. bootctl_exists = 1;
  104. }
  105. }
  106. memcpy(bctrl, &boot_control, sizeof(struct bootloader_control));
  107. } else if (mode == WRITE_PARTITION) {
  108. if (!bootctl_exists) {
  109. pal_log_info("[LK] skip bootctrl write because it's not inited\n");
  110. return 0;
  111. }
  112. bctrl->crc32_le = avb_crc32((const uint8_t *)bctrl, sizeof(struct bootloader_control) - sizeof(uint32_t));
  113. if (partition_write(BOOTCTR_PARTITION, (uint64_t) OFFSETOF_SLOT_SUFFIX, (uint8_t *) bctrl, (uint32_t) sizeof(struct bootloader_control)) <= 0) {
  114. pal_log_err("[LK] read_write_partition_info partition_write failed, unknown mode\n");
  115. return ret;
  116. }
  117. } else {
  118. pal_log_err("[LK] unknown mode, ret: 0x%x\n", ret);
  119. return ret;
  120. }
  121. return 0;
  122. }
  123. const char *get_suffix(void)
  124. {
  125. int slot = 0, ret = -1;
  126. struct bootloader_control metadata;
  127. ret = read_write_partition_info(&metadata, READ_PARTITION);
  128. if (ret < 0) {
  129. pal_log_err("[LK] read_partition_info failed, ret: 0x%x\n", ret);
  130. return NULL;
  131. }
  132. if(metadata.magic != BOOTCTRL_MAGIC) {
  133. pal_log_err("[LK] boot_ctrl magic number is not match %x , BOOTCTRL_MAGIC = %x\n",
  134. metadata.magic, BOOTCTRL_MAGIC);
  135. return NULL;
  136. } else {
  137. pal_log_info("[LK] boot_ctrl magic number is match, compare priority %d, %d\n", metadata.slot_info[0].priority, metadata.slot_info[1].priority);
  138. if (metadata.slot_info[0].priority >= metadata.slot_info[1].priority)
  139. slot = 0;
  140. else if (metadata.slot_info[0].priority < metadata.slot_info[1].priority)
  141. slot = 1;
  142. }
  143. return suffix[slot];
  144. }
  145. int get_slot_info(int slot, uint8_t *priority, uint8_t *tries_remaining, uint8_t *successful_boot) {
  146. int ret;
  147. struct bootloader_control metadata;
  148. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  149. pal_log_err("[LK] set_active_slot failed, slot: 0x%x\n", slot);
  150. return 1;
  151. }
  152. ret = read_write_partition_info(&metadata, READ_PARTITION);
  153. if (ret < 0) {
  154. pal_log_err("[LK] read_partition_info failed, ret: 0x%x\n", ret);
  155. return 1;
  156. }
  157. if(metadata.magic != BOOTCTRL_MAGIC) {
  158. pal_log_err("[LK] boot_ctrl magic number is not match %x , BOOTCTRL_MAGIC = %x\n",
  159. metadata.magic, BOOTCTRL_MAGIC);
  160. return 1;
  161. } else {
  162. *priority = metadata.slot_info[slot].priority;
  163. *tries_remaining = metadata.slot_info[slot].tries_remaining;
  164. *successful_boot = metadata.slot_info[slot].successful_boot;
  165. }
  166. return 0;
  167. }
  168. static int set_boot_region(int slot)
  169. {
  170. int ret = -1;
  171. u32 boot_part = 0;
  172. part_dev_t *dev;
  173. dev = mt_part_get_device();
  174. if(slot == 0) {
  175. #if defined(MTK_EMMC_SUPPORT)
  176. if (dev->blkdev->type == BOOTDEV_SDMMC)
  177. boot_part = EMMC_PART_BOOT1;
  178. #endif
  179. #if defined(MTK_UFS_SUPPORT)
  180. if (dev->blkdev->type == BOOTDEV_UFS)
  181. boot_part = ATTR_B_BOOT_LUN_EN_BOOT_LU_A;
  182. #endif
  183. } else if(slot == 1) {
  184. #if defined(MTK_EMMC_SUPPORT)
  185. if (dev->blkdev->type == BOOTDEV_SDMMC)
  186. boot_part = EMMC_PART_BOOT2;
  187. #endif
  188. #if defined(MTK_UFS_SUPPORT)
  189. if (dev->blkdev->type == BOOTDEV_UFS)
  190. boot_part = ATTR_B_BOOT_LUN_EN_BOOT_LU_B;
  191. #endif
  192. }
  193. #if defined(MTK_EMMC_SUPPORT)
  194. if (dev->blkdev->type == BOOTDEV_SDMMC) {
  195. ret = mmc_set_boot_part(boot_part);
  196. return ret;
  197. }
  198. #endif
  199. #if defined(MTK_UFS_SUPPORT)
  200. extern struct ufs_hba g_ufs_hba;
  201. struct ufs_hba *hba = &g_ufs_hba;
  202. ret = ufs_aio_set_boot_lu(hba, boot_part);
  203. #endif
  204. return ret;
  205. }
  206. int get_bootctrl_data(struct bootloader_control *metadata)
  207. {
  208. int ret;
  209. ret = read_write_partition_info(metadata, READ_PARTITION);
  210. if (ret < 0) {
  211. pal_log_err("[LK] %s failed, ret: 0x%x\n", __func__, ret);
  212. return -1;
  213. }
  214. return 0;
  215. }
  216. int set_active_slot(const char *suffix)
  217. {
  218. int slot = 0, slot1 = 0;
  219. int ret = -1;
  220. struct slot_metadata *slotp;
  221. struct bootloader_control metadata;
  222. slot = check_suffix_with_slot(suffix);
  223. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  224. pal_log_err("[LK] set_active_slot failed, slot: 0x%x\n", slot);
  225. return -1;
  226. }
  227. if (suffix == NULL) {
  228. pal_log_err("[LK] input suffix is NULL\n");
  229. return -1;
  230. }
  231. ret = read_write_partition_info(&metadata, READ_PARTITION);
  232. if (ret < 0) {
  233. pal_log_err("[LK] partition_read failed, ret: 0x%x\n", ret);
  234. return -1;
  235. }
  236. metadata.magic = BOOTCTRL_MAGIC;
  237. /* Set highest priority and reset retry count */
  238. slotp = &metadata.slot_info[slot];
  239. slotp->successful_boot = 0;
  240. slotp->priority = BOOT_CONTROL_MAX_PRI;
  241. slotp->tries_remaining = BOOT_CONTROL_MAX_RETRY;
  242. /* Ensure other slot doesn't have as high a priority. */
  243. slot1 = (slot == 0) ? 1 : 0;
  244. slotp = &metadata.slot_info[slot1];
  245. if (slotp->priority >= BOOT_CONTROL_MAX_PRI)
  246. slotp->priority = BOOT_CONTROL_MAX_PRI - 1;
  247. /* Switch boot part in boot region */
  248. ret = set_boot_region(slot);
  249. if (ret < 0) {
  250. pal_log_err("[LK] set boot part to slot %d fail, ret: 0x%x\n", slot, ret);
  251. return -1;
  252. }
  253. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  254. if (ret < 0) {
  255. pal_log_err("[LK] partition_write failed, ret: 0x%x\n", ret);
  256. return -1;
  257. }
  258. return 0;
  259. }
  260. uint8_t get_retry_count(const char *suffix)
  261. {
  262. int slot = 0;
  263. int ret = -1;
  264. struct bootloader_control metadata;
  265. slot = check_suffix_with_slot(suffix);
  266. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  267. pal_log_err("[LK] get_retry_count failed, slot: 0x%x\n", slot);
  268. return 0;
  269. }
  270. ret = read_write_partition_info(&metadata, READ_PARTITION);
  271. if (ret < 0) {
  272. pal_log_err("[LK] partition_read failed, ret: 0x%x\n", ret);
  273. return 0;
  274. }
  275. return metadata.slot_info[slot].tries_remaining;
  276. }
  277. /* Return value:
  278. 0: phone does not boot to home screen yet
  279. 1: phone already boots to home screen
  280. -1: read misc partition error
  281. */
  282. int get_bootup_status(const char *suffix)
  283. {
  284. int slot = 0, ret = -1;
  285. struct bootloader_control metadata;
  286. slot = check_suffix_with_slot(suffix);
  287. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  288. pal_log_err("set_not_boot_mode failed, slot: 0x%x\n", slot);
  289. return -1;
  290. }
  291. ret = read_write_partition_info(&metadata, READ_PARTITION);
  292. if (ret < 0) {
  293. pal_log_err("partition_read failed, ret: 0x%x\n", ret);
  294. return -1;
  295. }
  296. return metadata.slot_info[slot].successful_boot;
  297. }
  298. /* Return value:
  299. 0: slot is unbootable , tries_remaining equal to 0
  300. 1: slot is bootable , tries_remaining larger than 0
  301. -1: read misc partition error
  302. */
  303. int get_bootable_status(const char *suffix)
  304. {
  305. int slot = 0, ret = -1;
  306. struct bootloader_control metadata;
  307. slot = check_suffix_with_slot(suffix);
  308. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  309. pal_log_err("get_bootable_status failed, slot: 0x%x\n", slot);
  310. return -1;
  311. }
  312. ret = read_write_partition_info(&metadata, READ_PARTITION);
  313. if (ret < 0) {
  314. pal_log_err("partition_read failed, ret: 0x%x\n", ret);
  315. return -1;
  316. }
  317. if (metadata.slot_info[slot].priority > 0)
  318. return 1;
  319. return 0;
  320. }
  321. int bootctrl_retry_decrease(int slot)
  322. {
  323. int ret;
  324. struct bootloader_control metadata;
  325. struct slot_metadata *slotp;
  326. ret = read_write_partition_info(&metadata, READ_PARTITION);
  327. if (ret < 0) {
  328. pal_log_err("[LK] partition_read failed, ret: 0x%x\n", ret);
  329. return -1;
  330. }
  331. slotp = &metadata.slot_info[slot];
  332. if (slotp->tries_remaining > 0 && !slotp->successful_boot) {
  333. slotp->tries_remaining--;
  334. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  335. if (ret < 0) {
  336. pal_log_err("[LK] partition_write failed, ret: 0x%x\n", ret);
  337. return -1;
  338. }
  339. }
  340. return 0;
  341. }
  342. int increase_tries_remaining(void)
  343. {
  344. int slot = 0, ret = -1;
  345. struct slot_metadata *slotp;
  346. struct bootloader_control metadata;
  347. const char *suffix = NULL;
  348. suffix = get_suffix();
  349. slot = check_suffix_with_slot(suffix);
  350. if (slot < 0 || slot >= BOOTCTRL_NUM_SLOTS) {
  351. pal_log_err("[LK] check_suffix_with_slot failed, slot: 0x%x\n", slot);
  352. return -1;
  353. }
  354. ret = read_write_partition_info(&metadata, READ_PARTITION);
  355. if (ret < 0) {
  356. pal_log_err("[LK] partition_read failed, ret: 0x%x\n", ret);
  357. return -1;
  358. }
  359. slotp = &metadata.slot_info[slot];
  360. if (slotp->tries_remaining < BOOT_CONTROL_MAX_RETRY &&
  361. slotp->tries_remaining > 0 && !slotp->successful_boot)
  362. slotp->tries_remaining++;
  363. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  364. if (ret < 0) {
  365. pal_log_err("[LK] partition_write failed, ret: 0x%x\n", ret);
  366. return -1;
  367. }
  368. return 0;
  369. }