odm_mdtbo.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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) 2017. 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 <odm_mdtbo.h> // for get_odm_mdtbo_index()
  32. #include <debug.h> // for dprintf()
  33. #include <part_interface.h> // for partition_read()
  34. #include <part_status.h>
  35. #include <block_generic_interface.h> // for mt_part_get_device()
  36. #include <stdlib.h> // for malloc()
  37. #include <libfdt.h>
  38. #include <img_info.h>
  39. #include <rsc.h>
  40. /* global variable to send androidboot.dtbo_idx */
  41. static int hw_mdtbo_index = -1;
  42. int get_dtbo_index(void)
  43. {
  44. if (hw_mdtbo_index == -1)
  45. panic("hw_mdtbo_index is not inited!\n");
  46. return hw_mdtbo_index;
  47. }
  48. void set_dtbo_index(int dtbo_idx)
  49. {
  50. hw_mdtbo_index = dtbo_idx;
  51. }
  52. /******************************************************************************
  53. * NOTE: Customers need to implement their own customized_get_odm_mdtbo_index()
  54. * function. If customized_get_odm_mdtbo_index() is not implemented, the
  55. * value 0 will be used as the default dtbo index. Each customer can
  56. * maintain their own implementation of customized_get_odm_mdtbo_index()
  57. * in a separate source file as long as it can be linked.
  58. ******************************************************************************/
  59. int get_odm_mdtbo_index(void)
  60. {
  61. int odm_dtbo_index = 0;
  62. int rsc_is_valid = 0;
  63. if (rsc_get_dtbo_index) {
  64. rsc_is_valid = rsc_valid();
  65. if (rsc_is_valid)
  66. odm_dtbo_index = rsc_get_dtbo_index();
  67. }
  68. if (!rsc_is_valid) {
  69. if (customized_get_odm_mdtbo_index)
  70. odm_dtbo_index = customized_get_odm_mdtbo_index();
  71. }
  72. return odm_dtbo_index;
  73. }
  74. /******************************************************************************
  75. ******************************************************************************/
  76. static bool is_odm_mdtbo_header(const mdtbo_hdr_t *hdr2)
  77. {
  78. if (hdr2->info.magic != ODM_MDTBO_MAGIC) {
  79. dprintf(INFO, "Single ODM DTBO.\n");
  80. return false;
  81. }
  82. dprintf(INFO, "Multiple ODM DTBO.\n");
  83. return true;
  84. }
  85. /******************************************************************************
  86. * dtb_size: It is the size of the device tree selected by dtbo_index.
  87. * dtb_offset: It is the offset from the beginning of the partition.
  88. ******************************************************************************/
  89. static void get_odm_mdtbo_offset_and_size(const mdtbo_hdr_t *hdr2,
  90. int mdtbo_index, unsigned int *dtbo_size, unsigned int *dtbo_offset)
  91. {
  92. if (mdtbo_index < 0 || mdtbo_index >= MAX_NUM_OF_ODM_MDTBO) {
  93. goto fail;
  94. }
  95. if ((unsigned int)mdtbo_index == hdr2->info.num_of_dtbo - 1)
  96. *dtbo_size = hdr2->info.dsize;
  97. else {
  98. if ((mdtbo_index+1) >= MAX_NUM_OF_ODM_MDTBO)
  99. goto fail;
  100. *dtbo_size = hdr2->info.dtbo_offset[mdtbo_index + 1];
  101. }
  102. if (*dtbo_size <= hdr2->info.dtbo_offset[mdtbo_index]) {
  103. dprintf(CRITICAL, "Error: incorrect dtbo size\n");
  104. assert(0);
  105. }
  106. *dtbo_size -= hdr2->info.dtbo_offset[mdtbo_index];
  107. *dtbo_offset = hdr2->info.dtbo_offset[mdtbo_index];
  108. *dtbo_offset += PART_HDR_DATA_SIZE + ODM_MDTBO_HDR_SIZE;
  109. return;
  110. fail:
  111. dprintf(CRITICAL, "Error: mdtbo index %d is out of range!\n", mdtbo_index);
  112. assert(0);
  113. }
  114. /******************************************************************************
  115. * Side effect: This function allocates a memory on success.
  116. ******************************************************************************/
  117. static bool load_dtb_from_single_dtbo(char *part_name, union mkimg_hdr *img_hdr,
  118. char **handle, uint64_t recovery_dtbo_offset)
  119. {
  120. unsigned int dsize = img_hdr->info.dsz;
  121. *handle = malloc(dsize);
  122. if (*handle == NULL) {
  123. dprintf(CRITICAL, "Fail to malloc %d-byte buffer for dtbo!\n", dsize);
  124. assert(0);
  125. return false;
  126. }
  127. long len = partition_read(part_name, (off_t)(recovery_dtbo_offset+PART_HDR_DATA_SIZE), (uchar*)*handle, (size_t)dsize);
  128. if (len < 0) {
  129. dprintf(CRITICAL, "(L%d) Fail to read %s partition!\n", __LINE__, part_name);
  130. free(*handle);
  131. return false;
  132. }
  133. if (fdt_magic(*handle) != FDT_MAGIC) {
  134. dprintf(CRITICAL, "Error: invalid dtbo image format!\n");
  135. free(*handle);
  136. assert(0); // Keep running instead of assert!!
  137. return false;
  138. }
  139. return true;
  140. }
  141. /******************************************************************************
  142. * Side effect: This function allocates a memory on success.
  143. ******************************************************************************/
  144. static bool load_dtb_from_multiple_dtbo(char *part_name,
  145. const mdtbo_hdr_t *hdr2, char **handle, uint64_t recovery_dtbo_offset)
  146. {
  147. if (hdr2->info.hdr_size != ODM_MDTBO_HDR_SIZE) {
  148. dprintf(CRITICAL, "Error: odm mdtbo header size %d mismatch!\n",
  149. hdr2->info.hdr_size);
  150. assert(0);
  151. return false;
  152. }
  153. if (hdr2->info.hdr_version != ODM_MDTBO_VERSION) {
  154. dprintf(CRITICAL, "Error: odm mdtbo header version %d mismatch!\n",
  155. hdr2->info.hdr_version);
  156. assert(0);
  157. return false;
  158. }
  159. hw_mdtbo_index = get_odm_mdtbo_index();
  160. if (hw_mdtbo_index < 0 || hw_mdtbo_index >= MAX_NUM_OF_ODM_MDTBO) {
  161. dprintf(CRITICAL, "Error: mdtbo index %d is out of range!\n", hw_mdtbo_index);
  162. assert(0);
  163. return false;
  164. }
  165. unsigned int dtbo_size = 0, dtbo_offset = 0;
  166. if ((unsigned int)hw_mdtbo_index >= hdr2->info.num_of_dtbo) {
  167. dprintf(CRITICAL, "Error: hw_mdtbo_index %d >= num_of_dtbo %d.\n",
  168. hw_mdtbo_index, hdr2->info.num_of_dtbo);
  169. dprintf(CRITICAL, "Set hw_mdtbo_index to 0 for error handling!\n");
  170. hw_mdtbo_index = 0;
  171. }
  172. get_odm_mdtbo_offset_and_size(hdr2, hw_mdtbo_index, &dtbo_size, &dtbo_offset);
  173. dprintf(INFO, "ODM hw_mdtbo_index: %d, dtbo_offset: %d, dtbo_size: %d\n",
  174. hw_mdtbo_index, dtbo_offset, dtbo_size);
  175. *handle = malloc(dtbo_size);
  176. if (!*handle) {
  177. dprintf(CRITICAL, "Fail to malloc %d-byte buffer for dtbo!\n", dtbo_size);
  178. assert(0);
  179. return false;
  180. }
  181. long len = partition_read(part_name, (off_t)(recovery_dtbo_offset+dtbo_offset), (uchar*)*handle, (size_t)dtbo_size);
  182. if (len < 0) {
  183. dprintf(CRITICAL, "(L%d) Fail to read %s partition!\n", __LINE__, part_name);
  184. free(*handle);
  185. return false;
  186. }
  187. if (fdt_magic(*handle) != FDT_MAGIC) {
  188. dprintf(CRITICAL, "Error: invalid dtbo image format!\n");
  189. free(*handle);
  190. assert(0); // Keep running instead of assert!!
  191. return false;
  192. }
  193. return true;
  194. }
  195. /******************************************************************************
  196. * Load function from new dtb partition format defined since Android P
  197. ******************************************************************************/
  198. static bool load_dtb_from_dtb_entry(char *part_name,
  199. const struct dt_table_header *hdr2, char **handle, uint64_t recovery_dtbo_offset)
  200. {
  201. unsigned int i, dtbo_size = 0, dtbo_offset = 0;
  202. const struct dt_table_entry *hdr3 = (struct dt_table_entry *)(hdr2 + 1);
  203. if (fdt32_to_cpu(hdr2->header_size) != sizeof(struct dt_table_header)) {
  204. dprintf(CRITICAL, "Error: dt_table_header size %d mismatch!\n",
  205. fdt32_to_cpu(hdr2->header_size));
  206. assert(0);
  207. return false;
  208. }
  209. if (fdt32_to_cpu(hdr2->dt_entry_size) != sizeof(struct dt_table_entry)) {
  210. dprintf(CRITICAL, "Error: dt_table_entry size %d mismatch!\n",
  211. fdt32_to_cpu(hdr2->dt_entry_size));
  212. assert(0);
  213. return false;
  214. }
  215. hw_mdtbo_index = get_odm_mdtbo_index();
  216. /* traverse hw_mdtbo_index into dt_table_entry->id */
  217. for(i = 0; i < fdt32_to_cpu(hdr2->dt_entry_count); i++) {
  218. if ((unsigned int)hw_mdtbo_index == fdt32_to_cpu((hdr3 + i)->id)) {
  219. hw_mdtbo_index = i;
  220. dprintf(CRITICAL, "real mdtbo index=%d\n", hw_mdtbo_index);
  221. break;
  222. }
  223. }
  224. /* traverse end */
  225. if ((unsigned int)hw_mdtbo_index >= fdt32_to_cpu(hdr2->dt_entry_count)) {
  226. dprintf(CRITICAL, "Set hw_mdtbo_index to 0 for error handling!\n");
  227. hw_mdtbo_index = 0;
  228. }
  229. hdr3 = (struct dt_table_entry *)(hdr3 + hw_mdtbo_index);
  230. dtbo_size = fdt32_to_cpu(hdr3->dt_size);
  231. dtbo_offset = fdt32_to_cpu(hdr3->dt_offset);
  232. dprintf(INFO, "hw_mdtbo_index: %d, dtbo_offset: %d, dtbo_size: %d\n",
  233. hw_mdtbo_index, dtbo_offset, dtbo_size);
  234. *handle = malloc(dtbo_size);
  235. if (!*handle) {
  236. dprintf(CRITICAL, "Fail to malloc %d-byte buffer for dtbo!\n", dtbo_size);
  237. assert(0);
  238. return false;
  239. }
  240. long len = partition_read(part_name, (off_t)(recovery_dtbo_offset+dtbo_offset), (uchar*)*handle, (size_t)dtbo_size);
  241. if (len < 0) {
  242. dprintf(CRITICAL, "(L%d) Fail to read %s partition!\n", __LINE__, part_name);
  243. free(*handle);
  244. return false;
  245. }
  246. if ((fdt_magic(*handle) != FDT_MAGIC)||(fdt_totalsize(*handle) != dtbo_size)) {
  247. dprintf(CRITICAL, "Error: invalid dtbo image format!\n");
  248. free(*handle);
  249. assert(0);
  250. return false;
  251. }
  252. return true;
  253. }
  254. /******************************************************************************
  255. ******************************************************************************/
  256. char *load_overlay_dtbo(char *part_name, unsigned int *size, uint64_t recovery_dtbo_offset)
  257. {
  258. if (sizeof(union mkimg_hdr) != PART_HDR_DATA_SIZE) {
  259. dprintf(CRITICAL, "Error: incorrect partition header size!\n");
  260. assert(0);
  261. return NULL;
  262. }
  263. if (size == NULL) {
  264. dprintf(CRITICAL, "(L%d) Error: size is NULL!\n", __LINE__);
  265. return NULL;
  266. }
  267. if (partition_exists(part_name) != PART_OK) {
  268. dprintf(CRITICAL, "(L%d) Fail to get partition %s!\n", __LINE__, part_name);
  269. return NULL;
  270. }
  271. /* Read the partition header & the trailing 32 bytes for possible prolog. */
  272. long read_size = (long)(PART_HDR_DATA_SIZE + ODM_MDTBO_HDR_SIZE + LARGE_DT_ENTRY_SIZE);
  273. union mkimg_hdr *img_hdr = (union mkimg_hdr *)malloc(read_size);
  274. if (img_hdr == NULL) {
  275. dprintf(CRITICAL, "(L%d) Fail to allocate %d-byte memory!\n", __LINE__, (int)read_size);
  276. return NULL;
  277. }
  278. /* Read mkimage header. Treat it as the mdtbo header. */
  279. long len = partition_read(part_name, (off_t)recovery_dtbo_offset, (uchar*)img_hdr, (size_t)read_size);
  280. if (len < 0) {
  281. dprintf(CRITICAL, "(L%d) Fail to read %s partition!\n", __LINE__, part_name);
  282. free(img_hdr);
  283. return NULL;
  284. }
  285. /* Legacy MKIMG+MDTBO header parsing */
  286. if ((MKIMG_MAGIC == img_hdr->info.magic) && (MKIMG_EXT_MAGIC == img_hdr->info.ext_magic)) {
  287. /* hdr2 points to the possible prolog. */
  288. const mdtbo_hdr_t *hdr2 = (mdtbo_hdr_t*)(img_hdr + 1);
  289. char *ptr = NULL;
  290. bool success = false;
  291. if (is_odm_mdtbo_header(hdr2) == false)
  292. success = load_dtb_from_single_dtbo(part_name, img_hdr, &ptr, (uint64_t)recovery_dtbo_offset);
  293. else
  294. success = load_dtb_from_multiple_dtbo(part_name, hdr2, &ptr, (uint64_t)recovery_dtbo_offset);
  295. free(img_hdr);
  296. if (success) {
  297. *size = fdt32_to_cpu(*(unsigned int *)(ptr + 4));
  298. return ptr;
  299. }
  300. /* New DTBO parsing using dt_table_header/dt_table_entry */
  301. } else if (DT_TABLE_MAGIC == fdt_magic(img_hdr)) {
  302. const struct dt_table_header *hdr2 = (struct dt_table_header *)img_hdr;
  303. unsigned int dt_entries_offset = fdt32_to_cpu(hdr2->dt_entries_offset);
  304. unsigned int dt_entry_count = fdt32_to_cpu(hdr2->dt_entry_count);
  305. unsigned int dt_entry_size = fdt32_to_cpu(hdr2->dt_entry_size);
  306. char *ptr = NULL;
  307. bool success = false;
  308. if ((PART_HDR_DATA_SIZE + ODM_MDTBO_HDR_SIZE + LARGE_DT_ENTRY_SIZE) <
  309. (dt_entries_offset + dt_entry_count * dt_entry_size)){
  310. dprintf(CRITICAL, "error handle: need to load more dt_entry size = (%d)!\n",
  311. (dt_entries_offset + dt_entry_count * dt_entry_size));
  312. assert(0);
  313. return NULL;
  314. }
  315. success = load_dtb_from_dtb_entry(part_name, hdr2, &ptr, (uint64_t)recovery_dtbo_offset);
  316. free(img_hdr);
  317. if (success) {
  318. *size = fdt32_to_cpu(*(unsigned int *)(ptr + 4));
  319. return ptr;
  320. }
  321. }
  322. else {
  323. dprintf(CRITICAL, "assert: non of any known dtbo format !\n");
  324. assert(0);
  325. return NULL;
  326. }
  327. return NULL;
  328. }