loader.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include <pal_typedefs.h>
  36. #include <pal_log.h>
  37. #include <error.h>
  38. #include <img_info.h>
  39. #include <partition_api.h>
  40. #include <loader.h>
  41. #include <verified_boot_error.h>
  42. /* load_addr and load_addr_high are used as default load address if load address value
  43. in image header is "refer to external setting" */
  44. uint32_t loader(struct img_load_config *img_load_config,
  45. struct img_info *img_info)
  46. {
  47. uint32_t ret = STATUS_OK;
  48. uint8_t *buf = (uint8_t *)get_vb_buf();
  49. uint32_t buf_sz = (uint32_t)get_vb_buf_sz();
  50. uint32_t found = 0;
  51. uint64_t offset = 0;
  52. uint32_t name_compare_len;
  53. uint32_t max_name_len;
  54. uint32_t retry = 0;
  55. ssize_t len = 0;
  56. if (NULL == buf)
  57. return ERR_VB_BUF_ADDR_INVALID;
  58. if (NULL == img_load_config)
  59. return ERR_VB_BUF_ADDR_INVALID;
  60. if (img_load_config->num_load_addr > MAX_NUM_IMG_WITH_ONE_HDR)
  61. return ERR_VB_BUF_OVERFLOW;
  62. if (MAX_HDR_SZ > buf_sz)
  63. return ERR_VB_BUF_OVERFLOW;
  64. memset(buf, 0x0, MAX_HDR_SZ);
  65. while (0 == found) {
  66. if (NULL == img_load_config->part_name) {
  67. ret = ERR_VB_NOT_VALID_STRING;
  68. break;
  69. }
  70. len = partition_read(img_load_config->part_name, offset, buf, MAX_HDR_SZ);
  71. if (len < 0) {
  72. ret = (uint32_t)len;
  73. break;
  74. }
  75. ret = get_img_info(buf, MAX_HDR_SZ, img_info);
  76. if (ret) {
  77. if (retry == 1) {
  78. /* retried but in vain */
  79. break;
  80. } else {
  81. /* there might be a rsa2048 signature here,
  82. retry with offset + rsa2048 sig size */
  83. offset += RSA2048_SIG_SZ;
  84. retry = 1;
  85. continue;
  86. }
  87. }
  88. /* reset retry flag since there might be multiple subimages in
  89. current partition and each of them may include rsa2048 signature */
  90. retry = 0;
  91. /* image name is not given, once valid image header is found,
  92. continue image loading */
  93. if (NULL == img_load_config->img_name) {
  94. found = 1;
  95. break;
  96. }
  97. name_compare_len = strlen(img_load_config->img_name);
  98. if (img_info->img_hdr_type == IMG_HDR_TYPE_RAW)
  99. max_name_len = MKIMG_NAME_SZ - 1;
  100. else if (img_info->img_hdr_type == IMG_HDR_TYPE_BOOT)
  101. max_name_len = BOOTIMG_NAME_SZ - 1;
  102. else {
  103. max_name_len = 0;
  104. ret = ERR_VB_INVALID_IMG_HDR;
  105. break;
  106. }
  107. if (name_compare_len > max_name_len) {
  108. ret = ERR_VB_NOT_VALID_STRING;
  109. break;
  110. }
  111. if (!memcmp(img_load_config->img_name, img_info->name, name_compare_len)) {
  112. found = 1;
  113. break;
  114. }
  115. offset += img_info->img_hdr_sz;
  116. offset += img_info->img_sz + ((((uint64_t)img_info->img_sz_high & 0xffffffff))
  117. << 32);
  118. }
  119. if (!found)
  120. ret = ERR_VB_IMG_NOT_FOUND;
  121. else {
  122. uint32_t vfy_en = 0;
  123. vfy_en = get_vfy_policy_by_name(img_load_config->part_name,
  124. img_load_config->img_name);
  125. if (vfy_en) {
  126. ret = vfy_phase1(img_load_config->part_name, offset, img_info);
  127. if (ret) {
  128. pal_log_err("vfy_phase1 failed(0x%x)\n", ret);
  129. return ret;
  130. }
  131. pal_log_err("vfy_phase1 ok\n");
  132. }
  133. /* load image */
  134. /* 64 bit loading address is not supported now */
  135. if (EXTERNAL_LOAD_ADDR == img_info->img_load_addr)
  136. img_info->img_load_addr = img_load_config->load_addr;
  137. if (TEE_LOAD_MODE == img_info->img_load_mode)
  138. img_info->img_load_addr = tee_get_load_addr(img_info->img_load_addr);
  139. /* load address range check */
  140. if (img_info->img_load_addr == 0) {
  141. ret = ERR_VB_INVALID_LOAD_ADDR;
  142. return ret;
  143. }
  144. len = partition_read(img_load_config->part_name, offset + img_info->img_hdr_sz,
  145. (uint8_t *)img_info->img_load_addr, img_info->img_dsz);
  146. if (len < 0) {
  147. ret = (uint32_t)len;
  148. return ret;
  149. }
  150. /* do padding */
  151. if (img_info->img_sz != img_info->img_dsz)
  152. memset((uint8_t *)img_info->img_load_addr + img_info->img_dsz, 0x0,
  153. (img_info->img_sz - img_info->img_dsz) * sizeof(uint8_t));
  154. if (vfy_en) {
  155. ret = vfy_phase2(img_info->img_load_addr, img_info->img_sz);
  156. if (ret) {
  157. pal_log_err("vfy_phase2 failed(0x%x)\n", ret);
  158. return ret;
  159. }
  160. pal_log_err("vfy_phase2 ok\n");
  161. }
  162. /* postprocessing */
  163. if (img_info->scrambled) {
  164. /* [TODO] restore */
  165. }
  166. #if LOAD_BOOTIMG_SUPPORT
  167. if (img_info->img_hdr_type == IMG_HDR_TYPE_BOOT) {
  168. /* relocate ramdisk and second stage */
  169. uint32_t relocate_src = 0;
  170. uint32_t relocate_target = 0;
  171. uint32_t relocate_sz = 0;
  172. /* boot image header -> kernel -> ramdisk -> second stage */
  173. /* relocate ramdisk */
  174. relocate_src = img_info->img_load_addr + \
  175. img_info->img_hdr_sz + \
  176. img_info->sub_img_sz[KENREL_SLOT];
  177. relocate_target = img_info->sub_img_load_addr[RAMDISK_SLOT];
  178. relocate_sz = img_info->sub_img_sz[RAMDISK_SLOT];
  179. if (relocate_sz)
  180. memcpy(relocate_target, relocate_src, relocate_sz);
  181. /* relocate second stage */
  182. relocate_src = img_info->img_load_addr + \
  183. img_info->img_hdr_sz + \
  184. img_info->sub_img_sz[KENREL_SLOT] + \
  185. img_info->sub_img_sz[RAMDISK_SLOT];
  186. relocate_target = img_info->sub_img_load_addr[SECOND_STAGE_SLOT];
  187. relocate_sz = img_info->sub_img_sz[SECOND_STAGE_SLOT];
  188. if (relocate_sz)
  189. memcpy(relocate_target, relocate_src, relocate_sz);
  190. /* [TODO] decompress kernel if needed */
  191. /* [TODO] handle device tree */
  192. }
  193. #endif
  194. }
  195. return ret;
  196. }