bootctrl_api.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 "bootctrl.h"
  38. #include "platform.h"
  39. #include "mmc_core.h"
  40. #include "storage_api.h"
  41. #include <partition_api.h>
  42. #include <partition_active.h>
  43. #define BOOTCTR_PARTITION "para"
  44. #define MOD "bootctrl"
  45. /******************************************************************************
  46. * DEBUG
  47. ******************************************************************************/
  48. #define SMSG print
  49. static const char* suffix[2] = {BOOTCTRL_SUFFIX_A, BOOTCTRL_SUFFIX_B};
  50. static boot_ctrl_t metadata_saved;
  51. static int metadata_read = 0;
  52. int check_suffix_with_slot(const char *suffix)
  53. {
  54. int slot = -1;
  55. if(suffix == NULL) {
  56. SMSG("input suffix is NULL\n");
  57. return -1;
  58. }
  59. if(strcmp(suffix, BOOTCTRL_SUFFIX_A) == 0) {
  60. slot = 0;
  61. }
  62. else if(strcmp(suffix, BOOTCTRL_SUFFIX_B) == 0) {
  63. slot = 1;
  64. }
  65. else {
  66. SMSG("unknow slot suffix\n");
  67. }
  68. return slot;
  69. }
  70. static int read_write_partition_info(boot_ctrl_t *bctrl ,int mode)
  71. {
  72. u32 boot_ctrl_size;
  73. blkdev_t *bootdev = NULL;
  74. part_t *part = NULL;
  75. u64 src = 0;
  76. u32 part_id = 0;
  77. int ret = -1, storage_type = 0;
  78. boot_ctrl_size = sizeof(boot_ctrl_t);
  79. storage_type = ab_get_storage_type();
  80. if(storage_type == -1) {
  81. print("unknown device type\n");
  82. return -1;
  83. }
  84. if (NULL == (bootdev = blkdev_get(CFG_BOOT_DEV))) {
  85. SMSG("[%s] can't find boot device(%d)\n", MOD, CFG_BOOT_DEV);
  86. return -1;
  87. }
  88. if(NULL == (part = part_get(BOOTCTR_PARTITION))) {
  89. #if (CFG_DRAM_CALIB_OPTIMIZATION || EARLY_PARTITION_ACCESS)
  90. SMSG("[%s] Try to query by sram\n", MOD);
  91. /* The fail might caused by dram not init yet, using sram query then */
  92. src = get_part_addr(BOOTCTR_PARTITION);
  93. if (src == 0)
  94. SMSG("[%s] get_part_addr fail\n", MOD);
  95. part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
  96. #else
  97. SMSG("[%s] part_get fail\n", MOD);
  98. #endif
  99. } else {
  100. src = (u64)part->start_sect * bootdev->blksz;
  101. part_id = part->part_id;
  102. }
  103. src += OFFSETOF_SLOT_SUFFIX;
  104. if(bctrl == NULL) {
  105. SMSG("read_write_partition_info failed, bctrl is NULL\n");
  106. return ret;
  107. }
  108. if(mode == READ_PARTITION) {
  109. if ((metadata_read) && (metadata_saved.magic == BOOTCTRL_MAGIC)) {
  110. memcpy(bctrl, &metadata_saved, sizeof(boot_ctrl_t));
  111. }
  112. else {
  113. if (-1 == blkdev_read(bootdev, src, boot_ctrl_size, (char *)bctrl, part_id)) {
  114. SMSG("[%s] part_load fail\n", MOD);
  115. return ret;
  116. }
  117. else {
  118. memcpy(&metadata_saved, bctrl, sizeof(boot_ctrl_t));
  119. metadata_read = 1;
  120. }
  121. }
  122. }
  123. else if(mode == WRITE_PARTITION) {
  124. if (-1 == blkdev_write(bootdev, src, boot_ctrl_size, (char *)bctrl, part_id)) {
  125. SMSG("[%s] part_load fail\n", MOD);
  126. return ret;
  127. }
  128. else {
  129. metadata_read = 0; //force to read from partition after successful blkdev_write()
  130. }
  131. }
  132. else {
  133. SMSG(" unknown mode, ret: 0x%x\n", ret);
  134. return ret;
  135. }
  136. ret = 0;
  137. return ret;
  138. }
  139. const char *get_suffix(void)
  140. {
  141. int slot = 0, ret = -1;
  142. boot_ctrl_t metadata;
  143. ret = read_write_partition_info(&metadata, READ_PARTITION);
  144. if (ret < 0) {
  145. SMSG("get_suffix read_partition_info failed, ret: 0x%x\n", ret);
  146. return NULL;
  147. }
  148. if(metadata.magic != BOOTCTRL_MAGIC) {
  149. SMSG("boot_ctrl magic number is wrong, use default value\n");
  150. slot = 0;
  151. set_active_slot(BOOTCTRL_SUFFIX_A);
  152. }
  153. else {
  154. SMSG("boot_ctrl magic number is match, compare priority\n");
  155. if(metadata.slot_info[0].priority >= metadata.slot_info[1].priority)
  156. slot = 0;
  157. else if (metadata.slot_info[0].priority < metadata.slot_info[1].priority)
  158. slot = 1;
  159. }
  160. return suffix[slot];
  161. }
  162. int set_active_slot(const char *suffix) {
  163. int slot = 0 ,slot1 = 0;
  164. int ret = -1;
  165. slot_metadata_t *slotp;
  166. boot_ctrl_t metadata;
  167. slot = check_suffix_with_slot(suffix);
  168. if(slot == -1) {
  169. SMSG("set_active_slot failed, slot: 0x%x\n", slot);
  170. return -1;
  171. }
  172. if(suffix == NULL) {
  173. SMSG("input suffix is NULL\n");
  174. return -1;
  175. }
  176. ret = read_write_partition_info(&metadata, READ_PARTITION);
  177. if(ret < 0) {
  178. SMSG("partition_read failed, ret: 0x%x\n", ret);
  179. return -1;
  180. }
  181. metadata.magic = BOOTCTRL_MAGIC;
  182. /* Set highest priority and reset retry count */
  183. slotp = &metadata.slot_info[slot];
  184. slotp->successful_boot = 0;
  185. slotp->priority = 7;
  186. slotp->retry_count = 3;
  187. slotp->normal_boot = 1;
  188. /* Re-set arg to another slot */
  189. slot1 = (slot == 0) ? 1 : 0;
  190. slotp = &metadata.slot_info[slot1];
  191. slotp->successful_boot = 0;
  192. slotp->priority = 0;
  193. slotp->retry_count = 0;
  194. slotp->normal_boot = 0;
  195. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  196. if (ret < 0) {
  197. SMSG("partition_write failed, ret: 0x%x\n", ret);
  198. return -1;
  199. }
  200. return 0;
  201. }
  202. uint8_t get_retry_count(const char *suffix)
  203. {
  204. int slot = 0;
  205. int ret = -1;
  206. slot_metadata_t *slotp;
  207. boot_ctrl_t metadata;
  208. slot = check_suffix_with_slot(suffix);
  209. if(slot == -1) {
  210. SMSG("get_retry_count failed, slot: 0x%x\n", slot);
  211. return -1;
  212. }
  213. ret = read_write_partition_info(&metadata, READ_PARTITION);
  214. if (ret < 0) {
  215. SMSG("partition_read failed, ret: 0x%x\n", ret);
  216. return -1;
  217. }
  218. slotp = &metadata.slot_info[slot];
  219. return slotp->retry_count;
  220. }
  221. int set_normal_boot(const char *suffix, int boot_mode)
  222. {
  223. int slot = 0, ret = -1;
  224. slot_metadata_t *slotp;
  225. boot_ctrl_t metadata;
  226. slot = check_suffix_with_slot(suffix);
  227. if(slot == -1) {
  228. SMSG("set_not_normal_boot failed, slot: 0x%x\n", slot);
  229. return -1;
  230. }
  231. ret = read_write_partition_info(&metadata, READ_PARTITION);
  232. if(ret < 0) {
  233. SMSG("partition_read failed, ret: 0x%x\n", ret);
  234. return -1;
  235. }
  236. slotp = &metadata.slot_info[slot];
  237. slotp->normal_boot = boot_mode;
  238. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  239. if(ret < 0) {
  240. SMSG("partition_write failed, ret: 0x%x\n", ret);
  241. return -1;
  242. }
  243. return 0;
  244. }
  245. int reduce_retry_count(const char *suffix)
  246. {
  247. int slot = 0, ret = -1;
  248. slot_metadata_t *slotp;
  249. boot_ctrl_t metadata;
  250. slot = check_suffix_with_slot(suffix);
  251. if(slot == -1) {
  252. SMSG("set_not_normal_boot failed, slot: 0x%x\n", slot);
  253. return -1;
  254. }
  255. ret = read_write_partition_info(&metadata, READ_PARTITION);
  256. if(ret < 0) {
  257. SMSG("partition_read failed, ret: 0x%x\n", ret);
  258. return -1;
  259. }
  260. slotp = &metadata.slot_info[slot];
  261. if(slotp->retry_count > 0)
  262. slotp->retry_count--;
  263. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  264. if(ret < 0) {
  265. SMSG("partition_write failed, ret: 0x%x\n", ret);
  266. return -1;
  267. }
  268. return 0;
  269. }
  270. int get_boot_mode(const char *suffix)
  271. {
  272. int slot = 0;
  273. int ret = -1;
  274. slot_metadata_t *slotp;
  275. boot_ctrl_t metadata;
  276. slot = check_suffix_with_slot(suffix);
  277. if(slot == -1) {
  278. SMSG("get_retry_count failed, slot: 0x%x\n", slot);
  279. return -1;
  280. }
  281. ret = read_write_partition_info(&metadata, READ_PARTITION);
  282. if (ret < 0) {
  283. SMSG("partition_read failed, ret: 0x%x\n", ret);
  284. return -1;
  285. }
  286. slotp = &metadata.slot_info[slot];
  287. return slotp->normal_boot;
  288. }
  289. int check_valid_slot(void)
  290. {
  291. int slot = 0, ret = -1;
  292. boot_ctrl_t metadata;
  293. ret = read_write_partition_info(&metadata, READ_PARTITION);
  294. if (ret < 0) {
  295. SMSG("check_valid_slot read_partition_info failed, ret: 0x%x\n", ret);
  296. return -1;
  297. }
  298. if(metadata.slot_info[0].priority > 0)
  299. return 0;
  300. else if (metadata.slot_info[1].priority > 0)
  301. return 0;
  302. return -1;
  303. }
  304. int mark_slot_invalid(const char *suffix)
  305. {
  306. int slot = 0, slot2 = 0, ret = -1;
  307. slot_metadata_t *slotp;
  308. boot_ctrl_t metadata;
  309. slot = check_suffix_with_slot(suffix);
  310. if(slot == -1) {
  311. SMSG("set_not_normal_boot failed, slot: 0x%x\n", slot);
  312. return -1;
  313. }
  314. ret = read_write_partition_info(&metadata, READ_PARTITION);
  315. if(ret < 0) {
  316. SMSG("partition_read failed, ret: 0x%x\n", ret);
  317. return -1;
  318. }
  319. slotp = &metadata.slot_info[slot];
  320. slotp->successful_boot = 0;
  321. slotp->priority = 0;
  322. ret = read_write_partition_info(&metadata, WRITE_PARTITION);
  323. if(ret < 0) {
  324. SMSG("partition_write failed, ret: 0x%x\n", ret);
  325. return -1;
  326. }
  327. return 0;
  328. }
  329. int get_bootup_status(const char *suffix)
  330. {
  331. int slot = 0, ret = -1;
  332. slot_metadata_t *slotp;
  333. boot_ctrl_t metadata;
  334. slot = check_suffix_with_slot(suffix);
  335. if(slot == -1) {
  336. SMSG("set_not_normal_boot failed, slot: 0x%x\n", slot);
  337. return -1;
  338. }
  339. ret = read_write_partition_info(&metadata, READ_PARTITION);
  340. if(ret < 0) {
  341. SMSG("partition_read failed, ret: 0x%x\n", ret);
  342. return -1;
  343. }
  344. slotp = &metadata.slot_info[slot];
  345. return slotp->successful_boot;
  346. return 0;
  347. }
  348. int ab_get_storage_type(void)
  349. {
  350. blkdev_t *bootdev = NULL;
  351. bootdev = blkdev_get(CFG_BOOT_DEV);
  352. if (bootdev == NULL) {
  353. print("%s can't find boot device(%d)\n", MOD, CFG_BOOT_DEV);
  354. return -1;
  355. }
  356. if (bootdev->type == BOOTDEV_SDMMC) {
  357. print("device is EMMC\n");
  358. return BOOTDEV_SDMMC;
  359. } else if (bootdev->type == BOOTDEV_UFS) {
  360. print("device is UFS\n");
  361. return BOOTDEV_UFS;
  362. }
  363. print("unknown device type\n");
  364. return -1;
  365. }
  366. int ab_get_boot_part(u32 *bootpart)
  367. {
  368. int ret = 0, storage_type = 0;
  369. u32 boot_part = 0;
  370. storage_type = ab_get_storage_type();
  371. if(storage_type == -1) {
  372. print("unknown device type\n");
  373. return -1;
  374. }
  375. if (storage_type == BOOTDEV_SDMMC) {
  376. ret = mmc_get_boot_part(&boot_part);
  377. if(boot_part == EMMC_PART_BOOT1)
  378. *bootpart = BOOT_PART_A;
  379. else if(boot_part == EMMC_PART_BOOT2)
  380. *bootpart = BOOT_PART_B;
  381. } else if (storage_type == BOOTDEV_UFS) {
  382. ret = ufs_get_boot_part(&boot_part);
  383. if(boot_part == STORAGE_PHYS_PART_BOOT1)
  384. *bootpart = BOOT_PART_A;
  385. else if(boot_part == STORAGE_PHYS_PART_BOOT2)
  386. *bootpart = BOOT_PART_B;
  387. }
  388. return ret;
  389. }
  390. int ab_set_boot_part(u32 bootpart)
  391. {
  392. int storage_type = 0;
  393. storage_type = ab_get_storage_type();
  394. if(storage_type == -1) {
  395. print("unknown device type\n");
  396. return -1;
  397. }
  398. if (storage_type == BOOTDEV_SDMMC) {
  399. return mmc_set_boot_part(bootpart);
  400. } else if (storage_type == BOOTDEV_UFS) {
  401. if (bootpart == BOOT_PART_A)
  402. bootpart = STORAGE_PHYS_PART_BOOT1;
  403. else if (bootpart == BOOT_PART_B)
  404. bootpart = STORAGE_PHYS_PART_BOOT2;
  405. return ufs_set_boot_part(bootpart);
  406. }
  407. }